diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 3e71214f8c8db..74219c0491ac1 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,5 +1,5 @@ -# Start from the official PHP 8.2 image with Apache -FROM php:8.2-apache-bookworm +# Start from the official PHP 8.3 image with Apache +FROM php:8.3-apache-bookworm # Install system dependencies, Node.js, Composer, and Cypress dependencies RUN apt-get update && apt-get install -y \ diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 1b8b296ebfb4d..be67d08896bee 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,16 +1,31 @@ Contributing to the Joomla! CMS™ -=============== -You are welcome to submit a contribution for review and possible inclusion in the Joomla! CMS but, before it will be accepted, we ask that you follow these simple guidelines: +================================ -* If you have a feature request, then please open a discussion to define the feature request and discuss possible solutions. Discussions can be converted into issues when the request is defined sufficiently that a developer can start coding the feature. In this process you will get feedback from the maintainers, if the feature is something for the Joomla core distribution or not. +You are welcome to submit a contribution for review and possible inclusion in the Joomla! CMS but, +before it will be accepted, we ask that you follow these simple guidelines: -* If you have found a bug, open an issue on our [Issue Tracker](https://issues.joomla.org/) or here on GitHub. If you can, please provide a fix and create a pull request (PR) instead; this will automatically create an issue for you so you do not have to create an issue, if you are creating a pull request. +* If you have a feature request, then please open a discussion to define the feature request and discuss possible solutions. + Discussions can be converted into issues when the request is defined sufficiently that a developer can start coding the feature. + In this process you will get feedback from the maintainers, if the feature is something for the Joomla core distribution or not. + +* If you have found a bug, open an issue on our [Issue Tracker](https://issues.joomla.org/) or here on GitHub. + If you can, please provide a fix and create a pull request (PR) instead; this will automatically create an issue + for you so you do not have to create an issue, if you are creating a pull request. * Follow the [Joomla! Coding Standards](https://manual.joomla.org/docs/get-started/codestyle) for code contributions. -* When filing an issue or opening a Pull Request(PR), please include a clear title and description. The title should be a short summary of the issue. For example, `Invalid Query in com_admin`. All issues and PRs should include a description with as much detail as possible. If it is a PR, include what the issue is, what the PR is addressing, testing instructions and environmental information (PHP version, database driver and version, and other data you can retrieve from your site's system information view) in case the issue is specific to certain environments. If additional information is needed, please be prepared to provide it as our community members review your submission. +* When filing an issue or opening a Pull Request(PR), please include a clear title and description. + The title should be a short summary of the issue. For example, `Invalid Query in com_admin`. All issues and PRs + should include a description with as much detail as possible. If it is a PR, include what the issue is, what the + PR is addressing, testing instructions and environmental information (PHP version, database driver and version, + and other data you can retrieve from your site's system information view) in case the issue is specific to certain + environments. If additional information is needed, please be prepared to provide it as our community members + review your submission. -* Report security issues to the Joomla! Security Strike Team (JSST) at security@joomla.org or use the [JSST contact form](https://developer.joomla.org/contact-security-team.html). Please do not use the public tracker for security issues. Find [here](https://github.com/joomla/joomla-cms?tab=security-ov-file#readme) more information about the [Security Policies and Procedures](https://github.com/joomla/joomla-cms?tab=security-ov-file#readme). +* Report security issues to the Joomla! Security Strike Team (JSST) at security@joomla.org or use + the [JSST contact form](https://developer.joomla.org/contact-security-team.html). Please do not use the public tracker + for security issues. Find [here](https://github.com/joomla/joomla-cms?tab=security-ov-file#readme) more information + about the [Security Policies and Procedures](https://github.com/joomla/joomla-cms?tab=security-ov-file#readme). * Please follow our [Generative AI policy](https://developer.joomla.org/generative-ai-policy.html) when using AI to contribute to the Joomla! project @@ -19,7 +34,6 @@ Please be patient as not all items will be viewed or tested immediately (remembe #### Branches Bug fixing PRs should be made to the `5.4-dev` branch. Merged bugfixes will be upmerged into the current branches. New features that do not break backwards compatibility should be made to the `6.2-dev`. - | Branch | Purpose | |---------|--------------------------------------------------------------------------------------------------------------| | 5.4-dev | Branch for the current 5.x Joomla version. | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13f3c38c8bcc6..50194981e0087 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,11 @@ jobs: with: path: libraries/vendor key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + id: cache-webauthn + with: + path: plugins/system/webauthn/fido.jwt + key: ${{ runner.os }}-webauthn-${{ hashFiles('composer.lock') }} - name: Install PHP dependencies if: steps.cache-php.outputs.cache-hit != 'true' run: | @@ -45,11 +50,18 @@ jobs: node_modules media installation/template/css - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/media_source/**', 'administrator/components/com_media/resources/**', 'installation/template/scss/**') }} + installation/template/images + installation/template/js + installation/template/scss + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/build.mjs', 'build/build-modules-js/**', 'media_source/**') }} - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: libraries/vendor key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: plugins/system/webauthn/fido.jwt + key: ${{ runner.os }}-webauthn-${{ hashFiles('composer.lock') }} - name: Build assets if: steps.cache-assets.outputs.cache-hit != 'true' run: npm ci @@ -65,9 +77,11 @@ jobs: with: path: libraries/vendor key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: plugins/system/webauthn/fido.jwt + key: ${{ runner.os }}-webauthn-${{ hashFiles('composer.lock') }} - name: Check PHP code style - env: - PHP_CS_FIXER_IGNORE_ENV: true run: | set -e ./libraries/vendor/bin/php-cs-fixer fix -vvv --diff @@ -99,7 +113,10 @@ jobs: node_modules media installation/template/css - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/media_source/**', 'administrator/components/com_media/resources/**', 'installation/template/scss/**') }} + installation/template/images + installation/template/js + installation/template/scss + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/build.mjs', 'build/build-modules-js/**', 'media_source/**') }} - name: Check code style run: npm run ${{ matrix.check }} @@ -114,6 +131,10 @@ jobs: with: path: libraries/vendor key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: plugins/system/webauthn/fido.jwt + key: ${{ runner.os }}-webauthn-${{ hashFiles('composer.lock') }} - name: Run PHPstan run: | set -e @@ -135,13 +156,17 @@ jobs: needs: [code-style-php] strategy: matrix: - php_version: ['8.1', '8.2', '8.3', '8.4', '8.5'] + php_version: ['8.3', '8.4', '8.5'] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: libraries/vendor - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: plugins/system/webauthn/fido.jwt + key: ${{ runner.os }}-webauthn-${{ hashFiles('composer.lock') }} - name: Run Unit tests run: ./libraries/vendor/bin/phpunit --testsuite Unit @@ -152,7 +177,7 @@ jobs: needs: [code-style-php] strategy: matrix: - php_version: ['8.1', '8.2', '8.3', '8.4', '8.5'] + php_version: ['8.3', '8.4', '8.5'] config: - my_version: '9' engine: 'mysqli' @@ -191,7 +216,11 @@ jobs: - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: libraries/vendor - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: plugins/system/webauthn/fido.jwt + key: ${{ runner.os }}-webauthn-${{ hashFiles('composer.lock') }} - name: Run Integration tests env: JTEST_DB_ENGINE: ${{ matrix.config.engine }} @@ -234,14 +263,19 @@ jobs: needs: [code-style-php] strategy: matrix: - php_version: ['8.1', '8.2', '8.3', '8.4', '8.5'] + php_version: ['8.3', '8.4', '8.5'] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 id: cache-php-windows with: path: libraries/vendor - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + id: cache-webauthn-windows + with: + path: plugins/system/webauthn/fido.jwt + key: ${{ runner.os }}-webauthn-${{ hashFiles('composer.lock') }} - name: Setup PHP uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # v2.37.1 with: @@ -260,13 +294,17 @@ jobs: needs: [code-style-php] strategy: matrix: - php_version: ['8.1', '8.2', '8.3', '8.4', '8.5'] + php_version: ['8.3', '8.4', '8.5'] steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: libraries/vendor - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: plugins/system/webauthn/fido.jwt + key: ${{ runner.os }}-webauthn-${{ hashFiles('composer.lock') }} - uses: shogo82148/actions-setup-mysql@c80f44ab210a360ef966c5b9f48a2ae21123b533 # v1.51.0 with: mysql-version: "mariadb-10.4" @@ -304,7 +342,10 @@ jobs: node_modules media installation/template/css - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/media_source/**', 'administrator/components/com_media/resources/**', 'installation/template/scss/**') }} + installation/template/images + installation/template/js + installation/template/scss + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/build.mjs', 'build/build-modules-js/**', 'media_source/**') }} - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 id: cache-cypress with: @@ -337,7 +378,7 @@ jobs: db_engine: mysqli db_host: mysql my_version: '8.4' - - php_version: '8.1' + - php_version: '8.3' test_group: cmysql db_engine: mysqli db_host: mysql @@ -347,12 +388,12 @@ jobs: db_engine: mysqli db_host: maria maria_version: '12.0' - - php_version: '8.1' + - php_version: '8.3' test_group: cmaria db_engine: mysqli db_host: maria maria_version: '10.4' - - php_version: '8.1' + - php_version: '8.3' test_group: cpostgres db_engine: pgsql db_host: postgres @@ -370,13 +411,20 @@ jobs: with: path: libraries/vendor key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + with: + path: plugins/system/webauthn/fido.jwt + key: ${{ runner.os }}-webauthn-${{ hashFiles('composer.lock') }} - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | node_modules media installation/template/css - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/media_source/**', 'administrator/components/com_media/resources/**', 'installation/template/scss/**') }} + installation/template/images + installation/template/js + installation/template/scss + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/build.mjs', 'build/build-modules-js/**', 'media_source/**') }} - uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | diff --git a/.github/workflows/create-translation-pull-request-v6.yml b/.github/workflows/create-translation-pull-request-v6.yml index 9a4b73c4ba987..fa61039c8d267 100644 --- a/.github/workflows/create-translation-pull-request-v6.yml +++ b/.github/workflows/create-translation-pull-request-v6.yml @@ -12,7 +12,7 @@ on: env: JOOMLA_MAJOR_VERSION: 6 - JOOMLA_MINOR_VERSION: '6.0' + JOOMLA_MINOR_VERSION: '6.1' permissions: contents: read @@ -31,6 +31,7 @@ jobs: with: ref: translation6 fetch-depth: 0 + token: ${{ secrets.PAT_WORKFLOW }} - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: 24 diff --git a/.github/workflows/typos.toml b/.github/workflows/typos.toml index 1dedd5d9f2ef7..a1929444ab8a4 100644 --- a/.github/workflows/typos.toml +++ b/.github/workflows/typos.toml @@ -6,10 +6,9 @@ [files] extend-exclude = [ "/templates/system/*.html", - "/administrator/components/com_admin/sql/*", - "/build/media_source/vendor/tinymce/langs/*", "/installation/language/*", - "includes/*.html", + "!/installation/language/en-GB/", + "/includes/*.html", "/plugins/sampledata/testing/*", ] @@ -44,11 +43,5 @@ vertexes="vertexes" # Valid spelling waiting fix https://github.com/crat wheres="wheres" # $wheres in modules\mod_related_items\src\Helper\RelatedItemsHelper.php wrkarounds="wrkarounds" # Used as method parameter $wrkarounds in Joomla\CMS\Cache\Controller controller classes -# deprecated strings can be removed in 6.0 -configurated="configurated" -discernable="discernable" -hilight="hilight" -mis="mis" - # deprecated strings can be removed in 7.0 LANUAGES="LANUAGES" diff --git a/.gitignore b/.gitignore index 8098b5d5c3dfc..f5779ad143dc9 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ .docker /docker-compose.yml /nbproject +/.devcontainer +/.github +/.vscode # Local System Files (i.e. cache, logs, etc.) /administrator/cache @@ -23,6 +26,9 @@ # Template CSS files generated by NPM /installation/template/css +/installation/template/images +/installation/template/js +/installation/template/scss # Test Related Files /phpunit.xml diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index b188dd552c400..f8340f09f679f 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -1,4 +1,5 @@ in( - [ - __DIR__ . '/administrator', - __DIR__ . '/api', - __DIR__ . '/build', - __DIR__ . '/cache', - __DIR__ . '/cli', - __DIR__ . '/components', - __DIR__ . '/includes', - __DIR__ . '/installation', - __DIR__ . '/language', - __DIR__ . '/libraries/src', - __DIR__ . '/modules', - __DIR__ . '/plugins', - __DIR__ . '/templates', - __DIR__ . '/tests', - ] - ) - // Ignore template files as PHP CS fixer can't handle them properly - // https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues/3702#issuecomment-396717120 - ->notPath('/tmpl/') - ->notPath('/layouts/') - ->notPath('/cassiopeia/') - ->notPath('/atum/') - // Ignore psr12 scripts because they contain invalid syntax - ->notPath('/psr12/') - ->notName('github_rebase.php'); +$finder = (new Finder()) + ->in(__DIR__) + ->exclude([ + 'administrator/cache', + 'administrator/logs', + 'build/psr12', + 'node_modules', + 'libraries/php-encryption', + 'libraries/phpass', + ]) + ->notPath([ + 'configuration.php', + ]) +; + +final class JoomlaPolicy implements RuleCustomisationPolicyInterface +{ + public function getPolicyVersionForCache(): string + { + return hash_file('xxh128', __FILE__); + } + + public function getRuleCustomisers(): array + { + $disableLayoutFile = [ + 'binary_operator_spaces', + 'native_function_invocation', + 'no_trailing_whitespace_in_comment', + 'single_space_around_construct', + 'statement_indentation', + // @todo Remove in next major version to avoid having to update too many template overrides. + 'braces_position', + 'combine_consecutive_issets', + 'no_spaces_after_function_name', + 'no_unneeded_control_parentheses', + 'single_line_after_imports', + 'spaces_inside_parentheses', + 'ternary_operator_spaces', + 'trailing_comma_in_multiline', + ]; + + $ruleCustomisers = []; + foreach ($disableLayoutFile as $rule) { + $ruleCustomisers[$rule] = static function (\SplFileInfo $file): bool { + return !self::isLayoutFile($file); + }; + } + + return $ruleCustomisers; + } + + private static function isLayoutFile(\SplFileInfo $file): bool + { + return str_contains($file->getPathname(), \DIRECTORY_SEPARATOR . 'tmpl' . \DIRECTORY_SEPARATOR) + || str_contains($file->getPathname(), \DIRECTORY_SEPARATOR . 'layouts' . \DIRECTORY_SEPARATOR) + || str_contains($file->getPathname(), \DIRECTORY_SEPARATOR . 'templates' . \DIRECTORY_SEPARATOR . 'atum' . \DIRECTORY_SEPARATOR) + || str_contains($file->getPathname(), \DIRECTORY_SEPARATOR . 'templates' . \DIRECTORY_SEPARATOR . 'cassiopeia' . \DIRECTORY_SEPARATOR) + || str_contains($file->getPathname(), \DIRECTORY_SEPARATOR . 'templates' . \DIRECTORY_SEPARATOR . 'cassiopeia_extended' . \DIRECTORY_SEPARATOR); + } +} -$config = new PhpCsFixer\Config(); -$config - ->setParallelConfig(PhpCsFixer\Runner\Parallel\ParallelConfigFactory::detect()) +$config = (new Config()) ->setRiskyAllowed(true) ->setHideProgress(false) ->setUsingCache(false) @@ -101,6 +138,8 @@ 'no_useless_sprintf' => true, ] ) - ->setFinder($finder); + ->setRuleCustomisationPolicy(new JoomlaPolicy()) + ->setFinder($finder) +; return $config; diff --git a/README.md b/README.md index 1deecedd6be93..eb5272cd9269d 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,39 @@ Joomla! CMS™ -==================== +============ -Build Status ------------- +## The Joomla! 6.2 branch is under heavy development and not all links in this document are available yet + +## Build Status | Actions | PHP | Node | npm | |-------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------|--------------------------------------------------------------------------------------|----------------------------------------------------------------------------------| -| [![Build Status](https://github.com/joomla/joomla-cms/actions/workflows/ci.yml/badge.svg?branch=5.4-dev)](https://github.com/joomla/joomla-cms) | [![PHP](https://img.shields.io/badge/PHP-V8.1.0-green)](https://www.php.net/) | [![node-lts](https://img.shields.io/badge/Node-V20.0-green)](https://nodejs.org/en/) | [![npm](https://img.shields.io/badge/npm-v10.1.0-green)](https://nodejs.org/en/) | +| [![Build Status](https://github.com/joomla/joomla-cms/actions/workflows/ci.yml/badge.svg?branch=6.2-dev)](https://github.com/joomla/joomla-cms) | [![PHP](https://img.shields.io/badge/PHP-V8.3.0-green)](https://www.php.net/) | [![node-lts](https://img.shields.io/badge/Node-V20.0-green)](https://nodejs.org/en/) | [![npm](https://img.shields.io/badge/npm-v10.1.0-green)](https://nodejs.org/en/) | + +## Overview -Overview ---------------------- -* This is the source of Joomla! 5.x. +* This is the source of Joomla! 6.x. * Joomla's [Official website](https://www.joomla.org). -* Joomla! 5.4 [version history](https://docs.joomla.org/Special:MyLanguage/Joomla_5.4_version_history). -* Detailed changes are in the [changelog](https://github.com/joomla/joomla-cms/commits/5.4-dev). +* Joomla! 6.2 [version history](https://docs.joomla.org/Special:MyLanguage/Joomla_6.2_version_history). +* Detailed changes are in the [changelog](https://github.com/joomla/joomla-cms/commits/6.2-dev). +* Release Managers responsible for Joomla! 6.2 + * Charvi Mehra @charvimehradu + * Martin Kopp @MacJoom + +## What is Joomla? -What is Joomla? ---------------------- * [Joomla!](https://www.joomla.org/about-joomla.html) is a **Content Management System** (CMS) which enables you to build websites and powerful online applications. * It is a simple and powerful web server application which requires a server with PHP and either MySQL, MariaDB or PostgreSQL to run. You can find [full technical requirements here](https://downloads.joomla.org/technical-requirements). * Joomla! is **free and Open Source software** distributed under the GNU General Public License version 2 or later. -Looking for an installable package? ---------------------- +## Looking for an installable package? + Joomla is not installable out of the box from this repository, please use: - For the latest stable package: https://downloads.joomla.org - For a nightly package: https://developer.joomla.org/nightly-builds.html -How to get a working installation from the source ---------------------- -For detailed instructions please visit https://docs.joomla.org/Special:MyLanguage/J5.x:Setting_Up_Your_Local_Environment +## How to get a working installation from the source + +For detailed instructions please visit https://guide.joomla.org/user-manual/hosting/local-environment-setup You will need: - PHP - basically the same as you need for running a Joomla Site, but you need the cli (command line interface) Version (see https://docs.joomla.org/Special:MyLanguage/Configuring_a_LAMPP_server_for_PHP_development) @@ -46,9 +50,9 @@ git clone https://github.com/joomla/joomla-cms.git ```bash cd joomla-cms ``` -- Go to the 5.4-dev branch: +- Go to the 6.2-dev branch: ```bash -git checkout 5.4-dev +git checkout 6.2-dev ``` - Install all the needed composer packages: ```bash @@ -64,8 +68,8 @@ Joomla creates a cache of the namespaces of its extensions in `JOOMLA_ROOT/admin extensions are created, deleted or removed in git then this file needs to be recreated. You can simply delete the file and it will be regenerated on the next call to Joomla. -Do you want to improve Joomla? --------------------- +## Do you want to improve Joomla? + * Where to [request a feature](https://issues.joomla.org)? * How do you [report a bug](https://docs.joomla.org/Special:MyLanguage/Filing_bugs_and_issues) on the [Issue Tracker](https://issues.joomla.org)? * How to [submit code](https://manual.joomla.org/docs/get-started/git/) to the Joomla CMS using a Pull Request? @@ -74,22 +78,21 @@ Do you want to improve Joomla? * Documentation for [Web designers](https://docs.joomla.org/Special:MyLanguage/Web_designers). * Provide a translation for Joomla: [Joomla Crowdin Project](https://joomla.crowdin.com/cms) -Which branch should my Pull Request target? --------------------- +## Which branch should my Pull Request target? + Using a simple classification keeps the project **stable**, **transparent**, and **easy** for everyone to contribute. -| Type of change | What it means | Target branch | -|---|---|---| +| Type of change | What it means | Target branch | +|---|---|-------------------------------------------------------------------------------------------------------------------------------------| | **Bug / Patch release** | The change fixes an actual error. The software crashes, produces the wrong result, or behaves contrary to its specification. It can be resolved without large‑scale refactoring or new functionality. | **[5.4-dev](https://github.com/joomla/joomla-cms/tree/5.4-dev)** (6.1-dev) **\*** | -| **Feature / Minor release** | Anything that isn’t a strict bug – new behavior, refactoring, performance improvements, enhancements, UI tweaks, etc. These changes are bundled together for the next minor version. | **[6.2-dev](https://github.com/joomla/joomla-cms/tree/6.2-dev)** | +| **Feature / Minor release** | Anything that isn’t a strict bug – new behavior, refactoring, performance improvements, enhancements, UI tweaks, etc. These changes are bundled together for the next minor version. | **[6.2-dev](https://github.com/joomla/joomla-cms/tree/6.2-dev)** | -**\*** All bugs that already exist in version 5.4.x should be fixed in `5.4-dev`. Only bugs that are introduced for the first time in version 6.x should target the [`6.1-dev`](https://github.com/joomla/joomla-cms/tree/6.1-dev) branch. +**\*** All bugs that already exist in version 5.4.x or 6.1.x should be fixed in `5.4-dev` or `6.1-dev`. Only bugs that are introduced for the first time in version 6.2.x should target the [`6.2-dev`](https://github.com/joomla/joomla-cms/tree/6.2-dev) branch. A member of the maintainer or bug squad team confirms the classification and sets the appropriate labels when a PR is opened. If a PR is opened in the wrong branch, a maintainer will simply ask you to retarget it to the proper branch. +## Copyright -Copyright ---------------------- * (C) 2005 Open Source Matters, Inc. * Distributed under the GNU General Public License version 2 or later * See [License details](https://docs.joomla.org/Special:MyLanguage/Joomla_Licenses) diff --git a/README.txt b/README.txt index 83358afc09258..ab7dee5dd7256 100644 --- a/README.txt +++ b/README.txt @@ -1,10 +1,16 @@ Joomla! CMS™ +The Joomla! 6.2 branch is under heavy development and not all links in this document are available yet +------------------------------------------------------------------------------------------------------ + 1- Overview - * This is a Joomla! 5.x installation/upgrade package. + * This is a Joomla! 6.x installation/upgrade package. * Joomla! Official site: https://www.joomla.org - * Joomla! 5.4 version history - https://docs.joomla.org/Special:MyLanguage/Joomla_5.4_version_history - * Detailed changes in the Changelog: https://github.com/joomla/joomla-cms/commits/5.4-dev + * Joomla! 6.2 version history - https://docs.joomla.org/Special:MyLanguage/Joomla_6.2_version_history + * Detailed changes in the Changelog: https://github.com/joomla/joomla-cms/commits/6.2-dev + * Release Managers responsible for Joomla! 6.2 + * Charvi Mehra @charvimehradu + * Martin Kopp @MacJoom 2- What is Joomla? * Joomla! is a Content Management System (CMS) which enables you to build websites and powerful online applications. @@ -20,10 +26,10 @@ Joomla! CMS™ 4- How to find a Joomla! translation? * Repository of accredited language packs: https://downloads.joomla.org/language-packs * You can also add languages directly to your website via your Joomla! administration panel: https://docs.joomla.org/Special:MyLanguage/J5.x:Setup_a_Multilingual_Site/Installing_New_Language - * Learn how to setup a Multilingual Joomla! Site: https://docs.joomla.org/Special:MyLanguage/J5.x:Setup_a_Multilingual_Site + * Learn how to setup a Multilingual Joomla! Site: https://docs.joomla.org/Special:MyLanguage/J6.x:Setup_a_Multilingual_Site 5- Learn Joomla! - * Read Getting Started with Joomla to find out the basics: https://docs.joomla.org/Special:MyLanguage/J5.x:Getting_Started_with_Joomla! + * Read Getting Started with Joomla to find out the basics: https://docs.joomla.org/Special:MyLanguage/J6.x:Getting_Started_with_Joomla! * Before installing, read the beginners guide: https://docs.joomla.org/Special:MyLanguage/Portal:Beginners 6- What are the benefits of Joomla? @@ -48,15 +54,17 @@ Joomla! CMS™ 10- Where can you get support and help? * The Joomla! Documentation: https://docs.joomla.org/Special:MyLanguage/Main_Page + * Developer Documentation: https://manual.joomla.org/docs/ * FAQ Frequently Asked Questions: https://docs.joomla.org/Special:MyLanguage/Category:FAQ * Find the information you need: https://docs.joomla.org/Special:MyLanguage/Start_here * Find help and other users: https://www.joomla.org/about-joomla/create-and-share.html * Post questions at our forums: https://forum.joomla.org * Joomla! Resources Directory (JRD): https://community.joomla.org/service-providers-directory/ -11- Do you already have a Joomla! site that's not built with Joomla! 5.x ? - * What's new in Joomla! 5.x: https://www.joomla.org/5 - * What are the main differences between 4.x and 5.x? https://docs.joomla.org/Special:MyLanguage/What_are_the_major_differences_between_Joomla!_4.x_and_5.x +11- Do you already have a Joomla! site that's not built with Joomla! 6.x ? + * What's new in Joomla! 6.x: https://www.joomla.org/6 + * What are the main differences between 5.x and 6.x? https://docs.joomla.org/Special:MyLanguage/What_are_the_major_differences_between_Joomla!_5.x_and_6.x + * How to migrate from 5.x to 6.x? Tutorial: https://docs.joomla.org/Special:MyLanguage/Joomla_5.x_to_6.x_Step_by_Step_Migration * How to migrate from 4.x to 5.x? Tutorial: https://docs.joomla.org/Special:MyLanguage/Joomla_4.x_to_5.x_Step_by_Step_Migration * How to migrate from 3.x to 4.x? Tutorial: https://docs.joomla.org/Special:MyLanguage/Joomla_3.x_to_4.x_Step_by_Step_Migration * How to migrate from 2.5.x to 3.x? Tutorial: https://docs.joomla.org/Special:MyLanguage/Joomla_2.5_to_3.x_Step_by_Step_Migration diff --git a/administrator/components/com_actionlogs/src/Controller/ActionlogsController.php b/administrator/components/com_actionlogs/src/Controller/ActionlogsController.php index 5ac21098a147a..6e37e8d828ad8 100644 --- a/administrator/components/com_actionlogs/src/Controller/ActionlogsController.php +++ b/administrator/components/com_actionlogs/src/Controller/ActionlogsController.php @@ -14,13 +14,13 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Date\Date; use Joomla\CMS\Event\ActionLog\AfterLogExportEvent; -use Joomla\CMS\Input\Input; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\AdminController; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\Router\Route; use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper; use Joomla\Component\Actionlogs\Administrator\Model\ActionlogsModel; +use Joomla\Input\Input; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -38,11 +38,11 @@ class ActionlogsController extends AdminController * Constructor. * * @param array $config An optional associative array of configuration settings. - * Recognized key values include 'name', 'default_task', 'model_path', and - * 'view_path' (this list is not meant to be comprehensive). + * Recognized key values include 'name', 'default_task', 'model_path', and + * 'view_path' (this list is not meant to be comprehensive). * @param ?MVCFactoryInterface $factory The factory. - * @param CMSApplication $app The Application for the dispatcher - * @param Input $input Input + * @param ?CMSApplication $app The Application for the dispatcher + * @param ?Input $input Input * * @since 3.9.0 * diff --git a/administrator/components/com_actionlogs/src/Field/ExtensionField.php b/administrator/components/com_actionlogs/src/Field/ExtensionField.php index 49ec4a0a6d123..63220ade7e0b9 100644 --- a/administrator/components/com_actionlogs/src/Field/ExtensionField.php +++ b/administrator/components/com_actionlogs/src/Field/ExtensionField.php @@ -44,7 +44,7 @@ class ExtensionField extends ListField public function getOptions() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('extension')) ->from($db->quoteName('#__action_logs')) ->order($db->quoteName('extension')); diff --git a/administrator/components/com_actionlogs/src/Field/LogcreatorField.php b/administrator/components/com_actionlogs/src/Field/LogcreatorField.php index d7d5c516dba87..0925ddbc108a0 100644 --- a/administrator/components/com_actionlogs/src/Field/LogcreatorField.php +++ b/administrator/components/com_actionlogs/src/Field/LogcreatorField.php @@ -59,7 +59,7 @@ protected function getOptions() $db = $this->getDatabase(); // Construct the query - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('u.id', 'value')) ->select($db->quoteName('u.username', 'text')) ->from($db->quoteName('#__users', 'u')) diff --git a/administrator/components/com_actionlogs/src/Field/LogsdaterangeField.php b/administrator/components/com_actionlogs/src/Field/LogsdaterangeField.php index f211355b965d1..14100b4f8c542 100644 --- a/administrator/components/com_actionlogs/src/Field/LogsdaterangeField.php +++ b/administrator/components/com_actionlogs/src/Field/LogsdaterangeField.php @@ -60,7 +60,7 @@ public function __construct($form = null) parent::__construct($form); // Load the required language - $lang = Factory::getLanguage(); + $lang = Factory::getApplication()->getLanguage(); $lang->load('com_actionlogs', JPATH_ADMINISTRATOR); } } diff --git a/administrator/components/com_actionlogs/src/Field/LogtypeField.php b/administrator/components/com_actionlogs/src/Field/LogtypeField.php index 6aae799f0c2b2..ba2eb4569b152 100644 --- a/administrator/components/com_actionlogs/src/Field/LogtypeField.php +++ b/administrator/components/com_actionlogs/src/Field/LogtypeField.php @@ -45,7 +45,7 @@ class LogtypeField extends ListField public function getOptions() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension')) ->from($db->quoteName('#__action_logs_extensions')); diff --git a/administrator/components/com_actionlogs/src/Field/PlugininfoField.php b/administrator/components/com_actionlogs/src/Field/PlugininfoField.php index b1c3ac45f3a81..2b62df3e5b8bd 100644 --- a/administrator/components/com_actionlogs/src/Field/PlugininfoField.php +++ b/administrator/components/com_actionlogs/src/Field/PlugininfoField.php @@ -44,7 +44,7 @@ class PlugininfoField extends FormField protected function getInput() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' = ' . $db->quote('actionlog')) diff --git a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php index c821e5fb67a4e..4849e0379dccd 100644 --- a/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php +++ b/administrator/components/com_actionlogs/src/Field/UserlogtypeField.php @@ -45,7 +45,7 @@ public function getOptions() { $db = $this->getDatabase(); $user = Factory::getApplication()->getIdentity(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extensions')) ->from($db->quoteName('#__action_logs_users')) ->where($db->quoteName('user_id') . ' = :userid') diff --git a/administrator/components/com_actionlogs/src/Helper/ActionlogsHelper.php b/administrator/components/com_actionlogs/src/Helper/ActionlogsHelper.php index 98d884a22dc7a..f592770b1ea90 100644 --- a/administrator/components/com_actionlogs/src/Helper/ActionlogsHelper.php +++ b/administrator/components/com_actionlogs/src/Helper/ActionlogsHelper.php @@ -13,8 +13,8 @@ use Joomla\CMS\Date\Date; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Router\Route; +use Joomla\Database\DatabaseInterface; use Joomla\Filesystem\Path; use Joomla\String\StringHelper; @@ -100,7 +100,7 @@ public static function loadTranslationFiles($extension) return; } - $lang = Factory::getLanguage(); + $lang = Factory::getApplication()->getLanguage(); $source = ''; switch (substr($extension, 0, 3)) { @@ -145,26 +145,6 @@ public static function loadTranslationFiles($extension) $cache[$extension] = true; } - /** - * Get parameters to be - * - * @param string $context The context of the content - * - * @return mixed An object contains content type parameters, or null if not found - * - * @since 3.9.0 - * - * @deprecated 4.3 will be removed in 6.0 - * Use the action log config model instead - * Example: Factory::getApplication()->bootComponent('actionlogs')->getMVCFactory() - * ->createModel('ActionlogConfig', 'Administrator')->getLogContentTypeParams($context); - */ - public static function getLogContentTypeParams($context) - { - return Factory::getApplication()->bootComponent('actionlogs')->getMVCFactory() - ->createModel('ActionlogConfig', 'Administrator')->getLogContentTypeParams($context); - } - /** * Get human readable log message for a User Action Log * @@ -232,7 +212,7 @@ public static function getHumanReadableLogMessage($log, $generateLinks = true) * @param string $contentType * @param integer $id * @param string $urlVar - * @param CMSObject $object + * @param \stdClass $object * * @return string Link to the content item * @@ -280,11 +260,11 @@ public static function loadActionLogPluginsLanguage() } $loaded = true; - $lang = Factory::getLanguage(); - $db = Factory::getDbo(); + $lang = Factory::getApplication()->getLanguage(); + $db = Factory::getContainer()->get(DatabaseInterface::class); // Get all (both enabled and disabled) actionlog plugins - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( $db->quoteName( [ diff --git a/administrator/components/com_actionlogs/src/Model/ActionlogConfigModel.php b/administrator/components/com_actionlogs/src/Model/ActionlogConfigModel.php index 9ff7c98f3dafb..f772f5f29659a 100644 --- a/administrator/components/com_actionlogs/src/Model/ActionlogConfigModel.php +++ b/administrator/components/com_actionlogs/src/Model/ActionlogConfigModel.php @@ -35,7 +35,7 @@ class ActionlogConfigModel extends BaseDatabaseModel public function getLogContentTypeParams(string $context): ?\stdClass { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('a.*') ->from($db->quoteName('#__action_log_config', 'a')) ->where($db->quoteName('a.type_alias') . ' = :context') diff --git a/administrator/components/com_actionlogs/src/Model/ActionlogModel.php b/administrator/components/com_actionlogs/src/Model/ActionlogModel.php index 0f7e5dafa86a3..c4fd19f0a77b8 100644 --- a/administrator/components/com_actionlogs/src/Model/ActionlogModel.php +++ b/administrator/components/com_actionlogs/src/Model/ActionlogModel.php @@ -13,8 +13,12 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Text; use Joomla\CMS\Mail\Exception\MailDisabledException; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Model\BaseDatabaseModel; use Joomla\CMS\User\UserFactoryAwareInterface; @@ -32,9 +36,11 @@ * * @since 3.9.0 */ -class ActionlogModel extends BaseDatabaseModel implements UserFactoryAwareInterface +class ActionlogModel extends BaseDatabaseModel implements UserFactoryAwareInterface, MailerFactoryAwareInterface, LanguageFactoryAwareInterface { use UserFactoryAwareTrait; + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; /** * Function to add logs to the database @@ -123,7 +129,7 @@ protected function sendNotificationEmails($messages, $username, $context) $app = Factory::getApplication(); $lang = $app->getLanguage(); $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select($db->quoteName(['u.email', 'l.extensions'])) @@ -160,13 +166,14 @@ protected function sendNotificationEmails($messages, $username, $context) $tempPlain = []; foreach ($messages as $message) { - $m = []; - $m['extension'] = Text::_($extension); - $m['message'] = ActionlogsHelper::getHumanReadableLogMessage($message); - $tzOffset = Factory::getApplication()->get('offset'); - $m['date'] = HTMLHelper::_('date', $message->log_date, 'Y-m-d H:i:s T', $tzOffset); - $m['username'] = $username; - $temp[] = $m; + $m = []; + $m['extension'] = Text::_($extension); + $m['message'] = ActionlogsHelper::getHumanReadableLogMessage($message); + $tzOffset = Factory::getApplication()->get('offset'); + $m['date'] = HTMLHelper::_('date', $message->log_date, 'Y-m-d H:i:s T', $tzOffset); + $m['ip_address'] = Text::_($message->ip_address); + $m['username'] = $username; + $temp[] = $m; // copy replacement tags array and set non-HTML message. $mPlain = array_merge([], $m); @@ -181,7 +188,12 @@ protected function sendNotificationEmails($messages, $username, $context) 'messages' => $tempPlain, ]; - $mailer = new MailTemplate('com_actionlogs.notification', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_actionlogs.notification', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addTemplateData($templateData); $mailer->addTemplateData($templateDataPlain, true); diff --git a/administrator/components/com_actionlogs/src/Model/ActionlogsModel.php b/administrator/components/com_actionlogs/src/Model/ActionlogsModel.php index ca6c2a8289912..d02610f132f7b 100644 --- a/administrator/components/com_actionlogs/src/Model/ActionlogsModel.php +++ b/administrator/components/com_actionlogs/src/Model/ActionlogsModel.php @@ -90,7 +90,7 @@ protected function populateState($ordering = 'a.id', $direction = 'desc') protected function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('a.*') ->select($db->quoteName('u.name')) ->from($db->quoteName('#__action_logs', 'a')) @@ -212,7 +212,7 @@ private function buildDateRange($range) $dStart->setTime(0, 0, 0); // Now change the timezone back to UTC. - $tz = new \DateTimeZone('GMT'); + $tz = new \DateTimeZone('UTC'); $dStart->setTimezone($tz); break; } @@ -234,7 +234,7 @@ public function getLogsForItem($extension, $itemId) { $itemId = (int) $itemId; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('a.*') ->select($db->quoteName('u.name')) ->from($db->quoteName('#__action_logs', 'a')) @@ -307,7 +307,7 @@ public function getLogDataAsIterator($pks = null) private function getLogDataQuery($pks = null) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('a.*') ->select($db->quoteName('u.name')) ->from($db->quoteName('#__action_logs', 'a')) @@ -334,7 +334,7 @@ public function delete(&$pks) { $keys = ArrayHelper::toInteger($pks); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__action_logs')) ->whereIn($db->quoteName('id'), $keys); $db->setQuery($query); diff --git a/administrator/components/com_actionlogs/src/View/Actionlogs/HtmlView.php b/administrator/components/com_actionlogs/src/View/Actionlogs/HtmlView.php index 6e20d3a76dac2..0e1b817fe69ed 100644 --- a/administrator/components/com_actionlogs/src/View/Actionlogs/HtmlView.php +++ b/administrator/components/com_actionlogs/src/View/Actionlogs/HtmlView.php @@ -11,14 +11,10 @@ namespace Joomla\Component\Actionlogs\Administrator\View\Actionlogs; use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; -use Joomla\CMS\MVC\View\GenericDataException; -use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; -use Joomla\CMS\Pagination\Pagination; +use Joomla\CMS\MVC\View\ListView; use Joomla\CMS\Toolbar\ToolbarHelper; use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper; -use Joomla\Component\Actionlogs\Administrator\Model\ActionlogsModel; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -29,48 +25,8 @@ * * @since 3.9.0 */ -class HtmlView extends BaseHtmlView +class HtmlView extends ListView { - /** - * An array of items. - * - * @var array - * @since 3.9.0 - */ - protected $items; - - /** - * The model state - * - * @var array - * @since 3.9.0 - */ - protected $state; - - /** - * The pagination object - * - * @var Pagination - * @since 3.9.0 - */ - protected $pagination; - - /** - * Form object for search filters - * - * @var Form - * @since 3.9.0 - */ - public $filterForm; - - /** - * The active search filters - * - * @var array - * @since 3.9.0 - */ - public $activeFilters; - /** * Setting if the IP column should be shown * @@ -88,39 +44,41 @@ class HtmlView extends BaseHtmlView protected $dateRelative = false; /** - * Method to display the view. + * Constructor * - * @param string $tpl A template file to load. [optional] + * @param array $config An optional associative array of configuration settings. * - * @return void + * @since 6.0.0 + */ + public function __construct(array $config) + { + if (empty($config['option'])) { + $config['option'] = 'com_actionlogs'; + } + + $config['toolbar_title'] = 'COM_ACTIONLOGS_MANAGER_USERLOGS'; + $config['toolbar_icon'] = 'list-2 actionlog'; + + parent::__construct($config); + } + + /** + * Prepare view data * - * @since 3.9.0 + * @return void * - * @throws \Exception + * @since 6.0.0 */ - public function display($tpl = null) + protected function initializeView() { - /** @var ActionlogsModel $model */ - $model = $this->getModel(); - $this->items = $model->getItems(); - $this->state = $model->getState(); - $this->pagination = $model->getPagination(); - $this->filterForm = $model->getFilterForm(); - $this->activeFilters = $model->getActiveFilters(); + parent::initializeView(); + $params = ComponentHelper::getParams('com_actionlogs'); $this->showIpColumn = (bool) $params->get('ip_logging', 0); $this->dateRelative = (bool) $params->get('date_relative', 1); - if (\count($errors = $model->getErrors())) { - throw new GenericDataException(implode("\n", $errors), 500); - } - - $this->addToolbar(); - // Load all actionlog plugins language files ActionlogsHelper::loadActionLogPluginsLanguage(); - - parent::display($tpl); } /** @@ -133,6 +91,7 @@ public function display($tpl = null) protected function addToolbar() { ToolbarHelper::title(Text::_('COM_ACTIONLOGS_MANAGER_USERLOGS'), 'icon-list-2'); + $toolbar = $this->getDocument()->getToolbar(); $toolbar->standardButton('download', 'COM_ACTIONLOGS_EXPORT_CSV', 'actionlogs.exportSelectedLogs') diff --git a/administrator/components/com_actionlogs/tmpl/actionlogs/default.php b/administrator/components/com_actionlogs/tmpl/actionlogs/default.php index e0f9d0bf806b1..3261fb5568df4 100644 --- a/administrator/components/com_actionlogs/tmpl/actionlogs/default.php +++ b/administrator/components/com_actionlogs/tmpl/actionlogs/default.php @@ -15,9 +15,8 @@ use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\Component\Actionlogs\Administrator\Helper\ActionlogsHelper; -use Joomla\Component\Actionlogs\Administrator\View\Actionlogs\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Actionlogs\Administrator\View\Actionlogs\HtmlView $this */ $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); @@ -118,9 +117,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?>
diff --git a/administrator/components/com_admin/postinstall/behindproxy.php b/administrator/components/com_admin/postinstall/behindproxy.php index 241eeaf1bc574..48d0278731a0a 100644 --- a/administrator/components/com_admin/postinstall/behindproxy.php +++ b/administrator/components/com_admin/postinstall/behindproxy.php @@ -38,11 +38,7 @@ function admin_postinstall_behindproxy_condition() return true; } - if (\array_key_exists('HTTP_CLIENT_IP', $_SERVER) && !empty($_SERVER['HTTP_CLIENT_IP'])) { - return true; - } - - return false; + return !empty($_SERVER['HTTP_CLIENT_IP']); } diff --git a/administrator/components/com_admin/postinstall/languageaccess340.php b/administrator/components/com_admin/postinstall/languageaccess340.php index 32ec165e056c0..e62736d0c8539 100644 --- a/administrator/components/com_admin/postinstall/languageaccess340.php +++ b/administrator/components/com_admin/postinstall/languageaccess340.php @@ -30,7 +30,7 @@ function admin_postinstall_languageaccess340_condition() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('access')) ->from($db->quoteName('#__languages')) ->where($db->quoteName('access') . ' = ' . $db->quote('0')); @@ -38,11 +38,6 @@ function admin_postinstall_languageaccess340_condition() $db->execute(); $numRows = $db->getNumRows(); - if (isset($numRows) && $numRows != 0) { - // We have rows here so we have at minimum one row with access set to 0 - return true; - } - - // All good the query return nothing. - return false; + // Return true if we have have at minimum one row with access set to 0 + return $numRows > 0; } diff --git a/administrator/components/com_admin/script.php b/administrator/components/com_admin/script.php index e0ddda6c73b19..eb77c91dab6b1 100644 --- a/administrator/components/com_admin/script.php +++ b/administrator/components/com_admin/script.php @@ -10,19 +10,15 @@ * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace */ -use Joomla\CMS\Application\ApplicationHelper; -use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Extension\ExtensionHelper; use Joomla\CMS\Factory; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Table\Table; -use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Table\Asset; use Joomla\Database\ParameterType; use Joomla\Filesystem\File; use Joomla\Filesystem\Folder; -use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -174,7 +170,7 @@ protected function clearStatsCache() try { // Get the params for the stats plugin $params = $db->setQuery( - $db->getQuery(true) + $db->createQuery() ->select($db->quoteName('params')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) @@ -196,7 +192,7 @@ protected function clearStatsCache() $params = json_encode($params); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__extensions')) ->set($db->quoteName('params') . ' = ' . $db->quote($params)) ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) @@ -264,7 +260,7 @@ protected function updateDatabaseMysql() /** * Uninstall extensions and optionally migrate their parameters when - * updating from a version older than 5.0.1. + * updating from a version older than 6.0.0. * * @return void * @@ -272,8 +268,8 @@ protected function updateDatabaseMysql() */ protected function uninstallExtensions() { - // Don't uninstall extensions when not updating from a version older than 5.0.1 - if (empty($this->fromVersion) || version_compare($this->fromVersion, '5.0.1', 'ge')) { + // Don't uninstall extensions when not updating from a version older than 6.0.0 + if (empty($this->fromVersion) || version_compare($this->fromVersion, '6.0.0', 'ge')) { return true; } @@ -287,20 +283,19 @@ protected function uninstallExtensions() * 'client_id' => Field `client_id` in the `#__extensions` table * 'pre_function' => Name of an optional migration function to be called before * uninstalling, `null` if not used. + * Examples: + * ['type' => 'plugin', 'element' => 'demotasks', 'folder' => 'task', 'client_id' => 0, 'pre_function' => null], + * ['type' => 'plugin', 'element' => 'compat', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateCompatPlugin'], */ - ['type' => 'plugin', 'element' => 'demotasks', 'folder' => 'task', 'client_id' => 0, 'pre_function' => null], - ['type' => 'plugin', 'element' => 'compat', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateCompatPlugin'], - ['type' => 'plugin', 'element' => 'logrotation', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateLogRotationPlugin'], - ['type' => 'plugin', 'element' => 'recaptcha', 'folder' => 'captcha', 'client_id' => 0, 'pre_function' => null], - ['type' => 'plugin', 'element' => 'sessiongc', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateSessionGCPlugin'], - ['type' => 'plugin', 'element' => 'updatenotification', 'folder' => 'system', 'client_id' => 0, 'pre_function' => 'migrateUpdatenotificationPlugin'], + // Uninstall the old joomla 5 compatibility plugin + ['type' => 'plugin', 'element' => 'compat', 'folder' => 'behaviour', 'client_id' => 0, 'pre_function' => null], ]; $db = Factory::getDbo(); foreach ($extensions as $extension) { $row = $db->setQuery( - $db->getQuery(true) + $db->createQuery() ->select('*') ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote($extension['type'])) @@ -324,7 +319,7 @@ protected function uninstallExtensions() // Unlock and unprotect the plugin so we can uninstall it $db->setQuery( - $db->getQuery(true) + $db->createQuery() ->update($db->quoteName('#__extensions')) ->set($db->quoteName('locked') . ' = 0') ->set($db->quoteName('protected') . ' = 0') @@ -345,162 +340,6 @@ protected function uninstallExtensions() } } - /** - * Migrate plugin parameters of obsolete compat system plugin to compat behaviour plugin - * - * @param \stdClass $rowOld Object with the obsolete plugin's record in the `#__extensions` table - * - * @return void - * - * @since 5.0.0 - */ - private function migrateCompatPlugin($rowOld) - { - $db = Factory::getDbo(); - - $db->setQuery( - $db->getQuery(true) - ->update($db->quoteName('#__extensions')) - ->set($db->quoteName('enabled') . ' = :enabled') - ->set($db->quoteName('params') . ' = :params') - ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) - ->where($db->quoteName('element') . ' = ' . $db->quote('compat')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('behaviour')) - ->where($db->quoteName('client_id') . ' = 0') - ->bind(':enabled', $rowOld->enabled, ParameterType::INTEGER) - ->bind(':params', $rowOld->params) - )->execute(); - } - - /** - * This method is for migration for old logrotation system plugin migration to task. - * - * @param \stdClass $data Object with the extension's record in the `#__extensions` table - * - * @return void - * - * @since 5.0.0 - */ - private function migrateLogRotationPlugin($data) - { - if (!$data->enabled) { - return; - } - - /** @var \Joomla\Component\Scheduler\Administrator\Extension\SchedulerComponent $component */ - $component = Factory::getApplication()->bootComponent('com_scheduler'); - - /** @var \Joomla\Component\Scheduler\Administrator\Model\TaskModel $model */ - $model = $component->getMVCFactory()->createModel('Task', 'Administrator', ['ignore_request' => true]); - - // Get the timeout, as configured in plg_system_logrotation - $params = new Registry($data->params); - $cachetimeout = (int) $params->get('cachetimeout', 30); - $lastrun = (int) $params->get('lastrun', time()); - - $task = [ - 'title' => 'Rotate Logs', - 'type' => 'rotation.logs', - 'execution_rules' => [ - 'rule-type' => 'interval-days', - 'interval-days' => $cachetimeout, - 'exec-time' => gmdate('H:i', $lastrun), - 'exec-day' => gmdate('d'), - ], - 'state' => 1, - 'params' => [ - 'logstokeep' => $params->get('logstokeep', 1), - ], - ]; - $model->save($task); - } - - /** - * This method is for migration for old updatenotification system plugin migration to task. - * - * @param \stdClass $data Object with the extension's record in the `#__extensions` table - * - * @return void - * - * @since 5.0.0 - */ - private function migrateSessionGCPlugin($data) - { - if (!$data->enabled) { - return; - } - - // Get the plugin parameters - $params = new Registry($data->params); - - /** @var \Joomla\Component\Scheduler\Administrator\Extension\SchedulerComponent $component */ - $component = Factory::getApplication()->bootComponent('com_scheduler'); - - /** @var \Joomla\Component\Scheduler\Administrator\Model\TaskModel $model */ - $model = $component->getMVCFactory()->createModel('Task', 'Administrator', ['ignore_request' => true]); - $task = [ - 'title' => 'Session GC', - 'type' => 'session.gc', - 'execution_rules' => [ - 'rule-type' => 'interval-hours', - 'interval-hours' => 24, - 'exec-time' => gmdate('H:i'), - 'exec-day' => gmdate('d'), - ], - 'state' => 1, - 'params' => [ - 'enable_session_gc' => $params->get('enable_session_gc', 1), - 'enable_session_metadata_gc' => $params->get('enable_session_metadata_gc', 1), - ], - ]; - $model->save($task); - } - - /** - * This method is for migration for old updatenotification system plugin migration to task. - * - * @param \stdClass $data Object with the extension's record in the `#__extensions` table - * - * @return void - * - * @since 5.0.0 - */ - private function migrateUpdatenotificationPlugin($data) - { - if (!$data->enabled) { - return; - } - - // Get the timeout for Joomla! updates, as configured in com_installer's component parameters - $component = ComponentHelper::getComponent('com_installer'); - $paramsc = $component->getParams(); - $cachetimeout = (int) $paramsc->get('cachetimeout', 6); - $params = new Registry($data->params); - $lastrun = (int) $params->get('lastrun', time()); - - /** @var \Joomla\Component\Scheduler\Administrator\Extension\SchedulerComponent $component */ - $component = Factory::getApplication()->bootComponent('com_scheduler'); - - /** @var \Joomla\Component\Scheduler\Administrator\Model\TaskModel $model */ - $model = $component->getMVCFactory()->createModel('Task', 'Administrator', ['ignore_request' => true]); - $task = [ - 'title' => 'Update Notification', - 'type' => 'update.notification', - 'execution_rules' => [ - 'rule-type' => 'interval-hours', - 'interval-hours' => $cachetimeout, - 'exec-time' => gmdate('H:i', $lastrun), - 'exec-day' => gmdate('d'), - ], - 'state' => 1, - 'params' => [ - 'email' => $params->get('email', ''), - 'language_override' => $params->get('language_override', ''), - ], - ]; - $model->save($task); - } - /** * Update the manifest caches * @@ -512,7 +351,7 @@ protected function updateManifestCaches() // Attempt to refresh manifest caches $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from('#__extensions'); @@ -575,1915 +414,643 @@ public function deleteUnexistingFiles($dryRun = false, $suppressOutput = false) ]; $files = [ - // From 4.4 to 5.0 - '/administrator/components/com_admin/sql/others/mysql/utf8mb4-conversion.sql', - '/administrator/components/com_admin/sql/others/mysql/utf8mb4-conversion_optional.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2018-03-05.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2018-05-15.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2018-07-19.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2018-07-29.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2018-08-29.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-03-09.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-03-30.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-04-15.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-04-22.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-05-20.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-06-29.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-07-13.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-09-13.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-09-22.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-10-06.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2019-10-17.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2020-02-02.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2020-03-10.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2020-03-25.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2020-05-29.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2020-09-27.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2020-12-20.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2021-04-22.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2021-04-27.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2021-05-30.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2021-06-04.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2021-08-13.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.0-2021-08-17.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.3-2021-09-04.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.3-2021-09-05.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.0.6-2021-12-23.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.1.0-2021-11-20.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.1.0-2021-11-28.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.1.0-2021-12-29.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.1.0-2022-01-08.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.1.0-2022-01-19.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.1.0-2022-01-24.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.1.1-2022-02-20.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.1.3-2022-04-07.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.1.3-2022-04-08.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.2.0-2022-05-15.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.2.0-2022-06-15.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.2.0-2022-06-19.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.2.0-2022-06-22.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.2.0-2022-07-07.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.2.1-2022-08-23.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.2.3-2022-09-07.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.2.7-2022-12-29.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.2.9-2023-03-07.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2022-09-23.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2022-11-06.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2023-01-30.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2023-02-15.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2023-02-25.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2023-03-07.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2023-03-09.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2023-03-10.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2023-03-28.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.0-2023-03-29.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.2-2023-03-31.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.2-2023-05-03.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.3.2-2023-05-20.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.4.0-2023-05-08.sql', - '/administrator/components/com_admin/sql/updates/mysql/4.4.0-2023-09-13.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2018-03-05.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2018-05-15.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2018-07-19.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2018-07-29.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2018-08-29.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-03-09.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-03-30.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-04-15.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-04-22.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-05-20.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-06-29.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-07-13.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-09-13.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-09-22.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-10-06.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2019-10-17.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-02-02.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-03-10.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-03-25.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-05-29.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-08-01.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-09-27.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2020-12-20.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2021-04-22.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2021-04-27.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2021-05-30.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2021-06-04.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2021-08-13.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.0-2021-08-17.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.3-2021-09-04.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.3-2021-09-05.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.0.6-2021-12-23.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.1.0-2021-11-20.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.1.0-2021-11-28.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.1.0-2021-12-29.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.1.0-2022-01-08.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.1.0-2022-01-19.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.1.0-2022-01-24.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.1.1-2022-02-20.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.1.3-2022-04-07.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.1.3-2022-04-08.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.2.0-2022-05-15.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.2.0-2022-06-19.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.2.0-2022-06-22.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.2.0-2022-07-07.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.2.1-2022-08-23.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.2.3-2022-09-07.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.2.7-2022-12-29.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.2.9-2023-03-07.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2022-09-23.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2022-11-06.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2023-01-30.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2023-02-15.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2023-02-25.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2023-03-07.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2023-03-09.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2023-03-10.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2023-03-28.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.0-2023-03-29.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.2-2023-03-31.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.2-2023-05-03.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.3.2-2023-05-20.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.4.0-2023-05-08.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.4.0-2023-09-13.sql', - '/libraries/src/Schema/ChangeItem/SqlsrvChangeItem.php', - '/libraries/vendor/beberlei/assert/lib/Assert/Assert.php', - '/libraries/vendor/beberlei/assert/lib/Assert/Assertion.php', - '/libraries/vendor/beberlei/assert/lib/Assert/AssertionChain.php', - '/libraries/vendor/beberlei/assert/lib/Assert/AssertionFailedException.php', - '/libraries/vendor/beberlei/assert/lib/Assert/functions.php', - '/libraries/vendor/beberlei/assert/lib/Assert/InvalidArgumentException.php', - '/libraries/vendor/beberlei/assert/lib/Assert/LazyAssertion.php', - '/libraries/vendor/beberlei/assert/lib/Assert/LazyAssertionException.php', - '/libraries/vendor/beberlei/assert/LICENSE', - '/libraries/vendor/google/recaptcha/ARCHITECTURE.md', - '/libraries/vendor/jfcherng/php-color-output/src/helpers.php', - '/libraries/vendor/joomla/filter/PATCHES.txt', - '/libraries/vendor/joomla/ldap/LICENSE', - '/libraries/vendor/joomla/ldap/src/LdapClient.php', - '/libraries/vendor/laminas/laminas-zendframework-bridge/config/replacements.php', - '/libraries/vendor/laminas/laminas-zendframework-bridge/COPYRIGHT.md', - '/libraries/vendor/laminas/laminas-zendframework-bridge/LICENSE.md', - '/libraries/vendor/laminas/laminas-zendframework-bridge/src/autoload.php', - '/libraries/vendor/laminas/laminas-zendframework-bridge/src/Autoloader.php', - '/libraries/vendor/laminas/laminas-zendframework-bridge/src/ConfigPostProcessor.php', - '/libraries/vendor/laminas/laminas-zendframework-bridge/src/Module.php', - '/libraries/vendor/laminas/laminas-zendframework-bridge/src/Replacements.php', - '/libraries/vendor/laminas/laminas-zendframework-bridge/src/RewriteRules.php', - '/libraries/vendor/lcobucci/jwt/compat/class-aliases.php', - '/libraries/vendor/lcobucci/jwt/compat/json-exception-polyfill.php', - '/libraries/vendor/lcobucci/jwt/compat/lcobucci-clock-polyfill.php', - '/libraries/vendor/lcobucci/jwt/src/Claim.php', - '/libraries/vendor/lcobucci/jwt/src/Claim/Basic.php', - '/libraries/vendor/lcobucci/jwt/src/Claim/EqualsTo.php', - '/libraries/vendor/lcobucci/jwt/src/Claim/Factory.php', - '/libraries/vendor/lcobucci/jwt/src/Claim/GreaterOrEqualsTo.php', - '/libraries/vendor/lcobucci/jwt/src/Claim/LesserOrEqualsTo.php', - '/libraries/vendor/lcobucci/jwt/src/Claim/Validatable.php', - '/libraries/vendor/lcobucci/jwt/src/Parsing/Decoder.php', - '/libraries/vendor/lcobucci/jwt/src/Parsing/Encoder.php', - '/libraries/vendor/lcobucci/jwt/src/Signature.php', - '/libraries/vendor/lcobucci/jwt/src/Signer/BaseSigner.php', - '/libraries/vendor/lcobucci/jwt/src/Signer/Keychain.php', - '/libraries/vendor/lcobucci/jwt/src/ValidationData.php', - '/libraries/vendor/nyholm/psr7/LICENSE', - '/libraries/vendor/nyholm/psr7/phpstan-baseline.neon', - '/libraries/vendor/nyholm/psr7/psalm.baseline.xml', - '/libraries/vendor/nyholm/psr7/src/Factory/HttplugFactory.php', - '/libraries/vendor/nyholm/psr7/src/Factory/Psr17Factory.php', - '/libraries/vendor/nyholm/psr7/src/MessageTrait.php', - '/libraries/vendor/nyholm/psr7/src/Request.php', - '/libraries/vendor/nyholm/psr7/src/RequestTrait.php', - '/libraries/vendor/nyholm/psr7/src/Response.php', - '/libraries/vendor/nyholm/psr7/src/ServerRequest.php', - '/libraries/vendor/nyholm/psr7/src/Stream.php', - '/libraries/vendor/nyholm/psr7/src/StreamTrait.php', - '/libraries/vendor/nyholm/psr7/src/UploadedFile.php', - '/libraries/vendor/nyholm/psr7/src/Uri.php', - '/libraries/vendor/psr/log/Psr/Log/AbstractLogger.php', - '/libraries/vendor/psr/log/Psr/Log/InvalidArgumentException.php', - '/libraries/vendor/psr/log/Psr/Log/LoggerAwareInterface.php', - '/libraries/vendor/psr/log/Psr/Log/LoggerAwareTrait.php', - '/libraries/vendor/psr/log/Psr/Log/LoggerInterface.php', - '/libraries/vendor/psr/log/Psr/Log/LoggerTrait.php', - '/libraries/vendor/psr/log/Psr/Log/LogLevel.php', - '/libraries/vendor/psr/log/Psr/Log/NullLogger.php', - '/libraries/vendor/ramsey/uuid/LICENSE', - '/libraries/vendor/ramsey/uuid/src/BinaryUtils.php', - '/libraries/vendor/ramsey/uuid/src/Builder/DefaultUuidBuilder.php', - '/libraries/vendor/ramsey/uuid/src/Builder/DegradedUuidBuilder.php', - '/libraries/vendor/ramsey/uuid/src/Builder/UuidBuilderInterface.php', - '/libraries/vendor/ramsey/uuid/src/Codec/CodecInterface.php', - '/libraries/vendor/ramsey/uuid/src/Codec/GuidStringCodec.php', - '/libraries/vendor/ramsey/uuid/src/Codec/OrderedTimeCodec.php', - '/libraries/vendor/ramsey/uuid/src/Codec/StringCodec.php', - '/libraries/vendor/ramsey/uuid/src/Codec/TimestampFirstCombCodec.php', - '/libraries/vendor/ramsey/uuid/src/Codec/TimestampLastCombCodec.php', - '/libraries/vendor/ramsey/uuid/src/Converter/Number/BigNumberConverter.php', - '/libraries/vendor/ramsey/uuid/src/Converter/Number/DegradedNumberConverter.php', - '/libraries/vendor/ramsey/uuid/src/Converter/NumberConverterInterface.php', - '/libraries/vendor/ramsey/uuid/src/Converter/Time/BigNumberTimeConverter.php', - '/libraries/vendor/ramsey/uuid/src/Converter/Time/DegradedTimeConverter.php', - '/libraries/vendor/ramsey/uuid/src/Converter/Time/PhpTimeConverter.php', - '/libraries/vendor/ramsey/uuid/src/Converter/TimeConverterInterface.php', - '/libraries/vendor/ramsey/uuid/src/DegradedUuid.php', - '/libraries/vendor/ramsey/uuid/src/Exception/InvalidUuidStringException.php', - '/libraries/vendor/ramsey/uuid/src/Exception/UnsatisfiedDependencyException.php', - '/libraries/vendor/ramsey/uuid/src/Exception/UnsupportedOperationException.php', - '/libraries/vendor/ramsey/uuid/src/FeatureSet.php', - '/libraries/vendor/ramsey/uuid/src/functions.php', - '/libraries/vendor/ramsey/uuid/src/Generator/CombGenerator.php', - '/libraries/vendor/ramsey/uuid/src/Generator/DefaultTimeGenerator.php', - '/libraries/vendor/ramsey/uuid/src/Generator/MtRandGenerator.php', - '/libraries/vendor/ramsey/uuid/src/Generator/OpenSslGenerator.php', - '/libraries/vendor/ramsey/uuid/src/Generator/PeclUuidRandomGenerator.php', - '/libraries/vendor/ramsey/uuid/src/Generator/PeclUuidTimeGenerator.php', - '/libraries/vendor/ramsey/uuid/src/Generator/RandomBytesGenerator.php', - '/libraries/vendor/ramsey/uuid/src/Generator/RandomGeneratorFactory.php', - '/libraries/vendor/ramsey/uuid/src/Generator/RandomGeneratorInterface.php', - '/libraries/vendor/ramsey/uuid/src/Generator/RandomLibAdapter.php', - '/libraries/vendor/ramsey/uuid/src/Generator/SodiumRandomGenerator.php', - '/libraries/vendor/ramsey/uuid/src/Generator/TimeGeneratorFactory.php', - '/libraries/vendor/ramsey/uuid/src/Generator/TimeGeneratorInterface.php', - '/libraries/vendor/ramsey/uuid/src/Provider/Node/FallbackNodeProvider.php', - '/libraries/vendor/ramsey/uuid/src/Provider/Node/RandomNodeProvider.php', - '/libraries/vendor/ramsey/uuid/src/Provider/Node/SystemNodeProvider.php', - '/libraries/vendor/ramsey/uuid/src/Provider/NodeProviderInterface.php', - '/libraries/vendor/ramsey/uuid/src/Provider/Time/FixedTimeProvider.php', - '/libraries/vendor/ramsey/uuid/src/Provider/Time/SystemTimeProvider.php', - '/libraries/vendor/ramsey/uuid/src/Provider/TimeProviderInterface.php', - '/libraries/vendor/ramsey/uuid/src/Uuid.php', - '/libraries/vendor/ramsey/uuid/src/UuidFactory.php', - '/libraries/vendor/ramsey/uuid/src/UuidFactoryInterface.php', - '/libraries/vendor/ramsey/uuid/src/UuidInterface.php', - '/libraries/vendor/spomky-labs/base64url/LICENSE', - '/libraries/vendor/spomky-labs/base64url/src/Base64Url.php', - '/libraries/vendor/spomky-labs/cbor-php/src/ByteStringWithChunkObject.php', - '/libraries/vendor/spomky-labs/cbor-php/src/InfiniteListObject.php', - '/libraries/vendor/spomky-labs/cbor-php/src/InfiniteMapObject.php', - '/libraries/vendor/spomky-labs/cbor-php/src/SignedIntegerObject.php', - '/libraries/vendor/spomky-labs/cbor-php/src/Tag/EpochTag.php', - '/libraries/vendor/spomky-labs/cbor-php/src/Tag/PositiveBigIntegerTag.php', - '/libraries/vendor/spomky-labs/cbor-php/src/Tag/TagObjectManager.php', - '/libraries/vendor/spomky-labs/cbor-php/src/TagObject.php', - '/libraries/vendor/spomky-labs/cbor-php/src/TextStringWithChunkObject.php', - '/libraries/vendor/symfony/polyfill-php72/bootstrap.php', - '/libraries/vendor/symfony/polyfill-php72/LICENSE', - '/libraries/vendor/symfony/polyfill-php72/Php72.php', - '/libraries/vendor/symfony/polyfill-php73/bootstrap.php', - '/libraries/vendor/symfony/polyfill-php73/LICENSE', - '/libraries/vendor/symfony/polyfill-php73/Php73.php', - '/libraries/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php', - '/libraries/vendor/symfony/polyfill-php80/bootstrap.php', - '/libraries/vendor/symfony/polyfill-php80/LICENSE', - '/libraries/vendor/symfony/polyfill-php80/Php80.php', - '/libraries/vendor/symfony/polyfill-php80/PhpToken.php', - '/libraries/vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php', - '/libraries/vendor/symfony/polyfill-php80/Resources/stubs/PhpToken.php', - '/libraries/vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php', - '/libraries/vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', - '/libraries/vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php', - '/libraries/vendor/symfony/polyfill-php81/bootstrap.php', - '/libraries/vendor/symfony/polyfill-php81/LICENSE', - '/libraries/vendor/symfony/polyfill-php81/Php81.php', - '/libraries/vendor/symfony/polyfill-php81/Resources/stubs/CURLStringFile.php', - '/libraries/vendor/symfony/polyfill-php81/Resources/stubs/ReturnTypeWillChange.php', - '/libraries/vendor/web-auth/cose-lib/src/Verifier.php', - '/libraries/vendor/web-auth/metadata-service/src/AuthenticatorStatus.php', - '/libraries/vendor/web-auth/metadata-service/src/BiometricAccuracyDescriptor.php', - '/libraries/vendor/web-auth/metadata-service/src/BiometricStatusReport.php', - '/libraries/vendor/web-auth/metadata-service/src/CodeAccuracyDescriptor.php', - '/libraries/vendor/web-auth/metadata-service/src/DisplayPNGCharacteristicsDescriptor.php', - '/libraries/vendor/web-auth/metadata-service/src/DistantSingleMetadata.php', - '/libraries/vendor/web-auth/metadata-service/src/DistantSingleMetadataFactory.php', - '/libraries/vendor/web-auth/metadata-service/src/EcdaaTrustAnchor.php', - '/libraries/vendor/web-auth/metadata-service/src/ExtensionDescriptor.php', - '/libraries/vendor/web-auth/metadata-service/src/MetadataService.php', - '/libraries/vendor/web-auth/metadata-service/src/MetadataServiceFactory.php', - '/libraries/vendor/web-auth/metadata-service/src/MetadataStatement.php', - '/libraries/vendor/web-auth/metadata-service/src/MetadataStatementFetcher.php', - '/libraries/vendor/web-auth/metadata-service/src/MetadataTOCPayload.php', - '/libraries/vendor/web-auth/metadata-service/src/MetadataTOCPayloadEntry.php', - '/libraries/vendor/web-auth/metadata-service/src/PatternAccuracyDescriptor.php', - '/libraries/vendor/web-auth/metadata-service/src/RgbPaletteEntry.php', - '/libraries/vendor/web-auth/metadata-service/src/RogueListEntry.php', - '/libraries/vendor/web-auth/metadata-service/src/SimpleMetadataStatementRepository.php', - '/libraries/vendor/web-auth/metadata-service/src/SingleMetadata.php', - '/libraries/vendor/web-auth/metadata-service/src/StatusReport.php', - '/libraries/vendor/web-auth/metadata-service/src/VerificationMethodANDCombinations.php', - '/libraries/vendor/web-auth/metadata-service/src/VerificationMethodDescriptor.php', - '/libraries/vendor/web-auth/metadata-service/src/Version.php', - '/libraries/vendor/web-auth/webauthn-lib/src/Server.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/RSA.php', - '/media/com_templates/js/admin-template-compare-es5.js', - '/media/com_templates/js/admin-template-compare-es5.min.js', - '/media/com_templates/js/admin-template-compare-es5.min.js.gz', - '/media/com_templates/js/admin-template-compare.js', - '/media/com_templates/js/admin-template-compare.min.js', - '/media/com_templates/js/admin-template-compare.min.js.gz', - '/media/com_users/js/admin-users-mail-es5.js', - '/media/com_users/js/admin-users-mail-es5.min.js', - '/media/com_users/js/admin-users-mail-es5.min.js.gz', - '/media/com_users/js/admin-users-mail.js', - '/media/com_users/js/admin-users-mail.min.js', - '/media/com_users/js/admin-users-mail.min.js.gz', - '/media/vendor/fontawesome-free/scss/_larger.scss', - '/media/vendor/fontawesome-free/webfonts/fa-brands-400.eot', - '/media/vendor/fontawesome-free/webfonts/fa-brands-400.svg', - '/media/vendor/fontawesome-free/webfonts/fa-brands-400.woff', - '/media/vendor/fontawesome-free/webfonts/fa-regular-400.eot', - '/media/vendor/fontawesome-free/webfonts/fa-regular-400.svg', - '/media/vendor/fontawesome-free/webfonts/fa-regular-400.woff', - '/media/vendor/fontawesome-free/webfonts/fa-solid-900.eot', - '/media/vendor/fontawesome-free/webfonts/fa-solid-900.svg', - '/media/vendor/fontawesome-free/webfonts/fa-solid-900.woff', - '/media/vendor/tinymce/plugins/bbcode/index.js', - '/media/vendor/tinymce/plugins/bbcode/plugin.js', - '/media/vendor/tinymce/plugins/bbcode/plugin.min.js', - '/media/vendor/tinymce/plugins/bbcode/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/colorpicker/index.js', - '/media/vendor/tinymce/plugins/colorpicker/plugin.js', - '/media/vendor/tinymce/plugins/colorpicker/plugin.min.js', - '/media/vendor/tinymce/plugins/colorpicker/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/contextmenu/index.js', - '/media/vendor/tinymce/plugins/contextmenu/plugin.js', - '/media/vendor/tinymce/plugins/contextmenu/plugin.min.js', - '/media/vendor/tinymce/plugins/contextmenu/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/fullpage/index.js', - '/media/vendor/tinymce/plugins/fullpage/plugin.js', - '/media/vendor/tinymce/plugins/fullpage/plugin.min.js', - '/media/vendor/tinymce/plugins/fullpage/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/hr/index.js', - '/media/vendor/tinymce/plugins/hr/plugin.js', - '/media/vendor/tinymce/plugins/hr/plugin.min.js', - '/media/vendor/tinymce/plugins/hr/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/imagetools/index.js', - '/media/vendor/tinymce/plugins/imagetools/plugin.js', - '/media/vendor/tinymce/plugins/imagetools/plugin.min.js', - '/media/vendor/tinymce/plugins/imagetools/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/legacyoutput/index.js', - '/media/vendor/tinymce/plugins/legacyoutput/plugin.js', - '/media/vendor/tinymce/plugins/legacyoutput/plugin.min.js', - '/media/vendor/tinymce/plugins/legacyoutput/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/noneditable/index.js', - '/media/vendor/tinymce/plugins/noneditable/plugin.js', - '/media/vendor/tinymce/plugins/noneditable/plugin.min.js', - '/media/vendor/tinymce/plugins/noneditable/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/paste/index.js', - '/media/vendor/tinymce/plugins/paste/plugin.js', - '/media/vendor/tinymce/plugins/paste/plugin.min.js', - '/media/vendor/tinymce/plugins/paste/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/print/index.js', - '/media/vendor/tinymce/plugins/print/plugin.js', - '/media/vendor/tinymce/plugins/print/plugin.min.js', - '/media/vendor/tinymce/plugins/print/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/spellchecker/index.js', - '/media/vendor/tinymce/plugins/spellchecker/plugin.js', - '/media/vendor/tinymce/plugins/spellchecker/plugin.min.js', - '/media/vendor/tinymce/plugins/spellchecker/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/tabfocus/index.js', - '/media/vendor/tinymce/plugins/tabfocus/plugin.js', - '/media/vendor/tinymce/plugins/tabfocus/plugin.min.js', - '/media/vendor/tinymce/plugins/tabfocus/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/template/index.js', - '/media/vendor/tinymce/plugins/template/plugin.js', - '/media/vendor/tinymce/plugins/template/plugin.min.js', - '/media/vendor/tinymce/plugins/template/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/textcolor/index.js', - '/media/vendor/tinymce/plugins/textcolor/plugin.js', - '/media/vendor/tinymce/plugins/textcolor/plugin.min.js', - '/media/vendor/tinymce/plugins/textcolor/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/textpattern/index.js', - '/media/vendor/tinymce/plugins/textpattern/plugin.js', - '/media/vendor/tinymce/plugins/textpattern/plugin.min.js', - '/media/vendor/tinymce/plugins/textpattern/plugin.min.js.gz', - '/media/vendor/tinymce/plugins/toc/index.js', - '/media/vendor/tinymce/plugins/toc/plugin.js', - '/media/vendor/tinymce/plugins/toc/plugin.min.js', - '/media/vendor/tinymce/plugins/toc/plugin.min.js.gz', - '/media/vendor/tinymce/skins/ui/oxide-dark/content.mobile.css', - '/media/vendor/tinymce/skins/ui/oxide-dark/content.mobile.min.css', - '/media/vendor/tinymce/skins/ui/oxide-dark/content.mobile.min.css.gz', - '/media/vendor/tinymce/skins/ui/oxide-dark/fonts/tinymce-mobile.woff', - '/media/vendor/tinymce/skins/ui/oxide-dark/skin.mobile.css', - '/media/vendor/tinymce/skins/ui/oxide-dark/skin.mobile.min.css', - '/media/vendor/tinymce/skins/ui/oxide-dark/skin.mobile.min.css.gz', - '/media/vendor/tinymce/skins/ui/oxide/content.mobile.css', - '/media/vendor/tinymce/skins/ui/oxide/content.mobile.min.css', - '/media/vendor/tinymce/skins/ui/oxide/content.mobile.min.css.gz', - '/media/vendor/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff', - '/media/vendor/tinymce/skins/ui/oxide/skin.mobile.css', - '/media/vendor/tinymce/skins/ui/oxide/skin.mobile.min.css', - '/media/vendor/tinymce/skins/ui/oxide/skin.mobile.min.css.gz', - '/media/vendor/tinymce/themes/mobile/index.js', - '/media/vendor/tinymce/themes/mobile/theme.js', - '/media/vendor/tinymce/themes/mobile/theme.min.js', - '/media/vendor/tinymce/themes/mobile/theme.min.js.gz', - '/plugins/multifactorauth/webauthn/src/Hotfix/AndroidKeyAttestationStatementSupport.php', - '/plugins/multifactorauth/webauthn/src/Hotfix/FidoU2FAttestationStatementSupport.php', - '/plugins/multifactorauth/webauthn/src/Hotfix/Server.php', - '/plugins/system/webauthn/src/Hotfix/AndroidKeyAttestationStatementSupport.php', - '/plugins/system/webauthn/src/Hotfix/FidoU2FAttestationStatementSupport.php', - '/plugins/system/webauthn/src/Hotfix/Server.php', - // From 5.0.0-alpha1 to 5.0.0-alpha2 - '/libraries/vendor/jfcherng/php-diff/src/languages/readme.txt', - '/media/com_actionlogs/js/admin-actionlogs-default-es5.js', - '/media/com_actionlogs/js/admin-actionlogs-default-es5.min.js', - '/media/com_actionlogs/js/admin-actionlogs-default-es5.min.js.gz', - '/media/com_admin/js/admin-help-es5.js', - '/media/com_admin/js/admin-help-es5.min.js', - '/media/com_admin/js/admin-help-es5.min.js.gz', - '/media/com_associations/js/admin-associations-default-es5.js', - '/media/com_associations/js/admin-associations-default-es5.min.js', - '/media/com_associations/js/admin-associations-default-es5.min.js.gz', - '/media/com_associations/js/admin-associations-modal-es5.js', - '/media/com_associations/js/admin-associations-modal-es5.min.js', - '/media/com_associations/js/admin-associations-modal-es5.min.js.gz', - '/media/com_associations/js/associations-edit-es5.js', - '/media/com_associations/js/associations-edit-es5.min.js', - '/media/com_associations/js/associations-edit-es5.min.js.gz', - '/media/com_banners/js/admin-banner-edit-es5.js', - '/media/com_banners/js/admin-banner-edit-es5.min.js', - '/media/com_banners/js/admin-banner-edit-es5.min.js.gz', - '/media/com_cache/js/admin-cache-default-es5.js', - '/media/com_cache/js/admin-cache-default-es5.min.js', - '/media/com_cache/js/admin-cache-default-es5.min.js.gz', - '/media/com_categories/js/shared-categories-accordion-es5.js', - '/media/com_categories/js/shared-categories-accordion-es5.min.js', - '/media/com_categories/js/shared-categories-accordion-es5.min.js.gz', - '/media/com_config/js/config-default-es5.js', - '/media/com_config/js/config-default-es5.min.js', - '/media/com_config/js/config-default-es5.min.js.gz', - '/media/com_config/js/config-filters-es5.js', - '/media/com_config/js/config-filters-es5.min.js', - '/media/com_config/js/config-filters-es5.min.js.gz', - '/media/com_config/js/modules-default-es5.js', - '/media/com_config/js/modules-default-es5.min.js', - '/media/com_config/js/modules-default-es5.min.js.gz', - '/media/com_config/js/templates-default-es5.js', - '/media/com_config/js/templates-default-es5.min.js', - '/media/com_config/js/templates-default-es5.min.js.gz', - '/media/com_contact/js/admin-contacts-modal-es5.js', - '/media/com_contact/js/admin-contacts-modal-es5.min.js', - '/media/com_contact/js/admin-contacts-modal-es5.min.js.gz', - '/media/com_contact/js/contacts-list-es5.js', - '/media/com_contact/js/contacts-list-es5.min.js', - '/media/com_contact/js/contacts-list-es5.min.js.gz', - '/media/com_content/js/admin-article-pagebreak-es5.js', - '/media/com_content/js/admin-article-pagebreak-es5.min.js', - '/media/com_content/js/admin-article-pagebreak-es5.min.js.gz', - '/media/com_content/js/admin-article-readmore-es5.js', - '/media/com_content/js/admin-article-readmore-es5.min.js', - '/media/com_content/js/admin-article-readmore-es5.min.js.gz', - '/media/com_content/js/admin-articles-default-batch-footer-es5.js', - '/media/com_content/js/admin-articles-default-batch-footer-es5.min.js', - '/media/com_content/js/admin-articles-default-batch-footer-es5.min.js.gz', - '/media/com_content/js/admin-articles-default-stage-footer-es5.js', - '/media/com_content/js/admin-articles-default-stage-footer-es5.min.js', - '/media/com_content/js/admin-articles-default-stage-footer-es5.min.js.gz', - '/media/com_content/js/admin-articles-modal-es5.js', - '/media/com_content/js/admin-articles-modal-es5.min.js', - '/media/com_content/js/admin-articles-modal-es5.min.js.gz', - '/media/com_content/js/articles-list-es5.js', - '/media/com_content/js/articles-list-es5.min.js', - '/media/com_content/js/articles-list-es5.min.js.gz', - '/media/com_content/js/articles-status-es5.js', - '/media/com_content/js/articles-status-es5.min.js', - '/media/com_content/js/articles-status-es5.min.js.gz', - '/media/com_content/js/form-edit-es5.js', - '/media/com_content/js/form-edit-es5.min.js', - '/media/com_content/js/form-edit-es5.min.js.gz', - '/media/com_contenthistory/js/admin-compare-compare-es5.js', - '/media/com_contenthistory/js/admin-compare-compare-es5.min.js', - '/media/com_contenthistory/js/admin-compare-compare-es5.min.js.gz', - '/media/com_contenthistory/js/admin-history-modal-es5.js', - '/media/com_contenthistory/js/admin-history-modal-es5.min.js', - '/media/com_contenthistory/js/admin-history-modal-es5.min.js.gz', - '/media/com_contenthistory/js/admin-history-versions-es5.js', - '/media/com_contenthistory/js/admin-history-versions-es5.min.js', - '/media/com_contenthistory/js/admin-history-versions-es5.min.js.gz', - '/media/com_cpanel/js/admin-add_module-es5.js', - '/media/com_cpanel/js/admin-add_module-es5.min.js', - '/media/com_cpanel/js/admin-add_module-es5.min.js.gz', - '/media/com_cpanel/js/admin-cpanel-default-es5.js', - '/media/com_cpanel/js/admin-cpanel-default-es5.min.js', - '/media/com_cpanel/js/admin-cpanel-default-es5.min.js.gz', - '/media/com_cpanel/js/admin-system-loader-es5.js', - '/media/com_cpanel/js/admin-system-loader-es5.min.js', - '/media/com_cpanel/js/admin-system-loader-es5.min.js.gz', - '/media/com_fields/js/admin-field-changecontext-es5.js', - '/media/com_fields/js/admin-field-changecontext-es5.min.js', - '/media/com_fields/js/admin-field-changecontext-es5.min.js.gz', - '/media/com_fields/js/admin-field-edit-es5.js', - '/media/com_fields/js/admin-field-edit-es5.min.js', - '/media/com_fields/js/admin-field-edit-es5.min.js.gz', - '/media/com_fields/js/admin-field-typehaschanged-es5.js', - '/media/com_fields/js/admin-field-typehaschanged-es5.min.js', - '/media/com_fields/js/admin-field-typehaschanged-es5.min.js.gz', - '/media/com_fields/js/admin-fields-default-batch-es5.js', - '/media/com_fields/js/admin-fields-default-batch-es5.min.js', - '/media/com_fields/js/admin-fields-default-batch-es5.min.js.gz', - '/media/com_fields/js/admin-fields-modal-es5.js', - '/media/com_fields/js/admin-fields-modal-es5.min.js', - '/media/com_fields/js/admin-fields-modal-es5.min.js.gz', - '/media/com_finder/js/debug-es5.js', - '/media/com_finder/js/debug-es5.min.js', - '/media/com_finder/js/debug-es5.min.js.gz', - '/media/com_finder/js/filters-es5.js', - '/media/com_finder/js/filters-es5.min.js', - '/media/com_finder/js/filters-es5.min.js.gz', - '/media/com_finder/js/finder-edit-es5.js', - '/media/com_finder/js/finder-edit-es5.min.js', - '/media/com_finder/js/finder-edit-es5.min.js.gz', - '/media/com_finder/js/finder-es5.js', - '/media/com_finder/js/finder-es5.min.js', - '/media/com_finder/js/finder-es5.min.js.gz', - '/media/com_finder/js/indexer-es5.js', - '/media/com_finder/js/indexer-es5.min.js', - '/media/com_finder/js/indexer-es5.min.js.gz', - '/media/com_finder/js/maps-es5.js', - '/media/com_finder/js/maps-es5.min.js', - '/media/com_finder/js/maps-es5.min.js.gz', - '/media/com_installer/js/changelog-es5.js', - '/media/com_installer/js/changelog-es5.min.js', - '/media/com_installer/js/changelog-es5.min.js.gz', - '/media/com_installer/js/installer-es5.js', - '/media/com_installer/js/installer-es5.min.js', - '/media/com_installer/js/installer-es5.min.js.gz', - '/media/com_joomlaupdate/js/admin-update-default-es5.js', - '/media/com_joomlaupdate/js/admin-update-default-es5.min.js', - '/media/com_joomlaupdate/js/admin-update-default-es5.min.js.gz', - '/media/com_joomlaupdate/js/default-es5.js', - '/media/com_joomlaupdate/js/default-es5.min.js', - '/media/com_joomlaupdate/js/default-es5.min.js.gz', - '/media/com_languages/js/admin-language-edit-change-flag-es5.js', - '/media/com_languages/js/admin-language-edit-change-flag-es5.min.js', - '/media/com_languages/js/admin-language-edit-change-flag-es5.min.js.gz', - '/media/com_languages/js/admin-override-edit-refresh-searchstring-es5.js', - '/media/com_languages/js/admin-override-edit-refresh-searchstring-es5.min.js', - '/media/com_languages/js/admin-override-edit-refresh-searchstring-es5.min.js.gz', - '/media/com_languages/js/overrider-es5.js', - '/media/com_languages/js/overrider-es5.min.js', - '/media/com_languages/js/overrider-es5.min.js.gz', - '/media/com_mails/js/admin-email-template-edit-es5.js', - '/media/com_mails/js/admin-email-template-edit-es5.min.js', - '/media/com_mails/js/admin-email-template-edit-es5.min.js.gz', - '/media/com_media/js/edit-images-es5.js', - '/media/com_media/js/edit-images-es5.min.js', - '/media/com_media/js/edit-images-es5.min.js.gz', - '/media/com_media/js/media-manager-es5.js', - '/media/com_media/js/media-manager-es5.min.js', - '/media/com_media/js/media-manager-es5.min.js.gz', - '/media/com_menus/js/admin-item-edit-es5.js', - '/media/com_menus/js/admin-item-edit-es5.min.js', - '/media/com_menus/js/admin-item-edit-es5.min.js.gz', - '/media/com_menus/js/admin-item-edit_container-es5.js', - '/media/com_menus/js/admin-item-edit_container-es5.min.js', - '/media/com_menus/js/admin-item-edit_container-es5.min.js.gz', - '/media/com_menus/js/admin-item-edit_modules-es5.js', - '/media/com_menus/js/admin-item-edit_modules-es5.min.js', - '/media/com_menus/js/admin-item-edit_modules-es5.min.js.gz', - '/media/com_menus/js/admin-item-modal-es5.js', - '/media/com_menus/js/admin-item-modal-es5.min.js', - '/media/com_menus/js/admin-item-modal-es5.min.js.gz', - '/media/com_menus/js/admin-items-modal-es5.js', - '/media/com_menus/js/admin-items-modal-es5.min.js', - '/media/com_menus/js/admin-items-modal-es5.min.js.gz', - '/media/com_menus/js/admin-menus-default-es5.js', - '/media/com_menus/js/admin-menus-default-es5.min.js', - '/media/com_menus/js/admin-menus-default-es5.min.js.gz', - '/media/com_menus/js/default-batch-body-es5.js', - '/media/com_menus/js/default-batch-body-es5.min.js', - '/media/com_menus/js/default-batch-body-es5.min.js.gz', - '/media/com_modules/js/admin-module-edit-es5.js', - '/media/com_modules/js/admin-module-edit-es5.min.js', - '/media/com_modules/js/admin-module-edit-es5.min.js.gz', - '/media/com_modules/js/admin-module-edit_assignment-es5.js', - '/media/com_modules/js/admin-module-edit_assignment-es5.min.js', - '/media/com_modules/js/admin-module-edit_assignment-es5.min.js.gz', - '/media/com_modules/js/admin-module-search-es5.js', - '/media/com_modules/js/admin-module-search-es5.min.js', - '/media/com_modules/js/admin-module-search-es5.min.js.gz', - '/media/com_modules/js/admin-modules-modal-es5.js', - '/media/com_modules/js/admin-modules-modal-es5.min.js', - '/media/com_modules/js/admin-modules-modal-es5.min.js.gz', - '/media/com_modules/js/admin-select-modal-es5.js', - '/media/com_modules/js/admin-select-modal-es5.min.js', - '/media/com_modules/js/admin-select-modal-es5.min.js.gz', - '/media/com_scheduler/js/admin-view-run-test-task-es5.js', - '/media/com_scheduler/js/admin-view-run-test-task-es5.min.js', - '/media/com_scheduler/js/admin-view-run-test-task-es5.min.js.gz', - '/media/com_scheduler/js/admin-view-select-task-search-es5.js', - '/media/com_scheduler/js/admin-view-select-task-search-es5.min.js', - '/media/com_scheduler/js/admin-view-select-task-search-es5.min.js.gz', - '/media/com_scheduler/js/scheduler-config-es5.js', - '/media/com_scheduler/js/scheduler-config-es5.min.js', - '/media/com_scheduler/js/scheduler-config-es5.min.js.gz', - '/media/com_tags/js/tag-default-es5.js', - '/media/com_tags/js/tag-default-es5.min.js', - '/media/com_tags/js/tag-default-es5.min.js.gz', - '/media/com_tags/js/tag-list-es5.js', - '/media/com_tags/js/tag-list-es5.min.js', - '/media/com_tags/js/tag-list-es5.min.js.gz', - '/media/com_tags/js/tags-default-es5.js', - '/media/com_tags/js/tags-default-es5.min.js', - '/media/com_tags/js/tags-default-es5.min.js.gz', - '/media/com_templates/js/admin-template-compare-es5.js', - '/media/com_templates/js/admin-template-compare-es5.min.js', - '/media/com_templates/js/admin-template-compare-es5.min.js.gz', - '/media/com_templates/js/admin-template-toggle-assignment-es5.js', - '/media/com_templates/js/admin-template-toggle-assignment-es5.min.js', - '/media/com_templates/js/admin-template-toggle-assignment-es5.min.js.gz', - '/media/com_templates/js/admin-template-toggle-switch-es5.js', - '/media/com_templates/js/admin-template-toggle-switch-es5.min.js', - '/media/com_templates/js/admin-template-toggle-switch-es5.min.js.gz', - '/media/com_templates/js/admin-templates-default-es5.js', - '/media/com_templates/js/admin-templates-default-es5.min.js', - '/media/com_templates/js/admin-templates-default-es5.min.js.gz', - '/media/com_users/js/admin-users-groups-es5.js', - '/media/com_users/js/admin-users-groups-es5.min.js', - '/media/com_users/js/admin-users-groups-es5.min.js.gz', - '/media/com_users/js/admin-users-mail-es5.js', - '/media/com_users/js/admin-users-mail-es5.min.js', - '/media/com_users/js/admin-users-mail-es5.min.js.gz', - '/media/com_users/js/two-factor-focus-es5.js', - '/media/com_users/js/two-factor-focus-es5.min.js', - '/media/com_users/js/two-factor-focus-es5.min.js.gz', - '/media/com_users/js/two-factor-list-es5.js', - '/media/com_users/js/two-factor-list-es5.min.js', - '/media/com_users/js/two-factor-list-es5.min.js.gz', - '/media/com_workflow/js/admin-items-workflow-buttons-es5.js', - '/media/com_workflow/js/admin-items-workflow-buttons-es5.min.js', - '/media/com_workflow/js/admin-items-workflow-buttons-es5.min.js.gz', - '/media/com_wrapper/js/iframe-height-es5.js', - '/media/com_wrapper/js/iframe-height-es5.min.js', - '/media/com_wrapper/js/iframe-height-es5.min.js.gz', - '/media/layouts/js/joomla/form/field/category-change-es5.js', - '/media/layouts/js/joomla/form/field/category-change-es5.min.js', - '/media/layouts/js/joomla/form/field/category-change-es5.min.js.gz', - '/media/layouts/js/joomla/html/batch/batch-copymove-es5.js', - '/media/layouts/js/joomla/html/batch/batch-copymove-es5.min.js', - '/media/layouts/js/joomla/html/batch/batch-copymove-es5.min.js.gz', - '/media/mod_login/js/admin-login-es5.js', - '/media/mod_login/js/admin-login-es5.min.js', - '/media/mod_login/js/admin-login-es5.min.js.gz', - '/media/mod_menu/js/admin-menu-es5.js', - '/media/mod_menu/js/admin-menu-es5.min.js', - '/media/mod_menu/js/admin-menu-es5.min.js.gz', - '/media/mod_menu/js/menu-es5.js', - '/media/mod_menu/js/menu-es5.min.js', - '/media/mod_menu/js/menu-es5.min.js.gz', - '/media/mod_multilangstatus/js/admin-multilangstatus-es5.js', - '/media/mod_multilangstatus/js/admin-multilangstatus-es5.min.js', - '/media/mod_multilangstatus/js/admin-multilangstatus-es5.min.js.gz', - '/media/mod_quickicon/js/quickicon-es5.js', - '/media/mod_quickicon/js/quickicon-es5.min.js', - '/media/mod_quickicon/js/quickicon-es5.min.js.gz', - '/media/mod_sampledata/js/sampledata-process-es5.js', - '/media/mod_sampledata/js/sampledata-process-es5.min.js', - '/media/mod_sampledata/js/sampledata-process-es5.min.js.gz', - '/media/plg_captcha_recaptcha/js/recaptcha-es5.js', - '/media/plg_captcha_recaptcha/js/recaptcha-es5.min.js', - '/media/plg_captcha_recaptcha/js/recaptcha-es5.min.js.gz', - '/media/plg_captcha_recaptcha_invisible/js/recaptcha-es5.js', - '/media/plg_captcha_recaptcha_invisible/js/recaptcha-es5.min.js', - '/media/plg_captcha_recaptcha_invisible/js/recaptcha-es5.min.js.gz', - '/media/plg_editors_codemirror/js/joomla-editor-codemirror-es5.js', - '/media/plg_editors_codemirror/js/joomla-editor-codemirror-es5.min.js', - '/media/plg_editors_codemirror/js/joomla-editor-codemirror-es5.min.js.gz', - '/media/plg_editors_none/js/joomla-editor-none-es5.js', - '/media/plg_editors_none/js/joomla-editor-none-es5.min.js', - '/media/plg_editors_none/js/joomla-editor-none-es5.min.js.gz', - '/media/plg_editors_tinymce/js/plugins/highlighter/plugin-es5.js', - '/media/plg_editors_tinymce/js/plugins/highlighter/plugin-es5.min.js', - '/media/plg_editors_tinymce/js/plugins/highlighter/plugin-es5.min.js.gz', - '/media/plg_editors_tinymce/js/plugins/highlighter/source-es5.js', - '/media/plg_editors_tinymce/js/plugins/highlighter/source-es5.min.js', - '/media/plg_editors_tinymce/js/plugins/highlighter/source-es5.min.js.gz', - '/media/plg_editors_tinymce/js/tinymce-builder-es5.js', - '/media/plg_editors_tinymce/js/tinymce-builder-es5.min.js', - '/media/plg_editors_tinymce/js/tinymce-builder-es5.min.js.gz', - '/media/plg_editors_tinymce/js/tinymce-es5.js', - '/media/plg_editors_tinymce/js/tinymce-es5.min.js', - '/media/plg_editors_tinymce/js/tinymce-es5.min.js.gz', - '/media/plg_installer_folderinstaller/js/folderinstaller-es5.js', - '/media/plg_installer_folderinstaller/js/folderinstaller-es5.min.js', - '/media/plg_installer_folderinstaller/js/folderinstaller-es5.min.js.gz', - '/media/plg_installer_packageinstaller/js/packageinstaller-es5.js', - '/media/plg_installer_packageinstaller/js/packageinstaller-es5.min.js', - '/media/plg_installer_packageinstaller/js/packageinstaller-es5.min.js.gz', - '/media/plg_installer_urlinstaller/js/urlinstaller-es5.js', - '/media/plg_installer_urlinstaller/js/urlinstaller-es5.min.js', - '/media/plg_installer_urlinstaller/js/urlinstaller-es5.min.js.gz', - '/media/plg_installer_webinstaller/js/client-es5.js', - '/media/plg_installer_webinstaller/js/client-es5.min.js', - '/media/plg_installer_webinstaller/js/client-es5.min.js.gz', - '/media/plg_media-action_crop/js/crop-es5.js', - '/media/plg_media-action_crop/js/crop-es5.min.js', - '/media/plg_media-action_crop/js/crop-es5.min.js.gz', - '/media/plg_media-action_resize/js/resize-es5.js', - '/media/plg_media-action_resize/js/resize-es5.min.js', - '/media/plg_media-action_resize/js/resize-es5.min.js.gz', - '/media/plg_media-action_rotate/js/rotate-es5.js', - '/media/plg_media-action_rotate/js/rotate-es5.min.js', - '/media/plg_media-action_rotate/js/rotate-es5.min.js.gz', - '/media/plg_multifactorauth_totp/js/setup-es5.js', - '/media/plg_multifactorauth_totp/js/setup-es5.min.js', - '/media/plg_multifactorauth_totp/js/setup-es5.min.js.gz', - '/media/plg_multifactorauth_webauthn/js/webauthn-es5.js', - '/media/plg_multifactorauth_webauthn/js/webauthn-es5.min.js', - '/media/plg_multifactorauth_webauthn/js/webauthn-es5.min.js.gz', - '/media/plg_quickicon_eos/js/snooze-es5.js', - '/media/plg_quickicon_eos/js/snooze-es5.min.js', - '/media/plg_quickicon_eos/js/snooze-es5.min.js.gz', - '/media/plg_quickicon_extensionupdate/js/extensionupdatecheck-es5.js', - '/media/plg_quickicon_extensionupdate/js/extensionupdatecheck-es5.min.js', - '/media/plg_quickicon_extensionupdate/js/extensionupdatecheck-es5.min.js.gz', - '/media/plg_quickicon_joomlaupdate/js/jupdatecheck-es5.js', - '/media/plg_quickicon_joomlaupdate/js/jupdatecheck-es5.min.js', - '/media/plg_quickicon_joomlaupdate/js/jupdatecheck-es5.min.js.gz', - '/media/plg_quickicon_overridecheck/js/overridecheck-es5.js', - '/media/plg_quickicon_overridecheck/js/overridecheck-es5.min.js', - '/media/plg_quickicon_overridecheck/js/overridecheck-es5.min.js.gz', - '/media/plg_quickicon_privacycheck/js/privacycheck-es5.js', - '/media/plg_quickicon_privacycheck/js/privacycheck-es5.min.js', - '/media/plg_quickicon_privacycheck/js/privacycheck-es5.min.js.gz', - '/media/plg_system_debug/js/debug-es5.js', - '/media/plg_system_debug/js/debug-es5.min.js', - '/media/plg_system_debug/js/debug-es5.min.js.gz', - '/media/plg_system_guidedtours/js/guidedtours-es5.js', - '/media/plg_system_guidedtours/js/guidedtours-es5.min.js', - '/media/plg_system_guidedtours/js/guidedtours-es5.min.js.gz', - '/media/plg_system_jooa11y/js/jooa11y-es5.js', - '/media/plg_system_jooa11y/js/jooa11y-es5.min.js', - '/media/plg_system_jooa11y/js/jooa11y-es5.min.js.gz', - '/media/plg_system_schedulerunner/js/run-schedule-es5.js', - '/media/plg_system_schedulerunner/js/run-schedule-es5.min.js', - '/media/plg_system_schedulerunner/js/run-schedule-es5.min.js.gz', - '/media/plg_system_shortcut/js/shortcut-es5.js', - '/media/plg_system_shortcut/js/shortcut-es5.min.js', - '/media/plg_system_shortcut/js/shortcut-es5.min.js.gz', - '/media/plg_system_stats/js/stats-es5.js', - '/media/plg_system_stats/js/stats-es5.min.js', - '/media/plg_system_stats/js/stats-es5.min.js.gz', - '/media/plg_system_stats/js/stats-message-es5.js', - '/media/plg_system_stats/js/stats-message-es5.min.js', - '/media/plg_system_stats/js/stats-message-es5.min.js.gz', - '/media/plg_system_webauthn/js/login-es5.js', - '/media/plg_system_webauthn/js/login-es5.min.js', - '/media/plg_system_webauthn/js/login-es5.min.js.gz', - '/media/plg_system_webauthn/js/management-es5.js', - '/media/plg_system_webauthn/js/management-es5.min.js', - '/media/plg_system_webauthn/js/management-es5.min.js.gz', - '/media/plg_user_token/js/token-es5.js', - '/media/plg_user_token/js/token-es5.min.js', - '/media/plg_user_token/js/token-es5.min.js.gz', - '/media/system/js/core-es5.js', - '/media/system/js/core-es5.min.js', - '/media/system/js/core-es5.min.js.gz', - '/media/system/js/draggable-es5.js', - '/media/system/js/draggable-es5.min.js', - '/media/system/js/draggable-es5.min.js.gz', - '/media/system/js/fields/joomla-field-color-slider-es5.js', - '/media/system/js/fields/joomla-field-color-slider-es5.min.js', - '/media/system/js/fields/joomla-field-color-slider-es5.min.js.gz', - '/media/system/js/fields/joomla-field-fancy-select-es5.js', - '/media/system/js/fields/joomla-field-fancy-select-es5.min.js', - '/media/system/js/fields/joomla-field-fancy-select-es5.min.js.gz', - '/media/system/js/fields/joomla-field-media-es5.js', - '/media/system/js/fields/joomla-field-media-es5.min.js', - '/media/system/js/fields/joomla-field-media-es5.min.js.gz', - '/media/system/js/fields/joomla-field-module-order-es5.js', - '/media/system/js/fields/joomla-field-module-order-es5.min.js', - '/media/system/js/fields/joomla-field-module-order-es5.min.js.gz', - '/media/system/js/fields/joomla-field-permissions-es5.js', - '/media/system/js/fields/joomla-field-permissions-es5.min.js', - '/media/system/js/fields/joomla-field-permissions-es5.min.js.gz', - '/media/system/js/fields/joomla-field-send-test-mail-es5.js', - '/media/system/js/fields/joomla-field-send-test-mail-es5.min.js', - '/media/system/js/fields/joomla-field-send-test-mail-es5.min.js.gz', - '/media/system/js/fields/joomla-field-simple-color-es5.js', - '/media/system/js/fields/joomla-field-simple-color-es5.min.js', - '/media/system/js/fields/joomla-field-simple-color-es5.min.js.gz', - '/media/system/js/fields/joomla-field-subform-es5.js', - '/media/system/js/fields/joomla-field-subform-es5.min.js', - '/media/system/js/fields/joomla-field-subform-es5.min.js.gz', - '/media/system/js/fields/joomla-field-user-es5.js', - '/media/system/js/fields/joomla-field-user-es5.min.js', - '/media/system/js/fields/joomla-field-user-es5.min.js.gz', - '/media/system/js/fields/joomla-media-select-es5.js', - '/media/system/js/fields/joomla-media-select-es5.min.js', - '/media/system/js/fields/joomla-media-select-es5.min.js.gz', - '/media/system/js/fields/passwordstrength-es5.js', - '/media/system/js/fields/passwordstrength-es5.min.js', - '/media/system/js/fields/passwordstrength-es5.min.js.gz', - '/media/system/js/fields/passwordview-es5.js', - '/media/system/js/fields/passwordview-es5.min.js', - '/media/system/js/fields/passwordview-es5.min.js.gz', - '/media/system/js/fields/select-colour-es5.js', - '/media/system/js/fields/select-colour-es5.min.js', - '/media/system/js/fields/select-colour-es5.min.js.gz', - '/media/system/js/fields/validate-es5.js', - '/media/system/js/fields/validate-es5.min.js', - '/media/system/js/fields/validate-es5.min.js.gz', - '/media/system/js/highlight-es5.js', - '/media/system/js/highlight-es5.min.js', - '/media/system/js/highlight-es5.min.js.gz', - '/media/system/js/inlinehelp-es5.js', - '/media/system/js/inlinehelp-es5.min.js', - '/media/system/js/inlinehelp-es5.min.js.gz', - '/media/system/js/joomla-core-loader-es5.js', - '/media/system/js/joomla-core-loader-es5.min.js', - '/media/system/js/joomla-core-loader-es5.min.js.gz', - '/media/system/js/joomla-hidden-mail-es5.js', - '/media/system/js/joomla-hidden-mail-es5.min.js', - '/media/system/js/joomla-hidden-mail-es5.min.js.gz', - '/media/system/js/joomla-toolbar-button-es5.js', - '/media/system/js/joomla-toolbar-button-es5.min.js', - '/media/system/js/joomla-toolbar-button-es5.min.js.gz', - '/media/system/js/keepalive-es5.js', - '/media/system/js/keepalive-es5.min.js', - '/media/system/js/keepalive-es5.min.js.gz', - '/media/system/js/list-view-es5.js', - '/media/system/js/list-view-es5.min.js', - '/media/system/js/list-view-es5.min.js.gz', - '/media/system/js/messages-es5.js', - '/media/system/js/messages-es5.min.js', - '/media/system/js/messages-es5.min.js.gz', - '/media/system/js/multiselect-es5.js', - '/media/system/js/multiselect-es5.min.js', - '/media/system/js/multiselect-es5.min.js.gz', - '/media/system/js/searchtools-es5.js', - '/media/system/js/searchtools-es5.min.js', - '/media/system/js/searchtools-es5.min.js.gz', - '/media/system/js/showon-es5.js', - '/media/system/js/showon-es5.min.js', - '/media/system/js/showon-es5.min.js.gz', - '/media/system/js/table-columns-es5.js', - '/media/system/js/table-columns-es5.min.js', - '/media/system/js/table-columns-es5.min.js.gz', - '/media/templates/administrator/atum/js/template-es5.js', - '/media/templates/administrator/atum/js/template-es5.min.js', - '/media/templates/administrator/atum/js/template-es5.min.js.gz', - '/media/templates/site/cassiopeia/js/mod_menu/menu-metismenu-es5.js', - '/media/templates/site/cassiopeia/js/mod_menu/menu-metismenu-es5.min.js', - '/media/templates/site/cassiopeia/js/mod_menu/menu-metismenu-es5.min.js.gz', - '/media/vendor/bootstrap/js/bootstrap-es5.js', - '/media/vendor/bootstrap/js/bootstrap-es5.min.js', - '/media/vendor/bootstrap/js/bootstrap-es5.min.js.gz', - '/media/vendor/joomla-custom-elements/js/joomla-alert-es5.js', - '/media/vendor/joomla-custom-elements/js/joomla-alert-es5.min.js', - '/media/vendor/joomla-custom-elements/js/joomla-alert-es5.min.js.gz', - '/media/vendor/joomla-custom-elements/js/joomla-tab-es5.js', - '/media/vendor/joomla-custom-elements/js/joomla-tab-es5.min.js', - '/media/vendor/joomla-custom-elements/js/joomla-tab-es5.min.js.gz', - '/media/vendor/mediaelement/js/mediaelement-flash-audio-ogg.swf', - '/media/vendor/mediaelement/js/mediaelement-flash-audio.swf', - '/media/vendor/mediaelement/js/mediaelement-flash-video-hls.swf', - '/media/vendor/mediaelement/js/mediaelement-flash-video-mdash.swf', - '/media/vendor/mediaelement/js/mediaelement-flash-video.swf', - '/plugins/editors-xtd/pagebreak/pagebreak.php', - // From 5.0.0-alpha2 to 5.0.0-alpha3 - '/libraries/classmap.php', - '/libraries/extensions.classmap.php', - '/media/vendor/codemirror/addon/comment/comment.js', - '/media/vendor/codemirror/addon/comment/comment.min.js', - '/media/vendor/codemirror/addon/comment/comment.min.js.gz', - '/media/vendor/codemirror/addon/comment/continuecomment.js', - '/media/vendor/codemirror/addon/comment/continuecomment.min.js', - '/media/vendor/codemirror/addon/comment/continuecomment.min.js.gz', - '/media/vendor/codemirror/addon/dialog/dialog.css', - '/media/vendor/codemirror/addon/dialog/dialog.js', - '/media/vendor/codemirror/addon/dialog/dialog.min.js', - '/media/vendor/codemirror/addon/dialog/dialog.min.js.gz', - '/media/vendor/codemirror/addon/display/autorefresh.js', - '/media/vendor/codemirror/addon/display/autorefresh.min.js', - '/media/vendor/codemirror/addon/display/autorefresh.min.js.gz', - '/media/vendor/codemirror/addon/display/fullscreen.css', - '/media/vendor/codemirror/addon/display/fullscreen.js', - '/media/vendor/codemirror/addon/display/fullscreen.min.js', - '/media/vendor/codemirror/addon/display/fullscreen.min.js.gz', - '/media/vendor/codemirror/addon/display/panel.js', - '/media/vendor/codemirror/addon/display/panel.min.js', - '/media/vendor/codemirror/addon/display/panel.min.js.gz', - '/media/vendor/codemirror/addon/display/placeholder.js', - '/media/vendor/codemirror/addon/display/placeholder.min.js', - '/media/vendor/codemirror/addon/display/placeholder.min.js.gz', - '/media/vendor/codemirror/addon/display/rulers.js', - '/media/vendor/codemirror/addon/display/rulers.min.js', - '/media/vendor/codemirror/addon/display/rulers.min.js.gz', - '/media/vendor/codemirror/addon/edit/closebrackets.js', - '/media/vendor/codemirror/addon/edit/closebrackets.min.js', - '/media/vendor/codemirror/addon/edit/closebrackets.min.js.gz', - '/media/vendor/codemirror/addon/edit/closetag.js', - '/media/vendor/codemirror/addon/edit/closetag.min.js', - '/media/vendor/codemirror/addon/edit/closetag.min.js.gz', - '/media/vendor/codemirror/addon/edit/continuelist.js', - '/media/vendor/codemirror/addon/edit/continuelist.min.js', - '/media/vendor/codemirror/addon/edit/continuelist.min.js.gz', - '/media/vendor/codemirror/addon/edit/matchbrackets.js', - '/media/vendor/codemirror/addon/edit/matchbrackets.min.js', - '/media/vendor/codemirror/addon/edit/matchbrackets.min.js.gz', - '/media/vendor/codemirror/addon/edit/matchtags.js', - '/media/vendor/codemirror/addon/edit/matchtags.min.js', - '/media/vendor/codemirror/addon/edit/matchtags.min.js.gz', - '/media/vendor/codemirror/addon/edit/trailingspace.js', - '/media/vendor/codemirror/addon/edit/trailingspace.min.js', - '/media/vendor/codemirror/addon/edit/trailingspace.min.js.gz', - '/media/vendor/codemirror/addon/fold/brace-fold.js', - '/media/vendor/codemirror/addon/fold/brace-fold.min.js', - '/media/vendor/codemirror/addon/fold/brace-fold.min.js.gz', - '/media/vendor/codemirror/addon/fold/comment-fold.js', - '/media/vendor/codemirror/addon/fold/comment-fold.min.js', - '/media/vendor/codemirror/addon/fold/comment-fold.min.js.gz', - '/media/vendor/codemirror/addon/fold/foldcode.js', - '/media/vendor/codemirror/addon/fold/foldcode.min.js', - '/media/vendor/codemirror/addon/fold/foldcode.min.js.gz', - '/media/vendor/codemirror/addon/fold/foldgutter.css', - '/media/vendor/codemirror/addon/fold/foldgutter.js', - '/media/vendor/codemirror/addon/fold/foldgutter.min.js', - '/media/vendor/codemirror/addon/fold/foldgutter.min.js.gz', - '/media/vendor/codemirror/addon/fold/indent-fold.js', - '/media/vendor/codemirror/addon/fold/indent-fold.min.js', - '/media/vendor/codemirror/addon/fold/indent-fold.min.js.gz', - '/media/vendor/codemirror/addon/fold/markdown-fold.js', - '/media/vendor/codemirror/addon/fold/markdown-fold.min.js', - '/media/vendor/codemirror/addon/fold/markdown-fold.min.js.gz', - '/media/vendor/codemirror/addon/fold/xml-fold.js', - '/media/vendor/codemirror/addon/fold/xml-fold.min.js', - '/media/vendor/codemirror/addon/fold/xml-fold.min.js.gz', - '/media/vendor/codemirror/addon/hint/anyword-hint.js', - '/media/vendor/codemirror/addon/hint/anyword-hint.min.js', - '/media/vendor/codemirror/addon/hint/anyword-hint.min.js.gz', - '/media/vendor/codemirror/addon/hint/css-hint.js', - '/media/vendor/codemirror/addon/hint/css-hint.min.js', - '/media/vendor/codemirror/addon/hint/css-hint.min.js.gz', - '/media/vendor/codemirror/addon/hint/html-hint.js', - '/media/vendor/codemirror/addon/hint/html-hint.min.js', - '/media/vendor/codemirror/addon/hint/html-hint.min.js.gz', - '/media/vendor/codemirror/addon/hint/javascript-hint.js', - '/media/vendor/codemirror/addon/hint/javascript-hint.min.js', - '/media/vendor/codemirror/addon/hint/javascript-hint.min.js.gz', - '/media/vendor/codemirror/addon/hint/show-hint.css', - '/media/vendor/codemirror/addon/hint/show-hint.js', - '/media/vendor/codemirror/addon/hint/show-hint.min.js', - '/media/vendor/codemirror/addon/hint/show-hint.min.js.gz', - '/media/vendor/codemirror/addon/hint/sql-hint.js', - '/media/vendor/codemirror/addon/hint/sql-hint.min.js', - '/media/vendor/codemirror/addon/hint/sql-hint.min.js.gz', - '/media/vendor/codemirror/addon/hint/xml-hint.js', - '/media/vendor/codemirror/addon/hint/xml-hint.min.js', - '/media/vendor/codemirror/addon/hint/xml-hint.min.js.gz', - '/media/vendor/codemirror/addon/lint/coffeescript-lint.js', - '/media/vendor/codemirror/addon/lint/coffeescript-lint.min.js', - '/media/vendor/codemirror/addon/lint/coffeescript-lint.min.js.gz', - '/media/vendor/codemirror/addon/lint/css-lint.js', - '/media/vendor/codemirror/addon/lint/css-lint.min.js', - '/media/vendor/codemirror/addon/lint/css-lint.min.js.gz', - '/media/vendor/codemirror/addon/lint/html-lint.js', - '/media/vendor/codemirror/addon/lint/html-lint.min.js', - '/media/vendor/codemirror/addon/lint/html-lint.min.js.gz', - '/media/vendor/codemirror/addon/lint/javascript-lint.js', - '/media/vendor/codemirror/addon/lint/javascript-lint.min.js', - '/media/vendor/codemirror/addon/lint/javascript-lint.min.js.gz', - '/media/vendor/codemirror/addon/lint/json-lint.js', - '/media/vendor/codemirror/addon/lint/json-lint.min.js', - '/media/vendor/codemirror/addon/lint/json-lint.min.js.gz', - '/media/vendor/codemirror/addon/lint/lint.css', - '/media/vendor/codemirror/addon/lint/lint.js', - '/media/vendor/codemirror/addon/lint/lint.min.js', - '/media/vendor/codemirror/addon/lint/lint.min.js.gz', - '/media/vendor/codemirror/addon/lint/yaml-lint.js', - '/media/vendor/codemirror/addon/lint/yaml-lint.min.js', - '/media/vendor/codemirror/addon/lint/yaml-lint.min.js.gz', - '/media/vendor/codemirror/addon/merge/merge.css', - '/media/vendor/codemirror/addon/merge/merge.js', - '/media/vendor/codemirror/addon/merge/merge.min.js', - '/media/vendor/codemirror/addon/merge/merge.min.js.gz', - '/media/vendor/codemirror/addon/mode/loadmode.js', - '/media/vendor/codemirror/addon/mode/loadmode.min.js', - '/media/vendor/codemirror/addon/mode/loadmode.min.js.gz', - '/media/vendor/codemirror/addon/mode/multiplex.js', - '/media/vendor/codemirror/addon/mode/multiplex.min.js', - '/media/vendor/codemirror/addon/mode/multiplex.min.js.gz', - '/media/vendor/codemirror/addon/mode/multiplex_test.js', - '/media/vendor/codemirror/addon/mode/multiplex_test.min.js', - '/media/vendor/codemirror/addon/mode/multiplex_test.min.js.gz', - '/media/vendor/codemirror/addon/mode/overlay.js', - '/media/vendor/codemirror/addon/mode/overlay.min.js', - '/media/vendor/codemirror/addon/mode/overlay.min.js.gz', - '/media/vendor/codemirror/addon/mode/simple.js', - '/media/vendor/codemirror/addon/mode/simple.min.js', - '/media/vendor/codemirror/addon/mode/simple.min.js.gz', - '/media/vendor/codemirror/addon/runmode/colorize.js', - '/media/vendor/codemirror/addon/runmode/colorize.min.js', - '/media/vendor/codemirror/addon/runmode/colorize.min.js.gz', - '/media/vendor/codemirror/addon/runmode/runmode-standalone.js', - '/media/vendor/codemirror/addon/runmode/runmode-standalone.min.js', - '/media/vendor/codemirror/addon/runmode/runmode-standalone.min.js.gz', - '/media/vendor/codemirror/addon/runmode/runmode.js', - '/media/vendor/codemirror/addon/runmode/runmode.min.js', - '/media/vendor/codemirror/addon/runmode/runmode.min.js.gz', - '/media/vendor/codemirror/addon/runmode/runmode.node.js', - '/media/vendor/codemirror/addon/runmode/runmode.node.min.js', - '/media/vendor/codemirror/addon/runmode/runmode.node.min.js.gz', - '/media/vendor/codemirror/addon/scroll/annotatescrollbar.js', - '/media/vendor/codemirror/addon/scroll/annotatescrollbar.min.js', - '/media/vendor/codemirror/addon/scroll/annotatescrollbar.min.js.gz', - '/media/vendor/codemirror/addon/scroll/scrollpastend.js', - '/media/vendor/codemirror/addon/scroll/scrollpastend.min.js', - '/media/vendor/codemirror/addon/scroll/scrollpastend.min.js.gz', - '/media/vendor/codemirror/addon/scroll/simplescrollbars.css', - '/media/vendor/codemirror/addon/scroll/simplescrollbars.js', - '/media/vendor/codemirror/addon/scroll/simplescrollbars.min.js', - '/media/vendor/codemirror/addon/scroll/simplescrollbars.min.js.gz', - '/media/vendor/codemirror/addon/search/jump-to-line.js', - '/media/vendor/codemirror/addon/search/jump-to-line.min.js', - '/media/vendor/codemirror/addon/search/jump-to-line.min.js.gz', - '/media/vendor/codemirror/addon/search/match-highlighter.js', - '/media/vendor/codemirror/addon/search/match-highlighter.min.js', - '/media/vendor/codemirror/addon/search/match-highlighter.min.js.gz', - '/media/vendor/codemirror/addon/search/matchesonscrollbar.css', - '/media/vendor/codemirror/addon/search/matchesonscrollbar.js', - '/media/vendor/codemirror/addon/search/matchesonscrollbar.min.js', - '/media/vendor/codemirror/addon/search/matchesonscrollbar.min.js.gz', - '/media/vendor/codemirror/addon/search/search.js', - '/media/vendor/codemirror/addon/search/search.min.js', - '/media/vendor/codemirror/addon/search/search.min.js.gz', - '/media/vendor/codemirror/addon/search/searchcursor.js', - '/media/vendor/codemirror/addon/search/searchcursor.min.js', - '/media/vendor/codemirror/addon/search/searchcursor.min.js.gz', - '/media/vendor/codemirror/addon/selection/active-line.js', - '/media/vendor/codemirror/addon/selection/active-line.min.js', - '/media/vendor/codemirror/addon/selection/active-line.min.js.gz', - '/media/vendor/codemirror/addon/selection/mark-selection.js', - '/media/vendor/codemirror/addon/selection/mark-selection.min.js', - '/media/vendor/codemirror/addon/selection/mark-selection.min.js.gz', - '/media/vendor/codemirror/addon/selection/selection-pointer.js', - '/media/vendor/codemirror/addon/selection/selection-pointer.min.js', - '/media/vendor/codemirror/addon/selection/selection-pointer.min.js.gz', - '/media/vendor/codemirror/addon/tern/tern.css', - '/media/vendor/codemirror/addon/tern/tern.js', - '/media/vendor/codemirror/addon/tern/tern.min.js', - '/media/vendor/codemirror/addon/tern/tern.min.js.gz', - '/media/vendor/codemirror/addon/tern/worker.js', - '/media/vendor/codemirror/addon/tern/worker.min.js', - '/media/vendor/codemirror/addon/tern/worker.min.js.gz', - '/media/vendor/codemirror/addon/wrap/hardwrap.js', - '/media/vendor/codemirror/addon/wrap/hardwrap.min.js', - '/media/vendor/codemirror/addon/wrap/hardwrap.min.js.gz', - '/media/vendor/codemirror/keymap/emacs.js', - '/media/vendor/codemirror/keymap/emacs.min.js', - '/media/vendor/codemirror/keymap/emacs.min.js.gz', - '/media/vendor/codemirror/keymap/sublime.js', - '/media/vendor/codemirror/keymap/sublime.min.js', - '/media/vendor/codemirror/keymap/sublime.min.js.gz', - '/media/vendor/codemirror/keymap/vim.js', - '/media/vendor/codemirror/keymap/vim.min.js', - '/media/vendor/codemirror/keymap/vim.min.js.gz', - '/media/vendor/codemirror/lib/addons.css', - '/media/vendor/codemirror/lib/addons.js', - '/media/vendor/codemirror/lib/addons.min.js', - '/media/vendor/codemirror/lib/addons.min.js.gz', - '/media/vendor/codemirror/lib/codemirror.css', - '/media/vendor/codemirror/lib/codemirror.js', - '/media/vendor/codemirror/lib/codemirror.min.js', - '/media/vendor/codemirror/lib/codemirror.min.js.gz', - '/media/vendor/codemirror/mode/apl/apl.js', - '/media/vendor/codemirror/mode/apl/apl.min.js', - '/media/vendor/codemirror/mode/apl/apl.min.js.gz', - '/media/vendor/codemirror/mode/asciiarmor/asciiarmor.js', - '/media/vendor/codemirror/mode/asciiarmor/asciiarmor.min.js', - '/media/vendor/codemirror/mode/asciiarmor/asciiarmor.min.js.gz', - '/media/vendor/codemirror/mode/asn.1/asn.1.js', - '/media/vendor/codemirror/mode/asn.1/asn.1.min.js', - '/media/vendor/codemirror/mode/asn.1/asn.1.min.js.gz', - '/media/vendor/codemirror/mode/asterisk/asterisk.js', - '/media/vendor/codemirror/mode/asterisk/asterisk.min.js', - '/media/vendor/codemirror/mode/asterisk/asterisk.min.js.gz', - '/media/vendor/codemirror/mode/brainfuck/brainfuck.js', - '/media/vendor/codemirror/mode/brainfuck/brainfuck.min.js', - '/media/vendor/codemirror/mode/brainfuck/brainfuck.min.js.gz', - '/media/vendor/codemirror/mode/clike/clike.js', - '/media/vendor/codemirror/mode/clike/clike.min.js', - '/media/vendor/codemirror/mode/clike/clike.min.js.gz', - '/media/vendor/codemirror/mode/clojure/clojure.js', - '/media/vendor/codemirror/mode/clojure/clojure.min.js', - '/media/vendor/codemirror/mode/clojure/clojure.min.js.gz', - '/media/vendor/codemirror/mode/cmake/cmake.js', - '/media/vendor/codemirror/mode/cmake/cmake.min.js', - '/media/vendor/codemirror/mode/cmake/cmake.min.js.gz', - '/media/vendor/codemirror/mode/cobol/cobol.js', - '/media/vendor/codemirror/mode/cobol/cobol.min.js', - '/media/vendor/codemirror/mode/cobol/cobol.min.js.gz', - '/media/vendor/codemirror/mode/coffeescript/coffeescript.js', - '/media/vendor/codemirror/mode/coffeescript/coffeescript.min.js', - '/media/vendor/codemirror/mode/coffeescript/coffeescript.min.js.gz', - '/media/vendor/codemirror/mode/commonlisp/commonlisp.js', - '/media/vendor/codemirror/mode/commonlisp/commonlisp.min.js', - '/media/vendor/codemirror/mode/commonlisp/commonlisp.min.js.gz', - '/media/vendor/codemirror/mode/crystal/crystal.js', - '/media/vendor/codemirror/mode/crystal/crystal.min.js', - '/media/vendor/codemirror/mode/crystal/crystal.min.js.gz', - '/media/vendor/codemirror/mode/css/css.js', - '/media/vendor/codemirror/mode/css/css.min.js', - '/media/vendor/codemirror/mode/css/css.min.js.gz', - '/media/vendor/codemirror/mode/cypher/cypher.js', - '/media/vendor/codemirror/mode/cypher/cypher.min.js', - '/media/vendor/codemirror/mode/cypher/cypher.min.js.gz', - '/media/vendor/codemirror/mode/d/d.js', - '/media/vendor/codemirror/mode/d/d.min.js', - '/media/vendor/codemirror/mode/d/d.min.js.gz', - '/media/vendor/codemirror/mode/dart/dart.js', - '/media/vendor/codemirror/mode/dart/dart.min.js', - '/media/vendor/codemirror/mode/dart/dart.min.js.gz', - '/media/vendor/codemirror/mode/diff/diff.js', - '/media/vendor/codemirror/mode/diff/diff.min.js', - '/media/vendor/codemirror/mode/diff/diff.min.js.gz', - '/media/vendor/codemirror/mode/django/django.js', - '/media/vendor/codemirror/mode/django/django.min.js', - '/media/vendor/codemirror/mode/django/django.min.js.gz', - '/media/vendor/codemirror/mode/dockerfile/dockerfile.js', - '/media/vendor/codemirror/mode/dockerfile/dockerfile.min.js', - '/media/vendor/codemirror/mode/dockerfile/dockerfile.min.js.gz', - '/media/vendor/codemirror/mode/dtd/dtd.js', - '/media/vendor/codemirror/mode/dtd/dtd.min.js', - '/media/vendor/codemirror/mode/dtd/dtd.min.js.gz', - '/media/vendor/codemirror/mode/dylan/dylan.js', - '/media/vendor/codemirror/mode/dylan/dylan.min.js', - '/media/vendor/codemirror/mode/dylan/dylan.min.js.gz', - '/media/vendor/codemirror/mode/ebnf/ebnf.js', - '/media/vendor/codemirror/mode/ebnf/ebnf.min.js', - '/media/vendor/codemirror/mode/ebnf/ebnf.min.js.gz', - '/media/vendor/codemirror/mode/ecl/ecl.js', - '/media/vendor/codemirror/mode/ecl/ecl.min.js', - '/media/vendor/codemirror/mode/ecl/ecl.min.js.gz', - '/media/vendor/codemirror/mode/eiffel/eiffel.js', - '/media/vendor/codemirror/mode/eiffel/eiffel.min.js', - '/media/vendor/codemirror/mode/eiffel/eiffel.min.js.gz', - '/media/vendor/codemirror/mode/elm/elm.js', - '/media/vendor/codemirror/mode/elm/elm.min.js', - '/media/vendor/codemirror/mode/elm/elm.min.js.gz', - '/media/vendor/codemirror/mode/erlang/erlang.js', - '/media/vendor/codemirror/mode/erlang/erlang.min.js', - '/media/vendor/codemirror/mode/erlang/erlang.min.js.gz', - '/media/vendor/codemirror/mode/factor/factor.js', - '/media/vendor/codemirror/mode/factor/factor.min.js', - '/media/vendor/codemirror/mode/factor/factor.min.js.gz', - '/media/vendor/codemirror/mode/fcl/fcl.js', - '/media/vendor/codemirror/mode/fcl/fcl.min.js', - '/media/vendor/codemirror/mode/fcl/fcl.min.js.gz', - '/media/vendor/codemirror/mode/forth/forth.js', - '/media/vendor/codemirror/mode/forth/forth.min.js', - '/media/vendor/codemirror/mode/forth/forth.min.js.gz', - '/media/vendor/codemirror/mode/fortran/fortran.js', - '/media/vendor/codemirror/mode/fortran/fortran.min.js', - '/media/vendor/codemirror/mode/fortran/fortran.min.js.gz', - '/media/vendor/codemirror/mode/gas/gas.js', - '/media/vendor/codemirror/mode/gas/gas.min.js', - '/media/vendor/codemirror/mode/gas/gas.min.js.gz', - '/media/vendor/codemirror/mode/gfm/gfm.js', - '/media/vendor/codemirror/mode/gfm/gfm.min.js', - '/media/vendor/codemirror/mode/gfm/gfm.min.js.gz', - '/media/vendor/codemirror/mode/gherkin/gherkin.js', - '/media/vendor/codemirror/mode/gherkin/gherkin.min.js', - '/media/vendor/codemirror/mode/gherkin/gherkin.min.js.gz', - '/media/vendor/codemirror/mode/go/go.js', - '/media/vendor/codemirror/mode/go/go.min.js', - '/media/vendor/codemirror/mode/go/go.min.js.gz', - '/media/vendor/codemirror/mode/groovy/groovy.js', - '/media/vendor/codemirror/mode/groovy/groovy.min.js', - '/media/vendor/codemirror/mode/groovy/groovy.min.js.gz', - '/media/vendor/codemirror/mode/haml/haml.js', - '/media/vendor/codemirror/mode/haml/haml.min.js', - '/media/vendor/codemirror/mode/haml/haml.min.js.gz', - '/media/vendor/codemirror/mode/handlebars/handlebars.js', - '/media/vendor/codemirror/mode/handlebars/handlebars.min.js', - '/media/vendor/codemirror/mode/handlebars/handlebars.min.js.gz', - '/media/vendor/codemirror/mode/haskell-literate/haskell-literate.js', - '/media/vendor/codemirror/mode/haskell-literate/haskell-literate.min.js', - '/media/vendor/codemirror/mode/haskell-literate/haskell-literate.min.js.gz', - '/media/vendor/codemirror/mode/haskell/haskell.js', - '/media/vendor/codemirror/mode/haskell/haskell.min.js', - '/media/vendor/codemirror/mode/haskell/haskell.min.js.gz', - '/media/vendor/codemirror/mode/haxe/haxe.js', - '/media/vendor/codemirror/mode/haxe/haxe.min.js', - '/media/vendor/codemirror/mode/haxe/haxe.min.js.gz', - '/media/vendor/codemirror/mode/htmlembedded/htmlembedded.js', - '/media/vendor/codemirror/mode/htmlembedded/htmlembedded.min.js', - '/media/vendor/codemirror/mode/htmlembedded/htmlembedded.min.js.gz', - '/media/vendor/codemirror/mode/htmlmixed/htmlmixed.js', - '/media/vendor/codemirror/mode/htmlmixed/htmlmixed.min.js', - '/media/vendor/codemirror/mode/htmlmixed/htmlmixed.min.js.gz', - '/media/vendor/codemirror/mode/http/http.js', - '/media/vendor/codemirror/mode/http/http.min.js', - '/media/vendor/codemirror/mode/http/http.min.js.gz', - '/media/vendor/codemirror/mode/idl/idl.js', - '/media/vendor/codemirror/mode/idl/idl.min.js', - '/media/vendor/codemirror/mode/idl/idl.min.js.gz', - '/media/vendor/codemirror/mode/javascript/javascript.js', - '/media/vendor/codemirror/mode/javascript/javascript.min.js', - '/media/vendor/codemirror/mode/javascript/javascript.min.js.gz', - '/media/vendor/codemirror/mode/jinja2/jinja2.js', - '/media/vendor/codemirror/mode/jinja2/jinja2.min.js', - '/media/vendor/codemirror/mode/jinja2/jinja2.min.js.gz', - '/media/vendor/codemirror/mode/jsx/jsx.js', - '/media/vendor/codemirror/mode/jsx/jsx.min.js', - '/media/vendor/codemirror/mode/jsx/jsx.min.js.gz', - '/media/vendor/codemirror/mode/julia/julia.js', - '/media/vendor/codemirror/mode/julia/julia.min.js', - '/media/vendor/codemirror/mode/julia/julia.min.js.gz', - '/media/vendor/codemirror/mode/livescript/livescript.js', - '/media/vendor/codemirror/mode/livescript/livescript.min.js', - '/media/vendor/codemirror/mode/livescript/livescript.min.js.gz', - '/media/vendor/codemirror/mode/lua/lua.js', - '/media/vendor/codemirror/mode/lua/lua.min.js', - '/media/vendor/codemirror/mode/lua/lua.min.js.gz', - '/media/vendor/codemirror/mode/markdown/markdown.js', - '/media/vendor/codemirror/mode/markdown/markdown.min.js', - '/media/vendor/codemirror/mode/markdown/markdown.min.js.gz', - '/media/vendor/codemirror/mode/mathematica/mathematica.js', - '/media/vendor/codemirror/mode/mathematica/mathematica.min.js', - '/media/vendor/codemirror/mode/mathematica/mathematica.min.js.gz', - '/media/vendor/codemirror/mode/mbox/mbox.js', - '/media/vendor/codemirror/mode/mbox/mbox.min.js', - '/media/vendor/codemirror/mode/mbox/mbox.min.js.gz', - '/media/vendor/codemirror/mode/meta.js', - '/media/vendor/codemirror/mode/meta.min.js', - '/media/vendor/codemirror/mode/meta.min.js.gz', - '/media/vendor/codemirror/mode/mirc/mirc.js', - '/media/vendor/codemirror/mode/mirc/mirc.min.js', - '/media/vendor/codemirror/mode/mirc/mirc.min.js.gz', - '/media/vendor/codemirror/mode/mllike/mllike.js', - '/media/vendor/codemirror/mode/mllike/mllike.min.js', - '/media/vendor/codemirror/mode/mllike/mllike.min.js.gz', - '/media/vendor/codemirror/mode/modelica/modelica.js', - '/media/vendor/codemirror/mode/modelica/modelica.min.js', - '/media/vendor/codemirror/mode/modelica/modelica.min.js.gz', - '/media/vendor/codemirror/mode/mscgen/mscgen.js', - '/media/vendor/codemirror/mode/mscgen/mscgen.min.js', - '/media/vendor/codemirror/mode/mscgen/mscgen.min.js.gz', - '/media/vendor/codemirror/mode/mumps/mumps.js', - '/media/vendor/codemirror/mode/mumps/mumps.min.js', - '/media/vendor/codemirror/mode/mumps/mumps.min.js.gz', - '/media/vendor/codemirror/mode/nginx/nginx.js', - '/media/vendor/codemirror/mode/nginx/nginx.min.js', - '/media/vendor/codemirror/mode/nginx/nginx.min.js.gz', - '/media/vendor/codemirror/mode/nsis/nsis.js', - '/media/vendor/codemirror/mode/nsis/nsis.min.js', - '/media/vendor/codemirror/mode/nsis/nsis.min.js.gz', - '/media/vendor/codemirror/mode/ntriples/ntriples.js', - '/media/vendor/codemirror/mode/ntriples/ntriples.min.js', - '/media/vendor/codemirror/mode/ntriples/ntriples.min.js.gz', - '/media/vendor/codemirror/mode/octave/octave.js', - '/media/vendor/codemirror/mode/octave/octave.min.js', - '/media/vendor/codemirror/mode/octave/octave.min.js.gz', - '/media/vendor/codemirror/mode/oz/oz.js', - '/media/vendor/codemirror/mode/oz/oz.min.js', - '/media/vendor/codemirror/mode/oz/oz.min.js.gz', - '/media/vendor/codemirror/mode/pascal/pascal.js', - '/media/vendor/codemirror/mode/pascal/pascal.min.js', - '/media/vendor/codemirror/mode/pascal/pascal.min.js.gz', - '/media/vendor/codemirror/mode/pegjs/pegjs.js', - '/media/vendor/codemirror/mode/pegjs/pegjs.min.js', - '/media/vendor/codemirror/mode/pegjs/pegjs.min.js.gz', - '/media/vendor/codemirror/mode/perl/perl.js', - '/media/vendor/codemirror/mode/perl/perl.min.js', - '/media/vendor/codemirror/mode/perl/perl.min.js.gz', - '/media/vendor/codemirror/mode/php/php.js', - '/media/vendor/codemirror/mode/php/php.min.js', - '/media/vendor/codemirror/mode/php/php.min.js.gz', - '/media/vendor/codemirror/mode/pig/pig.js', - '/media/vendor/codemirror/mode/pig/pig.min.js', - '/media/vendor/codemirror/mode/pig/pig.min.js.gz', - '/media/vendor/codemirror/mode/powershell/powershell.js', - '/media/vendor/codemirror/mode/powershell/powershell.min.js', - '/media/vendor/codemirror/mode/powershell/powershell.min.js.gz', - '/media/vendor/codemirror/mode/properties/properties.js', - '/media/vendor/codemirror/mode/properties/properties.min.js', - '/media/vendor/codemirror/mode/properties/properties.min.js.gz', - '/media/vendor/codemirror/mode/protobuf/protobuf.js', - '/media/vendor/codemirror/mode/protobuf/protobuf.min.js', - '/media/vendor/codemirror/mode/protobuf/protobuf.min.js.gz', - '/media/vendor/codemirror/mode/pug/pug.js', - '/media/vendor/codemirror/mode/pug/pug.min.js', - '/media/vendor/codemirror/mode/pug/pug.min.js.gz', - '/media/vendor/codemirror/mode/puppet/puppet.js', - '/media/vendor/codemirror/mode/puppet/puppet.min.js', - '/media/vendor/codemirror/mode/puppet/puppet.min.js.gz', - '/media/vendor/codemirror/mode/python/python.js', - '/media/vendor/codemirror/mode/python/python.min.js', - '/media/vendor/codemirror/mode/python/python.min.js.gz', - '/media/vendor/codemirror/mode/q/q.js', - '/media/vendor/codemirror/mode/q/q.min.js', - '/media/vendor/codemirror/mode/q/q.min.js.gz', - '/media/vendor/codemirror/mode/r/r.js', - '/media/vendor/codemirror/mode/r/r.min.js', - '/media/vendor/codemirror/mode/r/r.min.js.gz', - '/media/vendor/codemirror/mode/rpm/changes/index.html', - '/media/vendor/codemirror/mode/rpm/rpm.js', - '/media/vendor/codemirror/mode/rpm/rpm.min.js', - '/media/vendor/codemirror/mode/rpm/rpm.min.js.gz', - '/media/vendor/codemirror/mode/rst/rst.js', - '/media/vendor/codemirror/mode/rst/rst.min.js', - '/media/vendor/codemirror/mode/rst/rst.min.js.gz', - '/media/vendor/codemirror/mode/ruby/ruby.js', - '/media/vendor/codemirror/mode/ruby/ruby.min.js', - '/media/vendor/codemirror/mode/ruby/ruby.min.js.gz', - '/media/vendor/codemirror/mode/rust/rust.js', - '/media/vendor/codemirror/mode/rust/rust.min.js', - '/media/vendor/codemirror/mode/rust/rust.min.js.gz', - '/media/vendor/codemirror/mode/sas/sas.js', - '/media/vendor/codemirror/mode/sas/sas.min.js', - '/media/vendor/codemirror/mode/sas/sas.min.js.gz', - '/media/vendor/codemirror/mode/sass/sass.js', - '/media/vendor/codemirror/mode/sass/sass.min.js', - '/media/vendor/codemirror/mode/sass/sass.min.js.gz', - '/media/vendor/codemirror/mode/scheme/scheme.js', - '/media/vendor/codemirror/mode/scheme/scheme.min.js', - '/media/vendor/codemirror/mode/scheme/scheme.min.js.gz', - '/media/vendor/codemirror/mode/shell/shell.js', - '/media/vendor/codemirror/mode/shell/shell.min.js', - '/media/vendor/codemirror/mode/shell/shell.min.js.gz', - '/media/vendor/codemirror/mode/sieve/sieve.js', - '/media/vendor/codemirror/mode/sieve/sieve.min.js', - '/media/vendor/codemirror/mode/sieve/sieve.min.js.gz', - '/media/vendor/codemirror/mode/slim/slim.js', - '/media/vendor/codemirror/mode/slim/slim.min.js', - '/media/vendor/codemirror/mode/slim/slim.min.js.gz', - '/media/vendor/codemirror/mode/smalltalk/smalltalk.js', - '/media/vendor/codemirror/mode/smalltalk/smalltalk.min.js', - '/media/vendor/codemirror/mode/smalltalk/smalltalk.min.js.gz', - '/media/vendor/codemirror/mode/smarty/smarty.js', - '/media/vendor/codemirror/mode/smarty/smarty.min.js', - '/media/vendor/codemirror/mode/smarty/smarty.min.js.gz', - '/media/vendor/codemirror/mode/solr/solr.js', - '/media/vendor/codemirror/mode/solr/solr.min.js', - '/media/vendor/codemirror/mode/solr/solr.min.js.gz', - '/media/vendor/codemirror/mode/soy/soy.js', - '/media/vendor/codemirror/mode/soy/soy.min.js', - '/media/vendor/codemirror/mode/soy/soy.min.js.gz', - '/media/vendor/codemirror/mode/sparql/sparql.js', - '/media/vendor/codemirror/mode/sparql/sparql.min.js', - '/media/vendor/codemirror/mode/sparql/sparql.min.js.gz', - '/media/vendor/codemirror/mode/spreadsheet/spreadsheet.js', - '/media/vendor/codemirror/mode/spreadsheet/spreadsheet.min.js', - '/media/vendor/codemirror/mode/spreadsheet/spreadsheet.min.js.gz', - '/media/vendor/codemirror/mode/sql/sql.js', - '/media/vendor/codemirror/mode/sql/sql.min.js', - '/media/vendor/codemirror/mode/sql/sql.min.js.gz', - '/media/vendor/codemirror/mode/stex/stex.js', - '/media/vendor/codemirror/mode/stex/stex.min.js', - '/media/vendor/codemirror/mode/stex/stex.min.js.gz', - '/media/vendor/codemirror/mode/stylus/stylus.js', - '/media/vendor/codemirror/mode/stylus/stylus.min.js', - '/media/vendor/codemirror/mode/stylus/stylus.min.js.gz', - '/media/vendor/codemirror/mode/swift/swift.js', - '/media/vendor/codemirror/mode/swift/swift.min.js', - '/media/vendor/codemirror/mode/swift/swift.min.js.gz', - '/media/vendor/codemirror/mode/tcl/tcl.js', - '/media/vendor/codemirror/mode/tcl/tcl.min.js', - '/media/vendor/codemirror/mode/tcl/tcl.min.js.gz', - '/media/vendor/codemirror/mode/textile/textile.js', - '/media/vendor/codemirror/mode/textile/textile.min.js', - '/media/vendor/codemirror/mode/textile/textile.min.js.gz', - '/media/vendor/codemirror/mode/tiddlywiki/tiddlywiki.css', - '/media/vendor/codemirror/mode/tiddlywiki/tiddlywiki.js', - '/media/vendor/codemirror/mode/tiddlywiki/tiddlywiki.min.js', - '/media/vendor/codemirror/mode/tiddlywiki/tiddlywiki.min.js.gz', - '/media/vendor/codemirror/mode/tiki/tiki.css', - '/media/vendor/codemirror/mode/tiki/tiki.js', - '/media/vendor/codemirror/mode/tiki/tiki.min.js', - '/media/vendor/codemirror/mode/tiki/tiki.min.js.gz', - '/media/vendor/codemirror/mode/toml/toml.js', - '/media/vendor/codemirror/mode/toml/toml.min.js', - '/media/vendor/codemirror/mode/toml/toml.min.js.gz', - '/media/vendor/codemirror/mode/tornado/tornado.js', - '/media/vendor/codemirror/mode/tornado/tornado.min.js', - '/media/vendor/codemirror/mode/tornado/tornado.min.js.gz', - '/media/vendor/codemirror/mode/troff/troff.js', - '/media/vendor/codemirror/mode/troff/troff.min.js', - '/media/vendor/codemirror/mode/troff/troff.min.js.gz', - '/media/vendor/codemirror/mode/ttcn-cfg/ttcn-cfg.js', - '/media/vendor/codemirror/mode/ttcn-cfg/ttcn-cfg.min.js', - '/media/vendor/codemirror/mode/ttcn-cfg/ttcn-cfg.min.js.gz', - '/media/vendor/codemirror/mode/ttcn/ttcn.js', - '/media/vendor/codemirror/mode/ttcn/ttcn.min.js', - '/media/vendor/codemirror/mode/ttcn/ttcn.min.js.gz', - '/media/vendor/codemirror/mode/turtle/turtle.js', - '/media/vendor/codemirror/mode/turtle/turtle.min.js', - '/media/vendor/codemirror/mode/turtle/turtle.min.js.gz', - '/media/vendor/codemirror/mode/twig/twig.js', - '/media/vendor/codemirror/mode/twig/twig.min.js', - '/media/vendor/codemirror/mode/twig/twig.min.js.gz', - '/media/vendor/codemirror/mode/vb/vb.js', - '/media/vendor/codemirror/mode/vb/vb.min.js', - '/media/vendor/codemirror/mode/vb/vb.min.js.gz', - '/media/vendor/codemirror/mode/vbscript/vbscript.js', - '/media/vendor/codemirror/mode/vbscript/vbscript.min.js', - '/media/vendor/codemirror/mode/vbscript/vbscript.min.js.gz', - '/media/vendor/codemirror/mode/velocity/velocity.js', - '/media/vendor/codemirror/mode/velocity/velocity.min.js', - '/media/vendor/codemirror/mode/velocity/velocity.min.js.gz', - '/media/vendor/codemirror/mode/verilog/verilog.js', - '/media/vendor/codemirror/mode/verilog/verilog.min.js', - '/media/vendor/codemirror/mode/verilog/verilog.min.js.gz', - '/media/vendor/codemirror/mode/vhdl/vhdl.js', - '/media/vendor/codemirror/mode/vhdl/vhdl.min.js', - '/media/vendor/codemirror/mode/vhdl/vhdl.min.js.gz', - '/media/vendor/codemirror/mode/vue/vue.js', - '/media/vendor/codemirror/mode/vue/vue.min.js', - '/media/vendor/codemirror/mode/vue/vue.min.js.gz', - '/media/vendor/codemirror/mode/wast/wast.js', - '/media/vendor/codemirror/mode/wast/wast.min.js', - '/media/vendor/codemirror/mode/wast/wast.min.js.gz', - '/media/vendor/codemirror/mode/webidl/webidl.js', - '/media/vendor/codemirror/mode/webidl/webidl.min.js', - '/media/vendor/codemirror/mode/webidl/webidl.min.js.gz', - '/media/vendor/codemirror/mode/xml/xml.js', - '/media/vendor/codemirror/mode/xml/xml.min.js', - '/media/vendor/codemirror/mode/xml/xml.min.js.gz', - '/media/vendor/codemirror/mode/xquery/xquery.js', - '/media/vendor/codemirror/mode/xquery/xquery.min.js', - '/media/vendor/codemirror/mode/xquery/xquery.min.js.gz', - '/media/vendor/codemirror/mode/yacas/yacas.js', - '/media/vendor/codemirror/mode/yacas/yacas.min.js', - '/media/vendor/codemirror/mode/yacas/yacas.min.js.gz', - '/media/vendor/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js', - '/media/vendor/codemirror/mode/yaml-frontmatter/yaml-frontmatter.min.js', - '/media/vendor/codemirror/mode/yaml-frontmatter/yaml-frontmatter.min.js.gz', - '/media/vendor/codemirror/mode/yaml/yaml.js', - '/media/vendor/codemirror/mode/yaml/yaml.min.js', - '/media/vendor/codemirror/mode/yaml/yaml.min.js.gz', - '/media/vendor/codemirror/mode/z80/z80.js', - '/media/vendor/codemirror/mode/z80/z80.min.js', - '/media/vendor/codemirror/mode/z80/z80.min.js.gz', - '/media/vendor/codemirror/theme/3024-day.css', - '/media/vendor/codemirror/theme/3024-night.css', - '/media/vendor/codemirror/theme/abbott.css', - '/media/vendor/codemirror/theme/abcdef.css', - '/media/vendor/codemirror/theme/ambiance-mobile.css', - '/media/vendor/codemirror/theme/ambiance.css', - '/media/vendor/codemirror/theme/ayu-dark.css', - '/media/vendor/codemirror/theme/ayu-mirage.css', - '/media/vendor/codemirror/theme/base16-dark.css', - '/media/vendor/codemirror/theme/base16-light.css', - '/media/vendor/codemirror/theme/bespin.css', - '/media/vendor/codemirror/theme/blackboard.css', - '/media/vendor/codemirror/theme/cobalt.css', - '/media/vendor/codemirror/theme/colorforth.css', - '/media/vendor/codemirror/theme/darcula.css', - '/media/vendor/codemirror/theme/dracula.css', - '/media/vendor/codemirror/theme/duotone-dark.css', - '/media/vendor/codemirror/theme/duotone-light.css', - '/media/vendor/codemirror/theme/eclipse.css', - '/media/vendor/codemirror/theme/elegant.css', - '/media/vendor/codemirror/theme/erlang-dark.css', - '/media/vendor/codemirror/theme/gruvbox-dark.css', - '/media/vendor/codemirror/theme/hopscotch.css', - '/media/vendor/codemirror/theme/icecoder.css', - '/media/vendor/codemirror/theme/idea.css', - '/media/vendor/codemirror/theme/isotope.css', - '/media/vendor/codemirror/theme/juejin.css', - '/media/vendor/codemirror/theme/lesser-dark.css', - '/media/vendor/codemirror/theme/liquibyte.css', - '/media/vendor/codemirror/theme/lucario.css', - '/media/vendor/codemirror/theme/material-darker.css', - '/media/vendor/codemirror/theme/material-ocean.css', - '/media/vendor/codemirror/theme/material-palenight.css', - '/media/vendor/codemirror/theme/material.css', - '/media/vendor/codemirror/theme/mbo.css', - '/media/vendor/codemirror/theme/mdn-like.css', - '/media/vendor/codemirror/theme/midnight.css', - '/media/vendor/codemirror/theme/monokai.css', - '/media/vendor/codemirror/theme/moxer.css', - '/media/vendor/codemirror/theme/neat.css', - '/media/vendor/codemirror/theme/neo.css', - '/media/vendor/codemirror/theme/night.css', - '/media/vendor/codemirror/theme/nord.css', - '/media/vendor/codemirror/theme/oceanic-next.css', - '/media/vendor/codemirror/theme/panda-syntax.css', - '/media/vendor/codemirror/theme/paraiso-dark.css', - '/media/vendor/codemirror/theme/paraiso-light.css', - '/media/vendor/codemirror/theme/pastel-on-dark.css', - '/media/vendor/codemirror/theme/railscasts.css', - '/media/vendor/codemirror/theme/rubyblue.css', - '/media/vendor/codemirror/theme/seti.css', - '/media/vendor/codemirror/theme/shadowfox.css', - '/media/vendor/codemirror/theme/solarized.css', - '/media/vendor/codemirror/theme/ssms.css', - '/media/vendor/codemirror/theme/the-matrix.css', - '/media/vendor/codemirror/theme/tomorrow-night-bright.css', - '/media/vendor/codemirror/theme/tomorrow-night-eighties.css', - '/media/vendor/codemirror/theme/ttcn.css', - '/media/vendor/codemirror/theme/twilight.css', - '/media/vendor/codemirror/theme/vibrant-ink.css', - '/media/vendor/codemirror/theme/xq-dark.css', - '/media/vendor/codemirror/theme/xq-light.css', - '/media/vendor/codemirror/theme/yeti.css', - '/media/vendor/codemirror/theme/yonce.css', - '/media/vendor/codemirror/theme/zenburn.css', - '/plugins/editors/codemirror/fonts.json', - '/plugins/editors/codemirror/layouts/editors/codemirror/element.php', - '/plugins/editors/codemirror/layouts/editors/codemirror/styles.php', - '/plugins/editors/codemirror/src/Field/FontsField.php', - // From 5.0.0-alpha3 to 5.0.0-alpha4 - '/libraries/src/Event/Application/DeamonForkEvent.php', - '/libraries/src/Event/Application/DeamonReceiveSignalEvent.php', - '/media/plg_editors_tinymce/js/plugins/highlighter/plugin.js', - '/media/plg_editors_tinymce/js/plugins/highlighter/plugin.min.js', - '/media/plg_editors_tinymce/js/plugins/highlighter/plugin.min.js.gz', - '/media/plg_editors_tinymce/js/plugins/highlighter/source.css', - '/media/plg_editors_tinymce/js/plugins/highlighter/source.html', - '/media/plg_editors_tinymce/js/plugins/highlighter/source.js', - '/media/plg_editors_tinymce/js/plugins/highlighter/source.min.css', - '/media/plg_editors_tinymce/js/plugins/highlighter/source.min.css.gz', - '/media/plg_editors_tinymce/js/plugins/highlighter/source.min.js', - '/media/plg_editors_tinymce/js/plugins/highlighter/source.min.js.gz', - '/media/plg_system_compat/es5.asset.json', - // From 5.0.0-alpha4 to 5.0.0-beta1 - '/administrator/components/com_categories/tmpl/categories/default_batch_footer.php', - '/administrator/components/com_content/tmpl/articles/default_batch_footer.php', - '/administrator/language/en-GB/plg_twofactorauth_totp.ini', - '/administrator/language/en-GB/plg_twofactorauth_totp.sys.ini', - '/administrator/language/en-GB/plg_twofactorauth_yubikey.ini', - '/administrator/language/en-GB/plg_twofactorauth_yubikey.sys.ini', - '/media/com_contenthistory/js/admin-history-versions.js', - '/media/com_contenthistory/js/admin-history-versions.min.js', - '/media/com_contenthistory/js/admin-history-versions.min.js.gz', - // From 5.0.0-beta1 to 5.0.0-beta2 - '/language/en-GB/lib_simplepie.sys.ini', - '/libraries/src/Cache/Storage/WincacheStorage.php', - // From 5.0.0-beta2 to 5.0.0-beta3 - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/AbstractString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/AbstractTime.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/ASNObject.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Base128.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Composite/AttributeTypeAndValue.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RDNString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Composite/RelativeDistinguishedName.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Construct.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Exception/NotImplementedException.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Exception/ParserException.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Identifier.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/OID.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Parsable.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/TemplateParser.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BitString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/BMPString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Boolean.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/CharacterString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Enumerated.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralizedTime.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GeneralString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/GraphicString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/IA5String.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Integer.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NullObject.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/NumericString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectDescriptor.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/ObjectIdentifier.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/OctetString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/PrintableString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/RelativeObjectIdentifier.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Sequence.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/Set.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/T61String.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UniversalString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTCTime.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/UTF8String.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal/VisibleString.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/UnknownConstructedObject.php', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/UnknownObject.php', - '/libraries/vendor/fgrosse/phpasn1/lib/Utility/BigInteger.php', - '/libraries/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerBcmath.php', - '/libraries/vendor/fgrosse/phpasn1/lib/Utility/BigIntegerGmp.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/AlgorithmIdentifier.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/CertificateExtensions.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/CertificateSubject.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/CSR/Attributes.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/CSR/CSR.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/PrivateKey.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/PublicKey.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/SAN/DNSName.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/SAN/IPAddress.php', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/SAN/SubjectAlternativeNames.php', - '/libraries/vendor/fgrosse/phpasn1/LICENSE', - '/libraries/vendor/stella-maris/clock/LICENSE.md', - '/libraries/vendor/stella-maris/clock/src/ClockInterface.php', - '/media/com_scheduler/css/admin-view-select-task.css', - '/media/com_scheduler/css/admin-view-select-task.min.css', - '/media/com_scheduler/css/admin-view-select-task.min.css.gz', - '/media/system/css/calendar-jos.css', - '/media/system/css/calendar-jos.min.css', - '/media/system/css/calendar-jos.min.css.gz', - '/media/system/css/debug.css', - '/media/system/css/debug.min.css', - '/media/system/css/debug.min.css.gz', - '/media/system/css/frontediting.css', - '/media/system/css/frontediting.min.css', - '/media/system/css/frontediting.min.css.gz', - '/media/system/css/mootree.css', - '/media/system/css/mootree.min.css', - '/media/system/css/mootree.min.css.gz', - '/media/system/css/mootree_rtl.css', - '/media/system/css/mootree_rtl.min.css', - '/media/system/css/mootree_rtl.min.css.gz', - '/media/system/css/sortablelist.css', - '/media/system/css/sortablelist.min.css', - '/media/system/css/sortablelist.min.css.gz', - // From 5.0.0 to 5.1.0-alpha1 - '/administrator/components/com_banners/tmpl/banners/default_batch_footer.php', - '/administrator/components/com_contact/tmpl/contacts/default_batch_footer.php', - '/administrator/components/com_fields/tmpl/fields/default_batch_footer.php', - '/administrator/components/com_fields/tmpl/groups/default_batch_footer.php', - '/administrator/components/com_menus/tmpl/items/default_batch_footer.php', - '/administrator/components/com_modules/tmpl/modules/default_batch_footer.php', - '/administrator/components/com_newsfeeds/tmpl/newsfeeds/default_batch_footer.php', - '/administrator/components/com_tags/tmpl/tags/default_batch_footer.php', - '/administrator/components/com_users/tmpl/users/default_batch_footer.php', - // From 5.1.0-alpha3 to 5.1.0-alpha4 - '/administrator/components/com_redirect/tmpl/links/default_batch_footer.php', - '/modules/mod_banners/mod_banners.php', - // From 5.1.0-alpha4 to 5.1.0-beta1 - '/administrator/modules/mod_custom/mod_custom.php', - '/administrator/modules/mod_frontend/mod_frontend.php', - '/administrator/modules/mod_latestactions/mod_latestactions.php', - '/administrator/modules/mod_loginsupport/mod_loginsupport.php', - '/administrator/modules/mod_messages/mod_messages.php', - '/administrator/modules/mod_multilangstatus/mod_multilangstatus.php', - '/administrator/modules/mod_sampledata/mod_sampledata.php', - '/administrator/modules/mod_stats_admin/mod_stats_admin.php', - '/administrator/modules/mod_title/mod_title.php', - '/administrator/modules/mod_toolbar/mod_toolbar.php', - '/administrator/modules/mod_user/mod_user.php', - '/administrator/modules/mod_version/mod_version.php', - '/libraries/vendor/web-token/jwt-core/Algorithm.php', - '/libraries/vendor/web-token/jwt-core/AlgorithmManager.php', - '/libraries/vendor/web-token/jwt-core/AlgorithmManagerFactory.php', - '/libraries/vendor/web-token/jwt-core/JWK.php', - '/libraries/vendor/web-token/jwt-core/JWKSet.php', - '/libraries/vendor/web-token/jwt-core/JWT.php', - '/libraries/vendor/web-token/jwt-core/LICENSE', - '/libraries/vendor/web-token/jwt-core/Util/BigInteger.php', - '/libraries/vendor/web-token/jwt-core/Util/ECKey.php', - '/libraries/vendor/web-token/jwt-core/Util/ECSignature.php', - '/libraries/vendor/web-token/jwt-core/Util/Hash.php', - '/libraries/vendor/web-token/jwt-core/Util/JsonConverter.php', - '/libraries/vendor/web-token/jwt-core/Util/KeyChecker.php', - '/libraries/vendor/web-token/jwt-core/Util/RSAKey.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-ecdsa/ECDSA.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-ecdsa/ES256.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-ecdsa/ES384.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-ecdsa/ES512.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-eddsa/EdDSA.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-experimental/Blake2b.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-experimental/ES256K.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-experimental/HS1.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-experimental/HS256_64.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-experimental/RS1.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-hmac/HMAC.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-hmac/HS256.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-hmac/HS384.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-hmac/HS512.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-none/None.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/PS256.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/PS384.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/PS512.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/RS256.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/RS384.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/RS512.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/RSAPKCS1.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/RSAPSS.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/Util/RSA.php', - '/libraries/vendor/web-token/jwt-signature/Algorithm/MacAlgorithm.php', - '/libraries/vendor/web-token/jwt-signature/Algorithm/SignatureAlgorithm.php', - '/libraries/vendor/web-token/jwt-signature/JWS.php', - '/libraries/vendor/web-token/jwt-signature/JWSBuilder.php', - '/libraries/vendor/web-token/jwt-signature/JWSBuilderFactory.php', - '/libraries/vendor/web-token/jwt-signature/JWSLoader.php', - '/libraries/vendor/web-token/jwt-signature/JWSLoaderFactory.php', - '/libraries/vendor/web-token/jwt-signature/JWSTokenSupport.php', - '/libraries/vendor/web-token/jwt-signature/JWSVerifier.php', - '/libraries/vendor/web-token/jwt-signature/JWSVerifierFactory.php', - '/libraries/vendor/web-token/jwt-signature/LICENSE', - '/libraries/vendor/web-token/jwt-signature/Serializer/CompactSerializer.php', - '/libraries/vendor/web-token/jwt-signature/Serializer/JSONFlattenedSerializer.php', - '/libraries/vendor/web-token/jwt-signature/Serializer/JSONGeneralSerializer.php', - '/libraries/vendor/web-token/jwt-signature/Serializer/JWSSerializer.php', - '/libraries/vendor/web-token/jwt-signature/Serializer/JWSSerializerManager.php', - '/libraries/vendor/web-token/jwt-signature/Serializer/JWSSerializerManagerFactory.php', - '/libraries/vendor/web-token/jwt-signature/Serializer/Serializer.php', - '/libraries/vendor/web-token/jwt-signature/Signature.php', - '/media/plg_system_jooa11y/css/jooa11y.css', - '/media/plg_system_jooa11y/css/jooa11y.min.css', - '/media/plg_system_jooa11y/css/jooa11y.min.css.gz', - '/media/plg_system_jooa11y/scss/jooa11y.scss', - '/media/vendor/joomla-a11y-checker/LICENSE.md', - '/modules/mod_feed/mod_feed.php', - '/modules/mod_languages/mod_languages.php', - '/modules/mod_stats/mod_stats.php', - '/modules/mod_syndicate/mod_syndicate.php', - '/modules/mod_tags_popular/mod_tags_popular.php', - '/modules/mod_tags_similar/mod_tags_similar.php', - '/modules/mod_wrapper/mod_wrapper.php', - // From 5.1.0-beta1 to 5.1.0-beta2 - '/administrator/modules/mod_login/mod_login.php', - '/libraries/src/Event/Router/AfterInitialiseRouterEvent.php', - '/libraries/src/Event/Router/RouterEvent.php', - '/libraries/src/Http/HttpFactoryInterface.php', - '/libraries/src/Service/Provider/Http.php', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption/A128CCM_16_128.php', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption/A128CCM_16_64.php', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption/A128CCM_64_128.php', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption/A128CCM_64_64.php', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption/A256CCM_16_128.php', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption/A256CCM_16_64.php', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption/A256CCM_64_128.php', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption/A256CCM_64_64.php', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption/AESCCM.php', - '/libraries/vendor/web-token/jwt-experimental/KeyEncryption/A128CTR.php', - '/libraries/vendor/web-token/jwt-experimental/KeyEncryption/A192CTR.php', - '/libraries/vendor/web-token/jwt-experimental/KeyEncryption/A256CTR.php', - '/libraries/vendor/web-token/jwt-experimental/KeyEncryption/AESCTR.php', - '/libraries/vendor/web-token/jwt-experimental/KeyEncryption/Chacha20Poly1305.php', - '/libraries/vendor/web-token/jwt-experimental/KeyEncryption/RSAOAEP384.php', - '/libraries/vendor/web-token/jwt-experimental/KeyEncryption/RSAOAEP512.php', - '/libraries/vendor/web-token/jwt-experimental/LICENSE', - '/libraries/vendor/web-token/jwt-experimental/Signature/Blake2b.php', - '/libraries/vendor/web-token/jwt-experimental/Signature/ES256K.php', - '/libraries/vendor/web-token/jwt-experimental/Signature/HS1.php', - '/libraries/vendor/web-token/jwt-experimental/Signature/HS256_64.php', - '/libraries/vendor/web-token/jwt-experimental/Signature/RS1.php', - '/libraries/vendor/web-token/jwt-signature-algorithm-ecdsa/LICENSE', - '/libraries/vendor/web-token/jwt-signature-algorithm-eddsa/LICENSE', - '/libraries/vendor/web-token/jwt-signature-algorithm-experimental/LICENSE', - '/libraries/vendor/web-token/jwt-signature-algorithm-hmac/LICENSE', - '/libraries/vendor/web-token/jwt-signature-algorithm-none/LICENSE', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/LICENSE', - // From 5.1.0-beta2 to 5.1.0-rc1 - '/administrator/components/com_admin/sql/updates/mysql/4.4.4-2024-03-28.sql', - '/administrator/components/com_admin/sql/updates/postgresql/4.4.4-2024-03-28.sql', - '/administrator/modules/mod_post_installation_messages/mod_post_installation_messages.php', - '/media/vendor/punycode/LICENSE-MIT.txt', - // From 5.1.0 to 5.1.1 - '/libraries/vendor/cweagans/composer-patches/LICENSE.md', - '/libraries/vendor/cweagans/composer-patches/src/PatchEvent.php', - '/libraries/vendor/cweagans/composer-patches/src/PatchEvents.php', - '/libraries/vendor/cweagans/composer-patches/src/Patches.php', - '/libraries/vendor/cweagans/composer-patches/tests/PatchEventTest.php', - '/libraries/vendor/laminas/laminas-diactoros/PATCHES.txt', - // From 5.1.2 to 5.1.3 - '/libraries/vendor/joomla/application/rector.php', - '/libraries/vendor/joomla/console/.drone.jsonnet', - '/libraries/vendor/joomla/console/.drone.yml', - '/libraries/vendor/joomla/database/.drone.jsonnet', - '/libraries/vendor/joomla/database/.drone.yml', - '/libraries/vendor/joomla/database/phpunit.appveyor_sql2012sp1.xml.dist', - '/libraries/vendor/joomla/database/phpunit.appveyor_sql2014.xml.dist', - '/libraries/vendor/joomla/database/phpunit.appveyor_sql2017.xml.dist', - '/libraries/vendor/joomla/database/phpunit.mariadb.xml.dist', - '/libraries/vendor/joomla/database/phpunit.mysql.xml.dist', - '/libraries/vendor/joomla/database/phpunit.mysqli.xml.dist', - '/libraries/vendor/joomla/database/phpunit.pgsql.xml.dist', - '/libraries/vendor/joomla/database/phpunit.sqlite.xml.dist', - '/libraries/vendor/joomla/database/phpunit.sqlsrv.xml.dist', - '/libraries/vendor/joomla/session/.drone.jsonnet', - '/libraries/vendor/joomla/session/.drone.yml', - // From 5.2.0-alpha2 to 5.2.0-alpha3 - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome/fonts/FontAwesome.otf', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.eot', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.svg', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.ttf', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.woff', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome/fonts/fontawesome-webfont.woff2', - // From 5.2.1 to 5.3.0-alpha1 - '/media/system/css/joomla-core-loader.css', - '/media/system/css/joomla-core-loader.min.css', - '/media/system/css/joomla-core-loader.min.css.gz', - '/media/system/scss/joomla-core-loader.scss', - // From 5.3.0-alpha2 to 5.3.0-alpha3 - '/administrator/components/com_scheduler/src/Table/LogsTable.php', - '/media/system/css/system-site-offline_rtl.css', - '/media/system/css/system-site-offline_rtl.min.css', - '/media/system/css/system-site-offline_rtl.min.css.gz', - '/media/system/scss/system-site-offline_rtl.scss', - // From 5.3.0-alpha3 to 5.3.0-beta1 - '/administrator/modules/mod_feed/mod_feed.php', - '/administrator/modules/mod_privacy_status/mod_privacy_status.php', - '/libraries/vendor/guzzlehttp/promises/src/functions.php', - '/libraries/vendor/guzzlehttp/promises/src/functions_include.php', - '/libraries/vendor/maximebf/debugbar/LICENSE', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/CacheCacheCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/DoctrineCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/MonologCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/NamespacedTwigProfileCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Propel2Collector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/PropelCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/SlimCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/SwiftMailer/SwiftLogCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/SwiftMailer/SwiftMailCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Symfony/SymfonyMailCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig/DebugTwigExtension.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig/DumpTwigExtension.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig/MeasureTwigExtension.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig/MeasureTwigNode.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig/MeasureTwigTokenParser.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig/TimeableTwigExtensionProfiler.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigEnvironment.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig/TraceableTwigTemplate.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig/TwigCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/TwigProfileCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/AggregatedCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/AssetProvider.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/ConfigCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/DataCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/DataCollectorInterface.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/ExceptionsCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/LocalizationCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/MemoryCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/MessagesAggregateInterface.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/MessagesCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/ObjectCountCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/PDO/PDOCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDO.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TraceablePDOStatement.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/PDO/TracedStatement.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/PhpInfoCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/Renderable.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/RequestDataCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/TimeDataCollector.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatter.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataFormatter/DataFormatterInterface.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataFormatter/DebugBarVarDumper.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataFormatter/HasDataFormatter.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataFormatter/HasXdebugLinks.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataFormatter/VarDumper/DebugBarHtmlDumper.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DebugBar.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DebugBarException.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/HttpDriverInterface.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/JavascriptRenderer.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/OpenHandler.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/PhpHttpDriver.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/RequestIdGenerator.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/RequestIdGeneratorInterface.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/debugbar.css', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/debugbar.js', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/openhandler.css', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/openhandler.js', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome/css/font-awesome.min.css', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/highlightjs/highlight.pack.js', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/highlightjs/styles/github.css', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/jquery/dist/jquery.min.js', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets.css', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets.js', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets/mails/widget.css', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets/mails/widget.js', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets/sqlqueries/widget.css', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets/sqlqueries/widget.js', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.css', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets/templates/widget.js', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/StandardDebugBar.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Storage/FileStorage.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Storage/MemcachedStorage.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Storage/pdo_storage_schema.sql', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Storage/PdoStorage.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Storage/RedisStorage.php', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Storage/StorageInterface.php', - // From 5.3.0-beta3 to 5.3.0-rc1 - '/libraries/vendor/joomla/http/.drone.jsonnet', - '/libraries/vendor/joomla/http/.drone.yml', - '/libraries/vendor/joomla/oauth1/.drone.jsonnet', - '/libraries/vendor/joomla/oauth1/.drone.yml', - '/libraries/vendor/joomla/oauth2/.drone.jsonnet', - '/libraries/vendor/joomla/oauth2/.drone.yml', - '/libraries/vendor/joomla/router/.drone.jsonnet', - '/libraries/vendor/joomla/router/.drone.yml', - '/libraries/vendor/joomla/string/.drone.jsonnet', - '/libraries/vendor/joomla/string/.drone.yml', - '/libraries/vendor/joomla/uri/.drone.jsonnet', - '/libraries/vendor/joomla/uri/.drone.yml', - '/libraries/vendor/joomla/utilities/.drone.jsonnet', - '/libraries/vendor/joomla/utilities/.drone.yml', - // From 5.3.0-rc1 to 5.3.0-rc2 - '/libraries/vendor/algo26-matthias/idna-convert/Dockerfile', - '/libraries/vendor/algo26-matthias/idna-convert/compose.yml', - '/libraries/vendor/algo26-matthias/idna-convert/src/Exception/Std3AsciiRulesViolationException.php', - '/libraries/vendor/algo26-matthias/idna-convert/src/TranscodeUnicode/ByteLengthTrait.php', - // From 5.4.0-alpha2 to 5.4.0-alpha3 + // From 5.x to 6.0 + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-03-11.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-03-17.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-12.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-25.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-29.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-21.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-26.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-28.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-29.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-30.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-02.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-06.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-09.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-11.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.1.0-2023-11-28.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-01-04.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-10.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-24.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-25.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-03-08.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-03-28.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.1.1-2024-04-18.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-07-02.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-07-19.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-08-22.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-09-17.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.2.2-2024-09-24.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.2.3-2025-01-09.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-10-13.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-10-26.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-12-09.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-12-19.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-02-09.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-02-22.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.3.4-2025-09-19.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-04-23.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql', + '/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-08-02.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-03-11.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-03-17.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-12.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-25.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-29.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-21.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-26.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-28.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-29.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-30.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-02.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-06.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-09.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-11.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2023-11-28.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-10.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-24.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-25.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-03-08.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-03-28.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.1.1-2024-04-18.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-07-02.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-07-19.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-08-22.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-09-17.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.2.2-2024-09-24.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.2.3-2025-01-09.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-10-26.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-12-09.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-12-19.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-02-09.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-02-22.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.3.1-2025-04-27.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.3.4-2025-09-19.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-04-23.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-08-02.sql', + '/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-10-07.sql', + '/administrator/components/com_content/forms/filter_featured.xml', + '/administrator/components/com_content/tmpl/featured/default.php', + '/administrator/components/com_content/tmpl/featured/default.xml', + '/administrator/components/com_content/tmpl/featured/default_stage_body.php', + '/administrator/components/com_content/tmpl/featured/default_stage_footer.php', + '/administrator/components/com_content/tmpl/featured/emptystate.php', + '/administrator/components/com_finder/helpers/indexer/adapter.php', + '/administrator/components/com_finder/helpers/indexer/helper.php', + '/administrator/components/com_finder/helpers/indexer/parser.php', + '/administrator/components/com_finder/helpers/indexer/query.php', + '/administrator/components/com_finder/helpers/indexer/result.php', + '/administrator/components/com_finder/helpers/indexer/taxonomy.php', + '/administrator/components/com_finder/helpers/indexer/token.php', + '/libraries/src/Application/BaseApplication.php', + '/libraries/src/Application/CLI/CliInput.php', + '/libraries/src/Application/CLI/CliOutput.php', + '/libraries/src/Application/CLI/ColorStyle.php', + '/libraries/src/Application/CLI/Output/Processor/ColorProcessor.php', + '/libraries/src/Application/CLI/Output/Processor/ProcessorInterface.php', + '/libraries/src/Application/CLI/Output/Stdout.php', + '/libraries/src/Application/CLI/Output/Xml.php', + '/libraries/src/Application/CliApplication.php', + '/libraries/src/Filesystem/File.php', + '/libraries/src/Filesystem/FilesystemHelper.php', + '/libraries/src/Filesystem/Folder.php', + '/libraries/src/Filesystem/Meta/language/en-GB/en-GB.lib_joomla_filesystem_patcher.ini', + '/libraries/src/Filesystem/Patcher.php', + '/libraries/src/Filesystem/Path.php', + '/libraries/src/Filesystem/Stream.php', + '/libraries/src/Filesystem/Streams/StreamString.php', + '/libraries/src/Filesystem/Support/StringController.php', + '/libraries/src/Input/Cookie.php', + '/libraries/src/Input/Files.php', + '/libraries/src/Input/Input.php', + '/libraries/src/Input/Json.php', + '/libraries/vendor/symfony/polyfill-iconv/bootstrap.php', + '/libraries/vendor/symfony/polyfill-iconv/bootstrap80.php', + '/libraries/vendor/symfony/polyfill-iconv/Iconv.php', + '/libraries/vendor/symfony/polyfill-iconv/LICENSE', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.big5.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp037.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp1006.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp1026.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp424.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp437.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp500.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp737.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp775.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp850.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp852.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp855.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp856.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp857.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp860.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp861.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp862.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp863.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp864.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp865.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp866.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp869.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp874.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp875.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp932.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp936.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp949.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.cp950.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-1.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-10.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-11.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-13.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-14.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-15.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-16.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-2.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-3.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-4.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-5.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-6.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-7.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-8.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.iso-8859-9.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.koi8-r.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.koi8-u.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.us-ascii.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1250.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1251.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1252.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1253.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1254.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1255.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1256.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1257.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/from.windows-1258.php', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset/translit.php', + '/libraries/vendor/typo3/phar-stream-wrapper/LICENSE', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Assertable.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Behavior.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Collectable.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Exception.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Helper.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Interceptor/ConjunctionInterceptor.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Interceptor/PharExtensionInterceptor.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Interceptor/PharMetaDataInterceptor.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Manager.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Phar/Container.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Phar/DeserializationException.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Phar/Manifest.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Phar/Reader.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Phar/ReaderException.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Phar/Stub.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/PharStreamWrapper.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Resolvable.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Resolver/PharInvocation.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Resolver/PharInvocationCollection.php', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Resolver/PharInvocationResolver.php', + '/libraries/vendor/voku/portable-ascii/.deepsource.toml', + '/libraries/vendor/voku/portable-ascii/LICENSE.txt', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/ASCII.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/ascii_by_languages.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/ascii_extras_by_languages.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/ascii_language_max_key.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/ascii_ord.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x000.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x001.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x002.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x003.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x004.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x005.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x006.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x007.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x009.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x00a.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x00b.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x00c.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x00d.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x00e.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x00f.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x010.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x011.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x012.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x013.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x014.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x015.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x016.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x017.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x018.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x01d.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x01e.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x01f.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x020.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x021.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x022.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x023.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x024.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x025.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x026.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x027.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x028.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x029.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x02a.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x02c.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x02e.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x02f.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x030.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x031.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x032.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x033.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x04d.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x04e.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x04f.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x050.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x051.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x052.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x053.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x054.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x055.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x056.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x057.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x058.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x059.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x05a.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x05b.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x05c.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x05d.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x05e.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x05f.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x060.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x061.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x062.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x063.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x064.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x065.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x066.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x067.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x068.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x069.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x06a.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x06b.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x06c.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x06d.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x06e.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x06f.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x070.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x071.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x072.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x073.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x074.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x075.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x076.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x077.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x078.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x079.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x07a.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x07b.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x07c.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x07d.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x07e.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x07f.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x080.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x081.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x082.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x083.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x084.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x085.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x086.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x087.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x088.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x089.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x08a.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x08b.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x08c.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x08d.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x08e.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x08f.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x090.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x091.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x092.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x093.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x094.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x095.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x096.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x097.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x098.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x099.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x09a.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x09b.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x09c.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x09d.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x09e.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x09f.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0a0.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0a1.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0a2.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0a3.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0a4.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0ac.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0ad.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0ae.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0af.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b0.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b1.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b2.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b3.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b4.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b5.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b6.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b7.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b8.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0b9.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0ba.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0bb.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0bc.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0bd.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0be.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0bf.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c0.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c1.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c2.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c3.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c4.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c5.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c6.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c7.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c8.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0c9.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0ca.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0cb.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0cc.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0cd.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0ce.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0cf.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0d0.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0d1.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0d2.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0d3.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0d4.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0d5.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0d6.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0d7.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0f9.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0fa.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0fb.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0fc.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0fd.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0fe.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x0ff.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x1d4.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x1d5.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x1d6.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x1d7.php', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data/x1f1.php', + '/libraries/vendor/voku/portable-utf8/.deepsource.toml', + '/libraries/vendor/voku/portable-utf8/bootstrap.php', + '/libraries/vendor/voku/portable-utf8/LICENSE-APACHE', + '/libraries/vendor/voku/portable-utf8/LICENSE-GPL', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/Bootup.php', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/data/caseFolding_full.php', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/data/chr.php', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/data/emoji.php', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/data/encodings.php', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/data/ord.php', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/data/transliterator_list.php', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/data/utf8_fix.php', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/data/win1252_to_utf8.php', + '/libraries/vendor/voku/portable-utf8/src/voku/helper/UTF8.php', + '/media/legacy/joomla.asset.json', + '/media/legacy/js/jquery-noconflict.js', + '/media/legacy/js/jquery-noconflict.min.js', + '/media/legacy/js/jquery-noconflict.min.js.gz', + '/media/legacy/js/tabs-state.js', + '/media/legacy/js/tabs-state.min.js', + '/media/legacy/js/tabs-state.min.js.gz', + // From 6.0.0-alpha2 to 6.0.0-alpha3 '/administrator/modules/mod_menu/mod_menu.php', '/modules/mod_random_image/mod_random_image.php', - // From 5.4.0-alpha3 to 5.4.0-beta1 + // From 6.0.0-alpha3 to 6.0.0-beta1 '/administrator/modules/mod_latest/mod_latest.php', '/administrator/modules/mod_logged/mod_logged.php', + '/administrator/modules/mod_popular/mod_popular.php', '/administrator/modules/mod_privacy_dashboard/mod_privacy_dashboard.php', '/administrator/modules/mod_submenu/mod_submenu.php', + '/libraries/src/Adapter/Adapter.php', + '/libraries/src/Adapter/AdapterInstance.php', + '/libraries/src/MVC/Model/DatabaseAwareTrait.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector/Inflector.php', + '/libraries/vendor/joomla/database/src/Query/LimitableInterface.php', + '/libraries/vendor/joomla/database/src/Query/PreparableInterface.php', + '/libraries/vendor/joomla/string/src/phputf8/LICENSE', + '/libraries/vendor/joomla/string/src/phputf8/mbstring/core.php', + '/libraries/vendor/joomla/string/src/phputf8/native/core.php', + '/libraries/vendor/joomla/string/src/phputf8/ord.php', + '/libraries/vendor/joomla/string/src/phputf8/README', + '/libraries/vendor/joomla/string/src/phputf8/str_ireplace.php', + '/libraries/vendor/joomla/string/src/phputf8/str_pad.php', + '/libraries/vendor/joomla/string/src/phputf8/str_split.php', + '/libraries/vendor/joomla/string/src/phputf8/strcasecmp.php', + '/libraries/vendor/joomla/string/src/phputf8/strcspn.php', + '/libraries/vendor/joomla/string/src/phputf8/stristr.php', + '/libraries/vendor/joomla/string/src/phputf8/strrev.php', + '/libraries/vendor/joomla/string/src/phputf8/strspn.php', + '/libraries/vendor/joomla/string/src/phputf8/substr_replace.php', + '/libraries/vendor/joomla/string/src/phputf8/trim.php', + '/libraries/vendor/joomla/string/src/phputf8/ucfirst.php', + '/libraries/vendor/joomla/string/src/phputf8/ucwords.php', + '/libraries/vendor/joomla/string/src/phputf8/utf8.php', + '/libraries/vendor/joomla/string/src/phputf8/utils/ascii.php', + '/libraries/vendor/joomla/string/src/phputf8/utils/bad.php', + '/libraries/vendor/joomla/string/src/phputf8/utils/patterns.php', + '/libraries/vendor/joomla/string/src/phputf8/utils/position.php', + '/libraries/vendor/joomla/string/src/phputf8/utils/specials.php', + '/libraries/vendor/joomla/string/src/phputf8/utils/unicode.php', + '/libraries/vendor/joomla/string/src/phputf8/utils/validation.php', + '/libraries/vendor/laminas/laminas-diactoros/src/functions/create_uploaded_file.legacy.php', + '/libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_headers_from_sapi.legacy.php', + '/libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_method_from_sapi.legacy.php', + '/libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_protocol_version_from_sapi.legacy.php', + '/libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.legacy.php', + '/libraries/vendor/laminas/laminas-diactoros/src/functions/marshal_uri_from_sapi.php', + '/libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_server.legacy.php', + '/libraries/vendor/laminas/laminas-diactoros/src/functions/normalize_uploaded_files.legacy.php', + '/libraries/vendor/laminas/laminas-diactoros/src/functions/parse_cookie_header.legacy.php', + '/libraries/vendor/laminas/laminas-diactoros/src/PhpInputStream.php', + '/libraries/vendor/lcobucci/clock/renovate.json', + '/libraries/vendor/symfony/http-client/Internal/AmpBody.php', + '/libraries/vendor/symfony/http-client/Internal/AmpClientState.php', + '/libraries/vendor/symfony/http-client/Internal/AmpListener.php', + '/libraries/vendor/symfony/http-client/Internal/AmpResolver.php', + '/libraries/vendor/symfony/http-client/Internal/LegacyHttplugInterface.php', + '/libraries/vendor/symfony/http-client/Response/AmpResponse.php', + '/libraries/vendor/symfony/polyfill-php83/bootstrap.php', + '/libraries/vendor/symfony/polyfill-php83/bootstrap81.php', + '/libraries/vendor/symfony/polyfill-php83/LICENSE', + '/libraries/vendor/symfony/polyfill-php83/Php83.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/DateError.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/DateException.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/DateInvalidOperationException.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/DateInvalidTimeZoneException.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/DateMalformedIntervalStringException.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/DateMalformedPeriodStringException.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/DateMalformedStringException.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/DateObjectError.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/DateRangeError.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/Override.php', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs/SQLite3Exception.php', + '/media/legacy/js/ajax-chosen.js', + '/media/legacy/js/ajax-chosen.min.js', + '/media/legacy/js/ajax-chosen.min.js.gz', + '/media/legacy/js/joomla-chosen.js', + '/media/legacy/js/joomla-chosen.min.js', + '/media/legacy/js/joomla-chosen.min.js.gz', + '/media/system/js/fields/tag.js', + '/media/system/js/fields/tag.min.js', + '/media/system/js/fields/tag.min.js.gz', + '/media/templates/site/cassiopeia/scss/vendor/_chosen.scss', + '/media/vendor/chosen/css/chosen-sprite.png', + '/media/vendor/chosen/css/chosen-sprite@2x.png', + '/media/vendor/chosen/css/chosen.css', + '/media/vendor/chosen/js/chosen.jquery.js', + '/media/vendor/chosen/js/chosen.jquery.min.js', + '/media/vendor/chosen/js/chosen.jquery.min.js.gz', + '/media/vendor/tinymce/langs/af.js', + '/media/vendor/tinymce/langs/af.min.js', + '/media/vendor/tinymce/langs/af.min.js.gz', + '/media/vendor/tinymce/langs/bg.js', + '/media/vendor/tinymce/langs/bg.min.js', + '/media/vendor/tinymce/langs/bg.min.js.gz', + '/media/vendor/tinymce/langs/fo.js', + '/media/vendor/tinymce/langs/fo.min.js', + '/media/vendor/tinymce/langs/fo.min.js.gz', + '/media/vendor/tinymce/langs/fr.js', + '/media/vendor/tinymce/langs/fr.min.js', + '/media/vendor/tinymce/langs/fr.min.js.gz', + '/media/vendor/tinymce/langs/he.js', + '/media/vendor/tinymce/langs/he.min.js', + '/media/vendor/tinymce/langs/he.min.js.gz', + '/media/vendor/tinymce/langs/hu.js', + '/media/vendor/tinymce/langs/hu.min.js', + '/media/vendor/tinymce/langs/hu.min.js.gz', + '/media/vendor/tinymce/langs/ka.js', + '/media/vendor/tinymce/langs/ka.min.js', + '/media/vendor/tinymce/langs/ka.min.js.gz', + '/media/vendor/tinymce/langs/km.js', + '/media/vendor/tinymce/langs/km.min.js', + '/media/vendor/tinymce/langs/km.min.js.gz', + '/media/vendor/tinymce/langs/ko.js', + '/media/vendor/tinymce/langs/ko.min.js', + '/media/vendor/tinymce/langs/ko.min.js.gz', + '/media/vendor/tinymce/langs/lb.js', + '/media/vendor/tinymce/langs/lb.min.js', + '/media/vendor/tinymce/langs/lb.min.js.gz', + '/media/vendor/tinymce/langs/mk.js', + '/media/vendor/tinymce/langs/mk.min.js', + '/media/vendor/tinymce/langs/mk.min.js.gz', + '/media/vendor/tinymce/langs/ms.js', + '/media/vendor/tinymce/langs/ms.min.js', + '/media/vendor/tinymce/langs/ms.min.js.gz', + '/media/vendor/tinymce/langs/nb.js', + '/media/vendor/tinymce/langs/nb.min.js', + '/media/vendor/tinymce/langs/nb.min.js.gz', + '/media/vendor/tinymce/langs/readme.md', + '/media/vendor/tinymce/langs/si-LK.js', + '/media/vendor/tinymce/langs/si-LK.min.js', + '/media/vendor/tinymce/langs/si-LK.min.js.gz', + '/media/vendor/tinymce/langs/sl.js', + '/media/vendor/tinymce/langs/sl.min.js', + '/media/vendor/tinymce/langs/sl.min.js.gz', + '/media/vendor/tinymce/langs/sv.js', + '/media/vendor/tinymce/langs/sv.min.js', + '/media/vendor/tinymce/langs/sv.min.js.gz', + '/media/vendor/tinymce/langs/sw.js', + '/media/vendor/tinymce/langs/sw.min.js', + '/media/vendor/tinymce/langs/sw.min.js.gz', + '/media/vendor/tinymce/langs/sy.js', + '/media/vendor/tinymce/langs/sy.min.js', + '/media/vendor/tinymce/langs/sy.min.js.gz', + '/media/vendor/tinymce/langs/th.js', + '/media/vendor/tinymce/langs/th.min.js', + '/media/vendor/tinymce/langs/th.min.js.gz', + '/media/vendor/tinymce/license.txt', + '/media/vendor/webcomponentsjs/js/webcomponents-bundle.js', + '/media/vendor/webcomponentsjs/js/webcomponents-bundle.min.js', + '/media/vendor/webcomponentsjs/js/webcomponents-bundle.min.js.gz', + '/media/vendor/webcomponentsjs/LICENSE.md', '/modules/mod_finder/mod_finder.php', '/modules/mod_login/mod_login.php', '/modules/mod_menu/mod_menu.php', '/modules/mod_whosonline/mod_whosonline.php', - // From 5.4.2 to 5.4.3 + // From 6.0.0-beta2 to 6.0.0-beta3 + '/media/templates/site/cassiopeia/css/global/colors_custom.css', + '/media/templates/site/cassiopeia/css/global/colors_custom.min.css', + '/media/templates/site/cassiopeia/css/global/colors_custom.min.css.gz', + '/media/templates/site/cassiopeia/css/global/font_advanced.css', + '/media/templates/site/cassiopeia/css/global/font_advanced.min.css', + '/media/templates/site/cassiopeia/css/global/font_advanced.min.css.gz', + '/media/templates/site/cassiopeia/scss/global/colors_custom.scss', + '/media/templates/site/cassiopeia/scss/global/font_advanced.scss', + // From 6.0.0-beta3 to 6.0.0-rc1 + '/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_2.ini', + '/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_2_steps.ini', + '/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini', + '/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini', + '/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini', + '/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4_steps.ini', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/CachedWordInflector.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/GenericLanguageInflectorFactory.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Inflector.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/InflectorFactory.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Language.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/LanguageInflectorFactory.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/NoopWordInflector.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Inflectible.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/InflectorFactory.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Rules.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English/Uninflected.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Inflectible.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/InflectorFactory.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Rules.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French/Uninflected.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Inflectible.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/InflectorFactory.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Rules.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal/Uninflected.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Pattern.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Patterns.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/Inflectible.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/InflectorFactory.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/Rules.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese/Uninflected.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Ruleset.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Spanish/Inflectible.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Spanish/InflectorFactory.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Spanish/Rules.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Spanish/Uninflected.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Substitution.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Substitutions.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Transformation.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Transformations.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Turkish/Inflectible.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Turkish/InflectorFactory.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Turkish/Rules.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Turkish/Uninflected.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Word.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/RulesetInflector.php', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/WordInflector.php', + '/media/com_guidedtours/images/5_2/enhancedtourheader.png', + '/media/com_guidedtours/images/5_2/mailtemplate.png', + '/media/com_guidedtours/images/5_3/filesdirectory.jpg', + '/media/com_guidedtours/images/5_4/automated-updates.jpg', + // From 6.1.0-alpha1 to 6.1.0-alpha2 + '/libraries/vendor/symfony/var-dumper/Cloner/Internal/NoDefault.php', + '/libraries/vendor/webmozart/assert/LICENSE', + '/libraries/vendor/webmozart/assert/src/Assert.php', + '/libraries/vendor/webmozart/assert/src/InvalidArgumentException.php', + '/libraries/vendor/webmozart/assert/src/Mixin.php', + // From 6.1.0-alpha2 to 6.1.0-alpha3 + '/build.xml', + // From 6.0.2 to 6.0.3 '/libraries/vendor/symfony/http-client-contracts/Test/Fixtures/web/index.php', '/libraries/vendor/symfony/http-client-contracts/Test/HttpClientTestCase.php', '/libraries/vendor/symfony/http-client-contracts/Test/TestHttpServer.php', @@ -2493,309 +1060,300 @@ public function deleteUnexistingFiles($dryRun = false, $suppressOutput = false) '/libraries/vendor/symfony/translation-contracts/Test/TranslatorTest.php', '/libraries/vendor/symfony/validator/Test/ConstraintValidatorTestCase.php', '/libraries/vendor/symfony/var-dumper/Test/VarDumperTestTrait.php', - // From 5.4.3 to 5.4.4 + // From 6.1.0-alpha3 to 6.1.0-beta1 + '/media/vendor/tinymce/langs/cy.js', + '/media/vendor/tinymce/langs/cy.min.js', + '/media/vendor/tinymce/langs/cy.min.js.gz', + '/media/vendor/tinymce/langs/dv.js', + '/media/vendor/tinymce/langs/dv.min.js', + '/media/vendor/tinymce/langs/dv.min.js.gz', + '/media/vendor/tinymce/langs/ga.js', + '/media/vendor/tinymce/langs/ga.min.js', + '/media/vendor/tinymce/langs/ga.min.js.gz', + '/media/vendor/tinymce/langs/ku.js', + '/media/vendor/tinymce/langs/ku.min.js', + '/media/vendor/tinymce/langs/ku.min.js.gz', + '/media/vendor/tinymce/langs/ky.js', + '/media/vendor/tinymce/langs/ky.min.js', + '/media/vendor/tinymce/langs/ky.min.js.gz', + '/media/vendor/tinymce/langs/sq.js', + '/media/vendor/tinymce/langs/sq.min.js', + '/media/vendor/tinymce/langs/sq.min.js.gz', + '/media/vendor/tinymce/langs/uz.js', + '/media/vendor/tinymce/langs/uz.min.js', + '/media/vendor/tinymce/langs/uz.min.js.gz', + '/media/vendor/tinymce/langs/zh-SG.js', + '/media/vendor/tinymce/langs/zh-SG.min.js', + '/media/vendor/tinymce/langs/zh-SG.min.js.gz', + // From 6.0.3 to 6.0.4 '/media/system/css/fields/calendar-rtl.css', '/media/system/css/fields/calendar-rtl.min.css', '/media/system/css/fields/calendar-rtl.min.css.gz', - // From 5.4.7 to 5.4.8 + // From 6.1.0-beta1 to 6.1.0-beta2 + '/libraries/vendor/altcha-org/altcha/phpstan-baseline.neon', + '/libraries/vendor/altcha-org/altcha/tests/AltchaTest.php', + // From 6.1.1 to 6.2.0-alpha1 + '/administrator/components/com_workflow/resources/scripts/app/Event.es6.js', + '/administrator/components/com_workflow/resources/scripts/app/WorkflowGraphApi.es6.js', + '/administrator/components/com_workflow/resources/scripts/components/App.vue', + '/administrator/components/com_workflow/resources/scripts/components/Titlebar.vue', + '/administrator/components/com_workflow/resources/scripts/components/canvas/ControlsPanel.vue', + '/administrator/components/com_workflow/resources/scripts/components/canvas/CustomControls.vue', + '/administrator/components/com_workflow/resources/scripts/components/canvas/WorkflowCanvas.vue', + '/administrator/components/com_workflow/resources/scripts/components/edges/CustomEdge.vue', + '/administrator/components/com_workflow/resources/scripts/components/nodes/StageNode.vue', + '/administrator/components/com_workflow/resources/scripts/plugins/Notifications.es6.js', + '/administrator/components/com_workflow/resources/scripts/plugins/translate.es6.js', + '/administrator/components/com_workflow/resources/scripts/store/actions.es6.js', + '/administrator/components/com_workflow/resources/scripts/store/getters.es6.js', + '/administrator/components/com_workflow/resources/scripts/store/mutations.es6.js', + '/administrator/components/com_workflow/resources/scripts/store/plugins/persisted-state.es6.js', + '/administrator/components/com_workflow/resources/scripts/store/state.es6.js', + '/administrator/components/com_workflow/resources/scripts/store/store.es6.js', + '/administrator/components/com_workflow/resources/scripts/utils/accessibility-fixer.es6.js', + '/administrator/components/com_workflow/resources/scripts/utils/edges.es6.js', + '/administrator/components/com_workflow/resources/scripts/utils/focus-utils.es6.js', + '/administrator/components/com_workflow/resources/scripts/utils/keyboard-manager.es6.js', + '/administrator/components/com_workflow/resources/scripts/utils/positioning.es6.js', + '/administrator/components/com_workflow/resources/scripts/utils/utils.es6.js', + '/administrator/components/com_workflow/resources/scripts/workflowgraph.es6.js', + '/media/index.html', + '/media/vendor/accessibility/js/accessibility.js', + '/media/vendor/tinymce/icons/default/index.js', + '/media/vendor/tinymce/langs/ar-SA.min.js', + '/media/vendor/tinymce/langs/ar-SA.min.js.gz', + '/media/vendor/tinymce/langs/ar.min.js', + '/media/vendor/tinymce/langs/ar.min.js.gz', + '/media/vendor/tinymce/langs/az.min.js', + '/media/vendor/tinymce/langs/az.min.js.gz', + '/media/vendor/tinymce/langs/be.min.js', + '/media/vendor/tinymce/langs/be.min.js.gz', + '/media/vendor/tinymce/langs/bg-BG.min.js', + '/media/vendor/tinymce/langs/bg-BG.min.js.gz', + '/media/vendor/tinymce/langs/bn-BD.min.js', + '/media/vendor/tinymce/langs/bn-BD.min.js.gz', + '/media/vendor/tinymce/langs/ca.min.js', + '/media/vendor/tinymce/langs/ca.min.js.gz', + '/media/vendor/tinymce/langs/cs.min.js', + '/media/vendor/tinymce/langs/cs.min.js.gz', + '/media/vendor/tinymce/langs/da.min.js', + '/media/vendor/tinymce/langs/da.min.js.gz', + '/media/vendor/tinymce/langs/de.min.js', + '/media/vendor/tinymce/langs/de.min.js.gz', + '/media/vendor/tinymce/langs/el.min.js', + '/media/vendor/tinymce/langs/el.min.js.gz', + '/media/vendor/tinymce/langs/eo.min.js', + '/media/vendor/tinymce/langs/eo.min.js.gz', + '/media/vendor/tinymce/langs/es-MX.min.js', + '/media/vendor/tinymce/langs/es-MX.min.js.gz', + '/media/vendor/tinymce/langs/es.min.js', + '/media/vendor/tinymce/langs/es.min.js.gz', + '/media/vendor/tinymce/langs/et.min.js', + '/media/vendor/tinymce/langs/et.min.js.gz', + '/media/vendor/tinymce/langs/eu.min.js', + '/media/vendor/tinymce/langs/eu.min.js.gz', + '/media/vendor/tinymce/langs/fa.min.js', + '/media/vendor/tinymce/langs/fa.min.js.gz', + '/media/vendor/tinymce/langs/fi.min.js', + '/media/vendor/tinymce/langs/fi.min.js.gz', + '/media/vendor/tinymce/langs/fr-FR.min.js', + '/media/vendor/tinymce/langs/fr-FR.min.js.gz', + '/media/vendor/tinymce/langs/gl.min.js', + '/media/vendor/tinymce/langs/gl.min.js.gz', + '/media/vendor/tinymce/langs/he-IL.min.js', + '/media/vendor/tinymce/langs/he-IL.min.js.gz', + '/media/vendor/tinymce/langs/hr.min.js', + '/media/vendor/tinymce/langs/hr.min.js.gz', + '/media/vendor/tinymce/langs/hu-HU.min.js', + '/media/vendor/tinymce/langs/hu-HU.min.js.gz', + '/media/vendor/tinymce/langs/hy.min.js', + '/media/vendor/tinymce/langs/hy.min.js.gz', + '/media/vendor/tinymce/langs/id.min.js', + '/media/vendor/tinymce/langs/id.min.js.gz', + '/media/vendor/tinymce/langs/is-IS.min.js', + '/media/vendor/tinymce/langs/is-IS.min.js.gz', + '/media/vendor/tinymce/langs/it.min.js', + '/media/vendor/tinymce/langs/it.min.js.gz', + '/media/vendor/tinymce/langs/ja.min.js', + '/media/vendor/tinymce/langs/ja.min.js.gz', + '/media/vendor/tinymce/langs/ka-GE.min.js', + '/media/vendor/tinymce/langs/ka-GE.min.js.gz', + '/media/vendor/tinymce/langs/kab.min.js', + '/media/vendor/tinymce/langs/kab.min.js.gz', + '/media/vendor/tinymce/langs/kk.min.js', + '/media/vendor/tinymce/langs/kk.min.js.gz', + '/media/vendor/tinymce/langs/ko-KR.min.js', + '/media/vendor/tinymce/langs/ko-KR.min.js.gz', + '/media/vendor/tinymce/langs/lt.min.js', + '/media/vendor/tinymce/langs/lt.min.js.gz', + '/media/vendor/tinymce/langs/lv.min.js', + '/media/vendor/tinymce/langs/lv.min.js.gz', + '/media/vendor/tinymce/langs/nb-NO.min.js', + '/media/vendor/tinymce/langs/nb-NO.min.js.gz', + '/media/vendor/tinymce/langs/ne.min.js', + '/media/vendor/tinymce/langs/ne.min.js.gz', + '/media/vendor/tinymce/langs/nl-BE.min.js', + '/media/vendor/tinymce/langs/nl-BE.min.js.gz', + '/media/vendor/tinymce/langs/nl.min.js', + '/media/vendor/tinymce/langs/nl.min.js.gz', + '/media/vendor/tinymce/langs/oc.min.js', + '/media/vendor/tinymce/langs/oc.min.js.gz', + '/media/vendor/tinymce/langs/pl.min.js', + '/media/vendor/tinymce/langs/pl.min.js.gz', + '/media/vendor/tinymce/langs/pt-BR.min.js', + '/media/vendor/tinymce/langs/pt-BR.min.js.gz', + '/media/vendor/tinymce/langs/pt-PT.min.js', + '/media/vendor/tinymce/langs/pt-PT.min.js.gz', + '/media/vendor/tinymce/langs/ro.min.js', + '/media/vendor/tinymce/langs/ro.min.js.gz', + '/media/vendor/tinymce/langs/ru.min.js', + '/media/vendor/tinymce/langs/ru.min.js.gz', + '/media/vendor/tinymce/langs/sk.min.js', + '/media/vendor/tinymce/langs/sk.min.js.gz', + '/media/vendor/tinymce/langs/sl-SI.min.js', + '/media/vendor/tinymce/langs/sl-SI.min.js.gz', + '/media/vendor/tinymce/langs/sr.min.js', + '/media/vendor/tinymce/langs/sr.min.js.gz', + '/media/vendor/tinymce/langs/sv-SE.min.js', + '/media/vendor/tinymce/langs/sv-SE.min.js.gz', + '/media/vendor/tinymce/langs/ta.min.js', + '/media/vendor/tinymce/langs/ta.min.js.gz', + '/media/vendor/tinymce/langs/tg.min.js', + '/media/vendor/tinymce/langs/tg.min.js.gz', + '/media/vendor/tinymce/langs/th-TH.min.js', + '/media/vendor/tinymce/langs/th-TH.min.js.gz', + '/media/vendor/tinymce/langs/tr.min.js', + '/media/vendor/tinymce/langs/tr.min.js.gz', + '/media/vendor/tinymce/langs/ug.min.js', + '/media/vendor/tinymce/langs/ug.min.js.gz', + '/media/vendor/tinymce/langs/uk.min.js', + '/media/vendor/tinymce/langs/uk.min.js.gz', + '/media/vendor/tinymce/langs/vi.min.js', + '/media/vendor/tinymce/langs/vi.min.js.gz', + '/media/vendor/tinymce/langs/zh-CN.min.js', + '/media/vendor/tinymce/langs/zh-CN.min.js.gz', + '/media/vendor/tinymce/langs/zh-HK.min.js', + '/media/vendor/tinymce/langs/zh-HK.min.js.gz', + '/media/vendor/tinymce/langs/zh-MO.min.js', + '/media/vendor/tinymce/langs/zh-MO.min.js.gz', + '/media/vendor/tinymce/langs/zh-TW.min.js', + '/media/vendor/tinymce/langs/zh-TW.min.js.gz', + '/media/vendor/tinymce/models/dom/index.js', + '/media/vendor/tinymce/plugins/accordion/index.js', + '/media/vendor/tinymce/plugins/advlist/index.js', + '/media/vendor/tinymce/plugins/anchor/index.js', + '/media/vendor/tinymce/plugins/autolink/index.js', + '/media/vendor/tinymce/plugins/autoresize/index.js', + '/media/vendor/tinymce/plugins/autosave/index.js', + '/media/vendor/tinymce/plugins/charmap/index.js', + '/media/vendor/tinymce/plugins/code/index.js', + '/media/vendor/tinymce/plugins/codesample/index.js', + '/media/vendor/tinymce/plugins/directionality/index.js', + '/media/vendor/tinymce/plugins/emoticons/index.js', + '/media/vendor/tinymce/plugins/fullscreen/index.js', + '/media/vendor/tinymce/plugins/help/index.js', + '/media/vendor/tinymce/plugins/image/index.js', + '/media/vendor/tinymce/plugins/importcss/index.js', + '/media/vendor/tinymce/plugins/insertdatetime/index.js', + '/media/vendor/tinymce/plugins/link/index.js', + '/media/vendor/tinymce/plugins/lists/index.js', + '/media/vendor/tinymce/plugins/media/index.js', + '/media/vendor/tinymce/plugins/nonbreaking/index.js', + '/media/vendor/tinymce/plugins/pagebreak/index.js', + '/media/vendor/tinymce/plugins/preview/index.js', + '/media/vendor/tinymce/plugins/quickbars/index.js', + '/media/vendor/tinymce/plugins/save/index.js', + '/media/vendor/tinymce/plugins/searchreplace/index.js', + '/media/vendor/tinymce/plugins/table/index.js', + '/media/vendor/tinymce/plugins/visualblocks/index.js', + '/media/vendor/tinymce/plugins/visualchars/index.js', + '/media/vendor/tinymce/plugins/wordcount/index.js', + '/media/vendor/tinymce/themes/silver/index.js', + // From 6.2.0-alpha1 to 6.2.0-alpha2 + '/administrator/help/en-GB/toc.json', + // From 6.1.1 to 6.1.2 + '/libraries/vendor/algo26-matthias/idna-convert/Dockerfile', + '/libraries/vendor/algo26-matthias/idna-convert/compose.yml', + // From 6.1.2 to 6.1.3 '/administrator/manifests/files/filepatcher.xml', '/filepatcher.php', '/filepatcher.xml', '/LICENSE', '/README.md', + // From 6.2.0-alpha3 to 6.2.0-beta1 + '/media/vendor/tinymce/langs/bs.min.js', + '/media/vendor/tinymce/langs/bs.min.js.gz', ]; $folders = [ - // From 4.4 to 5.0 - '/plugins/system/webauthn/src/Hotfix', - '/plugins/multifactorauth/webauthn/src/Hotfix', - '/media/vendor/tinymce/themes/mobile', - '/media/vendor/tinymce/skins/ui/oxide/fonts', - '/media/vendor/tinymce/skins/ui/oxide-dark/fonts', - '/media/vendor/tinymce/plugins/toc', - '/media/vendor/tinymce/plugins/textpattern', - '/media/vendor/tinymce/plugins/textcolor', - '/media/vendor/tinymce/plugins/template', - '/media/vendor/tinymce/plugins/tabfocus', - '/media/vendor/tinymce/plugins/spellchecker', - '/media/vendor/tinymce/plugins/print', - '/media/vendor/tinymce/plugins/paste', - '/media/vendor/tinymce/plugins/noneditable', - '/media/vendor/tinymce/plugins/legacyoutput', - '/media/vendor/tinymce/plugins/imagetools', - '/media/vendor/tinymce/plugins/hr', - '/media/vendor/tinymce/plugins/fullpage', - '/media/vendor/tinymce/plugins/contextmenu', - '/media/vendor/tinymce/plugins/colorpicker', - '/media/vendor/tinymce/plugins/bbcode', - '/libraries/vendor/symfony/polyfill-php81/Resources/stubs', - '/libraries/vendor/symfony/polyfill-php81/Resources', - '/libraries/vendor/symfony/polyfill-php81', - '/libraries/vendor/symfony/polyfill-php80/Resources/stubs', - '/libraries/vendor/symfony/polyfill-php80/Resources', - '/libraries/vendor/symfony/polyfill-php80', - '/libraries/vendor/symfony/polyfill-php73/Resources/stubs', - '/libraries/vendor/symfony/polyfill-php73/Resources', - '/libraries/vendor/symfony/polyfill-php73', - '/libraries/vendor/symfony/polyfill-php72', - '/libraries/vendor/spomky-labs/base64url/src', - '/libraries/vendor/spomky-labs/base64url', - '/libraries/vendor/ramsey/uuid/src/Provider/Time', - '/libraries/vendor/ramsey/uuid/src/Provider/Node', - '/libraries/vendor/ramsey/uuid/src/Provider', - '/libraries/vendor/ramsey/uuid/src/Generator', - '/libraries/vendor/ramsey/uuid/src/Exception', - '/libraries/vendor/ramsey/uuid/src/Converter/Time', - '/libraries/vendor/ramsey/uuid/src/Converter/Number', - '/libraries/vendor/ramsey/uuid/src/Converter', - '/libraries/vendor/ramsey/uuid/src/Codec', - '/libraries/vendor/ramsey/uuid/src/Builder', - '/libraries/vendor/ramsey/uuid/src', - '/libraries/vendor/ramsey/uuid', - '/libraries/vendor/ramsey', - '/libraries/vendor/psr/log/Psr/Log', - '/libraries/vendor/psr/log/Psr', - '/libraries/vendor/nyholm/psr7/src/Factory', - '/libraries/vendor/nyholm/psr7/src', - '/libraries/vendor/nyholm/psr7', - '/libraries/vendor/nyholm', - '/libraries/vendor/lcobucci/jwt/src/Parsing', - '/libraries/vendor/lcobucci/jwt/src/Claim', - '/libraries/vendor/lcobucci/jwt/compat', - '/libraries/vendor/laminas/laminas-zendframework-bridge/src', - '/libraries/vendor/laminas/laminas-zendframework-bridge/config', - '/libraries/vendor/laminas/laminas-zendframework-bridge', - '/libraries/vendor/joomla/ldap/src', - '/libraries/vendor/joomla/ldap', - '/libraries/vendor/beberlei/assert/lib/Assert', - '/libraries/vendor/beberlei/assert/lib', - '/libraries/vendor/beberlei/assert', - '/libraries/vendor/beberlei', - '/administrator/components/com_admin/sql/others/mysql', - '/administrator/components/com_admin/sql/others', - // From 5.0.0-alpha2 to 5.0.0-alpha3 - '/plugins/editors/codemirror/src/Field', - '/media/vendor/codemirror/theme', - '/media/vendor/codemirror/mode/z80', - '/media/vendor/codemirror/mode/yaml-frontmatter', - '/media/vendor/codemirror/mode/yaml', - '/media/vendor/codemirror/mode/yacas', - '/media/vendor/codemirror/mode/xquery', - '/media/vendor/codemirror/mode/xml', - '/media/vendor/codemirror/mode/webidl', - '/media/vendor/codemirror/mode/wast', - '/media/vendor/codemirror/mode/vue', - '/media/vendor/codemirror/mode/vhdl', - '/media/vendor/codemirror/mode/verilog', - '/media/vendor/codemirror/mode/velocity', - '/media/vendor/codemirror/mode/vbscript', - '/media/vendor/codemirror/mode/vb', - '/media/vendor/codemirror/mode/twig', - '/media/vendor/codemirror/mode/turtle', - '/media/vendor/codemirror/mode/ttcn-cfg', - '/media/vendor/codemirror/mode/ttcn', - '/media/vendor/codemirror/mode/troff', - '/media/vendor/codemirror/mode/tornado', - '/media/vendor/codemirror/mode/toml', - '/media/vendor/codemirror/mode/tiki', - '/media/vendor/codemirror/mode/tiddlywiki', - '/media/vendor/codemirror/mode/textile', - '/media/vendor/codemirror/mode/tcl', - '/media/vendor/codemirror/mode/swift', - '/media/vendor/codemirror/mode/stylus', - '/media/vendor/codemirror/mode/stex', - '/media/vendor/codemirror/mode/sql', - '/media/vendor/codemirror/mode/spreadsheet', - '/media/vendor/codemirror/mode/sparql', - '/media/vendor/codemirror/mode/soy', - '/media/vendor/codemirror/mode/solr', - '/media/vendor/codemirror/mode/smarty', - '/media/vendor/codemirror/mode/smalltalk', - '/media/vendor/codemirror/mode/slim', - '/media/vendor/codemirror/mode/sieve', - '/media/vendor/codemirror/mode/shell', - '/media/vendor/codemirror/mode/scheme', - '/media/vendor/codemirror/mode/sass', - '/media/vendor/codemirror/mode/sas', - '/media/vendor/codemirror/mode/rust', - '/media/vendor/codemirror/mode/ruby', - '/media/vendor/codemirror/mode/rst', - '/media/vendor/codemirror/mode/rpm/changes', - '/media/vendor/codemirror/mode/rpm', - '/media/vendor/codemirror/mode/r', - '/media/vendor/codemirror/mode/q', - '/media/vendor/codemirror/mode/python', - '/media/vendor/codemirror/mode/puppet', - '/media/vendor/codemirror/mode/pug', - '/media/vendor/codemirror/mode/protobuf', - '/media/vendor/codemirror/mode/properties', - '/media/vendor/codemirror/mode/powershell', - '/media/vendor/codemirror/mode/pig', - '/media/vendor/codemirror/mode/php', - '/media/vendor/codemirror/mode/perl', - '/media/vendor/codemirror/mode/pegjs', - '/media/vendor/codemirror/mode/pascal', - '/media/vendor/codemirror/mode/oz', - '/media/vendor/codemirror/mode/octave', - '/media/vendor/codemirror/mode/ntriples', - '/media/vendor/codemirror/mode/nsis', - '/media/vendor/codemirror/mode/nginx', - '/media/vendor/codemirror/mode/mumps', - '/media/vendor/codemirror/mode/mscgen', - '/media/vendor/codemirror/mode/modelica', - '/media/vendor/codemirror/mode/mllike', - '/media/vendor/codemirror/mode/mirc', - '/media/vendor/codemirror/mode/mbox', - '/media/vendor/codemirror/mode/mathematica', - '/media/vendor/codemirror/mode/markdown', - '/media/vendor/codemirror/mode/lua', - '/media/vendor/codemirror/mode/livescript', - '/media/vendor/codemirror/mode/julia', - '/media/vendor/codemirror/mode/jsx', - '/media/vendor/codemirror/mode/jinja2', - '/media/vendor/codemirror/mode/javascript', - '/media/vendor/codemirror/mode/idl', - '/media/vendor/codemirror/mode/http', - '/media/vendor/codemirror/mode/htmlmixed', - '/media/vendor/codemirror/mode/htmlembedded', - '/media/vendor/codemirror/mode/haxe', - '/media/vendor/codemirror/mode/haskell-literate', - '/media/vendor/codemirror/mode/haskell', - '/media/vendor/codemirror/mode/handlebars', - '/media/vendor/codemirror/mode/haml', - '/media/vendor/codemirror/mode/groovy', - '/media/vendor/codemirror/mode/go', - '/media/vendor/codemirror/mode/gherkin', - '/media/vendor/codemirror/mode/gfm', - '/media/vendor/codemirror/mode/gas', - '/media/vendor/codemirror/mode/fortran', - '/media/vendor/codemirror/mode/forth', - '/media/vendor/codemirror/mode/fcl', - '/media/vendor/codemirror/mode/factor', - '/media/vendor/codemirror/mode/erlang', - '/media/vendor/codemirror/mode/elm', - '/media/vendor/codemirror/mode/eiffel', - '/media/vendor/codemirror/mode/ecl', - '/media/vendor/codemirror/mode/ebnf', - '/media/vendor/codemirror/mode/dylan', - '/media/vendor/codemirror/mode/dtd', - '/media/vendor/codemirror/mode/dockerfile', - '/media/vendor/codemirror/mode/django', - '/media/vendor/codemirror/mode/diff', - '/media/vendor/codemirror/mode/dart', - '/media/vendor/codemirror/mode/d', - '/media/vendor/codemirror/mode/cypher', - '/media/vendor/codemirror/mode/css', - '/media/vendor/codemirror/mode/crystal', - '/media/vendor/codemirror/mode/commonlisp', - '/media/vendor/codemirror/mode/coffeescript', - '/media/vendor/codemirror/mode/cobol', - '/media/vendor/codemirror/mode/cmake', - '/media/vendor/codemirror/mode/clojure', - '/media/vendor/codemirror/mode/clike', - '/media/vendor/codemirror/mode/brainfuck', - '/media/vendor/codemirror/mode/asterisk', - '/media/vendor/codemirror/mode/asn.1', - '/media/vendor/codemirror/mode/asciiarmor', - '/media/vendor/codemirror/mode/apl', - '/media/vendor/codemirror/mode', - '/media/vendor/codemirror/lib', - '/media/vendor/codemirror/keymap', - '/media/vendor/codemirror/addon/wrap', - '/media/vendor/codemirror/addon/tern', - '/media/vendor/codemirror/addon/selection', - '/media/vendor/codemirror/addon/search', - '/media/vendor/codemirror/addon/scroll', - '/media/vendor/codemirror/addon/runmode', - '/media/vendor/codemirror/addon/mode', - '/media/vendor/codemirror/addon/merge', - '/media/vendor/codemirror/addon/lint', - '/media/vendor/codemirror/addon/hint', - '/media/vendor/codemirror/addon/fold', - '/media/vendor/codemirror/addon/edit', - '/media/vendor/codemirror/addon/display', - '/media/vendor/codemirror/addon/dialog', - '/media/vendor/codemirror/addon/comment', - '/media/vendor/codemirror/addon', - // From 5.0.0-alpha3 to 5.0.0-alpha4 - '/templates/system/incompatible.html,/includes', - '/templates/system/incompatible.html,', - '/media/plg_system_compat', - '/media/plg_editors_tinymce/js/plugins/highlighter', - // From 5.0.0-beta2 to 5.0.0-beta3 - '/libraries/vendor/stella-maris/clock/src', - '/libraries/vendor/stella-maris/clock', - '/libraries/vendor/stella-maris', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/SAN', - '/libraries/vendor/fgrosse/phpasn1/lib/X509/CSR', - '/libraries/vendor/fgrosse/phpasn1/lib/X509', - '/libraries/vendor/fgrosse/phpasn1/lib/Utility', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Universal', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Exception', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1/Composite', - '/libraries/vendor/fgrosse/phpasn1/lib/ASN1', - '/libraries/vendor/fgrosse/phpasn1/lib', - '/libraries/vendor/fgrosse/phpasn1', - '/libraries/vendor/fgrosse', - // From 5.1.0-alpha4 to 5.1.0-beta1 - '/media/vendor/joomla-a11y-checker', - '/media/plg_system_jooa11y/scss', - '/media/plg_system_jooa11y/css', - '/libraries/vendor/web-token/jwt-signature/Serializer', - '/libraries/vendor/web-token/jwt-signature/Algorithm', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa/Util', - '/libraries/vendor/web-token/jwt-signature', - '/libraries/vendor/web-token/jwt-core/Util', - '/libraries/vendor/web-token/jwt-core', - // From 5.1.0-beta1 to 5.1.0-beta2 - '/libraries/vendor/web-token/signature-pack', - '/libraries/vendor/web-token/jwt-signature-algorithm-rsa', - '/libraries/vendor/web-token/jwt-signature-algorithm-none', - '/libraries/vendor/web-token/jwt-signature-algorithm-hmac', - '/libraries/vendor/web-token/jwt-signature-algorithm-experimental', - '/libraries/vendor/web-token/jwt-signature-algorithm-eddsa', - '/libraries/vendor/web-token/jwt-signature-algorithm-ecdsa', - '/libraries/vendor/web-token/jwt-experimental/Signature', - '/libraries/vendor/web-token/jwt-experimental/KeyEncryption', - '/libraries/vendor/web-token/jwt-experimental/ContentEncryption', - '/libraries/vendor/web-token/jwt-experimental', - '/libraries/src/Event/Router', - // From 5.1.0-beta2 to 5.1.0-rc1 - '/media/vendor/punycode', - // From 5.1.0 to 5.1.1 - '/libraries/vendor/cweagans/composer-patches/tests', - '/libraries/vendor/cweagans/composer-patches/src', - '/libraries/vendor/cweagans/composer-patches', - '/libraries/vendor/cweagans', - // From 5.2.0-alpha2 to 5.2.0-alpha3 - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome/fonts', - // From 5.3.0-alpha3 to 5.3.0-beta1 - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Storage', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets/templates', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets/sqlqueries', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets/mails', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/widgets', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/jquery/dist', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/jquery', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/highlightjs/styles', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/highlightjs', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome/css', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor/font-awesome', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources/vendor', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Resources', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataFormatter/VarDumper', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataFormatter', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector/PDO', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/DataCollector', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Twig', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/Symfony', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge/SwiftMailer', - '/libraries/vendor/maximebf/debugbar/src/DebugBar/Bridge', - '/libraries/vendor/maximebf/debugbar/src/DebugBar', - '/libraries/vendor/maximebf/debugbar/src', - '/libraries/vendor/maximebf/debugbar', - '/libraries/vendor/maximebf', - // From 5.4.2 to 5.4.3 + // From 5.x to 6.0 + '/libraries/vendor/voku/portable-utf8/src/voku/helper/data', + '/libraries/vendor/voku/portable-utf8/src/voku/helper', + '/libraries/vendor/voku/portable-utf8/src/voku', + '/libraries/vendor/voku/portable-utf8/src', + '/libraries/vendor/voku/portable-utf8', + '/libraries/vendor/voku/portable-ascii/src/voku/helper/data', + '/libraries/vendor/voku/portable-ascii/src/voku/helper', + '/libraries/vendor/voku/portable-ascii/src/voku', + '/libraries/vendor/voku/portable-ascii/src', + '/libraries/vendor/voku/portable-ascii', + '/libraries/vendor/voku', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Resolver', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Phar', + '/libraries/vendor/typo3/phar-stream-wrapper/src/Interceptor', + '/libraries/vendor/typo3/phar-stream-wrapper/src', + '/libraries/vendor/typo3/phar-stream-wrapper', + '/libraries/vendor/typo3', + '/libraries/vendor/symfony/polyfill-iconv/Resources/charset', + '/libraries/vendor/symfony/polyfill-iconv/Resources', + '/libraries/vendor/symfony/polyfill-iconv', + '/libraries/src/Filesystem/Support', + '/libraries/src/Filesystem/Streams', + '/libraries/src/Filesystem/Meta/language/en-GB', + '/libraries/src/Filesystem/Meta/language', + '/libraries/src/Filesystem/Meta', + '/libraries/src/Filesystem', + '/libraries/src/Application/CLI/Output/Processor', + '/libraries/src/Application/CLI/Output', + '/libraries/src/Application/CLI', + '/administrator/components/com_finder/helpers/indexer', + '/administrator/components/com_content/tmpl/featured', + // From 6.0.0-alpha3 to 6.0.0-beta1 + '/media/vendor/webcomponentsjs/js', + '/media/vendor/webcomponentsjs', + '/media/vendor/chosen/js', + '/media/vendor/chosen/css', + '/media/vendor/chosen', + '/libraries/vendor/symfony/polyfill-php83/Resources/stubs', + '/libraries/vendor/symfony/polyfill-php83/Resources', + '/libraries/vendor/symfony/polyfill-php83', + '/libraries/vendor/joomla/string/src/phputf8/utils', + '/libraries/vendor/joomla/string/src/phputf8/native', + '/libraries/vendor/joomla/string/src/phputf8/mbstring', + '/libraries/vendor/joomla/string/src/phputf8', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Common/Inflector', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Common', + '/libraries/src/Adapter', + // From 6.0.0-beta3 to 6.0.0-rc1 + '/media/com_guidedtours/images/5_4', + '/media/com_guidedtours/images/5_3', + '/media/com_guidedtours/images/5_2', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Turkish', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Spanish', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/Portuguese', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/NorwegianBokmal', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/French', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules/English', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector/Rules', + '/libraries/vendor/doctrine/inflector/lib/Doctrine/Inflector', + '/libraries/vendor/doctrine/inflector/lib/Doctrine', + '/libraries/vendor/doctrine/inflector/lib', + // From 6.1.0-alpha1 to 6.1.0-alpha2 + '/libraries/vendor/webmozart/assert/src', + '/libraries/vendor/webmozart/assert', + '/libraries/vendor/webmozart', + '/libraries/vendor/symfony/var-dumper/Cloner/Internal', + // From 6.0.2 to 6.0.3 '/libraries/vendor/symfony/var-dumper/Test', '/libraries/vendor/symfony/validator/Test', '/libraries/vendor/symfony/translation-contracts/Test', @@ -2804,6 +1362,23 @@ public function deleteUnexistingFiles($dryRun = false, $suppressOutput = false) '/libraries/vendor/symfony/http-client-contracts/Test/Fixtures/web', '/libraries/vendor/symfony/http-client-contracts/Test/Fixtures', '/libraries/vendor/symfony/http-client-contracts/Test', + // From 6.1.0-beta1 to 6.1.0-beta2 + '/libraries/vendor/altcha-org/altcha/tests', + // From 6.1.1 to 6.2.0-alpha1 + '/administrator/components/com_workflow/resources/scripts/utils', + '/administrator/components/com_workflow/resources/scripts/store/plugins', + '/administrator/components/com_workflow/resources/scripts/store', + '/administrator/components/com_workflow/resources/scripts/plugins', + '/administrator/components/com_workflow/resources/scripts/components/nodes', + '/administrator/components/com_workflow/resources/scripts/components/edges', + '/administrator/components/com_workflow/resources/scripts/components/canvas', + '/administrator/components/com_workflow/resources/scripts/components', + '/administrator/components/com_workflow/resources/scripts/app', + '/administrator/components/com_workflow/resources/scripts', + '/administrator/components/com_workflow/resources', + // From 6.2.0-alpha1 to 6.2.0-alpha2 + '/administrator/help/en-GB', + '/administrator/help', ]; $status['files_checked'] = $files; @@ -2839,13 +1414,6 @@ public function deleteUnexistingFiles($dryRun = false, $suppressOutput = false) $this->fixFilenameCasing(); - /** - * Fix filesystem permissions when updating a new 5.2.0 installation. - * - * @todo: Remove in 6.0 - */ - $this->fixFilesystemPermissions(); - if ($suppressOutput === false && \count($status['folders_errors'])) { echo implode('
', $status['folders_errors']); } @@ -2868,18 +1436,13 @@ public function deleteUnexistingFiles($dryRun = false, $suppressOutput = false) */ public function updateAssets($installer) { - // List all components added since 4.0 + // List all components added since 6.0 $newComponents = [ // Components to be added here - 'com_guidedtours', - 'com_mails', - 'com_scheduler', - 'com_workflow', ]; foreach ($newComponents as $component) { - /** @var \Joomla\CMS\Table\Asset $asset */ - $asset = Table::getInstance('Asset'); + $asset = new Asset(Factory::getDbo()); if ($asset->loadByName($component)) { continue; @@ -2941,24 +1504,11 @@ public function postflight($action, $installer) return true; } - if (empty($this->fromVersion) || version_compare($this->fromVersion, '5.0.0', 'ge')) { + if (empty($this->fromVersion) || version_compare($this->fromVersion, '6.0.0', 'ge')) { return true; } - // Add here code which shall be executed only when updating from an older version than 5.0.0 - if (!$this->migrateTinymceConfiguration()) { - return false; - } - - if (!$this->migrateDeleteActionlogsConfiguration()) { - return false; - } - - if (!$this->migratePrivacyconsentConfiguration()) { - return false; - } - - $this->setGuidedToursUid(); + // Add here code which shall be executed only when updating from an older version than 6.0.0 // Refresh versionable assets cache. Factory::getApplication()->flushAssets(); @@ -2966,315 +1516,6 @@ public function postflight($action, $installer) return true; } - /** - * Migrate Deleteactionlogs plugin configuration - * - * @return boolean True on success - * - * @since 5.0.0 - */ - private function migrateDeleteActionlogsConfiguration(): bool - { - $db = Factory::getDbo(); - - try { - // Get the ActionLogs system plugin's parameters - $row = $db->setQuery( - $db->getQuery(true) - ->select([$db->quotename('enabled'), $db->quoteName('params')]) - ->from($db->quoteName('#__extensions')) - ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) - ->where($db->quoteName('element') . ' = ' . $db->quote('actionlogs')) - )->loadObject(); - } catch (Exception $e) { - $this->collectError(__METHOD__, $e); - - return false; - } - - // If not existing or disabled there is nothing to migrate - if (!$row || !$row->enabled) { - return true; - } - - $params = new Registry($row->params); - - // If deletion of outdated logs was disabled there is nothing to migrate - if (!$params->get('logDeletePeriod', 0)) { - return true; - } - - /** @var \Joomla\Component\Scheduler\Administrator\Extension\SchedulerComponent $component */ - $component = Factory::getApplication()->bootComponent('com_scheduler'); - - /** @var \Joomla\Component\Scheduler\Administrator\Model\TaskModel $model */ - $model = $component->getMVCFactory()->createModel('Task', 'Administrator', ['ignore_request' => true]); - $task = [ - 'title' => 'Delete Action Logs', - 'type' => 'delete.actionlogs', - 'execution_rules' => [ - 'rule-type' => 'interval-hours', - 'interval-hours' => 24, - 'exec-time' => gmdate('H:i', $params->get('lastrun', time())), - 'exec-day' => gmdate('d'), - ], - 'state' => 1, - 'params' => [ - 'logDeletePeriod' => $params->get('logDeletePeriod', 0), - ], - ]; - - try { - $model->save($task); - } catch (Exception $e) { - $this->collectError(__METHOD__, $e); - - return false; - } - - return true; - } - /** - * Migrate privacyconsents system plugin configuration - * - * @return boolean True on success - * - * @since 5.0.0 - */ - private function migratePrivacyconsentConfiguration(): bool - { - $db = Factory::getDbo(); - - try { - // Get the PrivacyConsent system plugin's parameters - $row = $db->setQuery( - $db->getQuery(true) - ->select([$db->quotename('enabled'), $db->quoteName('params')]) - ->from($db->quoteName('#__extensions')) - ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) - ->where($db->quoteName('element') . ' = ' . $db->quote('privacyconsent')) - )->loadObject(); - } catch (Exception $e) { - $this->collectError(__METHOD__, $e); - - return false; - } - - // If not existing or disabled there is nothing to migrate - if (!$row || !$row->enabled) { - return true; - } - - $params = new Registry($row->params); - - // If consent expiration was disabled there is nothing to migrate - if (!$params->get('enabled', 0)) { - return true; - } - - /** @var \Joomla\Component\Scheduler\Administrator\Extension\SchedulerComponent $component */ - $component = Factory::getApplication()->bootComponent('com_scheduler'); - - /** @var \Joomla\Component\Scheduler\Administrator\Model\TaskModel $model */ - $model = $component->getMVCFactory()->createModel('Task', 'Administrator', ['ignore_request' => true]); - $task = [ - 'title' => 'Privacy Consent', - 'type' => 'privacy.consent', - 'execution_rules' => [ - 'rule-type' => 'interval-days', - 'interval-days' => $params->get('cachetimeout', 30), - 'exec-time' => gmdate('H:i', $params->get('lastrun', time())), - 'exec-day' => gmdate('d'), - ], - 'state' => 1, - 'params' => [ - 'consentexpiration' => $params->get('consentexpiration', 360), - 'remind' => $params->get('remind', 30), - ], - ]; - - try { - $model->save($task); - } catch (Exception $e) { - $this->collectError(__METHOD__, $e); - - return false; - } - - // Refresh versionable assets cache. - Factory::getApplication()->flushAssets(); - - return true; - } - - /** - * Migrate TinyMCE editor plugin configuration - * - * @return boolean True on success - * - * @since 5.0.0 - */ - private function migrateTinymceConfiguration(): bool - { - $db = Factory::getDbo(); - - try { - // Get the TinyMCE editor plugin's parameters - $params = $db->setQuery( - $db->getQuery(true) - ->select($db->quoteName('params')) - ->from($db->quoteName('#__extensions')) - ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('editors')) - ->where($db->quoteName('element') . ' = ' . $db->quote('tinymce')) - )->loadResult(); - } catch (Exception $e) { - $this->collectError(__METHOD__, $e); - - return false; - } - - $params = json_decode($params, true); - - // If there are no toolbars there is nothing to migrate - if (!isset($params['configuration']['toolbars'])) { - return true; - } - - // Each set has its own toolbar configuration - foreach ($params['configuration']['toolbars'] as $setIdx => $toolbarConfig) { - // Migrate menu items if there is a menu - if (isset($toolbarConfig['menu'])) { - /** - * Replace array values with menu item names ("old name" -> "new name"): - * "blockformats" -> "blocks" - * "fontformats" -> "fontfamily" - * "fontsizes" -> "fontsize" - * "formats" -> "styles" - * "template" -> "jtemplate" - */ - $search = ['blockformats', 'fontformats', 'fontsizes', 'formats']; - $replace = ['blocks', 'fontfamily', 'fontsize', 'styles']; - - // Don't redo the template - if (!\in_array('jtemplate', $params['configuration']['toolbars'][$setIdx]['menu'])) { - $search[] = 'template'; - $replace[] = 'jtemplate'; - } - - $params['configuration']['toolbars'][$setIdx]['menu'] = str_replace($search, $replace, $toolbarConfig['menu']); - } - - // There could be no toolbar at all, or only toolbar1, or both toolbar1 and toolbar2 - foreach (['toolbar1', 'toolbar2'] as $toolbarIdx) { - // Migrate toolbar buttons if that toolbar exists - if (isset($toolbarConfig[$toolbarIdx])) { - /** - * Replace array values with button names ("old name" -> "new name"): - * "fontselect" -> "fontfamily" - * "fontsizeselect" -> "fontsize" - * "formatselect" -> "blocks" - * "styleselect" -> "styles" - * "template" -> "jtemplate" - */ - $search = ['fontselect', 'fontsizeselect', 'formatselect', 'styleselect']; - $replace = ['fontfamily', 'fontsize', 'blocks', 'styles']; - - // Don't redo the template - if (!\in_array('jtemplate', $params['configuration']['toolbars'][$setIdx][$toolbarIdx])) { - $search[] = 'template'; - $replace[] = 'jtemplate'; - } - - $params['configuration']['toolbars'][$setIdx][$toolbarIdx] = str_replace($search, $replace, $toolbarConfig[$toolbarIdx]); - } - } - } - - $params = json_encode($params); - - $query = $db->getQuery(true) - ->update($db->quoteName('#__extensions')) - ->set($db->quoteName('params') . ' = ' . $db->quote($params)) - ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) - ->where($db->quoteName('folder') . ' = ' . $db->quote('editors')) - ->where($db->quoteName('element') . ' = ' . $db->quote('tinymce')); - - try { - $db->setQuery($query)->execute(); - } catch (Exception $e) { - $this->collectError(__METHOD__, $e); - - return false; - } - - return true; - } - - /** - * setup Guided Tours Unique Identifiers - * - * @return void - * - * @since 5.0.0 - */ - private function setGuidedToursUid() - { - /** @var \Joomla\Component\Cache\Administrator\Model\CacheModel $model */ - $model = Factory::getApplication()->bootComponent('com_guidedtours')->getMVCFactory() - ->createModel('Tours', 'Administrator', ['ignore_request' => true]); - - $items = $model->getItems(); - - foreach ($items as $item) { - // Set uid for tours where it is empty - if (empty($item->uid)) { - $tourItem = $model->getTable('Tour'); - $tourItem->load($item->id); - - // Tour follows Joomla naming convention - if (str_starts_with($tourItem->title, 'COM_GUIDEDTOURS_TOUR_') && str_ends_with($tourItem->title, '_TITLE')) { - $uidTitle = 'joomla_' . str_replace('COM_GUIDEDTOURS_TOUR_', '', $tourItem->title); - - // Remove the last _TITLE part - $pos = strrpos($uidTitle, '_TITLE'); - if ($pos !== false) { - $uidTitle = substr($uidTitle, 0, $pos); - } - } elseif (preg_match('#COM_(\w+)_TOUR_#', $tourItem->title) && str_ends_with($tourItem->title, '_TITLE')) { - // Tour follows component naming pattern - $uidTitle = preg_replace('#COM_(\w+)_TOUR_#', '$1.', $tourItem->title); - - // Remove the last _TITLE part - $pos = strrpos($uidTitle, "_TITLE"); - if ($pos !== false) { - $uidTitle = substr($uidTitle, 0, $pos); - } - } else { - $uri = Uri::getInstance(); - $host = $uri->toString(['host']); - $host = ApplicationHelper::stringURLSafe($host, $tourItem->language); - $uidTitle = $host . ' ' . str_replace('COM_GUIDEDTOURS_TOUR_', '', $tourItem->title); - // Remove the last _TITLE part - if (str_ends_with($uidTitle, '_TITLE')) { - $pos = strrpos($uidTitle, '_TITLE'); - $uidTitle = substr($uidTitle, 0, $pos); - } - } - // ApplicationHelper::stringURLSafe will replace a period (.) separator so we split the construction into multiple parts - $uidTitleParts = explode('.', $uidTitle); - array_walk($uidTitleParts, function (&$value, $key, $tourLanguage) { - $value = ApplicationHelper::stringURLSafe($value, $tourLanguage); - }, $tourItem->language); - $tourItem->uid = implode('.', $uidTitleParts); - - $tourItem->store(); - } - } - } - /** * Renames or removes incorrectly cased files. * @@ -3285,11 +1526,7 @@ private function setGuidedToursUid() protected function fixFilenameCasing() { $files = [ - // From 4.4 to 5.0 - '/libraries/vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/ED256.php' => '/libraries/vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed256.php', - '/libraries/vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/ED512.php' => '/libraries/vendor/web-auth/cose-lib/src/Algorithm/Signature/EdDSA/Ed512.php', - // From 5.0.0-alpha3 to 5.0.0-alpha4 - '/plugins/schemaorg/blogposting/src/Extension/Blogposting.php' => '/plugins/schemaorg/blogposting/src/Extension/BlogPosting.php', + // From 5.x to 6.0 ]; foreach ($files as $old => $expected) { @@ -3333,426 +1570,4 @@ protected function fixFilenameCasing() } } } - - /** - * Fix filesystem permissions when updating a new 5.2.0 installation. - * - * @return void - * - * @since 5.2.2 - * - * @todo 6.0 Remove this method - * - * @deprecated 5.2.2 will be removed in 6.0 without replacement - */ - protected function fixFilesystemPermissions() - { - // Don't do anything if not updating from a 5.2.0 or 5.2.1 - if ( - empty($this->fromVersion) - || version_compare($this->fromVersion, '5.2.0', 'lt') - || version_compare($this->fromVersion, '5.2.1', 'gt') - ) { - return; - } - - // First check tmp folder if it has mode 777 - if (decoct(fileperms(JPATH_ROOT . '/tmp') & 0777) === '777') { - // We are either on Windows where folders always have 777, or we have to fix permissions - @chmod(JPATH_ROOT . '/tmp', 0755); - clearstatcache(true, JPATH_ROOT . '/tmp'); - } - - // Check tmp folder again if it still has mode 777 - if (decoct(fileperms(JPATH_ROOT . '/tmp') & 0777) === '777') { - // We are on Windows or chmod has no effect - return; - } - - try { - // Using hard-coded string because a new language string would not be available in all cases - Log::add('Fixing permissions for files and folders.', Log::INFO, 'Update'); - } catch (\RuntimeException) { - // Informational log only - } - - $files = [ - '/htaccess.txt', - '/index.php', - '/libraries/.htaccess', - '/libraries/vendor/jfcherng/php-diff/.phpstorm.meta.php', - '/libraries/vendor/joomla/http/.drone.jsonnet', - '/libraries/vendor/joomla/http/.drone.yml', - '/libraries/vendor/joomla/oauth1/.drone.jsonnet', - '/libraries/vendor/joomla/oauth1/.drone.yml', - '/libraries/vendor/joomla/oauth2/.drone.jsonnet', - '/libraries/vendor/joomla/oauth2/.drone.yml', - '/libraries/vendor/joomla/router/.drone.jsonnet', - '/libraries/vendor/joomla/router/.drone.yml', - '/libraries/vendor/joomla/string/.drone.jsonnet', - '/libraries/vendor/joomla/string/.drone.yml', - '/libraries/vendor/joomla/uri/.drone.jsonnet', - '/libraries/vendor/joomla/uri/.drone.yml', - '/libraries/vendor/joomla/utilities/.drone.jsonnet', - '/libraries/vendor/joomla/utilities/.drone.yml', - '/LICENSE.txt', - '/README.txt', - '/robots.txt', - '/robots.txt.dist', - '/tmp/index.html', - '/web.config.txt', - ]; - - $folders = [ - '/administrator', - '/administrator/cache', - '/administrator/components', - '/administrator/help', - '/administrator/help/en-GB', - '/administrator/includes', - '/administrator/language', - '/administrator/language/en-GB', - '/administrator/language/overrides', - '/administrator/logs', - '/administrator/manifests', - '/administrator/manifests/files', - '/administrator/manifests/libraries', - '/administrator/manifests/packages', - '/administrator/modules', - '/administrator/templates', - '/api', - '/api/components', - '/api/includes', - '/api/language', - '/api/language/en-GB', - '/cache', - '/cli', - '/components', - '/images', - '/images/banners', - '/images/headers', - '/images/sampledata', - '/images/sampledata/cassiopeia', - '/includes', - '/language', - '/language/en-GB', - '/language/overrides', - '/layouts', - '/layouts/chromes', - '/layouts/libraries', - '/layouts/libraries/html', - '/layouts/libraries/html/bootstrap', - '/layouts/libraries/html/bootstrap/modal', - '/layouts/libraries/html/bootstrap/tab', - '/libraries', - '/libraries/php-encryption', - '/libraries/phpass', - '/media', - '/media/cache', - '/media/templates', - '/media/templates/administrator', - '/media/templates/site', - '/media/vendor', - '/modules', - '/plugins', - '/templates', - ]; - - $foldersRecursive = [ - '/administrator/components/com_actionlogs', - '/administrator/components/com_admin', - '/administrator/components/com_ajax', - '/administrator/components/com_associations', - '/administrator/components/com_banners', - '/administrator/components/com_cache', - '/administrator/components/com_categories', - '/administrator/components/com_checkin', - '/administrator/components/com_config', - '/administrator/components/com_contact', - '/administrator/components/com_content', - '/administrator/components/com_contenthistory', - '/administrator/components/com_cpanel', - '/administrator/components/com_fields', - '/administrator/components/com_finder', - '/administrator/components/com_guidedtours', - '/administrator/components/com_installer', - '/administrator/components/com_joomlaupdate', - '/administrator/components/com_languages', - '/administrator/components/com_login', - '/administrator/components/com_mails', - '/administrator/components/com_media', - '/administrator/components/com_menus', - '/administrator/components/com_messages', - '/administrator/components/com_modules', - '/administrator/components/com_newsfeeds', - '/administrator/components/com_plugins', - '/administrator/components/com_postinstall', - '/administrator/components/com_privacy', - '/administrator/components/com_redirect', - '/administrator/components/com_scheduler', - '/administrator/components/com_tags', - '/administrator/components/com_templates', - '/administrator/components/com_users', - '/administrator/components/com_workflow', - '/administrator/components/com_wrapper', - '/administrator/modules/mod_custom', - '/administrator/modules/mod_feed', - '/administrator/modules/mod_frontend', - '/administrator/modules/mod_guidedtours', - '/administrator/modules/mod_latest', - '/administrator/modules/mod_latestactions', - '/administrator/modules/mod_logged', - '/administrator/modules/mod_login', - '/administrator/modules/mod_loginsupport', - '/administrator/modules/mod_menu', - '/administrator/modules/mod_messages', - '/administrator/modules/mod_multilangstatus', - '/administrator/modules/mod_popular', - '/administrator/modules/mod_post_installation_messages', - '/administrator/modules/mod_privacy_dashboard', - '/administrator/modules/mod_privacy_status', - '/administrator/modules/mod_quickicon', - '/administrator/modules/mod_sampledata', - '/administrator/modules/mod_stats_admin', - '/administrator/modules/mod_submenu', - '/administrator/modules/mod_title', - '/administrator/modules/mod_toolbar', - '/administrator/modules/mod_user', - '/administrator/modules/mod_version', - '/administrator/templates/atum', - '/administrator/templates/system', - '/api/components/com_banners', - '/api/components/com_categories', - '/api/components/com_config', - '/api/components/com_contact', - '/api/components/com_content', - '/api/components/com_contenthistory', - '/api/components/com_fields', - '/api/components/com_installer', - '/api/components/com_languages', - '/api/components/com_media', - '/api/components/com_menus', - '/api/components/com_messages', - '/api/components/com_modules', - '/api/components/com_newsfeeds', - '/api/components/com_plugins', - '/api/components/com_privacy', - '/api/components/com_redirect', - '/api/components/com_tags', - '/api/components/com_templates', - '/api/components/com_users', - '/components/com_ajax', - '/components/com_banners', - '/components/com_config', - '/components/com_contact', - '/components/com_content', - '/components/com_contenthistory', - '/components/com_fields', - '/components/com_finder', - '/components/com_media', - '/components/com_menus', - '/components/com_modules', - '/components/com_newsfeeds', - '/components/com_privacy', - '/components/com_tags', - '/components/com_users', - '/components/com_wrapper', - '/layouts/joomla', - '/layouts/plugins', - '/libraries/src', - '/libraries/vendor', - '/media/com_actionlogs', - '/media/com_admin', - '/media/com_associations', - '/media/com_banners', - '/media/com_cache', - '/media/com_categories', - '/media/com_config', - '/media/com_contact', - '/media/com_content', - '/media/com_contenthistory', - '/media/com_cpanel', - '/media/com_fields', - '/media/com_finder', - '/media/com_guidedtours', - '/media/com_installer', - '/media/com_joomlaupdate', - '/media/com_languages', - '/media/com_mails', - '/media/com_media', - '/media/com_menus', - '/media/com_modules', - '/media/com_scheduler', - '/media/com_tags', - '/media/com_templates', - '/media/com_users', - '/media/com_workflow', - '/media/com_wrapper', - '/media/layouts', - '/media/legacy', - '/media/mailto', - '/media/mod_articles', - '/media/mod_articles_news', - '/media/mod_languages', - '/media/mod_login', - '/media/mod_menu', - '/media/mod_quickicon', - '/media/mod_sampledata', - '/media/plg_behaviour_compat', - '/media/plg_captcha_recaptcha', - '/media/plg_captcha_recaptcha_invisible', - '/media/plg_content_vote', - '/media/plg_editors-xtd_image', - '/media/plg_editors_codemirror', - '/media/plg_editors_none', - '/media/plg_editors_tinymce', - '/media/plg_installer_folderinstaller', - '/media/plg_installer_packageinstaller', - '/media/plg_installer_urlinstaller', - '/media/plg_installer_webinstaller', - '/media/plg_media-action_crop', - '/media/plg_media-action_resize', - '/media/plg_media-action_rotate', - '/media/plg_multifactorauth_email', - '/media/plg_multifactorauth_fixed', - '/media/plg_multifactorauth_totp', - '/media/plg_multifactorauth_webauthn', - '/media/plg_multifactorauth_yubikey', - '/media/plg_quickicon_eos', - '/media/plg_quickicon_extensionupdate', - '/media/plg_quickicon_joomlaupdate', - '/media/plg_quickicon_overridecheck', - '/media/plg_quickicon_privacycheck', - '/media/plg_system_debug', - '/media/plg_system_guidedtours', - '/media/plg_system_jooa11y', - '/media/plg_system_schedulerunner', - '/media/plg_system_shortcut', - '/media/plg_system_stats', - '/media/plg_system_webauthn', - '/media/plg_user_token', - '/media/system', - '/media/templates/administrator/atum', - '/media/templates/site/cassiopeia', - '/media/vendor/accessibility', - '/media/vendor/awesomplete', - '/media/vendor/bootstrap', - '/media/vendor/choicesjs', - '/media/vendor/chosen', - '/media/vendor/codemirror', - '/media/vendor/cropperjs', - '/media/vendor/debugbar', - '/media/vendor/diff', - '/media/vendor/dragula', - '/media/vendor/es-module-shims', - '/media/vendor/focus-visible', - '/media/vendor/fontawesome-free', - '/media/vendor/hotkeysjs', - '/media/vendor/joomla-custom-elements', - '/media/vendor/jquery', - '/media/vendor/jquery-migrate', - '/media/vendor/mediaelement', - '/media/vendor/metismenujs', - '/media/vendor/minicolors', - '/media/vendor/qrcode', - '/media/vendor/roboto-fontface', - '/media/vendor/sa11y', - '/media/vendor/shepherdjs', - '/media/vendor/short-and-sweet', - '/media/vendor/skipto', - '/media/vendor/tinymce', - '/media/vendor/webcomponentsjs', - '/modules/mod_articles', - '/modules/mod_articles_archive', - '/modules/mod_articles_categories', - '/modules/mod_articles_category', - '/modules/mod_articles_latest', - '/modules/mod_articles_news', - '/modules/mod_articles_popular', - '/modules/mod_banners', - '/modules/mod_breadcrumbs', - '/modules/mod_custom', - '/modules/mod_feed', - '/modules/mod_finder', - '/modules/mod_footer', - '/modules/mod_languages', - '/modules/mod_login', - '/modules/mod_menu', - '/modules/mod_random_image', - '/modules/mod_related_items', - '/modules/mod_stats', - '/modules/mod_syndicate', - '/modules/mod_tags_popular', - '/modules/mod_tags_similar', - '/modules/mod_users_latest', - '/modules/mod_whosonline', - '/modules/mod_wrapper', - '/plugins/actionlog', - '/plugins/api-authentication', - '/plugins/authentication', - '/plugins/behaviour', - '/plugins/captcha', - '/plugins/content', - '/plugins/editors', - '/plugins/editors-xtd', - '/plugins/extension', - '/plugins/fields', - '/plugins/filesystem', - '/plugins/finder', - '/plugins/installer', - '/plugins/media-action', - '/plugins/multifactorauth', - '/plugins/privacy', - '/plugins/quickicon', - '/plugins/sampledata', - '/plugins/schemaorg', - '/plugins/system', - '/plugins/task', - '/plugins/user', - '/plugins/webservices', - '/plugins/workflow', - '/templates/cassiopeia', - '/templates/system', - ]; - - foreach ($files as $file) { - if (is_file(JPATH_ROOT . $file) && decoct(fileperms(JPATH_ROOT . $file) & 0777) === '777') { - @chmod(JPATH_ROOT . $file, 0644); - } - } - - foreach ($folders as $folder) { - if (is_dir(JPATH_ROOT . $folder)) { - if (decoct(fileperms(JPATH_ROOT . $folder) & 0777) === '777') { - @chmod(JPATH_ROOT . $folder, 0755); - } - - foreach (Folder::files(JPATH_ROOT . $folder, '.', false, true) as $file) { - if (decoct(fileperms($file) & 0777) === '777') { - @chmod($file, 0644); - } - } - } - } - - foreach ($foldersRecursive as $parentFolder) { - if (is_dir(JPATH_ROOT . $parentFolder)) { - if (decoct(fileperms(JPATH_ROOT . $parentFolder) & 0777) === '777') { - @chmod(JPATH_ROOT . $parentFolder, 0755); - } - - foreach (Folder::folders(JPATH_ROOT . $parentFolder, '.', true, true) as $folder) { - if (decoct(fileperms($folder) & 0777) === '777') { - @chmod($folder, 0755); - } - } - - foreach (Folder::files(JPATH_ROOT . $parentFolder, '.', true, true) as $file) { - if (decoct(fileperms($file) & 0777) === '777') { - @chmod($file, 0644); - } - } - } - } - } } diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-03-11.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-03-11.sql deleted file mode 100644 index 59b59432ea959..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-03-11.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS `#__utf8_conversion`; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-03-17.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-03-17.sql deleted file mode 100644 index 4f6aa1f79b567..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-03-17.sql +++ /dev/null @@ -1 +0,0 @@ -DELETE FROM `#__scheduler_tasks` WHERE `type` = 'demoTask_r1.sleep'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-12.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-12.sql deleted file mode 100644 index 882f857346fd7..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-12.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE `#__menu_types` ADD COLUMN `ordering` int NOT NULL DEFAULT 0 AFTER `client_id` /** CAN FAIL **/; -UPDATE `#__menu_types` SET `ordering` = `id` WHERE `client_id` = 0; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-25.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-25.sql deleted file mode 100644 index 897a721bfd927..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-25.sql +++ /dev/null @@ -1,28 +0,0 @@ --- --- Table structure for table `#__schemaorg` --- - -CREATE TABLE IF NOT EXISTS `#__schemaorg` ( - `id` int unsigned NOT NULL AUTO_INCREMENT, - `itemId` int unsigned, - `context` varchar(100), - `schemaType` varchar(100), - `schema` text, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci; - --- Add plugins to `#__extensions` --- -------------------------------------------------------- --- The following INSERT statement has been modified to insert --- core plugins with locked=1. --- See https://github.com/joomla/joomla-cms/pull/45821 for details. --- -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_schemaorg_blogposting', 'plugin', 'blogposting', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), -(0, 'plg_schemaorg_book', 'plugin', 'book', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 2, 0), -(0, 'plg_schemaorg_event', 'plugin', 'event', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), -(0, 'plg_schemaorg_organization', 'plugin', 'organization', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), -(0, 'plg_schemaorg_person', 'plugin', 'person', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), -(0, 'plg_schemaorg_recipe', 'plugin', 'recipe', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), -(0, 'plg_schemaorg_jobposting', 'plugin', 'jobposting', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), -(0, 'plg_system_schemaorg', 'plugin', 'schemaorg', 'system', 0, 1, 1, 0, 1, '', '{}', '', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-21.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-21.sql deleted file mode 100644 index 53a45aa687c0d..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-21.sql +++ /dev/null @@ -1,17 +0,0 @@ --- --- Attention: In the below SQL statements, the value of the filter is unescaped, i.e. uses "\\", while --- in base.sql the same value is using "\\\\". This is expected because of how JSON_REPLACE works. --- -UPDATE `#__extensions` - SET `params` = JSON_REPLACE(`params`, '$.filter' , '\\Joomla\\CMS\\Component\\ComponentHelper::filterText') - WHERE `type` = 'plugin' - AND `folder` = 'fields' - AND `element` IN ('editor', 'text', 'textarea') - AND `params` <> '' - AND JSON_EXTRACT(`params`, '$.filter') = 'JComponentHelper::filterText'; - -UPDATE `#__fields` - SET `fieldparams` = JSON_REPLACE(`fieldparams`, '$.filter' , '\\Joomla\\CMS\\Component\\ComponentHelper::filterText') - WHERE `type` IN ('editor', 'text', 'textarea') - AND `fieldparams` <> '' - AND JSON_EXTRACT(`fieldparams`, '$.filter') = 'JComponentHelper::filterText'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-26.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-26.sql deleted file mode 100644 index 61c645749148f..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-26.sql +++ /dev/null @@ -1,7 +0,0 @@ --- -------------------------------------------------------- --- The following INSERT statement has been modified to insert --- this core plugin with locked=1. --- See https://github.com/joomla/joomla-cms/pull/45821 for details. --- -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_task_globalcheckin', 'plugin', 'globalcheckin', 'task', 0, 1, 1, 0, 1, '', '{}', '', 5, 0); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-28.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-28.sql deleted file mode 100644 index 34c1d727cb1e7..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-28.sql +++ /dev/null @@ -1,13 +0,0 @@ -UPDATE `#__guidedtours` SET `extensions` = '["com_content","com_categories"]' WHERE `url` LIKE '%option=com_content%'; -UPDATE `#__guidedtours` SET `extensions` = '["com_content","com_categories"]' WHERE `url` LIKE '%option=com_categories%'; -UPDATE `#__guidedtours` SET `extensions` = '["com_menus"]' WHERE `url` LIKE '%com_menus%'; -UPDATE `#__guidedtours` SET `extensions` = '["com_tags"]' WHERE `url` LIKE '%com_tags%'; -UPDATE `#__guidedtours` SET `extensions` = '["com_banners"]' WHERE `url` LIKE '%com_banners%'; -UPDATE `#__guidedtours` SET `extensions` = '["com_contact"]' WHERE `url` LIKE '%com_contact%'; -UPDATE `#__guidedtours` SET `extensions` = '["com_newsfeeds"]' WHERE `url` LIKE '%com_newsfeeds%'; -UPDATE `#__guidedtours` SET `extensions` = '["com_finder"]' WHERE `url` LIKE '%com_finder%'; -UPDATE `#__guidedtours` SET `extensions` = '["com_users"]' WHERE `url` LIKE '%com_users%'; - -UPDATE `#__update_sites` - SET `location` = 'https://update.joomla.org/language/translationlist_5.xml' - WHERE `location` = 'https://update.joomla.org/language/translationlist_4.xml'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-29.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-29.sql deleted file mode 100644 index 85790c1132a04..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-29.sql +++ /dev/null @@ -1,14 +0,0 @@ -ALTER TABLE `#__guidedtours` ADD COLUMN `uid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL AFTER `title`/** CAN FAIL **/; -ALTER TABLE `#__guidedtours` ADD INDEX `idx_uid` (`uid`(191)) /** CAN FAIL **/; - -UPDATE `#__guidedtours` SET `uid` = 'joomla-guidedtours' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-guidedtoursteps' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURSTEPS_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-articles' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_ARTICLES_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-categories' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_CATEGORIES_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-menus' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_MENUS_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-tags' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_TAGS_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-banners' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_BANNERS_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-contacts' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_CONTACTS_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-newsfeeds' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_NEWSFEEDS_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-smartsearch' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_SMARTSEARCH_TITLE'; -UPDATE `#__guidedtours` SET `uid` = 'joomla-users' WHERE `title` = 'COM_GUIDEDTOURS_TOUR_USERS_TITLE'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-30.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-30.sql deleted file mode 100644 index 8b144004d1147..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-08-30.sql +++ /dev/null @@ -1,3 +0,0 @@ -UPDATE `#__extensions` - SET `locked` = 0 - WHERE `type` = 'plugin' AND `element` = 'recaptcha_invisible' AND `folder` = 'captcha'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-02.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-02.sql deleted file mode 100644 index 220f69cf47de2..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-02.sql +++ /dev/null @@ -1,14 +0,0 @@ -INSERT INTO `#__extensions` (`name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `checked_out`, `checked_out_time`, `ordering`, `state`) VALUES -('plg_task_deleteactionlogs', 'plugin', 'deleteactionlogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), -('plg_task_privacyconsent', 'plugin', 'privacyconsent', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), -('plg_task_rotatelogs', 'plugin', 'rotatelogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), -('plg_task_sessiongc', 'plugin', 'sessiongc', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), -('plg_task_updatenotification', 'plugin', 'updatenotification', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0); - -INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subject`, `body`, `htmlbody`, `attachments`, `params`) VALUES -('plg_task_privacyconsent.request.reminder', 'plg_task_privacyconsent', '', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_BODY', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), -('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'); - -DELETE FROM `#__mail_templates` WHERE `template_id` IN ('plg_system_privacyconsent.request.reminder', 'plg_system_updatenotification.mail'); - -DELETE FROM `#__postinstall_messages` WHERE `condition_file` = 'site://plugins/system/updatenotification/postinstall/updatecachetime.php'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-06.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-06.sql deleted file mode 100644 index de42fa7b0b92f..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-06.sql +++ /dev/null @@ -1,5 +0,0 @@ -UPDATE `#__scheduler_tasks` SET `title` = 'Delete Action Logs' WHERE `type` = 'delete.actionlogs' AND `title` = 'DeleteActionLogs'; -UPDATE `#__scheduler_tasks` SET `title` = 'Privacy Consent' WHERE `type` = 'privacy.consent' AND `title` = 'PrivacyConsent'; -UPDATE `#__scheduler_tasks` SET `title` = 'Rotate Logs' WHERE `type` = 'rotation.logs' AND `title` = 'RotateLogs'; -UPDATE `#__scheduler_tasks` SET `title` = 'Session GC' WHERE `type` = 'session.gc' AND `title` = 'SessionGC'; -UPDATE `#__scheduler_tasks` SET `title` = 'Update Notification' WHERE `type` = 'update.notification' AND `title` = 'UpdateNotification'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-09.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-09.sql deleted file mode 100644 index 9d90c87e0dd1a..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-09.sql +++ /dev/null @@ -1,5 +0,0 @@ --- Add com_fields to action logs -INSERT INTO `#__action_logs_extensions` (`extension`) VALUES ('com_fields'); - -INSERT INTO `#__action_log_config` (`type_title`, `type_alias`, `id_holder`, `title_holder`, `table_name`, `text_prefix`) VALUES -('field', 'com_fields.field', 'id', 'title', '#__fields', 'PLG_ACTIONLOG_JOOMLA'); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-11.sql b/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-11.sql deleted file mode 100644 index 1a7eec216bb13..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-09-11.sql +++ /dev/null @@ -1 +0,0 @@ -UPDATE `#__extensions` SET `enabled` = 1 WHERE `type` = 'plugin' AND `element` = 'schedulerunner' AND `folder` = 'system'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2023-11-28.sql b/administrator/components/com_admin/sql/updates/mysql/5.1.0-2023-11-28.sql deleted file mode 100644 index b29feba9fa8d8..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2023-11-28.sql +++ /dev/null @@ -1,7 +0,0 @@ --- -------------------------------------------------------- --- The following INSERT statement has been modified to insert --- this core plugin with locked=1. --- See https://github.com/joomla/joomla-cms/pull/45821 for details. --- -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_schemaorg_article', 'plugin', 'article', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-01-04.sql b/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-01-04.sql deleted file mode 100644 index 38f38ee1ec202..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-01-04.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE `#__fields_values` MODIFY `value` MEDIUMTEXT; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-10.sql b/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-10.sql deleted file mode 100644 index 946516cde5104..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-10.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE `#__guidedtour_steps` ADD COLUMN `params` text NULL /** CAN FAIL **/; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-24.sql b/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-24.sql deleted file mode 100644 index 3716a866f8d64..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-24.sql +++ /dev/null @@ -1,34 +0,0 @@ --- --- Table structure for table `#__tuf_metadata` --- - -CREATE TABLE IF NOT EXISTS `#__tuf_metadata` ( - `id` int NOT NULL AUTO_INCREMENT, - `update_site_id` int DEFAULT 0, - `root` text DEFAULT NULL, - `targets` text DEFAULT NULL, - `snapshot` text DEFAULT NULL, - `timestamp` text DEFAULT NULL, - `mirrors` text DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci COMMENT='Secure TUF Updates'; - --- -------------------------------------------------------- --- The following INSERT statement has been modified to avoid an SQL error --- when there is more than 1 update site for the Joomla core. --- See https://github.com/joomla/joomla-cms/pull/43169 for details. --- -INSERT INTO `#__tuf_metadata` (`update_site_id`, `root`) -SELECT ue.`update_site_id`, - '{"signed":{"_type":"root","spec_version":"1.0","version":2,"expires":"2025-03-02T11:22:17Z","keys":{"07eb082f367c034a95878687f6648aa76d93652b6ee73e58817053d89af6c44f":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"9b2af2d9b9727227735253d795bd27ea8f0e294a5f3603e822dc5052b44802b9"}},"1b1b1dd55b2c1c7258714cf1c1ae06f23e4607b28c762d016a9d81c48ffe5669":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"a18e5ebabc19d5d5984b601a292ece61ba3662ab2d071dc520da5bd4f8948799"}},"2dcaf3d0e552f150792f7c636d45429246dcfa34ac35b46a44f5c87cd17d457e":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"cb0a7a131961a20edea051d6dc2b091fb650bd399bd8514adb67b3c60db9f8f9"}},"31dd7c7290d664c9b88c0dead2697175293ea7df81b7f24153a37370fd3901c3":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"589d029a68b470deff1ca16dbf3eea6b5b3fcba0ae7bb52c468abc7fb058b2a2"}},"9e41a9d62d94c6a1c8a304f62c5bd72d84a9f286f27e8327cedeacb09e5156cc":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"6043c8bacc76ac5c9750f45454dd865c6ca1fc57d69e14cc192cfd420f6a66a9"}}},"roles":{"root":{"keyids":["1b1b1dd55b2c1c7258714cf1c1ae06f23e4607b28c762d016a9d81c48ffe5669","2dcaf3d0e552f150792f7c636d45429246dcfa34ac35b46a44f5c87cd17d457e"],"threshold":1},"snapshot":{"keyids":["07eb082f367c034a95878687f6648aa76d93652b6ee73e58817053d89af6c44f","2dcaf3d0e552f150792f7c636d45429246dcfa34ac35b46a44f5c87cd17d457e"],"threshold":1},"targets":{"keyids":["31dd7c7290d664c9b88c0dead2697175293ea7df81b7f24153a37370fd3901c3"],"threshold":1},"timestamp":{"keyids":["9e41a9d62d94c6a1c8a304f62c5bd72d84a9f286f27e8327cedeacb09e5156cc"],"threshold":1}},"consistent_snapshot":true},"signatures":[{"keyid":"2dcaf3d0e552f150792f7c636d45429246dcfa34ac35b46a44f5c87cd17d457e","sig":"2a225a560ec0837b721d4c5e379fedbd3c7c9079a94e6b31e47e0184c8b95421b6036b4286c5d90f29ab4c468d79a712fdb65e96511394ceb3aa8e2b3983a501"},{"keyid":"1b1b1dd55b2c1c7258714cf1c1ae06f23e4607b28c762d016a9d81c48ffe5669","sig":"8ce0b2a7bdc1e6dcba12081f440510df0a593c072dcf591631c2dd0f456844a7da63be8e8ac31ffbddf42641fde84dc733a336031d182c2163b4c1eaf2117005"}]}' - FROM `#__update_sites_extensions` AS ue JOIN `#__extensions` AS e ON (e.`extension_id` = ue.`extension_id`) - WHERE e.`type`='file' AND e.`element`='joomla'; - --- -------------------------------------------------------- --- The following UPDATE statement has been modified to avoid an SQL error --- when there is more than 1 update site for the Joomla core. --- See https://github.com/joomla/joomla-cms/pull/42988 for details. --- -UPDATE `#__update_sites` - SET `type` = 'tuf', `location` = 'https://update.joomla.org/cms/' - WHERE `update_site_id` IN (SELECT ue.`update_site_id` FROM `#__update_sites_extensions` AS ue JOIN `#__extensions` AS e ON (e.`extension_id` = ue.`extension_id`) WHERE e.`type`='file' AND e.`element`='joomla'); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-25.sql b/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-25.sql deleted file mode 100644 index 2819a1016ef08..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-02-25.sql +++ /dev/null @@ -1,7 +0,0 @@ --- -------------------------------------------------------- --- The following INSERT statement has been modified to insert --- this core plugin with locked=1. --- See https://github.com/joomla/joomla-cms/pull/45821 for details. --- -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_schemaorg_custom', 'plugin', 'custom', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-03-08.sql b/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-03-08.sql deleted file mode 100644 index 458403a3454a4..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-03-08.sql +++ /dev/null @@ -1,13 +0,0 @@ -INSERT IGNORE INTO `#__guidedtour_steps` (`tour_id`, `title`, `published`, `description`, `ordering`, `position`, `target`, `type`, `interactive_type`, `url`, `created`, `created_by`, `modified`, `modified_by`, `language`) VALUES -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_MENUS_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_MENUS_DESCRIPTION', 1, 'right', '#sidebarmenu', 0, 1, '', CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, '*'), -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_QUICKACCESS_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_QUICKACCESS_DESCRIPTION', 2, 'center', '', 0, 1, '', CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, '*'), -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_NOTIFICATIONS_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_NOTIFICATIONS_DESCRIPTION', 3, 'left', '.quickicons-for-update_quickicon .card', 0, 1, '', CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, '*'), -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_TOPBAR_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_TOPBAR_DESCRIPTION', 4, 'bottom', '#header', 0, 1, '', CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, '*'), -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_FINALWORDS_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_FINALWORDS_DESCRIPTION', 5, 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, '*'); - -ALTER TABLE `#__guidedtours` ADD COLUMN `autostart` int NOT NULL DEFAULT 0 /** CAN FAIL **/; - -INSERT IGNORE INTO `#__guidedtours` (`title`, `uid`, `description`, `ordering`, `extensions`, `url`, `created`, `created_by`, `modified`, `modified_by`, `published`, `language`, `access`, `autostart`) VALUES -('COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_TITLE', 'joomla-welcome', 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_DESCRIPTION', 1, '["com_cpanel"]', 'administrator/index.php', CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, 1, '*', 1, 0); - -UPDATE `#__guidedtour_steps` SET `tour_id` = LAST_INSERT_ID() WHERE `tour_id`=0; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-03-28.sql b/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-03-28.sql deleted file mode 100644 index e76716010f9fd..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.1.0-2024-03-28.sql +++ /dev/null @@ -1,12 +0,0 @@ --- --- Add post-installation message about Brotli compression in .htaccess --- --- This statement had to be modified to prevent duplicate postinstall messages --- when updating from 4.4. --- See https://github.com/joomla/joomla-cms/pull/43182 for details. --- -INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) -SELECT `extension_id`, 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_BROTLI_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_BROTLI_DESCRIPTION', '', 'com_admin', 1, 'message', '', '', 'admin://components/com_admin/postinstall/htaccessbrotli.php', 'admin_postinstall_htaccessbrotli_condition', '5.1.0', 1 - FROM `#__extensions` - WHERE `name` = 'files_joomla' - AND (SELECT COUNT(a.`postinstall_message_id`) FROM `#__postinstall_messages` a WHERE a.`title_key` = 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_BROTLI_TITLE') = 0; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.1.1-2024-04-18.sql b/administrator/components/com_admin/sql/updates/mysql/5.1.1-2024-04-18.sql deleted file mode 100644 index 8e59290ac5607..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.1.1-2024-04-18.sql +++ /dev/null @@ -1,10 +0,0 @@ --- --- Add a default value for the colorScheme in the Atum template on Joomla update --- only when a value is not already set. --- New installs will have the default value set in the installation sql. --- - -UPDATE `#__template_styles` -SET `params` = JSON_SET(`params`, '$.colorScheme', 'os') -WHERE `template` = 'atum' -AND JSON_EXTRACT(`params`, '$.colorScheme') IS NULL; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-07-02.sql b/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-07-02.sql deleted file mode 100644 index 23e79da2aad4d..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-07-02.sql +++ /dev/null @@ -1,3 +0,0 @@ --- Add mod_articles module -INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`) VALUES -(0, 'mod_articles', 'module', 'mod_articles', '', 0, 1, 0, 0, 1, '', '', ''); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-07-19.sql b/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-07-19.sql deleted file mode 100644 index 284938a777e2d..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-07-19.sql +++ /dev/null @@ -1,7 +0,0 @@ --- --- Add the Guided Tours selectable option to the User Action Logs --- -INSERT INTO `#__action_logs_extensions` (`extension`) VALUES ('com_guidedtours'); - -INSERT INTO `#__action_log_config` (`type_title`, `type_alias`, `id_holder`, `title_holder`, `table_name`, `text_prefix`) VALUES -('guidedtour', 'com_guidedtours.state', 'id', 'title', '#__guidedtours', 'PLG_ACTIONLOG_JOOMLA'); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-08-22.sql b/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-08-22.sql deleted file mode 100644 index 0876fa5024ede..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-08-22.sql +++ /dev/null @@ -1,6 +0,0 @@ -INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `published`, `language`, `note`, `access`, `uid`, `autostart`, `created`, `created_by`, `modified`, `modified_by`) VALUES -('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-2', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0); -INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '{"required":1,"requiredvalue":""}', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 - FROM `#__guidedtours` - WHERE `uid` = 'joomla-whatsnew-5-2'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-09-17.sql b/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-09-17.sql deleted file mode 100644 index 26b21f399c57a..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.2.0-2024-09-17.sql +++ /dev/null @@ -1,8 +0,0 @@ -UPDATE `#__guidedtour_steps` -SET `ordering` = `ordering` + 1 -WHERE `title` IN ('COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_SAVECLOSE_TITLE', 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_CONGRATULATIONS_TITLE'); - -INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`, `ordering`) -SELECT 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_AUTOSTART_TITLE', 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_AUTOSTART_DESCRIPTION', 'bottom', '#jform_autostart0', 2, 3, '', 1, '*', '', `tour_id`, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, `ordering` + 1 - FROM `#__guidedtour_steps` - WHERE `title` = 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_COMPONENT_TITLE'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.2.2-2024-09-24.sql b/administrator/components/com_admin/sql/updates/mysql/5.2.2-2024-09-24.sql deleted file mode 100644 index 1592aba38893f..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.2.2-2024-09-24.sql +++ /dev/null @@ -1,7 +0,0 @@ -UPDATE `#__assets` SET `title` = 'PUBLISH' WHERE `name` LIKE 'com_content.transition.%' AND `title` = 'Publish'; -UPDATE `#__assets` SET `title` = 'UNPUBLISH' WHERE `name` LIKE 'com_content.transition.%' AND `title` = 'Unpublish'; -UPDATE `#__assets` SET `title` = 'TRASH' WHERE `name` LIKE 'com_content.transition.%' AND `title` = 'Trash'; -UPDATE `#__assets` SET `title` = 'ARCHIVE' WHERE `name` LIKE 'com_content.transition.%' AND `title` = 'Archive'; -UPDATE `#__assets` SET `title` = 'FEATURE' WHERE `name` LIKE 'com_content.transition.%' AND `title` = 'Feature'; -UPDATE `#__assets` SET `title` = 'UNFEATURE' WHERE `name` LIKE 'com_content.transition.%' AND `title` = 'Unfeature'; -UPDATE `#__assets` SET `title` = 'PUBLISH_AND_FEATURE' WHERE `name` LIKE 'com_content.transition.%' AND `title` = 'Publish & Feature'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.2.3-2025-01-09.sql b/administrator/components/com_admin/sql/updates/mysql/5.2.3-2025-01-09.sql deleted file mode 100644 index 8620500fb8c00..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.2.3-2025-01-09.sql +++ /dev/null @@ -1,3 +0,0 @@ -UPDATE `#__mail_templates` -SET `params` = '{"tags":["messages","message","date","extension","username"]}' -WHERE `template_id` = 'com_actionlogs.notification'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-10-13.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-10-13.sql deleted file mode 100644 index 6db2da7c57115..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-10-13.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE `#__fields` MODIFY `fieldparams` MEDIUMTEXT NOT NULL; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-10-26.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-10-26.sql deleted file mode 100644 index b2e6c94cd0fcf..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-10-26.sql +++ /dev/null @@ -1,20 +0,0 @@ --- --- Table structure for table `#__scheduler_logs` --- - -CREATE TABLE IF NOT EXISTS `#__scheduler_logs` ( - `id` int unsigned NOT NULL AUTO_INCREMENT, - `taskname` varchar(255) NOT NULL DEFAULT '', - `tasktype` varchar(128) NOT NULL COMMENT 'unique identifier for job defined by plugin', - `duration` DECIMAL(5,3) NOT NULL, - `jobid` int UNSIGNED NOT NULL, - `taskid` int UNSIGNED NOT NULL, - `exitcode` int NOT NULL, - `lastdate` datetime COMMENT 'Timestamp of last run', - `nextdate` datetime COMMENT 'Timestamp of next (planned) run, referred for execution on trigger', - PRIMARY KEY (id), - KEY `idx_taskname` (`taskname`), - KEY `idx_tasktype` (`tasktype`), - KEY `idx_lastdate` (`lastdate`), - KEY `idx_nextdate` (`nextdate`) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 DEFAULT COLLATE = utf8mb4_unicode_ci; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-12-09.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-12-09.sql deleted file mode 100644 index ba1c2228248ed..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-12-09.sql +++ /dev/null @@ -1,2 +0,0 @@ -INSERT INTO `#__action_log_config` (`type_title`, `type_alias`, `id_holder`, `title_holder`, `table_name`, `text_prefix`) VALUES -('contact', 'com_contact.form', 'id', 'name', '#__contact_details', 'PLG_ACTIONLOG_JOOMLA'); \ No newline at end of file diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-12-19.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-12-19.sql deleted file mode 100644 index ff569052be73d..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2024-12-19.sql +++ /dev/null @@ -1,6 +0,0 @@ --- -------------------------------------------------------- --- The following statement which was introduced with 5.3.0-alpha3 --- has been disabled as it was reverted with 5.3.0-beta1. --- See https://github.com/joomla/joomla-cms/pull/44845 for details. --- --- ALTER TABLE `#__action_logs_users` ADD COLUMN `exclude_self` tinyint NOT NULL DEFAULT 0; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-02-09.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-02-09.sql deleted file mode 100644 index 55ae2550444fe..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-02-09.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE `#__action_logs_users` DROP COLUMN `exclude_self` /** CAN FAIL **/; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-02-22.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-02-22.sql deleted file mode 100644 index 426e088ca8979..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-02-22.sql +++ /dev/null @@ -1,3 +0,0 @@ --- Add plg_extension_joomlaupdate plugin -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_extension_joomlaupdate', 'plugin', 'joomlaupdate', 'extension', 0, 1, 1, 0, 1, '', '', '', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql deleted file mode 100644 index 2eedbb010e52d..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.0-2025-03-14.sql +++ /dev/null @@ -1,10 +0,0 @@ --- disable autostart for the previous tour -UPDATE `#__guidedtours` SET `autostart` = 0 WHERE `uid` = 'joomla-whatsnew-5-2'; - -INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `published`, `language`, `note`, `access`, `uid`, `autostart`, `created`, `created_by`, `modified`, `modified_by`) VALUES -('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-3', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0); - -INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 - FROM `#__guidedtours` - WHERE `uid` = 'joomla-whatsnew-5-3'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.3.4-2025-09-19.sql b/administrator/components/com_admin/sql/updates/mysql/5.3.4-2025-09-19.sql deleted file mode 100644 index cc18de1dfaf17..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.3.4-2025-09-19.sql +++ /dev/null @@ -1,7 +0,0 @@ -UPDATE `#__content_types` -SET `field_mappings` = JSON_SET(`field_mappings`, '$.common.core_created_user_id', 'created_by') -WHERE `type_alias` = 'com_content.article'; - -UPDATE `#__content_types` -SET `field_mappings` = JSON_SET(`field_mappings`, '$.common.core_created_by_alias', 'created_by_alias') -WHERE `type_alias` = 'com_content.article'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-04-23.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-04-23.sql deleted file mode 100644 index edad0d365e845..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-04-23.sql +++ /dev/null @@ -1,3 +0,0 @@ -INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) -SELECT 0, 'plg_behaviour_compat6', 'plugin', 'compat6', 'behaviour', 0, 1, 1, 0, 1, '', '{"classes_aliases":"1","legacy_classes":"1"}', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'compat6' AND e.`folder` = 'behaviour' AND e.`client_id` = 0); diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql b/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql deleted file mode 100644 index bbf6f3453946e..0000000000000 --- a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-05-10.sql +++ /dev/null @@ -1,27 +0,0 @@ -INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) -SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'autoupdate' AND e.`folder` = 'quickicon' AND e.`client_id` = 0); - -INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) -SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'joomlaupdate' AND e.`folder` = 'webservices' AND e.`client_id` = 0); - -INSERT IGNORE INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subject`, `body`, `htmlbody`, `attachments`, `params`) VALUES -('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), -('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'); - --- add post-installation message for automated updates -INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description_key`, `action_key`, `language_extension`, `language_client_id`, `type`, `action_file`, `action`, `condition_file`, `condition_method`, `version_introduced`, `enabled`) -SELECT `extension_id`, 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM `#__extensions` WHERE `name` = 'files_joomla'; - --- disable autostart for the previous tour -UPDATE `#__guidedtours` SET `autostart` = 0 WHERE `uid` = 'joomla-whatsnew-5-3'; - -INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `published`, `language`, `note`, `access`, `uid`, `autostart`, `created`, `created_by`, `modified`, `modified_by`) -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-4', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 -WHERE NOT EXISTS (SELECT * FROM `#__guidedtours` g WHERE g.`uid` = 'joomla-whatsnew-5-4'); - -INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`) -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX(`id`), CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 -FROM `#__guidedtours` -WHERE `uid` = 'joomla-whatsnew-5-4'; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2024-08-11.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2024-08-11.sql new file mode 100644 index 0000000000000..fa9269cf76003 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2024-08-11.sql @@ -0,0 +1,6 @@ +-- Update link to featured + +UPDATE `#__menu` +SET `link` = 'index.php?option=com_content&view=articles&filter[featured]=1' +WHERE `link` = 'index.php?option=com_content&view=featured' +AND `client_id` = 1; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-03-25.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-03-25.sql new file mode 100644 index 0000000000000..16ac7a6efe7f2 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-03-25.sql @@ -0,0 +1,2 @@ +INSERT IGNORE INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subject`, `body`, `htmlbody`, `attachments`, `params`) VALUES +('plg_content_joomla.newarticle', 'plg_content_joomla', '', 'PLG_CONTENT_JOOMLA_NEW_ARTICLE_SUBJECT', 'PLG_CONTENT_JOOMLA_NEW_ARTICLE_BODY', '', '', '{"tags":["sitename","name","email","title","url"]}'); diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-05-20.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-05-20.sql new file mode 100644 index 0000000000000..64bf420d9bcd1 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-05-20.sql @@ -0,0 +1,3 @@ +UPDATE `#__extensions` + SET `params` = '' + WHERE `type` = 'plugin' AND `element` = 'stats' AND `folder` = 'system'; diff --git a/administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-08-02.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-08-02.sql similarity index 100% rename from administrator/components/com_admin/sql/updates/mysql/5.4.0-2025-08-02.sql rename to administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-08-02.sql diff --git a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-29.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-08-16.sql similarity index 53% rename from administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-29.sql rename to administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-08-16.sql index ba16b0157b838..893721d854feb 100644 --- a/administrator/components/com_admin/sql/updates/mysql/5.0.0-2023-07-29.sql +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-08-16.sql @@ -1,3 +1,3 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) -SELECT 0, 'plg_behaviour_compat', 'plugin', 'compat', 'behaviour', 0, 1, 1, 0, 1, '', '{"classes_aliases":"1","es5_assets":"1"}', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'compat' AND e.`folder` = 'behaviour' AND e.`client_id` = 0); +SELECT 0, 'plg_fields_note', 'plugin', 'note', 'fields', 0, 1, 1, 0, 1, '', '{"class":"alert alert-info","heading":"h4"}', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'note' AND e.`folder` = 'fields' AND e.`client_id` = 0); diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-08-17.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-08-17.sql new file mode 100644 index 0000000000000..d3f9597ca175a --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-08-17.sql @@ -0,0 +1,3 @@ +INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) +SELECT 0, 'plg_fields_number', 'plugin', 'number', 'fields', 0, 1, 1, 0, 1, '', '{"min":"1.0","max":"100.0","step":"0.1","currency":"0","position":"0","decimals":"2"}', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'number' AND e.`folder` = 'fields' AND e.`client_id` = 0); diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-05.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-05.sql new file mode 100644 index 0000000000000..f62641b6b130a --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-05.sql @@ -0,0 +1,7 @@ +INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) +SELECT 0, 'cassiopeia_extended', 'template', 'cassiopeia_extended', '', 0, 1, 1, 0, 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","systemFontBody":"","systemFontHeading":"","colorName":"colors_standard","fluidContainer":"0","stickyHeader":"0","backTop":"0","colorSettings":"0","headerbg":"rgb(193, 205, 207)","headercolor":"rgb(23, 23, 23)","bodybg":"rgb(254, 254, 254)","bodycolor":"rgb(23, 23, 23)","linkcolor":"rgb(29, 121, 137)","linkcolorh":"rgb(14, 59, 67)","btnbg":"rgb(206, 60, 55)","btnbgh":"rgb(131, 35, 32)","btncolor":"rgb(254, 254, 254)","btncolorh":"rgb(254, 254, 254)","footerbg":"rgb(29, 121, 137)","footercolor":"rgb(254, 254, 254)","fontSettings":"0","bodysize":"1","h1size":"2","h2size":"1.7","h3size":"1.5"}', '', 0, 0 +WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'template' AND e.`element` = 'cassiopeia_extended' AND e.`client_id` = 0); + +INSERT INTO `#__template_styles` (`template`, `client_id`, `home`, `title`, `inheritable`, `parent`, `params`) +SELECT 'cassiopeia_extended', 0, '0', 'Cassiopeia Extended - Default', 0, 'cassiopeia', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","systemFontBody":"","systemFontHeading":"","colorName":"colors_standard","fluidContainer":"0","stickyHeader":"0","backTop":"0","colorSettings":"0","headerbg":"rgb(193, 205, 207)","headercolor":"rgb(23, 23, 23)","bodybg":"rgb(254, 254, 254)","bodycolor":"rgb(23, 23, 23)","linkcolor":"rgb(29, 121, 137)","linkcolorh":"rgb(14, 59, 67)","btnbg":"rgb(206, 60, 55)","btnbgh":"rgb(131, 35, 32)","btncolor":"rgb(254, 254, 254)","btncolorh":"rgb(254, 254, 254)","footerbg":"rgb(29, 121, 137)","footercolor":"rgb(254, 254, 254)","fontSettings":"0","bodysize":"1","h1size":"2","h2size":"1.7","h3size":"1.5"}' +WHERE NOT EXISTS (SELECT * FROM `#__template_styles` t WHERE t.`template` = 'cassiopeia_extended' AND t.`client_id` = 0 AND t.`inheritable` = 0 AND t.`parent` = 'cassiopeia'); diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-16.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-16.sql new file mode 100644 index 0000000000000..21c81bd3d6e09 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-16.sql @@ -0,0 +1,6 @@ +-- uninstall previous what's new tours +DELETE FROM `#__guidedtour_steps` + WHERE `tour_id` IN (SELECT `id` FROM `#__guidedtours` WHERE `uid` IN ('joomla-whatsnew-5-2', 'joomla-whatsnew-5-3', 'joomla-whatsnew-5-4')); + +DELETE FROM `#__guidedtours` + WHERE `uid` IN ('joomla-whatsnew-5-2', 'joomla-whatsnew-5-3', 'joomla-whatsnew-5-4'); diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-17.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-17.sql new file mode 100644 index 0000000000000..a7ca699f6695d --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-17.sql @@ -0,0 +1,13 @@ +INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `published`, `language`, `note`, `access`, `uid`, `autostart`, `created`, `created_by`, `modified`, `modified_by`) +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-6-0', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 +WHERE NOT EXISTS (SELECT * FROM `#__guidedtours` g WHERE g.`uid` = 'joomla-whatsnew-6-0'); + +INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `created`, `created_by`, `modified`, `modified_by`, `tour_id`) +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_0_DESCRIPTION', 'center', '', 0, 1, '', 1, '*', '', '{"required":1,"requiredvalue":""}', CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, MAX(`id`) + FROM `#__guidedtours` + WHERE `uid` = 'joomla-whatsnew-6-0'; + +INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `created`, `created_by`, `modified`, `modified_by`, `tour_id`) +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_1_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_1_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, MAX(`id`) + FROM `#__guidedtours` + WHERE `uid` = 'joomla-whatsnew-6-0'; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-23.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-23.sql new file mode 100644 index 0000000000000..6e81551f3530f --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-23.sql @@ -0,0 +1,3 @@ +UPDATE `#__update_sites` + SET `location` = 'https://update.joomla.org/language/translationlist_6.xml' + WHERE `location` = 'https://update.joomla.org/language/translationlist_5.xml'; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-26.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-26.sql new file mode 100644 index 0000000000000..9ab43e38ab2b2 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-09-26.sql @@ -0,0 +1,32 @@ +-- Update content types for lookup tags + +UPDATE `#__content_types` +SET `content_history_options` = JSON_ARRAY_APPEND( + `content_history_options`, + '$.displayLookup', + JSON_OBJECT( + 'sourceColumn', 'tags', + 'targetTable', '#__tags', + 'targetColumn', 'id', + 'displayColumn', 'title' + ) + ) +WHERE `type_alias` IN ( + 'com_content.article', + 'com_contact.contact', + 'com_newsfeeds.newsfeed', + 'com_content.category', + 'com_contact.category', + 'com_newsfeeds.category', + 'com_banners.category', + 'com_users.category' + ) +AND NOT JSON_CONTAINS( + JSON_EXTRACT(`content_history_options`, '$.displayLookup'), + JSON_OBJECT( + 'sourceColumn', 'tags', + 'targetTable', '#__tags', + 'targetColumn', 'id', + 'displayColumn', 'title' + ) + ); diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-10-11.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-10-11.sql new file mode 100644 index 0000000000000..18fbe9aaa21a6 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.0-2025-10-11.sql @@ -0,0 +1,5 @@ +ALTER TABLE `#__history` + ADD COLUMN `is_current` TINYINT NOT NULL DEFAULT 0 /** CAN FAIL **/; +ALTER TABLE `#__history` + ADD COLUMN `is_legacy` TINYINT NOT NULL DEFAULT 0 /** CAN FAIL **/; +UPDATE `#__history` SET `is_legacy` = 1; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.0.1-2025-10-29.sql b/administrator/components/com_admin/sql/updates/mysql/6.0.1-2025-10-29.sql new file mode 100644 index 0000000000000..677a4624912f5 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.0.1-2025-10-29.sql @@ -0,0 +1,14 @@ +UPDATE `#__menu` +SET `params` = JSON_SET(`params`, + JSON_UNQUOTE(JSON_SEARCH(`params`, 'one', ' ', NULL, '$.featured_categories[*]')), + '' + ) +WHERE JSON_VALID(`params`) = 1 + AND JSON_SEARCH(`params`, 'one', ' ', NULL, '$.featured_categories[*]') IS NOT NULL + AND `type` = 'component' + AND `link` = 'index.php?option=com_content&view=featured'; + +UPDATE `#__menu` +SET `link` = REPLACE(`link`, '&catid[0]= ', '&catid[0]=') +WHERE `type` = 'component' + AND `link` LIKE 'index.php?option=com_content&view=archive&catid[0]= %'; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.1.0-2025-10-30.sql b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2025-10-30.sql new file mode 100644 index 0000000000000..34c0bbce1704c --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2025-10-30.sql @@ -0,0 +1,8 @@ +-- +-- Add a template tag for ip_address on Joomla update. +-- New installs will have the default value set in the installation support sql. +-- + +UPDATE `#__mail_templates` +SET `params` = '{"tags":["messages","message","date","extension","username","ip_address"]}' +WHERE `template_id` = 'com_actionlogs.notification'; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.1.0-2025-11-29.sql b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2025-11-29.sql new file mode 100644 index 0000000000000..45073758a6543 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2025-11-29.sql @@ -0,0 +1,3 @@ +INSERT INTO `#__extensions` (`name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) +SELECT 'plg_captcha_powcaptcha', 'plugin', 'powcaptcha', 'captcha', 0, 1, 1, 0, 1, '', '{}', '', 0, 0 +WHERE NOT EXISTS (SELECT * FROM `#__extensions` e WHERE e.`type` = 'plugin' AND e.`element` = 'powcaptcha' AND e.`folder` = 'captcha' AND e.`client_id` = 0); diff --git a/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-01-29.sql b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-01-29.sql new file mode 100644 index 0000000000000..a6d0c2bcd6ff4 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-01-29.sql @@ -0,0 +1,7 @@ +-- -------------------------------------------------------- +-- The following statement which was introduced with 6.1.0-beta1 +-- has been disabled as it was replaced in 6.1.0-beta3 with +-- a new statement in file "6.1.0-2026-03-10.sql". +-- See https://github.com/joomla/joomla-cms/pull/47361 for details. +-- +-- INSERT INTO `#__content_types` (`type_id`, `type_title`, `type_alias`, `table`, `rules`, `field_mappings`, `router`, `content_history_options`) VALUES (14, 'Module', 'com_modules.module', '{"special":{"dbtable":"#__modules","key":"id","type":"Module","prefix":"Joomla\\\\CMS\\\\Table\\\\"}}', '', '{}', '', '{"formFile":"administrator\\/components\\/com_modules\\/forms\\/module.xml", "hideFields":["checked_out", "checked_out_time", "publish_up", "publish_down"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"checked_out", "targetTable":"#__users", "targetColumn":"id", "displayColumn":"name"}]}'); diff --git a/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-02-06.sql b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-02-06.sql new file mode 100644 index 0000000000000..3d262cb076b42 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-02-06.sql @@ -0,0 +1,5 @@ +-- +-- Add position column to workflow stages table +-- + +ALTER TABLE `#__workflow_stages` ADD COLUMN `position` text NULL AFTER `default` /** CAN FAIL **/; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-03-07.sql b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-03-07.sql new file mode 100644 index 0000000000000..39da8437bb774 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-03-07.sql @@ -0,0 +1,15 @@ +UPDATE `#__extensions` + SET `params` = JSON_REPLACE(`params`, '$.html_height' , '550px') + WHERE `type` = 'plugin' + AND `folder` = 'editors' + AND `element` = 'tinymce' + AND `params` <> '' + AND JSON_EXTRACT(`params`, '$.html_height') = '550'; + +UPDATE `#__extensions` + SET `params` = JSON_REPLACE(`params`, '$.html_width' , '100%') + WHERE `type` = 'plugin' + AND `folder` = 'editors' + AND `element` = 'tinymce' + AND `params` <> '' + AND JSON_EXTRACT(`params`, '$.html_width') = '750'; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-03-10.sql b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-03-10.sql new file mode 100644 index 0000000000000..491171e27e291 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-03-10.sql @@ -0,0 +1,13 @@ +-- -------------------------------------------------------- +-- The following statement replaces the statement which has been disabled +-- in file "6.1.0-2026-01-29.sql" with 6.1.0-beta3. +-- See https://github.com/joomla/joomla-cms/pull/47361 for details. +-- +INSERT INTO `#__content_types` (`type_title`, `type_alias`, `table`, `rules`, `field_mappings`, `router`, `content_history_options`) +SELECT 'Module', 'com_modules.module', '{"special":{"dbtable":"#__modules","key":"id","type":"Module","prefix":"Joomla\\\\CMS\\\\Table\\\\"}}', '', '{}', '' + , '{"formFile":"administrator\\/components\\/com_modules\\/forms\\/module.xml", "hideFields":["checked_out", "checked_out_time", "publish_up", "publish_down"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"checked_out", "targetTable":"#__users", "targetColumn":"id", "displayColumn":"name"}]}' +WHERE NOT EXISTS ( + SELECT * FROM `#__content_types` c + WHERE c.`type_title` = 'Module' AND c.`type_alias` = 'com_modules.module' + AND c.`table` = '{"special":{"dbtable":"#__modules","key":"id","type":"Module","prefix":"Joomla\\\\CMS\\\\Table\\\\"}}' +); diff --git a/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-03-13.sql b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-03-13.sql new file mode 100644 index 0000000000000..66538a79b3bd8 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.1.0-2026-03-13.sql @@ -0,0 +1,11 @@ +-- disable autostart for the previous tour +UPDATE `#__guidedtours` SET `autostart` = 0 WHERE `uid` = 'joomla-whatsnew-6-0'; + +INSERT INTO `#__guidedtours` (`title`, `description`, `extensions`, `url`, `published`, `language`, `note`, `access`, `uid`, `autostart`, `created`, `created_by`, `modified`, `modified_by`) +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-6-1', 1, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0 + WHERE NOT EXISTS (SELECT * FROM `#__guidedtours` g WHERE g.`uid` = 'joomla-whatsnew-6-1'); + +INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `params`, `created`, `created_by`, `modified`, `modified_by`, `tour_id`) +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '{"required":1,"requiredvalue":""}', CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, MAX(`id`) + FROM `#__guidedtours` + WHERE `uid` = 'joomla-whatsnew-6-1'; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.2.0-2026-07-21.sql b/administrator/components/com_admin/sql/updates/mysql/6.2.0-2026-07-21.sql new file mode 100644 index 0000000000000..0f3ee94db4d88 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.2.0-2026-07-21.sql @@ -0,0 +1,5 @@ +-- +-- Add security column to updates table +-- + +ALTER TABLE `#__updates` ADD COLUMN `security` TINYINT NULL DEFAULT NULL AFTER `extra_query` /** CAN FAIL **/; diff --git a/administrator/components/com_admin/sql/updates/mysql/6.2.0-2026-08-05.sql b/administrator/components/com_admin/sql/updates/mysql/6.2.0-2026-08-05.sql new file mode 100644 index 0000000000000..d60598ce27279 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/6.2.0-2026-08-05.sql @@ -0,0 +1,9 @@ +-- +-- Add show_subcat_image param to com_content +-- + +UPDATE `#__extensions` +SET `params` = JSON_SET(`params`, '$.show_subcat_image', '0') +WHERE `element` = 'com_content' + AND `type` = 'component' + AND JSON_EXTRACT(`params`, '$.show_subcat_image') IS NULL; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-03-11.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-03-11.sql deleted file mode 100644 index b214d01a96e05..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-03-11.sql +++ /dev/null @@ -1 +0,0 @@ -DROP TABLE IF EXISTS "#__utf8_conversion"; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-03-17.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-03-17.sql deleted file mode 100644 index c3bb4daede595..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-03-17.sql +++ /dev/null @@ -1 +0,0 @@ -DELETE FROM "#__scheduler_tasks" WHERE "type" = 'demoTask_r1.sleep'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-12.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-12.sql deleted file mode 100644 index 0c83e0d5360fd..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-12.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE "#__menu_types" ADD COLUMN "ordering" int NOT NULL DEFAULT 0 /** CAN FAIL **/; -UPDATE "#__menu_types" SET "ordering" = "id" WHERE "client_id" = 0; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-25.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-25.sql deleted file mode 100644 index 851076bf0110d..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-25.sql +++ /dev/null @@ -1,28 +0,0 @@ --- --- Table structure for table "#__schemaorg" --- - -CREATE TABLE IF NOT EXISTS "#__schemaorg" ( - "id" serial NOT NULL, - "itemId" bigint, - "context" varchar(100), - "schemaType" varchar(100), - "schema" text, - PRIMARY KEY ("id") -); - --- Add plugins to "#__extensions" --- -------------------------------------------------------- --- The following INSERT statement has been modified to insert --- core plugins with locked=1. --- See https://github.com/joomla/joomla-cms/pull/45821 for details. --- -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_schemaorg_blogposting', 'plugin', 'blogposting', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), -(0, 'plg_schemaorg_book', 'plugin', 'book', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 2, 0), -(0, 'plg_schemaorg_event', 'plugin', 'event', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), -(0, 'plg_schemaorg_organization', 'plugin', 'organization', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), -(0, 'plg_schemaorg_person', 'plugin', 'person', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 5, 0), -(0, 'plg_schemaorg_recipe', 'plugin', 'recipe', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 6, 0), -(0, 'plg_schemaorg_jobposting', 'plugin', 'jobposting', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 7, 0), -(0, 'plg_system_schemaorg', 'plugin', 'schemaorg', 'system', 0, 1, 1, 0, 1, '', '{}', '', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-21.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-21.sql deleted file mode 100644 index bcca1d7e0835f..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-21.sql +++ /dev/null @@ -1,13 +0,0 @@ -UPDATE "#__extensions" - SET "params" = jsonb_set("params"::jsonb, '{filter}' , '"\\\\Joomla\\\\CMS\\\\Component\\\\ComponentHelper::filterText"') - WHERE "type" = 'plugin' - AND "folder" = 'fields' - AND "element" IN ('editor', 'text', 'textarea') - AND "params" <> '' - AND "params"::jsonb->>'filter' = 'JComponentHelper::filterText'; - -UPDATE "#__fields" - SET "fieldparams" = jsonb_set("fieldparams"::jsonb, '{filter}' , '"\\\\Joomla\\\\CMS\\\\Component\\\\ComponentHelper::filterText"') - WHERE "type" IN ('editor', 'text', 'textarea') - AND "fieldparams" <> '' - AND "fieldparams"::jsonb->>'filter' = 'JComponentHelper::filterText'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-26.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-26.sql deleted file mode 100644 index 8ac88dde34fc5..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-26.sql +++ /dev/null @@ -1,7 +0,0 @@ --- -------------------------------------------------------- --- The following INSERT statement has been modified to insert --- this core plugin with locked=1. --- See https://github.com/joomla/joomla-cms/pull/45821 for details. --- -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_task_globalcheckin', 'plugin', 'globalcheckin', 'task', 0, 1, 1, 0, 1, '', '{}', '', 5, 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-28.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-28.sql deleted file mode 100644 index 252410f0e0baa..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-28.sql +++ /dev/null @@ -1,14 +0,0 @@ - -UPDATE "#__guidedtours" SET "extensions" = '["com_content","com_categories"]' WHERE "url" LIKE '%option=com_content%'; -UPDATE "#__guidedtours" SET "extensions" = '["com_content","com_categories"]' WHERE "url" LIKE '%option=com_categories%'; -UPDATE "#__guidedtours" SET "extensions" = '["com_menus"]' WHERE "url" LIKE '%com_menus%'; -UPDATE "#__guidedtours" SET "extensions" = '["com_tags"]' WHERE "url" LIKE '%com_tags%'; -UPDATE "#__guidedtours" SET "extensions" = '["com_banners"]' WHERE "url" LIKE '%com_banners%'; -UPDATE "#__guidedtours" SET "extensions" = '["com_contact"]' WHERE "url" LIKE '%com_contact%'; -UPDATE "#__guidedtours" SET "extensions" = '["com_newsfeeds"]' WHERE "url" LIKE '%com_newsfeeds%'; -UPDATE "#__guidedtours" SET "extensions" = '["com_finder"]' WHERE "url" LIKE '%com_finder%'; -UPDATE "#__guidedtours" SET "extensions" = '["com_users"]' WHERE "url" LIKE '%com_users%'; - -UPDATE "#__update_sites" - SET "location" = 'https://update.joomla.org/language/translationlist_5.xml' - WHERE "location" = 'https://update.joomla.org/language/translationlist_4.xml'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-29.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-29.sql deleted file mode 100644 index 21666a58eb649..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-29.sql +++ /dev/null @@ -1,14 +0,0 @@ -ALTER TABLE "#__guidedtours" ADD COLUMN "uid" varchar(255) DEFAULT '' NOT NULL /** CAN FAIL **/; -CREATE INDEX "#__guidedtours_idx_uid" ON "#__guidedtours" ("uid") /** CAN FAIL **/; - -UPDATE "#__guidedtours" SET "uid" = 'joomla-guidedtours' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-guidedtoursteps' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURSTEPS_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-articles' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_ARTICLES_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-categories' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_CATEGORIES_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-menus' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_MENUS_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-tags' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_TAGS_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-banners' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_BANNERS_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-contacts' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_CONTACTS_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-newsfeeds' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_NEWSFEEDS_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-smartsearch' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_SMARTSEARCH_TITLE'; -UPDATE "#__guidedtours" SET "uid" = 'joomla-users' WHERE "title" = 'COM_GUIDEDTOURS_TOUR_USERS_TITLE'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-30.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-30.sql deleted file mode 100644 index 6cdba7c66ee3c..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-08-30.sql +++ /dev/null @@ -1,3 +0,0 @@ -UPDATE "#__extensions" - SET "locked" = 0 - WHERE "type" = 'plugin' AND "element" = 'recaptcha_invisible' AND "folder" = 'captcha'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-02.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-02.sql deleted file mode 100644 index 42bdee445b720..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-02.sql +++ /dev/null @@ -1,14 +0,0 @@ -INSERT INTO "#__extensions" ("name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "checked_out", "checked_out_time", "ordering", "state") VALUES -('plg_task_deleteactionlogs', 'plugin', 'deleteactionlogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), -('plg_task_privacyconsent', 'plugin', 'privacyconsent', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), -('plg_task_rotatelogs', 'plugin', 'rotatelogs', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), -('plg_task_sessiongc', 'plugin', 'sessiongc', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0), -('plg_task_updatenotification', 'plugin', 'updatenotification', 'task', 0, 1, 1, 0, 1, '', '{}', '', NULL, NULL, 0, 0); - -INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subject", "body", "htmlbody", "attachments", "params") VALUES -('plg_task_privacyconsent.request.reminder', 'plg_task_privacyconsent', '', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT', 'PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_BODY', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), -('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'); - -DELETE FROM "#__mail_templates" WHERE "template_id" IN ('plg_system_privacyconsent.request.reminder', 'plg_system_updatenotification.mail'); - -DELETE FROM "#__postinstall_messages" WHERE "condition_file" = 'site://plugins/system/updatenotification/postinstall/updatecachetime.php'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-06.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-06.sql deleted file mode 100644 index 6561c6da33304..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-06.sql +++ /dev/null @@ -1,5 +0,0 @@ -UPDATE "#__scheduler_tasks" SET "title" = 'Delete Action Logs' WHERE "type" = 'delete.actionlogs' AND "title" = 'DeleteActionLogs'; -UPDATE "#__scheduler_tasks" SET "title" = 'Privacy Consent' WHERE "type" = 'privacy.consent' AND "title" = 'PrivacyConsent'; -UPDATE "#__scheduler_tasks" SET "title" = 'Rotate Logs' WHERE "type" = 'rotation.logs' AND "title" = 'RotateLogs'; -UPDATE "#__scheduler_tasks" SET "title" = 'Session GC' WHERE "type" = 'session.gc' AND "title" = 'SessionGC'; -UPDATE "#__scheduler_tasks" SET "title" = 'Update Notification' WHERE "type" = 'update.notification' AND "title" = 'UpdateNotification'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-09.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-09.sql deleted file mode 100644 index 4207b50a67858..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-09.sql +++ /dev/null @@ -1,5 +0,0 @@ --- Add com_fields to action logs extensions -INSERT INTO "#__action_logs_extensions" ("extension") VALUES ('com_fields'); - -INSERT INTO "#__action_log_config" ("type_title", "type_alias", "id_holder", "title_holder", "table_name", "text_prefix") VALUES -('field', 'com_fields.field', 'id', 'title', '#__fields', 'PLG_ACTIONLOG_JOOMLA'); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-11.sql b/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-11.sql deleted file mode 100644 index c540fd45a0d52..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-09-11.sql +++ /dev/null @@ -1 +0,0 @@ -UPDATE "#__extensions" SET "enabled" = 1 WHERE "type" = 'plugin' AND "element" = 'schedulerunner' AND "folder" = 'system'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2023-11-28.sql b/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2023-11-28.sql deleted file mode 100644 index 32e80f5656d1d..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2023-11-28.sql +++ /dev/null @@ -1,7 +0,0 @@ --- -------------------------------------------------------- --- The following INSERT statement has been modified to insert --- this core plugin with locked=1. --- See https://github.com/joomla/joomla-cms/pull/45821 for details. --- -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_schemaorg_article', 'plugin', 'article', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-10.sql b/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-10.sql deleted file mode 100644 index 29375e78c1f50..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-10.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "#__guidedtour_steps" ADD COLUMN "params" text NULL /** CAN FAIL **/; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-24.sql b/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-24.sql deleted file mode 100644 index 36692be7b3278..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-24.sql +++ /dev/null @@ -1,37 +0,0 @@ --- --- Table structure for table "#__tuf_metadata" --- - -CREATE TABLE IF NOT EXISTS "#__tuf_metadata" ( -"id" serial NOT NULL, -"update_site_id" bigint DEFAULT 0 NOT NULL, -"root" text DEFAULT NULL, -"targets" text DEFAULT NULL, -"snapshot" text DEFAULT NULL, -"timestamp" text DEFAULT NULL, -"mirrors" text DEFAULT NULL, -PRIMARY KEY ("id") -); - -COMMENT ON TABLE "#__tuf_metadata" IS 'Secure TUF Updates'; - --- -------------------------------------------------------- --- The following INSERT statement has been modified to avoid an SQL error --- when there is more than 1 update site for the Joomla core. --- See https://github.com/joomla/joomla-cms/pull/43169 for details. --- -INSERT INTO "#__tuf_metadata" ("update_site_id", "root") -SELECT ue."update_site_id", - '{"signed":{"_type":"root","spec_version":"1.0","version":2,"expires":"2025-03-02T11:22:17Z","keys":{"07eb082f367c034a95878687f6648aa76d93652b6ee73e58817053d89af6c44f":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"9b2af2d9b9727227735253d795bd27ea8f0e294a5f3603e822dc5052b44802b9"}},"1b1b1dd55b2c1c7258714cf1c1ae06f23e4607b28c762d016a9d81c48ffe5669":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"a18e5ebabc19d5d5984b601a292ece61ba3662ab2d071dc520da5bd4f8948799"}},"2dcaf3d0e552f150792f7c636d45429246dcfa34ac35b46a44f5c87cd17d457e":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"cb0a7a131961a20edea051d6dc2b091fb650bd399bd8514adb67b3c60db9f8f9"}},"31dd7c7290d664c9b88c0dead2697175293ea7df81b7f24153a37370fd3901c3":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"589d029a68b470deff1ca16dbf3eea6b5b3fcba0ae7bb52c468abc7fb058b2a2"}},"9e41a9d62d94c6a1c8a304f62c5bd72d84a9f286f27e8327cedeacb09e5156cc":{"keytype":"ed25519","scheme":"ed25519","keyid_hash_algorithms":["sha256","sha512"],"keyval":{"public":"6043c8bacc76ac5c9750f45454dd865c6ca1fc57d69e14cc192cfd420f6a66a9"}}},"roles":{"root":{"keyids":["1b1b1dd55b2c1c7258714cf1c1ae06f23e4607b28c762d016a9d81c48ffe5669","2dcaf3d0e552f150792f7c636d45429246dcfa34ac35b46a44f5c87cd17d457e"],"threshold":1},"snapshot":{"keyids":["07eb082f367c034a95878687f6648aa76d93652b6ee73e58817053d89af6c44f","2dcaf3d0e552f150792f7c636d45429246dcfa34ac35b46a44f5c87cd17d457e"],"threshold":1},"targets":{"keyids":["31dd7c7290d664c9b88c0dead2697175293ea7df81b7f24153a37370fd3901c3"],"threshold":1},"timestamp":{"keyids":["9e41a9d62d94c6a1c8a304f62c5bd72d84a9f286f27e8327cedeacb09e5156cc"],"threshold":1}},"consistent_snapshot":true},"signatures":[{"keyid":"2dcaf3d0e552f150792f7c636d45429246dcfa34ac35b46a44f5c87cd17d457e","sig":"2a225a560ec0837b721d4c5e379fedbd3c7c9079a94e6b31e47e0184c8b95421b6036b4286c5d90f29ab4c468d79a712fdb65e96511394ceb3aa8e2b3983a501"},{"keyid":"1b1b1dd55b2c1c7258714cf1c1ae06f23e4607b28c762d016a9d81c48ffe5669","sig":"8ce0b2a7bdc1e6dcba12081f440510df0a593c072dcf591631c2dd0f456844a7da63be8e8ac31ffbddf42641fde84dc733a336031d182c2163b4c1eaf2117005"}]}' - FROM "#__update_sites_extensions" AS ue JOIN "#__extensions" AS e ON (e."extension_id" = ue."extension_id") - WHERE e."type"='file' AND e."element"='joomla'; - --- -------------------------------------------------------- --- The following UPDATE statement has been modified to avoid an SQL error --- when there is more than 1 update site for the Joomla core. --- See https://github.com/joomla/joomla-cms/pull/42988 for details. --- -UPDATE "#__update_sites" - SET "type" = 'tuf', "location" = 'https://update.joomla.org/cms/' - WHERE "update_site_id" IN (SELECT ue."update_site_id" FROM "#__update_sites_extensions" AS ue JOIN "#__extensions" AS e ON (e."extension_id" = ue."extension_id") WHERE e."type"='file' AND e."element"='joomla'); - diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-25.sql b/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-25.sql deleted file mode 100644 index 0ec6c6793ffd9..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-02-25.sql +++ /dev/null @@ -1,7 +0,0 @@ --- -------------------------------------------------------- --- The following INSERT statement has been modified to insert --- this core plugin with locked=1. --- See https://github.com/joomla/joomla-cms/pull/45821 for details. --- -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_schemaorg_custom', 'plugin', 'custom', 'schemaorg', 0, 1, 1, 0, 1, '', '{}', '', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-03-08.sql b/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-03-08.sql deleted file mode 100644 index dde57323da713..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-03-08.sql +++ /dev/null @@ -1,15 +0,0 @@ -INSERT INTO "#__guidedtour_steps" ("tour_id", "title", "published", "description", "ordering", "position", "target", "type", "interactive_type", "url", "created", "created_by", "modified", "modified_by", "language") VALUES -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_MENUS_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_MENUS_DESCRIPTION', 1, 'right', '#sidebarmenu', 0, 1, '', CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, '*'), -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_QUICKACCESS_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_QUICKACCESS_DESCRIPTION', 2, 'center', '', 0, 1, '', CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, '*'), -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_NOTIFICATIONS_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_NOTIFICATIONS_DESCRIPTION', 3, 'left', '.quickicons-for-update_quickicon .card', 0, 1, '', CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, '*'), -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_TOPBAR_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_TOPBAR_DESCRIPTION', 4, 'bottom', '#header', 0, 1, '', CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, '*'), -(0, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_FINALWORDS_TITLE', 1, 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_STEP_FINALWORDS_DESCRIPTION', 5, 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, '*') -ON CONFLICT DO NOTHING; - -ALTER TABLE "#__guidedtours" ADD COLUMN "autostart" int NOT NULL DEFAULT 0 /** CAN FAIL **/; - -INSERT INTO "#__guidedtours" ("title", "uid", "description", "ordering", "extensions", "url", "created", "created_by", "modified", "modified_by", "published", "language", "access", "autostart") VALUES -('COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_TITLE', 'joomla-welcome', 'COM_GUIDEDTOURS_TOUR_WELCOMETOJOOMLA_DESCRIPTION', 1, '["com_cpanel"]', 'administrator/index.php', CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, 1, '*', 1, 0) -ON CONFLICT DO NOTHING; - -UPDATE "#__guidedtour_steps" SET "tour_id" = currval(pg_get_serial_sequence('#__guidedtours','id')) WHERE "tour_id"=0; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-03-28.sql b/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-03-28.sql deleted file mode 100644 index 82bf0d612608c..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.1.0-2024-03-28.sql +++ /dev/null @@ -1,12 +0,0 @@ --- --- Add post-installation message about Brotli compression in .htaccess --- --- This statement had to be modified to prevent duplicate postinstall messages --- when updating from 4.4. --- See https://github.com/joomla/joomla-cms/pull/43182 for details. --- -INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") -SELECT "extension_id", 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_BROTLI_TITLE', 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_BROTLI_DESCRIPTION', '', 'com_admin', 1, 'message', '', '', 'admin://components/com_admin/postinstall/htaccessbrotli.php', 'admin_postinstall_htaccessbrotli_condition', '5.1.0', 1 - FROM "#__extensions" - WHERE "name" = 'files_joomla' - AND (SELECT COUNT(a."postinstall_message_id") FROM "#__postinstall_messages" a WHERE a."title_key" = 'COM_ADMIN_POSTINSTALL_MSG_HTACCESS_BROTLI_TITLE') = 0; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.1.1-2024-04-18.sql b/administrator/components/com_admin/sql/updates/postgresql/5.1.1-2024-04-18.sql deleted file mode 100644 index fc44f25a2a219..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.1.1-2024-04-18.sql +++ /dev/null @@ -1,10 +0,0 @@ --- --- Add a default value for the colorScheme in the Atum template on Joomla update --- only when a value is not already set. --- New installs will have the default value set in the installation sql. --- - -UPDATE "#__template_styles" -SET "params" = jsonb_set("params"::jsonb, '{colorScheme}', '"os"', true) -WHERE "template" = 'atum' -AND "params"::jsonb->>'colorScheme' IS NULL; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-07-02.sql b/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-07-02.sql deleted file mode 100644 index 26464101c0f84..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-07-02.sql +++ /dev/null @@ -1,3 +0,0 @@ --- Add mod_articles module -INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") VALUES -(0, 'mod_articles', 'module', 'mod_articles', '', 0, 1, 0, 0, 1, '', '', '', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-07-19.sql b/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-07-19.sql deleted file mode 100644 index 66937855f9f0c..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-07-19.sql +++ /dev/null @@ -1,7 +0,0 @@ --- --- Add the Guided Tours selectable option to the User Action Logs --- -INSERT INTO "#__action_logs_extensions" ("extension") VALUES ('com_guidedtours'); - -INSERT INTO "#__action_log_config" ("type_title", "type_alias", "id_holder", "title_holder", "table_name", "text_prefix") VALUES -('guidedtour', 'com_guidedtours.state', 'id', 'title', '#__guidedtours', 'PLG_ACTIONLOG_JOOMLA'); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-08-22.sql b/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-08-22.sql deleted file mode 100644 index a92672ae0efd7..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-08-22.sql +++ /dev/null @@ -1,6 +0,0 @@ -INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "published", "language", "note", "access", "uid", "autostart", "created", "created_by", "modified", "modified_by") VALUES -('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-2', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0); -INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '{"required":1,"requiredvalue":""}', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 - FROM "#__guidedtours" - WHERE "uid" = 'joomla-whatsnew-5-2'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-09-17.sql b/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-09-17.sql deleted file mode 100644 index d05dd005e6615..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.2.0-2024-09-17.sql +++ /dev/null @@ -1,8 +0,0 @@ -UPDATE "#__guidedtour_steps" -SET "ordering" = "ordering" + 1 -WHERE "title" IN ('COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_SAVECLOSE_TITLE', 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_CONGRATULATIONS_TITLE'); - -INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "tour_id", "created", "created_by", "modified", "modified_by", "ordering") -SELECT 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_AUTOSTART_TITLE', 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_AUTOSTART_DESCRIPTION', 'bottom', '#jform_autostart0', 2, 3, '', 1, '*', '', "tour_id", CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, "ordering" + 1 - FROM "#__guidedtour_steps" - WHERE "title" = 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_COMPONENT_TITLE'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.2.2-2024-09-24.sql b/administrator/components/com_admin/sql/updates/postgresql/5.2.2-2024-09-24.sql deleted file mode 100644 index 8da7f706d58f6..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.2.2-2024-09-24.sql +++ /dev/null @@ -1,7 +0,0 @@ -UPDATE "#__assets" SET "title" = 'PUBLISH' WHERE "name" LIKE 'com_content.transition.%' AND "title" = 'Publish'; -UPDATE "#__assets" SET "title" = 'UNPUBLISH' WHERE "name" LIKE 'com_content.transition.%' AND "title" = 'Unpublish'; -UPDATE "#__assets" SET "title" = 'TRASH' WHERE "name" LIKE 'com_content.transition.%' AND "title" = 'Trash'; -UPDATE "#__assets" SET "title" = 'ARCHIVE' WHERE "name" LIKE 'com_content.transition.%' AND "title" = 'Archive'; -UPDATE "#__assets" SET "title" = 'FEATURE' WHERE "name" LIKE 'com_content.transition.%' AND "title" = 'Feature'; -UPDATE "#__assets" SET "title" = 'UNFEATURE' WHERE "name" LIKE 'com_content.transition.%' AND "title" = 'Unfeature'; -UPDATE "#__assets" SET "title" = 'PUBLISH_AND_FEATURE' WHERE "name" LIKE 'com_content.transition.%' AND "title" = 'Publish & Feature'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.2.3-2025-01-09.sql b/administrator/components/com_admin/sql/updates/postgresql/5.2.3-2025-01-09.sql deleted file mode 100644 index 27f126404b02e..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.2.3-2025-01-09.sql +++ /dev/null @@ -1,3 +0,0 @@ -UPDATE "#__mail_templates" -SET "params" = '{"tags":["messages","message","date","extension","username"]}' -WHERE "template_id" = 'com_actionlogs.notification'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-10-26.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-10-26.sql deleted file mode 100644 index 49794391fb4c4..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-10-26.sql +++ /dev/null @@ -1,20 +0,0 @@ --- --- Table structure for table "#__scheduler_logs" --- - -CREATE TABLE IF NOT EXISTS "#__scheduler_logs" ( - "id" serial NOT NULL, - "taskname" varchar(255) DEFAULT '' NOT NULL, - "tasktype" varchar(128) NOT NULL, - "duration" NUMERIC(5,3) NOT NULL, - "jobid" integer NOT NULL, - "taskid" integer NOT NULL, - "exitcode" integer NOT NULL, - "lastdate" timestamp without time zone, - "nextdate" timestamp without time zone, - PRIMARY KEY (id) -); -CREATE INDEX "#__scheduler_logs_idx_taskname" ON "#__scheduler_logs" ("taskname"); -CREATE INDEX "#__scheduler_logs_idx_tasktype" ON "#__scheduler_logs" ("tasktype"); -CREATE INDEX "#__scheduler_logs_idx_lastdate" ON "#__scheduler_logs" ("lastdate"); -CREATE INDEX "#__scheduler_logs_idx_nextdate" ON "#__scheduler_logs" ("nextdate"); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-12-09.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-12-09.sql deleted file mode 100644 index 2b4c0e2bed244..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-12-09.sql +++ /dev/null @@ -1,2 +0,0 @@ -INSERT INTO "#__action_log_config" ("type_title", "type_alias", "id_holder", "title_holder", "table_name", "text_prefix") VALUES -('contact', 'com_contact.form', 'id', 'name', '#__contact_details', 'PLG_ACTIONLOG_JOOMLA'); \ No newline at end of file diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-12-19.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-12-19.sql deleted file mode 100644 index 4e9852fa36751..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2024-12-19.sql +++ /dev/null @@ -1,6 +0,0 @@ --- -------------------------------------------------------- --- The following statement which was introduced with 5.3.0-alpha3 --- has been disabled as it was reverted with 5.3.0-beta1. --- See https://github.com/joomla/joomla-cms/pull/44845 for details. --- --- ALTER TABLE "#__action_logs_users" ADD COLUMN "exclude_self" integer DEFAULT 0 NOT NULL; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-02-09.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-02-09.sql deleted file mode 100644 index b169f6a493fc2..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-02-09.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE "#__action_logs_users" DROP COLUMN "exclude_self" /** CAN FAIL **/; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-02-22.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-02-22.sql deleted file mode 100644 index 4f319c1a92d2d..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-02-22.sql +++ /dev/null @@ -1,3 +0,0 @@ --- Add plg_extension_joomlaupdate module -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_extension_joomlaupdate', 'plugin', 'joomlaupdate', 'extension', 0, 1, 1, 0, 1, '', '', '', 0, 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql deleted file mode 100644 index cfb58259717f7..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.0-2025-03-14.sql +++ /dev/null @@ -1,10 +0,0 @@ --- disable autostart for the previous tour -UPDATE "#__guidedtours" SET "autostart" = 0 WHERE "uid" = 'joomla-whatsnew-5-2'; - -INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "published", "language", "note", "access", "uid", "autostart", "created", "created_by", "modified", "modified_by") VALUES -('COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-3', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0); - -INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 - FROM "#__guidedtours" - WHERE "uid" = 'joomla-whatsnew-5-3'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.1-2025-04-27.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.1-2025-04-27.sql deleted file mode 100644 index 9cc623fb217ff..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.1-2025-04-27.sql +++ /dev/null @@ -1,4 +0,0 @@ -UPDATE "#__mail_templates" -SET "params" = '{"tags":["messages","message","date","extension","username"]}' -WHERE "template_id" = 'com_actionlogs.notification' -AND "params" = '"tags":["messages","message","date","extension","username"]}'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.3.4-2025-09-19.sql b/administrator/components/com_admin/sql/updates/postgresql/5.3.4-2025-09-19.sql deleted file mode 100644 index 505eff0640add..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.3.4-2025-09-19.sql +++ /dev/null @@ -1,8 +0,0 @@ -UPDATE "#__content_types" -SET "field_mappings" = jsonb_set("field_mappings"::jsonb, '{common, core_created_user_id}' , '"created_by"', true) -WHERE "type_alias" = 'com_content.article'; - -UPDATE "#__content_types" -SET "field_mappings" = jsonb_set("field_mappings"::jsonb, '{common, core_created_by_alias}' , '"created_by_alias"', true) -WHERE "type_alias" = 'com_content.article'; - diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-04-23.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-04-23.sql deleted file mode 100644 index 95cdc7a2653bc..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-04-23.sql +++ /dev/null @@ -1,3 +0,0 @@ -INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") -SELECT 0, 'plg_behaviour_compat6', 'plugin', 'compat6', 'behaviour', 0, 1, 1, 0, 1, '', '{"classes_aliases":"1","legacy_classes":"1"}', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'compat6' AND e."folder" = 'behaviour' AND e."client_id" = 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql b/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql deleted file mode 100644 index 1c9a4100d726c..0000000000000 --- a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-05-10.sql +++ /dev/null @@ -1,28 +0,0 @@ -INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") -SELECT 0, 'plg_quickicon_autoupdate', 'plugin', 'autoupdate', 'quickicon', 0, 1, 1, 0, 1, '', '', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'autoupdate' AND e."folder" = 'quickicon' AND e."client_id" = 0); - -INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") -SELECT 0, 'plg_webservices_joomlaupdate', 'plugin', 'joomlaupdate', 'webservices', 0, 1, 1, 0, 1, '', '', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'joomlaupdate' AND e."folder" = 'webservices' AND e."client_id" = 0); - -INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subject", "body", "htmlbody", "attachments", "params") VALUES -('com_joomlaupdate.update.success', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_SUCCESS_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), -('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}') -ON CONFLICT DO NOTHING; - --- add post-installation message for automated updates -INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description_key", "action_key", "language_extension", "language_client_id", "type", "action_file", "action", "condition_file", "condition_method", "version_introduced", "enabled") -SELECT "extension_id", 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_TITLE', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_DESCRIPTION', 'COM_JOOMLAUPDATE_POSTINSTALL_MSG_AUTOMATED_UPDATES_ACTION', 'com_joomlaupdate', 1, 'action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_action', 'admin://components/com_joomlaupdate/postinstall/autoupdate.php', 'com_joomlaupdate_postinstall_autoupdate_condition', '5.4.0', 1 FROM "#__extensions" WHERE "name" = 'files_joomla'; - --- disable autostart for the previous tour -UPDATE "#__guidedtours" SET "autostart" = 0 WHERE "uid" = 'joomla-whatsnew-5-3'; - -INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "published", "language", "note", "access", "uid", "autostart", "created", "created_by", "modified", "modified_by") -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-5-4', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 -WHERE NOT EXISTS (SELECT * FROM "#__guidedtours" g WHERE g."uid" = 'joomla-whatsnew-5-4'); - -INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "tour_id", "created", "created_by", "modified", "modified_by") -SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', MAX("id"), CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 -FROM "#__guidedtours" -WHERE "uid" = 'joomla-whatsnew-5-4'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2024-08-11.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2024-08-11.sql new file mode 100644 index 0000000000000..e6fba47a2cfaa --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2024-08-11.sql @@ -0,0 +1,6 @@ +-- Update link to featured + +UPDATE "#__menu" +SET "link" = 'index.php?option=com_content&view=articles&filter[featured]=1' +WHERE "link" = 'index.php?option=com_content&view=featured' +AND "client_id" = 1; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-03-25.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-03-25.sql new file mode 100644 index 0000000000000..62797a72dfb48 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-03-25.sql @@ -0,0 +1,3 @@ +INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subject", "body", "htmlbody", "attachments", "params") VALUES +('plg_content_joomla.newarticle', 'plg_content_joomla', '', 'PLG_CONTENT_JOOMLA_NEW_ARTICLE_SUBJECT', 'PLG_CONTENT_JOOMLA_NEW_ARTICLE_BODY', '', '', '{"tags":["sitename","name","email","title","url"]}') +ON CONFLICT DO NOTHING; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-05-20.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-05-20.sql new file mode 100644 index 0000000000000..bed03447d009e --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-05-20.sql @@ -0,0 +1,3 @@ +UPDATE "#__extensions" + SET "params" = '' + WHERE "type" = 'plugin' AND "element" = 'stats' AND "folder" = 'system'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-08-02.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-08-02.sql similarity index 100% rename from administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-08-02.sql rename to administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-08-02.sql diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-29.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-08-16.sql similarity index 53% rename from administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-29.sql rename to administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-08-16.sql index 0d7535b274353..1ed8a5e60113f 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.0.0-2023-07-29.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-08-16.sql @@ -1,3 +1,3 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") -SELECT 0, 'plg_behaviour_compat', 'plugin', 'compat', 'behaviour', 0, 1, 1, 0, 1, '', '{"classes_aliases":"1","es5_assets":"1"}', '', -1, 0 -WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'compat' AND e."folder" = 'behaviour' AND e."client_id" = 0); +SELECT 0, 'plg_fields_note', 'plugin', 'note', 'fields', 0, 1, 1, 0, 1, '', '{"class":"alert alert-info","heading":"h4"}', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'note' AND e."folder" = 'fields' AND e."client_id" = 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-08-17.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-08-17.sql new file mode 100644 index 0000000000000..16731908df72b --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-08-17.sql @@ -0,0 +1,3 @@ +INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") +SELECT 0, 'plg_fields_number', 'plugin', 'number', 'fields', 0, 1, 1, 0, 1, '', '{"min":"1.0","max":"100.0","step":"0.1","currency":"0","position":"0","decimals":"2"}', '', -1, 0 +WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'number' AND e."folder" = 'fields' AND e."client_id" = 0); diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-05.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-05.sql new file mode 100644 index 0000000000000..bb3bc6726fb37 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-05.sql @@ -0,0 +1,8 @@ +INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") +SELECT 0, 'cassiopeia_extended', 'template', 'cassiopeia_extended', '', 0, 1, 1, 0, 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","systemFontBody":"","systemFontHeading":"","colorName":"colors_standard","fluidContainer":"0","stickyHeader":"0","backTop":"0","colorSettings":"0","headerbg":"rgb(193, 205, 207)","headercolor":"rgb(23, 23, 23)","bodybg":"rgb(254, 254, 254)","bodycolor":"rgb(23, 23, 23)","linkcolor":"rgb(29, 121, 137)","linkcolorh":"rgb(14, 59, 67)","btnbg":"rgb(206, 60, 55)","btnbgh":"rgb(131, 35, 32)","btncolor":"rgb(254, 254, 254)","btncolorh":"rgb(254, 254, 254)","footerbg":"rgb(29, 121, 137)","footercolor":"rgb(254, 254, 254)","fontSettings":"0","bodysize":"1","h1size":"2","h2size":"1.7","h3size":"1.5"}', '', 1, 0 +WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'template' AND e."element" = 'cassiopeia_extended' AND e."client_id" = 0); + + +INSERT INTO "#__template_styles" ("template", "client_id", "home", "title", "inheritable", "parent", "params") +SELECT 'cassiopeia_extended', 0, '0', 'Cassiopeia Extended - Default', 0, 'cassiopeia', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","systemFontBody":"","systemFontHeading":"","colorName":"colors_standard","fluidContainer":"0","stickyHeader":"0","backTop":"0","colorSettings":"0","headerbg":"rgb(193, 205, 207)","headercolor":"rgb(23, 23, 23)","bodybg":"rgb(254, 254, 254)","bodycolor":"rgb(23, 23, 23)","linkcolor":"rgb(29, 121, 137)","linkcolorh":"rgb(14, 59, 67)","btnbg":"rgb(206, 60, 55)","btnbgh":"rgb(131, 35, 32)","btncolor":"rgb(254, 254, 254)","btncolorh":"rgb(254, 254, 254)","footerbg":"rgb(29, 121, 137)","footercolor":"rgb(254, 254, 254)","fontSettings":"0","bodysize":"1","h1size":"2","h2size":"1.7","h3size":"1.5"}' +WHERE NOT EXISTS (SELECT * FROM "#__template_styles" t WHERE t."template" = 'cassiopeia_extended' AND t."client_id" = 0 AND t."inheritable" = 0 AND t."parent" = 'cassiopeia'); \ No newline at end of file diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-16.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-16.sql new file mode 100644 index 0000000000000..fea9098d5c027 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-16.sql @@ -0,0 +1,6 @@ +-- uninstall previous What's New tours +DELETE FROM "#__guidedtour_steps" + WHERE "tour_id" IN (SELECT "id" FROM "#__guidedtours" WHERE "uid" IN ('joomla-whatsnew-5-2', 'joomla-whatsnew-5-3', 'joomla-whatsnew-5-4')); + +DELETE FROM "#__guidedtours" + WHERE "uid" IN ('joomla-whatsnew-5-2', 'joomla-whatsnew-5-3', 'joomla-whatsnew-5-4'); diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-17.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-17.sql new file mode 100644 index 0000000000000..5a81db0d144de --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-17.sql @@ -0,0 +1,13 @@ +INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "published", "language", "note", "access", "uid", "autostart", "created", "created_by", "modified", "modified_by") +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-6-0', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 +WHERE NOT EXISTS (SELECT * FROM "#__guidedtours" g WHERE g."uid" = 'joomla-whatsnew-6-0'); + +INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "created", "created_by", "modified", "modified_by", "tour_id") +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_0_DESCRIPTION', 'center', '', 0, 1, '', 1, '*', '', '{"required":1,"requiredvalue":""}', CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, MAX("id") + FROM "#__guidedtours" + WHERE "uid" = 'joomla-whatsnew-6-0'; + +INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "created", "created_by", "modified", "modified_by", "tour_id") +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_1_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_1_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '"{\"required\":1,\"requiredvalue\":\"\"}"', CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, MAX("id") + FROM "#__guidedtours" + WHERE "uid" = 'joomla-whatsnew-6-0'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-23.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-23.sql new file mode 100644 index 0000000000000..d7f5708ce800c --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-23.sql @@ -0,0 +1,3 @@ +UPDATE "#__update_sites" + SET "location" = 'https://update.joomla.org/language/translationlist_6.xml' + WHERE "location" = 'https://update.joomla.org/language/translationlist_5.xml'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-26.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-26.sql new file mode 100644 index 0000000000000..5f91914aa269c --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-09-26.sql @@ -0,0 +1,33 @@ +-- Update content types for lookup tags + +UPDATE "#__content_types" +SET "content_history_options" = jsonb_set( + "content_history_options"::jsonb, + '{displayLookup}', + "content_history_options"::jsonb->'displayLookup' || + jsonb_build_object( + 'sourceColumn', 'tags', + 'targetTable', '#__tags', + 'targetColumn', 'id', + 'displayColumn', 'title' + ) + ) +WHERE "type_alias" IN ( + 'com_content.article', + 'com_contact.contact', + 'com_newsfeeds.newsfeed', + 'com_content.category', + 'com_contact.category', + 'com_newsfeeds.category', + 'com_banners.category', + 'com_users.category' + ) +AND NOT EXISTS ( + SELECT * FROM jsonb_array_elements("content_history_options"::jsonb->'displayLookup') + WHERE value = jsonb_build_object( + 'sourceColumn', 'tags', + 'targetTable', '#__tags', + 'targetColumn', 'id', + 'displayColumn', 'title' + ) + ); diff --git a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-10-07.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-10-10.sql similarity index 98% rename from administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-10-07.sql rename to administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-10-10.sql index 23407ee5a6a5a..c416183248cde 100644 --- a/administrator/components/com_admin/sql/updates/postgresql/5.4.0-2025-10-07.sql +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-10-10.sql @@ -1,2 +1,2 @@ --- Remove wrong unique constraint from "#__ucm_content" table -ALTER TABLE "#__ucm_content" DROP CONSTRAINT "#__ucm_content_idx_type_alias_item_id" /** CAN FAIL **/; +-- Remove wrong unique constraint from "#__ucm_content" table +ALTER TABLE "#__ucm_content" DROP CONSTRAINT "#__ucm_content_idx_type_alias_item_id" /** CAN FAIL **/; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-10-11.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-10-11.sql new file mode 100644 index 0000000000000..db3fae581c1e6 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.0-2025-10-11.sql @@ -0,0 +1,5 @@ +ALTER TABLE "#__history" + ADD COLUMN "is_current" SMALLINT NOT NULL DEFAULT 0 /** CAN FAIL **/; +ALTER TABLE "#__history" + ADD COLUMN "is_legacy" SMALLINT NOT NULL DEFAULT 0 /** CAN FAIL **/; +UPDATE "#__history" SET "is_legacy" = 1; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.0.1-2025-10-29.sql b/administrator/components/com_admin/sql/updates/postgresql/6.0.1-2025-10-29.sql new file mode 100644 index 0000000000000..94952c7643e62 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.0.1-2025-10-29.sql @@ -0,0 +1,21 @@ +UPDATE "#__menu" +SET "params" = jsonb_set( + "params"::jsonb, + '{featured_categories}', + COALESCE( + ( + SELECT jsonb_agg(to_jsonb(CASE WHEN elem = ' ' THEN '' ELSE elem END)) + FROM jsonb_array_elements_text("params"::jsonb->'featured_categories') AS t(elem) + ), + '[]'::jsonb + ), + false +) +WHERE ("params"::jsonb->'featured_categories') @> '[" "]'::jsonb + AND "type" = 'component' + AND "link" = 'index.php?option=com_content&view=featured'; + +UPDATE "#__menu" +SET "link" = REPLACE("link", '&catid[0]= ', '&catid[0]=') +WHERE "type" = 'component' + AND "link" LIKE 'index.php?option=com_content&view=archive&catid[0]= %'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2025-10-30.sql b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2025-10-30.sql new file mode 100644 index 0000000000000..7c05c45be4ff5 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2025-10-30.sql @@ -0,0 +1,8 @@ +-- +-- Add a template tag for ip_address on Joomla update. +-- New installs will have the default value set in the installation support sql. +-- + +UPDATE "#__mail_templates" +SET "params" = '{"tags":["messages","message","date","extension","username","ip_address"]}' +WHERE "template_id" = 'com_actionlogs.notification'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2025-11-29.sql b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2025-11-29.sql new file mode 100644 index 0000000000000..2cbc909b1fa68 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2025-11-29.sql @@ -0,0 +1,4 @@ +INSERT INTO "#__extensions" ("name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") +SELECT 'plg_captcha_powcaptcha', 'plugin', 'powcaptcha', 'captcha', 0, 1, 1, 0, 1, '', '{}', '', 0, 0 +WHERE NOT EXISTS (SELECT * FROM "#__extensions" e WHERE e."type" = 'plugin' AND e."element" = 'powcaptcha' AND e."folder" = 'captcha' AND e."client_id" = 0); + diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-01-29.sql b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-01-29.sql new file mode 100644 index 0000000000000..6f339b8dd3419 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-01-29.sql @@ -0,0 +1,7 @@ +-- -------------------------------------------------------- +-- The following statement which was introduced with 6.1.0-beta1 +-- has been disabled as it was replaced in 6.1.0-beta3 with +-- a new statement in file "6.1.0-2026-03-10.sql". +-- See https://github.com/joomla/joomla-cms/pull/47361 for details. +-- +-- INSERT INTO "#__content_types" ("type_id", "type_title", "type_alias", "table", "rules", "field_mappings", "router", "content_history_options") VALUES (14, 'Module', 'com_modules.module', '{"special":{"dbtable":"#__modules","key":"id","type":"Module","prefix":"Joomla\\\\CMS\\\\Table\\\\"}}', '', '{}', '', '{"formFile":"administrator\\/components\\/com_modules\\/forms\\/module.xml", "hideFields":["checked_out", "checked_out_time", "publish_up", "publish_down"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"checked_out", "targetTable":"#__users", "targetColumn":"id", "displayColumn":"name"}]}'); diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-02-06.sql b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-02-06.sql new file mode 100644 index 0000000000000..b456e37ba4e34 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-02-06.sql @@ -0,0 +1,5 @@ +-- +-- Add position column to workflow stages table +-- + +ALTER TABLE "#__workflow_stages" ADD COLUMN "position" text NULL /** CAN FAIL **/; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-03-07.sql b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-03-07.sql new file mode 100644 index 0000000000000..cfe92a8f8d613 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-03-07.sql @@ -0,0 +1,15 @@ +UPDATE "#__extensions" + SET "params" = jsonb_set("params"::jsonb, '{html_height}' , '"550px"') + WHERE "type" = 'plugin' + AND "folder" = 'editors' + AND "element" = 'tinymce' + AND "params" <> '' + AND "params"::jsonb->>'html_height' = '550'; + +UPDATE "#__extensions" + SET "params" = jsonb_set("params"::jsonb, '{html_width}' , '"100%"') + WHERE "type" = 'plugin' + AND "folder" = 'editors' + AND "element" = 'tinymce' + AND "params" <> '' + AND "params"::jsonb->>'html_width' = '750'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-03-10.sql b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-03-10.sql new file mode 100644 index 0000000000000..723f9cafa746d --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-03-10.sql @@ -0,0 +1,13 @@ +-- -------------------------------------------------------- +-- The following statement replaces the statement which has been disabled +-- in file "6.1.0-2026-01-29.sql" with 6.1.0-beta3. +-- See https://github.com/joomla/joomla-cms/pull/47361 for details. +-- +INSERT INTO "#__content_types" ("type_title", "type_alias", "table", "rules", "field_mappings", "router", "content_history_options") +SELECT 'Module', 'com_modules.module', '{"special":{"dbtable":"#__modules","key":"id","type":"Module","prefix":"Joomla\\\\CMS\\\\Table\\\\"}}', '', '{}', '' + , '{"formFile":"administrator\\/components\\/com_modules\\/forms\\/module.xml", "hideFields":["checked_out", "checked_out_time", "publish_up", "publish_down"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"checked_out", "targetTable":"#__users", "targetColumn":"id", "displayColumn":"name"}]}' +WHERE NOT EXISTS ( + SELECT * FROM "#__content_types" c + WHERE c."type_title" = 'Module' AND c."type_alias" = 'com_modules.module' + AND c."table" = '{"special":{"dbtable":"#__modules","key":"id","type":"Module","prefix":"Joomla\\\\CMS\\\\Table\\\\"}}' +); diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-03-13.sql b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-03-13.sql new file mode 100644 index 0000000000000..9bbe0dda6b5db --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.1.0-2026-03-13.sql @@ -0,0 +1,11 @@ +-- disable autostart for the previous tour +UPDATE "#__guidedtours" SET "autostart" = 0 WHERE "uid" = 'joomla-whatsnew-6-0'; + +INSERT INTO "#__guidedtours" ("title", "description", "extensions", "url", "published", "language", "note", "access", "uid", "autostart", "created", "created_by", "modified", "modified_by") +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_DESCRIPTION', '["com_cpanel"]', 'administrator/index.php', 1, '*', '', 1, 'joomla-whatsnew-6-1', 1, CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0 + WHERE NOT EXISTS (SELECT * FROM "#__guidedtours" g WHERE g."uid" = 'joomla-whatsnew-6-1'); + +INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "params", "created", "created_by", "modified", "modified_by", "tour_id") +SELECT 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_STEP_0_TITLE', 'COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_STEP_0_DESCRIPTION', 'right', '#sidebarmenu nav > ul:first-of-type > li:last-child', 0, 1, '', 1, '*', '', '{"required":1,"requiredvalue":""}', CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, MAX("id") + FROM "#__guidedtours" + WHERE "uid" = 'joomla-whatsnew-6-1'; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.2.0-2026-07-21.sql b/administrator/components/com_admin/sql/updates/postgresql/6.2.0-2026-07-21.sql new file mode 100644 index 0000000000000..52bef3ceb85dd --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.2.0-2026-07-21.sql @@ -0,0 +1,5 @@ +-- +-- Add security column to updates table +-- + +ALTER TABLE "#__updates" ADD COLUMN "security" smallint NULL DEFAULT NULL /** CAN FAIL **/; diff --git a/administrator/components/com_admin/sql/updates/postgresql/6.2.0-2026-08-05.sql b/administrator/components/com_admin/sql/updates/postgresql/6.2.0-2026-08-05.sql new file mode 100644 index 0000000000000..4ad7049a201bc --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/6.2.0-2026-08-05.sql @@ -0,0 +1,9 @@ +-- +-- Add show_subcat_image param to com_content +-- + +UPDATE "#__extensions" +SET "params" = jsonb_set("params"::jsonb, '{show_subcat_image}', '0', true) +WHERE "element" = 'com_content' + AND "type" = 'component' + AND "params"::jsonb->>'show_subcat_image' IS NULL; diff --git a/administrator/components/com_admin/src/Model/HelpModel.php b/administrator/components/com_admin/src/Model/HelpModel.php index 2198e6430e801..489b9f2e53680 100644 --- a/administrator/components/com_admin/src/Model/HelpModel.php +++ b/administrator/components/com_admin/src/Model/HelpModel.php @@ -12,10 +12,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Help\Help; -use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\BaseDatabaseModel; -use Joomla\Filesystem\Folder; -use Joomla\String\StringHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -28,14 +25,6 @@ */ class HelpModel extends BaseDatabaseModel { - /** - * The search string - * - * @var string - * @since 1.6 - */ - protected $help_search = null; - /** * The page to be viewed * @@ -44,46 +33,6 @@ class HelpModel extends BaseDatabaseModel */ protected $page = null; - /** - * The ISO language tag - * - * @var string - * @since 1.6 - */ - protected $lang_tag = null; - - /** - * Table of contents - * - * @var array - * @since 1.6 - */ - protected $toc = []; - - /** - * URL for the latest version check - * - * @var string - * @since 1.6 - */ - protected $latest_version_check = null; - - /** - * Method to get the help search string - * - * @return string Help search string - * - * @since 1.6 - */ - public function &getHelpSearch() - { - if (\is_null($this->help_search)) { - $this->help_search = Factory::getApplication()->getInput()->getString('helpsearch'); - } - - return $this->help_search; - } - /** * Method to get the page * @@ -99,91 +48,4 @@ public function &getPage() return $this->page; } - - /** - * Method to get the lang tag - * - * @return string lang iso tag - * - * @since 1.6 - */ - public function getLangTag() - { - if (\is_null($this->lang_tag)) { - $this->lang_tag = Factory::getLanguage()->getTag(); - - if (!is_dir(JPATH_BASE . '/help/' . $this->lang_tag)) { - // Use English as fallback - $this->lang_tag = 'en-GB'; - } - } - - return $this->lang_tag; - } - - /** - * Method to get the table of contents - * - * @return array Table of contents - */ - public function &getToc() - { - if (\count($this->toc)) { - return $this->toc; - } - - // Get vars - $lang_tag = $this->getLangTag(); - $help_search = $this->getHelpSearch(); - - // New style - Check for a TOC \JSON file - if (file_exists(JPATH_BASE . '/help/' . $lang_tag . '/toc.json')) { - $data = json_decode(file_get_contents(JPATH_BASE . '/help/' . $lang_tag . '/toc.json')); - - // Loop through the data array - foreach ($data as $key => $value) { - $this->toc[$key] = Text::_('COM_ADMIN_HELP_' . $value); - } - - // Sort the Table of Contents - asort($this->toc); - - return $this->toc; - } - - // Get Help files - $files = Folder::files(JPATH_BASE . '/help/' . $lang_tag, '\.xml$|\.html$'); - - foreach ($files as $file) { - $buffer = file_get_contents(JPATH_BASE . '/help/' . $lang_tag . '/' . $file); - - if (!preg_match('#(.*?)#', $buffer, $m)) { - continue; - } - - $title = trim($m[1]); - - if (!$title) { - continue; - } - - // Translate the page title - $title = Text::_($title); - - // Strip the extension - $file = preg_replace('#\.xml$|\.html$#', '', $file); - - if ($help_search && StringHelper::strpos(StringHelper::strtolower(strip_tags($buffer)), StringHelper::strtolower($help_search)) === false) { - continue; - } - - // Add an item in the Table of Contents - $this->toc[$file] = $title; - } - - // Sort the Table of Contents - asort($this->toc); - - return $this->toc; - } } diff --git a/administrator/components/com_admin/src/Model/SysinfoModel.php b/administrator/components/com_admin/src/Model/SysinfoModel.php index d5a3eb239f48b..9ebd648c6176a 100644 --- a/administrator/components/com_admin/src/Model/SysinfoModel.php +++ b/administrator/components/com_admin/src/Model/SysinfoModel.php @@ -314,7 +314,7 @@ public function &getInfo(): array $this->info = [ 'version' => (new Version())->getLongVersion(), - 'compatpluginenabled' => PluginHelper::isEnabled('behaviour', 'compat'), + 'compatpluginenabled' => PluginHelper::isEnabled('behaviour', 'compat6'), 'compatpluginparameters' => $this->getCompatPluginParameters(), 'phpversion' => PHP_VERSION, 'php' => php_uname(), @@ -334,7 +334,7 @@ public function &getInfo(): array private function getCompatPluginParameters() { - $record = ExtensionHelper::getExtensionRecord('compat', 'plugin', 0, 'behaviour'); + $record = ExtensionHelper::getExtensionRecord('compat6', 'plugin', 0, 'behaviour'); if ($record) { $params = new Registry($record->params); @@ -456,7 +456,7 @@ public function getExtensions(): array { $installed = []; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__extensions')); $db->setQuery($query); diff --git a/administrator/components/com_admin/src/Service/HTML/PhpSetting.php b/administrator/components/com_admin/src/Service/HTML/PhpSetting.php index c1f18f44a8616..6e2cb2179f4a7 100644 --- a/administrator/components/com_admin/src/Service/HTML/PhpSetting.php +++ b/administrator/components/com_admin/src/Service/HTML/PhpSetting.php @@ -47,6 +47,18 @@ public function set($val) return Text::_($val ? 'JYES' : 'JNO'); } + /** + * Method to generate a boolean message for a value + * + * @param boolean $val is the value set? + * + * @return string html code + */ + public function enabled($val) + { + return Text::_($val ? 'JENABLED' : 'JDISABLED'); + } + /** * Method to generate a string message for a value * diff --git a/administrator/components/com_admin/src/View/Help/HtmlView.php b/administrator/components/com_admin/src/View/Help/HtmlView.php index 9d893b8cd8a70..12a04b64c1f00 100644 --- a/administrator/components/com_admin/src/View/Help/HtmlView.php +++ b/administrator/components/com_admin/src/View/Help/HtmlView.php @@ -43,20 +43,11 @@ class HtmlView extends BaseHtmlView protected $page = null; /** - * The iso language tag + * The level of each submenu * - * @var string - * @since 1.6 - */ - protected $languageTag = null; - - /** - * Table of contents - * - * @var array - * @since 1.6 + * @var integer */ - protected $toc = []; + protected $toclevel = 0; /** * Execute and display a template script. @@ -73,10 +64,7 @@ public function display($tpl = null): void { /** @var HelpModel $model */ $model = $this->getModel(); - $this->helpSearch = $model->getHelpSearch(); $this->page = $model->getPage(); - $this->toc = $model->getToc(); - $this->languageTag = $model->getLangTag(); $this->addToolbar(); @@ -94,4 +82,21 @@ protected function addToolbar(): void { ToolbarHelper::title(Text::_('COM_ADMIN_HELP'), 'support help_header'); } + + /** + * Method to render a given level of a menu using provided layout file + * + * @param string $layoutFile The layout file to be used to render + * @param array $menu The menu to render the children of + * + * @return void + * + * @since 6.2.0 + */ + public function renderSubmenu($layoutFile, $menu) + { + if (is_file($layoutFile)) { + require $layoutFile; + } + } } diff --git a/administrator/components/com_admin/tmpl/help/default.php b/administrator/components/com_admin/tmpl/help/default.php index 14e0a81b9833f..7bbdb2fb49034 100644 --- a/administrator/components/com_admin/tmpl/help/default.php +++ b/administrator/components/com_admin/tmpl/help/default.php @@ -10,44 +10,38 @@ defined('_JEXEC') or die; -use Joomla\CMS\Help\Help; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; -use Joomla\CMS\Router\Route; /** @var \Joomla\Component\Admin\Administrator\View\Help\HtmlView $this */ /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->getDocument()->getWebAssetManager(); -$wa->useScript('com_admin.admin-help'); +$wa->useScript('com_admin.admin-help') + ->useStyle('com_admin.admin-help'); + +// Get the HTML for the Table of Contents from a separate file. +include_once 'toc-src.php'; ?> - -
- -
- -
+
+
+ + + +
+
+ +
- - +
diff --git a/administrator/components/com_admin/tmpl/help/toc-build.php b/administrator/components/com_admin/tmpl/help/toc-build.php new file mode 100644 index 0000000000000..49da7d3bfad3b --- /dev/null +++ b/administrator/components/com_admin/tmpl/help/toc-build.php @@ -0,0 +1,51 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +use Joomla\CMS\Help\Help; +use Joomla\CMS\Language\Text; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +// Increase the toclevel on entry +$this->toclevel += 1; +if ($this->toclevel > 1) { + $collapse = ' mm-collapse'; + echo "
    \n"; +} +foreach ($menu as $label => $value) { + $text = Text::_('COM_ADMIN_HELP_' . $label); + $lclabel = strtolower(str_replace('_', '-', $label)); + + if (is_array($value)) { + // This is a folder list item + $icon = ""; + $wrap_label = "{$text}"; + echo "
  • toclevel}\">"; + echo ""; + echo "{$icon}{$wrap_label}\n"; + if (!empty($value)) { + // Recursively build sublist. + $this->renderSubmenu(JPATH_ADMINISTRATOR . '/components/com_admin/tmpl/help/toc-build.php', $value); + } + echo "
  • \n"; + } else { + // This is an article list item. + $icon = ""; + // The url is help.joomla.org + $label (the help key). + $url = Help::createUrl($label); + $link = "{$icon}{$text}\n"; + echo "
  • toclevel}\">{$link}
  • \n"; + } +} +echo "
\n"; +// On return decrease the toclevel +$this->toclevel -= 1; diff --git a/administrator/components/com_admin/tmpl/help/toc-src.php b/administrator/components/com_admin/tmpl/help/toc-src.php new file mode 100644 index 0000000000000..6fee063304a30 --- /dev/null +++ b/administrator/components/com_admin/tmpl/help/toc-src.php @@ -0,0 +1,280 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +$menu = [ + "START_HERE" => [ + "Start_Here" => "START_HERE", + "License" => "COM_ADMIN_HELP_LICENSE", + "Glossary" => "GLOSSARY", + "Home_Dashboard" => "HOME_DASHBOARD", + "Site_Global_Configuration" => "SITE_GLOBAL_CONFIGURATION", + ], + "CONTENT" => [ + "ARTICLES" => [ + "Articles" => "ARTICLES", + "Articles:_Edit" => "ARTICLES:_EDIT", + "Articles:_Categories" => "ARTICLES:_CATEGORIES", + "Articles:_Edit_Category" => "ARTICLES:_EDIT_CATEGORY", + "Articles:_Featured" => "ARTICLES:_FEATURED", + "Articles:_Options" => "ARTICLES:_OPTIONS", + ], + "WORKFLOWS" => [ + "Workflows_List" => "WORKFLOWS_LIST", + "Stages_List:_Basic_Workflow" => "STAGES_LIST:_BASIC_WORKFLOW", + "Transitions_List:_Basic_Workflow" => "TRANSITIONS_LIST:_BASIC_WORKFLOW", + ], + "FIELDS" => [ + "Field_Groups" => "FIELD_GROUPS", + "Field_Groups:_Edit" => "FIELD_GROUPS:_EDIT", + "Fields" => "FIELDS", + "Fields:_Edit" => "FIELDS:_EDIT", + ], + "MEDIA" => [ + "Media" => "MEDIA", + "Media:_Options" => "MEDIA:_OPTIONS", + ], + "MODULES" => [ + "Modules" => "MODULES", + "Modules:_Options" => "MODULES:_OPTIONS", + ], + "SITE_MODULES" => [ + "Site_Modules:_Articles" => "SITE_MODULES:_ARTICLES", + "Site_Modules:_Articles_-_Archived" => "SITE_MODULES:_ARTICLES_-_ARCHIVED", + "Site_Modules:_Articles_-_Latest" => "SITE_MODULES:_ARTICLES_-_LATEST", + "Site_Modules:_Articles_-_Most_Read" => "SITE_MODULES:_ARTICLES_-_MOST_READ", + "Site_Modules:_Articles_-_Newsflash" => "SITE_MODULES:_ARTICLES_-_NEWSFLASH", + "Site_Modules:_Articles_-_Related" => "SITE_MODULES:_ARTICLES_-_RELATED", + "Site_Modules:_Banners" => "SITE_MODULES:_BANNERS", + "Site_Modules:_Breadcrumbs" => "SITE_MODULES:_BREADCRUMBS", + "Site_Modules:_Custom" => "SITE_MODULES:_CUSTOM", + "Site_Modules:_Feed_Display" => "SITE_MODULES:_FEED_DISPLAY", + "Site_Modules:_Footer" => "SITE_MODULES:_FOOTER", + "Site_Modules:_Language_Switcher" => "SITE_MODULES:_LANGUAGE_SWITCHER", + "Site_Modules:_Login" => "SITE_MODULES:_LOGIN", + "Site_Modules:_Menu" => "SITE_MODULES:_MENU", + "Site_Modules:_Random_Image" => "SITE_MODULES:_RANDOM_IMAGE", + "Site_Modules:_Smart_Search" => "SITE_MODULES:_SMART_SEARCH", + "Site_Modules:_Statistics" => "SITE_MODULES:_STATISTICS", + "Site_Modules:_Syndication_Feeds" => "SITE_MODULES:_SYNDICATION_FEEDS", + "Site_Modules:_Tags_-_Popular" => "SITE_MODULES:_TAGS_-_POPULAR", + "Site_Modules:_Tags_-_Similar" => "SITE_MODULES:_TAGS_-_SIMILAR", + "Site_Modules:_Wrapper" => "SITE_MODULES:_WRAPPER", + ], + "ADMIN_MODULES" => [ + "Admin_Modules:_Action_Logs_-_Latest" => "ADMIN_MODULES:_ACTION_LOGS_-_LATEST", + "Admin_Modules:_Administrator_Dashboard_Menu" => "ADMIN_MODULES:_ADMINISTRATOR_DASHBOARD_MENU", + "Admin_Modules:_Administrator_Menu" => "ADMIN_MODULES:_ADMINISTRATOR_MENU", + "Admin_Modules:_Articles_-_Latest" => "ADMIN_MODULES:_ARTICLES_-_LATEST", + "Admin_Modules:_Custom" => "ADMIN_MODULES:_CUSTOM", + "Admin_Modules:_Feed_Display" => "ADMIN_MODULES:_FEED_DISPLAY", + "Admin_Modules:_Frontend_Link" => "ADMIN_MODULES:_FRONTEND_LINK", + "Admin_Modules:_Guided_Tours" => "ADMIN_MODULES:_GUIDED_TOURS", + "Admin_Modules:_Joomla_Version_Information" => "ADMIN_MODULES:_JOOMLA_VERSION_INFORMATION", + "Admin_Modules:_Login_Form" => "ADMIN_MODULES:_LOGIN_FORM", + "Admin_Modules:_Login_Support_Information" => "ADMIN_MODULES:_LOGIN_SUPPORT_INFORMATION", + "Admin_Modules:_Messages" => "ADMIN_MODULES:_MESSAGES", + "Admin_Modules:_Multilingual_Status" => "ADMIN_MODULES:_MULTILINGUAL_STATUS", + "Admin_Modules:_Popular_Articles" => "ADMIN_MODULES:_POPULAR_ARTICLES", + "Admin_Modules:_Post_Installation_Messages" => "ADMIN_MODULES:_POST_INSTALLATION_MESSAGES", + "Admin_Modules:_Privacy_Dashboard" => "ADMIN_MODULES:_PRIVACY_DASHBOARD", + "Admin_Modules:_Privacy_Status_Check" => "ADMIN_MODULES:_PRIVACY_STATUS_CHECK", + "Admin_Modules:_Quick_Icons" => "ADMIN_MODULES:_QUICK_ICONS", + "Admin_Modules:_Sample_Data" => "ADMIN_MODULES:_SAMPLE_DATA", + "Admin_Modules:_Title" => "ADMIN_MODULES:_TITLE", + "Admin_Modules:_Toolbar" => "ADMIN_MODULES:_TOOLBAR", + ], + ], + "MENUS" => [ + "MENUS" => [ + "Menus" => "MENUS", + "Menus:_Edit" => "MENUS:_EDIT", + "Menus:_Items" => "MENUS:_ITEMS", + "Menus:_Options" => "MENUS:_OPTIONS", + ], + "MENU_ITEMS" => [ + "Menu_Item:_Alias" => "MENU_ITEM:_ALIAS", + "Menu_Item:_Article_Archived" => "MENU_ITEM:_ARTICLE_ARCHIVED", + "Menu_Item:_Compact_List_of_Tagged_Items" => "MENU_ITEM:_COMPACT_LIST_OF_TAGGED_ITEMS", + "Menu_Item:_Components_Menu_Container" => "MENU_ITEM:_COMPONENTS_MENU_CONTAINER", + "Menu_Item:_Confirm_Request" => "MENU_ITEM:_CONFIRM_REQUEST", + "Menu_Item:_Create_Article" => "MENU_ITEM:_CREATE_ARTICLE", + "Menu_Item:_Create_Contact" => "MENU_ITEM:_CREATE_CONTACT", + "Menu_Item:_Create_Request" => "MENU_ITEM:_CREATE_REQUEST", + "Menu_Item:_Display_Template_Options" => "MENU_ITEM:_DISPLAY_TEMPLATE_OPTIONS", + "Menu_Item:_Extend_Consent" => "MENU_ITEM:_EXTEND_CONSENT", + "Menu_Item:_Featured_Articles" => "MENU_ITEM:_FEATURED_ARTICLES", + "Menu_Item:_Featured_Contacts" => "MENU_ITEM:_FEATURED_CONTACTS", + "Menu_Item:_Heading" => "MENU_ITEM:_HEADING", + "Menu_Item:_Iframe_Wrapper" => "MENU_ITEM:_IFRAME_WRAPPER", + "Menu_Item:_List_All_Tags" => "MENU_ITEM:_LIST_ALL_TAGS", + "Menu_Item:_Login_Form" => "MENU_ITEM:_LOGIN_FORM", + "Menu_Item:_Logout" => "MENU_ITEM:_LOGOUT", + "Menu_Item:_New_Item" => "MENU_ITEM:_NEW_ITEM", + "Menu_Item:_Password_Reset" => "MENU_ITEM:_PASSWORD_RESET", + "Menu_Item:_Registration_Form" => "MENU_ITEM:_REGISTRATION_FORM", + "Menu_Item:_Search" => "MENU_ITEM:_SEARCH", + "Menu_Item:_Separator" => "MENU_ITEM:_SEPARATOR", + "Menu_Item:_Single_Article" => "MENU_ITEM:_SINGLE_ARTICLE", + "Menu_Item:_Single_Contact" => "MENU_ITEM:_SINGLE_CONTACT", + "Menu_Item:_Single_News_Feed" => "MENU_ITEM:_SINGLE_NEWS_FEED", + "Menu_Item:_Site_Configuration_Options" => "MENU_ITEM:_SITE_CONFIGURATION_OPTIONS", + "Menu_Item:_Tagged_Items" => "MENU_ITEM:_TAGGED_ITEMS", + "Menu_Item:_URL" => "MENU_ITEM:_URL", + ], + ], + "COMPONENTS" => [ + "BANNERS" => [ + "Banners" => "BANNERS", + "Banners:_Edit" => "BANNERS:_EDIT", + "Banners:_Categories" => "BANNERS:_CATEGORIES", + "Banners:_New_or_Edit_Category" => "BANNERS:_NEW_OR_EDIT_CATEGORY", + "Banners:_Clients" => "BANNERS:_CLIENTS", + "Banners:_New_or_Edit_Client" => "BANNERS:_NEW_OR_EDIT_CLIENT", + "Banners:_Tracks" => "BANNERS:_TRACKS", + "Banners:_Options" => "BANNERS:_OPTIONS", + ], + "CONTACTS" => [ + "Contacts" => "CONTACTS", + "Contacts:_Edit" => "CONTACTS:_EDIT", + "Contacts:_Categories" => "CONTACTS:_CATEGORIES", + "Contacts:_Edit_Category" => "CONTACTS:_EDIT_CATEGORY", + "Contacts:_Options" => "CONTACTS:_OPTIONS", + ], + "NEWS_FEEDS" => [ + "News_Feeds" => "NEWS_FEEDS", + "News_Feeds:_Edit" => "NEWS_FEEDS:_EDIT", + "News_Feeds:_Categories" => "NEWS_FEEDS:_CATEGORIES", + "News_Feeds:_Edit_Category" => "NEWS_FEEDS:_EDIT_CATEGORY", + "News_Feed:_Options" => "NEWS_FEED:_OPTIONS", + ], + "SMART_SEARCH" => [ + "Smart_Search:_Indexed_Content" => "SMART_SEARCH:_INDEXED_CONTENT", + "Smart_Search:_Content_Maps" => "SMART_SEARCH:_CONTENT_MAPS", + "Smart_Search:_Search_Filters" => "SMART_SEARCH:_SEARCH_FILTERS", + "Smart_Search:_New_or_Edit_Filter" => "SMART_SEARCH:_NEW_OR_EDIT_FILTER", + "Smart_Search:_Search_Term_Analysis" => "SMART_SEARCH:_SEARCH_TERM_ANALYSIS", + "Smart_Search:_Options" => "SMART_SEARCH:_OPTIONS", + ], + "TAGS" => [ + "Tags" => "TAGS", + "Tags:_New_or_Edit" => "TAGS:_NEW_OR_EDIT", + "Tags:_Options" => "TAGS:_OPTIONS", + ], + ], + "USERS" => [ + "Users" => "USERS", + "Users:_Edit_Profile" => "USERS:_EDIT_PROFILE", + "Users:_Viewing_Access_Levels" => "USERS:_VIEWING_ACCESS_LEVELS", + "Users:_Edit_Viewing_Access_Level" => "USERS:_EDIT_VIEWING_ACCESS_LEVEL", + "Users:_Groups" => "USERS:_GROUPS", + "Users:_New_or_Edit_Group" => "USERS:_NEW_OR_EDIT_GROUP", + "Permissions_for_Group" => "PERMISSIONS_FOR_GROUP", + "Permissions_for_User" => "PERMISSIONS_FOR_USER", + "Users:_Options" => "USERS:_OPTIONS", + ], + "USER_ACTIONS" => [ + "User_Actions_Log" => "USER_ACTIONS_LOG", + "User_Actions_Log:_Options" => "USER_ACTIONS_LOG:_OPTIONS", + "User_Notes" => "USER_NOTES", + "User_Notes:_New_or_Edit" => "USER_NOTES:_NEW_OR_EDIT", + "Mass_Mail_Users" => "MASS_MAIL_USERS", + "Private_Messages" => "PRIVATE_MESSAGES", + "Private_Messages:_Read" => "PRIVATE_MESSAGES:_READ", + "Private_Messages:_Write" => "PRIVATE_MESSAGES:_WRITE", + "Messages:_Options" => "MESSAGES:_OPTIONS", + ], + "PRIVACY" => [ + "Privacy_Dashboard" => "PRIVACY_DASHBOARD", + "Privacy:_Consents" => "PRIVACY:_CONSENTS", + "Privacy:_Extension_Capabilities" => "PRIVACY:_EXTENSION_CAPABILITIES", + "Privacy:_Information_Requests" => "PRIVACY:_INFORMATION_REQUESTS", + "Privacy:_New_Information_Request" => "PRIVACY:_NEW_INFORMATION_REQUEST", + "Privacy:_Review_Information_Request" => "PRIVACY:_REVIEW_INFORMATION_REQUEST", + "Privacy:_Options" => "PRIVACY:_OPTIONS", + ], + "SYSTEM" => [ + "EXTENSIONS" => [ + "Extensions:_Discover" => "EXTENSIONS:_DISCOVER", + "Extensions:_Install" => "EXTENSIONS:_INSTALL", + "Extensions:_Languages" => "EXTENSIONS:_LANGUAGES", + "Extensions:_Manage" => "EXTENSIONS:_MANAGE", + "Extensions:_Update" => "EXTENSIONS:_UPDATE", + "Extensions:_Update_Sites" => "EXTENSIONS:_UPDATE_SITES", + ], + "TEMPLATES" => [ + "Templates:_Templates" => "TEMPLATES:_TEMPLATES", + "Templates:_Customise" => "TEMPLATES:_CUSTOMISE", + "Templates:_Customise_Source" => "TEMPLATES:_CUSTOMISE_SOURCE", + "Templates:_Styles" => "TEMPLATES:_STYLES", + "Templates:_Edit_Style" => "TEMPLATES:_EDIT_STYLE", + "Template:_Options" => "TEMPLATE:_OPTIONS", + "Mail_Templates" => "MAIL_TEMPLATES", + "Mail_Template:_Edit" => "MAIL_TEMPLATE:_EDIT", + "Mail_Templates:_Options" => "MAIL_TEMPLATES:_OPTIONS", + ], + "MAINTENANCE" => [ + "Information:_Database" => "INFORMATION:_DATABASE", + "Maintenance:_Clear_Cache" => "MAINTENANCE:_CLEAR_CACHE", + "Maintenance:_Global_Check-in" => "MAINTENANCE:_GLOBAL_CHECK-IN", + "Cache:_Options" => "CACHE:_OPTIONS", + "Check-in:_Options" => "CHECK-IN:_OPTIONS", + ], + "LANGUAGES" => [ + "Languages:_Content" => "LANGUAGES:_CONTENT", + "Languages:_Edit_Content_Language" => "LANGUAGES:_EDIT_CONTENT_LANGUAGE", + "Languages:_Edit_Override" => "LANGUAGES:_EDIT_OVERRIDE", + "Languages:_Installed" => "LANGUAGES:_INSTALLED", + "Languages:_Options" => "LANGUAGES:_OPTIONS", + "Languages:_Overrides" => "LANGUAGES:_OVERRIDES", + "Multilingual_Associations" => "MULTILINGUAL_ASSOCIATIONS", + "Multilingual_Associations:_Edit" => "MULTILINGUAL_ASSOCIATIONS:_EDIT", + "Multilingual_Associations:_Options" => "MULTILINGUAL_ASSOCIATIONS:_OPTIONS", + ], + "PLUGINS" => [ + "Plugins" => "PLUGINS", + "Plugins:_Name_of_Plugin" => "PLUGINS:_NAME_OF_PLUGIN", + "Editors" => "EDITORS", + "Plugin:_Options" => "PLUGIN:_OPTIONS", + ], + "REDIRECTS" => [ + "Redirects:_Links" => "REDIRECTS:_LINKS", + "Redirects:_New_or_Edit" => "REDIRECTS:_NEW_OR_EDIT", + "Redirect:_Options" => "REDIRECT:_OPTIONS", + ], + "GUIDED_TOURS" => [ + "Guided_Tours" => "GUIDED_TOURS", + "Guided_Tours:_New_or_Edit_Tour" => "GUIDED_TOURS:_NEW_OR_EDIT_TOUR", + "Guided_Tours:_Steps" => "GUIDED_TOURS:_STEPS", + "Guided_Tours:_New_or_Edit_Step" => "GUIDED_TOURS:_NEW_OR_EDIT_STEP", + "Guided_Tours:_Options" => "GUIDED_TOURS:_OPTIONS", + ], + "SCHEDULED_TASKS" => [ + "Scheduled_Tasks" => "SCHEDULED_TASKS", + "Scheduled_Tasks:_Edit" => "SCHEDULED_TASKS:_EDIT", + "Scheduled_Tasks:_Options" => "SCHEDULED_TASKS:_OPTIONS", + ], + "INFORMATION" => [ + "Information:_Warnings" => "INFORMATION:_WARNINGS", + "Post-installation_Messages_for_Joomla_CMS" => "POST-INSTALLATION_MESSAGES_FOR_JOOMLA_CMS", + "Post-installation_Messages:_Options" => "POST-INSTALLATION_MESSAGES:_OPTIONS", + "Site_System_Information" => "SITE_SYSTEM_INFORMATION", + ], + "JOOMLA_UPDATE" => [ + "Joomla_Update" => "JOOMLA_UPDATE", + "Joomla_Update:_Options" => "JOOMLA_UPDATE:_OPTIONS", + "Edit_Update_Site" => "EDIT_UPDATE_SITE", + "Installer:_Options" => "INSTALLER:_OPTIONS", + ], + ], +]; diff --git a/administrator/components/com_admin/tmpl/sysinfo/default_phpsettings.php b/administrator/components/com_admin/tmpl/sysinfo/default_phpsettings.php index 078555d28d371..a2f520c81b14c 100644 --- a/administrator/components/com_admin/tmpl/sysinfo/default_phpsettings.php +++ b/administrator/components/com_admin/tmpl/sysinfo/default_phpsettings.php @@ -109,7 +109,7 @@ - phpSettings['session.auto_start']; ?> + phpSettings['session.auto_start']); ?> diff --git a/administrator/components/com_associations/src/Helper/AssociationsHelper.php b/administrator/components/com_associations/src/Helper/AssociationsHelper.php index 6f591141a919e..3fb7a8d10446d 100644 --- a/administrator/components/com_associations/src/Helper/AssociationsHelper.php +++ b/administrator/components/com_associations/src/Helper/AssociationsHelper.php @@ -258,7 +258,7 @@ public static function getAssociationHtmlList($extensionName, $typeName, $itemId $db = Factory::getDbo(); // Get the category name - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__categories')) ->where($db->quoteName('id') . ' = :id') @@ -272,7 +272,7 @@ public static function getAssociationHtmlList($extensionName, $typeName, $itemId $db = Factory::getDbo(); // Get the menutype name - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__menu_types')) ->where($db->quoteName('menutype') . ' = :menutype') @@ -448,7 +448,7 @@ private static function getEnabledExtensions() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('component')) @@ -653,7 +653,7 @@ public static function getTypeFieldName($extensionName, $typeName, $fieldName) public static function getLanguagefilterPluginId() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) diff --git a/administrator/components/com_associations/src/Model/AssociationModel.php b/administrator/components/com_associations/src/Model/AssociationModel.php index 1f366ecf36ead..6ba21237c628a 100644 --- a/administrator/components/com_associations/src/Model/AssociationModel.php +++ b/administrator/components/com_associations/src/Model/AssociationModel.php @@ -10,6 +10,7 @@ namespace Joomla\Component\Associations\Administrator\Model; +use Joomla\CMS\Form\Form; use Joomla\CMS\MVC\Model\ListModel; // phpcs:disable PSR1.Files.SideEffects @@ -29,15 +30,13 @@ class AssociationModel extends ListModel * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 3.7.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_associations.association', 'association', ['control' => 'jform', 'load_data' => $loadData]); - - return !empty($form) ? $form : false; + return $this->loadForm('com_associations.association', 'association', ['control' => 'jform', 'load_data' => $loadData]); } } diff --git a/administrator/components/com_associations/src/Model/AssociationsModel.php b/administrator/components/com_associations/src/Model/AssociationsModel.php index c0cffcc55f771..03adf17c33da7 100644 --- a/administrator/components/com_associations/src/Model/AssociationsModel.php +++ b/administrator/components/com_associations/src/Model/AssociationsModel.php @@ -14,7 +14,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Category; use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; @@ -170,7 +170,7 @@ protected function getListQuery() // Create a new query object. $user = $this->getCurrentUser(); $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $details = $type->get('details'); @@ -389,7 +389,7 @@ protected function getListQuery() $baselevel = 1; if ($categoryId = $this->getState('filter.category_id')) { - $categoryTable = Table::getInstance('Category', '\\Joomla\\CMS\\Table\\'); + $categoryTable = new Category($db); $categoryTable->load($categoryId); $baselevel = (int) $categoryTable->level; @@ -462,7 +462,7 @@ public function purge($context = '', $key = '') { $app = Factory::getApplication(); $db = $this->getDatabase(); - $query = $db->getQuery(true)->delete($db->quoteName('#__associations')); + $query = $db->createQuery()->delete($db->quoteName('#__associations')); // Filter by associations context. if ($context) { @@ -508,7 +508,7 @@ public function clean($context = '', $key = '') { $app = Factory::getApplication(); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('key') . ', COUNT(*)') ->from($db->quoteName('#__associations')) ->group($db->quoteName('key')) diff --git a/administrator/components/com_associations/src/View/Association/HtmlView.php b/administrator/components/com_associations/src/View/Association/HtmlView.php index 8e155d2aa4113..b5964d93e9a19 100644 --- a/administrator/components/com_associations/src/View/Association/HtmlView.php +++ b/administrator/components/com_associations/src/View/Association/HtmlView.php @@ -250,6 +250,32 @@ public function display($tpl = null): void if (!empty($this->typeSupports['save2copy'])) { $this->save2copy = true; } + + if (\array_key_exists('urlOptions', $details)) { + $urlOptions = $details['urlOptions']; + $specialOptions = []; + + foreach ($urlOptions as $tag => $urlOption) { + $helper = $extension->get('helper'); + + if (\array_key_exists('functionName', $urlOption)) { + $func = $urlOption['functionName']; + $args = []; + + if (\array_key_exists('params', $urlOption)) { + $params = $urlOption['params']; + + foreach ($params as $param) { + $args[] = $input->get($param); + } + } + + $value = \call_user_func_array([$helper, $func], $args); + } + + $specialOptions[$tag] = $value; + } + } } $this->extensionName = $extensionName; @@ -289,6 +315,10 @@ public function display($tpl = null): void ]; } + if (!empty($specialOptions)) { + $options = array_merge($options, $specialOptions); + } + // Reference and target edit links. $this->editUri = 'index.php?' . http_build_query($options); @@ -317,6 +347,11 @@ public function display($tpl = null): void $this->addToolbar(); + // Add form control fields + $this->form + ->addControlField('task') + ->addControlField('target-id', '', ['id' => 'target-id']); + parent::display($tpl); } diff --git a/administrator/components/com_associations/src/View/Associations/HtmlView.php b/administrator/components/com_associations/src/View/Associations/HtmlView.php index 64a32d30d8ea7..e2ab6004af122 100644 --- a/administrator/components/com_associations/src/View/Associations/HtmlView.php +++ b/administrator/components/com_associations/src/View/Associations/HtmlView.php @@ -135,6 +135,10 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task'); + if (!Associations::isEnabled()) { $link = Route::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . AssociationsHelper::getLanguagefilterPluginId()); Factory::getApplication()->enqueueMessage(Text::sprintf('COM_ASSOCIATIONS_ERROR_NO_ASSOC', $link), 'warning'); @@ -212,6 +216,11 @@ public function display($tpl = null) if ($forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'CMD')) { $this->filterForm->setFieldAttribute('category_id', 'language', '*,' . $forcedLanguage, 'filter'); } + + // Add extra form control fields for modal + $this->filterForm + ->addControlField('forcedItemType', Factory::getApplication()->getInput()->get('forcedItemType', '', 'string')) + ->addControlField('forcedLanguage', $forcedLanguage); } } diff --git a/administrator/components/com_associations/tmpl/association/edit.php b/administrator/components/com_associations/tmpl/association/edit.php index c654584ee894e..669ae9b18e4d4 100644 --- a/administrator/components/com_associations/tmpl/association/edit.php +++ b/administrator/components/com_associations/tmpl/association/edit.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -82,7 +81,5 @@
- - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_associations/tmpl/associations/default.php b/administrator/components/com_associations/tmpl/associations/default.php index 3c6bcc2f202c7..290d9c5da1239 100644 --- a/administrator/components/com_associations/tmpl/associations/default.php +++ b/administrator/components/com_associations/tmpl/associations/default.php @@ -164,8 +164,8 @@ pagination->getListFooter(); ?> - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_associations/tmpl/associations/modal.php b/administrator/components/com_associations/tmpl/associations/modal.php index 5a4b2214e4519..f945152d581eb 100644 --- a/administrator/components/com_associations/tmpl/associations/modal.php +++ b/administrator/components/com_associations/tmpl/associations/modal.php @@ -164,9 +164,6 @@ - - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_banners/helpers/banners.php b/administrator/components/com_banners/helpers/banners.php index ab6c17e19c362..fec09b76df383 100644 --- a/administrator/components/com_banners/helpers/banners.php +++ b/administrator/components/com_banners/helpers/banners.php @@ -19,7 +19,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Banners\Administrator\Helper\BannersHelper instead */ class BannersHelper extends \Joomla\Component\Banners\Administrator\Helper\BannersHelper diff --git a/administrator/components/com_banners/src/Helper/BannersHelper.php b/administrator/components/com_banners/src/Helper/BannersHelper.php index cd867e89e53e5..a74c0f0add8dc 100644 --- a/administrator/components/com_banners/src/Helper/BannersHelper.php +++ b/administrator/components/com_banners/src/Helper/BannersHelper.php @@ -15,7 +15,6 @@ use Joomla\CMS\Helper\ContentHelper; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; -use Joomla\CMS\Table\Table; use Joomla\Database\ParameterType; // phpcs:disable PSR1.Files.SideEffects @@ -43,7 +42,7 @@ public static function updateReset() $app = Factory::getApplication(); $user = $app->getIdentity(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__banners')) ->where( @@ -78,7 +77,7 @@ public static function updateReset() if ($purchaseType < 0 && $row->cid) { /** @var \Joomla\Component\Banners\Administrator\Table\ClientTable $client */ - $client = Table::getInstance('ClientTable', '\\Joomla\\Component\\Banners\\Administrator\\Table\\'); + $client = $app->bootComponent('com_banners')->getMVCFactory()->createTable('Client', 'Administrator'); $client->load($row->cid); $purchaseType = $client->purchase_type; } @@ -111,7 +110,7 @@ public static function updateReset() } // Update the row ordering field. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__banners')) ->set( [ @@ -148,7 +147,7 @@ public static function getClientOptions() $options = []; $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('id', 'value'), diff --git a/administrator/components/com_banners/src/Model/BannerModel.php b/administrator/components/com_banners/src/Model/BannerModel.php index 9e7b1eb703edf..c8ab1d37b548c 100644 --- a/administrator/components/com_banners/src/Model/BannerModel.php +++ b/administrator/components/com_banners/src/Model/BannerModel.php @@ -16,6 +16,7 @@ use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Table\Table; use Joomla\CMS\Table\TableInterface; +use Joomla\CMS\Versioning\VersionableModelInterface; use Joomla\CMS\Versioning\VersionableModelTrait; use Joomla\Component\Categories\Administrator\Helper\CategoriesHelper; use Joomla\Database\ParameterType; @@ -29,7 +30,7 @@ * * @since 1.6 */ -class BannerModel extends AdminModel +class BannerModel extends AdminModel implements VersionableModelInterface { use VersionableModelTrait; @@ -82,7 +83,7 @@ protected function cleanupPostBatchCopy(TableInterface $table, $newId, $oldId) // Initialise clicks and impmade $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__banners')) ->set($db->quoteName('clicks') . ' = 0') ->set($db->quoteName('impmade') . ' = 0') @@ -204,19 +205,16 @@ protected function canEditState($record) * @param array $data Data for the form. [optional] * @param boolean $loadData True if the form is to load its own data (default case), false if not. [optional] * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_banners.banner', 'banner', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - // Modify the form based on access controls. if (!$this->canEditState((object) $data)) { // Disable fields for display. @@ -264,7 +262,7 @@ protected function loadFormData() $filters = (array) $app->getUserState('com_banners.banners.filter'); $filterCatId = $filters['category_id'] ?? null; - $data->set('catid', $app->getInput()->getInt('catid', $filterCatId)); + $data->catid = $app->getInput()->getInt('catid', $filterCatId); } } @@ -352,7 +350,7 @@ protected function prepareTable($table) // Set ordering to the last item if not set if (empty($table->ordering)) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('MAX(' . $db->quoteName('ordering') . ')') ->from($db->quoteName('#__banners')); diff --git a/administrator/components/com_banners/src/Model/BannersModel.php b/administrator/components/com_banners/src/Model/BannersModel.php index a835d5bb23f5a..bd38b3a8f1fe3 100644 --- a/administrator/components/com_banners/src/Model/BannersModel.php +++ b/administrator/components/com_banners/src/Model/BannersModel.php @@ -78,7 +78,7 @@ public function &getCategoryOrders() { if (!isset($this->cache['categoryorders'])) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ 'MAX(' . $db->quoteName('ordering') . ') AS ' . $db->quoteName('max'), @@ -104,7 +104,7 @@ public function &getCategoryOrders() protected function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_banners/src/Model/ClientModel.php b/administrator/components/com_banners/src/Model/ClientModel.php index 6378292da6ab2..4b53b4e0cd796 100644 --- a/administrator/components/com_banners/src/Model/ClientModel.php +++ b/administrator/components/com_banners/src/Model/ClientModel.php @@ -11,8 +11,10 @@ namespace Joomla\Component\Banners\Administrator\Model; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Table\Table; +use Joomla\CMS\Versioning\VersionableModelInterface; use Joomla\CMS\Versioning\VersionableModelTrait; // phpcs:disable PSR1.Files.SideEffects @@ -24,7 +26,7 @@ * * @since 1.6 */ -class ClientModel extends AdminModel +class ClientModel extends AdminModel implements VersionableModelInterface { use VersionableModelTrait; @@ -85,20 +87,14 @@ protected function canEditState($record) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_banners.client', 'client', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_banners.client', 'client', ['control' => 'jform', 'load_data' => $loadData]); } /** diff --git a/administrator/components/com_banners/src/Model/ClientsModel.php b/administrator/components/com_banners/src/Model/ClientsModel.php index 54216dd4f553e..4d0105543bec7 100644 --- a/administrator/components/com_banners/src/Model/ClientsModel.php +++ b/administrator/components/com_banners/src/Model/ClientsModel.php @@ -103,7 +103,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $defaultPurchase = (int) ComponentHelper::getParams('com_banners')->get('purchase_type', 3); @@ -227,7 +227,7 @@ public function getItems() $db = $this->getDatabase(); $clientIds = array_column($items, 'id'); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('cid'), diff --git a/administrator/components/com_banners/src/Model/DownloadModel.php b/administrator/components/com_banners/src/Model/DownloadModel.php index 6dc2854c3b83a..2b276e5fc2b35 100644 --- a/administrator/components/com_banners/src/Model/DownloadModel.php +++ b/administrator/components/com_banners/src/Model/DownloadModel.php @@ -12,6 +12,7 @@ use Joomla\CMS\Application\ApplicationHelper; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; use Joomla\CMS\MVC\Model\FormModel; // phpcs:disable PSR1.Files.SideEffects @@ -55,20 +56,14 @@ protected function populateState() * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_banners.download', 'download', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_banners.download', 'download', ['control' => 'jform', 'load_data' => $loadData]); } /** diff --git a/administrator/components/com_banners/src/Model/TracksModel.php b/administrator/components/com_banners/src/Model/TracksModel.php index 3656463c93cf2..c2f60ce7e468c 100644 --- a/administrator/components/com_banners/src/Model/TracksModel.php +++ b/administrator/components/com_banners/src/Model/TracksModel.php @@ -98,7 +98,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( @@ -202,7 +202,7 @@ public function delete() if ($allow) { // Delete tracks from this banner $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__banner_tracks')); // Filter by type @@ -223,7 +223,7 @@ public function delete() ->bind(':end', $end); } - $subQuery = $db->getQuery(true); + $subQuery = $db->createQuery(); $subQuery->select($db->quoteName('id')) ->from($db->quoteName('#__banners')); @@ -344,7 +344,7 @@ protected function getCategoryName() if ($categoryId) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__categories')) ->where($db->quoteName('id') . ' = :categoryId') @@ -378,7 +378,7 @@ protected function getClientName() if ($clientId) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('name')) ->from($db->quoteName('#__banner_clients')) ->where($db->quoteName('id') . ' = :clientId') diff --git a/administrator/components/com_banners/src/Service/Html/Banner.php b/administrator/components/com_banners/src/Service/Html/Banner.php index 77314f24fd6f3..bf57f4b80742c 100644 --- a/administrator/components/com_banners/src/Service/Html/Banner.php +++ b/administrator/components/com_banners/src/Service/Html/Banner.php @@ -63,7 +63,7 @@ public function clients() public function clientlist() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('id', 'value'), diff --git a/administrator/components/com_banners/src/Table/BannerTable.php b/administrator/components/com_banners/src/Table/BannerTable.php index b26cd2b1782df..cbf5998929fea 100644 --- a/administrator/components/com_banners/src/Table/BannerTable.php +++ b/administrator/components/com_banners/src/Table/BannerTable.php @@ -15,7 +15,6 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Table\Table; -use Joomla\CMS\Versioning\VersionableTableInterface; use Joomla\Database\DatabaseInterface; use Joomla\Database\ParameterType; use Joomla\Event\DispatcherInterface; @@ -31,7 +30,7 @@ * * @since 1.5 */ -class BannerTable extends Table implements VersionableTableInterface +class BannerTable extends Table { /** * Indicates that columns fully support the NULL value in the database @@ -69,7 +68,7 @@ public function clicks() { $id = (int) $this->id; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__banners')) ->set($db->quoteName('clicks') . ' = ' . $db->quoteName('clicks') . ' + 1') ->where($db->quoteName('id') . ' = :id') diff --git a/administrator/components/com_banners/src/View/Banner/HtmlView.php b/administrator/components/com_banners/src/View/Banner/HtmlView.php index a8e16b6f90649..3626467a25e41 100644 --- a/administrator/components/com_banners/src/View/Banner/HtmlView.php +++ b/administrator/components/com_banners/src/View/Banner/HtmlView.php @@ -82,6 +82,10 @@ public function display($tpl = null): void $this->addToolbar(); + // Add form control fields + $this->form + ->addControlField('task'); + parent::display($tpl); } diff --git a/administrator/components/com_banners/src/View/Banners/HtmlView.php b/administrator/components/com_banners/src/View/Banners/HtmlView.php index 38a993977b8c7..88136e34e243c 100644 --- a/administrator/components/com_banners/src/View/Banners/HtmlView.php +++ b/administrator/components/com_banners/src/View/Banners/HtmlView.php @@ -10,16 +10,10 @@ namespace Joomla\Component\Banners\Administrator\View\Banners; -use Joomla\CMS\Form\Form; use Joomla\CMS\Helper\ContentHelper; use Joomla\CMS\Language\Multilanguage; -use Joomla\CMS\Language\Text; -use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; -use Joomla\CMS\Pagination\Pagination; -use Joomla\CMS\Toolbar\Button\DropdownButton; -use Joomla\CMS\Toolbar\ToolbarHelper; +use Joomla\CMS\MVC\View\ListView; use Joomla\Component\Banners\Administrator\Model\BannersModel; -use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -30,24 +24,8 @@ * * @since 1.6 */ -class HtmlView extends BaseHtmlView +class HtmlView extends ListView { - /** - * The search tools form - * - * @var Form - * @since 1.6 - */ - public $filterForm; - - /** - * The active search filters - * - * @var array - * @since 1.6 - */ - public $activeFilters = []; - /** * Category data * @@ -57,152 +35,53 @@ class HtmlView extends BaseHtmlView protected $categories = []; /** - * An array of items - * - * @var array - * @since 1.6 - */ - protected $items = []; - - /** - * The pagination object + * The help link for the view * - * @var Pagination - * @since 1.6 + * @var string */ - protected $pagination; + protected $helpLink = 'Banners'; /** - * The model state + * Constructor * - * @var Registry - * @since 1.6 - */ - protected $state; - - /** - * Is this view an Empty State + * @param array $config An optional associative array of configuration settings. * - * @var boolean - * @since 4.0.0 + * @since 6.0.0 */ - private $isEmptyState = false; - - /** - * Method to display the view. - * - * @param string $tpl A template file to load. [optional] - * - * @return void - * - * @since 1.6 - * @throws \Exception - */ - public function display($tpl = null): void + public function __construct(array $config) { - /** @var BannersModel $model */ - $model = $this->getModel(); - $model->setUseExceptions(true); - - $this->categories = $model->getCategoryOrders(); - $this->items = $model->getItems(); - $this->pagination = $model->getPagination(); - $this->state = $model->getState(); - $this->filterForm = $model->getFilterForm(); - $this->activeFilters = $model->getActiveFilters(); - - if (!\count($this->items) && $this->isEmptyState = $model->getIsEmptyState()) { - $this->setLayout('emptystate'); + if (empty($config['option'])) { + $config['option'] = 'com_banners'; } - $this->addToolbar(); - - // We do not need to filter by language when multilingual is disabled - if (!Multilanguage::isEnabled()) { - unset($this->activeFilters['language']); - $this->filterForm->removeField('language', 'filter'); - } + $config['toolbar_icon'] = 'bookmark banners'; + $config['supports_batch'] = true; + $config['category'] = 'com_banners'; - parent::display($tpl); + parent::__construct($config); } /** - * Add the page title and toolbar. + * Prepare view data * * @return void * - * @since 1.6 + * @since 6.0.0 */ - protected function addToolbar(): void + protected function initializeView() { - $canDo = ContentHelper::getActions('com_banners', 'category', $this->state->get('filter.category_id')); - $user = $this->getCurrentUser(); - $toolbar = $this->getDocument()->getToolbar(); - - ToolbarHelper::title(Text::_('COM_BANNERS_MANAGER_BANNERS'), 'bookmark banners'); - - if ($canDo->get('core.create') || \count($user->getAuthorisedCategories('com_banners', 'core.create')) > 0) { - $toolbar->addNew('banner.add'); - } - - if (!$this->isEmptyState && ($canDo->get('core.edit.state') || ($this->state->get('filter.published') == -2 && $canDo->get('core.delete')))) { - /** @var DropdownButton $dropdown */ - $dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS') - ->toggleSplit(false) - ->icon('icon-ellipsis-h') - ->buttonClass('btn btn-action') - ->listCheck(true); + parent::initializeView(); - $childBar = $dropdown->getChildToolbar(); - - if ($canDo->get('core.edit.state')) { - if ($this->state->get('filter.published') != 2) { - $childBar->publish('banners.publish')->listCheck(true); - - $childBar->unpublish('banners.unpublish')->listCheck(true); - } - - if ($this->state->get('filter.published') != -1) { - if ($this->state->get('filter.published') != 2) { - $childBar->archive('banners.archive')->listCheck(true); - } elseif ($this->state->get('filter.published') == 2) { - $childBar->publish('publish')->task('banners.publish')->listCheck(true); - } - } - - $childBar->checkin('banners.checkin'); - - if ($this->state->get('filter.published') != -2) { - $childBar->trash('banners.trash')->listCheck(true); - } - } + /** @var BannersModel $model */ + $model = $this->getModel(); - if ($this->state->get('filter.published') == -2 && $canDo->get('core.delete')) { - $toolbar->delete('banners.delete', 'JTOOLBAR_DELETE_FROM_TRASH') - ->message('JGLOBAL_CONFIRM_DELETE') - ->listCheck(true); - } + $this->categories = $model->getCategoryOrders(); + $this->canDo = ContentHelper::getActions('com_banners', 'category', $this->state->get('filter.category_id')); - // Add a batch button - if ( - $user->authorise('core.create', 'com_banners') - && $user->authorise('core.edit', 'com_banners') - && $user->authorise('core.edit.state', 'com_banners') - ) { - $childBar->popupButton('batch', 'JTOOLBAR_BATCH') - ->popupType('inline') - ->textHeader(Text::_('COM_BANNERS_BATCH_OPTIONS')) - ->url('#joomla-dialog-batch') - ->modalWidth('800px') - ->modalHeight('fit-content') - ->listCheck(true); - } - } - - if ($user->authorise('core.admin', 'com_banners') || $user->authorise('core.options', 'com_banners')) { - $toolbar->preferences('com_banners'); + // We do not need to filter by language when multilingual is disabled + if (!Multilanguage::isEnabled()) { + unset($this->activeFilters['language']); + $this->filterForm->removeField('language', 'filter'); } - - $toolbar->help('Banners'); } } diff --git a/administrator/components/com_banners/src/View/Client/HtmlView.php b/administrator/components/com_banners/src/View/Client/HtmlView.php index b00c442ff8c8f..7d28092ced147 100644 --- a/administrator/components/com_banners/src/View/Client/HtmlView.php +++ b/administrator/components/com_banners/src/View/Client/HtmlView.php @@ -91,6 +91,10 @@ public function display($tpl = null): void $this->addToolbar(); + // Add form control fields + $this->form + ->addControlField('task'); + parent::display($tpl); } diff --git a/administrator/components/com_banners/src/View/Clients/HtmlView.php b/administrator/components/com_banners/src/View/Clients/HtmlView.php index 314909b107932..da9a763990b2f 100644 --- a/administrator/components/com_banners/src/View/Clients/HtmlView.php +++ b/administrator/components/com_banners/src/View/Clients/HtmlView.php @@ -106,6 +106,11 @@ public function display($tpl = null): void $this->addToolbar(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_banners/src/View/Tracks/HtmlView.php b/administrator/components/com_banners/src/View/Tracks/HtmlView.php index ae53040ef7c08..03d06b869a4ea 100644 --- a/administrator/components/com_banners/src/View/Tracks/HtmlView.php +++ b/administrator/components/com_banners/src/View/Tracks/HtmlView.php @@ -106,6 +106,11 @@ public function display($tpl = null): void $this->addToolbar(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_banners/src/View/Tracks/RawView.php b/administrator/components/com_banners/src/View/Tracks/RawView.php index ff7652ac2f78a..7fdac446e0b73 100644 --- a/administrator/components/com_banners/src/View/Tracks/RawView.php +++ b/administrator/components/com_banners/src/View/Tracks/RawView.php @@ -58,7 +58,7 @@ public function display($tpl = null): void $app = Factory::getApplication(); $app->setHeader( 'Content-disposition', - 'attachment; filename="' . $basename . '.' . $fileType . '"; creation-date="' . Factory::getDate()->toRFC822() . '"', + 'attachment; filename="' . str_replace('"', '', $basename) . '.' . $fileType . '"; creation-date="' . Factory::getDate()->toRFC822() . '"', true ); echo $content; diff --git a/administrator/components/com_banners/tmpl/banner/edit.php b/administrator/components/com_banners/tmpl/banner/edit.php index 9ee378083f9c2..19faad9abe126 100644 --- a/administrator/components/com_banners/tmpl/banner/edit.php +++ b/administrator/components/com_banners/tmpl/banner/edit.php @@ -86,6 +86,5 @@ - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_banners/tmpl/banners/default.php b/administrator/components/com_banners/tmpl/banners/default.php index 7b24a58ff792c..975ff5ea9e223 100644 --- a/administrator/components/com_banners/tmpl/banners/default.php +++ b/administrator/components/com_banners/tmpl/banners/default.php @@ -177,18 +177,12 @@ authorise('core.create', 'com_banners') - && $user->authorise('core.edit', 'com_banners') - && $user->authorise('core.edit.state', 'com_banners') - ) : ?> + if ($this->batchAllowed) : ?> - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_banners/tmpl/banners/emptystate.php b/administrator/components/com_banners/tmpl/banners/emptystate.php index 24425a9e9ce4a..d914a76a204f5 100644 --- a/administrator/components/com_banners/tmpl/banners/emptystate.php +++ b/administrator/components/com_banners/tmpl/banners/emptystate.php @@ -17,8 +17,10 @@ $displayData = [ 'textPrefix' => 'COM_BANNERS', 'formURL' => 'index.php?option=com_banners&view=banners', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Banners', + 'helpURL' => 'https://guide.joomla.org/user-manual/banners/banners-banners', 'icon' => 'icon-bookmark banners', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; $user = $this->getCurrentUser(); diff --git a/administrator/components/com_banners/tmpl/client/edit.php b/administrator/components/com_banners/tmpl/client/edit.php index f7eec3482db98..bc69e03f3ff2e 100644 --- a/administrator/components/com_banners/tmpl/client/edit.php +++ b/administrator/components/com_banners/tmpl/client/edit.php @@ -65,6 +65,5 @@ - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_banners/tmpl/clients/default.php b/administrator/components/com_banners/tmpl/clients/default.php index 36e8899c727ad..5502d061aed39 100644 --- a/administrator/components/com_banners/tmpl/clients/default.php +++ b/administrator/components/com_banners/tmpl/clients/default.php @@ -189,9 +189,7 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_banners/tmpl/clients/emptystate.php b/administrator/components/com_banners/tmpl/clients/emptystate.php index d97f2d15ffd22..247799016d21b 100644 --- a/administrator/components/com_banners/tmpl/clients/emptystate.php +++ b/administrator/components/com_banners/tmpl/clients/emptystate.php @@ -17,8 +17,10 @@ $displayData = [ 'textPrefix' => 'COM_BANNERS_CLIENT', 'formURL' => 'index.php?option=com_banners&view=clients', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Banners:_Clients', + 'helpURL' => 'https://guide.joomla.org/user-manual/banners/banners-banners', 'icon' => 'icon-bookmark banners', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; if (count($this->getCurrentUser()->getAuthorisedCategories('com_banners', 'core.create')) > 0) { diff --git a/administrator/components/com_banners/tmpl/tracks/default.php b/administrator/components/com_banners/tmpl/tracks/default.php index 12c8c26b79dce..83e8ad4ae2cd0 100644 --- a/administrator/components/com_banners/tmpl/tracks/default.php +++ b/administrator/components/com_banners/tmpl/tracks/default.php @@ -92,9 +92,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_banners/tmpl/tracks/emptystate.php b/administrator/components/com_banners/tmpl/tracks/emptystate.php index 13913c3e7c7e8..0000fe803116d 100644 --- a/administrator/components/com_banners/tmpl/tracks/emptystate.php +++ b/administrator/components/com_banners/tmpl/tracks/emptystate.php @@ -14,8 +14,10 @@ $displayData = [ 'textPrefix' => 'COM_BANNERS_TRACKS', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Banners:_Tracks', + 'helpURL' => 'https://guide.joomla.org/user-manual/banners/banners-banners', 'icon' => 'icon-bookmark banners', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; echo LayoutHelper::render('joomla.content.emptystate', $displayData); diff --git a/administrator/components/com_cache/src/Model/CacheModel.php b/administrator/components/com_cache/src/Model/CacheModel.php index 2c270a5c9a369..21bb6ae371cf4 100644 --- a/administrator/components/com_cache/src/Model/CacheModel.php +++ b/administrator/components/com_cache/src/Model/CacheModel.php @@ -10,12 +10,10 @@ namespace Joomla\Component\Cache\Administrator\Model; -use Joomla\CMS\Cache\Cache; use Joomla\CMS\Cache\CacheController; use Joomla\CMS\Cache\Exception\CacheConnectingException; use Joomla\CMS\Cache\Exception\UnsupportedCacheException; use Joomla\CMS\Event\Cache\AfterPurgeEvent; -use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; @@ -172,16 +170,13 @@ public function getData() */ public function getCache() { - $app = Factory::getApplication(); - $options = [ 'defaultgroup' => '', - 'storage' => $app->get('cache_handler', ''), 'caching' => true, - 'cachebase' => $app->get('cache_path', JPATH_CACHE), ]; - return Cache::getInstance('', $options); + return $this->getCacheControllerFactory() + ->createCacheController('output', $options); } /** @@ -263,7 +258,7 @@ public function cleanlist($array) public function purge() { try { - Factory::getCache('')->gc(); + $this->getCache()->gc(); } catch (CacheConnectingException) { return false; } catch (UnsupportedCacheException) { diff --git a/administrator/components/com_cache/src/View/Cache/HtmlView.php b/administrator/components/com_cache/src/View/Cache/HtmlView.php index b30821e8fc67b..c70f0f1087af9 100644 --- a/administrator/components/com_cache/src/View/Cache/HtmlView.php +++ b/administrator/components/com_cache/src/View/Cache/HtmlView.php @@ -107,6 +107,11 @@ public function display($tpl = null): void $this->addToolbar(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_cache/tmpl/cache/default.php b/administrator/components/com_cache/tmpl/cache/default.php index 77ae9c5836892..e107886cc6042 100644 --- a/administrator/components/com_cache/tmpl/cache/default.php +++ b/administrator/components/com_cache/tmpl/cache/default.php @@ -92,9 +92,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_cache/tmpl/cache/emptystate.php b/administrator/components/com_cache/tmpl/cache/emptystate.php index 386e358d53236..6f03195be7b13 100644 --- a/administrator/components/com_cache/tmpl/cache/emptystate.php +++ b/administrator/components/com_cache/tmpl/cache/emptystate.php @@ -14,8 +14,10 @@ $displayData = [ 'textPrefix' => 'COM_CACHE', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Cache', + 'helpURL' => 'https://guide.joomla.org/user-manual/system/system-cache', 'icon' => 'icon-bolt clear', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; echo LayoutHelper::render('joomla.content.emptystate', $displayData); diff --git a/administrator/components/com_categories/helpers/categories.php b/administrator/components/com_categories/helpers/categories.php index 30cde81ad9571..68bb4fa507d09 100644 --- a/administrator/components/com_categories/helpers/categories.php +++ b/administrator/components/com_categories/helpers/categories.php @@ -19,7 +19,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Categories\Administrator\Helper\CategoriesHelper instead */ class CategoriesHelper extends \Joomla\Component\Categories\Administrator\Helper\CategoriesHelper diff --git a/administrator/components/com_categories/src/Controller/AjaxController.php b/administrator/components/com_categories/src/Controller/AjaxController.php index bc6433e1d3996..a92004737c122 100644 --- a/administrator/components/com_categories/src/Controller/AjaxController.php +++ b/administrator/components/com_categories/src/Controller/AjaxController.php @@ -10,13 +10,14 @@ namespace Joomla\Component\Categories\Administrator\Controller; +use Joomla\CMS\Factory; use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\BaseController; use Joomla\CMS\Response\JsonResponse; use Joomla\CMS\Session\Session; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Category; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -63,8 +64,7 @@ public function fetchAssociations() unset($associations[$excludeLang]); // Add the title to each of the associated records - Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_categories/tables'); - $categoryTable = Table::getInstance('Category', '\\Joomla\\CMS\\Table\\'); + $categoryTable = new Category(Factory::getDbo()); foreach ($associations as $association) { $categoryTable->load($association->id); diff --git a/administrator/components/com_categories/src/Field/CategoryeditField.php b/administrator/components/com_categories/src/Field/CategoryeditField.php index 42adbd6bd8462..0a482aa3f9bec 100644 --- a/administrator/components/com_categories/src/Field/CategoryeditField.php +++ b/administrator/components/com_categories/src/Field/CategoryeditField.php @@ -146,7 +146,7 @@ public function __set($name, $value) protected function getOptions() { $options = []; - $published = $this->element['published'] ? explode(',', (string) $this->element['published']) : [0, 1]; + $published = $this->element['published'] ? explode(',', (string) $this->element['published']) : [0, 1, 2]; $name = (string) $this->element['name']; // Let's get the id for the current item, either category or content item. @@ -175,7 +175,7 @@ protected function getOptions() $db = $this->getDatabase(); $user = $this->getCurrentUser(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('a.id', 'value'), @@ -251,10 +251,14 @@ protected function getOptions() $option->text = Text::_('JGLOBAL_ROOT_PARENT'); } - if ($option->published == 1) { - $option->text = str_repeat('- ', !$option->level ? 0 : $option->level - 1) . $option->text; + if ($option->published === 0) { + // Add ' ( Unpublished )' after every unpublished category + $option->text = str_repeat('- ', !$option->level ? 0 : $option->level - 1) . $option->text . ' (' . Text::_('JUNPUBLISHED') . ')'; + } elseif ($option->published === 2) { + // Add ' ( Archived )' after every archived category + $option->text = str_repeat('- ', !$option->level ? 0 : $option->level - 1) . $option->text . ' (' . Text::_('JARCHIVED') . ')'; } else { - $option->text = str_repeat('- ', !$option->level ? 0 : $option->level - 1) . '[' . $option->text . ']'; + $option->text = str_repeat('- ', !$option->level ? 0 : $option->level - 1) . $option->text; } // Displays language code if not set to All @@ -316,7 +320,7 @@ protected function getOptions() && !isset($options[0]) && isset($this->element['show_root']) ) { - $rowQuery = $db->getQuery(true) + $rowQuery = $db->createQuery() ->select( [ $db->quoteName('a.id', 'value'), diff --git a/administrator/components/com_categories/src/Field/ComponentsCategoryField.php b/administrator/components/com_categories/src/Field/ComponentsCategoryField.php index c6599b83b6127..ede94cfa605df 100644 --- a/administrator/components/com_categories/src/Field/ComponentsCategoryField.php +++ b/administrator/components/com_categories/src/Field/ComponentsCategoryField.php @@ -47,7 +47,7 @@ protected function getOptions() $db = $this->getDatabase(); $options = []; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select('DISTINCT ' . $db->quoteName('extension')) ->from($db->quoteName('#__categories')) ->where($db->quoteName('extension') . ' != ' . $db->quote('system')); diff --git a/administrator/components/com_categories/src/Field/Modal/CategoryField.php b/administrator/components/com_categories/src/Field/Modal/CategoryField.php index ba48fdcc64355..0541fa37e7dda 100644 --- a/administrator/components/com_categories/src/Field/Modal/CategoryField.php +++ b/administrator/components/com_categories/src/Field/Modal/CategoryField.php @@ -145,7 +145,7 @@ protected function getValueTitle() if ($value) { try { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__categories')) ->where($db->quoteName('id') . ' = :value') diff --git a/administrator/components/com_categories/src/Helper/CategoriesHelper.php b/administrator/components/com_categories/src/Helper/CategoriesHelper.php index 36d247022ff4a..e8970b7770743 100644 --- a/administrator/components/com_categories/src/Helper/CategoriesHelper.php +++ b/administrator/components/com_categories/src/Helper/CategoriesHelper.php @@ -12,8 +12,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Associations; -use Joomla\CMS\Table\Table; -use Joomla\Database\ParameterType; +use Joomla\Component\Categories\Administrator\Table\CategoryTable; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -29,39 +28,43 @@ class CategoriesHelper /** * Gets a list of associations for a given item. * - * @param integer $pk Content item key. - * @param string $extension Optional extension name. + * @param int|int[] $pk Category ID or array of IDs + * @param string $extension Optional extension name. * - * @return array of associations. + * @return array of associations, optionally grouped by ID */ public static function getAssociations($pk, $extension = 'com_content') { - $langAssociations = Associations::getAssociations($extension, '#__categories', 'com_categories.item', $pk, 'id', 'alias', ''); - $associations = []; - $user = Factory::getUser(); - $groups = $user->getAuthorisedViewLevels(); - - foreach ($langAssociations as $langAssociation) { - // Include only published categories with user access - $arrId = explode(':', $langAssociation->id); - $assocId = (int) $arrId[0]; - $db = Factory::getDbo(); - - $query = $db->getQuery(true) - ->select($db->quoteName('published')) - ->from($db->quoteName('#__categories')) - ->whereIn($db->quoteName('access'), $groups) - ->where($db->quoteName('id') . ' = :associd') - ->bind(':associd', $assocId, ParameterType::INTEGER); - - $result = (int) $db->setQuery($query)->loadResult(); - - if ($result === 1) { - $associations[$langAssociation->language] = $langAssociation->id; + // To avoid doing duplicate database queries. + static $multilanguageAssociations = []; + + // Multilanguage association array key. If the key is already in the array we don't need to run the query again, just return it. + $queryKey = md5(serialize(array_merge([$extension, print_r($pk, true)]))); + + if (!isset($multilanguageAssociations[$queryKey])) { + $multilanguageAssociations[$queryKey] = []; + + $user = Factory::getUser(); + $groups = implode(',', $user->getAuthorisedViewLevels()); + + $advClause = []; + + // Filter by user groups + $advClause[] = 'c2.access IN (' . $groups . ')'; + + // Filter by published categories + $advClause[] = 'c2.published = 1'; + + $associations = Associations::getAssociations($extension, '#__categories', 'com_categories.item', (array) $pk, 'id', 'alias', '', $advClause); + + foreach ($associations as $itemId => $langAssociations) { + foreach ($langAssociations as $langAssociation) { + $multilanguageAssociations[$queryKey][$itemId][$langAssociation->language] = $langAssociation->id; + } } } - return $associations; + return \is_array($pk) ? $multilanguageAssociations[$queryKey] : ($multilanguageAssociations[$queryKey][$pk] ?? []); } /** @@ -74,7 +77,7 @@ public static function getAssociations($pk, $extension = 'com_content') */ public static function validateCategoryId($catid, $extension) { - $categoryTable = Table::getInstance('CategoryTable', '\\Joomla\\Component\\Categories\\Administrator\\Table\\'); + $categoryTable = new CategoryTable(Factory::getDbo()); $data = []; $data['id'] = $catid; diff --git a/administrator/components/com_categories/src/Helper/CategoryAssociationHelper.php b/administrator/components/com_categories/src/Helper/CategoryAssociationHelper.php index f4d1950b519a4..5d27fb370e26b 100644 --- a/administrator/components/com_categories/src/Helper/CategoryAssociationHelper.php +++ b/administrator/components/com_categories/src/Helper/CategoryAssociationHelper.php @@ -32,42 +32,44 @@ abstract class CategoryAssociationHelper /** * Method to get the associations for a given category * - * @param integer $id Id of the item + * @param int|int[] $id ID of the item or array of IDs * @param string $extension Name of the component * @param string|null $layout Category layout * - * @return array Array of associations for the component categories + * @return array Array of associations for the component categories, optionally grouped by ID * * @since 3.0 */ - public static function getCategoryAssociations($id = 0, $extension = 'com_content', $layout = null) + public static function getCategoryAssociations($id, $extension = 'com_content', $layout = null) { $return = []; if ($id) { $helperClassname = ucfirst(substr($extension, 4)) . 'HelperRoute'; - $associations = CategoriesHelper::getAssociations($id, $extension); + $associations = CategoriesHelper::getAssociations((array) $id, $extension); - foreach ($associations as $tag => $item) { - if (class_exists($helperClassname) && \is_callable([$helperClassname, 'getCategoryRoute'])) { - $return[$tag] = $helperClassname::getCategoryRoute($item, $tag, $layout); - } else { - $link = 'index.php?option=' . $extension . '&view=category&id=' . $item; + foreach ($associations as $itemId => $itemAssociations) { + foreach ($itemAssociations as $tag => $item) { + if (class_exists($helperClassname) && \is_callable([$helperClassname, 'getCategoryRoute'])) { + $return[$itemId][$tag] = $helperClassname::getCategoryRoute($item, $tag, $layout); + } else { + $link = 'index.php?option=' . $extension . '&view=category&id=' . $item; - if ($tag && $tag !== '*') { - $link .= '&lang=' . $tag; - } + if ($tag && $tag !== '*') { + $link .= '&lang=' . $tag; + } - if ($layout) { - $link .= '&layout=' . $layout; - } + if ($layout) { + $link .= '&layout=' . $layout; + } - $return[$tag] = $link; + $return[$itemId][$tag] = $link; + } } } } - return $return; + return \is_array($id) ? $return : ($return[$id] ?? []); } } diff --git a/administrator/components/com_categories/src/Model/CategoriesModel.php b/administrator/components/com_categories/src/Model/CategoriesModel.php index 1b37ffd09caa8..f5a016a9fedbc 100644 --- a/administrator/components/com_categories/src/Model/CategoriesModel.php +++ b/administrator/components/com_categories/src/Model/CategoriesModel.php @@ -16,7 +16,7 @@ use Joomla\CMS\Language\Associations; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Category; use Joomla\Database\ParameterType; use Joomla\Database\QueryInterface; use Joomla\Utilities\ArrayHelper; @@ -164,7 +164,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = $this->getCurrentUser(); // Select the required fields from the table. @@ -251,7 +251,7 @@ protected function getListQuery() if (\count($categoryId)) { // Case: Using both categories filter and by level filter - $categoryTable = Table::getInstance('Category', 'JTable'); + $categoryTable = new Category($db); $subCatItemsWhere = []; foreach ($categoryId as $filterCatId) { @@ -341,7 +341,7 @@ protected function getListQuery() $includeNone = true; } - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where( @@ -359,7 +359,7 @@ protected function getListQuery() ->bind(':typeAlias', $typeAlias); if ($includeNone) { - $subQuery2 = $db->getQuery(true) + $subQuery2 = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('type_alias') . ' = :typeAlias2'); @@ -378,7 +378,7 @@ protected function getListQuery() $tag = (int) $tag; if ($tag === 0) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('type_alias') . ' = :typeAlias'); diff --git a/administrator/components/com_categories/src/Model/CategoryModel.php b/administrator/components/com_categories/src/Model/CategoryModel.php index e26c9230fada7..b60f7c73dc15b 100644 --- a/administrator/components/com_categories/src/Model/CategoryModel.php +++ b/administrator/components/com_categories/src/Model/CategoryModel.php @@ -26,8 +26,10 @@ use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Table\Category; use Joomla\CMS\UCM\UCMType; +use Joomla\CMS\Versioning\VersionableModelInterface; use Joomla\CMS\Versioning\VersionableModelTrait; use Joomla\Component\Categories\Administrator\Helper\CategoriesHelper; +use Joomla\Component\Categories\Administrator\Table\CategoryTable; use Joomla\Database\ParameterType; use Joomla\Filesystem\Path; use Joomla\Registry\Registry; @@ -43,7 +45,7 @@ * * @since 1.6 */ -class CategoryModel extends AdminModel +class CategoryModel extends AdminModel implements VersionableModelInterface { use VersionableModelTrait; @@ -242,9 +244,10 @@ public function getItem($pk = null) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -264,10 +267,6 @@ public function getForm($data = [], $loadData = true) // Get the form. $form = $this->loadForm('com_categories.category' . $extension, 'category', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - // Modify the form based on Edit State access controls. if (empty($data['extension'])) { $data['extension'] = $extension; @@ -337,18 +336,12 @@ protected function loadFormData() $extension = substr($app->getUserState('com_categories.categories.filter.extension', ''), 4); $filters = (array) $app->getUserState('com_categories.categories.' . $extension . '.filter'); - $data->set( + $data->published = $app->getInput()->getInt( 'published', - $app->getInput()->getInt( - 'published', - ((isset($filters['published']) && $filters['published'] !== '') ? $filters['published'] : null) - ) - ); - $data->set('language', $app->getInput()->getString('language', (!empty($filters['language']) ? $filters['language'] : null))); - $data->set( - 'access', - $app->getInput()->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access'))) + ((isset($filters['published']) && $filters['published'] !== '') ? $filters['published'] : null) ); + $data->language = $app->getInput()->getString('language', (!empty($filters['language']) ? $filters['language'] : null)); + $data->access = $app->getInput()->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access'))); } } @@ -508,28 +501,19 @@ protected function preprocessForm(Form $form, $data, $group = 'content') */ public function save($data) { - $table = $this->getTable(); - $input = Factory::getApplication()->getInput(); - $pk = (!empty($data['id'])) ? $data['id'] : (int) $this->getState($this->getName() . '.id'); - $isNew = true; - $context = $this->option . '.' . $this->name; + $assoc = $this->getAssoc(); - if (!empty($data['tags']) && $data['tags'][0] != '') { - $table->newTags = $data['tags']; + if (!$assoc) { + $this->associationsContext = null; } - // Include the plugins for the save events. - PluginHelper::importPlugin($this->events_map['save']); + $table = $this->getTable(); + $input = Factory::getApplication()->getInput(); + $pk = (!empty($data['id'])) ? $data['id'] : (int) $this->getState($this->getName() . '.id'); // Load the row if saving an existing category. if ($pk > 0) { $table->load($pk); - $isNew = false; - } - - // Set the new parent id if parent id not matched OR while New/Save as Copy . - if ($table->parent_id != $data['parent_id'] || $data['id'] == 0) { - $table->setLocation($data['parent_id'], 'last-child'); } // Alter the title for save as copy @@ -550,179 +534,55 @@ public function save($data) $data['published'] = 0; } - // Bind the data. - if (!$table->bind($data)) { - $this->setError($table->getError()); - - return false; - } - - // Bind the rules. - if (isset($data['rules'])) { - $rules = new Rules($data['rules']); - $table->setRules($rules); - } - - // Check the data. - if (!$table->check()) { - $this->setError($table->getError()); + $result = parent::save($data); - return false; - } + if ($result) { + /** + * @var CategoryTable + */ + $table = $this->getTable(); - // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, [$context, &$table, $isNew, $data]); + $categoryId = $this->getState($this->getName() . '.id'); - if (\in_array(false, $result, true)) { - $this->setError($table->getError()); + $table->load($categoryId); - return false; - } - - // Store the data. - if (!$table->store()) { - $this->setError($table->getError()); - - return false; - } - - $assoc = $this->getAssoc(); - - if ($assoc) { - // Adding self to the association - $associations = $data['associations'] ?? []; - - // Unset any invalid associations - $associations = ArrayHelper::toInteger($associations); - - foreach ($associations as $tag => $id) { - if (!$id) { - unset($associations[$tag]); - } - } - - // Detecting all item menus - $allLanguage = $table->language == '*'; - - if ($allLanguage && !empty($associations)) { - Factory::getApplication()->enqueueMessage(Text::_('COM_CATEGORIES_ERROR_ALL_LANGUAGE_ASSOCIATED'), 'notice'); - } - - // Get associationskey for edited item - $db = $this->getDatabase(); - $id = (int) $table->id; - $query = $db->getQuery(true) - ->select($db->quoteName('key')) - ->from($db->quoteName('#__associations')) - ->where($db->quoteName('context') . ' = :associationscontext') - ->where($db->quoteName('id') . ' = :id') - ->bind(':associationscontext', $this->associationsContext) - ->bind(':id', $id, ParameterType::INTEGER); - $db->setQuery($query); - $oldKey = $db->loadResult(); - - if ($associations || $oldKey !== null) { - $where = []; - - // Deleting old associations for the associated items - $query = $db->getQuery(true) - ->delete($db->quoteName('#__associations')) - ->where($db->quoteName('context') . ' = :associationscontext') - ->bind(':associationscontext', $this->associationsContext); - - if ($associations) { - $where[] = $db->quoteName('id') . ' IN (' . implode(',', $query->bindArray(array_values($associations))) . ')'; - } - - if ($oldKey !== null) { - $where[] = $db->quoteName('key') . ' = :oldKey'; - $query->bind(':oldKey', $oldKey); - } - - $query->extendWhere('AND', $where, 'OR'); - } - - $db->setQuery($query); - - try { - $db->execute(); - } catch (\RuntimeException $e) { - $this->setError($e->getMessage()); + // Rebuild the path for the category: + if (!$table->rebuildPath($table->id)) { + $this->setError($table->getError()); return false; } - // Adding self to the association - if (!$allLanguage) { - $associations[$table->language] = (int) $table->id; - } - - if (\count($associations) > 1) { - // Adding new association for these items - $key = md5(json_encode($associations)); - $query->clear() - ->insert($db->quoteName('#__associations')) - ->columns( - [ - $db->quoteName('id'), - $db->quoteName('context'), - $db->quoteName('key'), - ] - ); - - foreach ($associations as $id) { - $id = (int) $id; - - $query->values( - implode( - ',', - $query->bindArray( - [$id, $this->associationsContext, $key], - [ParameterType::INTEGER, ParameterType::STRING, ParameterType::STRING] - ) - ) - ); - } - - $db->setQuery($query); - - try { - $db->execute(); - } catch (\RuntimeException $e) { - $this->setError($e->getMessage()); + // Rebuild the paths of the category's children: + if (!$table->rebuild($table->id, $table->lft, $table->level, $table->path)) { + $this->setError($table->getError()); - return false; - } + return false; } } - // Trigger the after save event. - Factory::getApplication()->triggerEvent($this->event_after_save, [$context, &$table, $isNew, $data]); - - // Rebuild the path for the category: - if (!$table->rebuildPath($table->id)) { - $this->setError($table->getError()); - - return false; - } - - // Rebuild the paths of the category's children: - if (!$table->rebuild($table->id, $table->lft, $table->level, $table->path)) { - $this->setError($table->getError()); + return $result; + } - return false; - } + /** + * Prepare and sanitise the table data prior to saving. + * + * @param Table $table A reference to a Table object. + * + * @return void + * + * @since 6.1.0 + */ + protected function prepareTable($table) + { + $oldTable = clone $table; - $this->setState($this->getName() . '.id', $table->id); + $oldTable->load(); - if (Factory::getApplication()->getInput()->get('task') == 'editAssociations') { - return $this->redirectToAssociations($data); + // Set the new parent id if parent id not matched OR while New/Save as Copy . + if (empty($table->id) || (int) $table->parent_id !== (int) $oldTable->parent_id) { + $table->setLocation($table->parent_id, 'last-child'); } - - // Clear the cache - $this->cleanCache(); - - return true; } /** @@ -825,7 +685,7 @@ protected function batchFlipordering($value, $pks, $contexts) $successful = []; $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); /** * For each category get the max ordering value @@ -934,7 +794,7 @@ protected function batchCopy($value, $pks, $contexts) $parents = []; // Calculate the emergency stop count as a precaution against a runaway loop bug - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(' . $db->quoteName('id') . ')') ->from($db->quoteName('#__categories')); $db->setQuery($query); @@ -968,6 +828,13 @@ protected function batchCopy($value, $pks, $contexts) continue; } + // Check that the user is allowed to access the item + if (!$this->user->authorise('core.edit', $contexts[$pk])) { + $this->setError(Text::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + + return false; + } + // Copy is a bit tricky, because we also need to copy the children $lft = (int) $this->table->lft; $rgt = (int) $this->table->rgt; @@ -1085,7 +952,7 @@ protected function batchMove($value, $pks, $contexts) $this->type = $type->getTypeByAlias($this->typeAlias); $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $extension = Factory::getApplication()->getInput()->get('extension', '', 'word'); // Check that the parent exists. @@ -1217,15 +1084,13 @@ protected function batchMove($value, $pks, $contexts) /** * Custom clean the cache of com_content and content modules * - * @param string $group Cache group name. - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 1.6 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { $extension = Factory::getApplication()->getInput()->get('extension'); diff --git a/administrator/components/com_categories/src/Service/HTML/AdministratorService.php b/administrator/components/com_categories/src/Service/HTML/AdministratorService.php index c2c819e1f5960..cddb935cf5517 100644 --- a/administrator/components/com_categories/src/Service/HTML/AdministratorService.php +++ b/administrator/components/com_categories/src/Service/HTML/AdministratorService.php @@ -52,7 +52,7 @@ public function association($catid, $extension = 'com_content') // Get the associated categories $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('c.id'), diff --git a/administrator/components/com_categories/src/View/Categories/HtmlView.php b/administrator/components/com_categories/src/View/Categories/HtmlView.php index 961b9f3d181e9..0c6da623efd26 100644 --- a/administrator/components/com_categories/src/View/Categories/HtmlView.php +++ b/administrator/components/com_categories/src/View/Categories/HtmlView.php @@ -156,7 +156,7 @@ public function display($tpl = null) // Add form control fields $this->filterForm ->addControlField('extension', $this->state->get('filter.extension', '')) - ->addControlField('task', '') + ->addControlField('task') ->addControlField('boxchecked', '0'); parent::display($tpl); diff --git a/administrator/components/com_categories/src/View/Category/HtmlView.php b/administrator/components/com_categories/src/View/Category/HtmlView.php index 7e54e36d6af94..f387b6750cf9f 100644 --- a/administrator/components/com_categories/src/View/Category/HtmlView.php +++ b/administrator/components/com_categories/src/View/Category/HtmlView.php @@ -141,7 +141,7 @@ public function display($tpl = null) // Add form control fields $this->form - ->addControlField('task', '') + ->addControlField('task') ->addControlField('return', $input->getBase64('return', '')) ->addControlField('forcedLanguage', $forcedLanguage); diff --git a/administrator/components/com_categories/tmpl/categories/default.php b/administrator/components/com_categories/tmpl/categories/default.php index a6be402cc7ed2..7f243f78f577d 100644 --- a/administrator/components/com_categories/tmpl/categories/default.php +++ b/administrator/components/com_categories/tmpl/categories/default.php @@ -10,13 +10,13 @@ defined('_JEXEC') or die; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; -use Joomla\String\Inflector; /** @var \Joomla\Component\Categories\Administrator\View\Categories\HtmlView $this */ @@ -38,10 +38,10 @@ if (count($parts) > 1) { $section = $parts[1]; - $inflector = Inflector::getInstance(); + $inflector = InflectorFactory::create()->build(); - if (!$inflector->isPlural($section)) { - $section = $inflector->toPlural($section); + if ($inflector->pluralize($inflector->singularize($section)) !== $section) { + $section = $inflector->pluralize($section); } } diff --git a/administrator/components/com_categories/tmpl/categories/default_batch_body.php b/administrator/components/com_categories/tmpl/categories/default_batch_body.php index 22b7963dc4f70..721b6703d3da8 100644 --- a/administrator/components/com_categories/tmpl/categories/default_batch_body.php +++ b/administrator/components/com_categories/tmpl/categories/default_batch_body.php @@ -20,6 +20,9 @@ $published = (int) $this->state->get('filter.published'); $extension = $this->escape($this->state->get('filter.extension')); +/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ +$wa = $this->getDocument()->getWebAssetManager(); +$wa->useScript('joomla.batch-copymove'); ?>
diff --git a/administrator/components/com_categories/tmpl/categories/emptystate.php b/administrator/components/com_categories/tmpl/categories/emptystate.php index 96049dd3532aa..7ddf8b16f99ec 100644 --- a/administrator/components/com_categories/tmpl/categories/emptystate.php +++ b/administrator/components/com_categories/tmpl/categories/emptystate.php @@ -42,6 +42,8 @@ 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Category', 'title' => $title, 'icon' => 'icon-folder categories content-categories', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; if ($this->getCurrentUser()->authorise('core.create', $extension)) { diff --git a/administrator/components/com_categories/tmpl/categories/modal.php b/administrator/components/com_categories/tmpl/categories/modal.php index e16028f85ccd6..ada82ae3c44c4 100644 --- a/administrator/components/com_categories/tmpl/categories/modal.php +++ b/administrator/components/com_categories/tmpl/categories/modal.php @@ -33,7 +33,7 @@ ->useScript('modal-content-select'); $extension = $this->escape($this->state->get('filter.extension')); -// @todo: Use of Function is deprecated and should be removed in 6.0. It stays only for backward compatibility. +// @todo: Use of Function is deprecated and should be removed in 7.0. It stays only for backward compatibility. $function = $app->getInput()->getCmd('function', 'jSelectCategory'); $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); diff --git a/administrator/components/com_checkin/src/Model/CheckinModel.php b/administrator/components/com_checkin/src/Model/CheckinModel.php index dc04faf060efa..c1b5c374fea03 100644 --- a/administrator/components/com_checkin/src/Model/CheckinModel.php +++ b/administrator/components/com_checkin/src/Model/CheckinModel.php @@ -106,7 +106,7 @@ public function checkin($ids = []) continue; } - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($tn)) ->set($db->quoteName('checked_out') . ' = DEFAULT'); @@ -184,7 +184,7 @@ public function getItems() continue; } - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName($tn)); diff --git a/administrator/components/com_checkin/src/View/Checkin/HtmlView.php b/administrator/components/com_checkin/src/View/Checkin/HtmlView.php index f1bdb14870839..09fecd0d82e1e 100644 --- a/administrator/components/com_checkin/src/View/Checkin/HtmlView.php +++ b/administrator/components/com_checkin/src/View/Checkin/HtmlView.php @@ -108,6 +108,11 @@ public function display($tpl = null) $this->addToolbar(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_checkin/tmpl/checkin/default.php b/administrator/components/com_checkin/tmpl/checkin/default.php index 4067943b59336..2951960cec7b1 100644 --- a/administrator/components/com_checkin/tmpl/checkin/default.php +++ b/administrator/components/com_checkin/tmpl/checkin/default.php @@ -72,9 +72,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?>
diff --git a/administrator/components/com_checkin/tmpl/checkin/emptystate.php b/administrator/components/com_checkin/tmpl/checkin/emptystate.php index 5f8dfdada745f..6ecb1cc0a0716 100644 --- a/administrator/components/com_checkin/tmpl/checkin/emptystate.php +++ b/administrator/components/com_checkin/tmpl/checkin/emptystate.php @@ -18,6 +18,8 @@ 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Maintenance:_Global_Check-in', 'icon' => 'icon-check-square', 'title' => Text::_('COM_CHECKIN_GLOBAL_CHECK_IN'), + + 'controlFields' => $this->filterForm->renderControlFields(), ]; echo LayoutHelper::render('joomla.content.emptystate', $displayData); diff --git a/administrator/components/com_config/forms/application.xml b/administrator/components/com_config/forms/application.xml index 8f48019424b54..3e9bb13234a0e 100644 --- a/administrator/components/com_config/forms/application.xml +++ b/administrator/components/com_config/forms/application.xml @@ -357,7 +357,7 @@ label="Access-Control-Allow-Headers" description="COM_CONFIG_FIELD_WEBSERVICES_CORS_ALLOW_HEADERS_DESC" translate_label="false" - default="Content-Type,X-Joomla-Token" + default="Content-Type,X-Joomla-Token,Authorization" showon="cors:1" /> diff --git a/administrator/components/com_config/src/Field/ConfigComponentsField.php b/administrator/components/com_config/src/Field/ConfigComponentsField.php index 7ec5fb115417f..d63b17e649693 100644 --- a/administrator/components/com_config/src/Field/ConfigComponentsField.php +++ b/administrator/components/com_config/src/Field/ConfigComponentsField.php @@ -44,7 +44,7 @@ class ConfigComponentsField extends ListField protected function getOptions() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('name AS text, element AS value') ->from('#__extensions') ->where('enabled >= 1') diff --git a/administrator/components/com_config/src/Field/FiltersField.php b/administrator/components/com_config/src/Field/FiltersField.php index d2b5a6a9cc2e5..d851735ae21e9 100644 --- a/administrator/components/com_config/src/Field/FiltersField.php +++ b/administrator/components/com_config/src/Field/FiltersField.php @@ -162,7 +162,7 @@ protected function getUserGroups() $db = $this->getDatabase(); // Get the user groups from the database. - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select('a.id AS value, a.title AS text, COUNT(DISTINCT b.id) AS level, a.parent_id as parent'); $query->from('#__usergroups AS a'); $query->join('LEFT', '#__usergroups AS b on a.lft > b.lft AND a.rgt < b.rgt'); diff --git a/administrator/components/com_config/src/Helper/ConfigHelper.php b/administrator/components/com_config/src/Helper/ConfigHelper.php index 115d384402162..92c472b351057 100644 --- a/administrator/components/com_config/src/Helper/ConfigHelper.php +++ b/administrator/components/com_config/src/Helper/ConfigHelper.php @@ -36,7 +36,7 @@ class ConfigHelper extends ContentHelper public static function getAllComponents() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('element') ->from('#__extensions') ->where('type = ' . $db->quote('component')) diff --git a/administrator/components/com_config/src/Model/ApplicationModel.php b/administrator/components/com_config/src/Model/ApplicationModel.php index 89cd7abc42bef..e954140844f90 100644 --- a/administrator/components/com_config/src/Model/ApplicationModel.php +++ b/administrator/components/com_config/src/Model/ApplicationModel.php @@ -18,7 +18,7 @@ use Joomla\CMS\Event\Application\AfterSaveConfigurationEvent; use Joomla\CMS\Event\Application\BeforeSaveConfigurationEvent; use Joomla\CMS\Factory; -use Joomla\CMS\Http\HttpFactory; +use Joomla\CMS\Language\LanguageFactoryInterface; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\Mail\Exception\MailDisabledException; @@ -27,15 +27,16 @@ use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Model\FormModel; use Joomla\CMS\Table\Asset; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; use Joomla\CMS\Uri\Uri; use Joomla\CMS\User\UserHelper; -use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseFactory; use Joomla\Database\ParameterType; use Joomla\Filesystem\File; use Joomla\Filesystem\Folder; use Joomla\Filesystem\Path; use Joomla\Filter\OutputFilter; +use Joomla\Http\HttpFactory; use Joomla\Registry\Registry; use Joomla\Utilities\ArrayHelper; use PHPMailer\PHPMailer\Exception as phpMailerException; @@ -67,20 +68,14 @@ class ApplicationModel extends FormModel implements MailerFactoryAwareInterface * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return mixed A Form object on success, false on failure + * @return mixed A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_config.application', 'application', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_config.application', 'application', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -328,7 +323,7 @@ public function save($data) } try { - $revisedDbo = DatabaseDriver::getInstance($options); + $revisedDbo = (new DatabaseFactory())->getDriver($options['driver'], $options); $revisedDbo->getVersion(); } catch (\Exception $e) { $app->enqueueMessage(Text::sprintf('COM_CONFIG_ERROR_DATABASE_NOT_AVAILABLE', $e->getCode(), $e->getMessage()), 'error'); @@ -364,7 +359,7 @@ public function save($data) CURLOPT_PROXYUSERPWD => null, ] ); - $response = HttpFactory::getHttp($options)->get('https://' . $host . Uri::root(true) . '/', ['Host' => $host], 10); + $response = (new HttpFactory())->getHttp($options)->get('https://' . $host . Uri::root(true) . '/', ['Host' => $host], 10); // If available in HTTPS check also the status code. if (!\in_array($response->getStatusCode(), [200, 503, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 401], true)) { @@ -397,7 +392,7 @@ public function save($data) return false; } - $asset = Table::getInstance('asset'); + $asset = new Asset($this->getDatabase()); if ($asset->loadByName('root.1')) { $asset->rules = (string) $rules; @@ -420,7 +415,7 @@ public function save($data) if (isset($data['filters'])) { $registry = new Registry(['filters' => $data['filters']]); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); // Get extension_id $extensionId = $extension->find(['name' => 'com_config']); @@ -461,7 +456,7 @@ public function save($data) // Purge the database session table if we are changing to the database handler. if ($prev['session_handler'] != 'database' && $data['session_handler'] == 'database') { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__session')) ->where($db->quoteName('time') . ' < ' . (time() - 1)); $db->setQuery($query); @@ -474,7 +469,7 @@ public function save($data) // If we are are using the session handler, purge the extra columns, otherwise truncate the whole session table if ($data['session_handler'] === 'database') { $revisedDbo->setQuery( - $revisedDbo->getQuery(true) + $revisedDbo->createQuery() ->update('#__session') ->set( [ @@ -628,7 +623,9 @@ public function save($data) // Clean the cache if disabled but previously enabled or changing cache handlers; these operations use the `$prev` data already in memory if ((!$data['caching'] && $prev['caching']) || $data['cache_handler'] !== $prev['cache_handler']) { try { - Factory::getCache()->clean(); + $this->getCacheControllerFactory() + ->createCacheController('callback', ['defaultgroup' => '']) + ->clean(); } catch (CacheConnectingException) { try { Log::add(Text::_('COM_CONFIG_ERROR_CACHE_CONNECTION_FAILED'), Log::WARNING, 'jerror'); @@ -747,7 +744,7 @@ public function save($data) // Overwrite webservices cors settings $app->set('cors', $data['cors'] ?? 0); $app->set('cors_allow_origin', $data['cors_allow_origin'] ?? '*'); - $app->set('cors_allow_headers', $data['cors_allow_headers'] ?? 'Content-Type,X-Joomla-Token'); + $app->set('cors_allow_headers', $data['cors_allow_headers'] ?? 'Content-Type,X-Joomla-Token,Authorization'); $app->set('cors_allow_methods', $data['cors_allow_methods'] ?? ''); // Clear cache of com_config component. @@ -941,8 +938,7 @@ public function storePermissions($permission = null) } try { - /** @var Asset $asset */ - $asset = Table::getInstance('asset'); + $asset = new Asset($this->getDatabase()); $result = $asset->loadByName($permission['component']); if ($result === false) { @@ -954,8 +950,7 @@ public function storePermissions($permission = null) $asset->title = (string) $permission['title']; // Get the parent asset id so we have a correct tree. - /** @var Asset $parentAsset */ - $parentAsset = Table::getInstance('Asset'); + $parentAsset = new Asset($this->getDatabase()); if (str_contains($asset->name, '.')) { $assetParts = explode('.', $asset->name); @@ -1036,7 +1031,7 @@ public function storePermissions($permission = null) $db = $this->getDatabase(); // Get the asset id by the name of the component. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__assets')) ->where($db->quoteName('name') . ' = :component') @@ -1218,17 +1213,22 @@ public function sendTestMail() $mail = $this->getMailerFactory()->createMailer($config); // Prepare email and try to send it - $mailer = new MailTemplate('com_config.test_mail', $user->getParam('language', $app->get('language')), $mail); + $mailer = new MailTemplate( + 'com_config.test_mail', + $user->getParam('language', $app->get('language')), + $mail, + Factory::getContainer()->get(LanguageFactoryInterface::class), + $this->getDatabase() + ); $mailer->addTemplateData( [ // Replace the occurrences of "@" and "|" in the site name 'sitename' => str_replace(['@', '|'], '', $app->get('sitename')), - 'method' => Text::_('COM_CONFIG_SENDMAIL_METHOD_' . strtoupper($mail->Mailer)), + 'method' => Text::_('COM_CONFIG_SENDMAIL_METHOD_' . strtoupper($mail->Mailer ?? $input->get('mailer'))), ] ); $mailer->addRecipient($user->email, $user->name); - try { $mailSent = $mailer->send(); } catch (MailDisabledException | phpMailerException $e) { @@ -1238,10 +1238,10 @@ public function sendTestMail() } if ($mailSent === true) { - $methodName = Text::_('COM_CONFIG_SENDMAIL_METHOD_' . strtoupper($mail->Mailer)); + $methodName = Text::_('COM_CONFIG_SENDMAIL_METHOD_' . strtoupper($mail->Mailer ?? $input->get('mailer'))); - // If JMail send the mail using PHP Mail as fallback. - if ($mail->Mailer !== $app->get('mailer')) { + // If Mail send the mail using PHP Mail as fallback. + if (($mail->Mailer ?? $app->get('mailer')) !== $app->get('mailer')) { $app->enqueueMessage(Text::sprintf('COM_CONFIG_SENDMAIL_SUCCESS_FALLBACK', $user->email, $methodName), 'warning'); } else { $app->enqueueMessage(Text::sprintf('COM_CONFIG_SENDMAIL_SUCCESS', $user->email, $methodName), 'message'); diff --git a/administrator/components/com_config/src/Model/ComponentModel.php b/administrator/components/com_config/src/Model/ComponentModel.php index 0a80503e4e836..e424760b2005f 100644 --- a/administrator/components/com_config/src/Model/ComponentModel.php +++ b/administrator/components/com_config/src/Model/ComponentModel.php @@ -13,12 +13,15 @@ use Joomla\CMS\Access\Access; use Joomla\CMS\Access\Rules; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\Model\BeforeSaveEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\FormModel; use Joomla\CMS\Plugin\PluginHelper; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Asset; +use Joomla\CMS\Table\Extension; use Joomla\Filesystem\Path; // phpcs:disable PSR1.Files.SideEffects @@ -64,9 +67,10 @@ protected function populateState() * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return mixed A Form object on success, false on failure + * @return Form A Form object * * @since 3.2 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -90,10 +94,6 @@ public function getForm($data = [], $loadData = true) '/config' ); - if (empty($form)) { - return false; - } - $lang = Factory::getLanguage(); $lang->load($option, JPATH_BASE) || $lang->load($option, JPATH_BASE . "/components/$option"); @@ -156,9 +156,10 @@ public function getComponent() */ public function save($data) { - $table = Table::getInstance('extension'); + $table = new Extension($this->getDatabase()); $context = $this->option . '.' . $this->name; - PluginHelper::importPlugin('extension'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('extension', null, true, $dispatcher); // Check super user group. if (isset($data['params']) && !$this->getCurrentUser()->authorise('core.admin')) { @@ -184,10 +185,10 @@ public function save($data) } $rules = new Rules($data['params']['rules']); - $asset = Table::getInstance('asset'); + $asset = new Asset($this->getDatabase()); if (!$asset->loadByName($data['option'])) { - $root = Table::getInstance('asset'); + $root = new Asset($this->getDatabase()); $root->loadByName('root.1'); $asset->name = $data['option']; $asset->title = $data['option']; @@ -221,14 +222,24 @@ public function save($data) throw new \RuntimeException($table->getError()); } - $result = Factory::getApplication()->triggerEvent('onExtensionBeforeSave', [$context, $table, false]); + $result = $dispatcher->dispatch('onExtensionBeforeSave', new BeforeSaveEvent('onExtensionBeforeSave', [ + 'context' => $context, + 'subject' => $table, + 'isNew' => false, + 'data' => $data, + ]))->getArgument('result', []); // Store the data. if (\in_array(false, $result, true) || !$table->store()) { throw new \RuntimeException($table->getError()); } - Factory::getApplication()->triggerEvent('onExtensionAfterSave', [$context, $table, false]); + $dispatcher->dispatch('onExtensionAfterSave', new AfterSaveEvent('onExtensionAfterSave', [ + 'context' => $context, + 'subject' => $table, + 'isNew' => false, + 'data' => $data, + ])); // Clean the component cache. $this->cleanCache('_system'); diff --git a/administrator/components/com_config/src/View/Application/HtmlView.php b/administrator/components/com_config/src/View/Application/HtmlView.php index 6ec11ecb289a1..74a40f3ade163 100644 --- a/administrator/components/com_config/src/View/Application/HtmlView.php +++ b/administrator/components/com_config/src/View/Application/HtmlView.php @@ -125,6 +125,10 @@ public function display($tpl = null) $this->addToolbar(); + // Add form control fields + $this->form + ->addControlField('task'); + parent::display($tpl); } diff --git a/administrator/components/com_config/src/View/Component/HtmlView.php b/administrator/components/com_config/src/View/Component/HtmlView.php index 486824d9f564d..ce413d93a57cc 100644 --- a/administrator/components/com_config/src/View/Component/HtmlView.php +++ b/administrator/components/com_config/src/View/Component/HtmlView.php @@ -125,6 +125,13 @@ public function display($tpl = null) $this->addToolbar(); + // Add form control fields + $this->form + ->addControlField('task') + ->addControlField('id', $this->component->id) + ->addControlField('component', $this->component->option) + ->addControlField('return', $this->return); + parent::display($tpl); } diff --git a/administrator/components/com_config/tmpl/application/default.php b/administrator/components/com_config/tmpl/application/default.php index 828f1cfaeac5a..21818e6b44b45 100644 --- a/administrator/components/com_config/tmpl/application/default.php +++ b/administrator/components/com_config/tmpl/application/default.php @@ -78,8 +78,7 @@ - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_config/tmpl/component/default.php b/administrator/components/com_config/tmpl/component/default.php index 606956287439a..2cef0bd0cd4f0 100644 --- a/administrator/components/com_config/tmpl/component/default.php +++ b/administrator/components/com_config/tmpl/component/default.php @@ -136,10 +136,6 @@ - - - - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_contact/forms/contact.xml b/administrator/components/com_contact/forms/contact.xml index 6e4754dd826dd..78164130415f5 100644 --- a/administrator/components/com_contact/forms/contact.xml +++ b/administrator/components/com_contact/forms/contact.xml @@ -205,6 +205,11 @@ class="advancedSelect" multiple="true" /> + +
diff --git a/administrator/components/com_contact/helpers/contact.php b/administrator/components/com_contact/helpers/contact.php index e9af534cf1693..1a2b9e5d6e137 100644 --- a/administrator/components/com_contact/helpers/contact.php +++ b/administrator/components/com_contact/helpers/contact.php @@ -19,7 +19,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Contact\Administrator\Helper\ContactHelper instead */ class ContactHelper extends \Joomla\Component\Contact\Administrator\Helper\ContactHelper diff --git a/administrator/components/com_contact/src/Field/Modal/ContactField.php b/administrator/components/com_contact/src/Field/Modal/ContactField.php index 7dc872ac6db99..6832f18b7e8e0 100644 --- a/administrator/components/com_contact/src/Field/Modal/ContactField.php +++ b/administrator/components/com_contact/src/Field/Modal/ContactField.php @@ -138,7 +138,7 @@ protected function getValueTitle() if ($value) { try { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('name')) ->from($db->quoteName('#__contact_details')) ->where($db->quoteName('id') . ' = :value') diff --git a/administrator/components/com_contact/src/Helper/AssociationsHelper.php b/administrator/components/com_contact/src/Helper/AssociationsHelper.php index 35ee395ac5dfd..f98624830373d 100644 --- a/administrator/components/com_contact/src/Helper/AssociationsHelper.php +++ b/administrator/components/com_contact/src/Helper/AssociationsHelper.php @@ -11,8 +11,11 @@ namespace Joomla\Component\Contact\Administrator\Helper; use Joomla\CMS\Association\AssociationExtensionHelper; +use Joomla\CMS\Factory; use Joomla\CMS\Language\Associations; +use Joomla\CMS\Table\Category; use Joomla\CMS\Table\Table; +use Joomla\Component\Contact\Administrator\Table\ContactTable; use Joomla\Component\Contact\Site\Helper\AssociationHelper; // phpcs:disable PSR1.Files.SideEffects @@ -124,11 +127,11 @@ public function getItem($typeName, $id) switch ($typeName) { case 'contact': - $table = Table::getInstance('ContactTable', 'Joomla\\Component\\Contact\\Administrator\\Table\\'); + $table = new ContactTable(Factory::getDbo()); break; case 'category': - $table = Table::getInstance('Category'); + $table = new Category(Factory::getDbo()); break; } diff --git a/administrator/components/com_contact/src/Model/ContactModel.php b/administrator/components/com_contact/src/Model/ContactModel.php index 58d26e525c95c..9782d57b90c56 100644 --- a/administrator/components/com_contact/src/Model/ContactModel.php +++ b/administrator/components/com_contact/src/Model/ContactModel.php @@ -18,6 +18,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\String\PunycodeHelper; +use Joomla\CMS\Versioning\VersionableModelInterface; use Joomla\CMS\Versioning\VersionableModelTrait; use Joomla\Component\Categories\Administrator\Helper\CategoriesHelper; use Joomla\Database\ParameterType; @@ -33,7 +34,7 @@ * * @since 1.6 */ -class ContactModel extends AdminModel +class ContactModel extends AdminModel implements VersionableModelInterface { use VersionableModelTrait; @@ -161,9 +162,10 @@ protected function canEditState($record) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -172,10 +174,6 @@ public function getForm($data = [], $loadData = true) // Get the form. $form = $this->loadForm('com_contact.' . $this->formName, $this->formName, ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - // Modify the form based on access controls. if (!$this->canEditState((object) $data)) { // Disable fields for display. @@ -258,7 +256,7 @@ protected function loadFormData() // Prime some default values. if ($this->getState('contact.id') == 0) { - $data->set('catid', $app->getInput()->get('catid', $app->getUserState('com_contact.contacts.filter.category_id'), 'int')); + $data->catid = $app->getInput()->get('catid', $app->getUserState('com_contact.contacts.filter.category_id'), 'int'); } } @@ -368,7 +366,7 @@ protected function prepareTable($table) // Set ordering to the last item if not set if (empty($table->ordering)) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('MAX(ordering)') ->from($db->quoteName('#__contact_details')); $db->setQuery($query); @@ -478,7 +476,7 @@ public function featured($pks, $value = 0) try { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->update($db->quoteName('#__contact_details')); $query->set($db->quoteName('featured') . ' = :featured'); $query->whereIn($db->quoteName('id'), $pks); diff --git a/administrator/components/com_contact/src/Model/ContactsModel.php b/administrator/components/com_contact/src/Model/ContactsModel.php index a783ac5a8bd43..a781a3ca4e6f4 100644 --- a/administrator/components/com_contact/src/Model/ContactsModel.php +++ b/administrator/components/com_contact/src/Model/ContactsModel.php @@ -14,7 +14,7 @@ use Joomla\CMS\Language\Associations; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Category; use Joomla\Database\ParameterType; use Joomla\Database\QueryInterface; use Joomla\Utilities\ArrayHelper; @@ -146,7 +146,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = $this->getCurrentUser(); // Select the required fields from the table. @@ -208,7 +208,7 @@ protected function getListQuery() // Join over the associations. if (Associations::isEnabled()) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1') ->from($db->quoteName('#__associations', 'asso1')) ->join('INNER', $db->quoteName('#__associations', 'asso2'), $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key')) @@ -291,7 +291,7 @@ protected function getListQuery() $includeNone = true; } - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where( @@ -308,7 +308,7 @@ protected function getListQuery() ); if ($includeNone) { - $subQuery2 = $db->getQuery(true) + $subQuery2 = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('type_alias') . ' = ' . $db->quote('com_contact.contact')); @@ -326,7 +326,7 @@ protected function getListQuery() $tag = (int) $tag; if ($tag === 0) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('type_alias') . ' = ' . $db->quote('com_contact.contact')); @@ -365,7 +365,7 @@ protected function getListQuery() // Case: Using both categories filter and by level filter if (\count($categoryId)) { $categoryId = ArrayHelper::toInteger($categoryId); - $categoryTable = Table::getInstance('Category', '\\Joomla\\CMS\\Table\\'); + $categoryTable = new Category($db); $subCatItemsWhere = []; // @todo: Convert to prepared statement diff --git a/administrator/components/com_contact/src/Service/HTML/AdministratorService.php b/administrator/components/com_contact/src/Service/HTML/AdministratorService.php index d99c69510bb38..4c6a829bec937 100644 --- a/administrator/components/com_contact/src/Service/HTML/AdministratorService.php +++ b/administrator/components/com_contact/src/Service/HTML/AdministratorService.php @@ -52,7 +52,7 @@ public function association($contactid) // Get the associated contact items $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('c.id'), diff --git a/administrator/components/com_contact/src/Service/HTML/Icon.php b/administrator/components/com_contact/src/Service/HTML/Icon.php index 9073e21a66395..02b6c7f8f4684 100644 --- a/administrator/components/com_contact/src/Service/HTML/Icon.php +++ b/administrator/components/com_contact/src/Service/HTML/Icon.php @@ -100,7 +100,7 @@ public function create($category, $params, $attribs = []) */ public function edit($contact, $params, $attribs = [], $legacy = false) { - $user = Factory::getUser(); + $user = Factory::getApplication()->getIdentity(); $uri = Uri::getInstance(); // Ignore if in a popup window. diff --git a/administrator/components/com_contact/src/Table/ContactTable.php b/administrator/components/com_contact/src/Table/ContactTable.php index f3b369cdd92d5..c5d1d9c397420 100644 --- a/administrator/components/com_contact/src/Table/ContactTable.php +++ b/administrator/components/com_contact/src/Table/ContactTable.php @@ -20,7 +20,6 @@ use Joomla\CMS\Tag\TaggableTableTrait; use Joomla\CMS\User\CurrentUserInterface; use Joomla\CMS\User\CurrentUserTrait; -use Joomla\CMS\Versioning\VersionableTableInterface; use Joomla\Database\DatabaseInterface; use Joomla\Event\DispatcherInterface; use Joomla\String\StringHelper; @@ -34,7 +33,7 @@ * * @since 1.0 */ -class ContactTable extends Table implements VersionableTableInterface, TaggableTableInterface, CurrentUserInterface +class ContactTable extends Table implements TaggableTableInterface, CurrentUserInterface { use TaggableTableTrait; use CurrentUserTrait; diff --git a/administrator/components/com_contact/src/View/Contact/HtmlView.php b/administrator/components/com_contact/src/View/Contact/HtmlView.php index 5abfe5c972d58..7f35d4d27e942 100644 --- a/administrator/components/com_contact/src/View/Contact/HtmlView.php +++ b/administrator/components/com_contact/src/View/Contact/HtmlView.php @@ -10,16 +10,11 @@ namespace Joomla\Component\Contact\Administrator\View\Contact; -use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Helper\ContentHelper; -use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; -use Joomla\CMS\MVC\View\GenericDataException; -use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; -use Joomla\CMS\Toolbar\Toolbar; +use Joomla\CMS\MVC\View\FormView; use Joomla\CMS\Toolbar\ToolbarHelper; -use Joomla\Component\Contact\Administrator\Model\ContactModel; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -30,68 +25,62 @@ * * @since 1.6 */ -class HtmlView extends BaseHtmlView +class HtmlView extends FormView { /** - * The Form object + * Set to true, if saving to menu should be supported * - * @var \Joomla\CMS\Form\Form + * @var boolean */ - protected $form; + protected $supportSaveMenu = true; /** - * The active item + * Holds the extension for categories, if available * - * @var object + * @var string */ - protected $item; + protected $categorySection = 'com_contact'; /** - * The model state + * Constructor * - * @var \Joomla\Registry\Registry - */ - protected $state; - - /** - * Array of fieldsets not to display - * - * @var string[] + * @param array $config An optional associative array of configuration settings. * - * @since 5.2.0 + * @since 6.0.0 */ - public $ignore_fieldsets = []; + public function __construct(array $config) + { + if (empty($config['option'])) { + $config['option'] = 'com_contact'; + } + + $config['help_link'] = 'Contacts:_Edit'; + $config['toolbar_icon'] = 'address-book contact'; + + parent::__construct($config); + } /** - * Display the view. - * - * @param string $tpl The name of the template file to parse; automatically searches through the template paths. + * Prepare view data * * @return void + * + * @since 6.0.0 */ - public function display($tpl = null) + protected function initializeView() { - /** @var ContactModel $model */ - $model = $this->getModel(); + parent::initializeView(); - // Initialise variables. - $this->form = $model->getForm(); - $this->item = $model->getItem(); - $this->state = $model->getState(); + $this->canDo = ContentHelper::getActions('com_contact', 'category', $this->item->catid); if ($this->getLayout() === 'modalreturn') { - parent::display($tpl); - return; } - // Check for errors. - if (\count($errors = $model->getErrors())) { - throw new GenericDataException(implode("\n", $errors), 500); - } - // If we are forcing a language in modal (used for associations). - if ($this->getLayout() === 'modal' && $forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'cmd')) { + $forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'cmd'); + + if ($this->getLayout() === 'modal' && $forcedLanguage) { // Set the language field to the forcedLanguage and disable changing it. $this->form->setValue('language', null, $forcedLanguage); $this->form->setFieldAttribute('language', 'readonly', 'true'); @@ -103,13 +92,10 @@ public function display($tpl = null) $this->form->setFieldAttribute('tags', 'language', '*,' . $forcedLanguage); } - if ($this->getLayout() !== 'modal') { - $this->addToolbar(); - } else { - $this->addModalToolbar(); - } - - parent::display($tpl); + // Add form control fields + $this->form + ->addControlField('task') + ->addControlField('forcedLanguage', $forcedLanguage); } /** @@ -121,91 +107,15 @@ public function display($tpl = null) */ protected function addToolbar() { - Factory::getApplication()->getInput()->set('hidemainmenu', true); - - $user = $this->getCurrentUser(); - $userId = $user->id; - $isNew = ($this->item->id == 0); - $checkedOut = !(\is_null($this->item->checked_out) || $this->item->checked_out == $userId); - $toolbar = $this->getDocument()->getToolbar(); - - // Since we don't track these assets at the item level, use the category id. - $canDo = ContentHelper::getActions('com_contact', 'category', $this->item->catid); - - ToolbarHelper::title($isNew ? Text::_('COM_CONTACT_MANAGER_CONTACT_NEW') : Text::_('COM_CONTACT_MANAGER_CONTACT_EDIT'), 'address-book contact'); + if ($this->getLayout() === 'modal') { + $this->addModalToolbar(); - // Build the actions for new and existing records. - if ($isNew) { - // For new records, check the create permission. - if (\count($user->getAuthorisedCategories('com_contact', 'core.create')) > 0) { - $toolbar->apply('contact.apply'); - - $saveGroup = $toolbar->dropdownButton('save-group'); - - $saveGroup->configure( - function (Toolbar $childBar) use ($user) { - $childBar->save('contact.save'); - - if ($user->authorise('core.create', 'com_menus.menu')) { - $childBar->save('contact.save2menu', 'JTOOLBAR_SAVE_TO_MENU'); - } - - $childBar->save2new('contact.save2new'); - } - ); - } - - $toolbar->cancel('contact.cancel', 'JTOOLBAR_CANCEL'); - } else { - // Since it's an existing record, check the edit permission, or fall back to edit own if the owner. - $itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId); - - // Can't save the record if it's checked out and editable - if (!$checkedOut && $itemEditable) { - $toolbar->apply('contact.apply'); - } - - $saveGroup = $toolbar->dropdownButton('save-group'); - - $saveGroup->configure( - function (Toolbar $childBar) use ($checkedOut, $itemEditable, $canDo, $user) { - // Can't save the record if it's checked out and editable - if (!$checkedOut && $itemEditable) { - $childBar->save('contact.save'); - - // We can save this record, but check the create permission to see if we can return to make a new one. - if ($canDo->get('core.create')) { - $childBar->save2new('contact.save2new'); - } - } - - // If checked out, we can still save2menu - if ($user->authorise('core.create', 'com_menus.menu')) { - $childBar->save('contact.save2menu', 'JTOOLBAR_SAVE_TO_MENU'); - } - - // If checked out, we can still save - if ($canDo->get('core.create')) { - $childBar->save2copy('contact.save2copy'); - } - } - ); - - $toolbar->cancel('contact.cancel'); - - if (ComponentHelper::isEnabled('com_contenthistory') && $this->state->get('params')->get('save_history', 0) && $itemEditable) { - $toolbar->versions('com_contact.contact', $this->item->id); - } - - if (Associations::isEnabled() && ComponentHelper::isEnabled('com_associations')) { - $toolbar->standardButton('contract', 'JTOOLBAR_ASSOCIATIONS', 'contact.editAssociations') - ->icon('icon-contract') - ->listCheck(false); - } + return; } - $toolbar->divider(); - $toolbar->help('Contacts:_Edit'); + parent::addToolbar(); + + return; } /** diff --git a/administrator/components/com_contact/src/View/Contacts/HtmlView.php b/administrator/components/com_contact/src/View/Contacts/HtmlView.php index f53d82bbba304..31759d510880a 100644 --- a/administrator/components/com_contact/src/View/Contacts/HtmlView.php +++ b/administrator/components/com_contact/src/View/Contacts/HtmlView.php @@ -13,12 +13,8 @@ use Joomla\CMS\Factory; use Joomla\CMS\Helper\ContentHelper; use Joomla\CMS\Language\Multilanguage; -use Joomla\CMS\Language\Text; -use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\MVC\View\ListView; use Joomla\CMS\Session\Session; -use Joomla\CMS\Toolbar\Button\DropdownButton; -use Joomla\CMS\Toolbar\ToolbarHelper; -use Joomla\Component\Contact\Administrator\Model\ContactsModel; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -29,79 +25,52 @@ * * @since 1.6 */ -class HtmlView extends BaseHtmlView +class HtmlView extends ListView { /** - * An array of items + * The help link for the view * - * @var array + * @var string */ - protected $items; + protected $helpLink = 'Contacts'; /** - * The pagination object + * Constructor * - * @var \Joomla\CMS\Pagination\Pagination + * @param array $config An optional associative array of configuration settings. */ - protected $pagination; - - /** - * The model state - * - * @var \Joomla\Registry\Registry - */ - protected $state; - - /** - * Form object for search filters - * - * @var \Joomla\CMS\Form\Form - */ - public $filterForm; + public function __construct(array $config) + { + if (empty($config['option'])) { + $config['option'] = 'com_contact'; + } - /** - * The active search filters - * - * @var array - */ - public $activeFilters; + $config['toolbar_icon'] = 'address-book contact'; + $config['supports_batch'] = true; - /** - * Is this view an Empty State - * - * @var boolean - * - * @since 4.0.0 - */ - private $isEmptyState = false; + parent::__construct($config); + } /** - * Display the view. - * - * @param string $tpl The name of the template file to parse; automatically searches through the template paths. + * Prepare view data * * @return void */ - public function display($tpl = null) + protected function initializeView() { - /** @var ContactsModel $model */ - $model = $this->getModel(); - $model->setUseExceptions(true); - - $this->items = $model->getItems(); - $this->pagination = $model->getPagination(); - $this->state = $model->getState(); - $this->filterForm = $model->getFilterForm(); - $this->activeFilters = $model->getActiveFilters(); - - if (!\count($this->items) && $this->isEmptyState = $model->getIsEmptyState()) { - $this->setLayout('emptystate'); + parent::initializeView(); + + $user = $this->getCurrentUser(); + + $this->canDo = ContentHelper::getActions('com_contact', 'category', $this->state->get('filter.category_id')); + + // Special case of we can create contact for specific categories show add button + if (\count($user->getAuthorisedCategories('com_contact', 'core.create')) > 0) { + $this->canDo->set('core.create', true); } // We don't need toolbar in the modal window. if ($this->getLayout() !== 'modal') { - $this->addToolbar(); - // We do not need to filter by language when multilingual is disabled if (!Multilanguage::isEnabled()) { unset($this->activeFilters['language']); @@ -110,7 +79,9 @@ public function display($tpl = null) } else { // In article associations modal we need to remove language filter if forcing a language. // We also need to change the category filter to show show categories with All or the forced language. - if ($forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'CMD')) { + $forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'CMD'); + + if ($forcedLanguage) { // If the language is forced we can't allow to select the language, so transform the language selector filter into a hidden field. $languageXml = new \SimpleXMLElement(''); $this->filterForm->setField($languageXml, 'filter', true); @@ -122,6 +93,9 @@ public function display($tpl = null) $this->filterForm->setFieldAttribute('category_id', 'language', '*,' . $forcedLanguage, 'filter'); } + $this->filterForm + ->addControlField('forcedLanguage', $forcedLanguage); + /* * When loaded from the frontend, the modal template requires a valid CSRF token on every request. * Pagination links are plain GET anchor tags that bypass form submission, @@ -131,83 +105,5 @@ public function display($tpl = null) $this->pagination->setAdditionalUrlParam(Session::getFormToken(), '1'); } } - - parent::display($tpl); - } - - /** - * Add the page title and toolbar. - * - * @return void - * - * @since 1.6 - */ - protected function addToolbar() - { - $canDo = ContentHelper::getActions('com_contact', 'category', $this->state->get('filter.category_id')); - $user = $this->getCurrentUser(); - - // Get the toolbar object instance - $toolbar = $this->getDocument()->getToolbar(); - - ToolbarHelper::title(Text::_('COM_CONTACT_MANAGER_CONTACTS'), 'address-book contact'); - - if ($canDo->get('core.create') || \count($user->getAuthorisedCategories('com_contact', 'core.create')) > 0) { - $toolbar->addNew('contact.add'); - } - - if (!$this->isEmptyState && $canDo->get('core.edit.state')) { - /** @var DropdownButton $dropdown */ - $dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS') - ->toggleSplit(false) - ->icon('icon-ellipsis-h') - ->buttonClass('btn btn-action') - ->listCheck(true); - - $childBar = $dropdown->getChildToolbar(); - - $childBar->publish('contacts.publish')->listCheck(true); - $childBar->unpublish('contacts.unpublish')->listCheck(true); - $childBar->standardButton('featured', 'JFEATURE', 'contacts.featured') - ->listCheck(true); - $childBar->standardButton('unfeatured', 'JUNFEATURE', 'contacts.unfeatured') - ->listCheck(true); - $childBar->archive('contacts.archive')->listCheck(true); - - if ($user->authorise('core.admin')) { - $childBar->checkin('contacts.checkin'); - } - - if ($this->state->get('filter.published') != -2) { - $childBar->trash('contacts.trash')->listCheck(true); - } - - // Add a batch button - if ( - $user->authorise('core.create', 'com_contact') - && $user->authorise('core.edit', 'com_contact') - && $user->authorise('core.edit.state', 'com_contact') - ) { - $childBar->popupButton('batch', 'JTOOLBAR_BATCH') - ->popupType('inline') - ->textHeader(Text::_('COM_CONTACT_BATCH_OPTIONS')) - ->url('#joomla-dialog-batch') - ->modalWidth('800px') - ->modalHeight('fit-content') - ->listCheck(true); - } - } - - if (!$this->isEmptyState && $this->state->get('filter.published') == -2 && $canDo->get('core.delete')) { - $toolbar->delete('contacts.delete', 'JTOOLBAR_DELETE_FROM_TRASH') - ->message('JGLOBAL_CONFIRM_DELETE') - ->listCheck(true); - } - - if ($user->authorise('core.admin', 'com_contact') || $user->authorise('core.options', 'com_contact')) { - $toolbar->preferences('com_contact'); - } - - $toolbar->help('Contacts'); } } diff --git a/administrator/components/com_contact/tmpl/contact/edit.php b/administrator/components/com_contact/tmpl/contact/edit.php index dddda905f7305..c45ef221aaafd 100644 --- a/administrator/components/com_contact/tmpl/contact/edit.php +++ b/administrator/components/com_contact/tmpl/contact/edit.php @@ -130,7 +130,6 @@ - - - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_contact/tmpl/contacts/default.php b/administrator/components/com_contact/tmpl/contacts/default.php index d2cd208b88b85..32147cf2658ef 100644 --- a/administrator/components/com_contact/tmpl/contacts/default.php +++ b/administrator/components/com_contact/tmpl/contacts/default.php @@ -191,17 +191,12 @@ authorise('core.create', 'com_contact') - && $user->authorise('core.edit', 'com_contact') - && $user->authorise('core.edit.state', 'com_contact') - ) : ?> + if ($this->batchAllowed) : ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_contact/tmpl/contacts/emptystate.php b/administrator/components/com_contact/tmpl/contacts/emptystate.php index c42bdffdf487b..752e065b8ad01 100644 --- a/administrator/components/com_contact/tmpl/contacts/emptystate.php +++ b/administrator/components/com_contact/tmpl/contacts/emptystate.php @@ -17,8 +17,10 @@ $displayData = [ 'textPrefix' => 'COM_CONTACT', 'formURL' => 'index.php?option=com_contact', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Contacts', + 'helpURL' => 'https://guide.joomla.org/user-manual/contacts', 'icon' => 'icon-address-book contact', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; $user = $this->getCurrentUser(); diff --git a/administrator/components/com_contact/tmpl/contacts/modal.php b/administrator/components/com_contact/tmpl/contacts/modal.php index ed2579532dc83..dacc4777ceddb 100644 --- a/administrator/components/com_contact/tmpl/contacts/modal.php +++ b/administrator/components/com_contact/tmpl/contacts/modal.php @@ -32,7 +32,7 @@ $wa->useScript('modal-content-select') ->useScript('com_contact.admin-contacts-modal'); -// @todo: Use of Function and Editor is deprecated and should be removed in 6.0. It stays only for backward compatibility. +// @todo: Use of Function and Editor is deprecated and should be removed in 7.0. It stays only for backward compatibility. $function = $app->getInput()->getCmd('function', 'jSelectContact'); $editor = $app->getInput()->getCmd('editor', ''); $listOrder = $this->escape($this->state->get('list.ordering')); @@ -161,9 +161,7 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_content/config.xml b/administrator/components/com_content/config.xml index c037c6e9de367..8b21fceaf25d6 100644 --- a/administrator/components/com_content/config.xml +++ b/administrator/components/com_content/config.xml @@ -330,6 +330,17 @@ + +
@@ -516,7 +527,7 @@ @@ -629,6 +640,17 @@ + + + + + + +
@@ -744,10 +749,19 @@ /> + + @@ -782,12 +796,20 @@ label="COM_CONTENT_FIELD_IMAGE_ALT_EMPTY_LABEL" description="COM_CONTENT_FIELD_IMAGE_ALT_EMPTY_DESC" /> + @@ -797,6 +819,7 @@ type="text" label="COM_CONTENT_FIELD_IMAGE_CAPTION_LABEL" /> + diff --git a/administrator/components/com_content/forms/filter_articles.xml b/administrator/components/com_content/forms/filter_articles.xml index 88211741e70ef..6b9be58d6a399 100644 --- a/administrator/components/com_content/forms/filter_articles.xml +++ b/administrator/components/com_content/forms/filter_articles.xml @@ -14,8 +14,8 @@ name="featured" type="list" label="JFEATURED" + filtermode="selector" class="js-select-submit-on-change" - default="" validate="options" > diff --git a/administrator/components/com_content/forms/filter_featured.xml b/administrator/components/com_content/forms/filter_featured.xml deleted file mode 100644 index 5fdeefc9a2a9a..0000000000000 --- a/administrator/components/com_content/forms/filter_featured.xml +++ /dev/null @@ -1,156 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/administrator/components/com_content/helpers/content.php b/administrator/components/com_content/helpers/content.php index 1ae6756d2b044..9fb7ffcdf3682 100644 --- a/administrator/components/com_content/helpers/content.php +++ b/administrator/components/com_content/helpers/content.php @@ -19,7 +19,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Content\Administrator\Helper\ContentHelper instead */ class ContentHelper extends \Joomla\Component\Content\Administrator\Helper\ContentHelper diff --git a/administrator/components/com_content/presets/content.xml b/administrator/components/com_content/presets/content.xml index 214cf4c8ce64c..c6e1452e2606b 100644 --- a/administrator/components/com_content/presets/content.xml +++ b/administrator/components/com_content/presets/content.xml @@ -27,14 +27,6 @@ quicktask="index.php?option=com_categories&extension=com_content&task=category.add" quicktask-title="COM_CONTENT_MENUS_NEW_CATEGORY" /> - - load($association->id); diff --git a/administrator/components/com_content/src/Controller/ArticlesController.php b/administrator/components/com_content/src/Controller/ArticlesController.php index dc86b71f090e5..4794e167e1c0f 100644 --- a/administrator/components/com_content/src/Controller/ArticlesController.php +++ b/administrator/components/com_content/src/Controller/ArticlesController.php @@ -16,6 +16,7 @@ use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\Response\JsonResponse; use Joomla\CMS\Router\Route; +use Joomla\Component\Content\Administrator\Model\ArticlesModel; use Joomla\Input\Input; use Joomla\Utilities\ArrayHelper; @@ -145,9 +146,7 @@ public function getQuickiconContent() { $model = $this->getModel('articles'); - $model->setState('filter.published', 1); - - $amount = (int) $model->getTotal(); + $amount = (int) $model->getTotal($featured = ''); $result = []; @@ -157,4 +156,31 @@ public function getQuickiconContent() echo new JsonResponse($result); } + + /** + * Method to get the number of published featured articles for quickicons + * + * @return void + * + * @since 6.0.0 + */ + public function getQuickiconFeatured() + { + /** + * @var ArticlesModel $model + */ + $model = $this->getModel('articles'); + + $model->setState('filter.featured', '1'); + + $amount = (int) $model->getTotal(); + + $result = []; + + $result['amount'] = $amount; + $result['sronly'] = Text::plural('COM_CONTENT_FEATURED_N_QUICKICON_SRONLY', $amount); + $result['name'] = Text::plural('COM_CONTENT_FEATURED_N_QUICKICON', $amount); + + echo new JsonResponse($result); + } } diff --git a/administrator/components/com_content/src/Controller/DisplayController.php b/administrator/components/com_content/src/Controller/DisplayController.php index 158c8f3a17ce3..1afb8032bd43d 100644 --- a/administrator/components/com_content/src/Controller/DisplayController.php +++ b/administrator/components/com_content/src/Controller/DisplayController.php @@ -62,6 +62,11 @@ public function display($cachable = false, $urlparams = []) return false; } + if ($view === 'featured' || $this->input->getInt('featured')) { + $this->setRedirect(Route::_('index.php?option=com_content&view=articles&filter[featured]=1', false)); + return false; + } + return parent::display(); } } diff --git a/administrator/components/com_content/src/Controller/FeaturedController.php b/administrator/components/com_content/src/Controller/FeaturedController.php index 92756c9fc89c6..7206922c5fad2 100644 --- a/administrator/components/com_content/src/Controller/FeaturedController.php +++ b/administrator/components/com_content/src/Controller/FeaturedController.php @@ -10,9 +10,6 @@ namespace Joomla\Component\Content\Administrator\Controller; -use Joomla\CMS\Language\Text; -use Joomla\CMS\Response\JsonResponse; - // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects @@ -24,66 +21,6 @@ */ class FeaturedController extends ArticlesController { - /** - * Removes an item. - * - * @return void - * - * @since 1.6 - */ - public function delete() - { - // Check for request forgeries - $this->checkToken(); - - $user = $this->app->getIdentity(); - $ids = (array) $this->input->get('cid', [], 'int'); - - // Access checks. - foreach ($ids as $i => $id) { - // Remove zero value resulting from input filter - if ($id === 0) { - unset($ids[$i]); - - continue; - } - - if (!$user->authorise('core.delete', 'com_content.article.' . (int) $id)) { - // Prune items that you can't delete. - unset($ids[$i]); - $this->app->enqueueMessage(Text::_('JERROR_CORE_DELETE_NOT_PERMITTED'), 'notice'); - } - } - - if (empty($ids)) { - $this->app->enqueueMessage(Text::_('JERROR_NO_ITEMS_SELECTED'), 'error'); - } else { - /** @var \Joomla\Component\Content\Administrator\Model\FeatureModel $model */ - $model = $this->getModel(); - - // Remove the items. - if (!$model->featured($ids, 0)) { - $this->app->enqueueMessage($model->getError(), 'error'); - } - } - - $this->setRedirect('index.php?option=com_content&view=featured'); - } - - /** - * Method to publish a list of articles. - * - * @return void - * - * @since 1.0 - */ - public function publish() - { - parent::publish(); - - $this->setRedirect('index.php?option=com_content&view=featured'); - } - /** * Method to get a model object, loading it if required. * @@ -99,29 +36,4 @@ public function getModel($name = 'Feature', $prefix = 'Administrator', $config = { return parent::getModel($name, $prefix, $config); } - - /** - * Method to get the number of published featured articles for quickicons - * - * @return void - * - * @since 4.3.0 - */ - public function getQuickiconContent() - { - $model = $this->getModel('articles'); - - $model->setState('filter.published', 1); - $model->setState('filter.featured', 1); - - $amount = (int) $model->getTotal(); - - $result = []; - - $result['amount'] = $amount; - $result['sronly'] = Text::plural('COM_CONTENT_FEATURED_N_QUICKICON_SRONLY', $amount); - $result['name'] = Text::plural('COM_CONTENT_FEATURED_N_QUICKICON', $amount); - - echo new JsonResponse($result); - } } diff --git a/administrator/components/com_content/src/Extension/ContentComponent.php b/administrator/components/com_content/src/Extension/ContentComponent.php index bd2861e1fa467..a27ddb5a396b9 100644 --- a/administrator/components/com_content/src/Extension/ContentComponent.php +++ b/administrator/components/com_content/src/Extension/ContentComponent.php @@ -29,11 +29,13 @@ use Joomla\CMS\Schemaorg\SchemaorgServiceTrait; use Joomla\CMS\Tag\TagServiceInterface; use Joomla\CMS\Tag\TagServiceTrait; +use Joomla\CMS\User\UserFactoryInterface; use Joomla\CMS\Workflow\WorkflowServiceInterface; use Joomla\CMS\Workflow\WorkflowServiceTrait; use Joomla\Component\Content\Administrator\Helper\ContentHelper; use Joomla\Component\Content\Administrator\Service\HTML\AdministratorService; use Joomla\Component\Content\Administrator\Service\HTML\Icon; +use Joomla\Database\DatabaseInterface; use Psr\Container\ContainerInterface; // phpcs:disable PSR1.Files.SideEffects @@ -127,8 +129,13 @@ class ContentComponent extends MVCComponent implements */ public function boot(ContainerInterface $container) { - $this->getRegistry()->register('contentadministrator', new AdministratorService()); - $this->getRegistry()->register('contenticon', new Icon()); + $contentAdministrator = new AdministratorService(); + $contentAdministrator->setDatabase($container->get(DatabaseInterface::class)); + $this->getRegistry()->register('contentadministrator', $contentAdministrator); + + $icon = new Icon(); + $icon->setUserFactory($container->get(UserFactoryInterface::class)); + $this->getRegistry()->register('contenticon', $icon); // The layout joomla.content.icons does need a general icon service $this->getRegistry()->register('icon', $this->getRegistry()->getService('contenticon')); diff --git a/administrator/components/com_content/src/Field/Modal/ArticleField.php b/administrator/components/com_content/src/Field/Modal/ArticleField.php index c173321bbf6c0..478227bb2dbb0 100644 --- a/administrator/components/com_content/src/Field/Modal/ArticleField.php +++ b/administrator/components/com_content/src/Field/Modal/ArticleField.php @@ -138,7 +138,7 @@ protected function getValueTitle() if ($value) { try { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__content')) ->where($db->quoteName('id') . ' = :value') diff --git a/administrator/components/com_content/src/Helper/AssociationsHelper.php b/administrator/components/com_content/src/Helper/AssociationsHelper.php index 7a0c73cc48c0e..3580bf942559f 100644 --- a/administrator/components/com_content/src/Helper/AssociationsHelper.php +++ b/administrator/components/com_content/src/Helper/AssociationsHelper.php @@ -11,7 +11,10 @@ namespace Joomla\Component\Content\Administrator\Helper; use Joomla\CMS\Association\AssociationExtensionHelper; +use Joomla\CMS\Factory; use Joomla\CMS\Language\Associations; +use Joomla\CMS\Table\Category; +use Joomla\CMS\Table\Content; use Joomla\CMS\Table\Table; use Joomla\Component\Content\Site\Helper\AssociationHelper; @@ -124,11 +127,11 @@ public function getItem($typeName, $id) switch ($typeName) { case 'article': - $table = Table::getInstance('Content'); + $table = new Content(Factory::getDbo()); break; case 'category': - $table = Table::getInstance('Category'); + $table = new Category(Factory::getDbo()); break; } diff --git a/administrator/components/com_content/src/Helper/ContentHelper.php b/administrator/components/com_content/src/Helper/ContentHelper.php index 2729c5ab00d9b..7374b21dcca72 100644 --- a/administrator/components/com_content/src/Helper/ContentHelper.php +++ b/administrator/components/com_content/src/Helper/ContentHelper.php @@ -41,7 +41,7 @@ class ContentHelper extends \Joomla\CMS\Helper\ContentHelper public static function canDeleteState(int $id): bool { $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select('id') ->from($db->quoteName('#__content')) @@ -110,7 +110,7 @@ public static function onPrepareForm(Form $form, $data) return; } - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('title')) ->from($db->quoteName('#__workflows')) @@ -139,7 +139,7 @@ public static function onPrepareForm(Form $form, $data) if (!empty($categories)) { $categories = array_reverse($categories); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('title')) ->from($db->quoteName('#__workflows')) diff --git a/administrator/components/com_content/src/Model/ArticleModel.php b/administrator/components/com_content/src/Model/ArticleModel.php index 26202762b8031..8b18f53989ad8 100644 --- a/administrator/components/com_content/src/Model/ArticleModel.php +++ b/administrator/components/com_content/src/Model/ArticleModel.php @@ -12,6 +12,7 @@ use Joomla\CMS\Date\Date; use Joomla\CMS\Event\AbstractEvent; +use Joomla\CMS\Event\Model\AfterSaveEvent; use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; use Joomla\CMS\Form\Form; @@ -29,6 +30,7 @@ use Joomla\CMS\Table\TableInterface; use Joomla\CMS\Tag\TaggableTableInterface; use Joomla\CMS\UCM\UCMType; +use Joomla\CMS\Versioning\VersionableModelInterface; use Joomla\CMS\Versioning\VersionableModelTrait; use Joomla\CMS\Workflow\Workflow; use Joomla\Component\Categories\Administrator\Helper\CategoriesHelper; @@ -49,7 +51,7 @@ * @since 1.6 */ -class ArticleModel extends AdminModel implements WorkflowModelInterface +class ArticleModel extends AdminModel implements WorkflowModelInterface, VersionableModelInterface { use WorkflowBehaviorTrait; use VersionableModelTrait; @@ -140,7 +142,7 @@ protected function cleanupPostBatchCopy(TableInterface $table, $newId, $oldId) // Check if the article was featured and update the #__content_frontpage table if ($table->featured == 1) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('featured_up'), @@ -154,7 +156,7 @@ protected function cleanupPostBatchCopy(TableInterface $table, $newId, $oldId) $featured = $db->setQuery($query)->loadObject(); if ($featured) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->insert($db->quoteName('#__content_frontpage')) ->values(':newId, 0, :featuredUp, :featuredDown') ->bind(':newId', $newId, ParameterType::INTEGER) @@ -182,7 +184,15 @@ protected function cleanupPostBatchCopy(TableInterface $table, $newId, $oldId) } } - Factory::getApplication()->triggerEvent('onContentAfterSave', ['com_content.article', &$this->table, false, $fieldsData]); + $this->getDispatcher()->dispatch( + 'onContentAfterSave', + new AfterSaveEvent('onContentAfterSave', [ + 'context' => 'com_content.article', + 'subject' => $this->table, + 'isNew' => false, + 'data' => $fieldsData, + ]) + ); } /** @@ -213,7 +223,8 @@ protected function batchMove($value, $pks, $contexts) return false; } - PluginHelper::importPlugin('system'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('system', null, true, $dispatcher); // Parent exists so we proceed foreach ($pks as $pk) { @@ -272,7 +283,12 @@ protected function batchMove($value, $pks, $contexts) } // Run event for moved article - Factory::getApplication()->triggerEvent('onContentAfterSave', ['com_content.article', &$this->table, false, $fieldsData]); + $dispatcher->dispatch('onContentAfterSave', new AfterSaveEvent('onContentAfterSave', [ + 'context' => 'com_content.article', + 'subject' => $this->table, + 'isNew' => false, + 'data' => $fieldsData, + ])); } // Clean the cache @@ -410,7 +426,7 @@ public function getItem($pk = null) if ($item->featured) { // Get featured dates. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('featured_up'), @@ -455,9 +471,10 @@ public function getItem($pk = null) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -466,10 +483,6 @@ public function getForm($data = [], $loadData = true) // Get the form. $form = $this->loadForm('com_content.article', 'article', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - // Object uses for checking edit state permission of article $record = new \stdClass(); @@ -579,13 +592,10 @@ protected function loadFormData() // Pre-select some filters (Status, Category, Language, Access) in edit form if those have been selected in Article Manager: Articles if ($this->getState('article.id') == 0) { - $filters = (array) $app->getUserState('com_content.articles.filter'); - $data->set( + $filters = (array) $app->getUserState('com_content.articles.filter'); + $data->state = $app->getInput()->getInt( 'state', - $app->getInput()->getInt( - 'state', - ((isset($filters['published']) && $filters['published'] !== '') ? $filters['published'] : null) - ) + ((isset($filters['published']) && $filters['published'] !== '') ? $filters['published'] : null) ); // If multiple categories are filtered, pick the first one to avoid loading all fields @@ -598,16 +608,13 @@ protected function loadFormData() $selectedCatId = (int) $filteredCategories; } - $data->set('catid', $app->getInput()->getInt('catid', $selectedCatId)); + $data->catid = $app->getInput()->getInt('catid', $selectedCatId); if ($app->isClient('administrator')) { - $data->set('language', $app->getInput()->getString('language', (!empty($filters['language']) ? $filters['language'] : null))); + $data->language = $app->getInput()->getString('language', (!empty($filters['language']) ? $filters['language'] : null)); } - $data->set( - 'access', - $app->getInput()->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access'))) - ); + $data->access = $app->getInput()->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access'))); } } @@ -771,26 +778,26 @@ public function save($data) } // Automatic handling of alias for empty fields - if (\in_array($input->get('task'), ['apply', 'save', 'save2new']) && (!isset($data['id']) || (int) $data['id'] == 0)) { + if (\in_array($input->get('task'), ['add', 'apply', 'save', 'save2new']) && (!isset($data['id']) || (int) $data['id'] == 0)) { if ($data['alias'] == null) { if ($app->get('unicodeslugs') == 1) { $data['alias'] = OutputFilter::stringUrlUnicodeSlug($data['title']); } else { $data['alias'] = OutputFilter::stringURLSafe($data['title']); } + } - $table = $this->getTable(); + $table = $this->getTable(); - if ($table->load(['alias' => $data['alias'], 'catid' => $data['catid']])) { - $msg = Text::_('COM_CONTENT_SAVE_WARNING'); - } + if ($table->load(['alias' => $data['alias'], 'catid' => $data['catid']])) { + $msg = Text::_('COM_CONTENT_SAVE_WARNING'); + } - [$title, $alias] = $this->generateNewTitle($data['catid'], $data['alias'], $data['title']); - $data['alias'] = $alias; + [$title, $alias] = $this->generateNewTitle($data['catid'], $data['alias'], $data['title']); + $data['alias'] = $alias; - if (isset($msg)) { - $app->enqueueMessage($msg, 'warning'); - } + if (isset($msg)) { + $app->enqueueMessage($msg, 'warning'); } } @@ -880,7 +887,7 @@ public function featured($pks, $value = 0, $featuredUp = null, $featuredDown = n try { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__content')) ->set($db->quoteName('featured') . ' = :featured') ->whereIn($db->quoteName('id'), $pks) @@ -891,14 +898,14 @@ public function featured($pks, $value = 0, $featuredUp = null, $featuredDown = n if ($value === 0) { // Adjust the mapping table. // Clear the existing features settings. - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__content_frontpage')) ->whereIn($db->quoteName('content_id'), $pks); $db->setQuery($query); $db->execute(); } else { // First, we find out which of our new featured articles are already featured. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('content_id')) ->from($db->quoteName('#__content_frontpage')) ->whereIn($db->quoteName('content_id'), $pks); @@ -908,7 +915,7 @@ public function featured($pks, $value = 0, $featuredUp = null, $featuredDown = n // Update old featured articles if (\count($oldFeatured)) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__content_frontpage')) ->set( [ @@ -928,7 +935,7 @@ public function featured($pks, $value = 0, $featuredUp = null, $featuredDown = n // Featuring. if ($newFeatured) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->insert($db->quoteName('#__content_frontpage')) ->columns( [ @@ -1055,15 +1062,13 @@ protected function preprocessForm(Form $form, $data, $group = 'content') /** * Custom clean the cache of com_content and content modules * - * @param string $group The cache group - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 1.6 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { parent::cleanCache('com_content'); parent::cleanCache('mod_articles'); @@ -1114,7 +1119,7 @@ public function delete(&$pks) if ($return) { // Now check to see if this articles was featured if so delete it from the #__content_frontpage table $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__content_frontpage')) ->whereIn($db->quoteName('content_id'), $pks); $db->setQuery($query); diff --git a/administrator/components/com_content/src/Model/ArticlesModel.php b/administrator/components/com_content/src/Model/ArticlesModel.php index 8add698bad7bf..97b379cc68f48 100644 --- a/administrator/components/com_content/src/Model/ArticlesModel.php +++ b/administrator/components/com_content/src/Model/ArticlesModel.php @@ -17,7 +17,7 @@ use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; use Joomla\CMS\Plugin\PluginHelper; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Category; use Joomla\Component\Content\Administrator\Extension\ContentComponent; use Joomla\Database\ParameterType; use Joomla\Database\QueryInterface; @@ -76,6 +76,7 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) 'rating_count', 'rating', 'stage', 'wa.stage_id', 'ws.title', + 'fp.ordering', ]; if (Associations::isEnabled()) { @@ -141,6 +142,7 @@ protected function populateState($ordering = 'a.id', $direction = 'desc') // Required content filters for the administrator menu $this->getUserStateFromRequest($this->context . '.filter.category_id', 'filter_category_id'); $this->getUserStateFromRequest($this->context . '.filter.level', 'filter_level'); + $this->getUserStateFromRequest($this->context . '.filter.featured', 'filter_featured'); $this->getUserStateFromRequest($this->context . '.filter.author_id', 'filter_author_id'); $this->getUserStateFromRequest($this->context . '.filter.tag', 'filter_tag', ''); $this->getUserStateFromRequest($this->context . '.filter.access', 'filter_access'); @@ -176,11 +178,17 @@ protected function getStoreId($id = '') $id .= ':' . $this->getState('filter.search'); $id .= ':' . serialize($this->getState('filter.access')); $id .= ':' . $this->getState('filter.published'); + $id .= ':' . $this->getState('filter.featured'); $id .= ':' . serialize($this->getState('filter.category_id')); $id .= ':' . serialize($this->getState('filter.author_id')); $id .= ':' . $this->getState('filter.language'); $id .= ':' . serialize($this->getState('filter.tag')); $id .= ':' . $this->getState('filter.checked_out'); + $id .= ':' . $this->getState('filter.date_filtering'); + $id .= ':' . $this->getState('filter.date_field'); + $id .= ':' . $this->getState('filter.start_date_range'); + $id .= ':' . $this->getState('filter.end_date_range'); + $id .= ':' . $this->getState('filter.relative_date'); return parent::getStoreId($id); } @@ -196,7 +204,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = $this->getCurrentUser(); $params = ComponentHelper::getParams('com_content'); @@ -285,7 +293,7 @@ protected function getListQuery() // Join over the associations. if (Associations::isEnabled()) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1') ->from($db->quoteName('#__associations', 'asso1')) ->join('INNER', $db->quoteName('#__associations', 'asso2'), $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key')) @@ -312,12 +320,19 @@ protected function getListQuery() } // Filter by featured. - $featured = (string) $this->getState('filter.featured'); + $featured = $this->getState('filter.featured'); - if (\in_array($featured, ['0','1'])) { + $defaultOrdering = 'a.id'; + + if (is_numeric($featured) && \in_array($featured, [0, 1])) { $featured = (int) $featured; $query->where($db->quoteName('a.featured') . ' = :featured') ->bind(':featured', $featured, ParameterType::INTEGER); + + if ($featured) { + $query->select($db->quoteName('fp.ordering')); + $defaultOrdering = 'fp.ordering'; + } } // Filter by access level on categories. @@ -365,7 +380,7 @@ protected function getListQuery() // Case: Using both categories filter and by level filter if (\count($categoryId)) { $categoryId = ArrayHelper::toInteger($categoryId); - $categoryTable = Table::getInstance('Category', '\\Joomla\\CMS\\Table\\'); + $categoryTable = new Category($db); $subCatItemsWhere = []; foreach ($categoryId as $key => $filter_catid) { @@ -405,7 +420,7 @@ protected function getListQuery() if ($authorId === 0) { // Only show deleted authors' articles - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')); @@ -431,7 +446,7 @@ protected function getListQuery() $authorId = array_filter($authorId); // Subquery for deleted users - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')); @@ -519,7 +534,7 @@ protected function getListQuery() $includeNone = true; } - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where( @@ -536,7 +551,7 @@ protected function getListQuery() ); if ($includeNone) { - $subQuery2 = $db->getQuery(true) + $subQuery2 = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('type_alias') . ' = ' . $db->quote('com_content.article')); @@ -554,7 +569,7 @@ protected function getListQuery() $tag = (int) $tag; if ($tag === 0) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('type_alias') . ' = ' . $db->quote('com_content.article')); @@ -582,8 +597,74 @@ protected function getListQuery() } } + // Filter by date after modified date. + $modifiedStartDateTime = $this->getState('filter.modified_start'); + + if (!empty($modifiedStartDateTime)) { + $query->where($db->quoteName('a.modified') . ' >= :startDate') + ->bind(':startDate', $modifiedStartDateTime); + } + + // Filter by date before modified date. + $modifiedEndDateTime = $this->getState('filter.modified_end'); + + if (!empty($modifiedEndDateTime)) { + $query->where($db->quoteName('a.modified') . ' <= :endDate') + ->bind(':endDate', $modifiedEndDateTime); + } + + // Filter by Date Range or Relative Date + $dateFiltering = $this->getState('filter.date_filtering', 'off'); + $dateField = $this->getState('filter.date_field', 'a.created'); + + // Validate the date field to prevent SQL injection + $validDateFields = ['a.created', 'a.modified', 'a.publish_up']; + + if (!\in_array($dateField, $validDateFields)) { + $dateField = 'a.created'; + } + + switch ($dateFiltering) { + case 'range': + $startDateRange = $this->getState('filter.start_date_range', ''); + $endDateRange = $this->getState('filter.end_date_range', ''); + + if ($startDateRange || $endDateRange) { + $query->where($db->quoteName($dateField) . ' IS NOT NULL'); + + if ($startDateRange) { + $query->where($db->quoteName($dateField) . ' >= :startDateRange') + ->bind(':startDateRange', $startDateRange); + } + + if ($endDateRange) { + $query->where($db->quoteName($dateField) . ' <= :endDateRange') + ->bind(':endDateRange', $endDateRange); + } + } + + break; + + case 'relative': + $relativeDate = (int) $this->getState('filter.relative_date', 0); + + if ($relativeDate > 0) { + $nowDate = Factory::getDate()->toSql(); + $query->where( + $db->quoteName($dateField) . ' IS NOT NULL AND ' + . $db->quoteName($dateField) . ' >= ' . $query->dateAdd($db->quote($nowDate), -1 * $relativeDate, 'DAY') + ); + } + + break; + + case 'off': + default: + break; + } + // Add the list ordering clause. - $orderCol = $this->state->get('list.ordering', 'a.id'); + $orderCol = $this->state->get('list.ordering', $defaultOrdering); $orderDirn = $this->state->get('list.direction', 'DESC'); if ($orderCol === 'a.ordering' || $orderCol === 'category_title') { @@ -640,7 +721,7 @@ public function getTransitions() if (\count($stage_ids) || \count($workflow_ids)) { Factory::getLanguage()->load('com_workflow', JPATH_ADMINISTRATOR); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select( [ diff --git a/administrator/components/com_content/src/Model/FeaturedModel.php b/administrator/components/com_content/src/Model/FeaturedModel.php index 4491380af7a88..a9ecfb6378781 100644 --- a/administrator/components/com_content/src/Model/FeaturedModel.php +++ b/administrator/components/com_content/src/Model/FeaturedModel.php @@ -10,9 +10,6 @@ namespace Joomla\Component\Content\Administrator\Model; -use Joomla\CMS\MVC\Factory\MVCFactoryInterface; -use Joomla\Database\QueryInterface; - // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects @@ -21,87 +18,11 @@ * Methods supporting a list of featured article records. * * @since 1.6 + * + * @deprecated 6.0 will be removed in 8.0 + * Use \Joomla\Component\Content\Administrator\Model\ArticlesModel instead + * set the filter.featured state to 1 to get only featured articles */ class FeaturedModel extends ArticlesModel { - /** - * Constructor. - * - * @param array $config An optional associative array of configuration settings. - * @param ?MVCFactoryInterface $factory The factory. - * - * @see \Joomla\CMS\MVC\Controller\BaseController - * @since 1.6 - */ - public function __construct($config = [], ?MVCFactoryInterface $factory = null) - { - if (empty($config['filter_fields'])) { - $config['filter_fields'] = [ - 'id', 'a.id', - 'title', 'a.title', - 'alias', 'a.alias', - 'checked_out', 'a.checked_out', - 'checked_out_time', 'a.checked_out_time', - 'catid', 'a.catid', 'category_title', - 'state', 'a.state', - 'access', 'a.access', 'access_level', - 'created', 'a.created', - 'created_by', 'a.created_by', - 'created_by_alias', 'a.created_by_alias', - 'ordering', 'a.ordering', - 'featured_up', 'fp.featured_up', - 'featured_down', 'fp.featured_down', - 'language', 'a.language', - 'hits', 'a.hits', - 'publish_up', 'a.publish_up', - 'publish_down', 'a.publish_down', - 'fp.ordering', - 'published', 'a.published', - 'author_id', - 'category_id', - 'level', - 'tag', - 'rating_count', 'rating', - 'ws.title', - ]; - } - - parent::__construct($config, $factory); - } - - /** - * Method to auto-populate the model state. - * - * Note. Calling getState in this method will result in recursion. - * - * @param string $ordering An optional ordering field. - * @param string $direction An optional direction (asc|desc). - * - * @return void - * - * @since 3.5 - */ - protected function populateState($ordering = 'a.title', $direction = 'asc') - { - parent::populateState($ordering, $direction); - - // Filter by featured articles. - $this->setState('filter.featured', 1); - } - - /** - * Build an SQL query to load the list data. - * - * @return QueryInterface - * - * @since 4.0.0 - */ - protected function getListQuery() - { - $query = parent::getListQuery(); - - $query->select($this->getDatabase()->quoteName('fp.ordering')); - - return $query; - } } diff --git a/administrator/components/com_content/src/Service/HTML/AdministratorService.php b/administrator/components/com_content/src/Service/HTML/AdministratorService.php index bc6836e6897a4..bfa4f52fedb4f 100644 --- a/administrator/components/com_content/src/Service/HTML/AdministratorService.php +++ b/administrator/components/com_content/src/Service/HTML/AdministratorService.php @@ -16,6 +16,9 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; +use Joomla\Database\DatabaseAwareTrait; +use Joomla\Database\DatabaseInterface; +use Joomla\Database\Exception\DatabaseNotFoundException; use Joomla\Database\ParameterType; // phpcs:disable PSR1.Files.SideEffects @@ -29,6 +32,8 @@ */ class AdministratorService { + use DatabaseAwareTrait; + /** * Render the list of associated items * @@ -50,8 +55,14 @@ public function association($articleid) } // Get the associated menu items - $db = Factory::getDbo(); - $query = $db->getQuery(true) + try { + $db = $this->getDatabase(); + } catch (DatabaseNotFoundException) { + @trigger_error('Database must be set, this will not be caught anymore in 8.0', E_USER_DEPRECATED); + $db = Factory::getContainer()->get(DatabaseInterface::class); + } + + $query = $db->createQuery() ->select( [ 'c.*', diff --git a/administrator/components/com_content/src/Service/HTML/Icon.php b/administrator/components/com_content/src/Service/HTML/Icon.php index fe1782260de47..1d9e69cfd07a7 100644 --- a/administrator/components/com_content/src/Service/HTML/Icon.php +++ b/administrator/components/com_content/src/Service/HTML/Icon.php @@ -16,6 +16,8 @@ use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Uri\Uri; +use Joomla\CMS\User\UserFactoryAwareTrait; +use Joomla\CMS\User\UserFactoryInterface; use Joomla\CMS\Workflow\Workflow; use Joomla\Component\Content\Site\Helper\RouteHelper; use Joomla\Registry\Registry; @@ -31,6 +33,8 @@ */ class Icon { + use UserFactoryAwareTrait; + /** * Method to generate a link to the create item page for the given category * @@ -86,7 +90,7 @@ public function create($category, $params, $attribs = [], $legacy = false) */ public function edit($article, $params, $attribs = [], $legacy = false) { - $user = Factory::getUser(); + $user = Factory::getApplication()->getIdentity(); $uri = Uri::getInstance(); // Ignore if in a popup window. @@ -106,7 +110,15 @@ public function edit($article, $params, $attribs = [], $legacy = false) && !\is_null($article->checked_out) && $article->checked_out != $user->id ) { - $checkoutUser = Factory::getUser($article->checked_out); + try { + $checkoutUser = $this->getUserFactory()->loadUserById($article->checked_out); + } catch (\UnexpectedValueException) { + @trigger_error('UserFactory must be set, this will not be caught anymore in 8.0', E_USER_DEPRECATED); + $checkoutUser = Factory::getContainer()->get(UserFactoryInterface::class)->loadUserById( + $article->checked_out + ); + } + $date = HTMLHelper::_('date', $article->checked_out_time); $tooltip = Text::sprintf('COM_CONTENT_CHECKED_OUT_BY', $checkoutUser->name) . '
' . $date; diff --git a/administrator/components/com_content/src/Service/PreviewTokenService.php b/administrator/components/com_content/src/Service/PreviewTokenService.php new file mode 100644 index 0000000000000..a5d900d5eaa43 --- /dev/null +++ b/administrator/components/com_content/src/Service/PreviewTokenService.php @@ -0,0 +1,156 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Content\Administrator\Service; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Service class for generating and validating article preview tokens. + * + * Tokens are URL-safe, HMAC-SHA256 signed, and time-limited. + * They allow unauthenticated public access to article previews without + * requiring a frontend login or published state. + * + * Usage: + * $helper = new PreviewTokenService($app->get('secret')); + * $token = $helper->createToken($articleId, 24); + * $valid = $helper->validateToken($token, $articleId); + * + * @since 6.2.0 + */ +class PreviewTokenService +{ + /** + * The secret key used to sign and verify preview tokens. + * + * @var string + */ + private string $secret; + + /** + * @param string $secret The secret key + * + * @since 6.2.0 + */ + public function __construct(string $secret) + { + $this->secret = $secret; + } + + /** + * Generate a signed preview token for a given article. + * + * @param int $id The article ID. + * @param int $expiresInMinutes Number of minutes before the token expires. + * + * @return string + * + * @since 6.2.0 + */ + public function createToken(int $id, int $expiresInMinutes): string + { + $payload = $this->encode(json_encode([ + 'id' => $id, + 'exp' => time() + ($expiresInMinutes * 60), + ])); + + $signature = $this->encode(hash_hmac('sha256', $payload, $this->secret, true)); + + return $payload . '.' . $signature; + } + + /** + * Validate a preview token against a given article ID. + * + * Checks that the token: + * - Has a valid structure + * - Has not been tampered with (HMAC signature check) + * - Has not expired + * - Belongs to the expected article + * + * @param string $token The preview token from the URL. + * @param int $id The expected article ID. + * + * @return bool + * + * @since 6.2.0 + */ + public function validateToken(string $token, int $id): bool + { + $parts = explode('.', $token); + + if (\count($parts) !== 2) { + return false; + } + + [$payload, $signature] = $parts; + + if (!hash_equals($this->encode(hash_hmac('sha256', $payload, $this->secret, true)), $signature)) { + return false; + } + + $decoded = $this->decode($payload); + + if ($decoded === false) { + return false; + } + + $data = json_decode($decoded, true); + + if (!\is_array($data) || !isset($data['id'], $data['exp'])) { + return false; + } + + if (!\is_int($data['id']) || !\is_int($data['exp'])) { + return false; + } + + if ($data['id'] !== $id) { + return false; + } + + return time() < $data['exp']; + } + + /** + * Encode binary data to URL-safe Base64 string. + * + * @param string $data + * + * @return string + * + * @since 6.2.0 + */ + private function encode(string $data): string + { + return str_replace('=', '', strtr(base64_encode($data), '+/', '-_')); + } + + /** + * Decode a URL-safe Base64 string to binary data. + * + * @param string $data + * + * @return string|false + * + * @since 6.2.0 + */ + private function decode(string $data): string|false + { + if ($remainder = \strlen($data) % 4) { + $data .= str_repeat('=', 4 - $remainder); + } + + return base64_decode(strtr($data, '-_', '+/')); + } +} diff --git a/administrator/components/com_content/src/View/Article/HtmlView.php b/administrator/components/com_content/src/View/Article/HtmlView.php index 1cebea5ae0abe..6ded1f8cbe799 100644 --- a/administrator/components/com_content/src/View/Article/HtmlView.php +++ b/administrator/components/com_content/src/View/Article/HtmlView.php @@ -13,14 +13,10 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Helper\ContentHelper; -use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; -use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; -use Joomla\CMS\Plugin\PluginHelper; -use Joomla\CMS\Router\Route; -use Joomla\CMS\Toolbar\Toolbar; +use Joomla\CMS\MVC\View\FormView; use Joomla\CMS\Toolbar\ToolbarHelper; -use Joomla\Component\Content\Administrator\Model\ArticleModel; +use Joomla\Component\Content\Administrator\Service\PreviewTokenService; use Joomla\Component\Content\Site\Helper\RouteHelper; // phpcs:disable PSR1.Files.SideEffects @@ -32,83 +28,83 @@ * * @since 1.6 */ -class HtmlView extends BaseHtmlView +class HtmlView extends FormView { /** - * The \JForm object + * Pagebreak TOC alias * - * @var \Joomla\CMS\Form\Form + * @var string */ - protected $form; + protected $eName; /** - * The active item + * Set to true, if saving to menu should be supported * - * @var object + * @var boolean */ - protected $item; + protected $supportSaveMenu = true; /** - * The model state + * Holds the extension for categories, if available * - * @var object + * @var string */ - protected $state; + protected $categorySection = 'com_content'; /** - * The actions the user is authorised to perform + * Constructor * - * @var \Joomla\Registry\Registry - */ - protected $canDo; - - /** - * Pagebreak TOC alias + * @param array $config An optional associative array of configuration settings. * - * @var string + * @since 6.0.0 */ - protected $eName; + public function __construct(array $config) + { + if (empty($config['option'])) { + $config['option'] = 'com_content'; + } - /** - * Array of fieldsets not to display - * - * @var string[] - * - * @since 5.2.0 - */ - public $ignore_fieldsets = []; + $config['help_link'] = 'Articles:_Edit'; + $config['toolbar_icon'] = 'pencil-alt article-add'; + + parent::__construct($config); + } /** - * Execute and display a template script. - * - * @param string $tpl The name of the template file to parse; automatically searches through the template paths. + * Prepare view data * * @return void * - * @since 1.6 - * - * @throws \Exception + * @since 6.0.0 */ - public function display($tpl = null) + protected function initializeView() { if ($this->getLayout() == 'pagebreak') { - parent::display($tpl); - return; } - /** @var ArticleModel $model */ - $model = $this->getModel(); - $model->setUseExceptions(true); + parent::initializeView(); - $this->form = $model->getForm(); - $this->item = $model->getItem(); - $this->state = $model->getState(); $this->canDo = ContentHelper::getActions('com_content', 'article', $this->item->id); - if ($this->getLayout() === 'modalreturn') { - parent::display($tpl); + $url = RouteHelper::getArticleRoute($this->item->id . ':' . $this->item->alias, $this->item->catid, $this->item->language); + + // Generate preview token if editing an existing article + if ($this->item->id > 0) { + $params = ComponentHelper::getParams('com_content'); + $expiration = (int) $params->get('preview_token_expiration', 15); + + $tokenHelper = new PreviewTokenService(Factory::getApplication()->get('secret')); + $token = $tokenHelper->createToken((int) $this->item->id, $expiration); + + // Append token using proper URL query parameter handling + $url .= (!str_contains($url, '?') ? '?' : '&') . 'preview_token=' . $token; + } + + $this->previewLink = $url; + $this->jooa11yLink = $url . '&jooa11y=1'; + if ($this->getLayout() === 'modalreturn') { return; } @@ -130,17 +126,9 @@ public function display($tpl = null) // Add form control fields $this->form - ->addControlField('task', '') + ->addControlField('task') ->addControlField('return', $input->getBase64('return', '')) ->addControlField('forcedLanguage', $forcedLanguage); - - if ($this->getLayout() !== 'modal') { - $this->addToolbar(); - } else { - $this->addModalToolbar(); - } - - parent::display($tpl); } /** @@ -154,104 +142,23 @@ public function display($tpl = null) */ protected function addToolbar() { - Factory::getApplication()->getInput()->set('hidemainmenu', true); + if ($this->getLayout() === 'pagebreak') { + return; + } + if ($this->getLayout() === 'modal') { + $this->addModalToolbar(); + + return; + } + $user = $this->getCurrentUser(); $userId = $user->id; $isNew = ($this->item->id == 0); $checkedOut = !(\is_null($this->item->checked_out) || $this->item->checked_out == $userId); - $toolbar = $this->getDocument()->getToolbar(); - - // Built the actions for new and existing records. - $canDo = $this->canDo; - ToolbarHelper::title( - Text::_('COM_CONTENT_PAGE_' . ($checkedOut ? 'VIEW_ARTICLE' : ($isNew ? 'ADD_ARTICLE' : 'EDIT_ARTICLE'))), - 'pencil-alt article-add' - ); - - // For new records, check the create permission. - if ($isNew && (\count($user->getAuthorisedCategories('com_content', 'core.create')) > 0)) { - $toolbar->apply('article.apply'); - - $saveGroup = $toolbar->dropdownButton('save-group'); - - $saveGroup->configure( - function (Toolbar $childBar) use ($user) { - $childBar->save('article.save'); - - if ($user->authorise('core.create', 'com_menus.menu')) { - $childBar->save('article.save2menu', 'JTOOLBAR_SAVE_TO_MENU'); - } - - $childBar->save2new('article.save2new'); - } - ); - - $toolbar->cancel('article.cancel', 'JTOOLBAR_CANCEL'); - } else { - // Since it's an existing record, check the edit permission, or fall back to edit own if the owner. - $itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId); - - if (!$checkedOut && $itemEditable) { - $toolbar->apply('article.apply'); - } - - $saveGroup = $toolbar->dropdownButton('save-group'); - - $saveGroup->configure( - function (Toolbar $childBar) use ($checkedOut, $itemEditable, $canDo, $user) { - // Can't save the record if it's checked out and editable - if (!$checkedOut && $itemEditable) { - $childBar->save('article.save'); - - // We can save this record, but check the create permission to see if we can return to make a new one. - if ($canDo->get('core.create')) { - $childBar->save2new('article.save2new'); - } - } - - // If checked out, we can still save2menu - if ($user->authorise('core.create', 'com_menus.menu')) { - $childBar->save('article.save2menu', 'JTOOLBAR_SAVE_TO_MENU'); - } - - // If checked out, we can still save - if ($canDo->get('core.create')) { - $childBar->save2copy('article.save2copy'); - } - } - ); - - $toolbar->cancel('article.cancel', 'JTOOLBAR_CLOSE'); - - if (!$isNew) { - if (ComponentHelper::isEnabled('com_contenthistory') && $this->state->get('params')->get('save_history', 0) && $itemEditable) { - $toolbar->versions('com_content.article', $this->item->id); - } - - $url = RouteHelper::getArticleRoute($this->item->id . ':' . $this->item->alias, $this->item->catid, $this->item->language); - - $toolbar->preview(Route::link('site', $url, true), 'JGLOBAL_PREVIEW') - ->bodyHeight(80) - ->modalWidth(90); - - if (PluginHelper::isEnabled('system', 'jooa11y')) { - $toolbar->jooa11y(Route::link('site', $url . '&jooa11y=1', true), 'JGLOBAL_JOOA11Y') - ->bodyHeight(80) - ->modalWidth(90); - } - - if (Associations::isEnabled() && ComponentHelper::isEnabled('com_associations')) { - $toolbar->standardButton('associations', 'JTOOLBAR_ASSOCIATIONS', 'article.editAssociations') - ->icon('icon-contract') - ->listCheck(false); - } - } - } + $this->toolbarTitle = Text::_('COM_CONTENT_PAGE_' . ($checkedOut ? 'VIEW_ARTICLE' : ($isNew ? 'ADD_ARTICLE' : 'EDIT_ARTICLE'))); - $toolbar->divider(); - $toolbar->inlinehelp(); - $toolbar->help('Articles:_Edit'); + parent::addToolbar(); } /** diff --git a/administrator/components/com_content/src/View/Articles/HtmlView.php b/administrator/components/com_content/src/View/Articles/HtmlView.php index cbc8eba68fc75..272d89a947dff 100644 --- a/administrator/components/com_content/src/View/Articles/HtmlView.php +++ b/administrator/components/com_content/src/View/Articles/HtmlView.php @@ -171,7 +171,7 @@ public function display($tpl = null) // Add form control fields $this->filterForm - ->addControlField('task', '') + ->addControlField('task') ->addControlField('boxchecked', '0'); parent::display($tpl); @@ -186,9 +186,9 @@ public function display($tpl = null) */ protected function addToolbar() { - $canDo = ContentHelper::getActions('com_content', 'category', $this->state->get('filter.category_id')); - $user = $this->getCurrentUser(); - $toolbar = $this->getDocument()->getToolbar(); + $canDo = ContentHelper::getActions('com_content', 'category', $this->state->get('filter.category_id')); + $user = $this->getCurrentUser(); + $toolbar = $this->getDocument()->getToolbar(); ToolbarHelper::title(Text::_('COM_CONTENT_ARTICLES_TITLE'), 'copy article'); @@ -234,11 +234,9 @@ protected function addToolbar() $childBar->unpublish('articles.unpublish')->listCheck(true); - $childBar->standardButton('featured', 'JFEATURE', 'articles.featured') - ->listCheck(true); + $childBar->standardButton('featured', 'JFEATURE', 'articles.featured')->listCheck(true); - $childBar->standardButton('unfeatured', 'JUNFEATURE', 'articles.unfeatured') - ->listCheck(true); + $childBar->standardButton('unfeatured', 'JUNFEATURE', 'articles.unfeatured')->listCheck(true); $childBar->archive('articles.archive')->listCheck(true); diff --git a/administrator/components/com_content/src/View/Featured/HtmlView.php b/administrator/components/com_content/src/View/Featured/HtmlView.php index a38910a969d89..7a7730b551e35 100644 --- a/administrator/components/com_content/src/View/Featured/HtmlView.php +++ b/administrator/components/com_content/src/View/Featured/HtmlView.php @@ -10,16 +10,7 @@ namespace Joomla\Component\Content\Administrator\View\Featured; -use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Language\Multilanguage; -use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; -use Joomla\CMS\Plugin\PluginHelper; -use Joomla\CMS\Toolbar\Button\DropdownButton; -use Joomla\CMS\Toolbar\ToolbarHelper; -use Joomla\Component\Content\Administrator\Extension\ContentComponent; -use Joomla\Component\Content\Administrator\Helper\ContentHelper; -use Joomla\Component\Content\Administrator\Model\FeaturedModel; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -29,177 +20,9 @@ * View class for a list of featured articles. * * @since 1.6 + * + * @deprecated 6.0 will be removed in 8.0 is integrated in Articles view */ class HtmlView extends BaseHtmlView { - /** - * An array of items - * - * @var array - */ - protected $items; - - /** - * The pagination object - * - * @var \Joomla\CMS\Pagination\Pagination - */ - protected $pagination; - - /** - * The model state - * - * @var \Joomla\Registry\Registry - */ - protected $state; - - /** - * Form object for search filters - * - * @var \Joomla\CMS\Form\Form - */ - public $filterForm; - - /** - * The active search filters - * - * @var array - */ - public $activeFilters; - - /** - * All transition, which can be executed of one if the items - * - * @var array - */ - protected $transitions = []; - - /** - * Is this view an Empty State - * - * @var boolean - * @since 4.0.0 - */ - private $isEmptyState = false; - - /** - * Display the view - * - * @param string $tpl The name of the template file to parse; automatically searches through the template paths. - * - * @return void - */ - public function display($tpl = null) - { - /** @var FeaturedModel $model */ - $model = $this->getModel(); - $model->setUseExceptions(true); - - $this->items = $model->getItems(); - $this->pagination = $model->getPagination(); - $this->state = $model->getState(); - $this->filterForm = $model->getFilterForm(); - $this->activeFilters = $model->getActiveFilters(); - $this->vote = PluginHelper::isEnabled('content', 'vote'); - $this->hits = ComponentHelper::getParams('com_content')->get('record_hits', 1); - - if (!\count($this->items) && $this->isEmptyState = $model->getIsEmptyState()) { - $this->setLayout('emptystate'); - } - - if (ComponentHelper::getParams('com_content')->get('workflow_enabled')) { - PluginHelper::importPlugin('workflow'); - - $this->transitions = $model->getTransitions(); - } - - $this->addToolbar(); - - // We do not need to filter by language when multilingual is disabled - if (!Multilanguage::isEnabled()) { - unset($this->activeFilters['language']); - $this->filterForm->removeField('language', 'filter'); - } - - parent::display($tpl); - } - - /** - * Add the page title and toolbar. - * - * @return void - * - * @since 1.6 - */ - protected function addToolbar() - { - $canDo = ContentHelper::getActions('com_content', 'category', $this->state->get('filter.category_id')); - $user = $this->getCurrentUser(); - $toolbar = $this->getDocument()->getToolbar(); - - ToolbarHelper::title(Text::_('COM_CONTENT_FEATURED_TITLE'), 'star featured'); - - if ($canDo->get('core.create') || \count($user->getAuthorisedCategories('com_content', 'core.create')) > 0) { - $toolbar->addNew('article.add'); - } - - if (!$this->isEmptyState && ($canDo->get('core.edit.state') || \count($this->transitions))) { - /** @var DropdownButton $dropdown */ - $dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS') - ->toggleSplit(false) - ->icon('icon-ellipsis-h') - ->buttonClass('btn btn-action') - ->listCheck(true); - - $childBar = $dropdown->getChildToolbar(); - - if (\count($this->transitions)) { - $childBar->separatorButton('transition-headline', 'COM_CONTENT_RUN_TRANSITIONS') - ->buttonClass('text-center py-2 h3'); - - $cmd = "Joomla.submitbutton('articles.runTransition');"; - $messages = "{error: [Joomla.Text._('JLIB_HTML_PLEASE_MAKE_A_SELECTION_FROM_THE_LIST')]}"; - $alert = 'Joomla.renderMessages(' . $messages . ')'; - $cmd = 'if (document.adminForm.boxchecked.value == 0) { ' . $alert . ' } else { ' . $cmd . ' }'; - - foreach ($this->transitions as $transition) { - $childBar->standardButton('transition', $transition['text']) - ->buttonClass('transition-' . (int) $transition['value']) - ->icon('icon-project-diagram') - ->onclick('document.adminForm.transition_id.value=' . (int) $transition['value'] . ';' . $cmd); - } - - $childBar->separatorButton('transition-separator'); - } - - if ($canDo->get('core.edit.state')) { - $childBar->publish('articles.publish')->listCheck(true); - - $childBar->unpublish('articles.unpublish')->listCheck(true); - - $childBar->standardButton('unfeatured', 'JUNFEATURE') - ->task('articles.unfeatured') - ->listCheck(true); - - $childBar->archive('articles.archive')->listCheck(true); - $childBar->checkin('articles.checkin'); - - if (!$this->state->get('filter.published') == ContentComponent::CONDITION_TRASHED) { - $childBar->trash('articles.trash')->listCheck(true); - } - } - } - - if (!$this->isEmptyState && $this->state->get('filter.published') == ContentComponent::CONDITION_TRASHED && $canDo->get('core.delete')) { - $toolbar->delete('articles.delete', 'JTOOLBAR_DELETE_FROM_TRASH') - ->message('JGLOBAL_CONFIRM_DELETE') - ->listCheck(true); - } - - if ($user->authorise('core.admin', 'com_content') || $user->authorise('core.options', 'com_content')) { - $toolbar->preferences('com_content'); - } - - $toolbar->help('Articles:_Featured'); - } } diff --git a/administrator/components/com_content/tmpl/articles/default.php b/administrator/components/com_content/tmpl/articles/default.php index 2ad21717fd3bd..0c56baffad293 100644 --- a/administrator/components/com_content/tmpl/articles/default.php +++ b/administrator/components/com_content/tmpl/articles/default.php @@ -37,7 +37,9 @@ $userId = $user->id; $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); -$saveOrder = $listOrder == 'a.ordering'; +$featured = $this->state->get('filter.featured'); +$orderName = $featured === '1' ? 'fp.ordering' : 'a.ordering'; +$saveOrder = $listOrder == $orderName; if (strpos($listOrder, 'publish_up') !== false) { $orderingColumn = 'publish_up'; @@ -50,7 +52,8 @@ } if ($saveOrder && !empty($this->items)) { - $saveOrderingUrl = 'index.php?option=com_content&task=articles.saveOrderAjax&tmpl=component&' . Session::getFormToken() . '=1'; + $controller = $featured === '1' ? 'featured' : 'articles'; + $saveOrderingUrl = 'index.php?option=com_content&task=' . $controller . '.saveOrderAjax&tmpl=component&' . Session::getFormToken() . '=1'; HTMLHelper::_('draggablelist.draggable'); } @@ -78,7 +81,7 @@
$this]); + echo LayoutHelper::render('joomla.searchtools.default', ['view' => $this, 'options' => ['selectorFieldName' => 'featured']]); ?> items)) : ?>
@@ -88,7 +91,7 @@ @@ -98,15 +101,15 @@ - + class="js-draggable" data-url="" data-direction="" data-nested="true" class="js-draggable" data-url="" data-direction=""> items as $i => $item) : $item->max_ordering = 0; + $ordering = ($listOrder == 'fp.ordering'); + $assetId = 'com_content.article.' . $item->id; + $canCreate = $user->authorise('core.create', 'com_content.category.' . $item->catid); $canEdit = $user->authorise('core.edit', 'com_content.article.' . $item->id); $canCheckin = $user->authorise('core.manage', 'com_checkin') || $item->checked_out == $userId || is_null($item->checked_out); $canEditOwn = $user->authorise('core.edit.own', 'com_content.article.' . $item->id) && $item->created_by == $userId; @@ -190,7 +196,7 @@ } ?> - > - $value) : ?> - value) && isset($object2->$name->value) && $value->value != $object2->$name->value) : ?> - value)) : ?> - - - - value as $subName => $subValue) : ?> - $name->value->$subName->value ?? ''; ?> - value || $newSubValue) : ?> - value != $newSubValue) : ?> - - - - - - + $value1) : ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - $name->value = is_object($object2->$name->value) ? json_encode($object2->$name->value) : $object2->$name->value; ?> - - - + - - +
- , + , ,
- + - - + + - + @@ -152,10 +155,13 @@
diff --git a/administrator/components/com_content/tmpl/articles/default.xml b/administrator/components/com_content/tmpl/articles/default.xml index 424d988d71cde..b042f2497994f 100644 --- a/administrator/components/com_content/tmpl/articles/default.xml +++ b/administrator/components/com_content/tmpl/articles/default.xml @@ -37,6 +37,19 @@ + + + + + + 'COM_CONTENT', 'formURL' => 'index.php?option=com_content&view=articles', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Adding_a_new_article', + 'helpURL' => 'https://guide.joomla.org/user-manual/articles', 'icon' => 'icon-copy article', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; $user = $this->getCurrentUser(); diff --git a/administrator/components/com_content/tmpl/articles/modal.php b/administrator/components/com_content/tmpl/articles/modal.php index 1d498b8a16b2a..b773f02f463e3 100644 --- a/administrator/components/com_content/tmpl/articles/modal.php +++ b/administrator/components/com_content/tmpl/articles/modal.php @@ -34,7 +34,7 @@ ->useScript('modal-content-select') ->useScript('com_content.admin-articles-modal'); -// @todo: Use of Function and Editor is deprecated and should be removed in 6.0. It stays only for backward compatibility. +// @todo: Use of Function and Editor is deprecated and should be removed in 7.0. It stays only for backward compatibility. $function = $app->getInput()->getCmd('function', 'jSelectArticle'); $editor = $app->getInput()->getCmd('editor', ''); $listOrder = $this->escape($this->state->get('list.ordering')); diff --git a/administrator/components/com_content/tmpl/featured/default.php b/administrator/components/com_content/tmpl/featured/default.php deleted file mode 100644 index a6541223ffeb8..0000000000000 --- a/administrator/components/com_content/tmpl/featured/default.php +++ /dev/null @@ -1,400 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\Button\FeaturedButton; -use Joomla\CMS\Button\PublishedButton; -use Joomla\CMS\Button\TransitionButton; -use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Factory; -use Joomla\CMS\HTML\HTMLHelper; -use Joomla\CMS\Language\Associations; -use Joomla\CMS\Language\Multilanguage; -use Joomla\CMS\Language\Text; -use Joomla\CMS\Layout\LayoutHelper; -use Joomla\CMS\Router\Route; -use Joomla\CMS\Session\Session; -use Joomla\Component\Content\Administrator\Helper\ContentHelper; -use Joomla\Utilities\ArrayHelper; - -/** @var \Joomla\Component\Content\Administrator\View\Featured\HtmlView $this */ - -/** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ -$wa = $this->getDocument()->getWebAssetManager(); -$wa->useScript('table.columns') - ->useScript('multiselect'); - -$app = Factory::getApplication(); -$user = $this->getCurrentUser(); -$userId = $user->id; -$listOrder = $this->escape($this->state->get('list.ordering')); -$listDirn = $this->escape($this->state->get('list.direction')); -$saveOrder = $listOrder == 'fp.ordering'; - -if (strpos($listOrder, 'publish_up') !== false) { - $orderingColumn = 'publish_up'; -} elseif (strpos($listOrder, 'publish_down') !== false) { - $orderingColumn = 'publish_down'; -} elseif (strpos($listOrder, 'modified') !== false) { - $orderingColumn = 'modified'; -} else { - $orderingColumn = 'created'; -} - - -if ($saveOrder && !empty($this->items)) { - $saveOrderingUrl = 'index.php?option=com_content&task=featured.saveOrderAjax&tmpl=component&' . Session::getFormToken() . '=1'; - HTMLHelper::_('draggablelist.draggable'); -} - -$workflow_enabled = ComponentHelper::getParams('com_content')->get('workflow_enabled'); -$workflow_state = false; -$workflow_featured = false; - -if ($workflow_enabled) : - $wa->getRegistry()->addExtensionRegistryFile('com_workflow'); - $wa->useScript('com_workflow.admin-items-workflow-buttons') - ->useScript('com_content.articles-status'); - - $workflow_state = Factory::getApplication()->bootComponent('com_content')->isFunctionalityUsed('core.state', 'com_content.article'); - $workflow_featured = Factory::getApplication()->bootComponent('com_content')->isFunctionalityUsed('core.featured', 'com_content.article'); -endif; - -$assoc = Associations::isEnabled(); - -?> - -
-
-
-
- $this]); - ?> - items)) : ?> -
- - -
- - - - - - - - - - - - - - - - - - - - - - - hits) : ?> - - - vote) : ?> - - - - - - - class="js-draggable" data-url="" data-direction=""> - items); ?> - items as $i => $item) : - $item->max_ordering = 0; - $ordering = ($listOrder == 'fp.ordering'); - $assetId = 'com_content.article.' . $item->id; - $canCreate = $user->authorise('core.create', 'com_content.category.' . $item->catid); - $canEdit = $user->authorise('core.edit', 'com_content.article.' . $item->id); - $canCheckin = $user->authorise('core.manage', 'com_checkin') || $item->checked_out == $userId || is_null($item->checked_out); - $canChange = $user->authorise('core.edit.state', 'com_content.article.' . $item->id) && $canCheckin; - $canEditCat = $user->authorise('core.edit', 'com_content.category.' . $item->catid); - $canEditOwnCat = $user->authorise('core.edit.own', 'com_content.category.' . $item->catid) && $item->category_uid == $userId; - $canEditParCat = $user->authorise('core.edit', 'com_content.category.' . $item->parent_category_id); - $canEditOwnParCat = $user->authorise('core.edit.own', 'com_content.category.' . $item->parent_category_id) && $item->parent_category_uid == $userId; - - $transitions = ContentHelper::filterTransitions($this->transitions, (int) $item->stage_id, (int) $item->workflow_id); - - $transition_ids = ArrayHelper::getColumn($transitions, 'value'); - $transition_ids = ArrayHelper::toInteger($transition_ids); - - ?> - - - - - - - - - - - - - - - - - - - hits) : ?> - - - vote) : ?> - - - - - - - -
- , - , - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- id, false, 'cid', 'cb', $item->title); ?> - - - - - - - - - - $transitions, - 'title' => Text::_($item->stage_title), - 'tip_content' => Text::sprintf('JWORKFLOW', Text::_($item->workflow_title)), - 'id' => 'workflow-' . $item->id, - 'task' => 'articles.runTransition' - ]; - - echo (new TransitionButton($options)) - ->render(0, $i); - ?> -
- stage_title); ?> -
-
- 'articles.', - 'disabled' => $workflow_featured || !$canChange, - 'id' => 'featured-' . $item->id - ]; - - echo (new FeaturedButton()) - ->render((int) $item->featured, $i, $options, $item->featured_up, $item->featured_down); - ?> - - 'articles.', - 'disabled' => $workflow_state || !$canChange, - 'id' => 'state-' . $item->id, - 'category_published' => $item->category_published - ]; - - echo (new PublishedButton())->render((int) $item->state, $i, $options, $item->publish_up, $item->publish_down); - ?> - -
- checked_out) : ?> - editor, $item->checked_out_time, 'articles.', $canCheckin); ?> - - - - escape($item->title); ?> - - escape($item->title); ?> - -
- note)) : ?> - escape($item->alias)); ?> - - escape($item->alias), $this->escape($item->note)); ?> - -
-
- parent_category_id . '&extension=com_content'); - $CurrentCatUrl = Route::_('index.php?option=com_categories&task=category.edit&id=' . $item->catid . '&extension=com_content'); - $EditCatTxt = Text::_('COM_CONTENT_EDIT_CATEGORY'); - echo Text::_('JCATEGORY') . ': '; - if ($item->category_level != '1') : - if ($item->parent_category_level != '1') : - echo ' » '; - endif; - endif; - if ($this->getLanguage()->isRtl()) { - if ($canEditCat || $canEditOwnCat) : - echo ''; - endif; - echo $this->escape($item->category_title); - if ($canEditCat || $canEditOwnCat) : - echo ''; - endif; - if ($item->category_level != '1') : - echo ' « '; - if ($canEditParCat || $canEditOwnParCat) : - echo ''; - endif; - echo $this->escape($item->parent_category_title); - if ($canEditParCat || $canEditOwnParCat) : - echo ''; - endif; - endif; - } else { - if ($item->category_level != '1') : - if ($canEditParCat || $canEditOwnParCat) : - echo ''; - endif; - echo $this->escape($item->parent_category_title); - if ($canEditParCat || $canEditOwnParCat) : - echo ''; - endif; - echo ' » '; - endif; - if ($canEditCat || $canEditOwnCat) : - echo ''; - endif; - echo $this->escape($item->category_title); - if ($canEditCat || $canEditOwnCat) : - echo ''; - endif; - } - if ($item->category_published < '1') : - echo $item->category_published == '0' ? ' (' . Text::_('JUNPUBLISHED') . ')' : ' (' . Text::_('JTRASHED') . ')'; - endif; - ?> -
-
-
- escape($item->access_level); ?> - - author_name)) : ?> - - escape($item->author_name); ?> - - - [ ] - - created_by_alias) : ?> -
escape($item->created_by_alias)); ?>
- -
- association) : ?> - id); ?> - - - - - {$orderingColumn}; - echo $date > 0 ? HTMLHelper::_('date', $date, Text::_('DATE_FORMAT_LC4')) : '-'; - ?> - - - hits; ?> - - - - rating_count; ?> - - - - rating; ?> - - - id; ?> -
- - - pagination->getListFooter(); ?> - - Text::_('JTOOLBAR_CHANGE_STATUS'), - 'footer' => $this->loadTemplate('stage_footer'), - ], - $this->loadTemplate('stage_body') - ); ?> - - - - - - - - - - - -
-
-
-
diff --git a/administrator/components/com_content/tmpl/featured/default.xml b/administrator/components/com_content/tmpl/featured/default.xml deleted file mode 100644 index 34a2929f6e8e1..0000000000000 --- a/administrator/components/com_content/tmpl/featured/default.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/administrator/components/com_content/tmpl/featured/default_stage_body.php b/administrator/components/com_content/tmpl/featured/default_stage_body.php deleted file mode 100644 index d5f510e40a892..0000000000000 --- a/administrator/components/com_content/tmpl/featured/default_stage_body.php +++ /dev/null @@ -1,25 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\Language\Text; - -?> - -
-
-
-

-
-
-
-
-
diff --git a/administrator/components/com_content/tmpl/featured/default_stage_footer.php b/administrator/components/com_content/tmpl/featured/default_stage_footer.php deleted file mode 100644 index 8c6d2bfccdad4..0000000000000 --- a/administrator/components/com_content/tmpl/featured/default_stage_footer.php +++ /dev/null @@ -1,27 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\Language\Text; - -/** @var \Joomla\Component\Content\Administrator\View\Featured\HtmlView $this */ - -/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ -$wa = $this->getDocument()->getWebAssetManager(); -$wa->useScript('com_content.admin-articles-stage'); - -?> - - diff --git a/administrator/components/com_content/tmpl/featured/emptystate.php b/administrator/components/com_content/tmpl/featured/emptystate.php deleted file mode 100644 index 3f20dbd6f98e9..0000000000000 --- a/administrator/components/com_content/tmpl/featured/emptystate.php +++ /dev/null @@ -1,29 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -defined('_JEXEC') or die; - -use Joomla\CMS\Layout\LayoutHelper; - -/** @var \Joomla\Component\Content\Administrator\View\Featured\HtmlView $this */ - -$displayData = [ - 'textPrefix' => 'COM_CONTENT', - 'formURL' => 'index.php?option=com_content&view=featured', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Adding_a_new_article', -]; - -$user = $this->getCurrentUser(); - -if ($user->authorise('core.create', 'com_content') || count($user->getAuthorisedCategories('com_content', 'core.create')) > 0) { - $displayData['createURL'] = 'index.php?option=com_content&task=article.add'; -} - -echo LayoutHelper::render('joomla.content.emptystate', $displayData); diff --git a/administrator/components/com_contenthistory/helpers/contenthistory.php b/administrator/components/com_contenthistory/helpers/contenthistory.php index 2c6e09c5244a4..4bc9ab99a1c78 100644 --- a/administrator/components/com_contenthistory/helpers/contenthistory.php +++ b/administrator/components/com_contenthistory/helpers/contenthistory.php @@ -19,7 +19,7 @@ * * @since 3.2 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Contenthistory\Administrator\Helper\ContenthistoryHelper instead */ class ContenthistoryHelper extends \Joomla\Component\Contenthistory\Administrator\Helper\ContenthistoryHelper diff --git a/administrator/components/com_contenthistory/src/Helper/ContenthistoryHelper.php b/administrator/components/com_contenthistory/src/Helper/ContenthistoryHelper.php index aa501e65ce981..ade226ba68bc4 100644 --- a/administrator/components/com_contenthistory/src/Helper/ContenthistoryHelper.php +++ b/administrator/components/com_contenthistory/src/Helper/ContenthistoryHelper.php @@ -14,11 +14,11 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Table\ContentHistory; use Joomla\CMS\Table\ContentType; -use Joomla\CMS\Table\Table; use Joomla\Database\ParameterType; use Joomla\Filesystem\File; use Joomla\Filesystem\Folder; use Joomla\Filesystem\Path; +use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -76,8 +76,18 @@ public static function decodeFields($jsonString) if (\is_object($object)) { foreach ($object as $name => $value) { - if (!\is_null($value) && $subObject = json_decode($value)) { - $object->$name = $subObject; + if (!\is_null($value)) { + if (\is_object($value)) { + $object->$name = ArrayHelper::fromObject($value); + continue; + } + + if (str_starts_with($value, '{')) { + $object->$name = json_decode($value); + continue; + } + + $object->$name = $value; } } } @@ -192,7 +202,7 @@ public static function getLookupValue($lookup, $value) if (isset($lookup->sourceColumn, $lookup->targetTable, $lookup->targetColumn, $lookup->displayColumn)) { $db = Factory::getDbo(); $value = (int) $value; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName($lookup->displayColumn)) ->from($db->quoteName($lookup->targetTable)) ->where($db->quoteName($lookup->targetColumn) . ' = :value') @@ -320,7 +330,7 @@ public static function mergeLabels($object, $formValues) public static function prepareData(ContentHistory $table) { $object = static::decodeFields($table->version_data); - $typesTable = Table::getInstance('ContentType', 'Joomla\\CMS\\Table\\'); + $typesTable = new ContentType(Factory::getDbo()); $typeAlias = explode('.', $table->item_id); array_pop($typeAlias); $typesTable->load(['type_alias' => implode('.', $typeAlias)]); @@ -351,8 +361,24 @@ public static function processLookupFields($object, ContentType $typesTable) $sourceColumn = $lookup->sourceColumn ?? false; $sourceValue = $object->$sourceColumn->value ?? false; - if ($sourceColumn && $sourceValue && ($lookupValue = static::getLookupValue($lookup, $sourceValue))) { - $object->$sourceColumn->value = $lookupValue; + if (!\is_array($sourceValue)) { + if ($sourceColumn && $sourceValue && ($lookupValue = static::getLookupValue($lookup, $sourceValue))) { + $object->$sourceColumn->value = $lookupValue; + } + + continue; + } + + if (\is_array($sourceValue)) { + $result = []; + + foreach ($sourceValue as $key => $subValue) { + if ($sourceColumn && $subValue && ($lookupValue = static::getLookupValue($lookup, $subValue))) { + $result[$key] = $lookupValue; + } + + $object->$sourceColumn->value = $result; + } } } } diff --git a/administrator/components/com_contenthistory/src/Model/HistoryModel.php b/administrator/components/com_contenthistory/src/Model/HistoryModel.php index fa06f07b33773..60ef3d2c3a905 100644 --- a/administrator/components/com_contenthistory/src/Model/HistoryModel.php +++ b/administrator/components/com_contenthistory/src/Model/HistoryModel.php @@ -305,7 +305,6 @@ protected function populateState($ordering = 'h.save_date', $direction = 'DESC') $itemId = $input->get('item_id', '', 'string'); $this->setState('item_id', $itemId); - $this->setState('sha1_hash', $this->getSha1Hash()); // Load the parameters. $params = ComponentHelper::getParams('com_contenthistory'); @@ -326,7 +325,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $itemId = $this->getState('item_id'); // Select the required fields from the table. @@ -343,6 +342,7 @@ protected function getListQuery() $db->quoteName('h.sha1_hash'), $db->quoteName('h.version_data'), $db->quoteName('h.keep_forever'), + $db->quoteName('h.is_current'), ] ) ) @@ -373,17 +373,33 @@ protected function getListQuery() * * @since 3.2 */ - protected function getSha1Hash() + public function getSha1Hash() { + /** + * From Joomla 6, we use is_current field to determine the current version, so no need to calculate sha1 hash + * if there is already a current version + */ + + $items = $this->getItems(); + + foreach ($items as $item) { + if ($item->is_current == 1) { + return $item->sha1_hash; + } + } + + // Legacy code for history concept before 6.0.0, deprecated 6.0.0 will be removed with 8.0.0 $result = false; - $item_id = Factory::getApplication()->getInput()->getCmd('item_id', ''); - $typeAlias = explode('.', $item_id); - Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/' . $typeAlias[0] . '/tables'); + $item_id = $this->state->get('item_id', ''); + + [$extension, $type, $id] = explode('.', $item_id); + + Table::addIncludePath(JPATH_ADMINISTRATOR . '/components/' . $extension . '/tables'); $typeTable = $this->getTable('ContentType'); - $typeTable->load(['type_alias' => $typeAlias[0] . '.' . $typeAlias[1]]); + $typeTable->load(['type_alias' => $extension . '.' . $type]); $contentTable = $typeTable->getContentTable(); - if ($contentTable && $contentTable->load($typeAlias[2])) { + if ($contentTable && $contentTable->load($id)) { $helper = new CMSHelper(); $dataObject = $helper->getDataObject($contentTable); diff --git a/administrator/components/com_contenthistory/src/View/History/HtmlView.php b/administrator/components/com_contenthistory/src/View/History/HtmlView.php index 9167863588c04..2c29e9ee77b9d 100644 --- a/administrator/components/com_contenthistory/src/View/History/HtmlView.php +++ b/administrator/components/com_contenthistory/src/View/History/HtmlView.php @@ -59,6 +59,13 @@ class HtmlView extends BaseHtmlView */ protected $toolbar; + /** + * The SHA1 hash of the current version of the item being viewed + * + * @var string + */ + protected $currentVersionHash; + /** * Method to display the view. * @@ -74,9 +81,10 @@ public function display($tpl = null) $model = $this->getModel(); $model->setUseExceptions(true); - $this->state = $model->getState(); - $this->items = $model->getItems(); - $this->pagination = $model->getPagination(); + $this->state = $model->getState(); + $this->items = $model->getItems(); + $this->pagination = $model->getPagination(); + $this->currentVersionHash = $model->getSha1Hash(); $this->toolbar = $this->addToolbar(); diff --git a/administrator/components/com_contenthistory/tmpl/compare/compare.php b/administrator/components/com_contenthistory/tmpl/compare/compare.php index 8f855b92c1ad8..fd9812febac91 100644 --- a/administrator/components/com_contenthistory/tmpl/compare/compare.php +++ b/administrator/components/com_contenthistory/tmpl/compare/compare.php @@ -12,6 +12,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Session\Session; +use Joomla\Utilities\ArrayHelper; /** @var \Joomla\Component\Contenthistory\Administrator\View\Compare\HtmlView $this */ @@ -19,8 +20,8 @@ $version2 = $this->items[0]; $version1 = $this->items[1]; -$object1 = $version1->data; -$object2 = $version2->data; +$object1 = ArrayHelper::fromObject($version1->data); +$object2 = ArrayHelper::fromObject($version2->data); /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->getDocument()->getWebAssetManager(); @@ -43,40 +44,69 @@
- label; ?> -
  label; ?>value, ENT_COMPAT, 'UTF-8'); ?> 
+ +
+ + + + + + + + + + + + + + + + + + + +  
+ +  
- label; ?> - value); ?>$name->value, ENT_COMPAT, 'UTF-8'); ?> 
diff --git a/administrator/components/com_contenthistory/tmpl/history/modal.php b/administrator/components/com_contenthistory/tmpl/history/modal.php index 759607d4cbfd9..64d90c2502168 100644 --- a/administrator/components/com_contenthistory/tmpl/history/modal.php +++ b/administrator/components/com_contenthistory/tmpl/history/modal.php @@ -19,7 +19,7 @@ Session::checkToken('get') or die(Text::_('JINVALID_TOKEN')); -$hash = $this->state->get('sha1_hash'); +$hash = $this->currentVersionHash; $formUrl = 'index.php?option=com_contenthistory&view=history&layout=modal&tmpl=component&item_id=' . $this->state->get('item_id') . '&' . Session::getFormToken() . '=1'; Text::script('COM_CONTENTHISTORY_BUTTON_SELECT_ONE_VERSION', true); diff --git a/administrator/components/com_contenthistory/tmpl/preview/preview.php b/administrator/components/com_contenthistory/tmpl/preview/preview.php index 390aa50e6e7a6..587abb3452efc 100644 --- a/administrator/components/com_contenthistory/tmpl/preview/preview.php +++ b/administrator/components/com_contenthistory/tmpl/preview/preview.php @@ -51,14 +51,27 @@ value = (\is_object($subValue->value) || \is_array($subValue->value)) ? \json_encode($subValue->value, \JSON_UNESCAPED_UNICODE) : $subValue->value; ?>   label; ?> - escape($subValue->value); ?> + + value)) : ?> + escape(json_decode($subValue->value)); ?> + + escape($subValue->value); ?> + + + label; ?> - escape($value->value); ?> + + value)) : ?> + escape(json_encode($value->value)); ?> + + escape($value->value); ?> + + diff --git a/administrator/components/com_fields/helpers/fields.php b/administrator/components/com_fields/helpers/fields.php index 2553d401495d8..ac7be20986c8f 100644 --- a/administrator/components/com_fields/helpers/fields.php +++ b/administrator/components/com_fields/helpers/fields.php @@ -19,7 +19,7 @@ * * @since 3.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Fields\Administrator\Helper\FieldsHelper instead */ class FieldsHelper extends \Joomla\Component\Fields\Administrator\Helper\FieldsHelper diff --git a/administrator/components/com_fields/src/Controller/FieldController.php b/administrator/components/com_fields/src/Controller/FieldController.php index 8401f415a7f29..e58ecd2fba469 100644 --- a/administrator/components/com_fields/src/Controller/FieldController.php +++ b/administrator/components/com_fields/src/Controller/FieldController.php @@ -103,6 +103,20 @@ protected function allowEdit($data = [], $key = 'id') return parent::allowEdit($data, $key); } + // Get existing record + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) { + return false; + } + + [$recordOption] = explode('.', $record->context); + + // Validate request context and field context match + if ($recordOption !== $this->component) { + return false; + } + // Check edit on the record asset (explicit or inherited) if ($user->authorise('core.edit', $this->component . '.field.' . $recordId)) { return true; @@ -110,13 +124,6 @@ protected function allowEdit($data = [], $key = 'id') // Check edit own on the record asset (explicit or inherited) if ($user->authorise('core.edit.own', $this->component . '.field.' . $recordId)) { - // Existing record already has an owner, get it - $record = $this->getModel()->getItem($recordId); - - if (empty($record)) { - return false; - } - // Grant if current user is owner of the record return $user->id == $record->created_user_id; } diff --git a/administrator/components/com_fields/src/Controller/GroupController.php b/administrator/components/com_fields/src/Controller/GroupController.php index debed0279faeb..b5a6c82f043df 100644 --- a/administrator/components/com_fields/src/Controller/GroupController.php +++ b/administrator/components/com_fields/src/Controller/GroupController.php @@ -125,6 +125,20 @@ protected function allowEdit($data = [], $key = 'parent_id') return parent::allowEdit($data, $key); } + // Get existing record + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) { + return false; + } + + [$recordOption] = explode('.', $record->context); + + // Validate request context and field context match + if ($recordOption !== $this->component) { + return false; + } + // Check edit on the record asset (explicit or inherited) if ($user->authorise('core.edit', $this->component . '.fieldgroup.' . $recordId)) { return true; @@ -132,13 +146,6 @@ protected function allowEdit($data = [], $key = 'parent_id') // Check edit own on the record asset (explicit or inherited) if ($user->authorise('core.edit.own', $this->component . '.fieldgroup.' . $recordId) || $user->authorise('core.edit.own', $this->component)) { - // Existing record already has an owner, get it - $record = $this->getModel()->getItem($recordId); - - if (empty($record)) { - return false; - } - // Grant if current user is owner of the record return $user->id == $record->created_by; } diff --git a/administrator/components/com_fields/src/Field/ComponentsFieldgroupField.php b/administrator/components/com_fields/src/Field/ComponentsFieldgroupField.php index a0a846231577e..988e1a552947d 100644 --- a/administrator/components/com_fields/src/Field/ComponentsFieldgroupField.php +++ b/administrator/components/com_fields/src/Field/ComponentsFieldgroupField.php @@ -48,7 +48,7 @@ protected function getOptions() // Initialise variable. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT a.name AS text, a.element AS value') ->from('#__extensions as a') ->where('a.enabled >= 1') diff --git a/administrator/components/com_fields/src/Field/ComponentsFieldsField.php b/administrator/components/com_fields/src/Field/ComponentsFieldsField.php index 5e63972a75754..6991a493afa1d 100644 --- a/administrator/components/com_fields/src/Field/ComponentsFieldsField.php +++ b/administrator/components/com_fields/src/Field/ComponentsFieldsField.php @@ -48,7 +48,7 @@ protected function getOptions() // Initialise variable. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT a.name AS text, a.element AS value') ->from('#__extensions as a') ->where('a.enabled >= 1') diff --git a/administrator/components/com_fields/src/Field/FieldLayoutField.php b/administrator/components/com_fields/src/Field/FieldLayoutField.php index 95216b097eadb..b5d4c26b39166 100644 --- a/administrator/components/com_fields/src/Field/FieldLayoutField.php +++ b/administrator/components/com_fields/src/Field/FieldLayoutField.php @@ -51,7 +51,7 @@ protected function getInput() if ($extension) { // Get the database object and a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Build the query. $query->select('element, name') diff --git a/administrator/components/com_fields/src/Field/FieldgroupsField.php b/administrator/components/com_fields/src/Field/FieldgroupsField.php index 65e0110c776d0..bdaf402a17f84 100644 --- a/administrator/components/com_fields/src/Field/FieldgroupsField.php +++ b/administrator/components/com_fields/src/Field/FieldgroupsField.php @@ -46,7 +46,7 @@ protected function getOptions() $viewlevels = ArrayHelper::toInteger($user->getAuthorisedViewLevels()); $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ $db->quoteName('title', 'text'), diff --git a/administrator/components/com_fields/src/Helper/FieldsHelper.php b/administrator/components/com_fields/src/Helper/FieldsHelper.php index d1b98e21efe1a..a80d834387ace 100644 --- a/administrator/components/com_fields/src/Helper/FieldsHelper.php +++ b/administrator/components/com_fields/src/Helper/FieldsHelper.php @@ -601,7 +601,7 @@ public static function getAssignedCategoriesIds($fieldId) } $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('a.category_id')) ->from($db->quoteName('#__fields_categories', 'a')) @@ -630,7 +630,7 @@ public static function getAssignedCategoriesTitles($fieldId) } $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('c.title')) ->from($db->quoteName('#__fields_categories', 'a')) @@ -653,7 +653,7 @@ public static function getAssignedCategoriesTitles($fieldId) public static function getFieldsPluginId() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) diff --git a/administrator/components/com_fields/src/Model/FieldModel.php b/administrator/components/com_fields/src/Model/FieldModel.php index 6c18c3c76c52f..a09edbd323d57 100644 --- a/administrator/components/com_fields/src/Model/FieldModel.php +++ b/administrator/components/com_fields/src/Model/FieldModel.php @@ -224,7 +224,7 @@ public function save($data) } // First delete all assigned categories - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete('#__fields_categories') ->where($db->quoteName('field_id') . ' = :fieldid') ->bind(':fieldid', $id, ParameterType::INTEGER); @@ -261,7 +261,7 @@ public function save($data) $names = array_column((array) $newParams, 'value'); $fieldId = (int) $field->id; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete($db->quoteName('#__fields_values')) ->where($db->quoteName('field_id') . ' = :fieldid') ->bind(':fieldid', $fieldId, ParameterType::INTEGER); @@ -352,7 +352,7 @@ private function checkDefaultValue($data) try { $rule->setDatabase($this->getDatabase()); } catch (DatabaseNotFoundException) { - @trigger_error('Database must be set, this will not be caught anymore in 5.0.', E_USER_DEPRECATED); + @trigger_error('Database must be set, this will not be caught anymore in 7.0.', E_USER_DEPRECATED); $rule->setDatabase(Factory::getContainer()->get(DatabaseInterface::class)); } } @@ -429,7 +429,7 @@ public function getItem($pk = null) } $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $fieldId = (int) $result->id; $query->select($db->quoteName('category_id')) ->from($db->quoteName('#__fields_categories')) @@ -513,7 +513,7 @@ public function delete(&$pks) if (!empty($pks)) { // Delete Values - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete($db->quoteName('#__fields_values')) ->whereIn($db->quoteName('field_id'), $pks); @@ -521,7 +521,7 @@ public function delete(&$pks) $db->setQuery($query)->execute(); // Delete Assigned Categories - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete($db->quoteName('#__fields_categories')) ->whereIn($db->quoteName('field_id'), $pks); @@ -539,9 +539,10 @@ public function delete(&$pks) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 3.7.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -579,10 +580,6 @@ public function getForm($data = [], $loadData = true) ] ); - if (empty($form)) { - return false; - } - // Modify the form based on Edit State access controls. if (empty($data['context'])) { $data['context'] = $context; @@ -665,7 +662,7 @@ public function setFieldValue($fieldId, $itemId, $value) // Deleting the existing record as it is a reset $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete($db->quoteName('#__fields_values')) ->where($db->quoteName('field_id') . ' = :fieldid') @@ -749,7 +746,7 @@ public function getFieldValues(array $fieldIds, $itemId) if (!\array_key_exists($key, $this->valueCache)) { // Create the query $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName(['field_id', 'value'])) ->from($db->quoteName('#__fields_values')) @@ -804,12 +801,12 @@ public function cleanupValues($context, $itemId) { // Delete with inner join is not possible so we need to do a subquery $db = $this->getDatabase(); - $fieldsQuery = $db->getQuery(true); + $fieldsQuery = $db->createQuery(); $fieldsQuery->select($db->quoteName('id')) ->from($db->quoteName('#__fields')) ->where($db->quoteName('context') . ' = :context'); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete($db->quoteName('#__fields_values')) ->where($db->quoteName('field_id') . ' IN (' . $fieldsQuery . ')') @@ -960,24 +957,18 @@ protected function loadFormData() // get selected fields $filters = (array) $app->getUserState('com_fields.fields.filter'); - $data->set('state', $input->getInt('state', ((isset($filters['state']) && $filters['state'] !== '') ? $filters['state'] : null))); - $data->set('language', $input->getString('language', (!empty($filters['language']) ? $filters['language'] : null))); - $data->set('group_id', $input->getString('group_id', (!empty($filters['group_id']) ? $filters['group_id'] : null))); - $data->set( + $data->state = $input->getInt('state', ((isset($filters['state']) && $filters['state'] !== '') ? $filters['state'] : null)); + $data->language = $input->getString('language', (!empty($filters['language']) ? $filters['language'] : null)); + $data->group_id = $input->getString('group_id', (!empty($filters['group_id']) ? $filters['group_id'] : null)); + $data->assigned_cat_ids = $input->get( 'assigned_cat_ids', - $input->get( - 'assigned_cat_ids', - (!empty($filters['assigned_cat_ids']) ? (array)$filters['assigned_cat_ids'] : [0]), - 'array' - ) - ); - $data->set( - 'access', - $input->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access'))) + (!empty($filters['assigned_cat_ids']) ? (array)$filters['assigned_cat_ids'] : [0]), + 'array' ); + $data->access = $input->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access'))); // Set the type if available from the request - $data->set('type', $input->getWord('type', $this->state->get('field.type', $data->get('type')))); + $data->type = $input->getWord('type', $this->state->get('field.type', $data->type)); } if ($data->label && !isset($data->params['label'])) { @@ -1140,15 +1131,13 @@ function () use ($component, $section) { /** * Clean the cache * - * @param string $group The cache group - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 3.7.0 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { $context = Factory::getApplication()->getInput()->get('context'); @@ -1186,14 +1175,20 @@ protected function batchCopy($value, $pks, $contexts) $user = $this->getCurrentUser(); $table = $this->getTable(); $newIds = []; - $component = $this->state->get('filter.component'); $value = (int) $value; foreach ($pks as $pk) { - if ($user->authorise('core.create', $component . '.fieldgroup.' . $value)) { + $table->reset(); + $table->load($pk); + [$recordComponent] = explode('.', (string) $table->context); + + if ( + $user->authorise('core.create', $recordComponent . '.fieldgroup.' . $value) + && $user->authorise('core.edit', $recordComponent . '.field.' . $pk) + ) { // Find all assigned categories to this field $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('category_id')) ->from($db->quoteName('#__fields_categories')) @@ -1201,9 +1196,6 @@ protected function batchCopy($value, $pks, $contexts) $assignedCatIds = $db->setQuery($query)->loadColumn(); - $table->reset(); - $table->load($pk); - $table->group_id = $value; // Reset the ID because we are making a copy diff --git a/administrator/components/com_fields/src/Model/FieldsModel.php b/administrator/components/com_fields/src/Model/FieldsModel.php index 4993a1cfd1ca0..665c8ac44503c 100644 --- a/administrator/components/com_fields/src/Model/FieldsModel.php +++ b/administrator/components/com_fields/src/Model/FieldsModel.php @@ -140,7 +140,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = $this->getCurrentUser(); $app = Factory::getApplication(); @@ -444,7 +444,7 @@ public function getGroups() $context = $this->state->get('filter.context'); $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ $db->quoteName('title', 'text'), diff --git a/administrator/components/com_fields/src/Model/GroupModel.php b/administrator/components/com_fields/src/Model/GroupModel.php index 196b956b0d73d..ad49c788d043d 100644 --- a/administrator/components/com_fields/src/Model/GroupModel.php +++ b/administrator/components/com_fields/src/Model/GroupModel.php @@ -92,9 +92,10 @@ public function getTable($name = 'Group', $prefix = 'Administrator', $options = * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return mixed A Form object on success, false on failure + * @return Form A Form object * * @since 3.7.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -116,10 +117,6 @@ public function getForm($data = [], $loadData = true) ] ); - if (empty($form)) { - return false; - } - $record = new \stdClass(); $record->context = $context; $record->id = $jinput->get('id'); @@ -318,18 +315,9 @@ protected function loadFormData() $context = substr($app->getUserState('com_fields.groups.filter.context', ''), 4); $filters = (array) $app->getUserState('com_fields.groups.' . $context . '.filter'); - $data->set( - 'state', - $input->getInt('state', (!empty($filters['state']) ? $filters['state'] : null)) - ); - $data->set( - 'language', - $input->getString('language', (!empty($filters['language']) ? $filters['language'] : null)) - ); - $data->set( - 'access', - $input->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access'))) - ); + $data->state = $input->getInt('state', (!empty($filters['state']) ? $filters['state'] : null)); + $data->language = $input->getString('language', (!empty($filters['language']) ? $filters['language'] : null)); + $data->access = $input->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access'))); } } @@ -366,15 +354,13 @@ public function getItem($pk = null) /** * Clean the cache * - * @param string $group The cache group - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 3.7.0 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { $context = Factory::getApplication()->getInput()->get('context'); diff --git a/administrator/components/com_fields/src/Model/GroupsModel.php b/administrator/components/com_fields/src/Model/GroupsModel.php index 5ad10277f1c23..e5b270899e020 100644 --- a/administrator/components/com_fields/src/Model/GroupsModel.php +++ b/administrator/components/com_fields/src/Model/GroupsModel.php @@ -128,7 +128,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = $this->getCurrentUser(); // Select the required fields from the table. diff --git a/administrator/components/com_fields/src/Table/FieldTable.php b/administrator/components/com_fields/src/Table/FieldTable.php index de2620c2fc057..fdbd40c59c38e 100644 --- a/administrator/components/com_fields/src/Table/FieldTable.php +++ b/administrator/components/com_fields/src/Table/FieldTable.php @@ -127,7 +127,6 @@ public function bind($src, $ignore = '') * * @return boolean True if the instance is sane and able to be stored in the database. * - * @link https://docs.joomla.org/Special:MyLanguage/JTable/check * @since 3.7.0 */ public function check() @@ -243,7 +242,6 @@ protected function _getAssetName() * * @return string The string to use as the title in the asset table. * - * @link https://docs.joomla.org/Special:MyLanguage/JTable/getAssetTitle * @since 3.7.0 */ protected function _getAssetTitle() @@ -299,7 +297,7 @@ protected function _getAssetParentId(?Table $table = null, $id = null) private function getAssetId($name) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__assets')) ->where($db->quoteName('name') . ' = :name') diff --git a/administrator/components/com_fields/src/Table/GroupTable.php b/administrator/components/com_fields/src/Table/GroupTable.php index 2e9eb93ffc324..95cb3bad47454 100644 --- a/administrator/components/com_fields/src/Table/GroupTable.php +++ b/administrator/components/com_fields/src/Table/GroupTable.php @@ -94,7 +94,6 @@ public function bind($src, $ignore = '') * * @return boolean True if the instance is sane and able to be stored in the database. * - * @link https://docs.joomla.org/Special:MyLanguage/JTable/check * @since 3.7.0 */ public function check() @@ -178,7 +177,6 @@ protected function _getAssetName() * * @return string The string to use as the title in the asset table. * - * @link https://docs.joomla.org/Special:MyLanguage/JTable/getAssetTitle * @since 3.7.0 */ protected function _getAssetTitle() @@ -204,7 +202,7 @@ protected function _getAssetParentId(?Table $table = null, $id = null) { $component = explode('.', $this->context); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__assets')) ->where($db->quoteName('name') . ' = :name') diff --git a/administrator/components/com_fields/src/View/Field/HtmlView.php b/administrator/components/com_fields/src/View/Field/HtmlView.php index 647743895cb23..35e7cb6f2009a 100644 --- a/administrator/components/com_fields/src/View/Field/HtmlView.php +++ b/administrator/components/com_fields/src/View/Field/HtmlView.php @@ -78,6 +78,10 @@ public function display($tpl = null) $this->addToolbar(); + // Add form control fields + $this->form + ->addControlField('task'); + parent::display($tpl); } diff --git a/administrator/components/com_fields/src/View/Fields/HtmlView.php b/administrator/components/com_fields/src/View/Fields/HtmlView.php index 8f395bc2db3c7..da72c4a2e45e2 100644 --- a/administrator/components/com_fields/src/View/Fields/HtmlView.php +++ b/administrator/components/com_fields/src/View/Fields/HtmlView.php @@ -109,6 +109,11 @@ public function display($tpl = null) } } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_fields/src/View/Group/HtmlView.php b/administrator/components/com_fields/src/View/Group/HtmlView.php index b6ebc8d9bd778..b870e4deed52a 100644 --- a/administrator/components/com_fields/src/View/Group/HtmlView.php +++ b/administrator/components/com_fields/src/View/Group/HtmlView.php @@ -96,6 +96,10 @@ public function display($tpl = null) $this->addToolbar(); + // Add form control fields + $this->form + ->addControlField('task'); + parent::display($tpl); } diff --git a/administrator/components/com_fields/src/View/Groups/HtmlView.php b/administrator/components/com_fields/src/View/Groups/HtmlView.php index b2c15e384f39e..92e6de5b6b02e 100644 --- a/administrator/components/com_fields/src/View/Groups/HtmlView.php +++ b/administrator/components/com_fields/src/View/Groups/HtmlView.php @@ -106,6 +106,11 @@ public function display($tpl = null) $this->filterForm->removeField('language', 'filter'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_fields/tmpl/field/edit.php b/administrator/components/com_fields/tmpl/field/edit.php index ff044f1040eca..a6e0eaa7585c6 100644 --- a/administrator/components/com_fields/tmpl/field/edit.php +++ b/administrator/components/com_fields/tmpl/field/edit.php @@ -95,7 +95,7 @@ form->getInput('context'); ?> - - + + form->renderControlFields(); ?>
diff --git a/administrator/components/com_fields/tmpl/fields/default.php b/administrator/components/com_fields/tmpl/fields/default.php index 0c237e1ddde3b..21955fd2e5079 100644 --- a/administrator/components/com_fields/tmpl/fields/default.php +++ b/administrator/components/com_fields/tmpl/fields/default.php @@ -210,9 +210,8 @@ - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_fields/tmpl/fields/modal.php b/administrator/components/com_fields/tmpl/fields/modal.php index 717d6f07b9fd3..7a4e9794febcb 100644 --- a/administrator/components/com_fields/tmpl/fields/modal.php +++ b/administrator/components/com_fields/tmpl/fields/modal.php @@ -135,9 +135,6 @@ - - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_fields/tmpl/group/edit.php b/administrator/components/com_fields/tmpl/group/edit.php index a527ca814d36a..9190bf7d937a0 100644 --- a/administrator/components/com_fields/tmpl/group/edit.php +++ b/administrator/components/com_fields/tmpl/group/edit.php @@ -78,7 +78,7 @@ form->getInput('context'); ?> - - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_fields/tmpl/groups/default.php b/administrator/components/com_fields/tmpl/groups/default.php index d72ad1d5cb4c9..6ead0edaf2600 100644 --- a/administrator/components/com_fields/tmpl/groups/default.php +++ b/administrator/components/com_fields/tmpl/groups/default.php @@ -178,9 +178,8 @@ - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_finder/helpers/indexer/adapter.php b/administrator/components/com_finder/helpers/indexer/adapter.php deleted file mode 100644 index 0c4f653b6aae0..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/adapter.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -\defined('_JEXEC') or die; - -/** - * Finder Indexer Adapter class. - * - * @since 2.5 - * - * @deprecated 4.3 will be removed in 6.0 - * Use \Joomla\Component\Finder\Administrator\Indexer\Adapter instead - */ diff --git a/administrator/components/com_finder/helpers/indexer/helper.php b/administrator/components/com_finder/helpers/indexer/helper.php deleted file mode 100644 index 155fb6e74b641..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/helper.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -\defined('_JEXEC') or die; - -/** - * Finder Indexer Helper class. - * - * @since 2.5 - * - * @deprecated 4.3 will be removed in 6.0 - * Use \Joomla\Component\Finder\Administrator\Indexer\Helper instead - */ diff --git a/administrator/components/com_finder/helpers/indexer/parser.php b/administrator/components/com_finder/helpers/indexer/parser.php deleted file mode 100644 index 79465a956d971..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/parser.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -\defined('_JEXEC') or die; - -/** - * Finder Indexer Parser class. - * - * @since 2.5 - * - * @deprecated 4.3 will be removed in 6.0 - * 5.0 Use \Joomla\Component\Finder\Administrator\Indexer\Parser instead - */ diff --git a/administrator/components/com_finder/helpers/indexer/query.php b/administrator/components/com_finder/helpers/indexer/query.php deleted file mode 100644 index a1bec5b312162..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/query.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -\defined('_JEXEC') or die; - -/** - * Finder Indexer Query class. - * - * @since 2.5 - * - * @deprecated 4.3 will be removed in 6.0 - * Use \Joomla\Component\Finder\Administrator\Indexer\Query instead - */ diff --git a/administrator/components/com_finder/helpers/indexer/result.php b/administrator/components/com_finder/helpers/indexer/result.php deleted file mode 100644 index 70c3ded2ab226..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/result.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -\defined('_JEXEC') or die; - -/** - * Finder Indexer Result class. - * - * @since 2.5 - * - * @deprecated 4.3 will be removed in 6.0 - * Use \Joomla\Component\Finder\Administrator\Indexer\Result instead - */ diff --git a/administrator/components/com_finder/helpers/indexer/taxonomy.php b/administrator/components/com_finder/helpers/indexer/taxonomy.php deleted file mode 100644 index e539e7f7d4391..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/taxonomy.php +++ /dev/null @@ -1,19 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -\defined('_JEXEC') or die; - -/** - * Finder Indexer Taxonomy class. - * - * @since 2.5 - * @deprecated 4.3 will be removed in 6.0 - * Use \Joomla\Component\Finder\Administrator\Indexer\Taxonomy instead - */ diff --git a/administrator/components/com_finder/helpers/indexer/token.php b/administrator/components/com_finder/helpers/indexer/token.php deleted file mode 100644 index 1d24a63a58562..0000000000000 --- a/administrator/components/com_finder/helpers/indexer/token.php +++ /dev/null @@ -1,20 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -\defined('_JEXEC') or die; - -/** - * Finder Indexer Token class. - * - * @since 2.5 - * - * @deprecated 4.3 will be removed in 6.0 - * Use \Joomla\Component\Finder\Administrator\Indexer\Token instead - */ diff --git a/administrator/components/com_finder/helpers/language.php b/administrator/components/com_finder/helpers/language.php index e66f1caa9f7ac..07f8342eb2334 100644 --- a/administrator/components/com_finder/helpers/language.php +++ b/administrator/components/com_finder/helpers/language.php @@ -21,7 +21,7 @@ * * @since 2.5 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Finder\Administrator\Helper\LanguageHelper instead */ class FinderHelperLanguage extends LanguageHelper diff --git a/administrator/components/com_finder/src/Controller/IndexerController.php b/administrator/components/com_finder/src/Controller/IndexerController.php index f1012745ce234..4291c4924ef4e 100644 --- a/administrator/components/com_finder/src/Controller/IndexerController.php +++ b/administrator/components/com_finder/src/Controller/IndexerController.php @@ -57,7 +57,6 @@ public function start() $dispatcher = $this->getDispatcher(); if ($params->get('enable_logging', '0')) { - $options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}'; $options['text_file'] = 'indexer.php'; Log::addLogger($options); } @@ -129,7 +128,6 @@ public function batch() $dispatcher = $this->getDispatcher(); if ($params->get('enable_logging', '0')) { - $options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}'; $options['text_file'] = 'indexer.php'; Log::addLogger($options); } @@ -284,7 +282,6 @@ public static function sendResponse($data = null) $params = ComponentHelper::getParams('com_finder'); if ($params->get('enable_logging', '0')) { - $options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}'; $options['text_file'] = 'indexer.php'; Log::addLogger($options); } diff --git a/administrator/components/com_finder/src/Field/ContentmapField.php b/administrator/components/com_finder/src/Field/ContentmapField.php index ea005dc8e581d..d38fc8cb48cf2 100644 --- a/administrator/components/com_finder/src/Field/ContentmapField.php +++ b/administrator/components/com_finder/src/Field/ContentmapField.php @@ -50,7 +50,7 @@ protected function getGroups() $db = $this->getDatabase(); // Main query. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('a.title', 'text')) ->select($db->quoteName('a.id', 'value')) ->select($db->quoteName('a.parent_id')) diff --git a/administrator/components/com_finder/src/Field/ContenttypesField.php b/administrator/components/com_finder/src/Field/ContenttypesField.php index 45d78df38e5be..5e0eedc3afce7 100644 --- a/administrator/components/com_finder/src/Field/ContenttypesField.php +++ b/administrator/components/com_finder/src/Field/ContenttypesField.php @@ -49,7 +49,7 @@ public function getOptions() $options = []; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id', 'value')) ->select($db->quoteName('title', 'text')) ->from($db->quoteName('#__finder_types')); diff --git a/administrator/components/com_finder/src/Field/SearchfilterField.php b/administrator/components/com_finder/src/Field/SearchfilterField.php index 7925b42e01ab9..e22ec7ddf9b47 100644 --- a/administrator/components/com_finder/src/Field/SearchfilterField.php +++ b/administrator/components/com_finder/src/Field/SearchfilterField.php @@ -44,7 +44,7 @@ public function getOptions() { // Build the query. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('f.title AS text, f.filter_id AS value') ->from($db->quoteName('#__finder_filters') . ' AS f') ->where('f.state = 1') diff --git a/administrator/components/com_finder/src/Indexer/Adapter.php b/administrator/components/com_finder/src/Indexer/Adapter.php index 0f25a148d22d7..48de309632dc5 100644 --- a/administrator/components/com_finder/src/Indexer/Adapter.php +++ b/administrator/components/com_finder/src/Indexer/Adapter.php @@ -292,8 +292,8 @@ public function onFinderGarbageCollection() $db = $this->db; $type_id = $this->getTypeId(); - $query = $db->getQuery(true); - $subquery = $db->getQuery(true); + $query = $db->createQuery(); + $subquery = $db->createQuery(); $subquery->select('CONCAT(' . $db->quote($this->getUrl('', $this->extension, $this->layout)) . ', id)') ->from($db->quoteName($this->table)); $query->select($db->quoteName('l.link_id')) @@ -336,7 +336,7 @@ protected function change($id, $property, $value) $item = $this->db->quote($this->getUrl($id, $this->extension, $this->layout)); // Update the content items. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->update($this->db->quoteName('#__finder_links')) ->set($this->db->quoteName($property) . ' = ' . (int) $value) ->where($this->db->quoteName('url') . ' = ' . $item); @@ -399,7 +399,7 @@ protected function remove($id, $removeTaxonomies = true) $url = $this->db->quote($this->getUrl($id, $this->extension, $this->layout)); // Get the link ids for the content items. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('link_id')) ->from($this->db->quoteName('#__finder_links')) ->where($this->db->quoteName('url') . ' = ' . $url); @@ -506,7 +506,7 @@ protected function categoryStateChange($pks, $value) */ protected function checkCategoryAccess($row) { - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('access')) ->from($this->db->quoteName('#__categories')) ->where($this->db->quoteName('id') . ' = ' . (int) $row->id); @@ -527,7 +527,7 @@ protected function checkCategoryAccess($row) */ protected function checkItemAccess($row) { - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('access')) ->from($this->db->quoteName($this->table)) ->where($this->db->quoteName('id') . ' = ' . (int) $row->id); @@ -649,7 +649,7 @@ protected function getItems($offset, $limit, $query = null) protected function getListQuery($query = null) { // Check if we can use the supplied SQL query. - return $query instanceof QueryInterface ? $query : $this->db->getQuery(true); + return $query instanceof QueryInterface ? $query : $this->db->createQuery(); } /** @@ -664,7 +664,7 @@ protected function getListQuery($query = null) protected function getPluginType($id) { // Prepare the query - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('element')) ->from($this->db->quoteName('#__extensions')) ->where($this->db->quoteName('folder') . ' = ' . $this->db->quote('finder')) @@ -684,7 +684,7 @@ protected function getPluginType($id) */ protected function getStateQuery() { - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); // Item ID $query->select('a.id'); @@ -712,7 +712,7 @@ protected function getStateQuery() protected function getUpdateQueryByTime($time) { // Build an SQL query based on the modified time. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->where('a.modified >= ' . $this->db->quote($time)); return $query; @@ -730,7 +730,7 @@ protected function getUpdateQueryByTime($time) protected function getUpdateQueryByIds($ids) { // Build an SQL query based on the item ids. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->where('a.id IN(' . implode(',', $ids) . ')'); return $query; @@ -747,7 +747,7 @@ protected function getUpdateQueryByIds($ids) protected function getTypeId() { // Get the type id from the database. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('id')) ->from($this->db->quoteName('#__finder_types')) ->where($this->db->quoteName('title') . ' = ' . $this->db->quote($this->type_title)); @@ -793,7 +793,7 @@ protected function getItemMenuTitle($url) $groups = implode(',', $user->getAuthorisedViewLevels()); // Build a query to get the menu params. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('params')) ->from($this->db->quoteName('#__menu')) ->where($this->db->quoteName('link') . ' = ' . $this->db->quote($url)) diff --git a/administrator/components/com_finder/src/Indexer/DebugAdapter.php b/administrator/components/com_finder/src/Indexer/DebugAdapter.php index 419a7607f7447..4bdb474ae2d57 100644 --- a/administrator/components/com_finder/src/Indexer/DebugAdapter.php +++ b/administrator/components/com_finder/src/Indexer/DebugAdapter.php @@ -291,8 +291,8 @@ public function onFinderGarbageCollection() $db = $this->db; $type_id = $this->getTypeId(); - $query = $db->getQuery(true); - $subquery = $db->getQuery(true); + $query = $db->createQuery(); + $subquery = $db->createQuery(); $subquery->select('CONCAT(' . $db->quote($this->getUrl('', $this->extension, $this->layout)) . ', id)') ->from($db->quoteName($this->table)); $query->select($db->quoteName('l.link_id')) @@ -335,7 +335,7 @@ protected function change($id, $property, $value) $item = $this->db->quote($this->getUrl($id, $this->extension, $this->layout)); // Update the content items. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->update($this->db->quoteName('#__finder_links')) ->set($this->db->quoteName($property) . ' = ' . (int) $value) ->where($this->db->quoteName('url') . ' = ' . $item); @@ -401,7 +401,7 @@ protected function remove($id, $removeTaxonomies = true) $url = $this->db->quote($this->getUrl($id, $this->extension, $this->layout)); // Get the link ids for the content items. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('link_id')) ->from($this->db->quoteName('#__finder_links')) ->where($this->db->quoteName('url') . ' = ' . $url); @@ -508,7 +508,7 @@ protected function categoryStateChange($pks, $value) */ protected function checkCategoryAccess($row) { - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('access')) ->from($this->db->quoteName('#__categories')) ->where($this->db->quoteName('id') . ' = ' . (int) $row->id); @@ -529,7 +529,7 @@ protected function checkCategoryAccess($row) */ protected function checkItemAccess($row) { - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('access')) ->from($this->db->quoteName($this->table)) ->where($this->db->quoteName('id') . ' = ' . (int) $row->id); @@ -655,7 +655,7 @@ protected function getItems($offset, $limit, $query = null) protected function getListQuery($query = null) { // Check if we can use the supplied SQL query. - return $query instanceof QueryInterface ? $query : $this->db->getQuery(true); + return $query instanceof QueryInterface ? $query : $this->db->createQuery(); } /** @@ -670,7 +670,7 @@ protected function getListQuery($query = null) protected function getPluginType($id) { // Prepare the query - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('element')) ->from($this->db->quoteName('#__extensions')) ->where($this->db->quoteName('extension_id') . ' = ' . (int) $id); @@ -689,7 +689,7 @@ protected function getPluginType($id) */ protected function getStateQuery() { - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); // Item ID $query->select('a.id'); @@ -717,7 +717,7 @@ protected function getStateQuery() protected function getUpdateQueryByTime($time) { // Build an SQL query based on the modified time. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->where('a.modified >= ' . $this->db->quote($time)); return $query; @@ -735,7 +735,7 @@ protected function getUpdateQueryByTime($time) protected function getUpdateQueryByIds($ids) { // Build an SQL query based on the item ids. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->where('a.id IN(' . implode(',', $ids) . ')'); return $query; @@ -752,7 +752,7 @@ protected function getUpdateQueryByIds($ids) protected function getTypeId() { // Get the type id from the database. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('id')) ->from($this->db->quoteName('#__finder_types')) ->where($this->db->quoteName('title') . ' = ' . $this->db->quote($this->type_title)); @@ -798,7 +798,7 @@ protected function getItemMenuTitle($url) $groups = implode(',', $user->getAuthorisedViewLevels()); // Build a query to get the menu params. - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('params')) ->from($this->db->quoteName('#__menu')) ->where($this->db->quoteName('link') . ' = ' . $this->db->quote($url)) diff --git a/administrator/components/com_finder/src/Indexer/Helper.php b/administrator/components/com_finder/src/Indexer/Helper.php index b57cdbdb83de8..7e36e43bc6146 100644 --- a/administrator/components/com_finder/src/Indexer/Helper.php +++ b/administrator/components/com_finder/src/Indexer/Helper.php @@ -11,12 +11,14 @@ namespace Joomla\Component\Finder\Administrator\Indexer; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Content\ContentPrepareEvent; use Joomla\CMS\Event\Finder\PrepareContentEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Plugin\PluginHelper; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Content; use Joomla\Component\Fields\Administrator\Helper\FieldsHelper; +use Joomla\Event\DispatcherInterface; use Joomla\Registry\Registry; use Joomla\String\StringHelper; @@ -228,7 +230,7 @@ public static function addContentType($title, $mime = null) static $types; $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Check if the types are loaded. if (empty($types)) { @@ -321,7 +323,7 @@ public static function getCommonWords($lang) $db = Factory::getDbo(); // Create the query to load all the common terms for the language. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('term')) ->from($db->quoteName('#__finder_terms_common')) ->where($db->quoteName('language') . ' = ' . $db->quote($lang)); @@ -472,7 +474,7 @@ public static function prepareContent($text, $params = null, ?Result $item = nul } // Create a mock content object. - $content = Table::getInstance('Content'); + $content = new Content(Factory::getDbo()); $content->text = $text; if ($item) { @@ -485,7 +487,17 @@ public static function prepareContent($text, $params = null, ?Result $item = nul } // Fire the onContentPrepare event. - Factory::getApplication()->triggerEvent('onContentPrepare', ['com_finder.indexer', &$content, &$params, 0]); + Factory::getContainer() + ->get(DispatcherInterface::class) + ->dispatch( + 'onContentPrepare', + new ContentPrepareEvent('onContentPrepare', [ + 'context' => 'com_finder.indexer', + 'subject' => $content, + 'params' => $params, + 'page' => 0, + ]) + ); return $content->text; } diff --git a/administrator/components/com_finder/src/Indexer/Indexer.php b/administrator/components/com_finder/src/Indexer/Indexer.php index b8a5ddc407ef4..5a8784255ea0d 100644 --- a/administrator/components/com_finder/src/Indexer/Indexer.php +++ b/administrator/components/com_finder/src/Indexer/Indexer.php @@ -12,7 +12,6 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Profiler\Profiler; use Joomla\Database\DatabaseInterface; @@ -83,7 +82,7 @@ class Indexer /** * The indexer state object. * - * @var CMSObject + * @var \stdClass * @since 2.5 */ public static $state; @@ -122,14 +121,14 @@ class Indexer public function __construct(?DatabaseInterface $db = null) { if ($db === null) { - @trigger_error('Database will be mandatory in 5.0.', E_USER_DEPRECATED); + @trigger_error('Database will be mandatory in 7.0.', E_USER_DEPRECATED); $db = Factory::getContainer()->get(DatabaseInterface::class); } $this->db = $db; // Set up query template for addTokensToDb - $this->addTokensToDbQueryTemplate = $db->getQuery(true)->insert($db->quoteName('#__finder_tokens')) + $this->addTokensToDbQueryTemplate = $db->createQuery()->insert($db->quoteName('#__finder_tokens')) ->columns( [ $db->quoteName('term'), @@ -146,7 +145,7 @@ public function __construct(?DatabaseInterface $db = null) /** * Method to get the indexer state. * - * @return CMSObject The indexer state object. + * @return \stdClass The indexer state object. * * @since 2.5 */ @@ -158,12 +157,12 @@ public static function getState() } // If we couldn't load from the internal state, try the session. - $session = Factory::getSession(); + $session = Factory::getApplication()->getSession(); $data = $session->get('_finder.state', null); // If the state is empty, load the values for the first time. if (empty($data)) { - $data = new CMSObject(); + $data = new \stdClass(); $data->force = false; // Load the default configuration options. @@ -228,7 +227,7 @@ public static function getState() /** * Method to set the indexer state. * - * @param CMSObject $data A new indexer state object. + * @param \stdClass $data A new indexer state object. * * @return boolean True on success, false on failure. * @@ -237,7 +236,7 @@ public static function getState() public static function setState($data) { // Check the state object. - if (empty($data) || !$data instanceof CMSObject) { + if (empty($data) || !$data instanceof \stdClass) { return false; } @@ -245,7 +244,7 @@ public static function setState($data) static::$state = $data; // Set the new session state. - Factory::getSession()->set('_finder.state', $data); + Factory::getApplication()->getSession()->set('_finder.state', $data); return true; } @@ -263,7 +262,7 @@ public static function resetState() self::$state = null; // Reset the session state to null. - Factory::getSession()->set('_finder.state', null); + Factory::getApplication()->getSession()->set('_finder.state', null); } /** @@ -285,7 +284,7 @@ public function index($item, $format = 'html') $serverType = strtolower($db->getServerType()); // Check if the item is in the database. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('link_id') . ', ' . $db->quoteName('md5sum')) ->from($db->quoteName('#__finder_links')) ->where($db->quoteName('url') . ' = ' . $db->quote($item->url)); @@ -541,7 +540,7 @@ public function index($item, $format = 'html') * so we need to go back and update the aggregate table with all the * new term ids. */ - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__finder_tokens_aggregate', 'ta')) ->innerJoin($db->quoteName('#__finder_terms', 't'), 't.term = ta.term AND t.language = ta.language') ->where('ta.term_id = 0'); @@ -651,7 +650,7 @@ public function index($item, $format = 'html') public function remove($linkId, $removeTaxonomies = true) { $db = $this->db; - $query = $db->getQuery(true); + $query = $db->createQuery(); $linkId = (int) $linkId; // Update the link counts for the terms. @@ -713,25 +712,25 @@ public function optimize() $serverType = strtolower($db->getServerType()); // Delete all broken links. (Links missing the object) - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete('#__finder_links') ->where($db->quoteName('object') . ' = ' . $db->quote('')); $db->setQuery($query); $db->execute(); // Delete all orphaned mappings of terms to links - $query2 = $db->getQuery(true) + $query2 = $db->createQuery() ->select($db->quoteName('link_id')) ->from($db->quoteName('#__finder_links')); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__finder_links_terms')) ->where($db->quoteName('link_id') . ' NOT IN (' . $query2 . ')'); $db->setQuery($query); $db->execute(); // Update count of links in terms table - $query = $db->getQuery(true); - $query2 = $db->getQuery(true); + $query = $db->createQuery(); + $query2 = $db->createQuery(); $query2->select('COUNT(lt.link_id)') ->from($db->quoteName('#__finder_links_terms', 'lt')) ->where($db->quoteName('lt.term_id') . ' = ' . $db->quoteName('t.term_id')); @@ -741,7 +740,7 @@ public function optimize() $db->execute(); // Delete all orphaned terms. - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete($db->quoteName('#__finder_terms')) ->where($db->quoteName('links') . ' <= 0'); $db->setQuery($query); @@ -749,10 +748,10 @@ public function optimize() // Delete all orphaned terms - $query2 = $db->getQuery(true) + $query2 = $db->createQuery() ->select($db->quoteName('term_id')) ->from($db->quoteName('#__finder_links_terms')); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__finder_terms')) ->where($db->quoteName('term_id') . ' NOT IN (' . $query2 . ')'); $db->setQuery($query); diff --git a/administrator/components/com_finder/src/Indexer/Query.php b/administrator/components/com_finder/src/Indexer/Query.php index abcc2154a2f9b..405adc3fbca59 100644 --- a/administrator/components/com_finder/src/Indexer/Query.php +++ b/administrator/components/com_finder/src/Indexer/Query.php @@ -208,7 +208,7 @@ class Query public function __construct($options, ?DatabaseInterface $db = null) { if ($db === null) { - @trigger_error('Database will be mandatory in 5.0.', E_USER_DEPRECATED); + @trigger_error('Database will be mandatory in 7.0.', E_USER_DEPRECATED); $db = Factory::getContainer()->get(DatabaseInterface::class); } @@ -505,7 +505,7 @@ protected function processStaticTaxonomy($filterId) $groups = implode(',', Factory::getUser()->getAuthorisedViewLevels()); // Load the predefined filter. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('f.data, f.params') ->from($db->quoteName('#__finder_filters') . ' AS f') ->where('f.filter_id = ' . (int) $filterId); @@ -609,7 +609,7 @@ protected function processDynamicTaxonomy($filters) // Get the database object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); /* * Create the query to get filters from the database. We do this for @@ -1260,7 +1260,7 @@ protected function getTokenData($token) $db = $this->getDatabase(); // Create a database query to build match the token. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('t.term, t.term_id') ->from('#__finder_terms AS t'); diff --git a/administrator/components/com_finder/src/Indexer/Taxonomy.php b/administrator/components/com_finder/src/Indexer/Taxonomy.php index 28414eeef34bc..5091a21b92d4a 100644 --- a/administrator/components/com_finder/src/Indexer/Taxonomy.php +++ b/administrator/components/com_finder/src/Indexer/Taxonomy.php @@ -174,7 +174,7 @@ protected static function storeNode($node, $parentId) // Check to see if the node is in the table. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__finder_taxonomy')) ->where($db->quoteName('parent_id') . ' = ' . $db->quote($parentId)) @@ -277,7 +277,7 @@ public static function addMap($linkId, $nodeId) // Insert the map. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('link_id')) ->from($db->quoteName('#__finder_taxonomy_map')) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId) @@ -315,7 +315,7 @@ public static function getBranchTitles() $groups = implode(',', Factory::getUser()->getAuthorisedViewLevels()); // Create a query to get the taxonomy branch titles. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__finder_taxonomy')) ->where($db->quoteName('parent_id') . ' = 1') @@ -350,7 +350,7 @@ public static function getNodeByTitle($branch, $title) $groups = implode(',', Factory::getUser()->getAuthorisedViewLevels()); // Create a query to get the node. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('t1.*') ->from($db->quoteName('#__finder_taxonomy') . ' AS t1') ->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS t2 ON t2.id = t1.parent_id') @@ -382,7 +382,7 @@ public static function removeMaps($linkId) { // Delete the maps. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__finder_taxonomy_map')) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); $db->setQuery($query); @@ -403,10 +403,10 @@ public static function removeOrphanMaps() { // Delete all orphaned maps $db = Factory::getDbo(); - $query2 = $db->getQuery(true) + $query2 = $db->createQuery() ->select($db->quoteName('link_id')) ->from($db->quoteName('#__finder_links')); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__finder_taxonomy_map')) ->where($db->quoteName('link_id') . ' NOT IN (' . $query2 . ')'); $db->setQuery($query); @@ -430,8 +430,8 @@ public static function removeOrphanNodes() $affectedRows = 0; $db = Factory::getDbo(); $nodeTable = new MapTable($db); - $query = $db->getQuery(true); - $query2 = $db->getQuery(true); + $query = $db->createQuery(); + $query2 = $db->createQuery(); $query->select($db->quoteName('t.id')) ->from($db->quoteName('#__finder_taxonomy', 't')) @@ -473,7 +473,7 @@ public static function getTaxonomy($id = 0) { if (!\count(self::$taxonomies)) { $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select(['id','parent_id','lft','rgt','level','path','title','alias','state','access','language']) ->from($db->quoteName('#__finder_taxonomy')) diff --git a/administrator/components/com_finder/src/Model/FilterModel.php b/administrator/components/com_finder/src/Model/FilterModel.php index f785e07312386..1e0b84e0d7f21 100644 --- a/administrator/components/com_finder/src/Model/FilterModel.php +++ b/administrator/components/com_finder/src/Model/FilterModel.php @@ -45,15 +45,13 @@ class FilterModel extends AdminModel /** * Custom clean cache method. * - * @param string $group The component name. [optional] - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group The component name. [optional] * * @return void * * @since 2.5 */ - protected function cleanCache($group = 'com_finder', $clientId = 0) + protected function cleanCache($group = 'com_finder') { parent::cleanCache($group); } @@ -98,20 +96,14 @@ public function getFilter() * @param array $data Data for the form. [optional] * @param boolean $loadData True if the form is to load its own data (default case), false if not. [optional] * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 2.5 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_finder.filter', 'filter', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_finder.filter', 'filter', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -145,7 +137,7 @@ protected function loadFormData() public function getTotal() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('MAX(link_id)') ->from('#__finder_links'); diff --git a/administrator/components/com_finder/src/Model/FiltersModel.php b/administrator/components/com_finder/src/Model/FiltersModel.php index ec05f535ba67e..23d98fbf8a932 100644 --- a/administrator/components/com_finder/src/Model/FiltersModel.php +++ b/administrator/components/com_finder/src/Model/FiltersModel.php @@ -61,7 +61,7 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) protected function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select all fields from the table. $query->select('a.*') diff --git a/administrator/components/com_finder/src/Model/IndexModel.php b/administrator/components/com_finder/src/Model/IndexModel.php index b8cb0f99e005c..e2a903b861b7d 100644 --- a/administrator/components/com_finder/src/Model/IndexModel.php +++ b/administrator/components/com_finder/src/Model/IndexModel.php @@ -11,6 +11,9 @@ namespace Joomla\Component\Finder\Administrator\Model; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Model\AfterChangeStateEvent; +use Joomla\CMS\Event\Model\AfterDeleteEvent; +use Joomla\CMS\Event\Model\BeforeDeleteEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; @@ -123,7 +126,8 @@ public function delete(&$pks) $table = $this->getTable(); // Include the content plugins for the on delete events. - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Iterate the items to delete each one. foreach ($pks as $i => $pk) { @@ -132,7 +136,13 @@ public function delete(&$pks) $context = $this->option . '.' . $this->name; // Trigger the onContentBeforeDelete event. - $result = Factory::getApplication()->triggerEvent($this->event_before_delete, [$context, $table]); + $result = $dispatcher->dispatch( + $this->event_before_delete, + new BeforeDeleteEvent($this->event_before_delete, [ + 'context' => $context, + 'subject' => $table, + ]) + )->getArgument('result', []); if (\in_array(false, $result, true)) { $this->setError($table->getError()); @@ -147,7 +157,13 @@ public function delete(&$pks) } // Trigger the onContentAfterDelete event. - Factory::getApplication()->triggerEvent($this->event_after_delete, [$context, $table]); + $dispatcher->dispatch( + $this->event_after_delete, + new AfterDeleteEvent($this->event_after_delete, [ + 'context' => $context, + 'subject' => $table, + ]) + ); } else { // Prune items that you can't change. unset($pks[$i]); @@ -182,7 +198,7 @@ public function delete(&$pks) protected function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('l.*') ->select($db->quoteName('t.title', 't_title')) ->from($db->quoteName('#__finder_links', 'l')) @@ -259,7 +275,7 @@ protected function getListQuery() public function getPluginState() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('name, enabled') ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) @@ -304,7 +320,7 @@ protected function getStoreId($id = '') public function getTotalIndexed() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(link_id)') ->from($db->quoteName('#__finder_links')); $db->setQuery($query); @@ -419,7 +435,8 @@ public function publish(&$pks, $value = 1) $pks = (array) $pks; // Include the content plugins for the change of state event. - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Access checks. foreach ($pks as $i => $pk) { @@ -444,7 +461,14 @@ public function publish(&$pks, $value = 1) $context = $this->option . '.' . $this->name; // Trigger the onContentChangeState event. - $result = Factory::getApplication()->triggerEvent('onContentChangeState', [$context, $pks, $value]); + $result = $dispatcher->dispatch( + 'onContentChangeState', + new AfterChangeStateEvent('onContentChangeState', [ + 'context' => $context, + 'subject' => $pks, + 'value' => $value, + ]) + )->getArgument('result', []); if (\in_array(false, $result, true)) { $this->setError($table->getError()); diff --git a/administrator/components/com_finder/src/Model/IndexerModel.php b/administrator/components/com_finder/src/Model/IndexerModel.php index cdef667e77c08..4319a660ab417 100644 --- a/administrator/components/com_finder/src/Model/IndexerModel.php +++ b/administrator/components/com_finder/src/Model/IndexerModel.php @@ -38,13 +38,6 @@ class IndexerModel extends FormModel */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_finder.indexer', 'indexer', ['control' => '', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_finder.indexer', 'indexer', ['control' => '', 'load_data' => $loadData]); } } diff --git a/administrator/components/com_finder/src/Model/ItemModel.php b/administrator/components/com_finder/src/Model/ItemModel.php index fdb9b268bc054..cdeaf3b1a44be 100644 --- a/administrator/components/com_finder/src/Model/ItemModel.php +++ b/administrator/components/com_finder/src/Model/ItemModel.php @@ -46,7 +46,7 @@ public function getItem() { $link_id = (int) $this->getState('item.link_id'); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__finder_links', 'l')) ->where($db->quoteName('l.link_id') . ' = :link_id') @@ -68,7 +68,7 @@ public function getTerms() { $link_id = (int) $this->getState('item.link_id'); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('t.*, l.*') ->from($db->quoteName('#__finder_links_terms', 'l')) ->leftJoin($db->quoteName('#__finder_terms', 't') . ' ON ' . $db->quoteName('t.term_id') . ' = ' . $db->quoteName('l.term_id')) @@ -92,7 +92,7 @@ public function getTaxonomies() { $link_id = (int) $this->getState('item.link_id'); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('t.*, m.*') ->from($db->quoteName('#__finder_taxonomy_map', 'm')) ->leftJoin($db->quoteName('#__finder_taxonomy', 't') . ' ON ' . $db->quoteName('t.id') . ' = ' . $db->quoteName('m.node_id')) diff --git a/administrator/components/com_finder/src/Model/MapsModel.php b/administrator/components/com_finder/src/Model/MapsModel.php index 98231c4d188bf..ce9842149a554 100644 --- a/administrator/components/com_finder/src/Model/MapsModel.php +++ b/administrator/components/com_finder/src/Model/MapsModel.php @@ -11,7 +11,9 @@ namespace Joomla\Component\Finder\Administrator\Model; use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Factory; +use Joomla\CMS\Event\Model\AfterChangeStateEvent; +use Joomla\CMS\Event\Model\AfterDeleteEvent; +use Joomla\CMS\Event\Model\BeforeDeleteEvent; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; @@ -98,7 +100,8 @@ public function delete(&$pks) $table = $this->getTable(); // Include the content plugins for the on delete events. - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Iterate the items to check if all of them exist. foreach ($pks as $i => $pk) { @@ -117,7 +120,13 @@ public function delete(&$pks) $context = $this->option . '.' . $this->name; // Trigger the onContentBeforeDelete event. - $result = Factory::getApplication()->triggerEvent('onContentBeforeDelete', [$context, $table]); + $result = $dispatcher->dispatch( + 'onContentBeforeDelete', + new BeforeDeleteEvent('onContentBeforeDelete', [ + 'context' => $context, + 'subject' => $table, + ]) + )->getArgument('result', []); if (\in_array(false, $result, true)) { $this->setError($table->getError()); @@ -132,7 +141,10 @@ public function delete(&$pks) } // Trigger the onContentAfterDelete event. - Factory::getApplication()->triggerEvent('onContentAfterDelete', [$context, $table]); + $dispatcher->dispatch('onContentAfterDelete', new AfterDeleteEvent('onContentAfterDelete', [ + 'context' => $context, + 'subject' => $table, + ])); } else { // Prune items that you can't change. unset($pks[$i]); @@ -165,7 +177,7 @@ protected function getListQuery() $db = $this->getDatabase(); // Select all fields from the table. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('a.id, a.parent_id, a.lft, a.rgt, a.level, a.path, a.title, a.alias, a.state, a.access, a.language') ->from($db->quoteName('#__finder_taxonomy', 'a')) ->where('a.parent_id != 0'); @@ -175,7 +187,7 @@ protected function getListQuery() ->leftJoin($db->quoteName('#__finder_taxonomy', 'b') . ' ON b.level = 1 AND b.lft <= a.lft AND a.rgt <= b.rgt'); // Join to get the map links. - $stateQuery = $db->getQuery(true) + $stateQuery = $db->createQuery() ->select('m.node_id') ->select('COUNT(NULLIF(l.published, 0)) AS count_published') ->select('COUNT(NULLIF(l.published, 1)) AS count_unpublished') @@ -314,7 +326,8 @@ public function publish(&$pks, $value = 1) $pks = (array) $pks; // Include the content plugins for the change of state event. - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Access checks. foreach ($pks as $i => $pk) { @@ -339,7 +352,14 @@ public function publish(&$pks, $value = 1) $context = $this->option . '.' . $this->name; // Trigger the onContentChangeState event. - $result = Factory::getApplication()->triggerEvent('onContentChangeState', [$context, $pks, $value]); + $result = $dispatcher->dispatch( + 'onContentChangeState', + new AfterChangeStateEvent('onContentChangeState', [ + 'context' => $context, + 'subject' => $pks, + 'value' => $value, + ]) + )->getArgument('result', []); if (\in_array(false, $result, true)) { $this->setError($table->getError()); @@ -363,7 +383,7 @@ public function publish(&$pks, $value = 1) public function purge() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__finder_taxonomy')) ->where($db->quoteName('parent_id') . ' > 1'); $db->setQuery($query); diff --git a/administrator/components/com_finder/src/Model/SearchesModel.php b/administrator/components/com_finder/src/Model/SearchesModel.php index 5cdff1385b1c2..6ae77a2022e39 100644 --- a/administrator/components/com_finder/src/Model/SearchesModel.php +++ b/administrator/components/com_finder/src/Model/SearchesModel.php @@ -105,7 +105,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_finder/src/Model/StatisticsModel.php b/administrator/components/com_finder/src/Model/StatisticsModel.php index 8845712b15b58..2d066e0cca76c 100644 --- a/administrator/components/com_finder/src/Model/StatisticsModel.php +++ b/administrator/components/com_finder/src/Model/StatisticsModel.php @@ -12,7 +12,6 @@ use Joomla\CMS\Factory; use Joomla\CMS\MVC\Model\BaseDatabaseModel; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; // phpcs:disable PSR1.Files.SideEffects @@ -29,7 +28,7 @@ class StatisticsModel extends BaseDatabaseModel /** * Method to get the component statistics * - * @return CMSObject The component statistics + * @return \stdClass The component statistics * * @since 2.5 */ @@ -37,8 +36,8 @@ public function getData() { // Initialise $db = $this->getDatabase(); - $query = $db->getQuery(true); - $data = new CMSObject(); + $query = $db->createQuery(); + $data = new \stdClass(); $query->select('COUNT(term_id)') ->from($db->quoteName('#__finder_terms')); diff --git a/administrator/components/com_finder/src/Response/Response.php b/administrator/components/com_finder/src/Response/Response.php index 39691a8520f84..5737670b40874 100644 --- a/administrator/components/com_finder/src/Response/Response.php +++ b/administrator/components/com_finder/src/Response/Response.php @@ -142,7 +142,6 @@ public function __construct($state) $params = ComponentHelper::getParams('com_finder'); if ($params->get('enable_logging', '0')) { - $options['format'] = '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}'; $options['text_file'] = 'indexer.php'; Log::addLogger($options); } diff --git a/administrator/components/com_finder/src/Service/HTML/Filter.php b/administrator/components/com_finder/src/Service/HTML/Filter.php index 7a0c7c8531cdb..3080879d91d13 100644 --- a/administrator/components/com_finder/src/Service/HTML/Filter.php +++ b/administrator/components/com_finder/src/Service/HTML/Filter.php @@ -47,7 +47,7 @@ class Filter public function slider($options = []) { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = Factory::getUser(); $groups = implode(',', $user->getAuthorisedViewLevels()); $html = ''; @@ -225,7 +225,7 @@ public function select($idxQuery, $options) $branches = $cache->get($cacheId); } else { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Load the predefined filter if specified. if (!empty($idxQuery->filter)) { diff --git a/administrator/components/com_finder/src/Service/HTML/Finder.php b/administrator/components/com_finder/src/Service/HTML/Finder.php index fa62a601879e0..fad16340e01f7 100644 --- a/administrator/components/com_finder/src/Service/HTML/Finder.php +++ b/administrator/components/com_finder/src/Service/HTML/Finder.php @@ -41,7 +41,7 @@ public function typeslist() { // Load the finder types. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT t.title AS text, t.id AS value') ->from($db->quoteName('#__finder_types') . ' AS t') ->join('LEFT', $db->quoteName('#__finder_links') . ' AS l ON l.type_id = t.id') @@ -78,7 +78,7 @@ public function mapslist() { // Load the finder types. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title', 'text')) ->select($db->quoteName('id', 'value')) ->from($db->quoteName('#__finder_taxonomy')) diff --git a/administrator/components/com_finder/src/View/Filter/HtmlView.php b/administrator/components/com_finder/src/View/Filter/HtmlView.php index dc0cbebf16502..08d9458b489cb 100644 --- a/administrator/components/com_finder/src/View/Filter/HtmlView.php +++ b/administrator/components/com_finder/src/View/Filter/HtmlView.php @@ -110,6 +110,11 @@ public function display($tpl = null) throw new GenericDataException(implode("\n", $errors), 500); } + // Add form control fields + $this->form + ->addControlField('task') + ->addControlField('return', Factory::getApplication()->getInput()->get('return', '', 'BASE64')); + // Configure the toolbar. $this->addToolbar(); diff --git a/administrator/components/com_finder/src/View/Filters/HtmlView.php b/administrator/components/com_finder/src/View/Filters/HtmlView.php index 555aec748934c..c1d040b1e334f 100644 --- a/administrator/components/com_finder/src/View/Filters/HtmlView.php +++ b/administrator/components/com_finder/src/View/Filters/HtmlView.php @@ -112,9 +112,10 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); - if (\count($this->items) === 0 && $this->isEmptyState = $model->getIsEmptyState()) { - $this->setLayout('emptystate'); - } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); // Configure the toolbar. $this->addToolbar(); diff --git a/administrator/components/com_finder/src/View/Index/HtmlView.php b/administrator/components/com_finder/src/View/Index/HtmlView.php index 5434f680f1152..431da29241a32 100644 --- a/administrator/components/com_finder/src/View/Index/HtmlView.php +++ b/administrator/components/com_finder/src/View/Index/HtmlView.php @@ -166,6 +166,11 @@ public function display($tpl = null) $this->finderPlugins = false; } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + // Configure the toolbar. $this->addToolbar(); diff --git a/administrator/components/com_finder/src/View/Maps/HtmlView.php b/administrator/components/com_finder/src/View/Maps/HtmlView.php index f9bc5d7be75bc..8b8af14c9fd9d 100644 --- a/administrator/components/com_finder/src/View/Maps/HtmlView.php +++ b/administrator/components/com_finder/src/View/Maps/HtmlView.php @@ -120,6 +120,11 @@ public function display($tpl = null) $this->setLayout('emptystate'); } + // Add form control fields + $this->filterForm + ->addControlField('task', 'display') + ->addControlField('boxchecked', '0'); + // Prepare the view. $this->addToolbar(); diff --git a/administrator/components/com_finder/src/View/Searches/HtmlView.php b/administrator/components/com_finder/src/View/Searches/HtmlView.php index f2af9b33c6d46..27d6c21313f4f 100644 --- a/administrator/components/com_finder/src/View/Searches/HtmlView.php +++ b/administrator/components/com_finder/src/View/Searches/HtmlView.php @@ -132,6 +132,11 @@ public function display($tpl = null) } } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + // Prepare the view. $this->addToolbar(); diff --git a/administrator/components/com_finder/src/View/Statistics/HtmlView.php b/administrator/components/com_finder/src/View/Statistics/HtmlView.php index c4fbcb5aad878..635f690058f19 100644 --- a/administrator/components/com_finder/src/View/Statistics/HtmlView.php +++ b/administrator/components/com_finder/src/View/Statistics/HtmlView.php @@ -27,7 +27,7 @@ class HtmlView extends BaseHtmlView /** * The index statistics * - * @var \Joomla\CMS\Object\CMSObject + * @var \stdClass * * @since 3.6.1 */ diff --git a/administrator/components/com_finder/tmpl/filter/edit.php b/administrator/components/com_finder/tmpl/filter/edit.php index 8d0f660cffe46..10c4e69139e60 100644 --- a/administrator/components/com_finder/tmpl/filter/edit.php +++ b/administrator/components/com_finder/tmpl/filter/edit.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; @@ -87,8 +86,6 @@ - - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_finder/tmpl/filters/default.php b/administrator/components/com_finder/tmpl/filters/default.php index a75c842ed8ec5..88e5acbbc7bdb 100644 --- a/administrator/components/com_finder/tmpl/filters/default.php +++ b/administrator/components/com_finder/tmpl/filters/default.php @@ -124,9 +124,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_finder/tmpl/filters/emptystate.php b/administrator/components/com_finder/tmpl/filters/emptystate.php index 416a26b972689..a4597ea2e1fe3 100644 --- a/administrator/components/com_finder/tmpl/filters/emptystate.php +++ b/administrator/components/com_finder/tmpl/filters/emptystate.php @@ -18,11 +18,13 @@ $displayData = [ 'textPrefix' => 'COM_FINDER', 'formURL' => 'index.php?option=com_finder&view=filters', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Smart_Search_quickstart_guide', + 'helpURL' => 'https://guide.joomla.org/user-manual/smart-search/smart-search-smart-search-quickstart-guide', 'icon' => 'icon-search-plus finder', 'btnadd' => Text::_('COM_FINDER_FILTERS_EMPTYSTATE_BUTTON_ADD'), 'content' => Text::_('COM_FINDER_FILTERS_EMPTYSTATE_CONTENT'), 'title' => Text::_('COM_FINDER_FILTERS_TOOLBAR_TITLE'), + + 'controlFields' => $this->filterForm->renderControlFields(), ]; if ($this->getCurrentUser()->authorise('core.create', 'com_finder')) { diff --git a/administrator/components/com_finder/tmpl/index/default.php b/administrator/components/com_finder/tmpl/index/default.php index da5fe365c863c..10065d9d8ed3c 100644 --- a/administrator/components/com_finder/tmpl/index/default.php +++ b/administrator/components/com_finder/tmpl/index/default.php @@ -169,9 +169,7 @@ pagination->getListFooter(); ?> - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_finder/tmpl/index/emptystate.php b/administrator/components/com_finder/tmpl/index/emptystate.php index 10a2395144ea6..694932c5cc6b7 100644 --- a/administrator/components/com_finder/tmpl/index/emptystate.php +++ b/administrator/components/com_finder/tmpl/index/emptystate.php @@ -21,11 +21,13 @@ $displayData = [ 'textPrefix' => 'COM_FINDER', 'formURL' => 'index.php?option=com_finder&view=index', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Smart_Search_quickstart_guide', + 'helpURL' => 'https://guide.joomla.org/user-manual/smart-search/smart-search-smart-search-quickstart-guides', 'icon' => 'icon-search-plus finder', 'content' => Text::_('COM_FINDER_INDEX_NO_DATA') . '
' . Text::_('COM_FINDER_INDEX_TIP'), 'title' => Text::_('COM_FINDER_HEADING_INDEXER'), 'createURL' => "javascript:document.getElementsByClassName('button-index')[0].click();", + + 'controlFields' => $this->filterForm->renderControlFields(), ]; echo LayoutHelper::render('joomla.content.emptystate', $displayData); diff --git a/administrator/components/com_finder/tmpl/indexer/debug.php b/administrator/components/com_finder/tmpl/indexer/debug.php index 2cfad37dd97ba..d948819afca00 100644 --- a/administrator/components/com_finder/tmpl/indexer/debug.php +++ b/administrator/components/com_finder/tmpl/indexer/debug.php @@ -10,7 +10,7 @@ defined('_JEXEC') or die; -use Joomla\CMS\Factory; +use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -37,7 +37,7 @@ form->renderField('plugin'); ?> form->renderField('id'); ?> - + 'finder-indexer-token']); ?> diff --git a/administrator/components/com_finder/tmpl/indexer/default.php b/administrator/components/com_finder/tmpl/indexer/default.php index db3ca5a37d173..6e16d033ca958 100644 --- a/administrator/components/com_finder/tmpl/indexer/default.php +++ b/administrator/components/com_finder/tmpl/indexer/default.php @@ -10,7 +10,7 @@ defined('_JEXEC') or die; -use Joomla\CMS\Factory; +use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; /** @var \Joomla\Component\Finder\Administrator\View\Indexer\HtmlView $this */ @@ -39,5 +39,5 @@
- + 'finder-indexer-token']); ?> diff --git a/administrator/components/com_finder/tmpl/maps/default.php b/administrator/components/com_finder/tmpl/maps/default.php index 2b9ca870ffecc..1e14cc6b72653 100644 --- a/administrator/components/com_finder/tmpl/maps/default.php +++ b/administrator/components/com_finder/tmpl/maps/default.php @@ -168,9 +168,7 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_finder/tmpl/maps/emptystate.php b/administrator/components/com_finder/tmpl/maps/emptystate.php index 00bb16722d867..a7337a0766db4 100644 --- a/administrator/components/com_finder/tmpl/maps/emptystate.php +++ b/administrator/components/com_finder/tmpl/maps/emptystate.php @@ -18,7 +18,9 @@ 'formURL' => 'index.php?option=com_finder&view=maps', 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Smart_Search:_Content_Maps', 'icon' => 'icon-search-plus finder', - 'title' => Text::_('COM_FINDER_MAPS_TOOLBAR_TITLE') + 'title' => Text::_('COM_FINDER_MAPS_TOOLBAR_TITLE'), + + 'controlFields' => $this->filterForm->renderControlFields(), ]; echo LayoutHelper::render('joomla.content.emptystate', $displayData); diff --git a/administrator/components/com_finder/tmpl/searches/default.php b/administrator/components/com_finder/tmpl/searches/default.php index e6cf3b29731e4..d892b3163ecb9 100644 --- a/administrator/components/com_finder/tmpl/searches/default.php +++ b/administrator/components/com_finder/tmpl/searches/default.php @@ -76,9 +76,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_finder/tmpl/searches/emptystate.php b/administrator/components/com_finder/tmpl/searches/emptystate.php index 31d49307f0a37..3534093a67c53 100644 --- a/administrator/components/com_finder/tmpl/searches/emptystate.php +++ b/administrator/components/com_finder/tmpl/searches/emptystate.php @@ -20,6 +20,8 @@ 'icon' => 'icon-search', 'title' => Text::_('COM_FINDER_MANAGER_SEARCHES'), 'content' => Text::_('COM_FINDER_EMPTYSTATE_SEARCHES_CONTENT'), + + 'controlFields' => $this->filterForm->renderControlFields(), ]; echo LayoutHelper::render('joomla.content.emptystate', $displayData); diff --git a/administrator/components/com_guidedtours/src/Model/StepModel.php b/administrator/components/com_guidedtours/src/Model/StepModel.php index e78e4a221ef0b..4bbba92039c66 100644 --- a/administrator/components/com_guidedtours/src/Model/StepModel.php +++ b/administrator/components/com_guidedtours/src/Model/StepModel.php @@ -11,6 +11,7 @@ namespace Joomla\Component\Guidedtours\Administrator\Model; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Table\Table; @@ -129,7 +130,7 @@ protected function prepareTable($table) // Set ordering to the last item if not set if (empty($table->ordering)) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('MAX(ordering)') ->from($db->quoteName('#__guidedtour_steps')); $db->setQuery($query); @@ -167,9 +168,10 @@ public function getTable($type = 'Step', $prefix = 'Administrator', $config = [] * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \JForm|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 4.3.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -183,10 +185,6 @@ public function getForm($data = [], $loadData = true) ] ); - if (empty($form)) { - return false; - } - $id = $data['id'] ?? $form->getValue('id'); $item = $this->getItem($id); diff --git a/administrator/components/com_guidedtours/src/Model/StepsModel.php b/administrator/components/com_guidedtours/src/Model/StepsModel.php index d3daaa4685b81..1a6886b56c6f5 100644 --- a/administrator/components/com_guidedtours/src/Model/StepsModel.php +++ b/administrator/components/com_guidedtours/src/Model/StepsModel.php @@ -148,7 +148,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_guidedtours/src/Model/TourModel.php b/administrator/components/com_guidedtours/src/Model/TourModel.php index d39e479885b25..11363b2a8e504 100644 --- a/administrator/components/com_guidedtours/src/Model/TourModel.php +++ b/administrator/components/com_guidedtours/src/Model/TourModel.php @@ -11,11 +11,13 @@ namespace Joomla\Component\Guidedtours\Administrator\Model; use Joomla\CMS\Date\Date; +use Joomla\CMS\Event\Model\AfterDeleteEvent; +use Joomla\CMS\Event\Model\BeforeDeleteEvent; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\MVC\Model\AdminModel; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Component\Guidedtours\Administrator\Helper\GuidedtoursHelper; use Joomla\Database\ParameterType; @@ -105,7 +107,7 @@ protected function prepareTable($table) // Set ordering to the last item if not set if (empty($table->ordering)) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('MAX(ordering)') ->from($db->quoteName('#__guidedtours')); $db->setQuery($query); @@ -126,9 +128,10 @@ protected function prepareTable($table) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \JForm|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 4.3.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -142,10 +145,6 @@ public function getForm($data = [], $loadData = true) ] ); - if (empty($form)) { - return false; - } - $id = $data['id'] ?? $form->getValue('id'); $item = $this->getItem($id); @@ -221,9 +220,9 @@ public function getItem($pk = null) return false; } - // Convert to the CMSObject before adding other data. + // Convert to an object before adding other data. $properties = $table->getProperties(1); - $item = ArrayHelper::toObject($properties, CMSObject::class); + $item = ArrayHelper::toObject($properties); if (property_exists($item, 'params')) { $registry = new Registry($item->params); @@ -257,7 +256,8 @@ public function delete(&$pks) $table = $this->getTable(); // Include the plugins for the delete events. - PluginHelper::importPlugin($this->events_map['delete']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['delete'], null, true, $dispatcher); // Iterate the items to delete each one. foreach ($pks as $i => $pk) { @@ -266,7 +266,13 @@ public function delete(&$pks) $context = $this->option . '.' . $this->name; // Trigger the before delete event. - $result = Factory::getApplication()->triggerEvent($this->event_before_delete, [$context, $table]); + $result = $dispatcher->dispatch( + $this->event_before_delete, + new BeforeDeleteEvent($this->event_before_delete, [ + 'context' => $context, + 'subject' => $table, + ]) + )->getArgument('result', []); if (\in_array(false, $result, true)) { $this->setError($table->getError()); @@ -284,14 +290,20 @@ public function delete(&$pks) // Delete of the tour has been successful, now delete the steps $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__guidedtour_steps')) ->where($db->quoteName('tour_id') . '=' . $tourId); $db->setQuery($query); $db->execute(); // Trigger the after event. - Factory::getApplication()->triggerEvent($this->event_after_delete, [$context, $table]); + $dispatcher->dispatch( + $this->event_after_delete, + new AfterDeleteEvent($this->event_after_delete, [ + 'context' => $context, + 'subject' => $table, + ]) + ); } else { // Prune items that you can't change. unset($pks[$i]); @@ -356,7 +368,7 @@ public function duplicate(&$pks) $pk = (int) $pk; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( $db->quoteName( [ @@ -386,7 +398,7 @@ public function duplicate(&$pks) $rows = $db->loadObjectList(); if ($rows) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->insert($db->quoteName('#__guidedtour_steps')) ->columns( [ @@ -495,7 +507,7 @@ protected function setStepsLanguage(int $id, string $language = '*'): bool } $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__guidedtour_steps')) ->set($db->quoteName('language') . ' = :language') ->where($db->quoteName('tour_id') . ' = :tourId') @@ -518,7 +530,7 @@ public function setAutostart($id, $autostart) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__guidedtours')) ->set($db->quoteName('autostart') . ' = :autostart') ->where($db->quoteName('id') . ' = :tourId') @@ -542,7 +554,7 @@ public function isAutostart($pk): bool { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('autostart')) ->from($db->quoteName('#__guidedtours')) ->where($db->quoteName('published') . ' = 1'); @@ -587,7 +599,7 @@ public function saveTourUserState($id, $state = ''): bool $profileKey = 'guidedtour.id.' . $id; // Check if the profile key already exists. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('profile_value')) ->from($db->quoteName('#__user_profiles')) ->where($db->quoteName('user_id') . ' = :user_id') diff --git a/administrator/components/com_guidedtours/src/Model/ToursModel.php b/administrator/components/com_guidedtours/src/Model/ToursModel.php index 3179b7d79f91c..6f0358dcb0735 100644 --- a/administrator/components/com_guidedtours/src/Model/ToursModel.php +++ b/administrator/components/com_guidedtours/src/Model/ToursModel.php @@ -113,7 +113,7 @@ public function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( @@ -123,7 +123,7 @@ public function getListQuery() ) ); - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('COUNT(' . $db->quoteName('s.id') . ')') ->from($db->quoteName('#__guidedtour_steps', 's')) ->where( diff --git a/administrator/components/com_guidedtours/src/View/Step/HtmlView.php b/administrator/components/com_guidedtours/src/View/Step/HtmlView.php index 47f974e1092cb..01a1fdff9fc60 100644 --- a/administrator/components/com_guidedtours/src/View/Step/HtmlView.php +++ b/administrator/components/com_guidedtours/src/View/Step/HtmlView.php @@ -16,6 +16,7 @@ use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; use Joomla\CMS\Toolbar\ToolbarHelper; use Joomla\Component\Guidedtours\Administrator\Model\StepModel; +use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -52,7 +53,7 @@ class HtmlView extends BaseHtmlView /** * The actions the user is authorised to perform * - * @var \Joomla\CMS\Object\CMSObject + * @var Registry */ protected $canDo; @@ -76,6 +77,10 @@ public function display($tpl = null) $this->item = $model->getItem(); $this->state = $model->getState(); + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_guidedtours/src/View/Steps/HtmlView.php b/administrator/components/com_guidedtours/src/View/Steps/HtmlView.php index 66e8e659d9a48..e5ded57d049ed 100644 --- a/administrator/components/com_guidedtours/src/View/Steps/HtmlView.php +++ b/administrator/components/com_guidedtours/src/View/Steps/HtmlView.php @@ -108,6 +108,11 @@ public function display($tpl = null) // Unset the tour_id field from activeFilters as we don't filter by tour here. unset($this->activeFilters['tour_id']); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_guidedtours/src/View/Tour/HtmlView.php b/administrator/components/com_guidedtours/src/View/Tour/HtmlView.php index a65a5bc1f4e33..7a03caeba4d76 100644 --- a/administrator/components/com_guidedtours/src/View/Tour/HtmlView.php +++ b/administrator/components/com_guidedtours/src/View/Tour/HtmlView.php @@ -76,6 +76,10 @@ public function display($tpl = null) $this->item = $model->getItem(); $this->state = $model->getState(); + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_guidedtours/src/View/Tours/HtmlView.php b/administrator/components/com_guidedtours/src/View/Tours/HtmlView.php index ef8929999dd8e..30dea05f42a20 100644 --- a/administrator/components/com_guidedtours/src/View/Tours/HtmlView.php +++ b/administrator/components/com_guidedtours/src/View/Tours/HtmlView.php @@ -103,6 +103,11 @@ public function display($tpl = null) $this->filterForm->removeField('language', 'filter'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_guidedtours/tmpl/step/edit.php b/administrator/components/com_guidedtours/tmpl/step/edit.php index 6f0fac755e907..a529e494035ff 100644 --- a/administrator/components/com_guidedtours/tmpl/step/edit.php +++ b/administrator/components/com_guidedtours/tmpl/step/edit.php @@ -104,7 +104,7 @@ - form->getInput('tour_id'); ?> - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_guidedtours/tmpl/steps/default.php b/administrator/components/com_guidedtours/tmpl/steps/default.php index 97a0217a49c86..fccae6e1fb487 100644 --- a/administrator/components/com_guidedtours/tmpl/steps/default.php +++ b/administrator/components/com_guidedtours/tmpl/steps/default.php @@ -17,9 +17,8 @@ use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; use Joomla\Component\Guidedtours\Administrator\Extension\GuidedtoursComponent; -use Joomla\Component\Guidedtours\Administrator\View\Steps\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Guidedtours\Administrator\View\Steps\HtmlView $this */ /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->getDocument()->getWebAssetManager(); @@ -227,8 +226,6 @@ class="js-draggable" data-url="" data-direction=" ?> - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_guidedtours/tmpl/steps/emptystate.php b/administrator/components/com_guidedtours/tmpl/steps/emptystate.php index 68ae26353b72f..4364dbdc54013 100644 --- a/administrator/components/com_guidedtours/tmpl/steps/emptystate.php +++ b/administrator/components/com_guidedtours/tmpl/steps/emptystate.php @@ -19,6 +19,8 @@ 'formURL' => 'index.php?option=com_guidedtours&view=steps', 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Guided_Tours:_Steps', 'icon' => 'icon-map-signs', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; $user = $this->getCurrentUser(); diff --git a/administrator/components/com_guidedtours/tmpl/tour/edit.php b/administrator/components/com_guidedtours/tmpl/tour/edit.php index 5bef1f3549f89..7ed71c51be486 100644 --- a/administrator/components/com_guidedtours/tmpl/tour/edit.php +++ b/administrator/components/com_guidedtours/tmpl/tour/edit.php @@ -100,6 +100,5 @@ - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_guidedtours/tmpl/tours/default.php b/administrator/components/com_guidedtours/tmpl/tours/default.php index 33ef8b8f550f5..492777d1fa398 100644 --- a/administrator/components/com_guidedtours/tmpl/tours/default.php +++ b/administrator/components/com_guidedtours/tmpl/tours/default.php @@ -18,9 +18,8 @@ use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; -use Joomla\Component\Guidedtours\Administrator\View\Tours\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Guidedtours\Administrator\View\Tours\HtmlView $this */ /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->getDocument()->getWebAssetManager(); @@ -252,8 +251,6 @@ class="js-draggable" data-url="" data-direction=" ?> - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_guidedtours/tmpl/tours/emptystate.php b/administrator/components/com_guidedtours/tmpl/tours/emptystate.php index 6500a86264413..a899420c3ef53 100644 --- a/administrator/components/com_guidedtours/tmpl/tours/emptystate.php +++ b/administrator/components/com_guidedtours/tmpl/tours/emptystate.php @@ -19,6 +19,8 @@ 'formURL' => 'index.php?option=com_guidedtours&view=tours', 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Guided_Tours', 'icon' => 'icon-map-signs', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; $user = $this->getCurrentUser(); diff --git a/administrator/components/com_installer/helpers/installer.php b/administrator/components/com_installer/helpers/installer.php index 6a3f34aa789bc..27a4f56414085 100644 --- a/administrator/components/com_installer/helpers/installer.php +++ b/administrator/components/com_installer/helpers/installer.php @@ -19,7 +19,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Installer\Administrator\Helper\InstallerHelper instead */ class InstallerHelper extends \Joomla\Component\Installer\Administrator\Helper\InstallerHelper diff --git a/administrator/components/com_installer/src/Helper/InstallerHelper.php b/administrator/components/com_installer/src/Helper/InstallerHelper.php index 5be9411ad6e22..51d178bec9455 100644 --- a/administrator/components/com_installer/src/Helper/InstallerHelper.php +++ b/administrator/components/com_installer/src/Helper/InstallerHelper.php @@ -13,7 +13,6 @@ use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; -use Joomla\CMS\Object\CMSObject; use Joomla\Database\DatabaseInterface; use Joomla\Database\ParameterType; @@ -38,7 +37,7 @@ class InstallerHelper public static function getExtensionTypes() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('type')) ->from($db->quoteName('#__extensions')); $db->setQuery($query); @@ -64,7 +63,7 @@ public static function getExtensionGroups() { $nofolder = ''; $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('folder')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' != :folder') @@ -131,7 +130,7 @@ public static function getPackageOptions(): array /** @var DatabaseInterface $db The application's database driver object */ $db = Factory::getContainer()->get(DatabaseInterface::class); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( $db->quoteName( [ @@ -233,19 +232,19 @@ public static function getInstallationXML( /** * Get the download key of an extension going through their installation xml * - * @param CMSObject $extension element of an extension + * @param \stdClass $extension element of an extension * * @return array An array with the prefix, suffix and value of the download key * * @since 4.0.0 */ - public static function getDownloadKey(CMSObject $extension): array + public static function getDownloadKey(\stdClass $extension): array { $installXmlFile = self::getInstallationXML( - $extension->get('element'), - $extension->get('type'), - $extension->get('client_id'), - $extension->get('folder') + $extension->element, + $extension->type, + $extension->client_id, + $extension->folder ); if (!$installXmlFile) { @@ -264,7 +263,7 @@ public static function getDownloadKey(CMSObject $extension): array $prefix = (string) $installXmlFile->dlid['prefix']; $suffix = (string) $installXmlFile->dlid['suffix']; - $value = substr($extension->get('extra_query'), \strlen($prefix)); + $value = substr($extension->extra_query ?? '', \strlen($prefix)); if ($suffix) { $value = substr($value, 0, -\strlen($suffix)); @@ -309,8 +308,8 @@ public static function getExtensionDownloadKey( ]; } - // Try to retrieve the extension information as a CMSObject - $query = $db->getQuery(true) + // Try to retrieve the extension information + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = :type') @@ -323,8 +322,8 @@ public static function getExtensionDownloadKey( $query->bind(':folder', $folder, ParameterType::STRING); try { - $extension = new CMSObject($db->setQuery($query)->loadAssoc()); - } catch (\Exception) { + $extension = $db->setQuery($query)->loadObject(); + } catch (\Exception $e) { return [ 'supported' => false, 'valid' => false, @@ -355,15 +354,15 @@ public static function getDownloadKeySupportedSites($onlyEnabled = false): array $extensions = self::getUpdateSitesInformation($onlyEnabled); - $filterClosure = function (CMSObject $extension) { + $filterClosure = function ($extension) { $dlidInfo = self::getDownloadKey($extension); return $dlidInfo['supported']; }; $extensions = array_filter($extensions, $filterClosure); - $mapClosure = function (CMSObject $extension) { - return $extension->get('update_site_id'); + $mapClosure = function ($extension) { + return $extension->update_site_id ?? null; }; return array_map($mapClosure, $extensions); @@ -391,7 +390,7 @@ public static function getDownloadKeyExistsSites(bool $exists = true, $onlyEnabl $extensions = self::getUpdateSitesInformation($onlyEnabled); // Filter the extensions by what supports Download Keys - $filterClosure = function (CMSObject $extension) use ($exists) { + $filterClosure = function ($extension) use ($exists) { $dlidInfo = self::getDownloadKey($extension); if (!$dlidInfo['supported']) { @@ -403,8 +402,8 @@ public static function getDownloadKeyExistsSites(bool $exists = true, $onlyEnabl $extensions = array_filter($extensions, $filterClosure); // Return only the update site IDs - $mapClosure = function (CMSObject $extension) { - return $extension->get('update_site_id'); + $mapClosure = function ($extension) { + return $extension->update_site_id ?? null; }; return array_map($mapClosure, $extensions); @@ -416,7 +415,7 @@ public static function getDownloadKeyExistsSites(bool $exists = true, $onlyEnabl * * @param bool $onlyEnabled Only return enabled update sites * - * @return CMSObject[] List of update site and linked extension information + * @return \stdClass[] List of update site and linked extension information * @since 4.0.0 */ protected static function getUpdateSitesInformation(bool $onlyEnabled): array @@ -427,7 +426,7 @@ protected static function getUpdateSitesInformation(bool $onlyEnabled): array return []; } - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( $db->quoteName( [ @@ -473,15 +472,10 @@ protected static function getUpdateSitesInformation(bool $onlyEnabled): array // Try to get all of the update sites, including related extension information try { - $items = []; $db->setQuery($query); - foreach ($db->getIterator() as $item) { - $items[] = new CMSObject($item); - } - - return $items; - } catch (\Exception) { + return $db->loadObjectList(); + } catch (\Exception $e) { return []; } } diff --git a/administrator/components/com_installer/src/Model/DatabaseModel.php b/administrator/components/com_installer/src/Model/DatabaseModel.php index f9019190175f4..607507a85a81b 100644 --- a/administrator/components/com_installer/src/Model/DatabaseModel.php +++ b/administrator/components/com_installer/src/Model/DatabaseModel.php @@ -322,7 +322,7 @@ public function getItems() protected function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( $db->quoteName( [ @@ -427,7 +427,7 @@ public function getSchemaVersion($extensionId) { $db = $this->getDatabase(); $extensionId = (int) $extensionId; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('version_id')) ->from($db->quoteName('#__schemas')) ->where($db->quoteName('extension_id') . ' = :extensionid') @@ -462,7 +462,7 @@ public function fixSchemaVersion($changeSet, $extensionId) // Delete old row. $extensionId = (int) $extensionId; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__schemas')) ->where($db->quoteName('extension_id') . ' = :extensionid') ->bind(':extensionid', $extensionId, ParameterType::INTEGER); diff --git a/administrator/components/com_installer/src/Model/DiscoverModel.php b/administrator/components/com_installer/src/Model/DiscoverModel.php index 52e24afc3d801..1536c7f4d2f23 100644 --- a/administrator/components/com_installer/src/Model/DiscoverModel.php +++ b/administrator/components/com_installer/src/Model/DiscoverModel.php @@ -90,7 +90,7 @@ protected function populateState($ordering = 'name', $direction = 'asc') protected function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__extensions')) ->where($db->quoteName('state') . ' = -1'); @@ -150,7 +150,7 @@ public function discover() // Get all templates, including discovered ones $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['extension_id', 'element', 'folder', 'client_id', 'type'])) ->from($db->quoteName('#__extensions')); $db->setQuery($query); @@ -253,7 +253,7 @@ public function discover_install() public function purge() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__extensions')) ->where($db->quoteName('state') . ' = -1'); $db->setQuery($query); @@ -297,7 +297,7 @@ protected function getEmptyStateQuery() public function checkExtensions() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__extensions')) ->where($db->quoteName('state') . ' = -1'); diff --git a/administrator/components/com_installer/src/Model/InstallModel.php b/administrator/components/com_installer/src/Model/InstallModel.php index 8ebda75e853be..12c6cc02088a5 100644 --- a/administrator/components/com_installer/src/Model/InstallModel.php +++ b/administrator/components/com_installer/src/Model/InstallModel.php @@ -328,7 +328,7 @@ protected function _getPackageFromUpload() $tmp_src = $userfile['tmp_name']; // Move uploaded file. Allow "unsafe" files: an extension package legitimately contains PHP, - // which the File::upload() safety scan (default since joomla/filesystem 3.3.0) would reject. + // which the File::upload() safety scan (default since joomla/filesystem 4.2.0) would reject. try { File::upload($tmp_src, $tmp_dest, false, true); } catch (FilesystemException) { diff --git a/administrator/components/com_installer/src/Model/LanguagesModel.php b/administrator/components/com_installer/src/Model/LanguagesModel.php index 0c54ca93fb390..101f6cfd6955f 100644 --- a/administrator/components/com_installer/src/Model/LanguagesModel.php +++ b/administrator/components/com_installer/src/Model/LanguagesModel.php @@ -10,10 +10,12 @@ namespace Joomla\Component\Installer\Administrator\Model; use Joomla\CMS\Factory; -use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; +use Joomla\CMS\Version; +use Joomla\Http\HttpFactory; +use Joomla\Registry\Registry; use Joomla\String\StringHelper; // phpcs:disable PSR1.Files.SideEffects @@ -66,7 +68,7 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) private function getUpdateSite() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('us.location')) ->from($db->quoteName('#__extensions', 'e')) ->where($db->quoteName('e.type') . ' = ' . $db->quote('package')) @@ -131,11 +133,14 @@ protected function getLanguages() if (empty($updateSite)) { Factory::getApplication()->enqueueMessage(Text::_('COM_INSTALLER_MSG_WARNING_NO_LANGUAGES_UPDATESERVER'), 'warning'); - return; + return []; } + $options = new Registry(); + $options->set('userAgent', (new Version())->getUserAgent('Joomla', true, false)); + try { - $response = HttpFactory::getHttp()->get($updateSite); + $response = (new HttpFactory())->getHttp($options)->get($updateSite); } catch (\RuntimeException) { $response = null; } @@ -143,7 +148,7 @@ protected function getLanguages() if ($response === null || $response->getStatusCode() !== 200) { Factory::getApplication()->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_ERROR_CANT_CONNECT_TO_UPDATESERVER', $updateSite), 'error'); - return; + return []; } $updateSiteXML = simplexml_load_string((string) $response->getBody()); @@ -151,7 +156,7 @@ protected function getLanguages() if (!$updateSiteXML) { Factory::getApplication()->enqueueMessage(Text::sprintf('COM_INSTALLER_MSG_ERROR_CANT_RETRIEVE_XML', $updateSite), 'error'); - return; + return []; } $languages = []; diff --git a/administrator/components/com_installer/src/Model/ManageModel.php b/administrator/components/com_installer/src/Model/ManageModel.php index 2756887df1b77..8ac385f59e02e 100644 --- a/administrator/components/com_installer/src/Model/ManageModel.php +++ b/administrator/components/com_installer/src/Model/ManageModel.php @@ -263,20 +263,20 @@ public function remove($eid = []) // Build an array of extensions that failed to uninstall if ($result === false) { // There was an error in uninstalling the package - $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype); + $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype, $row->name); continue; } // Package uninstalled successfully - $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_SUCCESS', $rowtype); + $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_SUCCESS', $rowtype, $row->name); $result = true; continue; } // There was an error in uninstalling the package - $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype); + $msgs[] = Text::sprintf('COM_INSTALLER_UNINSTALL_ERROR', $rowtype, $row->name); } $msg = implode('
', $msgs); @@ -306,7 +306,7 @@ public function remove($eid = []) protected function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->select('2*protected+(1-protected)*enabled AS status') ->from('#__extensions') @@ -395,7 +395,7 @@ public function loadChangelog($eid, $source) // Get the changelog URL $eid = (int) $eid; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( $db->quoteName( [ diff --git a/administrator/components/com_installer/src/Model/UpdateModel.php b/administrator/components/com_installer/src/Model/UpdateModel.php index 5bfbf76b6d1b9..f07244302038b 100644 --- a/administrator/components/com_installer/src/Model/UpdateModel.php +++ b/administrator/components/com_installer/src/Model/UpdateModel.php @@ -12,7 +12,6 @@ use Joomla\CMS\Extension\ExtensionHelper; use Joomla\CMS\Factory; -use Joomla\CMS\Form\Form; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Installer\InstallerHelper; use Joomla\CMS\Language\Text; @@ -97,7 +96,7 @@ protected function getListQuery() $db = $this->getDatabase(); // Grab updates ignoring new installs - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('u.*') ->select($db->quoteName('e.manifest_cache')) ->from($db->quoteName('#__updates', 'u')) @@ -245,7 +244,7 @@ public function getDisabledUpdateSites() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__update_sites')) ->where($db->quoteName('enabled') . ' = 0'); @@ -293,7 +292,7 @@ public function purge() } // Reset the last update check timestamp - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__update_sites')) ->set($db->quoteName('last_check_timestamp') . ' = ' . $db->quote(0)); $db->setQuery($query); @@ -334,7 +333,7 @@ public function update($uids, $minimumStability = Updater::STABILITY_STABLE) $app = Factory::getApplication(); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('type') ->from('#__update_sites') ->where($db->quoteName('update_site_id') . ' = :id') @@ -519,49 +518,6 @@ private function install($update) return $result; } - /** - * Method to get the row form. - * - * @param array $data Data for the form. - * @param boolean $loadData True if the form is to load its own data (default case), false if not. - * - * @return Form|bool A Form object on success, false on failure - * - * @since 2.5.2 - */ - public function getForm($data = [], $loadData = true) - { - // Get the form. - Form::addFormPath(JPATH_COMPONENT . '/models/forms'); - Form::addFieldPath(JPATH_COMPONENT . '/models/fields'); - $form = Form::getInstance('com_installer.update', 'update', ['load_data' => $loadData]); - - // Check the session for previously entered form data. - $data = $this->loadFormData(); - - // Bind the form data if present. - if (!empty($data)) { - $form->bind($data); - } - - return $form; - } - - /** - * Method to get the data that should be injected in the form. - * - * @return mixed The data for the form. - * - * @since 2.5.2 - */ - protected function loadFormData() - { - // Check the session for previously entered form data. - $data = Factory::getApplication()->getUserState($this->context, []); - - return $data; - } - /** * Method to add parameters to the update * diff --git a/administrator/components/com_installer/src/Model/UpdatesiteModel.php b/administrator/components/com_installer/src/Model/UpdatesiteModel.php index 5b2efd737254c..3906da9393d4c 100644 --- a/administrator/components/com_installer/src/Model/UpdatesiteModel.php +++ b/administrator/components/com_installer/src/Model/UpdatesiteModel.php @@ -12,7 +12,6 @@ use Joomla\CMS\Form\Form; use Joomla\CMS\MVC\Model\AdminModel; -use Joomla\CMS\Object\CMSObject; use Joomla\Component\Installer\Administrator\Helper\InstallerHelper; use Joomla\Database\ParameterType; @@ -41,7 +40,7 @@ class UpdatesiteModel extends AdminModel * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @throws \Exception * @@ -49,14 +48,7 @@ class UpdatesiteModel extends AdminModel */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_installer.updatesite', 'updatesite', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_installer.updatesite', 'updatesite', ['control' => 'jform', 'load_data' => $loadData]); } /** * Method to get the data that should be injected in the form. @@ -87,8 +79,8 @@ public function getItem($pk = null) $item = parent::getItem($pk); $db = $this->getDatabase(); - $updateSiteId = (int) $item->get('update_site_id'); - $query = $db->getQuery(true) + $updateSiteId = (int) $item->update_site_id ?? 0; + $query = $db->createQuery() ->select( $db->quoteName( [ @@ -116,13 +108,13 @@ public function getItem($pk = null) ->bind(':updatesiteid', $updateSiteId, ParameterType::INTEGER); $db->setQuery($query); - $extension = new CMSObject($db->loadAssoc()); + $extension = $db->loadObject(); $downloadKey = InstallerHelper::getDownloadKey($extension); - $item->set('extra_query', $downloadKey['value'] ?? ''); - $item->set('downloadIdPrefix', $downloadKey['prefix'] ?? ''); - $item->set('downloadIdSuffix', $downloadKey['suffix'] ?? ''); + $item->extra_query = $downloadKey['value'] ?? ''; + $item->downloadIdPrefix = $downloadKey['prefix'] ?? ''; + $item->downloadIdSuffix = $downloadKey['suffix'] ?? ''; return $item; } @@ -154,7 +146,7 @@ public function save($data): bool // Delete update records forcing Joomla to fetch them again, applying the new extra_query. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__updates')) ->where($db->quoteName('update_site_id') . ' = :updateSiteId'); $query->bind(':updateSiteId', $data['update_site_id'], ParameterType::INTEGER); diff --git a/administrator/components/com_installer/src/Model/UpdatesitesModel.php b/administrator/components/com_installer/src/Model/UpdatesitesModel.php index b8b48d027f701..a4ef97e71ade6 100644 --- a/administrator/components/com_installer/src/Model/UpdatesitesModel.php +++ b/administrator/components/com_installer/src/Model/UpdatesitesModel.php @@ -10,11 +10,11 @@ namespace Joomla\Component\Installer\Administrator\Model; +use Joomla\CMS\Event\Extension\AfterUpdateEvent; use Joomla\CMS\Factory; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Table\UpdateSite as UpdateSiteTable; @@ -136,7 +136,7 @@ public function delete($ids = []) $count = 0; // Gets the update site names. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['update_site_id', 'name'])) ->from($db->quoteName('#__update_sites')) ->whereIn($db->quoteName('update_site_id'), $ids); @@ -157,21 +157,21 @@ public function delete($ids = []) // Delete the update site from all tables. try { $id = (int) $id; - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__update_sites')) ->where($db->quoteName('update_site_id') . ' = :id') ->bind(':id', $id, ParameterType::INTEGER); $db->setQuery($query); $db->execute(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__update_sites_extensions')) ->where($db->quoteName('update_site_id') . ' = :id') ->bind(':id', $id, ParameterType::INTEGER); $db->setQuery($query); $db->execute(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__updates')) ->where($db->quoteName('update_site_id') . ' = :id') ->bind(':id', $id, ParameterType::INTEGER); @@ -210,7 +210,7 @@ protected function getJoomlaUpdateSitesIds($column = 0) $db = $this->getDatabase(); // Fetch the Joomla core update sites ids and their extension ids. We search for all except the core joomla extension with update sites. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['use.update_site_id', 'e.extension_id'])) ->from($db->quoteName('#__update_sites_extensions', 'use')) ->join( @@ -256,7 +256,7 @@ public function rebuild(): void // Check if Joomla Extension plugin is enabled. if (!PluginHelper::isEnabled('extension', 'joomla')) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) @@ -305,26 +305,26 @@ public function rebuild(): void $joomlaUpdateSitesIds = $this->getJoomlaUpdateSitesIds(0); // First backup any custom extra_query for the sites - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('TRIM(' . $db->quoteName('location') . ') AS ' . $db->quoteName('location') . ', ' . $db->quoteName('extra_query')) ->from($db->quoteName('#__update_sites')); $db->setQuery($query); $backupExtraQuerys = $db->loadAssocList('location'); // Delete from all tables (except joomla core update sites). - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__update_sites')) ->whereNotIn($db->quoteName('update_site_id'), $joomlaUpdateSitesIds); $db->setQuery($query); $db->execute(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__update_sites_extensions')) ->whereNotIn($db->quoteName('update_site_id'), $joomlaUpdateSitesIds); $db->setQuery($query); $db->execute(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__updates')) ->whereNotIn($db->quoteName('update_site_id'), $joomlaUpdateSitesIds); $db->setQuery($query); @@ -366,7 +366,7 @@ public function rebuild(): void $pkgName = (string) $manifest->packagename; $type = (string) $manifest['type']; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where( @@ -408,10 +408,17 @@ public function rebuild(): void } // Load the extension plugin (if not loaded yet). - PluginHelper::importPlugin('extension', 'joomla'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('extension', 'joomla', true, $dispatcher); // Fire the onExtensionAfterUpdate - $app->triggerEvent('onExtensionAfterUpdate', ['installer' => $tmpInstaller, 'eid' => $eid]); + $dispatcher->dispatch( + 'onExtensionAfterUpdate', + new AfterUpdateEvent('onExtensionAfterUpdate', [ + 'installer' => $tmpInstaller, + 'eid' => $eid, + ]) + ); $count++; } @@ -444,8 +451,7 @@ public function getItems() array_walk( $items, static function ($item) { - $data = new CMSObject($item); - $item->downloadKey = InstallerHelper::getDownloadKey($data); + $item->downloadKey = InstallerHelper::getDownloadKey($item); } ); @@ -491,7 +497,7 @@ protected function getStoreId($id = '') protected function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( $db->quoteName( [ diff --git a/administrator/components/com_installer/src/View/Database/HtmlView.php b/administrator/components/com_installer/src/View/Database/HtmlView.php index 931bf0062da6c..ed0bf15239475 100644 --- a/administrator/components/com_installer/src/View/Database/HtmlView.php +++ b/administrator/components/com_installer/src/View/Database/HtmlView.php @@ -105,6 +105,11 @@ public function display($tpl = null) : $app->enqueueMessage(Text::_('COM_INSTALLER_MSG_DATABASE_CORE_ERRORS'), 'warning'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_installer/src/View/Discover/HtmlView.php b/administrator/components/com_installer/src/View/Discover/HtmlView.php index aed4d36a2c5e3..8d17f7d5af9ae 100644 --- a/administrator/components/com_installer/src/View/Discover/HtmlView.php +++ b/administrator/components/com_installer/src/View/Discover/HtmlView.php @@ -94,6 +94,11 @@ public function display($tpl = null) $this->setLayout('emptystate'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_installer/src/View/Languages/HtmlView.php b/administrator/components/com_installer/src/View/Languages/HtmlView.php index a8bf800a4c896..3b8e912752d6b 100644 --- a/administrator/components/com_installer/src/View/Languages/HtmlView.php +++ b/administrator/components/com_installer/src/View/Languages/HtmlView.php @@ -76,6 +76,15 @@ public function display($tpl = null) $this->activeFilters = $model->getActiveFilters(); $this->installedLang = LanguageHelper::getInstalledLanguages(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0') + ->addControlField('return', base64_encode('index.php?option=com_installer&view=languages')) + ->addControlField('install_url', '', ['id' => 'install_url']) + ->addControlField('installtype', 'url') + ->addControlField('package', 'language'); + parent::display($tpl); } diff --git a/administrator/components/com_installer/src/View/Manage/HtmlView.php b/administrator/components/com_installer/src/View/Manage/HtmlView.php index be38d698ab860..5abc4a85c018e 100644 --- a/administrator/components/com_installer/src/View/Manage/HtmlView.php +++ b/administrator/components/com_installer/src/View/Manage/HtmlView.php @@ -83,6 +83,11 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + // Display the view. parent::display($tpl); } @@ -117,6 +122,7 @@ protected function addToolbar() if ($canDo->get('core.delete')) { $childBar->delete('manage.remove', 'JTOOLBAR_UNINSTALL') + ->icon('icon-exclamation-triangle') ->message('COM_INSTALLER_CONFIRM_UNINSTALL') ->listCheck(true); } diff --git a/administrator/components/com_installer/src/View/Update/HtmlView.php b/administrator/components/com_installer/src/View/Update/HtmlView.php index e1b5b77156cb7..fc9017bd85aef 100644 --- a/administrator/components/com_installer/src/View/Update/HtmlView.php +++ b/administrator/components/com_installer/src/View/Update/HtmlView.php @@ -13,8 +13,7 @@ use Joomla\CMS\Application\CMSApplication; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; -use Joomla\CMS\Object\CMSObject; -use Joomla\Component\Installer\Administrator\Helper\InstallerHelper as CmsInstallerHelper; +use Joomla\Component\Installer\Administrator\Helper\InstallerHelper; use Joomla\Component\Installer\Administrator\Model\UpdateModel; use Joomla\Component\Installer\Administrator\View\Installer\HtmlView as InstallerViewDefault; @@ -32,7 +31,7 @@ class HtmlView extends InstallerViewDefault /** * List of update items. * - * @var array + * @var \stdClass[] */ protected $items; @@ -100,12 +99,12 @@ public function display($tpl = null) } // Find if there are any updates which require but are missing a Download Key - if (!class_exists('Joomla\Component\Installer\Administrator\Helper\InstallerHelper')) { + if (!class_exists(InstallerHelper::class)) { require_once JPATH_ADMINISTRATOR . '/components/com_installer/src/Helper/InstallerHelper.php'; } $mappingCallback = function ($item) { - $dlkeyInfo = CmsInstallerHelper::getDownloadKey(new CMSObject($item)); + $dlkeyInfo = InstallerHelper::getDownloadKey($item); $item->isMissingDownloadKey = $dlkeyInfo['supported'] && !$dlkeyInfo['valid']; if ($item->isMissingDownloadKey) { @@ -122,6 +121,11 @@ public function display($tpl = null) Factory::getApplication()->enqueueMessage($msg, CMSApplication::MSG_WARNING); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + parent::display($tpl); } diff --git a/administrator/components/com_installer/src/View/Updatesite/HtmlView.php b/administrator/components/com_installer/src/View/Updatesite/HtmlView.php index b643c21b4222e..386b9282b1a55 100644 --- a/administrator/components/com_installer/src/View/Updatesite/HtmlView.php +++ b/administrator/components/com_installer/src/View/Updatesite/HtmlView.php @@ -71,12 +71,16 @@ public function display($tpl = null): void // Remove the extra_query field if it's a free download extension $dlidSupportingSites = InstallerHelper::getDownloadKeySupportedSites(false); - $update_site_id = $this->item->get('update_site_id'); + $update_site_id = $this->item->update_site_id; if (!\in_array($update_site_id, $dlidSupportingSites)) { $this->form->removeField('extra_query'); } + // Add form control fields + $this->form + ->addControlField('task'); + parent::display($tpl); } @@ -109,14 +113,8 @@ protected function addToolbar(): void // Can't save the record if it's checked out and editable if (!$checkedOut && $itemEditable && $this->form->getField('extra_query')) { - $saveGroup = $toolbar->dropdownButton('save-group'); - - $saveGroup->configure( - function (Toolbar $childBar) { - $childBar->apply('updatesite.apply'); - $childBar->save('updatesite.save'); - } - ); + $toolbar->apply('updatesite.apply'); + $toolbar->save('updatesite.save'); } $toolbar->cancel('updatesite.cancel'); diff --git a/administrator/components/com_installer/src/View/Updatesites/HtmlView.php b/administrator/components/com_installer/src/View/Updatesites/HtmlView.php index 6d61cd5a16dfc..443247a3dd2b3 100644 --- a/administrator/components/com_installer/src/View/Updatesites/HtmlView.php +++ b/administrator/components/com_installer/src/View/Updatesites/HtmlView.php @@ -82,6 +82,11 @@ public function display($tpl = null): void $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + // Display the view parent::display($tpl); } @@ -114,7 +119,9 @@ protected function addToolbar(): void $childBar->unpublish('updatesites.unpublish', 'JTOOLBAR_DISABLE')->listCheck(true); if ($canDo->get('core.delete')) { - $childBar->delete('updatesites.delete')->listCheck(true); + $childBar->delete('updatesites.delete') + ->icon('icon-exclamation-triangle') + ->listCheck(true); } $childBar->checkin('updatesites.checkin')->listCheck(true); diff --git a/administrator/components/com_installer/tmpl/database/default.php b/administrator/components/com_installer/tmpl/database/default.php index dcbd008ce8c64..1755222e8b116 100644 --- a/administrator/components/com_installer/tmpl/database/default.php +++ b/administrator/components/com_installer/tmpl/database/default.php @@ -64,7 +64,7 @@ - + @@ -108,7 +108,7 @@ version_id; ?> - + version; ?> @@ -126,9 +126,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_installer/tmpl/discover/default.php b/administrator/components/com_installer/tmpl/discover/default.php index a42996408b1b9..7ab3c87446753 100644 --- a/administrator/components/com_installer/tmpl/discover/default.php +++ b/administrator/components/com_installer/tmpl/discover/default.php @@ -121,9 +121,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_installer/tmpl/discover/emptystate.php b/administrator/components/com_installer/tmpl/discover/emptystate.php index b895352e42a9d..f926998d141cb 100644 --- a/administrator/components/com_installer/tmpl/discover/emptystate.php +++ b/administrator/components/com_installer/tmpl/discover/emptystate.php @@ -25,6 +25,8 @@ 'content' => Text::_('COM_INSTALLER_MSG_DISCOVER_DESCRIPTION'), 'title' => Text::_('COM_INSTALLER_EMPTYSTATE_DISCOVER_TITLE'), 'btnadd' => Text::_('COM_INSTALLER_EMPTYSTATE_DISCOVER_BUTTON_ADD'), + + 'controlFields' => $this->filterForm->renderControlFields(), ]; /** @var \Joomla\Component\Installer\Administrator\View\Discover\HtmlView $this */ diff --git a/administrator/components/com_installer/tmpl/languages/default.php b/administrator/components/com_installer/tmpl/languages/default.php index dc022abcbec45..de255c066f9dc 100644 --- a/administrator/components/com_installer/tmpl/languages/default.php +++ b/administrator/components/com_installer/tmpl/languages/default.php @@ -117,13 +117,8 @@ class="" pagination->getListFooter(); ?> - - - - - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_installer/tmpl/manage/default.php b/administrator/components/com_installer/tmpl/manage/default.php index 0c09f458e1d68..0a0f76bc438ba 100644 --- a/administrator/components/com_installer/tmpl/manage/default.php +++ b/administrator/components/com_installer/tmpl/manage/default.php @@ -174,9 +174,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_installer/tmpl/update/default.php b/administrator/components/com_installer/tmpl/update/default.php index 43cb139e01d6d..e493e91f3b0da 100644 --- a/administrator/components/com_installer/tmpl/update/default.php +++ b/administrator/components/com_installer/tmpl/update/default.php @@ -105,6 +105,11 @@ update_site_id; ?> + security)) : ?> +
+ security); ?> +
+ client_translated; ?> @@ -153,9 +158,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_installer/tmpl/update/emptystate.php b/administrator/components/com_installer/tmpl/update/emptystate.php index 6ba4a0d275fe5..59b12f33b73e8 100644 --- a/administrator/components/com_installer/tmpl/update/emptystate.php +++ b/administrator/components/com_installer/tmpl/update/emptystate.php @@ -20,6 +20,8 @@ 'formURL' => 'index.php?option=com_installer&view=update', 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Extensions:_Update', 'icon' => 'icon-puzzle-piece install', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; $user = $this->getCurrentUser(); diff --git a/administrator/components/com_installer/tmpl/updatesite/edit.php b/administrator/components/com_installer/tmpl/updatesite/edit.php index dc95fcddcd8a8..a0f33c2094808 100644 --- a/administrator/components/com_installer/tmpl/updatesite/edit.php +++ b/administrator/components/com_installer/tmpl/updatesite/edit.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -24,6 +23,6 @@

item->name; ?>

form->renderFieldset('updateSite'); ?> - - + + form->renderControlFields(); ?>
diff --git a/administrator/components/com_installer/tmpl/updatesites/default.php b/administrator/components/com_installer/tmpl/updatesites/default.php index be5c1e9f25249..8c8bcd0d2e096 100644 --- a/administrator/components/com_installer/tmpl/updatesites/default.php +++ b/administrator/components/com_installer/tmpl/updatesites/default.php @@ -158,9 +158,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_joomlaupdate/postinstall/autoupdate.php b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php index 16f468f15fb6f..944cdd67bd544 100644 --- a/administrator/components/com_joomlaupdate/postinstall/autoupdate.php +++ b/administrator/components/com_joomlaupdate/postinstall/autoupdate.php @@ -26,7 +26,7 @@ * Returns true it is disabled. * * @return bool - * @since 5.4.0 + * @since 6.0.0 */ function com_joomlaupdate_postinstall_autoupdate_condition(): bool { @@ -39,7 +39,7 @@ function com_joomlaupdate_postinstall_autoupdate_condition(): bool * Enables the Automated Update. * * @return void - * @since 5.4.0 + * @since 6.0.0 */ function com_joomlaupdate_postinstall_autoupdate_action(): void { diff --git a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php index 1353fabeb306d..ee2668bf790c3 100644 --- a/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php +++ b/administrator/components/com_joomlaupdate/src/Controller/UpdateController.php @@ -11,7 +11,6 @@ namespace Joomla\Component\Joomlaupdate\Administrator\Controller; use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Factory; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; @@ -468,118 +467,14 @@ public function finaliseconfirm() $this->setRedirect('index.php?option=com_joomlaupdate&task=update.finalise&' . Session::getFormToken() . '=1'); } - /** - * Fetch Extension update XML proxy. Used to prevent Access-Control-Allow-Origin errors. - * Prints a JSON string. - * Called from JS. - * - * @since 3.10.0 - * - * @deprecated 4.3 will be removed in 6.0 - * Use batchextensioncompatibility instead. - * Example: $updateController->batchextensioncompatibility(); - * - * @return void - */ - public function fetchExtensionCompatibility() - { - $extensionID = $this->input->get('extension-id', '', 'DEFAULT'); - $joomlaTargetVersion = $this->input->get('joomla-target-version', '', 'DEFAULT'); - $joomlaCurrentVersion = $this->input->get('joomla-current-version', '', JVERSION); - $extensionVersion = $this->input->get('extension-version', '', 'DEFAULT'); - - /** @var \Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel $model */ - $model = $this->getModel('Update'); - $upgradeCompatibilityStatus = $model->fetchCompatibility($extensionID, $joomlaTargetVersion); - $currentCompatibilityStatus = $model->fetchCompatibility($extensionID, $joomlaCurrentVersion); - $upgradeUpdateVersion = false; - $currentUpdateVersion = false; - - $upgradeWarning = 0; - - if ($upgradeCompatibilityStatus->state == 1 && !empty($upgradeCompatibilityStatus->compatibleVersions)) { - $upgradeUpdateVersion = end($upgradeCompatibilityStatus->compatibleVersions); - } - - if ($currentCompatibilityStatus->state == 1 && !empty($currentCompatibilityStatus->compatibleVersions)) { - $currentUpdateVersion = end($currentCompatibilityStatus->compatibleVersions); - } - - if ($upgradeCompatibilityStatus->state === 3 || $currentCompatibilityStatus->state === 3) { - // One of the update servers could not be checked. - $resultGroup = 4; - } elseif ($upgradeUpdateVersion !== false) { - $upgradeOldestVersion = $upgradeCompatibilityStatus->compatibleVersions[0]; - - if ($currentUpdateVersion !== false) { - // If there are updates compatible with both CMS versions use these - $bothCompatibleVersions = array_values( - array_intersect($upgradeCompatibilityStatus->compatibleVersions, $currentCompatibilityStatus->compatibleVersions) - ); - - if (!empty($bothCompatibleVersions)) { - $upgradeOldestVersion = $bothCompatibleVersions[0]; - $upgradeUpdateVersion = end($bothCompatibleVersions); - } - } - - if (version_compare($upgradeOldestVersion, $extensionVersion, '>')) { - // Installed version is empty or older than the oldest compatible update: Update required - $resultGroup = 2; - } else { - // Current version is compatible - $resultGroup = 3; - } - - if ($currentUpdateVersion !== false && version_compare($upgradeUpdateVersion, $currentUpdateVersion, '<')) { - // Special case warning when version compatible with target is lower than current - $upgradeWarning = 2; - } - } elseif ($currentUpdateVersion !== false) { - // No compatible version for target version but there is a compatible version for current version - $resultGroup = 1; - } else { - // No update server available - $resultGroup = 1; - } - - // Do we need to capture - $combinedCompatibilityStatus = [ - 'upgradeCompatibilityStatus' => (object) [ - 'state' => $upgradeCompatibilityStatus->state, - 'compatibleVersion' => $upgradeUpdateVersion, - ], - 'currentCompatibilityStatus' => (object) [ - 'state' => $currentCompatibilityStatus->state, - 'compatibleVersion' => $currentUpdateVersion, - ], - 'resultGroup' => $resultGroup, - 'upgradeWarning' => $upgradeWarning, - ]; - - $this->app = Factory::getApplication(); - $this->app->mimeType = 'application/json'; - $this->app->charSet = 'utf-8'; - $this->app->setHeader('Content-Type', $this->app->mimeType . '; charset=' . $this->app->charSet); - $this->app->sendHeaders(); - - try { - echo new JsonResponse($combinedCompatibilityStatus); - } catch (\Exception $e) { - echo $e; - } - - $this->app->close(); - } - /** * Determines the compatibility information for a number of extensions. * * Called by the Joomla Update JavaScript (PreUpdateChecker.checkNextChunk). * * @return void - * @since 4.2.0 * + * @since 4.2.0 */ public function batchextensioncompatibility() { diff --git a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php index bf97abafd57d3..5519b5c7331ce 100644 --- a/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/NotificationModel.php @@ -14,7 +14,11 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Helper\UserGroupsHelper; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\LanguageFactoryInterface; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailHelper; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Model\BaseDatabaseModel; @@ -33,8 +37,11 @@ * @internal * @since 5.4.0 */ -final class NotificationModel extends BaseDatabaseModel +final class NotificationModel extends BaseDatabaseModel implements MailerFactoryAwareInterface, LanguageFactoryAwareInterface { + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; + /** * Sends the update notification to the specifically configured emails and superusers * @@ -116,7 +123,12 @@ public function sendNotification($type, $oldVersion, $newVersion): void $receiverLanguage->load('com_joomlaupdate', JPATH_ADMINISTRATOR, $receiverLocale); } - $mailer = new MailTemplate('com_joomlaupdate.update.' . $type, $receiverLocale); + $mailer = new MailTemplate( + 'com_joomlaupdate.update.' . $type, + $receiverLocale, + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addRecipient($receiver->email, $receiver->name); $mailer->addTemplateData($substitutions); $mailer->send(); diff --git a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php index 32faa4618b2ff..742ebfcbb0f4a 100644 --- a/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php +++ b/administrator/components/com_joomlaupdate/src/Model/UpdateModel.php @@ -18,8 +18,6 @@ use Joomla\CMS\Extension\ExtensionHelper; use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; -use Joomla\CMS\Http\Http; -use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; @@ -39,6 +37,7 @@ use Joomla\Database\ParameterType; use Joomla\Filesystem\Exception\FilesystemException; use Joomla\Filesystem\File; +use Joomla\Http\HttpFactory; use Joomla\Registry\Registry; use Joomla\Utilities\ArrayHelper; use Tobscure\JsonApi\Exception\InvalidParameterException; @@ -79,7 +78,6 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) // Register a logger for update process $options = [ - 'format' => '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}', 'text_file' => 'joomla_update.php', ]; @@ -130,7 +128,7 @@ public function applyUpdateSite(?string $updateSource = null, ?string $updateURL $id = ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id; $db = version_compare(JVERSION, '4.2.0', 'lt') ? $this->getDbo() : $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('us') . '.*') ->from($db->quoteName('#__update_sites_extensions', 'map')) ->join( @@ -204,7 +202,7 @@ public function getCheckForSelfUpdate() { $db = version_compare(JVERSION, '4.2.0', 'lt') ? $this->getDbo() : $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('element') . ' = ' . $db->quote('com_joomlaupdate')); @@ -228,7 +226,7 @@ public function getCheckForSelfUpdate() $updater->findUpdates($joomlaUpdateComponentId, $cache_timeout, Updater::STABILITY_STABLE); // Fetch the update information from the database. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__updates')) ->where($db->quoteName('extension_id') . ' = :id') @@ -274,7 +272,7 @@ public function getUpdateInformation() // Fetch the update information from the database. $id = ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id; $db = version_compare(JVERSION, '4.2.0', 'lt') ? $this->getDbo() : $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__updates')) ->where($db->quoteName('extension_id') . ' = :id') @@ -354,7 +352,7 @@ public function purge() $update_site->update_site_id = 1; $db->updateObject('#__update_sites', $update_site, 'update_site_id'); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__updates')) ->where($db->quoteName('update_site_id') . ' = 1'); $db->setQuery($query); @@ -386,11 +384,12 @@ public function download() // We have to manually follow the redirects here so we set the option to false. $httpOptions = new Registry(); $httpOptions->set('follow_location', false); + $httpOptions->set('userAgent', (new Version())->getUserAgent('Joomla', true, false)); $response = ['basename' => false, 'check' => null, 'version' => $updateInfo['latest']]; try { - $head = HttpFactory::getHttp($httpOptions)->head($packageURL); + $head = (new HttpFactory())->getHttp($httpOptions)->head($packageURL); } catch (\RuntimeException) { // Passing false here -> download failed message return $response; @@ -401,7 +400,7 @@ public function download() $packageURL = (string) $head->getHeaders()['location'][0]; try { - $head = HttpFactory::getHttp($httpOptions)->head($packageURL); + $head = (new HttpFactory())->getHttp($httpOptions)->head($packageURL); } catch (\RuntimeException) { // Passing false here -> download failed message return $response; @@ -586,7 +585,10 @@ public function changeAutoUpdateRegistration(AutoupdateRegisterState $targetStat $this->cleanCache('_system'); // Prepare connection - $http = HttpFactory::getHttp(); + $options = new Registry(); + $options->set('userAgent', (new Version())->getUserAgent('Joomla', true, false)); + + $http = (new HttpFactory())->getHttp($options); $url = self::AUTOUPDATE_URL; $url .= ($targetState === AutoupdateRegisterState::Subscribe) ? '/register' : '/delete'; @@ -661,7 +663,7 @@ public function changeAutoUpdateRegistration(AutoupdateRegisterState $targetStat /** * Update the autoupdate activation and registration states * - * @since 5.4.0 + * @since 6.0.0 */ protected function updateAutoUpdateParams(AutoupdateRegisterState $registrationState, bool $enableUpdate): void { @@ -779,8 +781,11 @@ protected function downloadPackage($url, $target) } // Download the package + $options = new Registry(); + $options->set('userAgent', (new Version())->getUserAgent('Joomla', true, false)); + try { - $result = HttpFactory::getHttp([], ['curl', 'stream'])->get($url); + $result = (new HttpFactory())->getHttp($options, ['curl', 'stream'])->get($url); } catch (\RuntimeException) { return false; } @@ -810,7 +815,7 @@ protected function downloadPackage($url, $target) * @return boolean * @since 2.5.1 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use "createUpdateFile" instead * Example: $updateModel->createUpdateFile($basename); */ @@ -943,8 +948,6 @@ public function finaliseUpgrade() $installer->extension = new \Joomla\CMS\Table\Extension($db); $installer->extension->load(ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id); - $installer->setAdapter($installer->extension->type); - $installer->setPath('manifest', JPATH_MANIFESTS . '/files/joomla.xml'); $installer->setPath('source', JPATH_MANIFESTS . '/files'); $installer->setPath('extension_root', JPATH_ROOT); @@ -989,7 +992,7 @@ public function finaliseUpgrade() * we can assume that it was (badly) uninstalled. * If it isn't, add an entry to extensions. */ - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('file')) @@ -1256,7 +1259,7 @@ public function upload() $tmp_src = $userfile['tmp_name']; // Move uploaded file. Allow "unsafe" files: the Joomla update package legitimately contains - // PHP, which the File::upload() safety scan (default since joomla/filesystem 3.3.0) would reject. + // PHP, which the File::upload() safety scan (default since joomla/filesystem 4.2.0) would reject. try { File::upload($tmp_src, $tmp_dest, false, true); } catch (FilesystemException $exception) { @@ -1294,11 +1297,7 @@ public function captiveLogin($credentials) $authenticate = Authentication::getInstance(); $response = $authenticate->authenticate($credentials); - if ($response->status !== Authentication::STATUS_SUCCESS) { - return false; - } - - return true; + return $response->status === Authentication::STATUS_SUCCESS; } /** @@ -1312,11 +1311,7 @@ public function captiveFileExists() { $file = Factory::getApplication()->getUserState('com_joomlaupdate.temp_file', null); - if (empty($file) || !is_file($file)) { - return false; - } - - return true; + return !empty($file) && is_file($file); } /** @@ -1427,33 +1422,37 @@ public function getPhpOptions() $option->notice = $option->state ? null : Text::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_DATABASE_NOT_SUPPORTED_NOTICE'); $options[] = $option; - // Check if the Joomla 5 backwards compatibility plugin is disabled - $plugin = ExtensionHelper::getExtensionRecord('compat', 'plugin', 0, 'behaviour'); - - $this->translateExtensionName($plugin); - - $option = new \stdClass(); - $option->state = !PluginHelper::isEnabled('behaviour', 'compat'); - $option->label = $option->state - ? $plugin->name - : Text::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_DISABLED_TITLE', $plugin->name); - $option->notice = $option->state - ? null - : Text::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_DISABLED_NOTICE', $plugin->name, $plugin->folder, $plugin->element); - $options[] = $option; + // Check if the backwards compatibility plugin of current Joomla major version is disabled + $plugin = ExtensionHelper::getExtensionRecord('compat' . Version::MAJOR_VERSION, 'plugin', 0, 'behaviour'); + + if ($plugin) { + $this->translateExtensionName($plugin); + + $option = new \stdClass(); + $option->state = !PluginHelper::isEnabled($plugin->folder, $plugin->element); + $option->label = $option->state + ? $plugin->name + : Text::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_DISABLED_TITLE', $plugin->name); + $option->notice = $option->state + ? null + : Text::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_DISABLED_NOTICE', $plugin->name, $plugin->folder, $plugin->element); + $options[] = $option; + } - // Check if the Joomla 6 backwards compatibility plugin is enabled - $plugin = ExtensionHelper::getExtensionRecord('compat6', 'plugin', 0, 'behaviour'); + // Check if the backwards compatibility plugin of next Joomla major version is enabled + $plugin = ExtensionHelper::getExtensionRecord('compat' . (Version::MAJOR_VERSION + 1), 'plugin', 0, 'behaviour'); - $this->translateExtensionName($plugin); + if ($plugin) { + $this->translateExtensionName($plugin); - $option = new \stdClass(); - $option->state = PluginHelper::isEnabled('behaviour', 'compat6'); - $option->label = $option->state - ? $plugin->name - : Text::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_ENABLED_TITLE', $plugin->name); - $option->notice = $option->state ? null : Text::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_ENABLED_NOTICE', $plugin->folder, $plugin->element); - $options[] = $option; + $option = new \stdClass(); + $option->state = PluginHelper::isEnabled($plugin->folder, $plugin->element); + $option->label = $option->state + ? $plugin->name + : Text::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_ENABLED_TITLE', $plugin->name); + $option->notice = $option->state ? null : Text::sprintf('COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_ENABLED_NOTICE', $plugin->folder, $plugin->element); + $options[] = $option; + } } // Check if database structure is up to date @@ -1680,13 +1679,8 @@ private function getDatabaseSchemaCheck(): bool return false; } - // Check if database schema version does not match CMS version - if ($model->getSchemaVersion($coreExtensionInfo->extension_id) != $changeInformation['schema']) { - return false; - } - - // No database problems found - return true; + // Check if database schema version match CMS version + return $model->getSchemaVersion($coreExtensionInfo->extension_id) === $changeInformation['schema']; } /** @@ -1699,7 +1693,7 @@ private function getDatabaseSchemaCheck(): bool public function getNonCoreExtensions() { $db = version_compare(JVERSION, '4.2.0', 'lt') ? $this->getDbo() : $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ @@ -1747,7 +1741,7 @@ public function getNonCoreExtensions() public function getNonCorePlugins($folderFilter = ['system', 'user', 'authentication', 'actionlog', 'multifactorauth']) { $db = version_compare(JVERSION, '4.2.0', 'lt') ? $this->getDbo() : $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( $db->quoteName('ex.name') . ', ' . @@ -1794,7 +1788,7 @@ public function getNonCorePlugins($folderFilter = ['system', 'user', 'authentica } /** - * Called by controller's fetchExtensionCompatibility, which is called via AJAX. + * Called by controller's batchextensioncompatibility, which is called via AJAX. * * @param string $extensionID The ID of the checked extension * @param string $joomlaTargetVersion Target version of Joomla @@ -1859,7 +1853,7 @@ private function getUpdateSitesInfo($extensionID) { $id = (int) $extensionID; $db = version_compare(JVERSION, '4.2.0', 'lt') ? $this->getDbo() : $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ @@ -1911,7 +1905,10 @@ private function getCollectionDetailsUrls($updateSiteInfo, $joomlaTargetVersion) { $return = []; - $http = new Http(); + $options = new Registry(); + $options->set('userAgent', (new Version())->getUserAgent('Joomla', true, false)); + + $http = (new HttpFactory())->getHttp($options); try { $response = $http->get($updateSiteInfo['location']); @@ -2005,7 +2002,7 @@ private function checkCompatibility($updateFileUrl, $joomlaTargetVersion) * * @return void * - * @since 5.4.8 + * @since 6.1.3 */ private function reportCompatibilityUpdateSiteFailure(array $updateSiteInfo, \Throwable $exception): void { @@ -2100,7 +2097,7 @@ protected function translateExtensionName(&$item) public function isTemplateActive($template) { $db = version_compare(JVERSION, '4.2.0', 'lt') ? $this->getDbo() : $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( $db->quoteName( @@ -2129,7 +2126,7 @@ function ($value) { $menu = false; if (\count($ids)) { - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( 'COUNT(*)' @@ -2437,7 +2434,7 @@ public function resetUpdateSource() $params = $params->toString(); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__extensions')) ->set($db->quoteName('params') . ' = :params') ->where($db->quoteName('type') . ' = ' . $db->quote('component')) diff --git a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/noupdate.php b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/noupdate.php index 5f7bcef919994..b19882347dd41 100644 --- a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/noupdate.php +++ b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/noupdate.php @@ -47,7 +47,7 @@ 'textPrefix' => 'COM_JOOMLAUPDATE' . $this->messagePrefix, 'content' => $reasonNoDownload . Text::sprintf($this->langKey, $this->updateSourceKey), 'formURL' => 'index.php?option=com_joomlaupdate&view=joomlaupdate', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Updating_from_an_existing_version', + 'helpURL' => 'https://guide.joomla.org/user-manual/migration', 'icon' => 'icon-loop joomlaupdate', 'createURL' => 'index.php?option=com_joomlaupdate&task=update.purge&' . Session::getFormToken() . '=1' ]; diff --git a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/preupdatecheck.php b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/preupdatecheck.php index 8101f06c2d1e3..9797d65c4d922 100644 --- a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/preupdatecheck.php +++ b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/preupdatecheck.php @@ -16,9 +16,8 @@ use Joomla\CMS\Router\Route; use Joomla\CMS\Uri\Uri; use Joomla\CMS\Version; -use Joomla\Component\Joomlaupdate\Administrator\View\Joomlaupdate\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Joomlaupdate\Administrator\View\Joomlaupdate\HtmlView $this */ /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->getDocument()->getWebAssetManager(); diff --git a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/reinstall.php b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/reinstall.php index 8e402929e3680..b770ca600a3f9 100644 --- a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/reinstall.php +++ b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/reinstall.php @@ -28,7 +28,7 @@ 'textPrefix' => 'COM_JOOMLAUPDATE_REINSTALL', 'content' => Text::sprintf($this->langKey, $this->updateSourceKey), 'formURL' => 'index.php?option=com_joomlaupdate&view=joomlaupdate', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Updating_from_an_existing_version', + 'helpURL' => 'https://guide.joomla.org/user-manual/migration', 'icon' => 'icon-loop joomlaupdate', 'createURL' => '#' ]; diff --git a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/selfupdate.php b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/selfupdate.php index 52044361cb0b2..4b05ae8e9bb50 100644 --- a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/selfupdate.php +++ b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/selfupdate.php @@ -15,7 +15,7 @@ $displayData = [ 'textPrefix' => 'COM_JOOMLAUPDATE_SELF', 'formURL' => 'index.php?option=com_joomlaupdate&view=joomlaupdate', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Updating_from_an_existing_version', + 'helpURL' => 'https://guide.joomla.org/user-manual/migration', 'icon' => 'icon-loop joomlaupdate', 'createURL' => 'index.php?option=com_installer&view=update' ]; diff --git a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/update.php b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/update.php index d316daba2266f..8719f09dc4e6b 100644 --- a/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/update.php +++ b/administrator/components/com_joomlaupdate/tmpl/joomlaupdate/update.php @@ -29,7 +29,7 @@ 'title' => Text::sprintf('COM_JOOMLAUPDATE_UPDATE_EMPTYSTATE_TITLE', $this->escape($this->updateInfo['latest'])), 'content' => Text::sprintf($this->langKey, $this->updateSourceKey), 'formURL' => 'index.php?option=com_joomlaupdate&view=joomlaupdate', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Updating_from_an_existing_version', + 'helpURL' => 'https://guide.joomla.org/user-manual/migration', 'icon' => 'icon-loop joomlaupdate', 'createURL' => '#' ]; diff --git a/administrator/components/com_joomlaupdate/tmpl/update/default.php b/administrator/components/com_joomlaupdate/tmpl/update/default.php index 898a647e62433..dac13c3f840c3 100644 --- a/administrator/components/com_joomlaupdate/tmpl/update/default.php +++ b/administrator/components/com_joomlaupdate/tmpl/update/default.php @@ -45,7 +45,7 @@ $password = Factory::getApplication()->getUserState('com_joomlaupdate.password', null); $filesize = Factory::getApplication()->getUserState('com_joomlaupdate.filesize', null); $ajaxUrl = Uri::base() . 'components/com_joomlaupdate/extract.php'; -$returnUrl = 'index.php?option=com_joomlaupdate&task=update.finalise&' . Factory::getSession()->getFormToken() . '=1'; +$returnUrl = 'index.php?option=com_joomlaupdate&task=update.finalise&' . Factory::getApplication()->getSession()->getFormToken() . '=1'; $this->getDocument()->addScriptOptions( 'joomlaupdate', diff --git a/administrator/components/com_joomlaupdate/tmpl/upload/default.php b/administrator/components/com_joomlaupdate/tmpl/upload/default.php index 1626462d8d430..8f54385b0e0bf 100644 --- a/administrator/components/com_joomlaupdate/tmpl/upload/default.php +++ b/administrator/components/com_joomlaupdate/tmpl/upload/default.php @@ -14,9 +14,8 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Updater\Update; use Joomla\CMS\Utility\Utility; -use Joomla\Component\Joomlaupdate\Administrator\View\Joomlaupdate\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Joomlaupdate\Administrator\View\Upload\HtmlView $this */ /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->getDocument()->getWebAssetManager(); diff --git a/administrator/components/com_languages/config.xml b/administrator/components/com_languages/config.xml index 89b9af7140712..c2f4fabe59fc2 100644 --- a/administrator/components/com_languages/config.xml +++ b/administrator/components/com_languages/config.xml @@ -1,6 +1,44 @@ +
+ + +
+ + + + + +
app->setUserState($context . '.data', null); $this->setRedirect(Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false)); } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 6.1.0 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + $append = parent::getRedirectToItemAppend($recordId, $urlVar); + + $filterLanguage = $this->input->get('filter_language', '', 'cmd'); + + if ($filterLanguage !== '') { + $append .= '&filter_language=' . $filterLanguage; + } + + $filterClient = $this->input->get('filter_client', null, 'int'); + + if ($filterClient !== null) { + $append .= '&filter_client=' . $filterClient; + } + + $sourceKey = $this->input->get('source_key', '', 'cmd'); + + if ($sourceKey !== '') { + $append .= '&source_key=' . rawurlencode($sourceKey); + } + + $sourceLanguage = $this->input->get('source_language', '', 'cmd'); + + if ($sourceLanguage !== '') { + $append .= '&source_language=' . $sourceLanguage; + } + + $sourceText = $this->input->getString('source_text', ''); + + if ($sourceText !== '') { + $append .= '&source_text=' . rawurlencode($sourceText); + } + + return $append; + } } diff --git a/administrator/components/com_languages/src/Helper/MultilangstatusHelper.php b/administrator/components/com_languages/src/Helper/MultilangstatusHelper.php index 1923d723313de..b06b599f480d7 100644 --- a/administrator/components/com_languages/src/Helper/MultilangstatusHelper.php +++ b/administrator/components/com_languages/src/Helper/MultilangstatusHelper.php @@ -36,7 +36,7 @@ public static function getHomes() { // Check for multiple Home pages. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__menu')) ->where( @@ -61,7 +61,7 @@ public static function getLangswitchers() { // Check if switcher is published. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__modules')) ->where( @@ -86,7 +86,7 @@ public static function getContentlangs() { // Check for published Content Languages. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('lang_code'), @@ -110,7 +110,7 @@ public static function getStatus() { // Check for combined status. $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select all fields from the languages table. $query->select( @@ -156,7 +156,7 @@ public static function getContacts() $languages = \count(LanguageHelper::getLanguages()); // Get the number of contact with all as language - $alang = $db->getQuery(true) + $alang = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__contact_details', 'cd')) ->where( @@ -168,7 +168,7 @@ public static function getContacts() ); // Get the number of languages for the contact - $slang = $db->getQuery(true) + $slang = $db->createQuery() ->select('COUNT(DISTINCT ' . $db->quoteName('l.lang_code') . ')') ->from($db->quoteName('#__languages', 'l')) ->join('LEFT', $db->quoteName('#__contact_details', 'cd'), $db->quoteName('cd.language') . ' = ' . $db->quoteName('l.lang_code')) @@ -181,7 +181,7 @@ public static function getContacts() ); // Get the number of multiple contact/language - $mlang = $db->getQuery(true) + $mlang = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__languages', 'l')) ->join('LEFT', $db->quoteName('#__contact_details', 'cd'), $db->quoteName('cd.language') . ' = ' . $db->quoteName('l.lang_code')) @@ -196,12 +196,12 @@ public static function getContacts() ->having('COUNT(*) > 1'); // Get the contacts - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('1') ->from($db->quoteName('#__content', 'c')) ->where($db->quoteName('c.created_by') . ' = ' . $db->quoteName('u.id')); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('u.name'), @@ -251,7 +251,7 @@ public static function getDefaultHomeModule() { // Find Default Home menutype. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('menutype')) ->from($db->quoteName('#__menu')) ->where( @@ -311,7 +311,7 @@ public static function getModule($moduleName, $instanceTitle = null) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('id'), diff --git a/administrator/components/com_languages/src/Model/InstalledModel.php b/administrator/components/com_languages/src/Model/InstalledModel.php index 950d735508294..9f33139c5205d 100644 --- a/administrator/components/com_languages/src/Model/InstalledModel.php +++ b/administrator/components/com_languages/src/Model/InstalledModel.php @@ -17,7 +17,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; use Joomla\Filesystem\Folder; use Joomla\Utilities\ArrayHelper; @@ -288,7 +288,7 @@ public function publish($cid) $params = ComponentHelper::getParams('com_languages'); $params->set($client->name, $cid); - $table = Table::getInstance('extension', 'Joomla\\CMS\\Table\\'); + $table = new Extension($this->getDatabase()); $id = $table->find(['element' => 'com_languages']); // Load. diff --git a/administrator/components/com_languages/src/Model/LanguageModel.php b/administrator/components/com_languages/src/Model/LanguageModel.php index 5c191be729218..5ae98e8ac1828 100644 --- a/administrator/components/com_languages/src/Model/LanguageModel.php +++ b/administrator/components/com_languages/src/Model/LanguageModel.php @@ -12,12 +12,15 @@ use Joomla\CMS\Application\ApplicationHelper; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\Model\BeforeSaveEvent; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\AdminModel; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Table\Language; use Joomla\CMS\Table\Table; use Joomla\Utilities\ArrayHelper; @@ -70,7 +73,7 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) */ public function getTable($name = '', $prefix = '', $options = []) { - return Table::getInstance('Language', 'Joomla\\CMS\\Table\\'); + return new Language($this->getDatabase()); } /** @@ -127,7 +130,7 @@ public function getItem($langId = null) } $properties = $table->getProperties(1); - $value = ArrayHelper::toObject($properties, CMSObject::class); + $value = ArrayHelper::toObject($properties); return $value; } @@ -138,20 +141,14 @@ public function getItem($langId = null) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|bool A Form object on success, false on failure. + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_languages.language', 'language', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_languages.language', 'language', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -189,7 +186,8 @@ public function save($data) $langId = (!empty($data['lang_id'])) ? $data['lang_id'] : (int) $this->getState('language.id'); $isNew = true; - PluginHelper::importPlugin($this->events_map['save']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['save'], null, true, $dispatcher); $table = $this->getTable(); $context = $this->option . '.' . $this->name; @@ -237,7 +235,15 @@ public function save($data) } // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, [$context, &$table, $isNew]); + $result = $dispatcher->dispatch( + $this->event_before_save, + new BeforeSaveEvent($this->event_before_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ]) + )->getArgument('result', []); // Check the event responses. if (\in_array(false, $result, true)) { @@ -254,7 +260,15 @@ public function save($data) } // Trigger the after save event. - Factory::getApplication()->triggerEvent($this->event_after_save, [$context, &$table, $isNew]); + $dispatcher->dispatch( + $this->event_after_save, + new AfterSaveEvent($this->event_after_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ]) + ); $this->setState('language.id', $table->lang_id); @@ -267,15 +281,13 @@ public function save($data) /** * Custom clean cache method. * - * @param string $group Optional cache group name. - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 1.6 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { parent::cleanCache('_system'); parent::cleanCache('com_languages'); diff --git a/administrator/components/com_languages/src/Model/LanguagesModel.php b/administrator/components/com_languages/src/Model/LanguagesModel.php index bd2a894d108af..8793360280deb 100644 --- a/administrator/components/com_languages/src/Model/LanguagesModel.php +++ b/administrator/components/com_languages/src/Model/LanguagesModel.php @@ -13,7 +13,7 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Language; use Joomla\Database\ParameterType; use Joomla\Database\QueryInterface; @@ -113,7 +113,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select all fields from the languages table. $query->select( @@ -182,7 +182,9 @@ protected function getListQuery() */ public function setPublished($cid, $value = 0) { - return Table::getInstance('Language', 'Joomla\\CMS\\Table\\')->publish($cid, $value); + $table = new Language($this->getDatabase()); + + return $table->publish($cid, $value); } /** @@ -200,7 +202,7 @@ public function delete($pks) $pks = (array) $pks; // Get a row instance. - $table = Table::getInstance('Language', 'Joomla\\CMS\\Table\\'); + $table = new Language($this->getDatabase()); // Iterate the items to delete each one. foreach ($pks as $itemId) { @@ -220,15 +222,13 @@ public function delete($pks) /** * Custom clean cache method, 2 places for 2 clients. * - * @param string $group Optional cache group name. - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 1.6 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { parent::cleanCache('_system'); parent::cleanCache('com_languages'); diff --git a/administrator/components/com_languages/src/Model/OverrideModel.php b/administrator/components/com_languages/src/Model/OverrideModel.php index ed8d5f5131384..222c553dd010c 100644 --- a/administrator/components/com_languages/src/Model/OverrideModel.php +++ b/administrator/components/com_languages/src/Model/OverrideModel.php @@ -11,6 +11,7 @@ namespace Joomla\Component\Languages\Administrator\Model; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Language; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; @@ -34,19 +35,16 @@ class OverrideModel extends AdminModel * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|bool A Form object on success, false on failure. + * @return Form A Form object * * @since 2.5 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_languages.override', 'override', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - $client = $this->getState('filter.client', 'site'); $language = $this->getState('filter.language', 'en-GB'); $langName = Language::getInstance($language)->getName(); @@ -74,12 +72,40 @@ public function getForm($data = [], $loadData = true) protected function loadFormData() { // Check the session for previously entered form data. - $data = Factory::getApplication()->getUserState('com_languages.edit.override.data', []); + $data = Factory::getApplication()->getUserState('com_languages.edit.override.data', []); + $input = Factory::getApplication()->getInput(); if (empty($data)) { $data = $this->getItem(); } + $currentKey = \is_object($data) ? ($data->key ?? '') : ($data['key'] ?? ''); + $currentOverride = \is_object($data) ? ($data->override ?? '') : ($data['override'] ?? ''); + + if ($currentKey === '') { + $sourceKey = $input->get('source_key', '', 'cmd'); + + if ($sourceKey !== '') { + if (\is_object($data)) { + $data->key = $sourceKey; + } else { + $data['key'] = $sourceKey; + } + } + } + + if ($currentOverride === '') { + $sourceText = $input->getString('source_text', ''); + + if ($sourceText !== '') { + if (\is_object($data)) { + $data->override = $sourceText; + } else { + $data['override'] = $sourceText; + } + } + } + $this->preprocessData('com_languages.override', $data); return $data; diff --git a/administrator/components/com_languages/src/Model/OverridesModel.php b/administrator/components/com_languages/src/Model/OverridesModel.php index 63092bcc64358..a01051911589b 100644 --- a/administrator/components/com_languages/src/Model/OverridesModel.php +++ b/administrator/components/com_languages/src/Model/OverridesModel.php @@ -115,6 +115,59 @@ public function getOverrides($all = false) return $this->cache[$store]; } + /** + * Retrieves overrides for all installed languages for the current client. + * + * @return array + * + * @since 6.1.0 + */ + public function getLanguageOverrides() + { + $store = $this->getStoreId('languageOverrides'); + + if (!empty($this->cache[$store])) { + return $this->cache[$store]; + } + + $client = strtoupper($this->getState('filter.client')); + $languages = $this->getLanguages(); + $overrides = []; + $basePath = \constant('JPATH_' . $client) . '/language/overrides/'; + + foreach ($languages as $tag => $language) { + $fileName = $basePath . $tag . '.override.ini'; + $overrides[$tag] = LanguageHelper::parseIniFile($fileName); + } + + $this->cache[$store] = $overrides; + + return $this->cache[$store]; + } + + /** + * Retrieves installed languages for the current client. + * + * @return array + * + * @since 6.1.0 + */ + public function getLanguages() + { + $store = $this->getStoreId('languages'); + + if (!empty($this->cache[$store])) { + return $this->cache[$store]; + } + + $client = strtoupper($this->getState('filter.client')); + $path = \constant('JPATH_' . $client); + + $this->cache[$store] = LanguageHelper::getKnownLanguages($path); + + return $this->cache[$store]; + } + /** * Method to get the total number of overrides. * diff --git a/administrator/components/com_languages/src/Model/StringsModel.php b/administrator/components/com_languages/src/Model/StringsModel.php index 0ffbd2de50420..06fb9df16ba91 100644 --- a/administrator/components/com_languages/src/Model/StringsModel.php +++ b/administrator/components/com_languages/src/Model/StringsModel.php @@ -51,7 +51,7 @@ public function refresh() } // Create the insert query. - $query = $db->getQuery(true) + $query = $db->createQuery() ->insert($db->quoteName('#__overrider')) ->columns( [ @@ -142,7 +142,7 @@ public function search() $searchstring = '%' . $filter->clean($searchTerm, 'TRIM') . '%'; // Create the search query. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('constant'), diff --git a/administrator/components/com_languages/src/Rule/DisallowQuotesRule.php b/administrator/components/com_languages/src/Rule/DisallowQuotesRule.php index 1b9f00a12adc0..c0988372a0de0 100644 --- a/administrator/components/com_languages/src/Rule/DisallowQuotesRule.php +++ b/administrator/components/com_languages/src/Rule/DisallowQuotesRule.php @@ -24,7 +24,7 @@ * The DisallowQuotesRule Class. * Validates that non-superadmins can not use quotes or doublequotes in i18n overrides * - * @since joomla 5.4.7 + * @since joomla 6.1.2 */ class DisallowQuotesRule extends FormRule { diff --git a/administrator/components/com_languages/src/View/Installed/HtmlView.php b/administrator/components/com_languages/src/View/Installed/HtmlView.php index 865fbe5f6fce0..3413acbd2f80e 100644 --- a/administrator/components/com_languages/src/View/Installed/HtmlView.php +++ b/administrator/components/com_languages/src/View/Installed/HtmlView.php @@ -95,6 +95,11 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_languages/src/View/Language/HtmlView.php b/administrator/components/com_languages/src/View/Language/HtmlView.php index 1ec3be4a03421..09d9fe9c18538 100644 --- a/administrator/components/com_languages/src/View/Language/HtmlView.php +++ b/administrator/components/com_languages/src/View/Language/HtmlView.php @@ -77,6 +77,10 @@ public function display($tpl = null) $this->state = $model->getState(); $this->canDo = ContentHelper::getActions('com_languages'); + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); } diff --git a/administrator/components/com_languages/src/View/Languages/HtmlView.php b/administrator/components/com_languages/src/View/Languages/HtmlView.php index 282680011f8fe..cf3dfecf1b6a1 100644 --- a/administrator/components/com_languages/src/View/Languages/HtmlView.php +++ b/administrator/components/com_languages/src/View/Languages/HtmlView.php @@ -87,6 +87,11 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_languages/src/View/Override/HtmlView.php b/administrator/components/com_languages/src/View/Override/HtmlView.php index b945582f7c14a..903d9ab803755 100644 --- a/administrator/components/com_languages/src/View/Override/HtmlView.php +++ b/administrator/components/com_languages/src/View/Override/HtmlView.php @@ -96,6 +96,11 @@ public function display($tpl = null) Text::script('COM_LANGUAGES_VIEW_OVERRIDE_NO_RESULTS'); Text::script('COM_LANGUAGES_VIEW_OVERRIDE_REQUEST_ERROR'); + // Add form control fields + $this->form + ->addControlField('task') + ->addControlField('id', $this->item->key); + $this->addToolbar(); parent::display($tpl); } diff --git a/administrator/components/com_languages/src/View/Overrides/HtmlView.php b/administrator/components/com_languages/src/View/Overrides/HtmlView.php index 6a7da3bddbe69..a54906fd4f3b3 100644 --- a/administrator/components/com_languages/src/View/Overrides/HtmlView.php +++ b/administrator/components/com_languages/src/View/Overrides/HtmlView.php @@ -11,6 +11,7 @@ namespace Joomla\Component\Languages\Administrator\View\Overrides; use Joomla\CMS\Helper\ContentHelper; +use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; use Joomla\CMS\Toolbar\ToolbarHelper; @@ -59,6 +60,22 @@ class HtmlView extends BaseHtmlView */ protected $languages; + /** + * Holds overrides indexed by language tag. + * + * @var array + * @since 6.1.0 + */ + protected $languageOverrides; + + /** + * Holds content languages data keyed by language tag. + * + * @var array + * @since 6.1.0 + */ + protected $contentLanguages; + /** * Form object for search filters * @@ -88,11 +105,19 @@ public function display($tpl = null) $model = $this->getModel(); $model->setUseExceptions(true); - $this->state = $model->getState(); - $this->items = $model->getOverrides(); - $this->pagination = $model->getPagination(); - $this->filterForm = $model->getFilterForm(); - $this->activeFilters = $model->getActiveFilters(); + $this->state = $model->getState(); + $this->items = $model->getOverrides(); + $this->pagination = $model->getPagination(); + $this->filterForm = $model->getFilterForm(); + $this->activeFilters = $model->getActiveFilters(); + $this->languages = $model->getLanguages(); + $this->languageOverrides = $model->getLanguageOverrides(); + $this->contentLanguages = LanguageHelper::getLanguages('lang_code'); + + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_languages/tmpl/installed/default.php b/administrator/components/com_languages/tmpl/installed/default.php index 02e4a83886341..582b5daa41c3d 100644 --- a/administrator/components/com_languages/tmpl/installed/default.php +++ b/administrator/components/com_languages/tmpl/installed/default.php @@ -135,9 +135,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_languages/tmpl/language/edit.php b/administrator/components/com_languages/tmpl/language/edit.php index 3288093d4fb89..8ddd5db4914c5 100644 --- a/administrator/components/com_languages/tmpl/language/edit.php +++ b/administrator/components/com_languages/tmpl/language/edit.php @@ -83,6 +83,5 @@ - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_languages/tmpl/languages/default.php b/administrator/components/com_languages/tmpl/languages/default.php index b9930320a5626..844dd1fe08147 100644 --- a/administrator/components/com_languages/tmpl/languages/default.php +++ b/administrator/components/com_languages/tmpl/languages/default.php @@ -165,9 +165,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_languages/tmpl/override/edit.php b/administrator/components/com_languages/tmpl/override/edit.php index 6df1ece2e9778..c37c2602107ce 100644 --- a/administrator/components/com_languages/tmpl/override/edit.php +++ b/administrator/components/com_languages/tmpl/override/edit.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -83,10 +82,7 @@
- - - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_languages/tmpl/overrides/default.php b/administrator/components/com_languages/tmpl/overrides/default.php index 66b295bd8c4c3..ad17d212bc2a4 100644 --- a/administrator/components/com_languages/tmpl/overrides/default.php +++ b/administrator/components/com_languages/tmpl/overrides/default.php @@ -23,15 +23,19 @@ $wa->useScript('table.columns') ->useScript('multiselect'); -$client = $this->state->get('filter.client') == 'site' ? Text::_('JSITE') : Text::_('JADMINISTRATOR'); -$language = $this->state->get('filter.language'); -$listOrder = $this->escape($this->state->get('list.ordering')); -$listDirn = $this->escape($this->state->get('list.direction')); +$client = $this->state->get('filter.client') == 'site' ? Text::_('JSITE') : Text::_('JADMINISTRATOR'); +$language = $this->state->get('filter.language'); +$listOrder = $this->escape($this->state->get('list.ordering')); +$listDirn = $this->escape($this->state->get('list.direction')); +$filterClientValue = $this->state->get('filter.client') === 'administrator' ? 1 : 0; $oppositeClient = $this->state->get('filter.client') == 'administrator' ? Text::_('JSITE') : Text::_('JADMINISTRATOR'); $oppositeFilename = constant('JPATH_' . strtoupper($this->state->get('filter.client') === 'site' ? 'administrator' : 'site')) . '/language/overrides/' . $this->state->get('filter.language', 'en-GB') . '.override.ini'; $oppositeStrings = LanguageHelper::parseIniFile($oppositeFilename); +$languageOverrides = $this->languageOverrides ?? []; +$installedLanguages = $this->languages ?? []; +$contentLanguages = $this->contentLanguages ?? []; ?>
@@ -69,10 +73,17 @@ + + + + + + getCurrentUser()->authorise('core.edit', 'com_languages'); ?> + getCurrentUser()->authorise('core.create', 'com_languages'); ?> items as $key => $text) : ?> @@ -101,6 +112,63 @@ endif; ?> + $langData) : + if ($tag === $language) : + continue; + endif; + + $hasOverride = isset($languageOverrides[$tag][$key]); + $contentLanguage = $contentLanguages[$tag] ?? null; + $languageTitle = $contentLanguage->title ?? ($langData['nativeName'] ?? $langData['name'] ?? $tag); + + $query = [ + 'option' => 'com_languages', + 'task' => $hasOverride ? 'override.edit' : 'override.add', + 'filter_language' => $tag, + 'filter_client' => $filterClientValue, + 'source_language' => $language, + 'source_key' => $key, + ]; + + if ($hasOverride) { + $query['id'] = $key; + } else { + $query['source_text'] = $text; + } + + $link = ($hasOverride && $canEdit) || (!$hasOverride && $canCreate) + ? Route::_('index.php?' . http_build_query($query, '', '&', PHP_QUERY_RFC3986)) + : ''; + $title = $hasOverride + ? Text::sprintf('COM_LANGUAGES_VIEW_OVERRIDES_EXISTS', $languageTitle) + : Text::sprintf('COM_LANGUAGES_VIEW_OVERRIDES_CREATE', $languageTitle); + $badgeClass = $hasOverride ? 'badge bg-secondary' : 'badge bg-warning'; + + $badgeHtml = $link + ? '' . $this->escape($tag) . '' + : '' . $this->escape($tag) . ''; + + if ($hasOverride) { + $translatedBadges[] = $badgeHtml; + } else { + $untranslatedBadges[] = $badgeHtml; + } + endforeach; + ?> + +
+ +
+ + +
+ +
+ @@ -112,9 +180,7 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_login/src/Model/LoginModel.php b/administrator/components/com_login/src/Model/LoginModel.php index 3ee47f7e6810e..6b67eff495238 100644 --- a/administrator/components/com_login/src/Model/LoginModel.php +++ b/administrator/components/com_login/src/Model/LoginModel.php @@ -139,7 +139,7 @@ protected static function _load($module) $loader = function () use ($app, $lang, $module) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( $db->quoteName( [ diff --git a/administrator/components/com_mails/src/Field/MailtemplateLayoutField.php b/administrator/components/com_mails/src/Field/MailtemplateLayoutField.php index 4d43928dcba33..3a351d257d86c 100644 --- a/administrator/components/com_mails/src/Field/MailtemplateLayoutField.php +++ b/administrator/components/com_mails/src/Field/MailtemplateLayoutField.php @@ -50,7 +50,7 @@ protected function getInput() // Get the database object and a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Build the query. $query->select('element, name') diff --git a/administrator/components/com_mails/src/Model/TemplateModel.php b/administrator/components/com_mails/src/Model/TemplateModel.php index 10ef8e8b0d3f7..6251622911d5b 100644 --- a/administrator/components/com_mails/src/Model/TemplateModel.php +++ b/administrator/components/com_mails/src/Model/TemplateModel.php @@ -11,13 +11,16 @@ namespace Joomla\Component\Mails\Administrator\Model; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\Model\BeforeSaveEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\AdminModel; -use Joomla\CMS\Object\CMSObject; +use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Table\Table; +use Joomla\Database\ParameterType; use Joomla\Filesystem\Path; use Joomla\Registry\Registry; use Joomla\Utilities\ArrayHelper; @@ -49,39 +52,22 @@ class TemplateModel extends AdminModel */ public $typeAlias = 'com_mails.template'; - /** - * Method to test whether a record can be deleted. - * - * @param object $record A record object. - * - * @return boolean True if allowed to delete the record. Defaults to the permission set in the component. - * - * @since 4.0.0 - */ - protected function canDelete($record) - { - return false; - } - /** * Method to get the record form. * * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 4.0.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_mails.template', 'template', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - $params = ComponentHelper::getParams('com_mails'); if ($params->get('mail_style', 'plaintext') == 'plaintext') { @@ -176,9 +162,9 @@ public function getItem($pk = null) } } - // Convert to the CMSObject before adding other data. + // Convert to an object before adding other data. $properties = $table->getProperties(1); - $item = ArrayHelper::toObject($properties, CMSObject::class); + $item = ArrayHelper::toObject($properties); if (property_exists($item, 'params')) { $registry = new Registry($item->params); @@ -222,9 +208,9 @@ public function getMaster($pk = null) } } - // Convert to the CMSObject before adding other data. + // Convert to an object before adding other data. $properties = $table->getProperties(1); - $item = ArrayHelper::toObject($properties, CMSObject::class); + $item = ArrayHelper::toObject($properties); if (property_exists($item, 'params')) { $registry = new Registry($item->params); @@ -317,7 +303,8 @@ public function save($data) $isNew = true; // Include the plugins for the save events. - \Joomla\CMS\Plugin\PluginHelper::importPlugin($this->events_map['save']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['save'], null, true, $dispatcher); // Allow an exception to be thrown. try { @@ -349,7 +336,12 @@ public function save($data) } // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, [$context, $table, $isNew, $data]); + $result = $dispatcher->dispatch($this->event_before_save, new BeforeSaveEvent($this->event_before_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ]))->getArgument('result', []); if (\in_array(false, $result, true)) { $this->setError($table->getError()); @@ -368,7 +360,12 @@ public function save($data) $this->cleanCache(); // Trigger the after save event. - Factory::getApplication()->triggerEvent($this->event_after_save, [$context, $table, $isNew, $data]); + $dispatcher->dispatch($this->event_after_save, new AfterSaveEvent($this->event_after_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ])); } catch (\Exception $e) { $this->setError($e->getMessage()); @@ -410,4 +407,29 @@ protected function populateState() $language = Factory::getApplication()->getInput()->getCmd('language'); $this->setState($this->getName() . '.language', $language); } + + /** + * Method to delete one or more records. + * + * @param array &$pks An array of record primary keys. + * + * @return boolean True if successful, false if an error occurs. + * + * @since 1.6 + */ + public function delete(&$pks) + { + $pks = (array)$pks; + foreach ($pks as $i => $pk) { + if (!$this->canDelete((object)['template_id' => $pk])) { + return false; + } + } + + $db = $this->getDatabase(); + $query = $db->createQuery(); + $query->delete($db->quoteName('#__mail_templates')) + ->whereIn($db->quoteName('template_id'), $pks, ParameterType::STRING); + return $db->setQuery($query)->execute(); + } } diff --git a/administrator/components/com_mails/src/Model/TemplatesModel.php b/administrator/components/com_mails/src/Model/TemplatesModel.php index ac28287c4483b..1fddea2c6f5c0 100644 --- a/administrator/components/com_mails/src/Model/TemplatesModel.php +++ b/administrator/components/com_mails/src/Model/TemplatesModel.php @@ -91,7 +91,7 @@ public function getItems() $id = ''; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('language')) ->from($db->quoteName('#__mail_templates')) ->where($db->quoteName('template_id') . ' = :id') @@ -119,7 +119,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( @@ -155,7 +155,7 @@ protected function getListQuery() ->bind(':extension', $extension); } else { // Only show mail template from enabled extensions - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select($db->quoteName('name')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('enabled') . ' = 1'); @@ -193,12 +193,12 @@ protected function getListQuery() public function getExtensions() { $db = $this->getDatabase(); - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select($db->quoteName('name')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('enabled') . ' = 1'); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('extension')) ->from($db->quoteName('#__mail_templates')) ->where($db->quoteName('extension') . ' IN (' . $subQuery . ')'); diff --git a/administrator/components/com_mails/src/View/Template/HtmlView.php b/administrator/components/com_mails/src/View/Template/HtmlView.php index dac94d2f5240c..accb985c9518e 100644 --- a/administrator/components/com_mails/src/View/Template/HtmlView.php +++ b/administrator/components/com_mails/src/View/Template/HtmlView.php @@ -13,7 +13,6 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Toolbar\ToolbarHelper; use Joomla\Component\Mails\Administrator\Helper\MailsHelper; use Joomla\Component\Mails\Administrator\Model\TemplateModel; @@ -60,7 +59,7 @@ class HtmlView extends BaseHtmlView /** * Master data for the mail template * - * @var CMSObject + * @var \stdClass */ protected $master; @@ -112,6 +111,11 @@ public function display($tpl = null) } } + // Add form control fields + $this->form + ->addControlField('task') + ->addControlField('return', Factory::getApplication()->getInput()->get('return', '', 'BASE64')); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_mails/src/View/Templates/HtmlView.php b/administrator/components/com_mails/src/View/Templates/HtmlView.php index d3bc86c5c0c9d..17caf61596334 100644 --- a/administrator/components/com_mails/src/View/Templates/HtmlView.php +++ b/administrator/components/com_mails/src/View/Templates/HtmlView.php @@ -119,6 +119,11 @@ public function display($tpl = null) MailsHelper::loadTranslationFiles($extension, $currentLanguageTag); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_mails/tmpl/template/edit.php b/administrator/components/com_mails/tmpl/template/edit.php index 5cd1385fb84a5..b39f2fc828af1 100644 --- a/administrator/components/com_mails/tmpl/template/edit.php +++ b/administrator/components/com_mails/tmpl/template/edit.php @@ -116,7 +116,6 @@ form->renderField('template_id'); ?> form->renderField('language'); ?> - - - + + form->renderControlFields(); ?>
diff --git a/administrator/components/com_mails/tmpl/templates/default.php b/administrator/components/com_mails/tmpl/templates/default.php index 86690895985b8..b0d56a46f35a1 100644 --- a/administrator/components/com_mails/tmpl/templates/default.php +++ b/administrator/components/com_mails/tmpl/templates/default.php @@ -113,9 +113,7 @@ pagination->getListFooter(); ?> - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_media/helpers/media.php b/administrator/components/com_media/helpers/media.php index 6e9aa05cd81fd..57f5788769644 100644 --- a/administrator/components/com_media/helpers/media.php +++ b/administrator/components/com_media/helpers/media.php @@ -10,8 +10,6 @@ * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace */ -use Joomla\CMS\Object\CMSObject; - // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects @@ -26,26 +24,24 @@ abstract class MediaHelper /** * Generates the URL to the object in the action logs component * - * @param string $contentType The content type - * @param integer $id The integer id - * @param CMSObject $mediaObject The media object being uploaded + * @param string $contentType The content type + * @param integer $id The integer id + * @param \stdClass $mediaObject The media object being uploaded * * @return string The link for the action log * * @since 3.9.27 */ - public static function getContentTypeLink($contentType, $id, CMSObject $mediaObject) + public static function getContentTypeLink($contentType, $id, \stdClass $mediaObject) { if ($contentType === 'com_media.file') { return ''; } - $link = 'index.php?option=com_media'; - $adapter = $mediaObject->get('adapter'); - $uploadedPath = $mediaObject->get('path'); + $link = 'index.php?option=com_media'; - if (!empty($adapter) && !empty($uploadedPath)) { - $link .= '&path=' . $adapter . ':' . $uploadedPath; + if (!empty($mediaObject->adapter) && !empty($mediaObject->path)) { + $link .= '&path=' . $mediaObject->adapter . ':' . $mediaObject->path; } return $link; diff --git a/administrator/components/com_media/src/Controller/PluginController.php b/administrator/components/com_media/src/Controller/PluginController.php index b97b636fdeb71..38f145e5bd717 100644 --- a/administrator/components/com_media/src/Controller/PluginController.php +++ b/administrator/components/com_media/src/Controller/PluginController.php @@ -59,14 +59,15 @@ public function oauthcallback() } // Only import our required plugin, not entire group - PluginHelper::importPlugin('filesystem', $pluginName); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('filesystem', $pluginName, true, $dispatcher); // Event parameters $eventParameters = ['context' => $pluginName, 'input' => $this->input]; $event = new OAuthCallbackEvent('onFileSystemOAuthCallback', $eventParameters); // Get results from event - $eventResults = (array) $this->app->triggerEvent('onFileSystemOAuthCallback', $event); + $eventResults = (array) $dispatcher->dispatch('onFileSystemOAuthCallback', $event)->getArgument('result', []); // If event was not triggered in the selected Plugin, raise a warning and fallback to Control Panel if (!$eventResults) { diff --git a/administrator/components/com_media/src/Model/ApiModel.php b/administrator/components/com_media/src/Model/ApiModel.php index d98f24e0cf1fa..07f15808faa54 100644 --- a/administrator/components/com_media/src/Model/ApiModel.php +++ b/administrator/components/com_media/src/Model/ApiModel.php @@ -11,10 +11,13 @@ namespace Joomla\Component\Media\Administrator\Model; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Model\AfterDeleteEvent; +use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\Model\BeforeDeleteEvent; +use Joomla\CMS\Event\Model\BeforeSaveEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\BaseDatabaseModel; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Component\Media\Administrator\Event\FetchMediaItemEvent; use Joomla\Component\Media\Administrator\Event\FetchMediaItemsEvent; @@ -146,7 +149,7 @@ public function getFiles($adapter, $path = '/', $options = []) $files = array_values($files); $event = new FetchMediaItemsEvent('onFetchMediaItems', ['items' => $files]); - Factory::getApplication()->getDispatcher()->dispatch($event->getName(), $event); + $this->getDispatcher()->dispatch($event->getName(), $event); return $event->getArgument('items'); } @@ -179,15 +182,20 @@ public function createFolder($adapter, $name, $path, $override) throw new FileExistsException(); } - $app = Factory::getApplication(); - $object = new CMSObject(); + $object = new \stdClass(); $object->adapter = $adapter; $object->name = $name; $object->path = $path; - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); - $result = $app->triggerEvent('onContentBeforeSave', ['com_media.folder', $object, true, $object]); + $result = $dispatcher->dispatch('onContentBeforeSave', new BeforeSaveEvent('onContentBeforeSave', [ + 'context' => 'com_media.folder', + 'subject' => $object, + 'isNew' => true, + 'data' => $object, + ]))->getArgument('result', []); if (\in_array(false, $result, true)) { throw new \Exception($object->getError()); @@ -195,7 +203,12 @@ public function createFolder($adapter, $name, $path, $override) $object->name = $this->getAdapter($object->adapter)->createFolder($object->name, $object->path); - $app->triggerEvent('onContentAfterSave', ['com_media.folder', $object, true, $object]); + $dispatcher->dispatch('onContentAfterSave', new AfterSaveEvent('onContentAfterSave', [ + 'context' => 'com_media.folder', + 'subject' => $object, + 'isNew' => true, + 'data' => $object, + ])); return $object->name; } @@ -234,20 +247,25 @@ public function createFile($adapter, $name, $path, $data, $override) throw new InvalidPathException(Text::_('JLIB_MEDIA_ERROR_WARNFILETYPE')); } - $app = Factory::getApplication(); - $object = new CMSObject(); + $object = new \stdClass(); $object->adapter = $adapter; $object->name = $name; $object->path = $path; $object->data = $data; $object->extension = strtolower(File::getExt($name)); - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Also include the filesystem plugins, perhaps they support batch processing too - PluginHelper::importPlugin('media-action'); + PluginHelper::importPlugin('media-action', null, true, $dispatcher); - $result = $app->triggerEvent('onContentBeforeSave', ['com_media.file', $object, true, $object]); + $result = $dispatcher->dispatch('onContentBeforeSave', new BeforeSaveEvent('onContentBeforeSave', [ + 'context' => 'com_media.file', + 'subject' => $object, + 'isNew' => true, + 'data' => $object, + ]))->getArgument('result', []); if (\in_array(false, $result, true)) { throw new \Exception($object->getError()); @@ -255,7 +273,12 @@ public function createFile($adapter, $name, $path, $data, $override) $object->name = $this->getAdapter($object->adapter)->createFile($object->name, $object->path, $object->data); - $app->triggerEvent('onContentAfterSave', ['com_media.file', $object, true, $object]); + $dispatcher->dispatch('onContentAfterSave', new AfterSaveEvent('onContentAfterSave', [ + 'context' => 'com_media.file', + 'subject' => $object, + 'isNew' => true, + 'data' => $object, + ])); return $object->name; } @@ -282,20 +305,25 @@ public function updateFile($adapter, $name, $path, $data) throw new InvalidPathException(); } - $app = Factory::getApplication(); - $object = new CMSObject(); + $object = new \stdClass(); $object->adapter = $adapter; $object->name = $name; $object->path = $path; $object->data = $data; $object->extension = strtolower(File::getExt($name)); - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Also include the filesystem plugins, perhaps they support batch processing too - PluginHelper::importPlugin('media-action'); + PluginHelper::importPlugin('media-action', null, true, $dispatcher); - $result = $app->triggerEvent('onContentBeforeSave', ['com_media.file', $object, false, $object]); + $result = $dispatcher->dispatch('onContentBeforeSave', new BeforeSaveEvent('onContentBeforeSave', [ + 'context' => 'com_media.file', + 'subject' => $object, + 'isNew' => false, + 'data' => $object, + ]))->getArgument('result', []); if (\in_array(false, $result, true)) { throw new \Exception($object->getError()); @@ -303,7 +331,12 @@ public function updateFile($adapter, $name, $path, $data) $this->getAdapter($object->adapter)->updateFile($object->name, $object->path, $object->data); - $app->triggerEvent('onContentAfterSave', ['com_media.file', $object, false, $object]); + $dispatcher->dispatch('onContentAfterSave', new AfterSaveEvent('onContentAfterSave', [ + 'context' => 'com_media.file', + 'subject' => $object, + 'isNew' => false, + 'data' => $object, + ])); } /** @@ -329,17 +362,20 @@ public function delete($adapter, $path) } $type = $file->type === 'file' ? 'file' : 'folder'; - $app = Factory::getApplication(); - $object = new CMSObject(); + $object = new \stdClass(); $object->adapter = $adapter; $object->path = $path; - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Also include the filesystem plugins, perhaps they support batch processing too - PluginHelper::importPlugin('media-action'); + PluginHelper::importPlugin('media-action', null, true, $dispatcher); - $result = $app->triggerEvent('onContentBeforeDelete', ['com_media.' . $type, $object]); + $result = $dispatcher->dispatch('onContentBeforeDelete', new BeforeDeleteEvent('onContentBeforeDelete', [ + 'context' => 'com_media.' . $type, + 'subject' => $object, + ]))->getArgument('result', []); if (\in_array(false, $result, true)) { throw new \Exception($object->getError()); @@ -347,7 +383,10 @@ public function delete($adapter, $path) $this->getAdapter($object->adapter)->delete($object->path); - $app->triggerEvent('onContentAfterDelete', ['com_media.' . $type, $object]); + $dispatcher->dispatch('onContentAfterDelete', new AfterDeleteEvent('onContentAfterDelete', [ + 'context' => 'com_media.' . $type, + 'subject' => $object, + ])); } /** diff --git a/administrator/components/com_media/src/Model/FileModel.php b/administrator/components/com_media/src/Model/FileModel.php index 4404350924182..2005ec2382084 100644 --- a/administrator/components/com_media/src/Model/FileModel.php +++ b/administrator/components/com_media/src/Model/FileModel.php @@ -10,6 +10,7 @@ namespace Joomla\Component\Media\Administrator\Model; +use Joomla\CMS\Form\Form; use Joomla\CMS\Form\FormHelper; use Joomla\CMS\MVC\Model\FormModel; use Joomla\CMS\Plugin\PluginHelper; @@ -31,9 +32,10 @@ class FileModel extends FormModel * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 4.0.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -43,13 +45,7 @@ public function getForm($data = [], $loadData = true) FormHelper::addFormPath(JPATH_ADMINISTRATOR . '/components/com_media/forms'); // Get the form. - $form = $this->loadForm('com_media.file', 'file', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_media.file', 'file', ['control' => 'jform', 'load_data' => $loadData]); } /** diff --git a/administrator/components/com_media/src/Provider/ProviderManagerHelperTrait.php b/administrator/components/com_media/src/Provider/ProviderManagerHelperTrait.php index 863aad4e01c09..da7cc7980c491 100644 --- a/administrator/components/com_media/src/Provider/ProviderManagerHelperTrait.php +++ b/administrator/components/com_media/src/Provider/ProviderManagerHelperTrait.php @@ -17,6 +17,7 @@ use Joomla\Component\Media\Administrator\Adapter\AdapterInterface; use Joomla\Component\Media\Administrator\Event\MediaProviderEvent; use Joomla\Component\Media\Administrator\Exception\ProviderAccountNotFoundException; +use Joomla\Event\DispatcherInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -61,7 +62,7 @@ public function getProviderManager(): ProviderManager $eventParameters = ['context' => 'AdapterManager', 'providerManager' => new ProviderManager()]; $event = new MediaProviderEvent('onSetupProviders', $eventParameters); PluginHelper::importPlugin('filesystem'); - Factory::getApplication()->triggerEvent('onSetupProviders', $event); + Factory::getContainer()->get(DispatcherInterface::class)->dispatch('onSetupProviders', $event); $this->providerManager = $event->getProviderManager(); } diff --git a/administrator/components/com_menus/forms/item.xml b/administrator/components/com_menus/forms/item.xml index 3bef3c301d8e2..db58e1cd3cd7a 100644 --- a/administrator/components/com_menus/forms/item.xml +++ b/administrator/components/com_menus/forms/item.xml @@ -1,5 +1,8 @@
+ + +
- - @@ -576,7 +569,7 @@ type="url" target="_blank" title="MOD_MENU_HELP_DOCUMENTATION" - link="https://docs.joomla.org" + link="https://guide.joomla.org" scope="help" /> diff --git a/administrator/components/com_menus/presets/default.xml b/administrator/components/com_menus/presets/default.xml index 2683557626ce5..b4a1c6ce40659 100644 --- a/administrator/components/com_menus/presets/default.xml +++ b/administrator/components/com_menus/presets/default.xml @@ -37,14 +37,6 @@ quicktask="index.php?option=com_categories&extension=com_content&task=category.add" /> - - load($association->id); diff --git a/administrator/components/com_menus/src/Field/MenuItemByComponentField.php b/administrator/components/com_menus/src/Field/MenuItemByComponentField.php index 929a5cf40c714..53068e1c67648 100644 --- a/administrator/components/com_menus/src/Field/MenuItemByComponentField.php +++ b/administrator/components/com_menus/src/Field/MenuItemByComponentField.php @@ -43,7 +43,7 @@ protected function getOptions() $db = $this->getDatabase(); $options = []; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select('DISTINCT ' . $db->quoteName('extensions.element')) ->from($db->quoteName('#__menu', 'menu')) ->join( diff --git a/administrator/components/com_menus/src/Field/MenuItemByTypeField.php b/administrator/components/com_menus/src/Field/MenuItemByTypeField.php index b61f54500888f..7399a0de3fb12 100644 --- a/administrator/components/com_menus/src/Field/MenuItemByTypeField.php +++ b/administrator/components/com_menus/src/Field/MenuItemByTypeField.php @@ -188,7 +188,7 @@ protected function getGroups() if ($menuType) { // If the menutype is empty, group the items by menutype. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__menu_types')) ->where($db->quoteName('menutype') . ' = :menuType') diff --git a/administrator/components/com_menus/src/Field/MenuOrderingField.php b/administrator/components/com_menus/src/Field/MenuOrderingField.php index 63009de9eaadb..c3af813e96a58 100644 --- a/administrator/components/com_menus/src/Field/MenuOrderingField.php +++ b/administrator/components/com_menus/src/Field/MenuOrderingField.php @@ -54,7 +54,7 @@ protected function getOptions() } $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('a.id', 'value'), diff --git a/administrator/components/com_menus/src/Field/MenuParentField.php b/administrator/components/com_menus/src/Field/MenuParentField.php index 432293e6c6970..4bd84e2a93fab 100644 --- a/administrator/components/com_menus/src/Field/MenuParentField.php +++ b/administrator/components/com_menus/src/Field/MenuParentField.php @@ -46,7 +46,7 @@ protected function getOptions() $options = []; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ 'DISTINCT ' . $db->quoteName('a.id', 'value'), diff --git a/administrator/components/com_menus/src/Field/Modal/MenuField.php b/administrator/components/com_menus/src/Field/Modal/MenuField.php index 683583a150444..f86ce5e4364b1 100644 --- a/administrator/components/com_menus/src/Field/Modal/MenuField.php +++ b/administrator/components/com_menus/src/Field/Modal/MenuField.php @@ -241,7 +241,7 @@ protected function getValueTitle() if ($value) { try { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__menu')) ->where($db->quoteName('id') . ' = :id') diff --git a/administrator/components/com_menus/src/Helper/AssociationsHelper.php b/administrator/components/com_menus/src/Helper/AssociationsHelper.php index e7cb3817d68b8..be9560f3562a0 100644 --- a/administrator/components/com_menus/src/Helper/AssociationsHelper.php +++ b/administrator/components/com_menus/src/Helper/AssociationsHelper.php @@ -11,7 +11,9 @@ namespace Joomla\Component\Menus\Administrator\Helper; use Joomla\CMS\Association\AssociationExtensionHelper; +use Joomla\CMS\Factory; use Joomla\CMS\Language\Associations; +use Joomla\CMS\Table\Menu; use Joomla\CMS\Table\Table; // phpcs:disable PSR1.Files.SideEffects @@ -117,7 +119,7 @@ public function getItem($typeName, $id) switch ($typeName) { case 'item': - $table = Table::getInstance('menu'); + $table = new Menu(Factory::getDbo()); break; } diff --git a/administrator/components/com_menus/src/Helper/MenusHelper.php b/administrator/components/com_menus/src/Helper/MenusHelper.php index 1e9261698cf3d..57c2d81dd3044 100644 --- a/administrator/components/com_menus/src/Helper/MenusHelper.php +++ b/administrator/components/com_menus/src/Helper/MenusHelper.php @@ -19,7 +19,7 @@ use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Language\Text; use Joomla\CMS\Menu\AdministratorMenuItem; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Menu; use Joomla\Database\DatabaseInterface; use Joomla\Database\ParameterType; use Joomla\Filesystem\File; @@ -106,9 +106,10 @@ public static function getLinkKey($request) public static function getMenuTypes($clientId = 0) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('a.menutype')) - ->from($db->quoteName('#__menu_types', 'a')); + ->from($db->quoteName('#__menu_types', 'a')) + ->order($db->quoteName('ordering')); if (isset($clientId)) { $clientId = (int) $clientId; @@ -142,7 +143,7 @@ public static function getMenuLinks($menuType = null, $parentId = 0, $mode = 0, $clientId = (int) $clientId; $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ 'DISTINCT ' . $db->quoteName('a.id', 'value'), @@ -217,13 +218,13 @@ public static function getMenuLinks($menuType = null, $parentId = 0, $mode = 0, if (empty($menuType)) { // If the menutype is empty, group the items by menutype. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__menu_types')) ->where($db->quoteName('menutype') . ' <> ' . $db->quote('')) ->order( [ - $db->quoteName('title'), + $db->quoteName('ordering'), $db->quoteName('menutype'), ] ); @@ -302,7 +303,7 @@ public static function getMenuItems($menutype, $enabledOnly = false, $exclude = { $root = new AdministratorMenuItem(); $db = Factory::getContainer()->get(DatabaseInterface::class); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Prepare the query. $query->select($db->quoteName('m') . '.*') @@ -428,7 +429,7 @@ public static function installPreset($preset, $menutype) protected static function installPresetItems($node, $menutype) { $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $items = $node->getChildren(); static $components = []; @@ -455,8 +456,7 @@ protected static function installPresetItems($node, $menutype) ]))->getArgument('subject', $items); foreach ($items as $item) { - /** @var \Joomla\CMS\Table\Menu $table */ - $table = Table::getInstance('Menu'); + $table = new Menu($db); $item->alias = $menutype . '-' . $item->title; @@ -509,7 +509,7 @@ protected static function installPresetItems($node, $menutype) } } - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->whereIn($db->quoteName('component_id'), $hideitems); @@ -697,7 +697,7 @@ public static function resolveAlias(&$item) $aliasTo = (int) $obj->getParams()->get('aliasoptions'); $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ $db->quoteName('a.id'), @@ -790,7 +790,7 @@ protected static function loadXml($elements, $parent, $replace = []) $iJoin = (string) $element['sql_innerjoin']; $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($select)->from($from); if ($where) { diff --git a/administrator/components/com_menus/src/Model/ItemModel.php b/administrator/components/com_menus/src/Model/ItemModel.php index 756a26e94ccb0..418ed43c5125b 100644 --- a/administrator/components/com_menus/src/Model/ItemModel.php +++ b/administrator/components/com_menus/src/Model/ItemModel.php @@ -12,6 +12,8 @@ use Joomla\CMS\Application\ApplicationHelper; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\Model\BeforeSaveEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Associations; @@ -157,7 +159,7 @@ protected function batchCopy($value, $pks, $contexts) $table = $this->getTable(); $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $newIds = []; // Check that the parent exists @@ -234,7 +236,7 @@ protected function batchCopy($value, $pks, $contexts) } // Copy is a bit tricky, because we also need to copy the children - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->where( @@ -409,7 +411,7 @@ protected function batchMove($value, $pks, $contexts) // Check if we are moving to a different menu if ($menuType != $table->menutype) { // Add the child node ids to the children array. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->where($db->quoteName('lft') . ' BETWEEN :lft AND :rgt') @@ -448,7 +450,7 @@ protected function batchMove($value, $pks, $contexts) $children = ArrayHelper::toInteger($children); // Update the menutype field in all nodes where necessary. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__menu')) ->set($db->quoteName('menutype') . ' = :menuType') ->whereIn($db->quoteName('id'), $children) @@ -491,9 +493,10 @@ protected function canSave($data = [], $key = 'id') * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return mixed A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -517,10 +520,6 @@ public function getForm($data = [], $loadData = true) $form = $this->loadForm('com_menus.item', 'item', ['control' => 'jform', 'load_data' => $loadData], true); } - if (empty($form)) { - return false; - } - if ($loadData) { $data = $this->loadFormData(); } @@ -784,7 +783,7 @@ public function getModules() } $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); /** * Join on the module-to-menu mapping table. @@ -808,7 +807,7 @@ public function getModules() . ' AND ' . $db->quoteName('map.menuid') . ' IN (' . implode(',', $query->bindArray([0, $id, -$id])) . ')' ); - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__modules_menu')) ->where( @@ -860,7 +859,7 @@ public function getModules() public function getViewLevels() { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Get all the available view levels $query->select($db->quoteName('id')) @@ -1060,7 +1059,7 @@ protected function getMenuTypeId($menutype) * * @return array An array of menu item objects with id, title, and level properties. * - * @since 5.4.8 + * @since 6.1.3 */ public function getParentItems(string $menutype): array { @@ -1287,7 +1286,7 @@ public function rebuild() { // Initialise variables. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $table = $this->getTable(); try { @@ -1327,7 +1326,7 @@ public function rebuild() return false; } - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__menu')) ->set($db->quoteName('params') . ' = :params') ->where($db->quoteName('id') . ' = :id') @@ -1369,12 +1368,13 @@ public function save($data) $pk = $data['id'] ?? (int) $this->getState('item.id'); $isNew = true; $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $table = $this->getTable(); $context = $this->option . '.' . $this->name; // Include the plugins for the on save events. - PluginHelper::importPlugin($this->events_map['save']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['save'], null, true, $dispatcher); // Load the row if saving an existing item. if ($pk > 0) { @@ -1456,7 +1456,12 @@ public function save($data) } // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, [$context, &$table, $isNew, $data]); + $result = $dispatcher->dispatch($this->event_before_save, new BeforeSaveEvent($this->event_before_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ]))->getArgument('result', []); // Store the data. if (\in_array(false, $result, true) || !$table->store()) { @@ -1466,7 +1471,12 @@ public function save($data) } // Trigger the after save event. - Factory::getApplication()->triggerEvent($this->event_after_save, [$context, &$table, $isNew]); + $dispatcher->dispatch($this->event_after_save, new AfterSaveEvent($this->event_after_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ])); // Rebuild the tree path. if (!$table->rebuildPath($table->id)) { @@ -1489,7 +1499,7 @@ public function save($data) $children = ArrayHelper::toInteger($children); // Update the menutype field in all nodes where necessary. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__menu')) ->set($db->quoteName('menutype') . ' = :menutype') ->whereIn($db->quoteName('id'), $children) @@ -1531,7 +1541,7 @@ public function save($data) // Get associationskey for edited item $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('key')) ->from($db->quoteName('#__associations')) ->where( @@ -1548,7 +1558,7 @@ public function save($data) if ($associations || $oldKey !== null) { // Deleting old associations for the associated items $where = []; - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__associations')) ->where($db->quoteName('context') . ' = :context') ->bind(':context', $this->associationsContext); @@ -1582,7 +1592,7 @@ public function save($data) if (\count($associations) > 1) { // Adding new association for these items $key = md5(json_encode($associations)); - $query = $db->getQuery(true) + $query = $db->createQuery() ->insert($db->quoteName('#__associations')) ->columns( [ @@ -1801,15 +1811,13 @@ protected function generateNewTitle($parentId, $alias, $title) /** * Custom clean the cache * - * @param string $group Cache group name. - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 1.6 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { parent::cleanCache('com_menus'); parent::cleanCache('com_modules'); diff --git a/administrator/components/com_menus/src/Model/ItemsModel.php b/administrator/components/com_menus/src/Model/ItemsModel.php index 8b66b49bbc3ce..ef802abfbc58f 100644 --- a/administrator/components/com_menus/src/Model/ItemsModel.php +++ b/administrator/components/com_menus/src/Model/ItemsModel.php @@ -225,7 +225,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = $this->getCurrentUser(); $clientId = (int) $this->getState('filter.client_id'); @@ -302,7 +302,7 @@ protected function getListQuery() // Join over the associations. if (Associations::isEnabled()) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1') ->from($db->quoteName('#__associations', 'asso1')) ->join('INNER', $db->quoteName('#__associations', 'asso2'), $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key')) @@ -368,7 +368,7 @@ protected function getListQuery() if ($parentId) { // Create a subquery for the sub-items list - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select($db->quoteName('sub.id')) ->from($db->quoteName('#__menu', 'sub')) ->join( @@ -406,7 +406,7 @@ protected function getListQuery() // A value "" means all if ($menuType == '') { // Load all menu types we have manage access - $query2 = $db->getQuery(true) + $query2 = $db->createQuery() ->select( [ $db->quoteName('id'), @@ -416,7 +416,7 @@ protected function getListQuery() ->from($db->quoteName('#__menu_types')) ->where($db->quoteName('client_id') . ' = :clientId') ->bind(':clientId', $clientId, ParameterType::INTEGER) - ->order($db->quoteName('title')); + ->order($db->quoteName('ordering')); // Show protected items on explicit filter only $query->where($db->quoteName('a.menutype') . ' != ' . $db->quote('main')); @@ -518,7 +518,7 @@ protected function preprocessForm(Form $form, $data, $group = 'content') protected function getMenu($menuType, $check = false) { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('a') . '.*') ->from($db->quoteName('#__menu_types', 'a')) diff --git a/administrator/components/com_menus/src/Model/MenuModel.php b/administrator/components/com_menus/src/Model/MenuModel.php index 27f2feee24c41..958949cde8053 100644 --- a/administrator/components/com_menus/src/Model/MenuModel.php +++ b/administrator/components/com_menus/src/Model/MenuModel.php @@ -11,10 +11,13 @@ namespace Joomla\Component\Menus\Administrator\Model; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Model\AfterDeleteEvent; +use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\Model\BeforeDeleteEvent; +use Joomla\CMS\Event\Model\BeforeSaveEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\MVC\Model\AdminModel; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Table\Table; use Joomla\Registry\Registry; @@ -121,7 +124,7 @@ protected function populateState() * * @param integer $itemId The id of the menu item to get. * - * @return mixed Menu item data object on success, false on failure. + * @return \stdClass|false Menu item data object on success, false on failure. * * @since 1.6 */ @@ -143,7 +146,7 @@ public function getItem($itemId = null) } $properties = $table->getProperties(1); - $value = ArrayHelper::toObject($properties, CMSObject::class); + $value = ArrayHelper::toObject($properties); return $value; } @@ -154,19 +157,16 @@ public function getItem($itemId = null) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_menus.menu', 'menu', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - if (!$this->getState('client_id', 0)) { $form->removeField('preset'); } @@ -243,7 +243,8 @@ public function save($data) $table = $this->getTable(); // Include the plugins for the save events. - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Load the row if saving an existing item. if ($id > 0) { @@ -266,7 +267,12 @@ public function save($data) } // Trigger the before event. - $result = Factory::getApplication()->triggerEvent('onContentBeforeSave', [$this->_context, &$table, $isNew, $data]); + $result = $dispatcher->dispatch('onContentBeforeSave', new BeforeSaveEvent('onContentBeforeSave', [ + 'context' => $this->_context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ]))->getArgument('result', []); // Store the data. if (\in_array(false, $result, true) || !$table->store()) { @@ -276,7 +282,12 @@ public function save($data) } // Trigger the after save event. - Factory::getApplication()->triggerEvent('onContentAfterSave', [$this->_context, &$table, $isNew]); + $dispatcher->dispatch('onContentAfterSave', new AfterSaveEvent('onContentAfterSave', [ + 'context' => $this->_context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ])); $this->setState('menu.id', $table->id); @@ -304,13 +315,20 @@ public function delete(&$pks) $table = $this->getTable(); // Include the plugins for the delete events. - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Iterate the items to delete each one. foreach ($itemIds as $itemId) { if ($table->load($itemId)) { // Trigger the before delete event. - $result = Factory::getApplication()->triggerEvent('onContentBeforeDelete', [$this->_context, $table]); + $result = $dispatcher->dispatch( + 'onContentBeforeDelete', + new BeforeDeleteEvent('onContentBeforeDelete', [ + 'context' => $this->_context, + 'subject' => $table, + ]) + )->getArgument('result', []); if (\in_array(false, $result, true) || !$table->delete($itemId)) { $this->setError($table->getError()); @@ -319,7 +337,10 @@ public function delete(&$pks) } // Trigger the after delete event. - Factory::getApplication()->triggerEvent('onContentAfterDelete', [$this->_context, $table]); + $dispatcher->dispatch('onContentAfterDelete', new AfterDeleteEvent('onContentAfterDelete', [ + 'context' => $this->_context, + 'subject' => $table, + ])); // @todo: Delete the menu associations - Menu items and Modules } @@ -342,7 +363,7 @@ public function &getModules() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('a.id'), @@ -388,7 +409,7 @@ public function &getModules() public function getExtensionElementsForMenuItems(array $itemIds): array { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select($db->quoteName('e.element')) @@ -402,15 +423,13 @@ public function getExtensionElementsForMenuItems(array $itemIds): array /** * Custom clean the cache * - * @param string $group Cache group name. - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 1.6 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { parent::cleanCache('com_menus'); parent::cleanCache('com_modules'); diff --git a/administrator/components/com_menus/src/Model/MenusModel.php b/administrator/components/com_menus/src/Model/MenusModel.php index 374ab7f42a4a5..a6e66f3f77ab4 100644 --- a/administrator/components/com_menus/src/Model/MenusModel.php +++ b/administrator/components/com_menus/src/Model/MenusModel.php @@ -84,7 +84,7 @@ public function getItems() $db = $this->getDatabase(); $menuTypes = array_column((array) $items, 'menutype'); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('m.menutype'), @@ -153,7 +153,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $clientId = (int) $this->getState('client_id'); // Select all fields from the table. @@ -231,7 +231,7 @@ public function getModMenuId() { $clientId = (int) $this->getState('client_id'); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('e.extension_id')) ->from($db->quoteName('#__extensions', 'e')) ->where( @@ -287,7 +287,7 @@ public function getMissingModuleLanguages(): array } $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('m.language')) ->from($db->quoteName('#__modules', 'm')) diff --git a/administrator/components/com_menus/src/Model/MenutypesModel.php b/administrator/components/com_menus/src/Model/MenutypesModel.php index 2f9a826a0b0f5..1f3acec65a872 100644 --- a/administrator/components/com_menus/src/Model/MenutypesModel.php +++ b/administrator/components/com_menus/src/Model/MenutypesModel.php @@ -14,7 +14,6 @@ use Joomla\CMS\Event\Menu\AfterGetMenuTypeOptionsEvent; use Joomla\CMS\Factory; use Joomla\CMS\MVC\Model\BaseDatabaseModel; -use Joomla\CMS\Object\CMSObject; use Joomla\Component\Menus\Administrator\Helper\MenusHelper; use Joomla\Filesystem\Folder; @@ -87,7 +86,7 @@ public function getTypeOptions() // Get the list of components. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('name'), @@ -137,7 +136,7 @@ public function getTypeOptions() * Method to create the reverse lookup for link-to-name. * (can be used from onAfterGetMenuTypeOptions handlers) * - * @param CMSObject $option Object with request array or string and title public variables + * @param \stdClass $option Object with request array or string and title public variables * * @return void * @@ -184,7 +183,7 @@ protected function getTypeOptionsByComponent($component) * @param string $file File path * @param string $component Component option as in URL * - * @return array|boolean + * @return \stdClass|boolean * * @since 1.6 */ @@ -207,7 +206,7 @@ protected function getTypeOptionsFromXml($file, $component) // If we have no options to parse, just add the base component to the list of options. if (!empty($menu['options']) && $menu['options'] == 'none') { // Create the menu option for the component. - $o = new CMSObject(); + $o = new \stdClass(); $o->title = (string) $menu['name']; $o->description = (string) $menu['msg']; $o->request = ['option' => $component]; @@ -233,7 +232,7 @@ protected function getTypeOptionsFromXml($file, $component) foreach ($children as $child) { if ($child->getName() == 'option') { // Create the menu option for the component. - $o = new CMSObject(); + $o = new \stdClass(); $o->title = (string) $child['name']; $o->description = (string) $child['msg']; $o->request = ['option' => $component, (string) $optionsNode['var'] => (string) $child['value']]; @@ -241,7 +240,7 @@ protected function getTypeOptionsFromXml($file, $component) $options[] = $o; } elseif ($child->getName() == 'default') { // Create the menu option for the component. - $o = new CMSObject(); + $o = new \stdClass(); $o->title = (string) $child['name']; $o->description = (string) $child['msg']; $o->request = ['option' => $component]; @@ -258,7 +257,7 @@ protected function getTypeOptionsFromXml($file, $component) * * @param string $component Component option like in URLs * - * @return array|boolean + * @return \stdClass[]|boolean * * @since 1.6 */ @@ -307,7 +306,7 @@ protected function getTypeOptionsFromMvc($component) foreach ($children as $child) { if ($child->getName() == 'option') { // Create the menu option for the component. - $o = new CMSObject(); + $o = new \stdClass(); $o->title = (string) $child['name']; $o->description = (string) $child['msg']; $o->request = ['option' => $component, 'view' => $view, (string) $optionsNode['var'] => (string) $child['value']]; @@ -315,7 +314,7 @@ protected function getTypeOptionsFromMvc($component) $options[] = $o; } elseif ($child->getName() == 'default') { // Create the menu option for the component. - $o = new CMSObject(); + $o = new \stdClass(); $o->title = (string) $child['name']; $o->description = (string) $child['msg']; $o->request = ['option' => $component, 'view' => $view]; @@ -345,7 +344,7 @@ protected function getTypeOptionsFromMvc($component) * * @param string $component Component option like in URLs * - * @return array|boolean + * @return \stdClass[]|boolean * * @since 3.7.0 */ @@ -419,7 +418,7 @@ protected function getTypeOptionsFromManifest($component) return \strlen($value); }); - $options[] = new CMSObject($o); + $options[] = $o; // Do not repeat the default view link (index.php?option=com_abc). if (\count($o->request) == 1) { @@ -428,7 +427,7 @@ protected function getTypeOptionsFromManifest($component) } if ($ro) { - $options[] = new CMSObject($ro); + $options[] = $ro; } return $options; @@ -440,7 +439,7 @@ protected function getTypeOptionsFromManifest($component) * @param string $component Component option as in URLs * @param string $view Name of the view * - * @return array + * @return \stdClass[] * * @since 1.6 */ @@ -516,7 +515,7 @@ protected function getTypeOptionsFromLayouts($component, $view) $layout = basename($layout, '.xml'); // Create the menu option for the layout. - $o = new CMSObject(); + $o = new \stdClass(); $o->title = ucfirst($layout); $o->description = ''; $o->request = ['option' => $component, 'view' => $view]; diff --git a/administrator/components/com_menus/src/Service/HTML/Menus.php b/administrator/components/com_menus/src/Service/HTML/Menus.php index 081f6bce55368..4aa3fe7fe9308 100644 --- a/administrator/components/com_menus/src/Service/HTML/Menus.php +++ b/administrator/components/com_menus/src/Service/HTML/Menus.php @@ -52,7 +52,7 @@ public function association($itemid) if ($associations = MenusHelper::getAssociations($itemid)) { // Get the associated menu items $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('m.id'), diff --git a/administrator/components/com_menus/src/Table/MenuTable.php b/administrator/components/com_menus/src/Table/MenuTable.php index 8d4153e514fb2..2056d07e03694 100644 --- a/administrator/components/com_menus/src/Table/MenuTable.php +++ b/administrator/components/com_menus/src/Table/MenuTable.php @@ -42,7 +42,7 @@ public function delete($pk = null, $children = false) if ($return) { // Delete key from the #__modules_menu table $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__modules_menu')) ->where($db->quoteName('menuid') . ' = :pk') ->bind(':pk', $pk, ParameterType::INTEGER); diff --git a/administrator/components/com_menus/src/View/Item/HtmlView.php b/administrator/components/com_menus/src/View/Item/HtmlView.php index 173d95d085125..130395cebb589 100644 --- a/administrator/components/com_menus/src/View/Item/HtmlView.php +++ b/administrator/components/com_menus/src/View/Item/HtmlView.php @@ -131,7 +131,7 @@ public function display($tpl = null) // Add form control fields $this->form - ->addControlField('task', '') + ->addControlField('task') ->addControlField('forcedLanguage', $forcedLanguage) ->addControlField('menutype', $input->get('menutype', '')) ->addControlField('fieldtype', '', ['id' => 'fieldtype']); @@ -233,6 +233,7 @@ function (Toolbar $childBar) use ($isNew, $checkedOut, $canDo) { $url = $help->url; } + $toolbar->inlinehelp(); $toolbar->help($help->key, $help->local, $url); } diff --git a/administrator/components/com_menus/src/View/Items/HtmlView.php b/administrator/components/com_menus/src/View/Items/HtmlView.php index f9454fb5d9447..0b64478528587 100644 --- a/administrator/components/com_menus/src/View/Items/HtmlView.php +++ b/administrator/components/com_menus/src/View/Items/HtmlView.php @@ -290,7 +290,7 @@ public function display($tpl = null) // Add form control fields $this->filterForm - ->addControlField('task', '') + ->addControlField('task') ->addControlField('boxchecked', '0'); // Allow a system plugin to insert dynamic menu types to the list shown in menus: diff --git a/administrator/components/com_menus/src/View/Menu/HtmlView.php b/administrator/components/com_menus/src/View/Menu/HtmlView.php index 9075a8254f5a2..d23c63c941cdb 100644 --- a/administrator/components/com_menus/src/View/Menu/HtmlView.php +++ b/administrator/components/com_menus/src/View/Menu/HtmlView.php @@ -84,7 +84,7 @@ public function display($tpl = null) } // Add form control fields - $this->form->addControlField('task', ''); + $this->form->addControlField('task'); parent::display($tpl); $this->addToolbar(); diff --git a/administrator/components/com_menus/src/View/Menutypes/HtmlView.php b/administrator/components/com_menus/src/View/Menutypes/HtmlView.php index 7061caabc73b6..dae25d49a82d9 100644 --- a/administrator/components/com_menus/src/View/Menutypes/HtmlView.php +++ b/administrator/components/com_menus/src/View/Menutypes/HtmlView.php @@ -13,7 +13,6 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Toolbar\ToolbarHelper; use Joomla\Component\Menus\Administrator\Model\MenutypesModel; @@ -39,7 +38,7 @@ class HtmlView extends BaseHtmlView /** * Array of menu types * - * @var CMSObject[] + * @var \stdClass[] * * @since 3.7.0 */ @@ -140,28 +139,28 @@ protected function addCustomTypes(&$types) // Adding System Links $list = []; - $o = new CMSObject(); + $o = new \stdClass(); $o->title = 'COM_MENUS_TYPE_EXTERNAL_URL'; $o->type = 'url'; $o->description = 'COM_MENUS_TYPE_EXTERNAL_URL_DESC'; $o->request = null; $list[] = $o; - $o = new CMSObject(); + $o = new \stdClass(); $o->title = 'COM_MENUS_TYPE_ALIAS'; $o->type = 'alias'; $o->description = 'COM_MENUS_TYPE_ALIAS_DESC'; $o->request = null; $list[] = $o; - $o = new CMSObject(); + $o = new \stdClass(); $o->title = 'COM_MENUS_TYPE_SEPARATOR'; $o->type = 'separator'; $o->description = 'COM_MENUS_TYPE_SEPARATOR_DESC'; $o->request = null; $list[] = $o; - $o = new CMSObject(); + $o = new \stdClass(); $o->title = 'COM_MENUS_TYPE_HEADING'; $o->type = 'heading'; $o->description = 'COM_MENUS_TYPE_HEADING_DESC'; @@ -169,7 +168,7 @@ protected function addCustomTypes(&$types) $list[] = $o; if ($this->state->get('client_id') == 1) { - $o = new CMSObject(); + $o = new \stdClass(); $o->title = 'COM_MENUS_TYPE_CONTAINER'; $o->type = 'container'; $o->description = 'COM_MENUS_TYPE_CONTAINER_DESC'; diff --git a/administrator/components/com_menus/tmpl/item/edit.php b/administrator/components/com_menus/tmpl/item/edit.php index 34b88ce707969..0cc3d0e36f20b 100644 --- a/administrator/components/com_menus/tmpl/item/edit.php +++ b/administrator/components/com_menus/tmpl/item/edit.php @@ -24,6 +24,11 @@ Text::script('ERROR'); Text::script('JGLOBAL_VALIDATION_FORM_FAILED'); Text::script('JGLOBAL_ROOT_PARENT'); +Text::script('JLIB_JS_AJAX_ERROR_CONNECTION_ABORT'); +Text::script('JLIB_JS_AJAX_ERROR_NO_CONTENT'); +Text::script('JLIB_JS_AJAX_ERROR_OTHER'); +Text::script('JLIB_JS_AJAX_ERROR_PARSE'); +Text::script('JLIB_JS_AJAX_ERROR_TIMEOUT'); $this->getDocument()->addScriptOptions('menu-item', ['itemId' => (int) $this->item->id]); diff --git a/administrator/components/com_menus/tmpl/items/default_batch_body.php b/administrator/components/com_menus/tmpl/items/default_batch_body.php index 266830db1368f..1d431c7886247 100644 --- a/administrator/components/com_menus/tmpl/items/default_batch_body.php +++ b/administrator/components/com_menus/tmpl/items/default_batch_body.php @@ -24,11 +24,12 @@ $published = (int) $this->state->get('filter.published'); $clientId = (int) $this->state->get('filter.client_id'); +/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ +$wa = $this->getDocument()->getWebAssetManager(); +$wa->useScript('joomla.batch-copymove'); + if ($clientId == 1) { - /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ - $wa = $this->getDocument()->getWebAssetManager(); $wa->useScript('com_menus.batch-body'); - $wa->useScript('joomla.batch-copymove'); } ?>
diff --git a/administrator/components/com_menus/tmpl/items/modal.php b/administrator/components/com_menus/tmpl/items/modal.php index 62ade8a302d58..dfe011ba5b96e 100644 --- a/administrator/components/com_menus/tmpl/items/modal.php +++ b/administrator/components/com_menus/tmpl/items/modal.php @@ -30,7 +30,7 @@ $wa = $this->getDocument()->getWebAssetManager(); $wa->useScript('com_menus.admin-items-modal')->useScript('modal-content-select'); -// @todo: Use of Function and Editor is deprecated and should be removed in 6.0. It stays only for backward compatibility. +// @todo: Use of Function and Editor is deprecated and should be removed in 7.0. It stays only for backward compatibility. $function = $app->getInput()->get('function', 'jSelectMenuItem', 'cmd'); $editor = $app->getInput()->getCmd('editor', ''); $listOrder = $this->escape($this->state->get('list.ordering')); diff --git a/administrator/components/com_messages/src/Field/UserMessagesField.php b/administrator/components/com_messages/src/Field/UserMessagesField.php index 939460035fdcb..2f34f01f5f29e 100644 --- a/administrator/components/com_messages/src/Field/UserMessagesField.php +++ b/administrator/components/com_messages/src/Field/UserMessagesField.php @@ -44,7 +44,7 @@ protected function getGroups() { // Compute usergroups $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('id') ->from('#__usergroups'); $db->setQuery($query); diff --git a/administrator/components/com_messages/src/Model/ConfigModel.php b/administrator/components/com_messages/src/Model/ConfigModel.php index 4153c5fe9993f..714616a20b441 100644 --- a/administrator/components/com_messages/src/Model/ConfigModel.php +++ b/administrator/components/com_messages/src/Model/ConfigModel.php @@ -11,9 +11,10 @@ namespace Joomla\Component\Messages\Administrator\Model; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Form\Form; use Joomla\CMS\MVC\Model\FormModel; -use Joomla\CMS\Object\CMSObject; use Joomla\Database\ParameterType; +use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -53,17 +54,17 @@ protected function populateState() /** * Method to get a single record. * - * @return mixed Object on success, false on failure. + * @return \stdClass|false Object on success, false on failure. * * @since 1.6 */ public function getItem() { - $item = new CMSObject(); + $item = new Registry(); $userid = (int) $this->getState('user.id'); $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ $db->quoteName('cfg_name'), @@ -86,7 +87,7 @@ public function getItem() foreach ($rows as $row) { $property = $row->cfg_name; - $item->$property = $row->cfg_value; + $item->set($property, $row->cfg_value); } $this->preprocessData('com_messages.config', $item); @@ -100,20 +101,14 @@ public function getItem() * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_messages.config', 'config', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_messages.config', 'config', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -130,7 +125,7 @@ public function save($data) $db = $this->getDatabase(); if ($userId = (int) $this->getState('user.id')) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__messages_cfg')) ->where($db->quoteName('user_id') . ' = :userid') ->bind(':userid', $userId, ParameterType::INTEGER); @@ -145,7 +140,7 @@ public function save($data) } if (\count($data)) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->insert($db->quoteName('#__messages_cfg')) ->columns( [ diff --git a/administrator/components/com_messages/src/Model/MessageModel.php b/administrator/components/com_messages/src/Model/MessageModel.php index 6d071dd75dc21..a3d910fbfd785 100644 --- a/administrator/components/com_messages/src/Model/MessageModel.php +++ b/administrator/components/com_messages/src/Model/MessageModel.php @@ -14,15 +14,19 @@ use Joomla\CMS\Access\Rule; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Language; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\Mail\Exception\MailDisabledException; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Router\Route; use Joomla\CMS\Table\Asset; -use Joomla\CMS\Table\Table; use Joomla\CMS\User\User; use Joomla\CMS\User\UserFactoryAwareInterface; use Joomla\CMS\User\UserFactoryAwareTrait; @@ -38,9 +42,11 @@ * * @since 1.6 */ -class MessageModel extends AdminModel implements UserFactoryAwareInterface +class MessageModel extends AdminModel implements UserFactoryAwareInterface, MailerFactoryAwareInterface, LanguageFactoryAwareInterface { use UserFactoryAwareTrait; + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; /** * Message @@ -144,7 +150,7 @@ public function getItem($pk = null) if ($replyId = (int) $this->getState('reply.id')) { // If replying to a message, preload some data. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['subject', 'user_id_from', 'user_id_to'])) ->from($db->quoteName('#__messages')) ->where($db->quoteName('message_id') . ' = :messageid') @@ -164,11 +170,12 @@ public function getItem($pk = null) return false; } - $this->item->set('user_id_to', $message->user_id_from); + $this->item->user_id_to = $message->user_id_from; + $re = Text::_('COM_MESSAGES_RE'); if (stripos($message->subject, $re) !== 0) { - $this->item->set('subject', $re . ' ' . $message->subject); + $this->item->subject = $re . ' ' . $message->subject; } } } elseif ($this->item->user_id_to != $this->getCurrentUser()->id) { @@ -178,7 +185,7 @@ public function getItem($pk = null) } else { // Mark message read $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__messages')) ->set($db->quoteName('state') . ' = 1') ->where($db->quoteName('message_id') . ' = :messageid') @@ -189,7 +196,7 @@ public function getItem($pk = null) // Get the user name for an existing message. if ($this->item->user_id_from && $fromUser = new User($this->item->user_id_from)) { - $this->item->set('from_user_name', $fromUser->name); + $this->item->from_user_name = $fromUser->name; } } @@ -202,20 +209,14 @@ public function getItem($pk = null) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_messages.message', 'message', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_messages.message', 'message', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -378,7 +379,12 @@ public function save($data) $message = strip_tags(html_entity_decode($table->message, ENT_COMPAT, 'UTF-8')); // Send the email - $mailer = new MailTemplate('com_messages.new_message', $lang->getTag()); + $mailer = new MailTemplate( + 'com_messages.new_message', + $lang->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $data = [ 'subject' => $subject, 'message' => $message, @@ -426,8 +432,7 @@ public function notifySuperUsers($subject, $message, $fromUser = null) $db = $this->getDatabase(); try { - /** @var Asset $table */ - $table = Table::getInstance('Asset'); + $table = new Asset($db); $rootId = $table->getRootId(); /** @var Rule[] $rules */ @@ -454,7 +459,7 @@ public function notifySuperUsers($subject, $message, $fromUser = null) return false; } - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('map.user_id')) ->from($db->quoteName('#__user_usergroup_map', 'map')) ->join( diff --git a/administrator/components/com_messages/src/Model/MessagesModel.php b/administrator/components/com_messages/src/Model/MessagesModel.php index 76dacc7e90503..2479d3497d13b 100644 --- a/administrator/components/com_messages/src/Model/MessagesModel.php +++ b/administrator/components/com_messages/src/Model/MessagesModel.php @@ -108,7 +108,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = $this->getCurrentUser(); $id = (int) $user->id; @@ -179,7 +179,7 @@ protected function getListQuery() public function purge(int $userId): void { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['cfg_name', 'cfg_value'])) ->from($db->quoteName('#__messages_cfg')) ->where( @@ -206,7 +206,7 @@ public function purge(int $userId): void // Purge old messages at day set in message configuration $past = Factory::getDate(time() - $purge * 86400)->toSql(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__messages')) ->where( [ diff --git a/administrator/components/com_messages/src/View/Config/HtmlView.php b/administrator/components/com_messages/src/View/Config/HtmlView.php index abb53a485e360..e3d2ce6938fd9 100644 --- a/administrator/components/com_messages/src/View/Config/HtmlView.php +++ b/administrator/components/com_messages/src/View/Config/HtmlView.php @@ -70,6 +70,10 @@ public function display($tpl = null) // Bind the record to the form. $this->form->bind($this->item); + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_messages/src/View/Message/HtmlView.php b/administrator/components/com_messages/src/View/Message/HtmlView.php index cb75bb39d2d5b..305c255dbc1e9 100644 --- a/administrator/components/com_messages/src/View/Message/HtmlView.php +++ b/administrator/components/com_messages/src/View/Message/HtmlView.php @@ -76,6 +76,10 @@ public function display($tpl = null) throw new GenericDataException(Text::_('JERROR_ALERTNOAUTHOR'), 403); } + // Add form control fields + $this->form + ->addControlField('task'); + parent::display($tpl); $this->addToolbar(); } diff --git a/administrator/components/com_messages/src/View/Messages/HtmlView.php b/administrator/components/com_messages/src/View/Messages/HtmlView.php index 5e897d6d3c430..ed2d8d9b8e307 100644 --- a/administrator/components/com_messages/src/View/Messages/HtmlView.php +++ b/administrator/components/com_messages/src/View/Messages/HtmlView.php @@ -98,6 +98,11 @@ public function display($tpl = null) $this->setLayout('emptystate'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_messages/tmpl/config/default.php b/administrator/components/com_messages/tmpl/config/default.php index a366045716225..9cdf2f65105a9 100644 --- a/administrator/components/com_messages/tmpl/config/default.php +++ b/administrator/components/com_messages/tmpl/config/default.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -36,6 +35,5 @@
- - + form->renderControlFields(); ?> diff --git a/administrator/components/com_messages/tmpl/message/default.php b/administrator/components/com_messages/tmpl/message/default.php index 9d0a626586d3e..dbec384a36b3c 100644 --- a/administrator/components/com_messages/tmpl/message/default.php +++ b/administrator/components/com_messages/tmpl/message/default.php @@ -33,7 +33,7 @@
-
item->get('from_user_name'); ?>
+
item->from_user_name; ?>
item->date_time, Text::_('DATE_FORMAT_LC2')); ?>
diff --git a/administrator/components/com_messages/tmpl/message/edit.php b/administrator/components/com_messages/tmpl/message/edit.php index ac0fe33e81b54..35ef50855f078 100644 --- a/administrator/components/com_messages/tmpl/message/edit.php +++ b/administrator/components/com_messages/tmpl/message/edit.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -41,6 +40,6 @@
- - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_messages/tmpl/messages/default.php b/administrator/components/com_messages/tmpl/messages/default.php index f79eb7488bdd7..abf0723a9c2c2 100644 --- a/administrator/components/com_messages/tmpl/messages/default.php +++ b/administrator/components/com_messages/tmpl/messages/default.php @@ -89,10 +89,7 @@ pagination->getListFooter(); ?> -
- - - -
+ + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_messages/tmpl/messages/emptystate.php b/administrator/components/com_messages/tmpl/messages/emptystate.php index 5b4eb77cbdf61..362c22b6aa95d 100644 --- a/administrator/components/com_messages/tmpl/messages/emptystate.php +++ b/administrator/components/com_messages/tmpl/messages/emptystate.php @@ -19,6 +19,8 @@ 'formURL' => 'index.php?option=com_messages&view=messages', 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Private_Messages', 'icon' => 'icon-envelope inbox', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; if ( diff --git a/administrator/components/com_modules/config.xml b/administrator/components/com_modules/config.xml index 3d758260108c7..cd14b9b6f2548 100644 --- a/administrator/components/com_modules/config.xml +++ b/administrator/components/com_modules/config.xml @@ -19,6 +19,28 @@
+ + + + + + +
COM_MODULES_HEADING_PAGES_DESC + + diff --git a/administrator/components/com_modules/forms/module.xml b/administrator/components/com_modules/forms/module.xml index 7207d5976e2fd..0f4c00a6ac94e 100644 --- a/administrator/components/com_modules/forms/module.xml +++ b/administrator/components/com_modules/forms/module.xml @@ -4,14 +4,6 @@
- - + + + +
- - + + + + set(AssociationExtensionInterface::class, new AssociationsHelper()); + $container->registerServiceProvider(new MVCFactory('\\Joomla\\Component\\Modules')); $container->registerServiceProvider(new ComponentDispatcherFactory('\\Joomla\\Component\\Modules')); @@ -45,8 +49,9 @@ public function register(Container $container) function (Container $container) { $component = new ModulesComponent($container->get(ComponentDispatcherFactoryInterface::class)); - $component->setMVCFactory($container->get(MVCFactoryInterface::class)); $component->setRegistry($container->get(Registry::class)); + $component->setMVCFactory($container->get(MVCFactoryInterface::class)); + $component->setAssociationExtension($container->get(AssociationExtensionInterface::class)); return $component; } diff --git a/administrator/components/com_modules/src/Controller/ModuleController.php b/administrator/components/com_modules/src/Controller/ModuleController.php index f6b14678e9f69..6a480a9e31deb 100644 --- a/administrator/components/com_modules/src/Controller/ModuleController.php +++ b/administrator/components/com_modules/src/Controller/ModuleController.php @@ -18,6 +18,7 @@ use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; use Joomla\CMS\Uri\Uri; +use Joomla\CMS\Versioning\VersionableControllerTrait; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -30,6 +31,8 @@ */ class ModuleController extends FormController { + use VersionableControllerTrait; + /** * Override parent add method. * @@ -149,11 +152,7 @@ protected function allowEdit($data = [], $key = 'id') } // Check edit on the record asset (explicit or inherited) - if ($this->app->getIdentity()->authorise('core.edit', 'com_modules.module.' . $recordId)) { - return true; - } - - return false; + return $this->app->getIdentity()->authorise('core.edit', 'com_modules.module.' . $recordId); } /** @@ -232,7 +231,7 @@ public function save($key = null, $urlVar = null) $model = $this->getModel(); $data = $this->input->post->get('jform', [], 'array'); $item = $model->getItem($this->input->get('id')); - $properties = $item->getProperties(); + $properties = get_object_vars($item); if (isset($data['params'])) { unset($properties['params']); diff --git a/administrator/components/com_modules/src/Extension/ModulesComponent.php b/administrator/components/com_modules/src/Extension/ModulesComponent.php index 2fb82863c7921..6de089d1cf44f 100644 --- a/administrator/components/com_modules/src/Extension/ModulesComponent.php +++ b/administrator/components/com_modules/src/Extension/ModulesComponent.php @@ -10,10 +10,13 @@ namespace Joomla\Component\Modules\Administrator\Extension; +use Joomla\CMS\Association\AssociationServiceInterface; +use Joomla\CMS\Association\AssociationServiceTrait; use Joomla\CMS\Extension\BootableExtensionInterface; use Joomla\CMS\Extension\MVCComponent; use Joomla\CMS\HTML\HTMLRegistryAwareTrait; use Joomla\Component\Modules\Administrator\Service\HTML\Modules; +use Joomla\Database\DatabaseInterface; use Psr\Container\ContainerInterface; // phpcs:disable PSR1.Files.SideEffects @@ -25,8 +28,9 @@ * * @since 4.0.0 */ -class ModulesComponent extends MVCComponent implements BootableExtensionInterface +class ModulesComponent extends MVCComponent implements BootableExtensionInterface, AssociationServiceInterface { + use AssociationServiceTrait; use HTMLRegistryAwareTrait; /** @@ -44,6 +48,9 @@ class ModulesComponent extends MVCComponent implements BootableExtensionInterfac */ public function boot(ContainerInterface $container) { - $this->getRegistry()->register('modules', new Modules()); + $modules = new Modules(); + $modules->setDatabase($container->get(DatabaseInterface::class)); + + $this->getRegistry()->register('modules', $modules); } } diff --git a/administrator/components/com_modules/src/Field/Modal/ModuleField.php b/administrator/components/com_modules/src/Field/Modal/ModuleField.php new file mode 100644 index 0000000000000..62e20f86b5586 --- /dev/null +++ b/administrator/components/com_modules/src/Field/Modal/ModuleField.php @@ -0,0 +1,239 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Modules\Administrator\Field\Modal; + +use Joomla\CMS\Factory; +use Joomla\CMS\Form\Field\ModalSelectField; +use Joomla\CMS\Form\FormField; +use Joomla\CMS\Language\LanguageHelper; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Layout\FileLayout; +use Joomla\CMS\Session\Session; +use Joomla\CMS\Uri\Uri; +use Joomla\Database\ParameterType; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Supports a modal menu item picker. + * + * @since 6.1.0 + */ +class ModuleField extends ModalSelectField +{ + /** + * The form field type. + * + * @var string + * @since 6.1.0 + */ + protected $type = 'Modal_Module'; + + + /** + * Method to attach a Form object to the field. + * + * @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 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]". + * + * @return boolean True on success. + * + * @see FormField::setup() + * @since 6.1.0 + */ + public function setup(\SimpleXMLElement $element, $value, $group = null) + { + // Check if the value consist with id:alias, extract the id only + if ($value && str_contains($value, ':')) { + [$id] = explode(':', $value, 2); + $value = (int) $id; + } + + $return = parent::setup($element, $value, $group); + + if (!$return) { + return $return; + } + + $app = Factory::getApplication(); + + $app->getLanguage()->load('com_modules', JPATH_ADMINISTRATOR); + + $languages = LanguageHelper::getContentLanguages([0, 1], false); + $language = (string) $this->element['language']; + $clientId = (int) $this->element['clientid']; + + // Prepare enabled actions + $this->canDo['propagate'] = ((string) $this->element['propagate'] === 'true') && \count($languages) > 2; + + // Creating/editing module items is not supported in frontend. + if (!$app->isClient('administrator')) { + $this->canDo['new'] = false; + $this->canDo['edit'] = false; + } + + // Prepare Urls + $linkItems = (new Uri())->setPath(Uri::base(true) . '/index.php'); + $linkItems->setQuery([ + 'option' => 'com_modules', + 'view' => 'modules', + 'layout' => 'modal', + 'tmpl' => 'component', + 'client_id' => $clientId, + 'eid' => $this->getExtensionId(), + Session::getFormToken() => 1, + ]); + $linkItem = clone $linkItems; + $linkItem->setVar('view', 'module'); + $linkCheckin = (new Uri())->setPath(Uri::base(true) . '/index.php'); + $linkCheckin->setQuery([ + 'option' => 'com_modules', + 'task' => 'modules.checkin', + 'format' => 'json', + Session::getFormToken() => 1, + ]); + + if ($language) { + $linkItems->setVar('forcedLanguage', $language); + $linkItem->setVar('forcedLanguage', $language); + + $modalTitle = Text::_('COM_MODULES_SELECT_A_MODULE') . ' — ' . $this->getTitle(); + + $this->dataAttributes['data-language'] = $language; + } else { + $modalTitle = Text::_('COM_MODULES_SELECT_A_MODULE'); + } + + $urlSelect = $linkItems; + $urlEdit = clone $linkItem; + $urlEdit->setVar('task', 'module.edit'); + $urlNew = clone $linkItem; + $urlNew->setVar('task', 'module.add'); + + $this->urls['select'] = (string) $urlSelect; + $this->urls['new'] = (string) $urlNew; + $this->urls['edit'] = (string) $urlEdit; + $this->urls['checkin'] = (string) $linkCheckin; + + // Prepare titles + $this->modalTitles['select'] = $modalTitle; + $this->modalTitles['new'] = Text::_('COM_MODULES_NEW_MODULE'); + $this->modalTitles['edit'] = Text::_('COM_MODULES_EDIT_MODULE'); + + $this->hint = $this->hint ?: Text::_('COM_MODULES_SELECT_A_MODULE'); + + return $return; + } + + + /** + * Method to retrieve the title of selected item. + * + * @return string + * + * @since 6.1.0 + */ + protected function getExtensionId() + { + $data = $this->form->getData(); + + $module = $data->get('module', ''); + + $eid = 0; + + if ($module) { + try { + $db = $this->getDatabase(); + $query = $db->createQuery() + ->select($db->quoteName('extension_id')) + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('element') . ' = :module') + ->bind(':module', $module, ParameterType::STRING); + $db->setQuery($query); + + $eid = $db->loadResult(); + } catch (\Throwable $e) { + Factory::getApplication()->enqueueMessage($e->getMessage(), 'error'); + } + } + + return $eid; + } + + /** + * Method to retrieve the title of selected item. + * + * @return string + * + * @since 6.1.0 + */ + protected function getValueTitle() + { + $value = (int) $this->value ?: ''; + $title = ''; + + if ($value) { + try { + $db = $this->getDatabase(); + $query = $db->createQuery() + ->select($db->quoteName('title')) + ->from($db->quoteName('#__modules')) + ->where($db->quoteName('id') . ' = :id') + ->bind(':id', $value, ParameterType::INTEGER); + $db->setQuery($query); + + $title = $db->loadResult(); + } catch (\Throwable $e) { + Factory::getApplication()->enqueueMessage($e->getMessage(), 'error'); + } + } + + return $title ?: $value; + } + + /** + * Method to get the data to be passed to the layout for rendering. + * + * @return array + * + * @since 6.1.0 + */ + protected function getLayoutData() + { + $data = parent::getLayoutData(); + $data['language'] = (string) $this->element['language']; + + return $data; + } + + /** + * Get the renderer + * + * @param string $layoutId Id to load + * + * @return FileLayout + * + * @since 6.1.0 + */ + protected function getRenderer($layoutId = 'default') + { + $layout = parent::getRenderer($layoutId); + $layout->setComponent('com_modules'); + $layout->setClient((int) $this->element['clientid']); + + return $layout; + } +} diff --git a/administrator/components/com_modules/src/Helper/AssociationsHelper.php b/administrator/components/com_modules/src/Helper/AssociationsHelper.php new file mode 100644 index 0000000000000..1f579c6a01c48 --- /dev/null +++ b/administrator/components/com_modules/src/Helper/AssociationsHelper.php @@ -0,0 +1,224 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Modules\Administrator\Helper; + +use Joomla\CMS\Association\AssociationExtensionHelper; +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Associations; +use Joomla\CMS\Table\Module; +use Joomla\CMS\Table\Table; +use Joomla\Database\ParameterType; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Module associations helper. + * + * @since 6.1.0 + */ +class AssociationsHelper extends AssociationExtensionHelper +{ + /** + * The extension name + * + * @var array $extension + * + * @since 6.1.0 + */ + protected $extension = 'com_modules'; + + /** + * Array of item types + * + * @var array $itemTypes + * + * @since 6.1.0 + */ + protected $itemTypes = ['module']; + + /** + * Has the extension association support + * + * @var boolean $associationsSupport + * + * @since 6.1.0 + */ + protected $associationsSupport = true; + + /** + * Method to get the associations for a given item. + * + * @param integer $id Id of the item + * @param string $view Name of the view + * + * @return array Array of associations for the item + * + * @since 6.1.0 + */ + public function getAssociationsForItem($id = 0, $view = null) + { + return $this->getAssociations('item', $id); + } + + /** + * Get the associated items for an item + * + * @param string $typeName The item type + * @param int $id The id of item for which we need the associated items + * + * @return array + * + * @since 6.1.0 + */ + public function getAssociations($typeName, $id) + { + $type = $this->getType($typeName); + $context = $this->extension . '.item'; + + // Get the associations. + $associations = Associations::getAssociations( + $this->extension, + $type['tables']['a'], + $context, + $id, + 'id', + '', + '' + ); + + return $associations; + } + + /** + * Get item information + * + * @param string $typeName The item type + * @param int $id The id of item for which we need the associated items + * + * @return Table|null + * + * @since 6.1.0 + */ + public function getItem($typeName, $id) + { + if (empty($id)) { + return null; + } + + $table = new Module(Factory::getDbo()); + + if (\is_null($table)) { + return null; + } + + $table->load($id); + + return $table; + } + + /** + * Get information about the type + * + * @param string $typeName The item type + * + * @return array Array of item types + * + * @since 6.1.0 + */ + public function getType($typeName = '') + { + $fields = $this->getFieldsTemplate(); + $fields['state'] = 'a.published'; + $fields['catid'] = ''; + + // Next line looks odd, and it is, it is because of a bug. I am going to make another PR to fix it. + // We should be able to set the alias field to empty + $fields['alias'] = 'a.title'; + $fields['created_user_id'] = ''; + + $tables = ['a' => '#__modules']; + $joins = []; + + $support = $this->getSupportTemplate(); + $support['state'] = true; + $support['acl'] = true; + $support['checkout'] = true; + $support['save2copy'] = false; + + $title = 'module'; + + $urlOptions = $this->getUrlOptions(); + + return [ + 'fields' => $fields, + 'support' => $support, + 'tables' => $tables, + 'joins' => $joins, + 'title' => $title, + 'urlOptions' => $urlOptions, + ]; + } + + /** + * Get options we need for the associations side by side view + * + * @param string $type The item type + * + * @return array + * + * @since 6.1.0 + */ + public function getUrlOptions($type = '') + { + return [ + 'eid' => [ + 'functionName' => 'getExtensionId', + 'params' => [ + 'id', + ], + ], + ]; + } + + /** + * Method to retrieve the title of selected item. + * + * @return string + * + * @since 6.1.0 + */ + public function getExtensionId($id) + { + $data = $this->getItem('module', $id); + $module = $data->module; + $eid = 0; + + if ($module) { + try { + $db = Factory::getDbo(); + $query = $db->createQuery() + ->select($db->quoteName('extension_id')) + ->from($db->quoteName('#__extensions')) + ->where($db->quoteName('element') . ' = :module') + ->bind(':module', $module, ParameterType::STRING); + $db->setQuery($query); + + $eid = $db->loadResult(); + } catch (\Throwable $e) { + Factory::getApplication()->enqueueMessage($e->getMessage(), 'error'); + } + } + + return $eid; + } +} diff --git a/administrator/components/com_modules/src/Helper/ModulesHelper.php b/administrator/components/com_modules/src/Helper/ModulesHelper.php index fac753b736857..6be307a0fc0b0 100644 --- a/administrator/components/com_modules/src/Helper/ModulesHelper.php +++ b/administrator/components/com_modules/src/Helper/ModulesHelper.php @@ -12,6 +12,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; use Joomla\Database\ParameterType; use Joomla\Utilities\ArrayHelper; @@ -27,6 +28,27 @@ */ abstract class ModulesHelper { + /** + * Get the associations + * + * @param integer $pk Module item id + * + * @return array + * + * @since 6.1.0 + */ + public static function getAssociations($pk) + { + $langAssociations = Associations::getAssociations('com_modules', '#__modules', 'com_modules.item', $pk, 'id', '', ''); + $associations = []; + + foreach ($langAssociations as $langAssociation) { + $associations[$langAssociation->language] = $langAssociation->id; + } + + return $associations; + } + /** * Get a list of filter options for the state of a module. * @@ -71,7 +93,7 @@ public static function getPositions($clientId, $editPositions = false) { $db = Factory::getDbo(); $clientId = (int) $clientId; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('position')) ->from($db->quoteName('#__modules')) ->where($db->quoteName('client_id') . ' = :clientid') @@ -120,7 +142,7 @@ public static function getTemplates($clientId = 0, $state = '', $template = '') $clientId = (int) $clientId; // Get the database object and a new query object. - $query = $db->getQuery(true); + $query = $db->createQuery(); // Build the query. $query->select($db->quoteName(['element', 'name', 'enabled'])) @@ -157,7 +179,7 @@ public static function getTemplates($clientId = 0, $state = '', $template = '') public static function getModules($clientId) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('element AS value, name AS text') ->from('#__extensions as e') ->where('e.client_id = ' . (int) $clientId) diff --git a/administrator/components/com_modules/src/Model/ModuleModel.php b/administrator/components/com_modules/src/Model/ModuleModel.php index 9e8d5b17d57c0..9024b83e51f65 100644 --- a/administrator/components/com_modules/src/Model/ModuleModel.php +++ b/administrator/components/com_modules/src/Model/ModuleModel.php @@ -12,16 +12,22 @@ use Joomla\CMS\Application\ApplicationHelper; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\Model\AfterDeleteEvent; +use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\Model\BeforeDeleteEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Helper\ModuleHelper; +use Joomla\CMS\Language\Associations; +use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\AdminModel; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Table\Table; +use Joomla\CMS\Versioning\VersionableModelInterface; +use Joomla\CMS\Versioning\VersionableModelTrait; use Joomla\Component\Modules\Administrator\Helper\ModulesHelper; use Joomla\Database\ParameterType; use Joomla\Filesystem\Folder; @@ -39,8 +45,10 @@ * * @since 1.6 */ -class ModuleModel extends AdminModel +class ModuleModel extends AdminModel implements VersionableModelInterface { + use VersionableModelTrait; + /** * The type alias for this content type. * @@ -49,6 +57,14 @@ class ModuleModel extends AdminModel */ public $typeAlias = 'com_modules.module'; + /** + * The context used for the associations table + * + * @var string + * @since 6.1.0 + */ + protected $associationsContext = 'com_modules.item'; + /** * @var string The prefix to use with controller messages. * @since 1.6 @@ -160,7 +176,10 @@ protected function batchCopy($value, $pks, $contexts) $newIds = []; foreach ($pks as $pk) { - if ($user->authorise('core.create', 'com_modules')) { + if ( + $user->authorise('core.create', 'com_modules') + && $user->authorise('core.edit', $contexts[$pk]) + ) { $table->reset(); $table->load($pk); @@ -202,7 +221,7 @@ protected function batchCopy($value, $pks, $contexts) // Now we need to handle the module assignments $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('menuid')) ->from($db->quoteName('#__modules_menu')) ->where($db->quoteName('moduleid') . ' = :moduleid') @@ -327,14 +346,14 @@ protected function canEditState($record) */ public function delete(&$pks) { - $app = Factory::getApplication(); $pks = (array) $pks; $user = $this->getCurrentUser(); $table = $this->getTable(); $context = $this->option . '.' . $this->name; // Include the plugins for the on delete events. - PluginHelper::importPlugin($this->events_map['delete']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['delete'], null, true, $dispatcher); // Iterate the items to delete each one. foreach ($pks as $pk) { @@ -347,7 +366,10 @@ public function delete(&$pks) } // Trigger the before delete event. - $result = $app->triggerEvent($this->event_before_delete, [$context, $table]); + $result = $dispatcher->dispatch($this->event_before_delete, new BeforeDeleteEvent($this->event_before_delete, [ + 'context' => $context, + 'subject' => $table, + ]))->getArgument('result', []); if (\in_array(false, $result, true) || !$table->delete($pk)) { throw new \Exception($table->getError()); @@ -356,7 +378,7 @@ public function delete(&$pks) // Delete the menu assignments $pk = (int) $pk; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__modules_menu')) ->where($db->quoteName('moduleid') . ' = :moduleid') ->bind(':moduleid', $pk, ParameterType::INTEGER); @@ -364,7 +386,10 @@ public function delete(&$pks) $db->execute(); // Trigger the after delete event. - $app->triggerEvent($this->event_after_delete, [$context, $table]); + $dispatcher->dispatch($this->event_after_delete, new AfterDeleteEvent($this->event_after_delete, [ + 'context' => $context, + 'subject' => $table, + ])); // Clear module cache parent::cleanCache($table->module); @@ -426,7 +451,7 @@ public function duplicate(&$pks) } $pk = (int) $pk; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('menuid')) ->from($db->quoteName('#__modules_menu')) ->where($db->quoteName('moduleid') . ' = :moduleid') @@ -445,7 +470,7 @@ public function duplicate(&$pks) if (!empty($tuples)) { // Module-Menu Mapping: Do it in one query - $query = $db->getQuery(true) + $query = $db->createQuery() ->insert($db->quoteName('#__modules_menu')) ->columns($db->quoteName(['moduleid', 'menuid'])) ->values($tuples); @@ -508,9 +533,10 @@ public function &getClient() * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -546,10 +572,6 @@ public function getForm($data = [], $loadData = true) $form = $this->loadForm('com_modules.module', 'module', ['control' => 'jform', 'load_data' => $loadData], true); } - if (empty($form)) { - return false; - } - $user = $this->getCurrentUser(); /** @@ -597,12 +619,12 @@ protected function loadFormData() // Pre-select some filters (Status, Module Position, Language, Access Level) in edit form if those have been selected in Module Manager if (!$data->id) { - $clientId = $input->getInt('client_id', 0); - $filters = (array) $app->getUserState('com_modules.modules.' . $clientId . '.filter'); - $data->set('published', $input->getInt('published', ((isset($filters['state']) && $filters['state'] !== '') ? $filters['state'] : null))); - $data->set('position', $input->getInt('position', (!empty($filters['position']) ? $filters['position'] : null))); - $data->set('language', $input->getString('language', (!empty($filters['language']) ? $filters['language'] : null))); - $data->set('access', $input->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access')))); + $clientId = $input->getInt('client_id', 0); + $filters = (array) $app->getUserState('com_modules.modules.' . $clientId . '.filter'); + $data->published = $input->getInt('published', ((isset($filters['state']) && $filters['state'] !== '') ? $filters['state'] : null)); + $data->position = $input->getInt('position', (!empty($filters['position']) ? $filters['position'] : null)); + $data->language = $input->getString('language', (!empty($filters['language']) ? $filters['language'] : null)); + $data->access = $input->getInt('access', (!empty($filters['access']) ? $filters['access'] : $app->get('access'))); } // Avoid to delete params of a second module opened in a new browser tab while new one is not saved yet. @@ -611,7 +633,7 @@ protected function loadFormData() $params = $app->getUserState('com_modules.add.module.params'); if (\is_array($params)) { - $data->set('params', $params); + $data->params = $params; } } } @@ -626,7 +648,7 @@ protected function loadFormData() * * @param integer $pk The id of the primary key. * - * @return mixed Object on success, false on failure. + * @return \stdClass|false Object on success, false on failure. * * @since 1.6 */ @@ -652,7 +674,7 @@ public function getItem($pk = null) // Check if we are creating a new extension. if (empty($pk)) { if ($extensionId = (int) $this->getState('extension.id')) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['element', 'client_id'])) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('extension_id') . ' = :extensionid') @@ -684,16 +706,16 @@ public function getItem($pk = null) } } - // Convert to the \Joomla\CMS\Object\CMSObject before adding other data. + // Convert to an object before adding other data. $properties = $table->getProperties(1); - $this->_cache[$pk] = ArrayHelper::toObject($properties, CMSObject::class); + $this->_cache[$pk] = ArrayHelper::toObject($properties); // Convert the params field to an array. $registry = new Registry($table->params); $this->_cache[$pk]->params = $registry->toArray(); // Determine the page assignment mode. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('menuid')) ->from($db->quoteName('#__modules_menu')) ->where($db->quoteName('moduleid') . ' = :moduleid') @@ -729,6 +751,21 @@ public function getItem($pk = null) } else { $this->_cache[$pk]->xml = null; } + + // Load associated module items + $assoc = Associations::isEnabled(); + + if ($assoc) { + $this->_cache[$pk]->associations = []; + + if ($this->_cache[$pk]->id != null && $this->_cache[$pk]->client_id === 0) { + $associations = Associations::getAssociations('com_modules', '#__modules', 'com_modules.item', $this->_cache[$pk]->id, 'id', '', ''); + + foreach ($associations as $tag => $association) { + $this->_cache[$pk]->associations[$tag] = $association->id; + } + } + } } return $this->_cache[$pk]; @@ -863,6 +900,35 @@ protected function preprocessForm(Form $form, $data, $group = 'content') } } + // Association for modules + if (Associations::isEnabled()) { + $languages = LanguageHelper::getContentLanguages(false, false, null, 'ordering', 'asc'); + + if (\count($languages) > 1) { + $addform = new \SimpleXMLElement('
'); + $fields = $addform->addChild('fields'); + $fields->addAttribute('name', 'associations'); + $fieldset = $fields->addChild('fieldset'); + $fieldset->addAttribute('name', 'item_associations'); + $fieldset->addAttribute('addfieldprefix', 'Joomla\Component\Modules\Administrator\Field'); + + foreach ($languages as $language) { + $field = $fieldset->addChild('field'); + $field->addAttribute('name', $language->lang_code); + $field->addAttribute('type', 'modal_module'); + $field->addAttribute('language', $language->lang_code); + $field->addAttribute('label', $language->title); + $field->addAttribute('translate_label', 'false'); + $field->addAttribute('select', 'true'); + $field->addAttribute('new', 'true'); + $field->addAttribute('edit', 'true'); + $field->addAttribute('clear', 'true'); + $field->addAttribute('propagate', 'true'); + } + + $form->load($addform, false); + } + } // Trigger the default form events. parent::preprocessForm($form, $data, $group); } @@ -907,7 +973,8 @@ public function save($data) $context = $this->option . '.' . $this->name; // Include the plugins for the save event. - PluginHelper::importPlugin($this->events_map['save']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['save'], null, true, $dispatcher); // Load the row if saving an existing record. if ($pk > 0) { @@ -926,50 +993,24 @@ public function save($data) } } - // Bind the data. - if (!$table->bind($data)) { - $this->setError($table->getError()); - - return false; - } - - // Prepare the row for saving - $this->prepareTable($table); - - // Check the data. - if (!$table->check()) { - $this->setError($table->getError()); - - return false; - } - - // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, [$context, &$table, $isNew]); - - if (\in_array(false, $result, true)) { - $this->setError($table->getError()); - - return false; - } - - // Store the data. - if (!$table->store()) { - $this->setError($table->getError()); - + if (!parent::save($data)) { return false; } // Process the menu link mappings. $assignment = $data['assignment'] ?? 0; - $table->id = (int) $table->id; + $id = $this->getState('module.id'); + + // Reload Table + $table->load($id); // Delete old module to menu item associations $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__modules_menu')) ->where($db->quoteName('moduleid') . ' = :moduleid') - ->bind(':moduleid', $table->id, ParameterType::INTEGER); + ->bind(':moduleid', $id, ParameterType::INTEGER); $db->setQuery($query); try { @@ -998,7 +1039,7 @@ public function save($data) ->insert($db->quoteName('#__modules_menu')) ->columns($db->quoteName(['moduleid', 'menuid'])) ->values(implode(', ', [':moduleid', 0])) - ->bind(':moduleid', $table->id, ParameterType::INTEGER); + ->bind(':moduleid', $id, ParameterType::INTEGER); $db->setQuery($query); try { @@ -1017,7 +1058,7 @@ public function save($data) ->columns($db->quoteName(['moduleid', 'menuid'])); foreach ($data['assigned'] as &$pk) { - $query->values((int) $table->id . ',' . (int) $pk * $sign); + $query->values((int) $id . ',' . (int) $pk * $sign); } $db->setQuery($query); @@ -1033,7 +1074,12 @@ public function save($data) } // Trigger the after save event. - Factory::getApplication()->triggerEvent($this->event_after_save, [$context, &$table, $isNew]); + $dispatcher->dispatch($this->event_after_save, new AfterSaveEvent($this->event_after_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ])); // Compute the extension id of this module in case the controller wants it. $query->clear() @@ -1057,7 +1103,6 @@ public function save($data) } $this->setState('module.extension_id', $extensionId); - $this->setState('module.id', $table->id); // Clear modules cache $this->cleanCache(); @@ -1090,15 +1135,13 @@ protected function getReorderConditions($table) /** * Custom clean cache method for different clients * - * @param string $group The name of the plugin group to import (defaults to null). - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 1.6 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { parent::cleanCache('com_modules'); } diff --git a/administrator/components/com_modules/src/Model/ModulesModel.php b/administrator/components/com_modules/src/Model/ModulesModel.php index 2ad18918777d0..d790472edc643 100644 --- a/administrator/components/com_modules/src/Model/ModulesModel.php +++ b/administrator/components/com_modules/src/Model/ModulesModel.php @@ -12,6 +12,7 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; +use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; @@ -63,6 +64,10 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) 'name', 'e.name', 'menuitem', ]; + + if (Associations::isEnabled()) { + $config['filter_fields'][] = 'association'; + } } parent::__construct($config, $factory); @@ -84,13 +89,19 @@ protected function populateState($ordering = 'a.position', $direction = 'asc') { $app = Factory::getApplication(); - $layout = $app->getInput()->get('layout', '', 'cmd'); + $forcedLanguage = $app->getInput()->get('forcedLanguage', '', 'cmd'); + $layout = $app->getInput()->get('layout', '', 'cmd'); // Adjust the context to support modal layouts. if ($layout) { $this->context .= '.' . $layout; } + // Adjust the context to support forced languages. + if ($forcedLanguage) { + $this->context .= '.' . $forcedLanguage; + } + // Make context client aware $this->context .= '.' . $app->getInput()->get->getInt('client_id', 0); @@ -121,6 +132,11 @@ protected function populateState($ordering = 'a.position', $direction = 'asc') // List state information. parent::populateState($ordering, $direction); + + // Force a language. + if (!empty($forcedLanguage)) { + $this->setState('filter.language', $forcedLanguage); + } } /** @@ -249,7 +265,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields. $query->select( @@ -346,7 +362,7 @@ protected function getListQuery() } else { // If user selected the modules assigned to some particular page (menu item). // Modules in "All" pages. - $subQuery1 = $db->getQuery(true); + $subQuery1 = $db->createQuery(); $subQuery1->select('MIN(' . $db->quoteName('menuid') . ')') ->from($db->quoteName('#__modules_menu')) ->where($db->quoteName('moduleid') . ' = ' . $db->quoteName('a.id')); @@ -354,13 +370,13 @@ protected function getListQuery() // Modules in "Selected" pages that have the chosen menu item id. $menuItemId = (int) $menuItemId; $minusMenuItemId = $menuItemId * -1; - $subQuery2 = $db->getQuery(true); + $subQuery2 = $db->createQuery(); $subQuery2->select($db->quoteName('moduleid')) ->from($db->quoteName('#__modules_menu')) ->where($db->quoteName('menuid') . ' = :menuitemid2'); // Modules in "All except selected" pages that doesn't have the chosen menu item id. - $subQuery3 = $db->getQuery(true); + $subQuery3 = $db->createQuery(); $subQuery3->select($db->quoteName('moduleid')) ->from($db->quoteName('#__modules_menu')) ->where($db->quoteName('menuid') . ' = :menuitemid3'); @@ -410,6 +426,22 @@ protected function getListQuery() } } + // Join over the associations. + if (Associations::isEnabled()) { + $subQuery = $db->createQuery() + ->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1') + ->from($db->quoteName('#__associations', 'asso1')) + ->join('INNER', $db->quoteName('#__associations', 'asso2'), $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key')) + ->where( + [ + $db->quoteName('asso1.id') . ' = ' . $db->quoteName('a.id'), + $db->quoteName('asso1.context') . ' = ' . $db->quote('com_modules.item'), + ] + ); + + $query->select('(' . $subQuery . ') AS ' . $db->quoteName('association')); + } + return $query; } diff --git a/administrator/components/com_modules/src/Model/PositionsModel.php b/administrator/components/com_modules/src/Model/PositionsModel.php index 0351c13dc8363..3d99a58ace4e6 100644 --- a/administrator/components/com_modules/src/Model/PositionsModel.php +++ b/administrator/components/com_modules/src/Model/PositionsModel.php @@ -105,7 +105,7 @@ public function getItems() // Get the database object and a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('position', 'value')) ->from($db->quoteName('#__modules')) ->where($db->quoteName('client_id') . ' = :clientid') diff --git a/administrator/components/com_modules/src/Model/SelectModel.php b/administrator/components/com_modules/src/Model/SelectModel.php index 643ca24503046..9a2fb6212e44b 100644 --- a/administrator/components/com_modules/src/Model/SelectModel.php +++ b/administrator/components/com_modules/src/Model/SelectModel.php @@ -90,7 +90,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_modules/src/Service/HTML/Modules.php b/administrator/components/com_modules/src/Service/HTML/Modules.php index 78b02e6e90582..a7f9736c95080 100644 --- a/administrator/components/com_modules/src/Service/HTML/Modules.php +++ b/administrator/components/com_modules/src/Service/HTML/Modules.php @@ -12,9 +12,13 @@ use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; +use Joomla\CMS\Layout\LayoutHelper; +use Joomla\CMS\Router\Route; use Joomla\Component\Modules\Administrator\Helper\ModulesHelper; use Joomla\Component\Templates\Administrator\Helper\TemplatesHelper; +use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; use Joomla\Utilities\ArrayHelper; @@ -29,6 +33,82 @@ */ class Modules { + use DatabaseAwareTrait; + + /** + * Generate the markup to display the item associations + * + * @param int $itemid The menu item id + * + * @return string + * + * @since 6.1.0 + * + * @throws \Exception If there is an error on the query + */ + public function association($itemid) + { + // Defaults + $html = ''; + + // Get the associations + $associations = ModulesHelper::getAssociations($itemid); + + if ($associations) { + // Get the associated menu items + $db = $this->getDatabase(); + $query = $db->createQuery() + ->select( + [ + $db->quoteName('m.id'), + $db->quoteName('m.title'), + $db->quoteName('l.sef', 'lang_sef'), + $db->quoteName('l.lang_code'), + $db->quoteName('l.image'), + $db->quoteName('l.title', 'language_title'), + ] + ) + ->from($db->quoteName('#__modules', 'm')) + ->join('LEFT', $db->quoteName('#__languages', 'l'), $db->quoteName('m.language') . ' = ' . $db->quoteName('l.lang_code')) + ->whereIn($db->quoteName('m.id'), array_values($associations)) + ->where($db->quoteName('m.id') . ' != :itemid') + ->bind(':itemid', $itemid, ParameterType::INTEGER); + $db->setQuery($query); + + try { + $items = $db->loadObjectList('id'); + } catch (\RuntimeException $e) { + throw new \Exception($e->getMessage(), 500); + } + + // Construct html + if ($items) { + $languages = LanguageHelper::getContentLanguages([0, 1]); + $content_languages = array_column($languages, 'lang_code'); + + foreach ($items as &$item) { + if (\in_array($item->lang_code, $content_languages)) { + $text = $item->lang_code; + $url = Route::_('index.php?option=com_modules&task=modules.edit&id=' . (int) $item->id); + $tooltip = '' . htmlspecialchars($item->language_title, ENT_QUOTES, 'UTF-8') . '
' + . Text::sprintf('COM_MODULES_MODULE_SPRINTF', $item->title); + $classes = 'badge bg-secondary'; + + $item->link = '' . $text . '' + . ''; + } else { + // Display warning if Content Language is trashed or deleted + Factory::getApplication()->enqueueMessage(Text::sprintf('JGLOBAL_ASSOCIATIONS_CONTENTLANGUAGE_WARNING', $item->lang_code), 'warning'); + } + } + } + + $html = LayoutHelper::render('joomla.content.associations', $items); + } + + return $html; + } + /** * Builds an array of template options * @@ -223,14 +303,14 @@ public function batchOptions() * * @since 2.5 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed with no replacement */ public function positionList($clientId = 0) { $clientId = (int) $clientId; - $db = Factory::getDbo(); - $query = $db->getQuery(true) + $db = $this->getDatabase(); + $query = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('position', 'value')) ->select($db->quoteName('position', 'text')) ->from($db->quoteName('#__modules')) diff --git a/administrator/components/com_modules/src/View/Module/HtmlView.php b/administrator/components/com_modules/src/View/Module/HtmlView.php index 4037f50637bf7..1037dcd8071d1 100644 --- a/administrator/components/com_modules/src/View/Module/HtmlView.php +++ b/administrator/components/com_modules/src/View/Module/HtmlView.php @@ -10,8 +10,10 @@ namespace Joomla\Component\Modules\Administrator\View\Module; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Helper\ContentHelper; +use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; use Joomla\CMS\Toolbar\Toolbar; @@ -100,6 +102,24 @@ public function display($tpl = null) return; } + $input = Factory::getApplication()->getInput(); + $forcedLanguage = $input->get('forcedLanguage', '', 'cmd'); + + // If we are forcing a language in modal (used for associations). + if ($this->getLayout() === 'modal' && $forcedLanguage) { + // Set the language field to the forcedLanguage and disable changing it. + $this->form->setValue('language', null, $forcedLanguage); + $this->form->setFieldAttribute('language', 'readonly', 'true'); + + // Only allow to select categories with All language or with the forced language. + $this->form->setFieldAttribute('parent_id', 'language', '*,' . $forcedLanguage); + } + + // Add form control fields + $this->form + ->addControlField('task') + ->addControlField('return', Factory::getApplication()->getInput()->getBase64('return', '')); + if ($this->getLayout() !== 'modal') { $this->addToolbar(); } else { @@ -170,6 +190,16 @@ function (Toolbar $childBar) use ($checkedOut, $canDo) { ); $toolbar->cancel('module.cancel'); + + if (ComponentHelper::isEnabled('com_contenthistory') && $this->state->get('params')->get('save_history', 0) && $canDo->get('core.edit')) { + $toolbar->versions('com_modules.module', $this->item->id); + } + + if (Associations::isEnabled() && ComponentHelper::isEnabled('com_associations') && $this->item->client_id === 0) { + $toolbar->standardButton('associations', 'JTOOLBAR_ASSOCIATIONS', 'module.editAssociations') + ->icon('icon-contract') + ->listCheck(false); + } } // Get the help information for the menu item. diff --git a/administrator/components/com_modules/src/View/Modules/HtmlView.php b/administrator/components/com_modules/src/View/Modules/HtmlView.php index f52d23592643f..b610a5a593426 100644 --- a/administrator/components/com_modules/src/View/Modules/HtmlView.php +++ b/administrator/components/com_modules/src/View/Modules/HtmlView.php @@ -14,12 +14,9 @@ use Joomla\CMS\Helper\ContentHelper; use Joomla\CMS\Helper\ModuleHelper; use Joomla\CMS\Language\Multilanguage; -use Joomla\CMS\Language\Text; -use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\MVC\Model\ListModel; +use Joomla\CMS\MVC\View\ListView; use Joomla\CMS\Session\Session; -use Joomla\CMS\Toolbar\Button\DropdownButton; -use Joomla\CMS\Toolbar\ToolbarHelper; -use Joomla\Component\Modules\Administrator\Model\ModulesModel; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -30,80 +27,61 @@ * * @since 1.6 */ -class HtmlView extends BaseHtmlView +class HtmlView extends ListView { /** - * An array of items + * The client ID for the modules we're showing * - * @var array - */ - protected $items; - - /** - * The pagination object + * @var int * - * @var \Joomla\CMS\Pagination\Pagination + * @since 6.0.0 */ - protected $pagination; + protected $clientId; /** - * The model state + * The help link for the view * - * @var \Joomla\Registry\Registry + * @var string */ - protected $state; + protected $helpLink = 'Modules'; /** - * Form object for search filters + * Constructor * - * @var \Joomla\CMS\Form\Form - * - * @since 4.0.0 + * @param array $config An optional associative array of configuration settings. */ - public $filterForm; + public function __construct(array $config) + { + if (empty($config['option'])) { + $config['option'] = 'com_modules'; + } - /** - * The active search filters - * - * @var array - * @since 4.0.0 - */ - public $activeFilters; + $config['toolbar_icon'] = 'cube module'; + $config['supports_batch'] = true; - /** - * Is this view an Empty State - * - * @var boolean - * @since 4.0.0 - */ - private $isEmptyState = false; + parent::__construct($config); + } /** - * Display the view - * - * @param string $tpl The name of the template file to parse; automatically searches through the template paths. + * Prepare view data * * @return void - * - * @since 1.6 */ - public function display($tpl = null) + protected function initializeView() { - /** @var ModulesModel $model */ + parent::initializeView(); + + /** + * @var ListModel + */ $model = $this->getModel(); - $model->setUseExceptions(true); - $this->items = $model->getItems(); - $this->pagination = $model->getPagination(); - $this->state = $model->getState(); $this->total = $model->getTotal(); - $this->filterForm = $model->getFilterForm(); - $this->activeFilters = $model->getActiveFilters(); - $this->clientId = $this->state->get('client_id'); + $this->clientId = (int) $this->state->get('client_id', 0); - if (!\count($this->items) && $this->isEmptyState = $model->getIsEmptyState()) { - $this->setLayout('emptystate'); - } + $this->canDo = ContentHelper::getActions('com_modules'); + + $this->toolbarTitle = $this->clientId == 1 ? 'COM_MODULES_MANAGER_MODULES_ADMIN' : 'COM_MODULES_MANAGER_MODULES_SITE'; /** * The code below make sure the remembered position will be available from filter dropdown even if there are no @@ -138,8 +116,6 @@ public function display($tpl = null) // We don't need the toolbar in the modal window. if ($this->getLayout() !== 'modal') { - $this->addToolbar(); - // We do not need to filter by language when multilingual is disabled if (!Multilanguage::isEnabled()) { unset($this->activeFilters['language']); @@ -161,9 +137,21 @@ public function display($tpl = null) */ $this->pagination->setAdditionalUrlParam(Session::getFormToken(), '1'); } - } - parent::display($tpl); + // In menu associations modal we need to remove language filter if forcing a language. + $forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'CMD'); + + if ($forcedLanguage) { + // If the language is forced we can't allow to select the language, so transform the language selector filter into a hidden field. + $languageXml = new \SimpleXMLElement(''); + $this->filterForm->setField($languageXml, 'filter', true); + + // Also, unset the active language filter so the search tools is not open by default with this filter. + unset($this->activeFilters['language']); + } + + $this->filterForm->addControlField('forcedLanguage', $forcedLanguage); + } } /** @@ -175,78 +163,42 @@ public function display($tpl = null) */ protected function addToolbar() { - $state = $this->state; - $canDo = ContentHelper::getActions('com_modules'); - $user = $this->getCurrentUser(); + $canDo = $this->canDo; - // Get the toolbar object instance - $toolbar = $this->getDocument()->getToolbar(); + $canCreate = $canDo->get('core.create'); - if ($state->get('client_id') == 1) { - ToolbarHelper::title(Text::_('COM_MODULES_MANAGER_MODULES_ADMIN'), 'cube module'); - } else { - ToolbarHelper::title(Text::_('COM_MODULES_MANAGER_MODULES_SITE'), 'cube module'); + if ($canCreate) { + $this->getDocument()->getToolbar()->standardButton('new', 'JTOOLBAR_NEW') + ->onclick("location.href='index.php?option=com_modules&view=select&client_id=" . $this->clientId . "'"); } - if ($canDo->get('core.create')) { - $toolbar->standardButton('new', 'JTOOLBAR_NEW') - ->onclick("location.href='index.php?option=com_modules&view=select&client_id=" . $this->state->get('client_id', 0) . "'"); - } + // Prevent showing default add button + $canDo->set('core.create', false); - if (!$this->isEmptyState && ($canDo->get('core.edit.state') || $this->getCurrentUser()->authorise('core.admin'))) { - /** @var DropdownButton $dropdown */ - $dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS') - ->toggleSplit(false) - ->icon('icon-ellipsis-h') - ->buttonClass('btn btn-action') - ->listCheck(true); + parent::addToolbar(); - $childBar = $dropdown->getChildToolbar(); + $canDo->set('core.create', $canCreate); - if ($canDo->get('core.edit.state')) { - $childBar->publish('modules.publish')->listCheck(true); + // We add the duplicate button if there is the default dropdown + if ($canCreate) { - $childBar->unpublish('modules.unpublish')->listCheck(true); - } + /** + * @var \Joomla\CMS\Toolbar\Toolbar $toolbar + */ + $toolbar = $this->getDocument()->getToolbar(); - if ($this->getCurrentUser()->authorise('core.admin')) { - $childBar->checkin('modules.checkin')->listCheck(true); - } + $buttons = $toolbar->getItems(); - if ($canDo->get('core.edit.state') && $this->state->get('filter.published') != -2) { - $childBar->trash('modules.trash')->listCheck(true); - } + foreach ($buttons as $button) { + if ($button->getName() === 'status-group') { + $childBar = $button->getChildToolbar(); - // Add a batch button - if ( - $user->authorise('core.create', 'com_modules') && $user->authorise('core.edit', 'com_modules') - && $user->authorise('core.edit.state', 'com_modules') - ) { - $childBar->popupButton('batch', 'JTOOLBAR_BATCH') - ->popupType('inline') - ->textHeader(Text::_('COM_MODULES_BATCH_OPTIONS')) - ->url('#joomla-dialog-batch') - ->modalWidth('800px') - ->modalHeight('fit-content') - ->listCheck(true); - } + $childBar->standardButton('copy', 'JTOOLBAR_DUPLICATE', 'modules.duplicate') + ->listCheck(true); - if ($canDo->get('core.create')) { - $childBar->standardButton('copy', 'JTOOLBAR_DUPLICATE', 'modules.duplicate') - ->listCheck(true); + break; + } } } - - if (!$this->isEmptyState && ($state->get('filter.state') == -2 && $canDo->get('core.delete'))) { - $toolbar->delete('modules.delete', 'JTOOLBAR_DELETE_FROM_TRASH') - ->message('JGLOBAL_CONFIRM_DELETE') - ->listCheck(true); - } - - if ($canDo->get('core.admin')) { - $toolbar->preferences('com_modules'); - } - - $toolbar->help('Modules'); } } diff --git a/administrator/components/com_modules/tmpl/module/edit.php b/administrator/components/com_modules/tmpl/module/edit.php index 45a819a54cfa9..1695523f3bbce 100644 --- a/administrator/components/com_modules/tmpl/module/edit.php +++ b/administrator/components/com_modules/tmpl/module/edit.php @@ -12,14 +12,13 @@ use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; /** @var \Joomla\Component\Modules\Administrator\View\Module\HtmlView $this */ -HTMLHelper::_('behavior.combobox'); - $hasContent = isset($this->item->xml->customContent); $hasContentFieldName = 'content'; @@ -39,12 +38,14 @@ $this->getDocument()->addScriptOptions('module-edit', ['itemId' => $this->item->id, 'state' => (int) $this->item->id == 0 ? 'Add' : 'Edit']); -/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ -$wa = $this->getDocument()->getWebAssetManager(); -$wa->useScript('keepalive') - ->useScript('form.validate'); +$this->getDocument()->getWebAssetManager() + ->useScript('keepalive') + ->useScript('form.validate') + ->useScript('awesomplete'); -$input = Factory::getApplication()->getInput(); +$clientId = (int) $this->item->client_id; +$assoc = Associations::isEnabled() && $clientId == 0; +$input = Factory::getApplication()->getInput(); // In case of modal $isModal = $input->get('layout') === 'modal'; @@ -136,7 +137,8 @@ 'access', 'ordering', 'language', - 'note' + 'note', + 'version_note' ]; ?> @@ -172,10 +174,23 @@ fieldsets = []; - $this->ignore_fieldsets = ['basic', 'description']; + $this->ignore_fieldsets = ['basic', 'description', 'item_associations']; echo LayoutHelper::render('joomla.edit.params', $this); ?> + + +
+ +
+ +
+
+ + + + + canDo->get('core.admin')) : ?>
@@ -189,10 +204,10 @@ - - - form->getInput('module'); ?> form->getInput('client_id'); ?> + form->getInput('id'); ?> + + form->renderControlFields(); ?> diff --git a/administrator/components/com_modules/tmpl/module/modal.php b/administrator/components/com_modules/tmpl/module/modal.php index 4d9cad46253cf..25bce0f104420 100644 --- a/administrator/components/com_modules/tmpl/module/modal.php +++ b/administrator/components/com_modules/tmpl/module/modal.php @@ -13,7 +13,7 @@ /** @var \Joomla\Component\Modules\Administrator\View\Module\HtmlView $this */ // A backward compatibility for bootstrap modals: hide toolbar -// @TODO: Remove in 6.0 +// @TODO: Remove in 7.0 $this->getDocument()->getWebAssetManager()->addInlineScript(' if (window.parent.Joomla.Modal) { const modal = window.parent.Joomla.Modal.getCurrent(); diff --git a/administrator/components/com_modules/tmpl/modules/default.php b/administrator/components/com_modules/tmpl/modules/default.php index 2962d5ae2c2c1..679f51614f2f1 100644 --- a/administrator/components/com_modules/tmpl/modules/default.php +++ b/administrator/components/com_modules/tmpl/modules/default.php @@ -12,6 +12,7 @@ use Joomla\CMS\Helper\ModuleHelper; use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; @@ -35,6 +36,9 @@ $saveOrderingUrl = 'index.php?option=com_modules&task=modules.saveOrderAjax&tmpl=component&' . Session::getFormToken() . '=1'; HTMLHelper::_('draggablelist.draggable'); } + +$assoc = Associations::isEnabled() && $clientId == 0; + ?>
@@ -74,8 +78,13 @@ + + + + + - + @@ -170,6 +179,13 @@ escape($item->access_level); ?> + + + association) : ?> + id); ?> + + + @@ -200,15 +216,10 @@ authorise('core.create', 'com_modules') - && $user->authorise('core.edit', 'com_modules') - && $user->authorise('core.edit.state', 'com_modules') - ) : ?> + if ($this->batchAllowed) : ?> - - - + + filterForm->renderControlFields(); ?>
diff --git a/administrator/components/com_modules/tmpl/modules/emptystate.php b/administrator/components/com_modules/tmpl/modules/emptystate.php index 75450cad12077..9b31c10e17778 100644 --- a/administrator/components/com_modules/tmpl/modules/emptystate.php +++ b/administrator/components/com_modules/tmpl/modules/emptystate.php @@ -18,10 +18,12 @@ $displayData = [ 'textPrefix' => 'COM_MODULES', 'formURL' => 'index.php?option=com_modules&view=select&client_id=' . $this->clientId, - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Module', + 'helpURL' => 'https://guide.joomla.org/user-manual/modules', 'icon' => 'icon-cube module', // Although it is (almost) impossible to get to this page with no created Administrator Modules, we add this for completeness. 'title' => Text::_('COM_MODULES_EMPTYSTATE_TITLE_' . ($this->clientId ? 'ADMINISTRATOR' : 'SITE')), + + 'controlFields' => $this->filterForm->renderControlFields(), ]; if ($this->getCurrentUser()->authorise('core.create', 'com_modules')) { diff --git a/administrator/components/com_modules/tmpl/modules/modal.php b/administrator/components/com_modules/tmpl/modules/modal.php index 45111f6b0d5a1..198ffdf7dbb1c 100644 --- a/administrator/components/com_modules/tmpl/modules/modal.php +++ b/administrator/components/com_modules/tmpl/modules/modal.php @@ -37,7 +37,6 @@ } ?>
-
$this]); ?> diff --git a/administrator/components/com_newsfeeds/helpers/newsfeeds.php b/administrator/components/com_newsfeeds/helpers/newsfeeds.php index b474e08ee4a03..378de40b6eff7 100644 --- a/administrator/components/com_newsfeeds/helpers/newsfeeds.php +++ b/administrator/components/com_newsfeeds/helpers/newsfeeds.php @@ -19,7 +19,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Newsfeeds\Administrator\Helper\NewsfeedsHelper instead */ class NewsfeedsHelper extends \Joomla\Component\Newsfeeds\Administrator\Helper\NewsfeedsHelper diff --git a/administrator/components/com_newsfeeds/src/Field/Modal/NewsfeedField.php b/administrator/components/com_newsfeeds/src/Field/Modal/NewsfeedField.php index 97ed426e7ce8b..834174f3e5454 100644 --- a/administrator/components/com_newsfeeds/src/Field/Modal/NewsfeedField.php +++ b/administrator/components/com_newsfeeds/src/Field/Modal/NewsfeedField.php @@ -138,7 +138,7 @@ protected function getValueTitle() if ($value) { try { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('name')) ->from($db->quoteName('#__newsfeeds')) ->where($db->quoteName('id') . ' = :value') diff --git a/administrator/components/com_newsfeeds/src/Field/NewsfeedsField.php b/administrator/components/com_newsfeeds/src/Field/NewsfeedsField.php index a4975ea91a467..d41a20203c93b 100644 --- a/administrator/components/com_newsfeeds/src/Field/NewsfeedsField.php +++ b/administrator/components/com_newsfeeds/src/Field/NewsfeedsField.php @@ -44,7 +44,7 @@ protected function getOptions() $options = []; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('id', 'value'), diff --git a/administrator/components/com_newsfeeds/src/Helper/AssociationsHelper.php b/administrator/components/com_newsfeeds/src/Helper/AssociationsHelper.php index f7cbdebf3aa2c..213e3eb0b4d68 100644 --- a/administrator/components/com_newsfeeds/src/Helper/AssociationsHelper.php +++ b/administrator/components/com_newsfeeds/src/Helper/AssociationsHelper.php @@ -11,8 +11,11 @@ namespace Joomla\Component\Newsfeeds\Administrator\Helper; use Joomla\CMS\Association\AssociationExtensionHelper; +use Joomla\CMS\Factory; use Joomla\CMS\Language\Associations; +use Joomla\CMS\Table\Category; use Joomla\CMS\Table\Table; +use Joomla\Component\Newsfeeds\Administrator\Table\NewsfeedTable; use Joomla\Component\Newsfeeds\Site\Helper\AssociationHelper; // phpcs:disable PSR1.Files.SideEffects @@ -124,11 +127,11 @@ public function getItem($typeName, $id) switch ($typeName) { case 'newsfeed': - $table = Table::getInstance('NewsfeedTable', 'Joomla\\Component\\Newsfeeds\\Administrator\\Table\\'); + $table = new NewsfeedTable(Factory::getDbo()); break; case 'category': - $table = Table::getInstance('Category'); + $table = new Category(Factory::getDbo()); break; } diff --git a/administrator/components/com_newsfeeds/src/Helper/NewsfeedsHelper.php b/administrator/components/com_newsfeeds/src/Helper/NewsfeedsHelper.php index d2733fe1ddc32..febf63625bfa8 100644 --- a/administrator/components/com_newsfeeds/src/Helper/NewsfeedsHelper.php +++ b/administrator/components/com_newsfeeds/src/Helper/NewsfeedsHelper.php @@ -44,7 +44,7 @@ class NewsfeedsHelper extends ContentHelper public static function countItems(&$items) { $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ $db->quoteName('published', 'state'), @@ -101,7 +101,7 @@ public static function countItems(&$items) public static function countTagItems(&$items, $extension) { $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $parts = explode('.', $extension); $section = null; diff --git a/administrator/components/com_newsfeeds/src/Model/NewsfeedModel.php b/administrator/components/com_newsfeeds/src/Model/NewsfeedModel.php index 90878c7430696..7fc7a53a5ad5e 100644 --- a/administrator/components/com_newsfeeds/src/Model/NewsfeedModel.php +++ b/administrator/components/com_newsfeeds/src/Model/NewsfeedModel.php @@ -17,6 +17,7 @@ use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\CMS\Versioning\VersionableModelInterface; use Joomla\CMS\Versioning\VersionableModelTrait; use Joomla\Component\Categories\Administrator\Helper\CategoriesHelper; use Joomla\Registry\Registry; @@ -30,7 +31,7 @@ * * @since 1.6 */ -class NewsfeedModel extends AdminModel +class NewsfeedModel extends AdminModel implements VersionableModelInterface { use VersionableModelTrait; @@ -102,19 +103,16 @@ protected function canEditState($record) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_newsfeeds.newsfeed', 'newsfeed', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - // Modify the form based on access controls. if (!$this->canEditState((object) $data)) { // Disable fields for display. @@ -156,8 +154,8 @@ protected function loadFormData() // Prime some default values. if ($this->getState('newsfeed.id') == 0) { - $app = Factory::getApplication(); - $data->set('catid', $app->getInput()->get('catid', $app->getUserState('com_newsfeeds.newsfeeds.filter.category_id'), 'int')); + $app = Factory::getApplication(); + $data->catid = $app->getInput()->get('catid', $app->getUserState('com_newsfeeds.newsfeeds.filter.category_id'), 'int'); } } @@ -310,7 +308,7 @@ protected function prepareTable($table) // Set ordering to the last item if not set if (empty($table->ordering)) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('MAX(' . $db->quoteName('ordering') . ')') ->from($db->quoteName('#__newsfeeds')); $db->setQuery($query); diff --git a/administrator/components/com_newsfeeds/src/Model/NewsfeedsModel.php b/administrator/components/com_newsfeeds/src/Model/NewsfeedsModel.php index 6d806ec3a06fd..e7a62b1f7c61e 100644 --- a/administrator/components/com_newsfeeds/src/Model/NewsfeedsModel.php +++ b/administrator/components/com_newsfeeds/src/Model/NewsfeedsModel.php @@ -147,7 +147,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = $this->getCurrentUser(); // Select the required fields from the table. @@ -191,7 +191,7 @@ protected function getListQuery() // Join over the associations. if (Associations::isEnabled()) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('COUNT(' . $db->quoteName('asso1.id') . ') > 1') ->from($db->quoteName('#__associations', 'asso1')) ->join('INNER', $db->quoteName('#__associations', 'asso2'), $db->quoteName('asso1.key') . ' = ' . $db->quoteName('asso2.key')) @@ -278,7 +278,7 @@ protected function getListQuery() $includeNone = true; } - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where( @@ -295,7 +295,7 @@ protected function getListQuery() ); if ($includeNone) { - $subQuery2 = $db->getQuery(true) + $subQuery2 = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('type_alias') . ' = ' . $db->quote('com_newsfeeds.newsfeed')); @@ -313,7 +313,7 @@ protected function getListQuery() $tag = (int) $tag; if ($tag === 0) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('type_alias') . ' = ' . $db->quote('com_newsfeeds.newsfeed')); diff --git a/administrator/components/com_newsfeeds/src/Service/HTML/AdministratorService.php b/administrator/components/com_newsfeeds/src/Service/HTML/AdministratorService.php index 1de326795b4f3..97d94dd5d12ce 100644 --- a/administrator/components/com_newsfeeds/src/Service/HTML/AdministratorService.php +++ b/administrator/components/com_newsfeeds/src/Service/HTML/AdministratorService.php @@ -51,7 +51,7 @@ public function association($newsfeedid) // Get the associated newsfeed items $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select( [ diff --git a/administrator/components/com_newsfeeds/src/Table/NewsfeedTable.php b/administrator/components/com_newsfeeds/src/Table/NewsfeedTable.php index 58a4f4c686695..0aa0f05208fea 100644 --- a/administrator/components/com_newsfeeds/src/Table/NewsfeedTable.php +++ b/administrator/components/com_newsfeeds/src/Table/NewsfeedTable.php @@ -177,7 +177,7 @@ public function store($updateNulls = true) } // Verify that the alias is unique - $table = Table::getInstance('NewsfeedTable', __NAMESPACE__ . '\\', ['dbo' => $this->getDatabase()]); + $table = new self($this->getDatabase()); if ($table->load(['alias' => $this->alias, 'catid' => $this->catid]) && ($table->id != $this->id || $this->id == 0)) { // Is the existing newsfeed trashed? diff --git a/administrator/components/com_newsfeeds/src/View/Newsfeed/HtmlView.php b/administrator/components/com_newsfeeds/src/View/Newsfeed/HtmlView.php index 151f87a3f817a..a30422fedb812 100644 --- a/administrator/components/com_newsfeeds/src/View/Newsfeed/HtmlView.php +++ b/administrator/components/com_newsfeeds/src/View/Newsfeed/HtmlView.php @@ -93,7 +93,9 @@ public function display($tpl = null) } // If we are forcing a language in modal (used for associations). - if ($this->getLayout() === 'modal' && $forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'cmd')) { + $forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'cmd'); + + if ($this->getLayout() === 'modal' && $forcedLanguage) { // Set the language field to the forcedLanguage and disable changing it. $this->form->setValue('language', null, $forcedLanguage); $this->form->setFieldAttribute('language', 'readonly', 'true'); @@ -105,6 +107,11 @@ public function display($tpl = null) $this->form->setFieldAttribute('tags', 'language', '*,' . $forcedLanguage); } + // Add form control fields + $this->form + ->addControlField('task') + ->addControlField('forcedLanguage', $forcedLanguage); + if ($this->getLayout() !== 'modal') { $this->addToolbar(); } else { diff --git a/administrator/components/com_newsfeeds/src/View/Newsfeeds/HtmlView.php b/administrator/components/com_newsfeeds/src/View/Newsfeeds/HtmlView.php index df52945d15a32..76d42e26fdf14 100644 --- a/administrator/components/com_newsfeeds/src/View/Newsfeeds/HtmlView.php +++ b/administrator/components/com_newsfeeds/src/View/Newsfeeds/HtmlView.php @@ -105,6 +105,11 @@ public function display($tpl = null) $this->setLayout('emptystate'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + // We don't need toolbar in the modal layout. if ($this->getLayout() !== 'modal') { $this->addToolbar(); @@ -117,7 +122,9 @@ public function display($tpl = null) } else { // In article associations modal we need to remove language filter if forcing a language. // We also need to change the category filter to show show categories with All or the forced language. - if ($forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'CMD')) { + $forcedLanguage = Factory::getApplication()->getInput()->get('forcedLanguage', '', 'CMD'); + + if ($forcedLanguage) { // If the language is forced we can't allow to select the language, so transform the language selector filter into a hidden field. $languageXml = new \SimpleXMLElement(''); $this->filterForm->setField($languageXml, 'filter', true); @@ -128,6 +135,8 @@ public function display($tpl = null) // One last changes needed is to change the category filter to just show categories with All language or with the forced language. $this->filterForm->setFieldAttribute('category_id', 'language', '*,' . $forcedLanguage, 'filter'); } + + $this->filterForm->addControlField('forcedLanguage', $forcedLanguage); } parent::display($tpl); diff --git a/administrator/components/com_newsfeeds/tmpl/newsfeed/edit.php b/administrator/components/com_newsfeeds/tmpl/newsfeed/edit.php index 0122427456644..9aa2867fc0810 100644 --- a/administrator/components/com_newsfeeds/tmpl/newsfeed/edit.php +++ b/administrator/components/com_newsfeeds/tmpl/newsfeed/edit.php @@ -116,7 +116,6 @@
- - - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_newsfeeds/tmpl/newsfeeds/default.php b/administrator/components/com_newsfeeds/tmpl/newsfeeds/default.php index 5b1cf424eb896..1d2a205d34067 100644 --- a/administrator/components/com_newsfeeds/tmpl/newsfeeds/default.php +++ b/administrator/components/com_newsfeeds/tmpl/newsfeeds/default.php @@ -186,9 +186,8 @@ - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_newsfeeds/tmpl/newsfeeds/emptystate.php b/administrator/components/com_newsfeeds/tmpl/newsfeeds/emptystate.php index d9df032a63371..f9cb1223dcb72 100644 --- a/administrator/components/com_newsfeeds/tmpl/newsfeeds/emptystate.php +++ b/administrator/components/com_newsfeeds/tmpl/newsfeeds/emptystate.php @@ -17,8 +17,10 @@ $displayData = [ 'textPrefix' => 'COM_NEWSFEEDS', 'formURL' => 'index.php?option=com_newsfeeds&view=newsfeeds', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:News_Feeds', + 'helpURL' => 'https://guide.joomla.org/user-manual/news-feeds/news-feeds-news-feeds', 'icon' => 'icon-rss newsfeeds', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; $user = $this->getCurrentUser(); diff --git a/administrator/components/com_newsfeeds/tmpl/newsfeeds/modal.php b/administrator/components/com_newsfeeds/tmpl/newsfeeds/modal.php index e048cc5bbf434..a4af92aa16535 100644 --- a/administrator/components/com_newsfeeds/tmpl/newsfeeds/modal.php +++ b/administrator/components/com_newsfeeds/tmpl/newsfeeds/modal.php @@ -27,7 +27,7 @@ $app = Factory::getApplication(); -// @todo: Use of Function is deprecated and should be removed in 6.0. It stays only for backward compatibility. +// @todo: Use of Function is deprecated and should be removed in 7.0. It stays only for backward compatibility. $function = $app->getInput()->getCmd('function', 'jSelectNewsfeed'); $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); @@ -139,10 +139,7 @@ - - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_plugins/helpers/plugins.php b/administrator/components/com_plugins/helpers/plugins.php index 35325f4f180e3..a50009e6339d1 100644 --- a/administrator/components/com_plugins/helpers/plugins.php +++ b/administrator/components/com_plugins/helpers/plugins.php @@ -19,7 +19,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Plugins\Administrator\Helper\PluginsHelper instead */ class PluginsHelper extends \Joomla\Component\Plugins\Administrator\Helper\PluginsHelper diff --git a/administrator/components/com_plugins/src/Field/PluginorderingField.php b/administrator/components/com_plugins/src/Field/PluginorderingField.php index 42e8b36257efc..396a3ae2aa2c7 100644 --- a/administrator/components/com_plugins/src/Field/PluginorderingField.php +++ b/administrator/components/com_plugins/src/Field/PluginorderingField.php @@ -42,7 +42,7 @@ protected function getQuery() $folder = $this->form->getValue('folder'); // Build the query for the ordering list. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('ordering', 'value'), diff --git a/administrator/components/com_plugins/src/Helper/PluginsHelper.php b/administrator/components/com_plugins/src/Helper/PluginsHelper.php index a32bea364ed84..5f00603036283 100644 --- a/administrator/components/com_plugins/src/Helper/PluginsHelper.php +++ b/administrator/components/com_plugins/src/Helper/PluginsHelper.php @@ -13,7 +13,6 @@ use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Installer\Installer; -use Joomla\CMS\Object\CMSObject; use Joomla\Filesystem\Path; // phpcs:disable PSR1.Files.SideEffects @@ -52,7 +51,7 @@ public static function publishedOptions() public static function folderOptions() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT(folder) AS value, folder AS text') ->from('#__extensions') ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) @@ -77,7 +76,7 @@ public static function folderOptions() public static function elementOptions() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT(element) AS value, element AS text') ->from('#__extensions') ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) @@ -99,11 +98,11 @@ public static function elementOptions() * @param string $templateBaseDir Base path to the template directory. * @param string $templateDir Template directory. * - * @return CMSObject|bool + * @return \stdClass|bool */ public function parseXMLTemplateFile($templateBaseDir, $templateDir) { - $data = new CMSObject(); + $data = new \stdClass(); // Check of the xml file exists. $filePath = Path::clean($templateBaseDir . '/templates/' . $templateDir . '/templateDetails.xml'); diff --git a/administrator/components/com_plugins/src/Model/PluginModel.php b/administrator/components/com_plugins/src/Model/PluginModel.php index c12192d5dbd91..5a4f9bb16d1ec 100644 --- a/administrator/components/com_plugins/src/Model/PluginModel.php +++ b/administrator/components/com_plugins/src/Model/PluginModel.php @@ -15,7 +15,6 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\AdminModel; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Router\Route; use Joomla\CMS\Table\Table; use Joomla\Filesystem\Path; @@ -82,9 +81,10 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|bool A Form object on success, false on failure. + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -108,10 +108,6 @@ public function getForm($data = [], $loadData = true) // Get the form. $form = $this->loadForm('com_plugins.plugin', 'plugin', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - // Modify the form based on access controls. if (!$this->canEditState((object) $data)) { // Disable fields for display. @@ -177,9 +173,9 @@ public function getItem($pk = null) return false; } - // Convert to the \Joomla\CMS\Object\CMSObject before adding other data. + // Convert to an object before adding other data. $properties = $table->getProperties(1); - $this->_cache[$cacheId] = ArrayHelper::toObject($properties, CMSObject::class); + $this->_cache[$cacheId] = ArrayHelper::toObject($properties); // Convert the params field to an array. $registry = new Registry($table->params); @@ -254,7 +250,7 @@ protected function preprocessForm(Form $form, $data, $group = 'content') // Load the core and/or local language sys file(s) for the ordering field. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('element')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) @@ -361,15 +357,13 @@ public function getHelp() /** * Custom clean cache method, plugins are cached in 2 places for different clients. * - * @param string $group Cache group name. - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 1.6 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { parent::cleanCache('com_plugins'); } diff --git a/administrator/components/com_plugins/src/Model/PluginsModel.php b/administrator/components/com_plugins/src/Model/PluginsModel.php index 50d193fd1cb5c..a20c718ab6184 100644 --- a/administrator/components/com_plugins/src/Model/PluginsModel.php +++ b/administrator/components/com_plugins/src/Model/PluginsModel.php @@ -203,7 +203,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_plugins/src/View/Plugin/HtmlView.php b/administrator/components/com_plugins/src/View/Plugin/HtmlView.php index 0eeb114fd2816..36685f1e142b3 100644 --- a/administrator/components/com_plugins/src/View/Plugin/HtmlView.php +++ b/administrator/components/com_plugins/src/View/Plugin/HtmlView.php @@ -81,6 +81,10 @@ public function display($tpl = null) return; } + // Add form control fields + $this->form + ->addControlField('task'); + if ($this->getLayout() !== 'modal') { $this->addToolbar(); } else { diff --git a/administrator/components/com_plugins/src/View/Plugins/HtmlView.php b/administrator/components/com_plugins/src/View/Plugins/HtmlView.php index e9713aff4a18f..f47a68cb4db39 100644 --- a/administrator/components/com_plugins/src/View/Plugins/HtmlView.php +++ b/administrator/components/com_plugins/src/View/Plugins/HtmlView.php @@ -83,6 +83,11 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_plugins/tmpl/plugin/edit.php b/administrator/components/com_plugins/tmpl/plugin/edit.php index 1939185cd5f6d..3660b9321376f 100644 --- a/administrator/components/com_plugins/tmpl/plugin/edit.php +++ b/administrator/components/com_plugins/tmpl/plugin/edit.php @@ -134,6 +134,5 @@ - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_plugins/tmpl/plugin/modal.php b/administrator/components/com_plugins/tmpl/plugin/modal.php index d44de9e1a8a77..1222c29d7bda5 100644 --- a/administrator/components/com_plugins/tmpl/plugin/modal.php +++ b/administrator/components/com_plugins/tmpl/plugin/modal.php @@ -13,7 +13,7 @@ /** @var \Joomla\Component\Plugins\Administrator\View\Plugin\HtmlView $this */ // A backward compatibility for bootstrap modals: hide toolbar -// @TODO: Remove in 6.0 +// @TODO: Remove in 7.0 $this->getDocument()->getWebAssetManager()->addInlineScript(' if (window.parent.Joomla.Modal) { const modal = window.parent.Joomla.Modal.getCurrent(); @@ -33,4 +33,3 @@ setLayout('edit'); ?> loadTemplate(); ?> - diff --git a/administrator/components/com_plugins/tmpl/plugins/default.php b/administrator/components/com_plugins/tmpl/plugins/default.php index f56129c5dacd5..d279a8e30af94 100644 --- a/administrator/components/com_plugins/tmpl/plugins/default.php +++ b/administrator/components/com_plugins/tmpl/plugins/default.php @@ -146,8 +146,6 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_postinstall/src/Model/MessagesModel.php b/administrator/components/com_postinstall/src/Model/MessagesModel.php index 0ae8648b5fbf9..78325659a3997 100644 --- a/administrator/components/com_postinstall/src/Model/MessagesModel.php +++ b/administrator/components/com_postinstall/src/Model/MessagesModel.php @@ -10,7 +10,7 @@ namespace Joomla\Component\Postinstall\Administrator\Model; -use Joomla\CMS\Cache\CacheControllerFactoryInterface; +use Joomla\CMS\Cache\CacheController; use Joomla\CMS\Cache\Controller\CallbackController; use Joomla\CMS\Extension\ExtensionHelper; use Joomla\CMS\Factory; @@ -68,7 +68,7 @@ public function getItem($id) $db = $this->getDatabase(); $id = (int) $id; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ $db->quoteName('postinstall_message_id'), @@ -110,7 +110,7 @@ public function unpublishMessage($id) $db = $this->getDatabase(); $id = (int) $id; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->update($db->quoteName('#__postinstall_messages')) ->set($db->quoteName('enabled') . ' = 0') @@ -118,7 +118,7 @@ public function unpublishMessage($id) ->bind(':id', $id, ParameterType::INTEGER); $db->setQuery($query); $db->execute(); - Factory::getCache()->clean('com_postinstall'); + $this->getPostinstallMessagesCache()->clean('com_postinstall'); } /** @@ -135,7 +135,7 @@ public function archiveMessage($id) $db = $this->getDatabase(); $id = (int) $id; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->update($db->quoteName('#__postinstall_messages')) ->set($db->quoteName('enabled') . ' = 2') @@ -143,7 +143,7 @@ public function archiveMessage($id) ->bind(':id', $id, ParameterType::INTEGER); $db->setQuery($query); $db->execute(); - Factory::getCache()->clean('com_postinstall'); + $this->getPostinstallMessagesCache()->clean('com_postinstall'); } /** @@ -160,7 +160,7 @@ public function republishMessage($id) $db = $this->getDatabase(); $id = (int) $id; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->update($db->quoteName('#__postinstall_messages')) ->set($db->quoteName('enabled') . ' = 1') @@ -168,7 +168,7 @@ public function republishMessage($id) ->bind(':id', $id, ParameterType::INTEGER); $db->setQuery($query); $db->execute(); - Factory::getCache()->clean('com_postinstall'); + $this->getPostinstallMessagesCache()->clean('com_postinstall'); } /** @@ -187,7 +187,7 @@ public function getItems() $cacheId = 'postinstall_messages.' . $eid; $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ $db->quoteName('postinstall_message_id'), @@ -216,7 +216,7 @@ public function getItems() try { /** @var CallbackController $cache */ - $cache = $this->getCacheControllerFactory()->createCacheController('callback', ['defaultgroup' => 'com_postinstall']); + $cache = $this->getPostinstallMessagesCache(); $result = $cache->get([$db, 'loadObjectList'], [], md5($cacheId), false); } catch (\RuntimeException $e) { @@ -244,7 +244,7 @@ public function getItems() public function getItemsCount() { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ $db->quoteName('language_extension'), @@ -261,8 +261,7 @@ public function getItemsCount() try { /** @var CallbackController $cache */ - $cache = Factory::getContainer()->get(CacheControllerFactoryInterface::class) - ->createCacheController('callback', ['defaultgroup' => 'com_postinstall']); + $cache = $this->getPostinstallMessagesCache(); // Get the resulting data object for cache ID 'all.1' from com_postinstall group. $result = $cache->get([$db, 'loadObjectList'], [], md5('all.1'), false); @@ -296,7 +295,7 @@ public function getExtensionName($eid) $db = $this->getDatabase(); $eid = (int) $eid; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('name'), @@ -345,7 +344,7 @@ public function resetMessages($eid) $db = $this->getDatabase(); $eid = (int) $eid; - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__postinstall_messages')) ->set($db->quoteName('enabled') . ' = 1') ->where($db->quoteName('extension_id') . ' = :eid') @@ -353,7 +352,7 @@ public function resetMessages($eid) $db->setQuery($query); $result = $db->execute(); - Factory::getCache()->clean('com_postinstall'); + $this->getPostinstallMessagesCache()->clean('com_postinstall'); return $result; } @@ -372,7 +371,7 @@ public function hideMessages($eid) $db = $this->getDatabase(); $eid = (int) $eid; - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__postinstall_messages')) ->set($db->quoteName('enabled') . ' = 0') ->where($db->quoteName('extension_id') . ' = :eid') @@ -380,7 +379,7 @@ public function hideMessages($eid) $db->setQuery($query); $result = $db->execute(); - Factory::getCache()->clean('com_postinstall'); + $this->getPostinstallMessagesCache()->clean('com_postinstall'); return $result; } @@ -453,7 +452,7 @@ public function getComponentOptions() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__postinstall_messages')) ->group($db->quoteName('extension_id')); @@ -668,7 +667,7 @@ public function addPostInstallationMessage(array $options) $extensionId = (int) $options['extension_id']; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName($tableName)) ->where( @@ -701,7 +700,7 @@ public function addPostInstallationMessage(array $options) } // Otherwise it's not the same row. Remove the old row before insert a new one. - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName($tableName)) ->where( [ @@ -720,7 +719,8 @@ public function addPostInstallationMessage(array $options) // Insert the new row $options = (object) $options; $db->insertObject($tableName, $options); - Factory::getCache()->clean('com_postinstall'); + + $this->getPostinstallMessagesCache()->clean('com_postinstall'); return $this; } @@ -736,4 +736,17 @@ public function getJoomlaFilesExtensionId() { return ExtensionHelper::getExtensionRecord('joomla', 'file')->extension_id; } + + /** + * Get cache controller instance for postinstall messages caching. + * + * @return CacheController + * + * @since 6.2.0 + */ + private function getPostinstallMessagesCache(): CacheController + { + return $this->getCacheControllerFactory() + ->createCacheController('callback', ['defaultgroup' => 'com_postinstall']); + } } diff --git a/administrator/components/com_postinstall/src/View/Messages/HtmlView.php b/administrator/components/com_postinstall/src/View/Messages/HtmlView.php index a9c596c63c491..955d80a3ecaf8 100644 --- a/administrator/components/com_postinstall/src/View/Messages/HtmlView.php +++ b/administrator/components/com_postinstall/src/View/Messages/HtmlView.php @@ -65,7 +65,7 @@ public function display($tpl = null) $this->toolbar(); - $this->token = Factory::getSession()->getFormToken(); + $this->token = Factory::getApplication()->getSession()->getFormToken(); $this->extension_options = $model->getComponentOptions(); ToolbarHelper::title(Text::sprintf('COM_POSTINSTALL_MESSAGES_TITLE', $model->getExtensionName($this->eid)), 'bell'); diff --git a/administrator/components/com_privacy/src/Helper/PrivacyHelper.php b/administrator/components/com_privacy/src/Helper/PrivacyHelper.php index 325cfc48b3877..1d4b8250ea485 100644 --- a/administrator/components/com_privacy/src/Helper/PrivacyHelper.php +++ b/administrator/components/com_privacy/src/Helper/PrivacyHelper.php @@ -73,7 +73,7 @@ public static function renderDataAsXml(array $exportData) public static function getPrivacyConsentPluginId() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) diff --git a/administrator/components/com_privacy/src/Model/ConsentsModel.php b/administrator/components/com_privacy/src/Model/ConsentsModel.php index ccfcbb0eec388..76617f0a97ad2 100644 --- a/administrator/components/com_privacy/src/Model/ConsentsModel.php +++ b/administrator/components/com_privacy/src/Model/ConsentsModel.php @@ -65,7 +65,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select($this->getState('list.select', 'a.*')); @@ -182,7 +182,7 @@ public function invalidate($pks) try { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__privacy_consents')) ->set($db->quoteName('state') . ' = -1') ->whereIn($db->quoteName('id'), $pks) @@ -209,7 +209,7 @@ public function invalidateAll($subject) { try { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__privacy_consents')) ->set($db->quoteName('state') . ' = -1') ->where($db->quoteName('subject') . ' = :subject') diff --git a/administrator/components/com_privacy/src/Model/ExportModel.php b/administrator/components/com_privacy/src/Model/ExportModel.php index 8ae502d1d713b..35683e2ca526f 100644 --- a/administrator/components/com_privacy/src/Model/ExportModel.php +++ b/administrator/components/com_privacy/src/Model/ExportModel.php @@ -14,7 +14,11 @@ use Joomla\CMS\Event\Privacy\ExportRequestEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Language; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Text; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Model\BaseDatabaseModel; use Joomla\CMS\Plugin\PluginHelper; @@ -37,9 +41,11 @@ * * @since 3.9.0 */ -class ExportModel extends BaseDatabaseModel implements UserFactoryAwareInterface +class ExportModel extends BaseDatabaseModel implements UserFactoryAwareInterface, MailerFactoryAwareInterface, LanguageFactoryAwareInterface { use UserFactoryAwareTrait; + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; /** * Create the export document for an information request. @@ -85,7 +91,7 @@ public function collectDataForExportRequest($id = null) $db = $this->getDatabase(); $userId = (int) $db->setQuery( - $db->getQuery(true) + $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(:email)') @@ -179,7 +185,7 @@ public function emailDataExport($id = null) $db = $this->getDatabase(); $userId = (int) $db->setQuery( - $db->getQuery(true) + $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(:email)') @@ -212,7 +218,12 @@ public function emailDataExport($id = null) // The mailer can be set to either throw Exceptions or return boolean false, account for both try { $app = Factory::getApplication(); - $mailer = new MailTemplate('com_privacy.userdataexport', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_privacy.userdataexport', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $templateData = [ 'sitename' => $app->get('sitename'), diff --git a/administrator/components/com_privacy/src/Model/RemoveModel.php b/administrator/components/com_privacy/src/Model/RemoveModel.php index 864e79a840455..741840031510f 100644 --- a/administrator/components/com_privacy/src/Model/RemoveModel.php +++ b/administrator/components/com_privacy/src/Model/RemoveModel.php @@ -81,7 +81,7 @@ public function removeDataForRequest($id = null) $db = $this->getDatabase(); $userId = (int) $db->setQuery( - $db->getQuery(true) + $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(:email)') diff --git a/administrator/components/com_privacy/src/Model/RequestModel.php b/administrator/components/com_privacy/src/Model/RequestModel.php index 47b531c848b6e..3ad7988dba5a3 100644 --- a/administrator/components/com_privacy/src/Model/RequestModel.php +++ b/administrator/components/com_privacy/src/Model/RequestModel.php @@ -14,8 +14,12 @@ use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Language; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Text; use Joomla\CMS\Mail\Exception\MailDisabledException; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Router\Route; @@ -38,9 +42,11 @@ * * @since 3.9.0 */ -class RequestModel extends AdminModel implements UserFactoryAwareInterface +class RequestModel extends AdminModel implements UserFactoryAwareInterface, MailerFactoryAwareInterface, LanguageFactoryAwareInterface { use UserFactoryAwareTrait; + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; /** * Clean the cache @@ -62,20 +68,14 @@ protected function cleanCache($group = 'com_privacy') * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 3.9.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_privacy.request', 'request', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_privacy.request', 'request', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -264,7 +264,7 @@ public function notifyUserAdminCreatedRequest($id) $db = $this->getDatabase(); $userId = (int) $db->setQuery( - $db->getQuery(true) + $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(:email)') @@ -324,12 +324,22 @@ public function notifyUserAdminCreatedRequest($id) switch ($table->request_type) { case 'export': - $mailer = new MailTemplate('com_privacy.notification.admin.export', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_privacy.notification.admin.export', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); break; case 'remove': - $mailer = new MailTemplate('com_privacy.notification.admin.remove', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_privacy.notification.admin.remove', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); break; @@ -411,7 +421,7 @@ public function validate($form, $data, $group = null) // Check for an active request for this email address $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(id)') ->from($db->quoteName('#__privacy_requests')) ->where($db->quoteName('email') . ' = :email') diff --git a/administrator/components/com_privacy/src/Model/RequestsModel.php b/administrator/components/com_privacy/src/Model/RequestsModel.php index f28ac566aba2e..4b2724ffb377f 100644 --- a/administrator/components/com_privacy/src/Model/RequestsModel.php +++ b/administrator/components/com_privacy/src/Model/RequestsModel.php @@ -62,7 +62,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select($this->getState('list.select', 'a.*')); @@ -171,7 +171,7 @@ public function getNumberUrgentRequests() $period = '-' . $notify; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)'); $query->from($db->quoteName('#__privacy_requests')); $query->where($db->quoteName('status') . ' = 1 '); diff --git a/administrator/components/com_privacy/src/Plugin/PrivacyPlugin.php b/administrator/components/com_privacy/src/Plugin/PrivacyPlugin.php index 1317ef650b634..f37560ee0446e 100644 --- a/administrator/components/com_privacy/src/Plugin/PrivacyPlugin.php +++ b/administrator/components/com_privacy/src/Plugin/PrivacyPlugin.php @@ -36,7 +36,7 @@ abstract class PrivacyPlugin extends CMSPlugin * * @var \Joomla\Database\DatabaseDriver * @since 3.9.0 - * @deprecated 4.4.0 will be removed in 6.0 use $this->getDatabase() instead + * @deprecated 4.4.0 will be removed in 7.0 use $this->getDatabase() instead */ protected $db; diff --git a/administrator/components/com_privacy/src/View/Consents/HtmlView.php b/administrator/components/com_privacy/src/View/Consents/HtmlView.php index 95bfd32591708..9b45e340fdeb3 100644 --- a/administrator/components/com_privacy/src/View/Consents/HtmlView.php +++ b/administrator/components/com_privacy/src/View/Consents/HtmlView.php @@ -105,6 +105,11 @@ public function display($tpl = null) $this->setLayout('emptystate'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_privacy/src/View/Request/HtmlView.php b/administrator/components/com_privacy/src/View/Request/HtmlView.php index 968e806e8a2c0..1862bd11ed1b4 100644 --- a/administrator/components/com_privacy/src/View/Request/HtmlView.php +++ b/administrator/components/com_privacy/src/View/Request/HtmlView.php @@ -98,6 +98,10 @@ public function display($tpl = null) // Variables only required for the edit layout if ($this->getLayout() === 'edit') { $this->form = $model->getForm(); + + // Add form control fields + $this->form + ->addControlField('task'); } $this->addToolbar(); diff --git a/administrator/components/com_privacy/src/View/Requests/HtmlView.php b/administrator/components/com_privacy/src/View/Requests/HtmlView.php index 14e52693dc7b5..0ec21d7b7ee19 100644 --- a/administrator/components/com_privacy/src/View/Requests/HtmlView.php +++ b/administrator/components/com_privacy/src/View/Requests/HtmlView.php @@ -117,6 +117,11 @@ public function display($tpl = null) $this->setLayout('emptystate'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_privacy/tmpl/consents/default.php b/administrator/components/com_privacy/tmpl/consents/default.php index 73d9e7fd90c28..0f26a4228b6a8 100644 --- a/administrator/components/com_privacy/tmpl/consents/default.php +++ b/administrator/components/com_privacy/tmpl/consents/default.php @@ -123,8 +123,6 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_privacy/tmpl/consents/emptystate.php b/administrator/components/com_privacy/tmpl/consents/emptystate.php index c9f60e961f396..370fbe14c5b94 100644 --- a/administrator/components/com_privacy/tmpl/consents/emptystate.php +++ b/administrator/components/com_privacy/tmpl/consents/emptystate.php @@ -17,6 +17,8 @@ 'formURL' => 'index.php?option=com_privacy&view=consents', 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Privacy:_Consents', 'icon' => 'icon-lock', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; echo LayoutHelper::render('joomla.content.emptystate', $displayData); diff --git a/administrator/components/com_privacy/tmpl/request/edit.php b/administrator/components/com_privacy/tmpl/request/edit.php index c29e4134b394e..15aa480caa16f 100644 --- a/administrator/components/com_privacy/tmpl/request/edit.php +++ b/administrator/components/com_privacy/tmpl/request/edit.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -35,7 +34,6 @@ - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_privacy/tmpl/requests/default.php b/administrator/components/com_privacy/tmpl/requests/default.php index 954c9ec399d1b..7ac43b100299a 100644 --- a/administrator/components/com_privacy/tmpl/requests/default.php +++ b/administrator/components/com_privacy/tmpl/requests/default.php @@ -82,11 +82,11 @@ status == 1 && $item->request_type === 'export') : ?> sendMailEnabled) : ?> - + status == 1 && $item->request_type === 'remove') : ?> - + @@ -123,8 +123,6 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_privacy/tmpl/requests/emptystate.php b/administrator/components/com_privacy/tmpl/requests/emptystate.php index 804dd09f628ef..65216d3857b48 100644 --- a/administrator/components/com_privacy/tmpl/requests/emptystate.php +++ b/administrator/components/com_privacy/tmpl/requests/emptystate.php @@ -18,6 +18,8 @@ 'formURL' => 'index.php?option=com_privacy&view=requests', 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Privacy:_Information_Requests', 'icon' => 'icon-lock', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; if (Factory::getApplication()->get('mailonline', 1)) { diff --git a/administrator/components/com_redirect/helpers/redirect.php b/administrator/components/com_redirect/helpers/redirect.php index 5013c15cac79b..4fac1bc0efd24 100644 --- a/administrator/components/com_redirect/helpers/redirect.php +++ b/administrator/components/com_redirect/helpers/redirect.php @@ -18,7 +18,7 @@ * Redirect component helper. * * @since 1.6 - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Redirect\Administrator\Helper\RedirectHelp instead */ class RedirectHelper extends \Joomla\Component\Redirect\Administrator\Helper\RedirectHelper diff --git a/administrator/components/com_redirect/src/Helper/RedirectHelper.php b/administrator/components/com_redirect/src/Helper/RedirectHelper.php index 8cf148fd8ab85..0adc03fec439d 100644 --- a/administrator/components/com_redirect/src/Helper/RedirectHelper.php +++ b/administrator/components/com_redirect/src/Helper/RedirectHelper.php @@ -63,7 +63,7 @@ public static function publishedOptions() public static function getRedirectPluginId() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) diff --git a/administrator/components/com_redirect/src/Model/LinkModel.php b/administrator/components/com_redirect/src/Model/LinkModel.php index 69af0758524a1..ae1d51f229ca3 100644 --- a/administrator/components/com_redirect/src/Model/LinkModel.php +++ b/administrator/components/com_redirect/src/Model/LinkModel.php @@ -12,6 +12,7 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\AdminModel; @@ -58,19 +59,16 @@ protected function canDelete($record) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_redirect.link', 'link', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - // Modify the form based on access controls. if (!$this->canEditState((object)$data)) { // Disable fields for display. @@ -145,7 +143,7 @@ public function activate(&$pks, $url, $comment = null) if (!empty($pks)) { // Update the link rows. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__redirect_links')) ->set($db->quoteName('new_url') . ' = :url') ->set($db->quoteName('published') . ' = 1') @@ -199,7 +197,7 @@ public function duplicateUrls(&$pks, $url, $comment = null) $date = Factory::getDate()->toSql(); // Update the link rows. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__redirect_links')) ->set($db->quoteName('new_url') . ' = :url') ->set($db->quoteName('modified_date') . ' = :date') diff --git a/administrator/components/com_redirect/src/Model/LinksModel.php b/administrator/components/com_redirect/src/Model/LinksModel.php index 8fde16f511534..4f7eef13414b5 100644 --- a/administrator/components/com_redirect/src/Model/LinksModel.php +++ b/administrator/components/com_redirect/src/Model/LinksModel.php @@ -65,7 +65,7 @@ public function purge() { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete('#__redirect_links')->where($db->quoteName('published') . '= 0'); @@ -136,7 +136,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( @@ -204,7 +204,7 @@ protected function getListQuery() public function batchProcess($batchUrls) { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $params = ComponentHelper::getParams('com_redirect'); $state = (int) $params->get('defaultImportState', 0); diff --git a/administrator/components/com_redirect/src/Table/LinkTable.php b/administrator/components/com_redirect/src/Table/LinkTable.php index 73f4172137d99..b75bb302fb0e2 100644 --- a/administrator/components/com_redirect/src/Table/LinkTable.php +++ b/administrator/components/com_redirect/src/Table/LinkTable.php @@ -99,7 +99,7 @@ public function check() $db = $this->getDatabase(); // Check for existing name - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->select($db->quoteName('old_url')) ->from($db->quoteName('#__redirect_links')) diff --git a/administrator/components/com_redirect/src/View/Link/HtmlView.php b/administrator/components/com_redirect/src/View/Link/HtmlView.php index b976c02115c3c..63488d23b0d87 100644 --- a/administrator/components/com_redirect/src/View/Link/HtmlView.php +++ b/administrator/components/com_redirect/src/View/Link/HtmlView.php @@ -74,6 +74,10 @@ public function display($tpl = null) throw new GenericDataException(implode("\n", $errors), 500); } + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); } diff --git a/administrator/components/com_redirect/src/View/Links/HtmlView.php b/administrator/components/com_redirect/src/View/Links/HtmlView.php index c7e60655172b7..6d2e71c2afb0d 100644 --- a/administrator/components/com_redirect/src/View/Links/HtmlView.php +++ b/administrator/components/com_redirect/src/View/Links/HtmlView.php @@ -139,6 +139,11 @@ public function display($tpl = null) $this->redirectPluginId = RedirectHelper::getRedirectPluginId(); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_redirect/tmpl/link/edit.php b/administrator/components/com_redirect/tmpl/link/edit.php index 6cc9b7d0cb9f0..f746eb9cf4234 100644 --- a/administrator/components/com_redirect/tmpl/link/edit.php +++ b/administrator/components/com_redirect/tmpl/link/edit.php @@ -43,7 +43,6 @@ - - + form->renderControlFields(); ?>
diff --git a/administrator/components/com_redirect/tmpl/links/default.php b/administrator/components/com_redirect/tmpl/links/default.php index e3264a20df01d..7c85bf5754872 100644 --- a/administrator/components/com_redirect/tmpl/links/default.php +++ b/administrator/components/com_redirect/tmpl/links/default.php @@ -177,8 +177,6 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_redirect/tmpl/links/emptystate.php b/administrator/components/com_redirect/tmpl/links/emptystate.php index c5b709f637558..12fcaed2dd1d1 100644 --- a/administrator/components/com_redirect/tmpl/links/emptystate.php +++ b/administrator/components/com_redirect/tmpl/links/emptystate.php @@ -25,6 +25,8 @@ 'formURL' => 'index.php?option=com_redirect&view=links', 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:Redirects:_Links', 'icon' => 'icon-map-signs redirect', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; $app = Factory::getApplication(); diff --git a/administrator/components/com_scheduler/src/Model/LogModel.php b/administrator/components/com_scheduler/src/Model/LogModel.php index 825c5b0a1aa4e..0218e867f05cf 100644 --- a/administrator/components/com_scheduler/src/Model/LogModel.php +++ b/administrator/components/com_scheduler/src/Model/LogModel.php @@ -31,7 +31,7 @@ class LogModel extends AdminModel * @param array $data Data that needs to go into the form * @param bool $loadData Should the form load its data from the DB? * - * @return Form|boolean A Form object on success, false on failure. + * @return Form|boolean A Form object, false on failure. * * @since 5.3.0 * @throws \Exception diff --git a/administrator/components/com_scheduler/src/Model/LogsModel.php b/administrator/components/com_scheduler/src/Model/LogsModel.php index 3823e6da9a423..3da2e19fab4ad 100644 --- a/administrator/components/com_scheduler/src/Model/LogsModel.php +++ b/administrator/components/com_scheduler/src/Model/LogsModel.php @@ -130,7 +130,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_scheduler/src/Model/TaskModel.php b/administrator/components/com_scheduler/src/Model/TaskModel.php index ab09cf12f872e..889c1059f5e70 100644 --- a/administrator/components/com_scheduler/src/Model/TaskModel.php +++ b/administrator/components/com_scheduler/src/Model/TaskModel.php @@ -20,7 +20,6 @@ use Joomla\CMS\Log\Log; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\AdminModel; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Table\Table; use Joomla\Component\Scheduler\Administrator\Helper\ExecRuleHelper; @@ -154,7 +153,7 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null, * @param array $data Data that needs to go into the form * @param bool $loadData Should the form load its data from the DB? * - * @return Form|boolean A Form object on success, false on failure. + * @return Form A Form object * * @since 4.1.0 * @throws \Exception @@ -170,10 +169,6 @@ public function getForm($data = [], $loadData = true) */ $form = $this->loadForm('com_scheduler.task', 'task', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - $user = $this->app->getIdentity(); // If new entry, set task type from state @@ -274,7 +269,6 @@ protected function loadFormData() // If the data from UserState is empty, we fetch it with getItem() if (empty($data)) { - /** @var CMSObject $data */ $data = $this->getItem(); // @todo : further data processing goes here @@ -323,14 +317,14 @@ public function getItem($pk = null) } // Parent call leaves `execution_rules` and `cron_rules` JSON encoded - $item->set('execution_rules', json_decode($item->get('execution_rules', ''))); - $item->set('cron_rules', json_decode($item->get('cron_rules', ''))); + $item->execution_rules = json_decode($item->execution_rules ?? ''); + $item->cron_rules = json_decode($item->cron_rules ?? ''); $taskOption = SchedulerHelper::getTaskOptions()->findOption( ($item->id ?? 0) ? ($item->type ?? 0) : $this->getState('task.type') ); - $item->set('taskOption', $taskOption); + $item->taskOption = $taskOption; return $item; } @@ -424,7 +418,7 @@ private function hasRunningTasks($db): bool $timeout = ComponentHelper::getParams('com_scheduler')->get('timeout', 300); $threshold = (clone $now)->modify("-$timeout seconds")->toSql(); - $lockCountQuery = $db->getQuery(true) + $lockCountQuery = $db->createQuery() ->select('COUNT(id)') ->from($db->quoteName(self::TASK_TABLE)) ->where($db->quoteName('locked') . ' IS NOT NULL') @@ -456,7 +450,7 @@ private function hasRunningTasks($db): bool */ private function buildLockQuery($db, $now, $options) { - $lockQuery = $db->getQuery(true) + $lockQuery = $db->createQuery() ->update($db->quoteName(self::TASK_TABLE)) ->set($db->quoteName('locked') . ' = :now1') ->bind(':now1', $now); @@ -501,7 +495,7 @@ static function (TaskOption $taskOption): string { */ private function getNextTaskId($db, $now, $options) { - $idQuery = $db->getQuery(true) + $idQuery = $db->createQuery() ->from($db->quoteName(self::TASK_TABLE)) ->select($db->quoteName('id')); @@ -549,7 +543,7 @@ static function (TaskOption $taskOption): string { */ private function fetchTask($db, $now): ?\stdClass { - $getQuery = $db->getQuery(true) + $getQuery = $db->createQuery() ->select('*') ->from($db->quoteName(self::TASK_TABLE)) ->where($db->quoteName('locked') . ' = :now') @@ -619,7 +613,7 @@ public function save($data): bool $basisDayOfMonth = $data['execution_rules']['exec-day']; [$basisHour, $basisMinute] = explode(':', $data['execution_rules']['exec-time']); - $data['last_execution'] = Factory::getDate('now', 'GMT')->format('Y-m') + $data['last_execution'] = Factory::getDate('now', 'UTC')->format('Y-m') . "-$basisDayOfMonth $basisHour:$basisMinute:00"; } else { $item = $this->getItem($id); diff --git a/administrator/components/com_scheduler/src/Model/TasksModel.php b/administrator/components/com_scheduler/src/Model/TasksModel.php index 3e04c9ebef29a..946e0c1a29d7d 100644 --- a/administrator/components/com_scheduler/src/Model/TasksModel.php +++ b/administrator/components/com_scheduler/src/Model/TasksModel.php @@ -16,7 +16,6 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; -use Joomla\CMS\Object\CMSObject; use Joomla\Component\Scheduler\Administrator\Helper\SchedulerHelper; use Joomla\Component\Scheduler\Administrator\Task\TaskOption; use Joomla\Database\ParameterType; @@ -113,7 +112,7 @@ protected function getListQuery(): QueryInterface { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); /** * Select the required fields from the table. @@ -254,7 +253,7 @@ static function (TaskOption $taskOption): string { $due = $this->getState('filter.due'); if (is_numeric($due) && $due != 0) { - $now = Factory::getDate('now', 'GMT')->toSql(); + $now = Factory::getDate('now', 'UTC')->toSql(); $operator = $due == 1 ? ' <= ' : ' > '; $filterCount++; $query->where($db->quoteName('a.next_execution') . $operator . ':now') @@ -271,7 +270,7 @@ static function (TaskOption $taskOption): string { $locked = $this->getState('filter.locked'); if (is_numeric($locked) && $locked != 0) { - $now = Factory::getDate('now', 'GMT'); + $now = Factory::getDate('now', 'UTC'); $timeout = ComponentHelper::getParams('com_scheduler')->get('timeout', 300); $timeout = new \DateInterval(\sprintf('PT%dS', $timeout)); $timeoutThreshold = (clone $now)->sub($timeout)->toSql(); @@ -385,25 +384,7 @@ protected function _getList($query, $limitstart = 0, $limit = 0): array // Set limit parameters and get object list $query->setLimit($limit, $limitstart); $this->getDatabase()->setQuery($query); - - // Return optionally an extended class. - // @todo: Use something other than CMSObject.. - if ($this->getState('list.customClass')) { - $responseList = array_map( - static function (array $arr) { - $o = new CMSObject(); - - foreach ($arr as $k => $v) { - $o->{$k} = $v; - } - - return $o; - }, - $this->getDatabase()->loadAssocList() ?: [] - ); - } else { - $responseList = $this->getDatabase()->loadObjectList(); - } + $responseList = $this->getDatabase()->loadObjectList(); // Attach TaskOptions objects and a safe type title $this->attachTaskOptions($responseList); @@ -506,7 +487,7 @@ public function hasDueTasks(Date $time): bool $timeout = ComponentHelper::getParams('com_scheduler')->get('timeout', 300); $threshold = (clone $time)->modify("-$timeout seconds")->toSql(); - $query = $db->getQuery(true) + $query = $db->createQuery() // Count due tasks ->select('SUM(CASE WHEN ' . $db->quoteName('a.next_execution') . ' <= :now THEN 1 ELSE 0 END) AS due_count') // Count locked tasks diff --git a/administrator/components/com_scheduler/src/Scheduler/Scheduler.php b/administrator/components/com_scheduler/src/Scheduler/Scheduler.php index f5eb2260990f1..76e5f705247d7 100644 --- a/administrator/components/com_scheduler/src/Scheduler/Scheduler.php +++ b/administrator/components/com_scheduler/src/Scheduler/Scheduler.php @@ -123,7 +123,7 @@ public function runTask(array $options): ?Task $app->getLanguage()->load('com_scheduler', JPATH_ADMINISTRATOR); - $options['text_entry_format'] = '{DATE} {TIME} {PRIORITY} {MESSAGE}'; + $options['text_entry_format'] = "{DATE}\t{TIME}\t{PRIORITY}\t{MESSAGE}"; $options['text_file'] = 'joomla_scheduler.php'; Log::addLogger($options, Log::ALL, $task->logCategory); @@ -344,13 +344,7 @@ public static function isAuthorizedToRun(object $taskRecord, User $user): bool * We allow the user to run a task if they have the permission or if they created the task & still have the authority * to create tasks. */ - if ( - $user->authorise('core.testrun', 'com_scheduler.task.' . $taskRecord->id) - || ($user->id == $taskRecord->created_by && $user->authorise('core.create', 'com_scheduler')) - ) { - return true; - } - - return false; + return $user->authorise('core.testrun', 'com_scheduler.task.' . $taskRecord->id) + || ($user->id == $taskRecord->created_by && $user->authorise('core.create', 'com_scheduler')); } } diff --git a/administrator/components/com_scheduler/src/Table/TaskTable.php b/administrator/components/com_scheduler/src/Table/TaskTable.php index 19e34778e81e9..a710d8ab487d3 100644 --- a/administrator/components/com_scheduler/src/Table/TaskTable.php +++ b/administrator/components/com_scheduler/src/Table/TaskTable.php @@ -289,7 +289,7 @@ public function unlock(array $pks = [], ?int $userId = null): bool foreach ($pks as $pk) { // Update the publishing state for rows with the given primary keys. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($this->_tbl) ->set($db->quoteName($lockedField) . ' = NULL'); diff --git a/administrator/components/com_scheduler/src/Task/Task.php b/administrator/components/com_scheduler/src/Task/Task.php index 7144be82153c2..a73bf360e0653 100644 --- a/administrator/components/com_scheduler/src/Task/Task.php +++ b/administrator/components/com_scheduler/src/Task/Task.php @@ -148,7 +148,7 @@ public function __construct(object $record) if ($this->get('params.individual_log')) { $logFile = $this->get('params.log_file') ?? 'task_' . $this->get('id') . '.log.php'; - $options['text_entry_format'] = '{DATE} {TIME} {PRIORITY} {MESSAGE}'; + $options['text_entry_format'] = "{DATE}\t{TIME}\t{PRIORITY}\t{MESSAGE}"; $options['text_file'] = $logFile; Log::addLogger($options, Log::ALL, [$this->logCategory]); } @@ -305,9 +305,9 @@ public function getContent(): array public function acquireLock(): bool { $db = $this->db; - $query = $db->getQuery(true); + $query = $db->createQuery(); $id = $this->get('id'); - $now = Factory::getDate('now', 'GMT'); + $now = Factory::getDate('now', 'UTC'); $timeout = ComponentHelper::getParams('com_scheduler')->get('timeout', 300); $timeout = new \DateInterval(\sprintf('PT%dS', $timeout)); @@ -361,7 +361,7 @@ public function acquireLock(): bool public function releaseLock(bool $update = true): bool { $db = $this->db; - $query = $db->getQuery(true); + $query = $db->createQuery(); $id = $this->get('id'); $query->update($db->quoteName('#__scheduler_tasks', 't')) @@ -433,7 +433,7 @@ public function log(string $message, string $priority = 'info'): void public function skipExecution(): void { $db = $this->db; - $query = $db->getQuery(true); + $query = $db->createQuery(); $id = $this->get('id'); $nextExec = (new ExecRuleHelper($this->taskRegistry->toObject()))->nextExec(true, true); @@ -553,10 +553,6 @@ public static function isValidId(string $id): bool { $id = is_numeric($id) ? ($id + 0) : $id; - if (!\is_int($id) || $id <= 0) { - return false; - } - - return true; + return \is_int($id) && $id > 0; } } diff --git a/administrator/components/com_scheduler/src/Traits/TaskPluginTrait.php b/administrator/components/com_scheduler/src/Traits/TaskPluginTrait.php index 6461cb26915a4..57a545cc7f7f4 100644 --- a/administrator/components/com_scheduler/src/Traits/TaskPluginTrait.php +++ b/administrator/components/com_scheduler/src/Traits/TaskPluginTrait.php @@ -169,6 +169,10 @@ public function advertiseRoutines(EventInterface $event): void { $options = []; + // In case if the plugin is lazy loaded we might not initialise the object + // That means autoloading the language is not executed + $this->loadLanguage(); + foreach (self::TASKS_MAP as $routineId => $details) { // Sanity check against non-compliant plugins if (isset($details['langConstPrefix'])) { diff --git a/administrator/components/com_scheduler/src/View/Logs/HtmlView.php b/administrator/components/com_scheduler/src/View/Logs/HtmlView.php index 5b3a0160ab208..3a65a89fc270d 100644 --- a/administrator/components/com_scheduler/src/View/Logs/HtmlView.php +++ b/administrator/components/com_scheduler/src/View/Logs/HtmlView.php @@ -10,13 +10,13 @@ namespace Joomla\Component\Scheduler\Administrator\View\Logs; +use Joomla\CMS\Document\HtmlDocument; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Helper\ContentHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; use Joomla\CMS\Pagination\Pagination; -use Joomla\CMS\Toolbar\Toolbar; use Joomla\CMS\Toolbar\ToolbarHelper; use Joomla\Registry\Registry; @@ -93,6 +93,11 @@ public function display($tpl = null): void $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); } @@ -106,8 +111,10 @@ public function display($tpl = null): void */ protected function addToolbar(): void { - $canDo = ContentHelper::getActions('com_scheduler'); - $toolbar = Toolbar::getInstance(); + /** @var HtmlDocument $document */ + $document = $this->getDocument(); + $canDo = ContentHelper::getActions('com_scheduler'); + $toolbar = $document->getToolbar(); ToolbarHelper::title(Text::_('COM_SCHEDULER_FIELDSET_EXEC_HIST'), 'list'); diff --git a/administrator/components/com_scheduler/src/View/Task/HtmlView.php b/administrator/components/com_scheduler/src/View/Task/HtmlView.php index f7fbeff76443a..4ace46cf69048 100644 --- a/administrator/components/com_scheduler/src/View/Task/HtmlView.php +++ b/administrator/components/com_scheduler/src/View/Task/HtmlView.php @@ -118,6 +118,10 @@ public function display($tpl = null): void $this->state = $model->getState(); $this->canDo = ContentHelper::getActions('com_scheduler', 'task', $this->item->id); + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_scheduler/src/View/Tasks/HtmlView.php b/administrator/components/com_scheduler/src/View/Tasks/HtmlView.php index 6119990e7357c..72e2e88cb1786 100644 --- a/administrator/components/com_scheduler/src/View/Tasks/HtmlView.php +++ b/administrator/components/com_scheduler/src/View/Tasks/HtmlView.php @@ -106,6 +106,11 @@ public function display($tpl = null): void $this->setLayout('empty_state'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_scheduler/tmpl/logs/default.php b/administrator/components/com_scheduler/tmpl/logs/default.php index 20e656982ecba..8872b6ce28196 100644 --- a/administrator/components/com_scheduler/tmpl/logs/default.php +++ b/administrator/components/com_scheduler/tmpl/logs/default.php @@ -17,7 +17,7 @@ use Joomla\CMS\Uri\Uri; /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ -$wa = $this->document->getWebAssetManager(); +$wa = $this->getDocument()->getWebAssetManager(); $wa->useScript('table.columns') ->useScript('multiselect'); @@ -133,9 +133,8 @@ ?> pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_scheduler/tmpl/select/default.php b/administrator/components/com_scheduler/tmpl/select/default.php index 10d4939f39a50..fefbc189718b2 100644 --- a/administrator/components/com_scheduler/tmpl/select/default.php +++ b/administrator/components/com_scheduler/tmpl/select/default.php @@ -16,9 +16,8 @@ use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; -use Joomla\Component\Scheduler\Administrator\View\Select\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Scheduler\Administrator\View\Select\HtmlView $this */ $app = $this->app; diff --git a/administrator/components/com_scheduler/tmpl/task/edit.php b/administrator/components/com_scheduler/tmpl/task/edit.php index 8240b1996cb4e..1608277851139 100644 --- a/administrator/components/com_scheduler/tmpl/task/edit.php +++ b/administrator/components/com_scheduler/tmpl/task/edit.php @@ -17,9 +17,8 @@ use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\Component\Scheduler\Administrator\Task\TaskOption; -use Joomla\Component\Scheduler\Administrator\View\Task\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Scheduler\Administrator\View\Task\HtmlView $this */ $wa = $this->getDocument()->getWebAssetManager(); @@ -198,7 +197,7 @@ class="form-validate"> form->getInput('context'); ?> - - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_scheduler/tmpl/tasks/default.php b/administrator/components/com_scheduler/tmpl/tasks/default.php index 5d02098463977..abef34beaa7b7 100644 --- a/administrator/components/com_scheduler/tmpl/tasks/default.php +++ b/administrator/components/com_scheduler/tmpl/tasks/default.php @@ -20,9 +20,8 @@ use Joomla\CMS\Session\Session; use Joomla\Component\Scheduler\Administrator\Scheduler\Scheduler; use Joomla\Component\Scheduler\Administrator\Task\Status; -use Joomla\Component\Scheduler\Administrator\View\Tasks\HtmlView; -/** @var HtmlView $this*/ +/** @var \Joomla\Component\Scheduler\Administrator\View\Tasks\HtmlView $this*/ /** @var \Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->getDocument()->getWebAssetManager(); @@ -301,8 +300,6 @@ class="js-draggable" data-url="" data-direction=" - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_scheduler/tmpl/tasks/empty_state.php b/administrator/components/com_scheduler/tmpl/tasks/empty_state.php index 0665fd68284d0..dd82ce3cdf777 100644 --- a/administrator/components/com_scheduler/tmpl/tasks/empty_state.php +++ b/administrator/components/com_scheduler/tmpl/tasks/empty_state.php @@ -15,10 +15,11 @@ /** @var \Joomla\Component\Scheduler\Administrator\View\Tasks\HtmlView $this */ $displayData = [ - 'textPrefix' => 'COM_SCHEDULER', - 'formURL' => 'index.php?option=com_scheduler&task=task.add', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/J4.x:Task_Scheduler', - 'icon' => 'icon-clock clock', + 'textPrefix' => 'COM_SCHEDULER', + 'formURL' => 'index.php?option=com_scheduler&task=task.add', + 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/J4.x:Task_Scheduler', + 'icon' => 'icon-clock clock', + 'controlFields' => $this->filterForm->renderControlFields(), ]; if ($this->getCurrentUser()->authorise('core.create', 'com_scheduler')) { diff --git a/administrator/components/com_tags/src/Model/TagModel.php b/administrator/components/com_tags/src/Model/TagModel.php index b4e1901670743..06ed62fa7ae39 100644 --- a/administrator/components/com_tags/src/Model/TagModel.php +++ b/administrator/components/com_tags/src/Model/TagModel.php @@ -12,10 +12,16 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Date\Date; +use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\Model\BeforeSaveEvent; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Versioning\VersionableModelInterface; use Joomla\CMS\Versioning\VersionableModelTrait; +use Joomla\Database\ParameterType; use Joomla\Registry\Registry; use Joomla\String\StringHelper; @@ -28,7 +34,7 @@ * * @since 3.1 */ -class TagModel extends AdminModel +class TagModel extends AdminModel implements VersionableModelInterface { use VersionableModelTrait; @@ -44,6 +50,15 @@ class TagModel extends AdminModel */ public $typeAlias = 'com_tags.tag'; + /** + * Batch copy/move command. If set to false, + * the batch copy/move command is not supported. + * + * @var string + * @since 6.1.0 + */ + protected $batch_copymove = 'tag_id'; + /** * Allowed batch commands * @@ -73,6 +88,22 @@ protected function canDelete($record) return parent::canDelete($record); } + /** + * Method to get a table object, load it if necessary. + * + * @param string $type The table name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return \Joomla\Cms\Table\Table|\Joomla\Cms\Table\Nested A Table object + * + * @since 6.1.0 + */ + public function getTable($type = 'Tag', $prefix = 'Administrator', $config = []) + { + return parent::getTable($type, $prefix, $config); + } + /** * Auto-populate the model state. * @@ -148,9 +179,10 @@ public function getItem($pk = null) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return bool|\Joomla\CMS\Form\Form A Form object on success, false on failure + * @return Form A Form object * * @since 3.1 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -159,10 +191,6 @@ public function getForm($data = [], $loadData = true) // Get the form. $form = $this->loadForm('com_tags.tag', 'tag', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - $user = $this->getCurrentUser(); if (!$user->authorise('core.edit.state', 'com_tags' . $jinput->get('id'))) { @@ -219,7 +247,8 @@ public function save($data) $context = $this->option . '.' . $this->name; // Include the plugins for the save events. - PluginHelper::importPlugin($this->events_map['save']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['save'], null, true, $dispatcher); try { // Load the row if saving an existing tag. @@ -267,7 +296,12 @@ public function save($data) } // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, [$context, $table, $isNew, $data]); + $result = $dispatcher->dispatch($this->event_before_save, new BeforeSaveEvent($this->event_before_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ]))->getArgument('result', []); if (\in_array(false, $result, true)) { $this->setError($table->getError()); @@ -283,7 +317,12 @@ public function save($data) } // Trigger the after save event. - Factory::getApplication()->triggerEvent($this->event_after_save, [$context, $table, $isNew]); + $dispatcher->dispatch($this->event_after_save, new AfterSaveEvent($this->event_after_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ])); // Rebuild the path for the tag: if (!$table->rebuildPath($table->id)) { @@ -307,6 +346,9 @@ public function save($data) $this->setState($this->getName() . '.id', $table->id); $this->setState($this->getName() . '.new', $isNew); + // Save version history. + $this->saveHistory($data, $context); + // Clear the cache $this->cleanCache(); @@ -403,11 +445,295 @@ protected function generateNewTitle($parentId, $alias, $title) $table = $this->getTable(); - while ($table->load(['alias' => $alias, 'parent_id' => $parentId])) { + while ($table->load(['alias' => $alias])) { $title = ($table->title != $title) ? $title : StringHelper::increment($title); $alias = StringHelper::increment($alias, 'dash'); } return [$title, $alias]; } + + + /** + * Batch copy tags to a new tag or parent. + * + * @param integer $value The new tag or sub-item. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return array|false An array of new IDs on success, boolean false on failure. + * + * @since 6.1.0 + */ + protected function batchCopy($value, $pks, $contexts) + { + $parentId = (int) $value; + $table = $this->getTable(); + $db = $this->getDatabase(); + $query = $db->getQuery(true); + $newIds = []; + + // Check that the parent exists + if ($parentId) { + if (!$table->load($parentId)) { + if ($error = $table->getError()) { + // Fatal error + $this->setError($error); + + return false; + } + // Non-fatal error + $this->setError(Text::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND')); + $parentId = 0; + } + } + + // If the parent is 0, set it to the ID of the root item in the tree + if (empty($parentId)) { + if (!$parentId = $table->getRootId()) { + $this->setError($table->getError()); + + return false; + } + } + + // Check that user has create permission for tags + if (!$this->getCurrentUser()->authorise('core.create', 'com_tags')) { + $this->setError(Text::_('COM_TAGS_BATCH_COPY_MOVE_CANNOT_CREATE')); + + return false; + } + + // We need to log the parent ID + $parents = []; + + // Calculate the emergency stop count as a precaution against a runaway loop bug + $query->select('COUNT(' . $db->quoteName('id') . ')') + ->from($db->quoteName('#__tags')); + $db->setQuery($query); + + try { + $count = $db->loadResult(); + } catch (\RuntimeException $e) { + $this->setError($e->getMessage()); + + return false; + } + + // Parent exists so let's proceed + while (!empty($pks) && $count > 0) { + // Pop the first id off the stack + $pk = array_shift($pks); + + $table->reset(); + + // Check that the row actually exists + if (!$table->load($pk)) { + if ($error = $table->getError()) { + // Fatal error + $this->setError($error); + + return false; + } + // Non-fatal error + $this->setError(Text::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Check that the user is allowed to access the item + if (!$this->user->authorise('core.edit', $contexts[$pk])) { + $this->setError(Text::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + + return false; + } + + // Copy is a bit tricky, because we also need to copy the children + $query = $db->getQuery(true) + ->select($db->quoteName('id')) + ->from($db->quoteName('#__tags')) + ->where( + [ + $db->quoteName('lft') . ' > :lft', + $db->quoteName('rgt') . ' < :rgt', + ] + ) + ->bind(':lft', $table->lft, ParameterType::INTEGER) + ->bind(':rgt', $table->rgt, ParameterType::INTEGER); + $db->setQuery($query); + $childIds = $db->loadColumn(); + + // Add child IDs to the array only if they aren't already there. + foreach ($childIds as $childId) { + if (!\in_array($childId, $pks)) { + $pks[] = $childId; + } + } + + // Make a copy of the old ID and Parent ID + $oldId = $table->id; + $oldParentId = $table->parent_id; + + // Reset the id because we are making a copy. + $table->id = 0; + + // If we are copying children, the Old ID will turn up in the parents list + // otherwise it's a new top level item + $table->parent_id = $parents[$oldParentId] ?? $parentId; + + // Set the new location in the tree for the node. + $table->setLocation($table->parent_id, 'last-child'); + + // @todo: Deal with ordering? + // $table->ordering = 1; + $table->level = null; + $table->lft = null; + $table->rgt = null; + + // Alter the title & alias + [$title, $alias] = $this->generateNewTitle($table->parent_id, $table->alias, $table->title); + $table->title = $title; + $table->alias = $alias; + + // Unpublish because we are making a copy + $table->published = 0; + + // Check the row. + if (!$table->check()) { + $this->setError($table->getError()); + + return false; + } + + // Store the row. + if (!$table->store()) { + $this->setError($table->getError()); + + return false; + } + + // Get the new item ID + $newId = $table->id; + + // Add the new ID to the array + $newIds[$pk] = $newId; + + // Now we log the old 'parent' to the new 'parent' + $parents[$oldId] = $table->id; + $count--; + } + + // Rebuild the hierarchy. + if (!$table->rebuild()) { + $this->setError($table->getError()); + + return false; + } + + // Rebuild the tree path. + if (!$table->rebuildPath($table->id)) { + $this->setError($table->getError()); + + return false; + } + + // Clean the cache + $this->cleanCache(); + + return $newIds; + } + + /** + * Batch move tags to a new tag or parent. + * + * @param integer $value The new tag or sub-item. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * + * @return boolean True on success. + * + * @since 6.1.0 + */ + protected function batchMove($value, $pks, $contexts) + { + $parentId = (int) $value; + $table = $this->getTable(); + + // Check that the parent exists. + if ($parentId) { + if (!$table->load($parentId)) { + if ($error = $table->getError()) { + // Fatal error + $this->setError($error); + + return false; + } + // Non-fatal error + $this->setError(Text::_('JGLOBAL_BATCH_MOVE_PARENT_NOT_FOUND')); + $parentId = 0; + } + } + + // Check that user has create and edit permission for tags + $user = $this->getCurrentUser(); + + if (!$user->authorise('core.create', 'com_tags')) { + $this->setError(Text::_('COM_TAGS_BATCH_COPY_MOVE_CANNOT_CREATE')); + + return false; + } + + if (!$user->authorise('core.edit', 'com_tags')) { + $this->setError(Text::_('COM_TAGS_BATCH_COPY_MOVE_CANNOT_EDIT')); + + return false; + } + + // Parent exists so let's proceed + foreach ($pks as $pk) { + // Check that the row actually exists + if (!$table->load($pk)) { + if ($error = $table->getError()) { + // Fatal error + $this->setError($error); + + return false; + } + // Non-fatal error + $this->setError(Text::sprintf('JGLOBAL_BATCH_MOVE_ROW_NOT_FOUND', $pk)); + continue; + } + + // Set the new location in the tree for the node. + $table->setLocation($parentId, 'last-child'); + + // Set the new Parent Id + $table->parent_id = $parentId; + + // Check the row. + if (!$table->check()) { + $this->setError($table->getError()); + + return false; + } + + // Store the row. + if (!$table->store()) { + $this->setError($table->getError()); + + return false; + } + + // Rebuild the tree path. + if (!$table->rebuildPath()) { + $this->setError($table->getError()); + + return false; + } + } + + // Clean the cache + $this->cleanCache(); + + return true; + } } diff --git a/administrator/components/com_tags/src/Model/TagsModel.php b/administrator/components/com_tags/src/Model/TagsModel.php index 2dde7f9b3a5e6..e9319d0e2fe79 100644 --- a/administrator/components/com_tags/src/Model/TagsModel.php +++ b/administrator/components/com_tags/src/Model/TagsModel.php @@ -147,7 +147,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = $this->getCurrentUser(); // Select the required fields from the table. @@ -183,7 +183,7 @@ protected function getListQuery() ->join('LEFT', $db->quoteName('#__viewlevels', 'ug'), $db->quoteName('ug.id') . ' = ' . $db->quoteName('a.access')); // Count Items - $subQueryCountTaggedItems = $db->getQuery(true); + $subQueryCountTaggedItems = $db->createQuery(); $subQueryCountTaggedItems ->select('COUNT(' . $db->quoteName('tag_map.content_item_id') . ')') ->from($db->quoteName('#__contentitem_tag_map', 'tag_map')) diff --git a/administrator/components/com_tags/src/Table/TagTable.php b/administrator/components/com_tags/src/Table/TagTable.php index d130fc92cc0b4..307e0a647c4ac 100644 --- a/administrator/components/com_tags/src/Table/TagTable.php +++ b/administrator/components/com_tags/src/Table/TagTable.php @@ -17,7 +17,6 @@ use Joomla\CMS\Table\Nested; use Joomla\CMS\User\CurrentUserInterface; use Joomla\CMS\User\CurrentUserTrait; -use Joomla\CMS\Versioning\VersionableTableInterface; use Joomla\Database\DatabaseInterface; use Joomla\Event\DispatcherInterface; use Joomla\String\StringHelper; @@ -31,7 +30,7 @@ * * @since 3.1 */ -class TagTable extends Nested implements VersionableTableInterface, CurrentUserInterface +class TagTable extends Nested implements CurrentUserInterface { use CurrentUserTrait; diff --git a/administrator/components/com_tags/src/View/Tag/HtmlView.php b/administrator/components/com_tags/src/View/Tag/HtmlView.php index 465dc376268da..ed9bf66b428d0 100644 --- a/administrator/components/com_tags/src/View/Tag/HtmlView.php +++ b/administrator/components/com_tags/src/View/Tag/HtmlView.php @@ -93,6 +93,10 @@ public function display($tpl = null) $this->item = $model->getItem(); $this->state = $model->getState(); + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_tags/src/View/Tags/HtmlView.php b/administrator/components/com_tags/src/View/Tags/HtmlView.php index 986f2648bcc94..fd022137589f8 100644 --- a/administrator/components/com_tags/src/View/Tags/HtmlView.php +++ b/administrator/components/com_tags/src/View/Tags/HtmlView.php @@ -113,6 +113,11 @@ public function display($tpl = null) $this->ordering[$item->parent_id][] = $item->id; } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + // We don't need toolbar in the modal window. if ($this->getLayout() !== 'modal') { $this->addToolbar(); diff --git a/administrator/components/com_tags/tmpl/tag/edit.php b/administrator/components/com_tags/tmpl/tag/edit.php index 9b23c6acec63c..d269eeac902c0 100644 --- a/administrator/components/com_tags/tmpl/tag/edit.php +++ b/administrator/components/com_tags/tmpl/tag/edit.php @@ -74,6 +74,6 @@ - - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_tags/tmpl/tags/default.php b/administrator/components/com_tags/tmpl/tags/default.php index a3b20bea037f1..d033dbf341b38 100644 --- a/administrator/components/com_tags/tmpl/tags/default.php +++ b/administrator/components/com_tags/tmpl/tags/default.php @@ -10,6 +10,7 @@ defined('_JEXEC') or die; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Multilanguage; @@ -17,7 +18,6 @@ use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Session\Session; -use Joomla\String\Inflector; /** @var \Joomla\Component\Tags\Administrator\View\Tags\HtmlView $this */ @@ -40,10 +40,10 @@ if (count($parts) > 1) { $section = $parts[1]; - $inflector = Inflector::getInstance(); + $inflector = InflectorFactory::create()->build(); - if (!$inflector->isPlural($section)) { - $section = $inflector->toPlural($section); + if ($inflector->pluralize($inflector->singularize($section)) !== $section) { + $section = $inflector->pluralize($section); } } @@ -263,8 +263,6 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_tags/tmpl/tags/default_batch_body.php b/administrator/components/com_tags/tmpl/tags/default_batch_body.php index ad996a4f58883..bf3ded2f3e1a3 100644 --- a/administrator/components/com_tags/tmpl/tags/default_batch_body.php +++ b/administrator/components/com_tags/tmpl/tags/default_batch_body.php @@ -10,9 +10,19 @@ defined('_JEXEC') or die; +use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; + +$options = [ + HTMLHelper::_('select.option', 'c', Text::_('JLIB_HTML_BATCH_COPY')), + HTMLHelper::_('select.option', 'm', Text::_('JLIB_HTML_BATCH_MOVE')) +]; + +/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ +$wa = $this->getDocument()->getWebAssetManager(); +$wa->useScript('joomla.batch-copymove'); ?>
@@ -30,6 +40,24 @@
+
+
+
+ + +
+
+ + +
+
+
diff --git a/administrator/components/com_tags/tmpl/tags/emptystate.php b/administrator/components/com_tags/tmpl/tags/emptystate.php index ab70fe7c796d7..d48e8cc7a993a 100644 --- a/administrator/components/com_tags/tmpl/tags/emptystate.php +++ b/administrator/components/com_tags/tmpl/tags/emptystate.php @@ -17,8 +17,10 @@ $displayData = [ 'textPrefix' => 'COM_TAGS', 'formURL' => 'index.php?option=com_tags&task=tag.add', - 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/J4.x:How_To_Use_Content_Tags_in_Joomla', + 'helpURL' => 'https://guide.joomla.org/user-manual/tags', 'icon' => 'icon-tags tags', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; if ($this->getCurrentUser()->authorise('core.create', 'com_tags')) { diff --git a/administrator/components/com_templates/helpers/template.php b/administrator/components/com_templates/helpers/template.php index 466fd798258af..eb822df1920e5 100644 --- a/administrator/components/com_templates/helpers/template.php +++ b/administrator/components/com_templates/helpers/template.php @@ -19,7 +19,7 @@ * * @since 3.2 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Templates\Administrator\Helper\TemplateHelper instead */ abstract class TemplateHelper extends \Joomla\Component\Templates\Administrator\Helper\TemplateHelper diff --git a/administrator/components/com_templates/helpers/templates.php b/administrator/components/com_templates/helpers/templates.php index 9b583f2cd99b8..8819852e56f7b 100644 --- a/administrator/components/com_templates/helpers/templates.php +++ b/administrator/components/com_templates/helpers/templates.php @@ -19,7 +19,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Templates\Administrator\Helper\TemplatesHelper instead */ class TemplatesHelper extends \Joomla\Component\Templates\Administrator\Helper\TemplatesHelper diff --git a/administrator/components/com_templates/src/Controller/StyleController.php b/administrator/components/com_templates/src/Controller/StyleController.php index c9df25cb8fc4b..1549908cd32e0 100644 --- a/administrator/components/com_templates/src/Controller/StyleController.php +++ b/administrator/components/com_templates/src/Controller/StyleController.php @@ -58,9 +58,9 @@ public function save($key = null, $urlVar = null) $item = $model->getItem($this->app->getTemplate(true)->id); // Setting received params - $item->set('params', $data); + $item->params = $data; - $data = $item->getProperties(); + $data = get_object_vars($item); unset($data['xml']); $key = $table->getKeyName(); diff --git a/administrator/components/com_templates/src/Helper/TemplateHelper.php b/administrator/components/com_templates/src/Helper/TemplateHelper.php index 2b1297e2c111b..a50a62f4d11f7 100644 --- a/administrator/components/com_templates/src/Helper/TemplateHelper.php +++ b/administrator/components/com_templates/src/Helper/TemplateHelper.php @@ -67,7 +67,7 @@ public static function canUpload($file, $err = '') 'exe', 'phtml','java', 'perl', 'py', 'asp','dll', 'go', 'jar', 'ade', 'adp', 'bat', 'chm', 'cmd', 'com', 'cpl', 'hta', 'ins', 'isp', 'jse', 'lib', 'mde', 'msc', 'msp', 'mst', 'pif', 'scr', 'sct', 'shb', - 'sys', 'vb', 'vbe', 'vbs', 'vxd', 'wsc', 'wsf', 'wsh', + 'sys', 'vb', 'vbe', 'vbs', 'vxd', 'wsc', 'wsf', 'wsh', 'shtml', 'shtm', 'sht', 'stm', ]; $explodedFileName = explode('.', $file['name']); @@ -143,28 +143,6 @@ public static function canUpload($file, $err = '') return false; } - $xss_check = file_get_contents($file['tmp_name'], false, null, -1, 256); - $html_tags = [ - 'abbr', 'acronym', 'address', 'applet', 'area', 'audioscope', 'base', 'basefont', 'bdo', 'bgsound', 'big', 'blackface', 'blink', 'blockquote', - 'body', 'bq', 'br', 'button', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'comment', 'custom', 'dd', 'del', 'dfn', 'dir', 'div', - 'dl', 'dt', 'em', 'embed', 'fieldset', 'fn', 'font', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'html', - 'iframe', 'ilayer', 'img', 'input', 'ins', 'isindex', 'keygen', 'kbd', 'label', 'layer', 'legend', 'li', 'limittext', 'link', 'listing', - 'map', 'marquee', 'menu', 'meta', 'multicol', 'nobr', 'noembed', 'noframes', 'noscript', 'nosmartquotes', 'object', 'ol', 'optgroup', 'option', - 'param', 'plaintext', 'pre', 'rt', 'ruby', 's', 'samp', 'script', 'select', 'server', 'shadow', 'sidebar', 'small', 'spacer', 'span', 'strike', - 'strong', 'style', 'sub', 'sup', 'table', 'tbody', 'td', 'textarea', 'tfoot', 'th', 'thead', 'title', 'tr', 'tt', 'ul', 'var', 'wbr', 'xml', - 'xmp', '!DOCTYPE', '!--', - ]; - - foreach ($html_tags as $tag) { - // A tag is '' - if (stristr($xss_check, '<' . $tag . ' ') || stristr($xss_check, '<' . $tag . '>')) { - $app = Factory::getApplication(); - $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_WARNIEXSS'), 'error'); - - return false; - } - } - return true; } } diff --git a/administrator/components/com_templates/src/Helper/TemplatesHelper.php b/administrator/components/com_templates/src/Helper/TemplatesHelper.php index 615354706b65b..ae92fd48a37ab 100644 --- a/administrator/components/com_templates/src/Helper/TemplatesHelper.php +++ b/administrator/components/com_templates/src/Helper/TemplatesHelper.php @@ -14,7 +14,6 @@ use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Installer\Installer; use Joomla\CMS\Language\Text; -use Joomla\CMS\Object\CMSObject; use Joomla\Database\ParameterType; use Joomla\Filesystem\Path; @@ -55,7 +54,7 @@ public static function getTemplateOptions($clientId = '*') { // Build the filter options. $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('element', 'value')) ->select($db->quoteName('name', 'text')) @@ -82,11 +81,11 @@ public static function getTemplateOptions($clientId = '*') * @param string $templateBaseDir * @param string $templateDir * - * @return boolean|CMSObject + * @return \stdClass|false */ public static function parseXMLTemplateFile($templateBaseDir, $templateDir) { - $data = new CMSObject(); + $data = new \stdClass(); // Check of the xml file exists $filePath = Path::clean($templateBaseDir . '/templates/' . $templateDir . '/templateDetails.xml'); diff --git a/administrator/components/com_templates/src/Model/StyleModel.php b/administrator/components/com_templates/src/Model/StyleModel.php index ee5ed39d665aa..027afb4fe85b9 100644 --- a/administrator/components/com_templates/src/Model/StyleModel.php +++ b/administrator/components/com_templates/src/Model/StyleModel.php @@ -11,6 +11,10 @@ namespace Joomla\Component\Templates\Administrator\Model; use Joomla\CMS\Application\ApplicationHelper; +use Joomla\CMS\Event\Model\AfterDeleteEvent; +use Joomla\CMS\Event\Model\AfterSaveEvent; +use Joomla\CMS\Event\Model\BeforeDeleteEvent; +use Joomla\CMS\Event\Model\BeforeSaveEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Multilanguage; @@ -18,7 +22,7 @@ use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Plugin\PluginHelper; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; use Joomla\Database\ParameterType; use Joomla\Filesystem\Path; use Joomla\String\StringHelper; @@ -93,7 +97,8 @@ public function delete(&$pks) $table = $this->getTable(); $context = $this->option . '.' . $this->name; - PluginHelper::importPlugin($this->events_map['delete']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['delete'], null, true, $dispatcher); // Iterate the items to delete each one. foreach ($pks as $pk) { @@ -111,7 +116,13 @@ public function delete(&$pks) } // Trigger the before delete event. - $result = Factory::getApplication()->triggerEvent($this->event_before_delete, [$context, $table]); + $result = $dispatcher->dispatch( + $this->event_before_delete, + new BeforeDeleteEvent($this->event_before_delete, [ + 'context' => $context, + 'subject' => $table, + ]) + )->getArgument('result', []); if (\in_array(false, $result, true) || !$table->delete($pk)) { $this->setError($table->getError()); @@ -120,7 +131,10 @@ public function delete(&$pks) } // Trigger the after delete event. - Factory::getApplication()->triggerEvent($this->event_after_delete, [$context, $table]); + $dispatcher->dispatch($this->event_after_delete, new AfterDeleteEvent($this->event_after_delete, [ + 'context' => $context, + 'subject' => $table, + ])); } else { $this->setError($table->getError()); @@ -155,7 +169,8 @@ public function duplicate(&$pks) $context = $this->option . '.' . $this->name; // Include the plugins for the save events. - PluginHelper::importPlugin($this->events_map['save']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['save'], null, true, $dispatcher); $table = $this->getTable(); @@ -176,14 +191,22 @@ public function duplicate(&$pks) } // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, [$context, &$table, true]); + $result = $dispatcher->dispatch($this->event_before_save, new BeforeSaveEvent($this->event_before_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => true, + ]))->getArgument('result', []); if (\in_array(false, $result, true) || !$table->store()) { throw new \Exception($table->getError()); } // Trigger the after save event. - Factory::getApplication()->triggerEvent($this->event_after_save, [$context, &$table, true]); + $dispatcher->dispatch($this->event_after_save, new AfterSaveEvent($this->event_after_save, [ + 'context' => $context, + 'subject' => $table, + 'isNew' => true, + ])); } else { throw new \Exception($table->getError()); } @@ -224,9 +247,10 @@ protected function generateNewTitle($categoryId, $alias, $title) * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -290,7 +314,7 @@ protected function loadFormData() * * @param integer $pk The id of the primary key. * - * @return mixed Object on success, false on failure. + * @return \stdClass|false Object on success, false on failure. */ public function getItem($pk = null) { @@ -397,7 +421,7 @@ protected function preprocessForm(Form $form, $data, $group = 'content') public function save($data) { // Detect disabled extension - $extension = Table::getInstance('Extension', 'Joomla\\CMS\\Table\\'); + $extension = new Extension($this->getDatabase()); if ($extension->load(['enabled' => 0, 'type' => 'template', 'element' => $data['template'], 'client_id' => $data['client_id']])) { $this->setError(Text::_('COM_TEMPLATES_ERROR_SAVE_DISABLED_TEMPLATE')); @@ -411,7 +435,8 @@ public function save($data) $isNew = true; // Include the extension plugins for the save events. - PluginHelper::importPlugin($this->events_map['save']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['save'], null, true, $dispatcher); // Load the row if saving an existing record. if ($pk > 0) { @@ -443,7 +468,12 @@ public function save($data) } // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, ['com_templates.style', &$table, $isNew]); + $result = $dispatcher->dispatch($this->event_before_save, new BeforeSaveEvent($this->event_before_save, [ + 'context' => 'com_templates.style', + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ]))->getArgument('result', []); // Store the data. if (\in_array(false, $result, true) || !$table->store()) { @@ -465,7 +495,7 @@ public function save($data) $data['assigned'] = ArrayHelper::toInteger($data['assigned']); // Update the mapping for menu items that this style IS assigned to. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__menu')) ->set($db->quoteName('template_style_id') . ' = :newtsid') ->whereIn($db->quoteName('id'), $data['assigned']) @@ -481,7 +511,7 @@ public function save($data) // Remove style mappings for menu items this style is NOT assigned to. // If unassigned then all existing maps will be removed. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__menu')) ->set($db->quoteName('template_style_id') . ' = 0'); @@ -507,7 +537,12 @@ public function save($data) $this->cleanCache(); // Trigger the after save event. - Factory::getApplication()->triggerEvent($this->event_after_save, ['com_templates.style', &$table, $isNew]); + $dispatcher->dispatch($this->event_after_save, new AfterSaveEvent($this->event_after_save, [ + 'context' => 'com_templates.style', + 'subject' => $table, + 'isNew' => $isNew, + 'data' => $data, + ])); $this->setState('style.id', $table->id); @@ -540,7 +575,7 @@ public function setHome($id = 0) } // Detect disabled extension - $extension = Table::getInstance('Extension', 'Joomla\\CMS\\Table\\'); + $extension = new Extension($this->getDatabase()); if ($extension->load(['enabled' => 0, 'type' => 'template', 'element' => $style->template, 'client_id' => $style->client_id])) { throw new \Exception(Text::_('COM_TEMPLATES_ERROR_SAVE_DISABLED_TEMPLATE')); @@ -550,7 +585,7 @@ public function setHome($id = 0) $id = (int) $id; // Reset the home fields for the client_id. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__template_styles')) ->set($db->quoteName('home') . ' = ' . $db->quote('0')) ->where($db->quoteName('client_id') . ' = :clientid') @@ -560,7 +595,7 @@ public function setHome($id = 0) $db->execute(); // Set the new home style. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__template_styles')) ->set($db->quoteName('home') . ' = ' . $db->quote('1')) ->where($db->quoteName('id') . ' = :id') @@ -596,7 +631,7 @@ public function unsetHome($id = 0) $id = (int) $id; // Lookup the client_id. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['client_id', 'home'])) ->from($db->quoteName('#__template_styles')) ->where($db->quoteName('id') . ' = :id') @@ -613,7 +648,7 @@ public function unsetHome($id = 0) } // Set the new home style. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__template_styles')) ->set($db->quoteName('home') . ' = ' . $db->quote('0')) ->where($db->quoteName('id') . ' = :id') @@ -651,8 +686,8 @@ public function getHelp() public function getAdminTemplate(int $styleId): \stdClass { $db = $this->getDatabase(); - $query = $db->getQuery(true) - ->select($db->quoteName(['s.template', 's.params', 's.inheritable', 's.parent'])) + $query = $db->createQuery() + ->select($db->quoteName(['s.template', 's.params', 's.inheritable', 's.parent', 'e.custom_data'])) ->from($db->quoteName('#__template_styles', 's')) ->join( 'LEFT', @@ -696,8 +731,8 @@ public function getAdminTemplate(int $styleId): \stdClass public function getSiteTemplates(): array { $db = $this->getDatabase(); - $query = $db->getQuery(true) - ->select($db->quoteName(['id', 'home', 'template', 's.params', 'inheritable', 'parent'])) + $query = $db->createQuery() + ->select($db->quoteName(['id', 'home', 'template', 's.params', 'inheritable', 'parent', 'e.custom_data'])) ->from($db->quoteName('#__template_styles', 's')) ->where( [ @@ -721,15 +756,13 @@ public function getSiteTemplates(): array /** * Custom clean cache method * - * @param string $group The cache group - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 1.6 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { parent::cleanCache('com_templates'); parent::cleanCache('_system'); diff --git a/administrator/components/com_templates/src/Model/StylesModel.php b/administrator/components/com_templates/src/Model/StylesModel.php index ea93fa73af4a2..c370e330aa040 100644 --- a/administrator/components/com_templates/src/Model/StylesModel.php +++ b/administrator/components/com_templates/src/Model/StylesModel.php @@ -117,7 +117,7 @@ protected function getListQuery() // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( @@ -201,14 +201,14 @@ protected function getListQuery() // If user selected the templates styles assigned to particular pages. // Subquery to get the language of the selected menu item. $menuItemId = (int) $menuItemId; - $menuItemLanguageSubQuery = $db->getQuery(true); + $menuItemLanguageSubQuery = $db->createQuery(); $menuItemLanguageSubQuery->select($db->quoteName('language')) ->from($db->quoteName('#__menu')) ->where($db->quoteName('id') . ' = :menuitemid'); $query->bind(':menuitemid', $menuItemId, ParameterType::INTEGER); // Subquery to get the language of the selected menu item. - $templateStylesMenuItemsSubQuery = $db->getQuery(true); + $templateStylesMenuItemsSubQuery = $db->createQuery(); $templateStylesMenuItemsSubQuery->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->where($db->quoteName('template_style_id') . ' = ' . $db->quoteName('a.id')); diff --git a/administrator/components/com_templates/src/Model/TemplateModel.php b/administrator/components/com_templates/src/Model/TemplateModel.php index 39f9056c1ada4..112876f14ca83 100644 --- a/administrator/components/com_templates/src/Model/TemplateModel.php +++ b/administrator/components/com_templates/src/Model/TemplateModel.php @@ -129,7 +129,7 @@ public function getTemplateList() $db = $this->getDatabase(); // Create a new query object. - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table $query->select( @@ -169,7 +169,7 @@ public function getUpdatedList($state = false, $all = false, $cleanup = false) $db = $this->getDatabase(); // Create a new query object. - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table $query->select( @@ -316,7 +316,7 @@ public function publish($ids, $value, $exid) foreach ($ids as $id) { if ($value === -3) { - $deleteQuery = $db->getQuery(true) + $deleteQuery = $db->createQuery() ->delete($db->quoteName('#__template_overrides')) ->where($db->quoteName('hash_id') . ' = :hashid') ->where($db->quoteName('extension_id') . ' = :exid') @@ -331,7 +331,7 @@ public function publish($ids, $value, $exid) return $e; } } elseif ($value === 1 || $value === 0) { - $updateQuery = $db->getQuery(true) + $updateQuery = $db->createQuery() ->update($db->quoteName('#__template_overrides')) ->set($db->quoteName('state') . ' = :state') ->where($db->quoteName('hash_id') . ' = :hashid') @@ -370,12 +370,14 @@ public function getFiles() $path = Path::clean($client->path . '/templates/' . $template->element . '/'); $lang = Factory::getLanguage(); - // Load the core and/or local language file(s). + // Load the parent and child overrides for template language constants + if (!empty($template->xmldata->parent)) { + $lang->load('tpl_' . $template->xmldata->parent, $client->path) + || $lang->load('tpl_' . $template->xmldata->parent, $client->path . '/templates/' . $template->xmldata->parent); + } + $lang->load('tpl_' . $template->element, $client->path) - || (!empty($template->xmldata->parent) && $lang->load('tpl_' . $template->xmldata->parent, $client->path)) - || $lang->load('tpl_' . $template->element, $client->path . '/templates/' . $template->element) - || (!empty($template->xmldata->parent) && $lang->load('tpl_' . $template->xmldata->parent, $client->path . '/templates/' . $template->xmldata->parent)); - $this->element = $path; + || $lang->load('tpl_' . $template->element, $client->path . '/templates/' . $template->element); if (!is_writable($path)) { $app->enqueueMessage(Text::_('COM_TEMPLATES_DIRECTORY_NOT_WRITABLE'), 'error'); @@ -645,7 +647,7 @@ public function getTemplate() $app = Factory::getApplication(); // Get the template information. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['extension_id', 'client_id', 'element', 'name', 'manifest_cache'])) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('extension_id') . ' = :pk') @@ -691,7 +693,7 @@ public function checkNewName() { $db = $this->getDatabase(); $name = $this->getState('new_name'); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__extensions')) ->where($db->quoteName('name') . ' = :name') @@ -777,11 +779,7 @@ public function copy() } // Adjust to new template name - if (!$this->fixTemplateName()) { - return false; - } - - return true; + return $this->fixTemplateName(); } $app->enqueueMessage(Text::_('COM_TEMPLATES_ERROR_INVALID_FROM_NAME'), 'error'); @@ -825,6 +823,11 @@ protected function fixTemplateName() $oldName = $template->element; $manifest = json_decode($template->manifest_cache); + // When copying a child template we need to prefix it with the parent template name + if (!empty($template->xmldata->parent)) { + $newName = $template->xmldata->parent . '_' . $newName; + } + foreach ($files as $file) { $newFile = '/' . str_replace($oldName, $newName, basename($file)); @@ -864,9 +867,10 @@ protected function fixTemplateName() * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -874,7 +878,7 @@ public function getForm($data = [], $loadData = true) // Codemirror or Editor None should be enabled $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from('#__extensions as a') ->where( @@ -891,13 +895,7 @@ public function getForm($data = [], $loadData = true) } // Get the form. - $form = $this->loadForm('com_templates.source', 'source', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_templates.source', 'source', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -1394,8 +1392,10 @@ public function uploadFile($file, $location) return false; } + // Allow "unsafe" files: template files legitimately contain PHP, which the File::upload() + // safety scan (default since joomla/filesystem 4.2.0) would reject. Super-User-only action. try { - File::upload($file['tmp_name'], Path::check($path . '/' . $location . '/' . $fileName)); + File::upload($file['tmp_name'], Path::check($path . '/' . $location . '/' . $fileName), false, true); } catch (FilesystemException) { $app->enqueueMessage(Text::_('COM_TEMPLATES_FILE_UPLOAD_ERROR'), 'error'); @@ -1661,7 +1661,7 @@ public function getPreview() { $app = Factory::getApplication(); $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName(['id', 'client_id'])); $query->from($db->quoteName('#__template_styles')); @@ -2053,14 +2053,16 @@ public function child() $media->addChild('folder', 'images'); $media->addChild('folder', 'scss'); - $xml->name = $template->element . '_' . $newName; + $element = (!empty($template->xmldata->parent) ? $template->xmldata->parent : $template->element); + + $xml->name = $element . '_' . $newName; if (isset($xml->namespace)) { $xml->namespace .= '_' . ucfirst($newName); } $xml->inheritable = 0; - $files = $xml->addChild('parent', $template->element); + $files = $xml->addChild('parent', $element); $dom = new \DOMDocument(); $dom->preserveWhiteSpace = false; @@ -2076,17 +2078,11 @@ public function child() } // Create an empty media folder structure - if ( - !Folder::create($toPath . '/media') - || !Folder::create($toPath . '/media/css') - || !Folder::create($toPath . '/media/js') - || !Folder::create($toPath . '/media/images') - || !Folder::create($toPath . '/media/scss') - ) { - return false; - } - - return true; + return Folder::create($toPath . '/media') + && Folder::create($toPath . '/media/css') + && Folder::create($toPath . '/media/js') + && Folder::create($toPath . '/media/images') + && Folder::create($toPath . '/media/scss'); } /** @@ -2105,7 +2101,7 @@ public function getAllTemplateStyles() } $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName(['id', 'title'])) ->from($db->quoteName('#__template_styles')) @@ -2139,7 +2135,7 @@ public function copyStyles() $db = $this->getDatabase(); // Create a new query object. - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName(['title', 'params'])) ->from($db->quoteName('#__template_styles')) @@ -2156,7 +2152,7 @@ public function copyStyles() } foreach ($parentStyle as $style) { - $query = $db->getQuery(true); + $query = $db->createQuery(); $styleName = Text::sprintf('COM_TEMPLATES_COPY_CHILD_TEMPLATE_STYLES', ucfirst($template->element . '_' . $newName), $style->title); // Insert columns and values diff --git a/administrator/components/com_templates/src/Model/TemplatesModel.php b/administrator/components/com_templates/src/Model/TemplatesModel.php index 13047daa92d06..450565ede5599 100644 --- a/administrator/components/com_templates/src/Model/TemplatesModel.php +++ b/administrator/components/com_templates/src/Model/TemplatesModel.php @@ -96,7 +96,7 @@ public function updated($exid) $db = $this->getDatabase(); // Select the required fields from the table - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('template')) ->from($db->quoteName('#__template_overrides')) ->where($db->quoteName('extension_id') . ' = :extensionid') @@ -127,7 +127,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_templates/src/Service/HTML/Templates.php b/administrator/components/com_templates/src/Service/HTML/Templates.php index a72d198689565..1d74a9b424e5c 100644 --- a/administrator/components/com_templates/src/Service/HTML/Templates.php +++ b/administrator/components/com_templates/src/Service/HTML/Templates.php @@ -31,10 +31,10 @@ class Templates * Display the thumb for the template. * * @param string|object $template The name of the template or the template object. - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * The argument $template must be an object only * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * * @return string The html string * @@ -89,10 +89,10 @@ public function thumb($template, $clientId = 0) * Renders the html for the modal linked to thumb. * * @param string|object $template The name of the template or the template object. - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * The argument $template must be an object only * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * * @return string The html string * diff --git a/administrator/components/com_templates/src/Table/StyleTable.php b/administrator/components/com_templates/src/Table/StyleTable.php index 37dd1af4bcb26..6568a2c37b9cf 100644 --- a/administrator/components/com_templates/src/Table/StyleTable.php +++ b/administrator/components/com_templates/src/Table/StyleTable.php @@ -108,7 +108,7 @@ public function store($updateNulls = false) if ($this->home != '0') { $clientId = (int)$this->client_id; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__template_styles')) ->set($db->quoteName('home') . ' = ' . $db->quote('0')) ->where($db->quoteName('client_id') . ' = :clientid') @@ -139,7 +139,7 @@ public function delete($pk = null) if (!\is_null($pk)) { $clientId = (int)$this->client_id; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__template_styles')) ->where($db->quoteName('client_id') . ' = :clientid') diff --git a/administrator/components/com_templates/src/View/Style/HtmlView.php b/administrator/components/com_templates/src/View/Style/HtmlView.php index e325f838acb70..2e5855752351d 100644 --- a/administrator/components/com_templates/src/View/Style/HtmlView.php +++ b/administrator/components/com_templates/src/View/Style/HtmlView.php @@ -88,6 +88,10 @@ public function display($tpl = null) $this->form = $model->getForm(); $this->canDo = ContentHelper::getActions('com_templates'); + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_templates/src/View/Styles/HtmlView.php b/administrator/components/com_templates/src/View/Styles/HtmlView.php index 5efffed718699..1dcf39b99948d 100644 --- a/administrator/components/com_templates/src/View/Styles/HtmlView.php +++ b/administrator/components/com_templates/src/View/Styles/HtmlView.php @@ -101,6 +101,11 @@ public function display($tpl = null) $this->filterForm->removeField('menuitem', 'filter'); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_templates/src/View/Template/HtmlView.php b/administrator/components/com_templates/src/View/Template/HtmlView.php index 1c7a2ae5d084d..941cda3543095 100644 --- a/administrator/components/com_templates/src/View/Template/HtmlView.php +++ b/administrator/components/com_templates/src/View/Template/HtmlView.php @@ -275,9 +275,9 @@ protected function addToolbar() // Add a copy/child template button if (isset($this->template->xmldata->inheritable) && (string) $this->template->xmldata->inheritable === '1') { ToolbarHelper::modal('childModal', 'icon-copy', 'COM_TEMPLATES_BUTTON_TEMPLATE_CHILD'); - } elseif (empty($this->template->xmldata->parent) && empty($this->template->xmldata->namespace)) { - // We can't copy parent templates nor namespaced templates - ToolbarHelper::modal('copyModal', 'icon-copy', 'COM_TEMPLATES_BUTTON_COPY_TEMPLATE'); + } elseif (empty($this->template->xmldata->namespace)) { + // We can't copy namespaced templates + ToolbarHelper::modal('copyModal', 'icon-copy', !empty($this->template->xmldata->parent) ? 'COM_TEMPLATES_BUTTON_COPY_CHILD_TEMPLATE' : 'COM_TEMPLATES_BUTTON_COPY_TEMPLATE'); } break; diff --git a/administrator/components/com_templates/src/View/Templates/HtmlView.php b/administrator/components/com_templates/src/View/Templates/HtmlView.php index 0cf8257ff1e0b..29627d405f842 100644 --- a/administrator/components/com_templates/src/View/Templates/HtmlView.php +++ b/administrator/components/com_templates/src/View/Templates/HtmlView.php @@ -118,6 +118,11 @@ public function display($tpl = null) $this->file = base64_encode('home'); $this->pluginState = PluginHelper::isEnabled('installer', 'override'); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_templates/tmpl/style/edit.php b/administrator/components/com_templates/tmpl/style/edit.php index 56b4fb41d92f7..d263626ccab9e 100644 --- a/administrator/components/com_templates/tmpl/style/edit.php +++ b/administrator/components/com_templates/tmpl/style/edit.php @@ -143,7 +143,6 @@ class="form-validate"> - - + form->renderControlFields(); ?>
diff --git a/administrator/components/com_templates/tmpl/styles/default.php b/administrator/components/com_templates/tmpl/styles/default.php index c708fdd97315d..e8e07afc17fe1 100644 --- a/administrator/components/com_templates/tmpl/styles/default.php +++ b/administrator/components/com_templates/tmpl/styles/default.php @@ -146,9 +146,7 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_templates/tmpl/template/default.php b/administrator/components/com_templates/tmpl/template/default.php index 1467d9d7f532a..4474b252c0f10 100644 --- a/administrator/components/com_templates/tmpl/template/default.php +++ b/administrator/components/com_templates/tmpl/template/default.php @@ -21,16 +21,21 @@ /** @var \Joomla\Component\Templates\Administrator\View\Template\HtmlView $this */ -HTMLHelper::_('behavior.multiselect', 'updateForm'); -HTMLHelper::_('bootstrap.modal'); +$app = Factory::getApplication(); +$doc = $app->getDocument(); + +// Pass the required options to the javascript +$doc->addScriptOptions('js-multiselect', ['formName' => 'updateForm']); /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ -$wa = $this->getDocument()->getWebAssetManager(); -$input = Factory::getApplication()->getInput(); +$wa = $doc->getWebAssetManager(); +$input = $app->getInput(); // Enable assets $wa->useScript('form.validate') ->useScript('keepalive') + ->useScript('bootstrap.modal') + ->useScript('multiselect') ->useScript('com_templates.admin-template-toggle-switch') ->useScript('com_templates.admin-templates') ->useStyle('com_templates.admin-templates'); @@ -109,7 +114,7 @@

- +

@@ -391,7 +396,7 @@ $copyModalData = [ 'selector' => $taskName . 'Modal', 'params' => [ - 'title' => Text::_('COM_TEMPLATES_TEMPLATE_' . strtoupper($taskName)), + 'title' => Text::_('COM_TEMPLATES_TEMPLATE_' . strtoupper($taskName) . (isset($this->template->xmldata->parent) && (string) $this->template->xmldata->parent !== '' ? '_CHILD' : '')), 'footer' => $this->loadTemplate('modal_' . $taskName . '_footer') ], 'body' => $this->loadTemplate('modal_' . $taskName . '_body') diff --git a/administrator/components/com_templates/tmpl/template/default_description.php b/administrator/components/com_templates/tmpl/template/default_description.php index 8d8f1ca2eb41c..616f37d8b77ec 100644 --- a/administrator/components/com_templates/tmpl/template/default_description.php +++ b/administrator/components/com_templates/tmpl/template/default_description.php @@ -27,5 +27,5 @@

template->element); ?>

template->client_id); ?>

template->xmldata = TemplatesHelper::parseXMLTemplateFile($client->path, $this->template->element); ?>

-

template->xmldata->get('description')); ?>

+

template->xmldata->description); ?>

diff --git a/administrator/components/com_templates/tmpl/template/default_modal_copy_footer.php b/administrator/components/com_templates/tmpl/template/default_modal_copy_footer.php index 17d0f3f17a4de..6d53da8526b4b 100644 --- a/administrator/components/com_templates/tmpl/template/default_modal_copy_footer.php +++ b/administrator/components/com_templates/tmpl/template/default_modal_copy_footer.php @@ -14,4 +14,4 @@ ?> - + diff --git a/administrator/components/com_templates/tmpl/templates/default.php b/administrator/components/com_templates/tmpl/templates/default.php index a15338f9455f5..aafcd5c299b74 100644 --- a/administrator/components/com_templates/tmpl/templates/default.php +++ b/administrator/components/com_templates/tmpl/templates/default.php @@ -98,21 +98,21 @@ - escape($item->xmldata->get('version')); ?> + escape($item->xmldata->version); ?> - escape($item->xmldata->get('creationDate')); ?> + escape($item->xmldata->creationDate); ?> - xmldata->get('author')) : ?> + xmldata->author) : ?>
escape($author); ?>
— - xmldata->get('authorEmail')) : ?> + xmldata->authorEmail) : ?>
escape($email); ?>
- xmldata->get('authorUrl')) : ?> + xmldata->authorUrl) : ?> @@ -137,9 +137,7 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_users/config.xml b/administrator/components/com_users/config.xml index 025629b98fc6c..652a307306e2a 100644 --- a/administrator/components/com_users/config.xml +++ b/administrator/components/com_users/config.xml @@ -124,7 +124,7 @@ label="COM_USERS_CONFIG_FIELD_DOMAINS_LABEL" hiddenLabel="true" multiple="true" - layout="joomla.form.field.subform.repeatable-table" + layout="joomla.form.field.subform.repeatable-grid" formsource="administrator/components/com_users/forms/config_domain.xml" />
@@ -258,7 +258,6 @@ label="COM_USERS_CONFIG_NEVERMFAUSERGROUPS_LABEL" description="COM_USERS_CONFIG_NEVERMFAUSERGROUPS_DESC" layout="joomla.form.field.list-fancy-select" - checksuperusergroup="1" default="" multiple="1" > @@ -271,7 +270,6 @@ label="COM_USERS_CONFIG_FORCEMFAUSERGROUPS_LABEL" description="COM_USERS_CONFIG_FORCEMFAUSERGROUPS_DESC" layout="joomla.form.field.list-fancy-select" - checksuperusergroup="1" default="" multiple="1" > diff --git a/administrator/components/com_users/helpers/debug.php b/administrator/components/com_users/helpers/debug.php index b9a25cd50064c..88857a20cdc38 100644 --- a/administrator/components/com_users/helpers/debug.php +++ b/administrator/components/com_users/helpers/debug.php @@ -21,7 +21,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Users\Administrator\Helper\DebugHelper instead */ class UsersHelperDebug extends DebugHelper diff --git a/administrator/components/com_users/helpers/users.php b/administrator/components/com_users/helpers/users.php index 8e15208d23858..521dc31a39ee8 100644 --- a/administrator/components/com_users/helpers/users.php +++ b/administrator/components/com_users/helpers/users.php @@ -19,7 +19,7 @@ * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Users\Administrator\Helper\UsersHelper instead */ class UsersHelper extends \Joomla\Component\Users\Administrator\Helper\UsersHelper diff --git a/administrator/components/com_users/postinstall/multifactorauth.php b/administrator/components/com_users/postinstall/multifactorauth.php index d1ca2b0f46c21..aecf8858b059c 100644 --- a/administrator/components/com_users/postinstall/multifactorauth.php +++ b/administrator/components/com_users/postinstall/multifactorauth.php @@ -44,7 +44,7 @@ function com_users_postinstall_mfa_action(): void $db = Factory::getContainer()->get(DatabaseInterface::class); $coreMfaPlugins = ['email', 'totp', 'webauthn', 'yubikey']; - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__extensions')) ->set($db->quoteName('enabled') . ' = 1') ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) diff --git a/administrator/components/com_users/src/Controller/CaptiveController.php b/administrator/components/com_users/src/Controller/CaptiveController.php index 3d47fda0f1c0b..35ec3478803ff 100644 --- a/administrator/components/com_users/src/Controller/CaptiveController.php +++ b/administrator/components/com_users/src/Controller/CaptiveController.php @@ -153,7 +153,7 @@ public function validate($cachable = false, $urlparameters = []) if (!$model->checkTryLimit($record)) { // The try limit is reached, show error and return - $captiveURL = Route::_('index.php?option=com_users&view=captive&task=select', false); + $captiveURL = Route::_('index.php?option=com_users&view=captive&task=captive.select', false); $message = Text::_('COM_USERS_MFA_TRY_LIMIT_REACHED'); $this->setRedirect($captiveURL, $message, 'error'); diff --git a/administrator/components/com_users/src/Controller/UserController.php b/administrator/components/com_users/src/Controller/UserController.php index 390753331d231..83827ec9a142a 100644 --- a/administrator/components/com_users/src/Controller/UserController.php +++ b/administrator/components/com_users/src/Controller/UserController.php @@ -13,6 +13,7 @@ use Joomla\CMS\Access\Access; use Joomla\CMS\MVC\Controller\FormController; use Joomla\CMS\MVC\Model\BaseDatabaseModel; +use Joomla\CMS\Response\JsonResponse; use Joomla\CMS\Router\Route; use Joomla\CMS\Uri\Uri; @@ -160,4 +161,36 @@ public function batch($model = null) protected function postSaveHook(BaseDatabaseModel $model, $validData = []) { } + + /** + * Get the XHR request to activate a user + * js: media/com_users/js/activate-user-send-email + * + * @return void + * + * @since 6.0.0 + */ + public function active(): void + { + $this->checkToken(); + + // Get the ID of the user + $userId = $this->input->getString('userid', ''); + + // Prepare the default response + $responseError = false; + $responseMessage = null; + + // Set the model + $model = $this->getModel('User', 'Administrator', []); + + // Activate the user and send the email + if (!$model->activate($userId)) { + $responseError = true; + } + + $responseMessage = \Joomla\CMS\Factory::getApplication()->getMessageQueue(); + + echo new JsonResponse(null, $responseMessage, $responseError); + } } diff --git a/administrator/components/com_users/src/Controller/UsersController.php b/administrator/components/com_users/src/Controller/UsersController.php index 9840b5708dd2e..5024b3de5bdb8 100644 --- a/administrator/components/com_users/src/Controller/UsersController.php +++ b/administrator/components/com_users/src/Controller/UsersController.php @@ -11,12 +11,12 @@ namespace Joomla\Component\Users\Administrator\Controller; use Joomla\CMS\Application\CMSApplication; -use Joomla\CMS\Input\Input; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\AdminController; use Joomla\CMS\MVC\Controller\BaseController; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\Response\JsonResponse; +use Joomla\Input\Input; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -39,7 +39,7 @@ class UsersController extends AdminController /** * Constructor. * - * @param array $config An optional associative array of configuration settings. + * @param array $config An optional associative array of configuration settings. * @param ?MVCFactoryInterface $factory The factory. * @param ?CMSApplication $app The CMSApplication for the dispatcher * @param ?Input $input Input diff --git a/administrator/components/com_users/src/Dispatcher/Dispatcher.php b/administrator/components/com_users/src/Dispatcher/Dispatcher.php index f32aa23a36a34..8e41ea41dfe99 100644 --- a/administrator/components/com_users/src/Dispatcher/Dispatcher.php +++ b/administrator/components/com_users/src/Dispatcher/Dispatcher.php @@ -34,16 +34,11 @@ protected function checkAccess() { $task = $this->input->getCmd('task'); $view = $this->input->getCmd('view'); - $layout = $this->input->getCmd('layout'); - $allowedTasks = ['user.edit', 'user.apply', 'user.save', 'user.cancel']; - // If the user editing layout is called, we assume its the user.edit task - if (!$task && $view === 'user' && $layout === 'edit') { - $task = 'user.edit'; - } + $allowedTasks = ['user.edit', 'user.apply', 'user.save', 'user.cancel']; // Allow users to edit their own account - if (\in_array($task, $allowedTasks, true) || ($view === 'user' && $layout === 'edit')) { + if (\in_array($task, $allowedTasks, true) || (\in_array($view, ['user']) && !$task)) { $user = $this->app->getIdentity(); $id = $this->input->getInt('id'); @@ -60,16 +55,13 @@ protected function checkAccess() * are trying to modify. Implementing these checks in the Dispatcher would violate the * separation of concerns. */ - $allowedViews = ['callback', 'captive', 'method', 'methods']; - $isAllowedTask = array_reduce( - $allowedViews, - function ($carry, $taskPrefix) use ($task) { - return $carry || str_starts_with($task ?? '', $taskPrefix . '.'); - }, - false - ); + $allowedTasks = [ + 'captive.captive', 'captive.validate', 'callback.callback', 'captive.select', + 'method.add', 'method.edit', 'method.regenerateBackupCodes', 'method.delete', 'method.save', + 'methods.display', 'methods.disable', 'methods.doNotShowThisAgain', + ]; - if (\in_array(strtolower($view ?? ''), $allowedViews) || $isAllowedTask) { + if (\in_array($task, $allowedTasks) || (\in_array($view, ['captive', 'methods', 'method']) && !$task)) { return; } diff --git a/administrator/components/com_users/src/Helper/DebugHelper.php b/administrator/components/com_users/src/Helper/DebugHelper.php index dda89bf802f11..718a70b64730b 100644 --- a/administrator/components/com_users/src/Helper/DebugHelper.php +++ b/administrator/components/com_users/src/Helper/DebugHelper.php @@ -38,7 +38,7 @@ public static function getComponents() { // Initialise variable. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('name AS text, element AS value') ->from('#__extensions') ->where('enabled >= 1') diff --git a/administrator/components/com_users/src/Helper/Mfa.php b/administrator/components/com_users/src/Helper/Mfa.php index 5dbaa0734d931..ea4e4ca4e1195 100644 --- a/administrator/components/com_users/src/Helper/Mfa.php +++ b/administrator/components/com_users/src/Helper/Mfa.php @@ -264,7 +264,7 @@ public static function getUserMfaRecords(?int $userId): array /** @var DatabaseInterface $db */ $db = Factory::getContainer()->get(DatabaseInterface::class); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__user_mfa')) ->where($db->quoteName('user_id') . ' = :user_id') diff --git a/administrator/components/com_users/src/Helper/UsersHelper.php b/administrator/components/com_users/src/Helper/UsersHelper.php index f727cf60bec77..d961af51653bb 100644 --- a/administrator/components/com_users/src/Helper/UsersHelper.php +++ b/administrator/components/com_users/src/Helper/UsersHelper.php @@ -125,7 +125,7 @@ public static function getRangeOptions() * @since 3.2.0 * @throws \Exception * - * @deprecated 4.2 will be removed in 6.0 + * @deprecated 4.2 will be removed in 7.0 * No longer used, will be removed without replacement */ public static function getTwoFactorMethods() @@ -151,7 +151,7 @@ public static function getVisibleByGroups($rules) } $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title', 'text')) ->from($db->quoteName('#__usergroups')) ->whereIn($db->quoteName('id'), $rules); @@ -174,7 +174,7 @@ public static function getVisibleByGroups($rules) * @since 3.7.0 * @throws \Exception * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Users\Administrator\Extension\UsersComponent::validateSection() instead. */ public static function validateSection($section) @@ -189,7 +189,7 @@ public static function validateSection($section) * * @since 3.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Users\Administrator\Extension\UsersComponent::getContexts() instead. */ public static function getContexts() diff --git a/administrator/components/com_users/src/Model/BackupcodesModel.php b/administrator/components/com_users/src/Model/BackupcodesModel.php index 33271b4f73c99..aff8effd799a1 100644 --- a/administrator/components/com_users/src/Model/BackupcodesModel.php +++ b/administrator/components/com_users/src/Model/BackupcodesModel.php @@ -10,7 +10,6 @@ namespace Joomla\Component\Users\Administrator\Model; -use Joomla\CMS\Crypt\Crypt; use Joomla\CMS\Date\Date; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\BaseDatabaseModel; @@ -259,7 +258,7 @@ public function isBackupCode($code, ?User $user = null): bool } for ($i = 0; $i < $restLength; $i++) { - if (Crypt::timingSafeCompare($temp1[$i], $code)) { + if (hash_equals($temp1[$i], $code)) { $otherResult = $otherResult || true; $newArray[] = ''; $dummyArray[] = $temp1[$i]; diff --git a/administrator/components/com_users/src/Model/DebuggroupModel.php b/administrator/components/com_users/src/Model/DebuggroupModel.php index ad28a6009cce7..e458f20356b38 100644 --- a/administrator/components/com_users/src/Model/DebuggroupModel.php +++ b/administrator/components/com_users/src/Model/DebuggroupModel.php @@ -177,7 +177,7 @@ public function getGroup() $groupId = (int) $this->getState('group_id'); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['id', 'title'])) ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('id') . ' = :id') @@ -207,7 +207,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_users/src/Model/DebuguserModel.php b/administrator/components/com_users/src/Model/DebuguserModel.php index 5766b292aa5aa..190b4b011a8ea 100644 --- a/administrator/components/com_users/src/Model/DebuguserModel.php +++ b/administrator/components/com_users/src/Model/DebuguserModel.php @@ -196,7 +196,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_users/src/Model/GroupModel.php b/administrator/components/com_users/src/Model/GroupModel.php index bcb16170e0977..17ca3f701cc55 100644 --- a/administrator/components/com_users/src/Model/GroupModel.php +++ b/administrator/components/com_users/src/Model/GroupModel.php @@ -18,7 +18,6 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\AdminModel; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Table\Table; use Joomla\String\StringHelper; @@ -84,20 +83,14 @@ public function getTable($type = 'Usergroup', $prefix = 'Joomla\\CMS\\Table\\', * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_users.group', 'group', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_users.group', 'group', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -136,7 +129,7 @@ protected function loadFormData() */ protected function preprocessForm(Form $form, $data, $group = '') { - $obj = \is_array($data) ? ArrayHelper::toObject($data, CMSObject::class) : $data; + $obj = \is_array($data) ? ArrayHelper::toObject($data) : $data; if (isset($obj->parent_id) && $obj->parent_id == 0 && $obj->id > 0) { $form->setFieldAttribute('parent_id', 'type', 'hidden'); diff --git a/administrator/components/com_users/src/Model/GroupsModel.php b/administrator/components/com_users/src/Model/GroupsModel.php index 868c02229d4d1..8606f17f644b8 100644 --- a/administrator/components/com_users/src/Model/GroupsModel.php +++ b/administrator/components/com_users/src/Model/GroupsModel.php @@ -140,7 +140,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( @@ -195,7 +195,7 @@ private function populateExtraData(array $items) $db = $this->getDatabase(); // Get total enabled users in group. - $query = $db->getQuery(true); + $query = $db->createQuery(); // Count the objects in the user group. $query->select('map.group_id, COUNT(DISTINCT map.user_id) AS user_count') diff --git a/administrator/components/com_users/src/Model/LevelModel.php b/administrator/components/com_users/src/Model/LevelModel.php index 398309e41fff6..04321b8216976 100644 --- a/administrator/components/com_users/src/Model/LevelModel.php +++ b/administrator/components/com_users/src/Model/LevelModel.php @@ -18,6 +18,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Table\Table; +use Joomla\String\StringHelper; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -52,7 +53,7 @@ public function delete(&$pks) if ($table->load($pk)) { // Check if the access level is being used. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT access'); // Get all tables that have the access field @@ -189,20 +190,14 @@ public function getItem($pk = null) * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_users.level', 'level', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_users.level', 'level', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -262,9 +257,36 @@ public function save($data) $data['title'] = InputFilter::getInstance()->clean($data['title'], 'TRIM'); + if (Factory::getApplication()->getInput()->get('task') === 'save2copy') { + $data['title'] = $this->generateLevelTitle($data['title']); + } + return parent::save($data); } + /** + * Method to generate the title of access level on Save as Copy action + * + * @param string $title The title of the access level + * + * @return string Contains the modified title. + * + * @since 6.2.0 + */ + protected function generateLevelTitle($title) + { + // Alter the title + $table = $this->getTable(); + + while ($table->load(['title' => $title])) { + if ($title === $table->title) { + $title = StringHelper::increment($title); + } + } + + return $title; + } + /** * Method to validate the form data. * diff --git a/administrator/components/com_users/src/Model/LevelsModel.php b/administrator/components/com_users/src/Model/LevelsModel.php index a00d3376773ff..5c8de890426da 100644 --- a/administrator/components/com_users/src/Model/LevelsModel.php +++ b/administrator/components/com_users/src/Model/LevelsModel.php @@ -15,7 +15,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\ViewLevel; use Joomla\Database\ParameterType; use Joomla\Database\QueryInterface; @@ -102,7 +102,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( @@ -154,7 +154,7 @@ public function reorder($pk, $direction = 0) $user = $this->getCurrentUser(); // Get an instance of the record's table. - $table = Table::getInstance('ViewLevel', 'Joomla\\CMS\Table\\'); + $table = new ViewLevel($this->getDatabase()); // Load the row. if (!$table->load($pk)) { @@ -191,7 +191,7 @@ public function reorder($pk, $direction = 0) */ public function saveorder($pks, $order) { - $table = Table::getInstance('viewlevel', 'Joomla\\CMS\Table\\'); + $table = new ViewLevel($this->getDatabase()); $user = $this->getCurrentUser(); $conditions = []; diff --git a/administrator/components/com_users/src/Model/MailModel.php b/administrator/components/com_users/src/Model/MailModel.php index 34562773f20f2..1b1047ea8fb5d 100644 --- a/administrator/components/com_users/src/Model/MailModel.php +++ b/administrator/components/com_users/src/Model/MailModel.php @@ -15,9 +15,13 @@ use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\Mail\Exception\MailDisabledException; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\Database\ParameterType; @@ -32,28 +36,25 @@ * * @since 1.6 */ -class MailModel extends AdminModel +class MailModel extends AdminModel implements MailerFactoryAwareInterface, LanguageFactoryAwareInterface { + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; + /** * Method to get the row form. * * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_users.mail', 'mail', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_users.mail', 'mail', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -136,7 +137,7 @@ public function send() } else { // Get all users email and group except for senders $uid = (int) $user->id; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('email'), @@ -173,7 +174,12 @@ public function send() } // Get the Mailer - $mailer = new MailTemplate('com_users.massmail.mail', $language->getTag()); + $mailer = new MailTemplate( + 'com_users.massmail.mail', + $language->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $params = ComponentHelper::getParams('com_users'); try { diff --git a/administrator/components/com_users/src/Model/MethodsModel.php b/administrator/components/com_users/src/Model/MethodsModel.php index 0efe426b28c1c..542f77c7d66e3 100644 --- a/administrator/components/com_users/src/Model/MethodsModel.php +++ b/administrator/components/com_users/src/Model/MethodsModel.php @@ -97,7 +97,7 @@ public function deleteAll(?User $user = null): void } $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__user_mfa')) ->where($db->quoteName('user_id') . ' = :user_id') ->bind(':user_id', $user->id, ParameterType::INTEGER); @@ -187,7 +187,7 @@ public function setFlag(User $user, bool $flag = true): void { $db = $this->getDatabase(); $profileKey = 'mfa.dontshow'; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('profile_value')) ->from($db->quoteName('#__user_profiles')) ->where($db->quoteName('user_id') . ' = :user_id') diff --git a/administrator/components/com_users/src/Model/NoteModel.php b/administrator/components/com_users/src/Model/NoteModel.php index 6573c0fbecae2..c0110e56ec394 100644 --- a/administrator/components/com_users/src/Model/NoteModel.php +++ b/administrator/components/com_users/src/Model/NoteModel.php @@ -10,9 +10,12 @@ namespace Joomla\Component\Users\Administrator\Model; +use Joomla\CMS\Event\Model\PrepareDataEvent; use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Versioning\VersionableModelInterface; use Joomla\CMS\Versioning\VersionableModelTrait; // phpcs:disable PSR1.Files.SideEffects @@ -24,7 +27,7 @@ * * @since 2.5 */ -class NoteModel extends AdminModel +class NoteModel extends AdminModel implements VersionableModelInterface { use VersionableModelTrait; @@ -42,20 +45,14 @@ class NoteModel extends AdminModel * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 2.5 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_users.note', 'note', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_users.note', 'note', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -73,13 +70,17 @@ public function getItem($pk = null) $result = parent::getItem($pk); // Get the dispatcher and load the content plugins. - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Load the user plugins for backward compatibility (v3.3.3 and earlier). - PluginHelper::importPlugin('user'); + PluginHelper::importPlugin('user', null, true, $dispatcher); // Trigger the data preparation event. - Factory::getApplication()->triggerEvent('onContentPrepareData', ['com_users.note', $result]); + $dispatcher->dispatch('onContentPrepareData', new PrepareDataEvent('onContentPrepareData', [ + 'context' => 'com_users.note', + 'data' => $result, + ])); return $result; } @@ -105,7 +106,7 @@ protected function loadFormData() // Prime some default values. if ($this->getState('note.id') == 0) { - $data->set('catid', $app->getInput()->get('catid', $app->getUserState('com_users.notes.filter.category_id'), 'int')); + $data->catid = $app->getInput()->get('catid', $app->getUserState('com_users.notes.filter.category_id'), 'int'); } $userId = $app->getInput()->get('u_id', 0, 'int'); diff --git a/administrator/components/com_users/src/Model/NotesModel.php b/administrator/components/com_users/src/Model/NotesModel.php index 311eed443982b..62d65740b04ef 100644 --- a/administrator/components/com_users/src/Model/NotesModel.php +++ b/administrator/components/com_users/src/Model/NotesModel.php @@ -69,7 +69,7 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) protected function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( diff --git a/administrator/components/com_users/src/Model/UserModel.php b/administrator/components/com_users/src/Model/UserModel.php index a11f59afc45a1..bfd3913c1c2c1 100644 --- a/administrator/components/com_users/src/Model/UserModel.php +++ b/administrator/components/com_users/src/Model/UserModel.php @@ -12,10 +12,19 @@ use Joomla\CMS\Access\Access; use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Event\User\AfterDeleteEvent; +use Joomla\CMS\Event\User\AfterSaveEvent; +use Joomla\CMS\Event\User\BeforeDeleteEvent; +use Joomla\CMS\Event\User\BeforeSaveEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Language\Text; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; +use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\AdminModel; use Joomla\CMS\Plugin\PluginHelper; @@ -35,9 +44,11 @@ * * @since 1.6 */ -class UserModel extends AdminModel implements UserFactoryAwareInterface +class UserModel extends AdminModel implements UserFactoryAwareInterface, MailerFactoryAwareInterface, LanguageFactoryAwareInterface { use UserFactoryAwareTrait; + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; /** * An item. @@ -119,19 +130,16 @@ public function getItem($pk = null) * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_users.user', 'user', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - $user = $this->getCurrentUser(); // If the user needs to change their password, mark the password fields as required @@ -224,9 +232,8 @@ protected function preprocessForm(Form $form, $data, $group = 'user') */ public function save($data) { - $pk = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('user.id'); - $user = $this->getUserFactory()->loadUserById($pk); - + $pk = (!empty($data['id'])) ? $data['id'] : (int) $this->getState('user.id'); + $user = $this->getUserFactory()->loadUserById($pk); $my = $this->getCurrentUser(); $iAmSuperAdmin = $my->authorise('core.admin'); @@ -292,7 +299,7 @@ public function save($data) } // Destroy all active sessions for the user after changing the password or blocking him - if (!empty($data['password2']) || $data['block']) { + if (!empty($data['password2']) || !empty($data['block'])) { UserHelper::destroyUserSessions($user->id, true); } @@ -320,7 +327,8 @@ public function delete(&$pks) // Check if I am a Super Admin $iAmSuperAdmin = $user->authorise('core.admin'); - PluginHelper::importPlugin($this->events_map['delete']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['delete'], null, true, $dispatcher); if (\in_array($user->id, $pks)) { $this->setError(Text::_('COM_USERS_USERS_ERROR_CANNOT_DELETE_SELF')); @@ -342,7 +350,12 @@ public function delete(&$pks) $user_to_delete = $this->getUserFactory()->loadUserById($pk); // Fire the before delete event. - Factory::getApplication()->triggerEvent($this->event_before_delete, [$table->getProperties()]); + $dispatcher->dispatch( + $this->event_before_delete, + new BeforeDeleteEvent($this->event_before_delete, [ + 'subject' => $table->getProperties(), + ]) + ); if (!$table->delete($pk)) { $this->setError($table->getError()); @@ -351,7 +364,14 @@ public function delete(&$pks) } // Trigger the after delete event. - Factory::getApplication()->triggerEvent($this->event_after_delete, [ArrayHelper::fromObject($user_to_delete, false), true, $this->getError()]); + $dispatcher->dispatch( + $this->event_after_delete, + new AfterDeleteEvent($this->event_after_delete, [ + 'subject' => ArrayHelper::fromObject($user_to_delete, false), + 'deletingResult' => true, + 'errorMessage' => $this->getError(), + ]) + ); } else { // Prune items that you can't change. unset($pks[$i]); @@ -380,15 +400,16 @@ public function delete(&$pks) */ public function block(&$pks, $value = 1) { - $app = Factory::getApplication(); - $user = $this->getCurrentUser(); + $app = Factory::getApplication(); + $user = $this->getCurrentUser(); // Check if I am a Super Admin $iAmSuperAdmin = $user->authorise('core.admin'); $table = $this->getTable(); $pks = (array) $pks; - PluginHelper::importPlugin($this->events_map['save']); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['save'], null, true, $dispatcher); // Prepare the logout options. $options = [ @@ -431,7 +452,14 @@ public function block(&$pks, $value = 1) } // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, [$old, false, $table->getProperties()]); + $result = $dispatcher->dispatch( + $this->event_before_save, + new BeforeSaveEvent($this->event_before_save, [ + 'subject' => $old, + 'isNew' => false, + 'data' => $table->getProperties(), + ]) + )->getArgument('result', []); if (\in_array(false, $result, true)) { // Plugin will have to raise its own error or throw an exception. @@ -450,7 +478,12 @@ public function block(&$pks, $value = 1) } // Trigger the after save event - Factory::getApplication()->triggerEvent($this->event_after_save, [$table->getProperties(), false, true, null]); + $dispatcher->dispatch($this->event_after_save, new AfterSaveEvent($this->event_after_save, [ + 'subject' => $table->getProperties(), + 'isNew' => false, + 'savingResult' => true, + 'errorMessage' => null, + ])); } catch (\Exception $e) { $this->setError($e->getMessage()); @@ -484,26 +517,86 @@ public function block(&$pks, $value = 1) */ public function activate(&$pks) { - $user = $this->getCurrentUser(); + $app = Factory::getApplication(); + $user = $app->getIdentity(); - // Check if I am a Super Admin + // Check if I am a super admin $iAmSuperAdmin = $user->authorise('core.admin'); - $table = $this->getTable(); - $pks = (array) $pks; - PluginHelper::importPlugin($this->events_map['save']); + // Load user table + $table = $this->getTable(); + $pks = (array) $pks; - // Access checks. + // Compile the user activated notification mail default values. + $mailData = []; + $mailData['siteurl'] = \Joomla\CMS\Uri\Uri::root(); + $mailData['fromname'] = $app->get('fromname'); + $mailData['mailfrom'] = $app->get('mailfrom'); + $mailData['sitename'] = $app->get('sitename'); + + // Load com_users site language strings, the mail template use it + $app->getLanguage()->load('com_users', JPATH_SITE); + + $sendMailTo = function ($userData) use ($app, $mailData) { + $mailData['name'] = $userData['name']; + $mailData['username'] = $userData['username']; + + // Use the default language + $langTag = ComponentHelper::getParams('com_languages')->get('site', 'en-GB'); + + $mailer = new MailTemplate( + 'com_users.registration.user.admin_activated', + $langTag, + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); + $mailer->addTemplateData($mailData); + $mailer->addRecipient($userData['email']); + + try { + $return = $mailer->send(); + } catch (\Exception $exception) { + try { + \Joomla\CMS\Log\Log::add(Text::_($exception->getMessage()), \Joomla\CMS\Log\Log::WARNING, 'jerror'); + + $return = false; + } catch (\RuntimeException $exception) { + $app->enqueueMessage(Text::_($exception->errorMessage()), $app::MSG_WARNING); + + $return = false; + } + } + + // Check for an error. + if ($return !== true) { + $app->enqueueMessage(Text::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED'), $app::MSG_WARNING); + + return false; + } + + $app->enqueueMessage(Text::_('COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_SUCCESS'), $app::MSG_INFO); + return true; + }; + + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin($this->events_map['save'], null, true, $dispatcher); + + // Activate and send the notification email foreach ($pks as $i => $pk) { if ($table->load($pk)) { - $old = $table->getProperties(); - $allow = $user->authorise('core.edit.state', 'com_users'); + $prevUserData = $table->getProperties(); + $allow = $user->authorise('core.edit.state', 'com_users'); - // Don't allow non-super-admin to delete a super admin + // Don't allow non-super-admin to edit the active status of a super admin $allow = (!$iAmSuperAdmin && Access::check($pk, 'core.admin')) ? false : $allow; + // Ignore activated accounts but check if we can still + // resend the notification email if (empty($table->activation)) { - // Ignore activated accounts. + if (\is_null($table->lastvisitDate)) { + $sendMailTo($prevUserData); + } + unset($pks[$i]); } elseif ($allow) { $table->block = 0; @@ -518,7 +611,15 @@ public function activate(&$pks) } // Trigger the before save event. - $result = Factory::getApplication()->triggerEvent($this->event_before_save, [$old, false, $table->getProperties()]); + $result = $dispatcher->dispatch( + $this->event_before_save, + new BeforeSaveEvent($this->event_before_save, [ + 'subject' => $prevUserData, + 'isNew' => false, + 'data' => $table->getProperties(), + ]) + )->getArgument('result', []); + if (\in_array(false, $result, true)) { // Plugin will have to raise it's own error or throw an exception. @@ -533,7 +634,17 @@ public function activate(&$pks) } // Fire the after save event - Factory::getApplication()->triggerEvent($this->event_after_save, [$table->getProperties(), false, true, null]); + $dispatcher->dispatch($this->event_after_save, new AfterSaveEvent($this->event_after_save, [ + 'subject' => $table->getProperties(), + 'isNew' => false, + 'savingResult' => true, + 'errorMessage' => null, + ])); + + // Send the email + if (!$sendMailTo($prevUserData)) { + return false; + } } catch (\Exception $e) { $this->setError($e->getMessage()); @@ -542,7 +653,7 @@ public function activate(&$pks) } else { // Prune items that you can't change. unset($pks[$i]); - Factory::getApplication()->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'error'); + $app->enqueueMessage(Text::_('JLIB_APPLICATION_ERROR_EDITSTATE_NOT_PERMITTED'), 'error'); } } } @@ -662,7 +773,7 @@ public function batchReset($userIds, $action) $userIds = ArrayHelper::toInteger($userIds); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Update the reset flag $query->update($db->quoteName('#__users')) @@ -747,12 +858,12 @@ public function batchUser($groupId, $userIds, $action) // Remove the users from the group if requested. if (isset($doDelete)) { /* - * First we need to check that the user is part of more than one group - * otherwise we will end up with a user that is not part of any group - * unless we are moving the user to a new group. - */ + * First we need to check that the user is part of more than one group + * otherwise we will end up with a user that is not part of any group + * unless we are moving the user to a new group. + */ if ($doDelete === 'group') { - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('user_id')) ->from($db->quoteName('#__user_usergroup_map')) ->whereIn($db->quoteName('user_id'), $userIds); @@ -795,7 +906,7 @@ public function batchUser($groupId, $userIds, $action) ->bind(':group_id', $groupId, ParameterType::INTEGER); $db->setQuery($query); } elseif ($doDelete === 'all') { - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete($db->quoteName('#__user_usergroup_map')) ->whereIn($db->quoteName('user_id'), $userIds); } @@ -812,7 +923,7 @@ public function batchUser($groupId, $userIds, $action) // Assign the users to the group if requested. if (isset($doAssign)) { - $query = $db->getQuery(true); + $query = $db->createQuery(); // First, we need to check if the user is already assigned to a group $query->select($db->quoteName('user_id')) @@ -891,8 +1002,8 @@ public function getAssignedGroups($userId = null) $userId = (!empty($userId)) ? $userId : (int) $this->getState('user.id'); if (empty($userId)) { - $result = []; - $form = $this->getForm(); + $result = []; + $form = $this->getForm(); if ($form) { $groupsIDs = $form->getValue('groups'); @@ -923,7 +1034,7 @@ public function getAssignedGroups($userId = null) * * @since 3.2 * - * @deprecated 4.2 will be removed in 6.0. + * @deprecated 4.2 will be removed in 7.0. * Will be removed without replacement */ public function getOtpConfig($userId = null) @@ -954,7 +1065,7 @@ public function getOtpConfig($userId = null) * * @since 3.2 * - * @deprecated 4.2 will be removed in 5.0. + * @deprecated 4.2 will be removed in 7.0. * Will be removed without replacement */ public function setOtpConfig($userId, $otpConfig) @@ -977,7 +1088,7 @@ public function setOtpConfig($userId, $otpConfig) * * @since 3.2 * - * @deprecated 4.2 will be removed in 6.0. + * @deprecated 4.2 will be removed in 7.0. * Use \Joomla\CMS\Factory::getApplication()->get('secret') instead' */ public function getOtpConfigEncryptionKey() @@ -1003,7 +1114,7 @@ public function getOtpConfigEncryptionKey() * @since 3.2 * @throws \Exception * - * @deprecated 4.2 will be removed in 5.0. + * @deprecated 4.2 will be removed in 7.0. * Will be removed without replacement */ public function getTwofactorform($userId = null) @@ -1029,7 +1140,7 @@ public function getTwofactorform($userId = null) * * @since 3.2 * - * @deprecated 4.2 will be removed in 5.0 + * @deprecated 4.2 will be removed in 7.0 * Will be removed without replacement */ public function generateOteps($userId, $count = 10) @@ -1057,7 +1168,7 @@ public function generateOteps($userId, $count = 10) * @since 3.2 * @throws \Exception * - * @deprecated 4.2 will be removed in 5.0 + * @deprecated 4.2 will be removed in 7.0 * Will be removed without replacement */ public function isValidSecretKey($userId, $secretKey, $options = []) @@ -1084,7 +1195,7 @@ public function isValidSecretKey($userId, $secretKey, $options = []) * * @since 3.2 * - * @deprecated 4.2 will be removed in 5.0 + * @deprecated 4.2 will be removed in 7.0 * Will be removed without replacement */ public function isValidOtep($userId, $otep, $otpConfig = null) diff --git a/administrator/components/com_users/src/Model/UsersModel.php b/administrator/components/com_users/src/Model/UsersModel.php index 587f82482c2a8..c2ef69f501ae1 100644 --- a/administrator/components/com_users/src/Model/UsersModel.php +++ b/administrator/components/com_users/src/Model/UsersModel.php @@ -196,7 +196,7 @@ public function getItems() // Get the counts from the database only for the users in the list. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Join over the group mapping table. $query->select('map.user_id, COUNT(map.group_id) AS group_count') @@ -289,7 +289,7 @@ protected function getListQuery() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the table. $query->select( @@ -303,7 +303,7 @@ protected function getListQuery() // Include MFA information if (PluginHelper::isEnabled('multifactorauth')) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select( [ 'MIN(' . $db->quoteName('user_id') . ') AS ' . $db->quoteName('uid'), @@ -575,7 +575,7 @@ private function buildDateRange($range) $dStart->setTime(0, 0, 0); // Now change the timezone back to UTC. - $tz = new \DateTimeZone('GMT'); + $tz = new \DateTimeZone('UTC'); $dStart->setTimezone($tz); break; case 'never': @@ -597,7 +597,7 @@ private function buildDateRange($range) protected function getUserDisplayedGroups($userId) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__usergroups', 'ug')) ->join('LEFT', $db->quoteName('#__user_usergroup_map', 'map') . ' ON (ug.id = map.group_id)') diff --git a/administrator/components/com_users/src/Service/HTML/Users.php b/administrator/components/com_users/src/Service/HTML/Users.php index 83adfbc60a489..a81dd5fe98ba7 100644 --- a/administrator/components/com_users/src/Service/HTML/Users.php +++ b/administrator/components/com_users/src/Service/HTML/Users.php @@ -299,7 +299,7 @@ public function templatestyle($value) } $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__template_styles')) ->where($db->quoteName('id') . ' = :id') @@ -403,7 +403,7 @@ public function editor($value) $db = Factory::getDbo(); $lang = Factory::getLanguage(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('name')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('element') . ' = :element') diff --git a/administrator/components/com_users/src/Table/MfaTable.php b/administrator/components/com_users/src/Table/MfaTable.php index c6b3fd7c5c10e..bec60ee2f2203 100644 --- a/administrator/components/com_users/src/Table/MfaTable.php +++ b/administrator/components/com_users/src/Table/MfaTable.php @@ -314,7 +314,7 @@ private function switchDefaultRecord(): void * user. */ $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__user_mfa')) ->set($db->quoteName('default') . ' = 0') ->where($db->quoteName('user_id') . ' = :user_id') @@ -367,7 +367,7 @@ private function afterDelete($pk): void * the `backupcodes` because we might just be regenerating the backup codes. */ $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__user_mfa')) ->where($db->quoteName('user_id') . ' = :user_id') ->bind(':user_id', $this->deleteFlags[$pk]['user_id'], ParameterType::INTEGER); @@ -381,7 +381,7 @@ private function afterDelete($pk): void // This was the default record. Promote the next available record to default. if ($this->deleteFlags[$pk]['default']) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__user_mfa')) ->where($db->quoteName('user_id') . ' = :user_id') @@ -394,7 +394,7 @@ private function afterDelete($pk): void } $id = array_shift($ids); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__user_mfa')) ->set($db->quoteName('default') . ' = 1') ->where($db->quoteName('id') . ' = :id') @@ -415,7 +415,7 @@ private function afterDelete($pk): void private function getNumRecords(int $userId): int { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__user_mfa')) ->where($db->quoteName('user_id') . ' = :user_id') diff --git a/administrator/components/com_users/src/View/Debuggroup/HtmlView.php b/administrator/components/com_users/src/View/Debuggroup/HtmlView.php index 267231e44defb..7e0ca7e058edc 100644 --- a/administrator/components/com_users/src/View/Debuggroup/HtmlView.php +++ b/administrator/components/com_users/src/View/Debuggroup/HtmlView.php @@ -107,6 +107,11 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_users/src/View/Debuguser/HtmlView.php b/administrator/components/com_users/src/View/Debuguser/HtmlView.php index 4c833ca2c364f..572667a30e257 100644 --- a/administrator/components/com_users/src/View/Debuguser/HtmlView.php +++ b/administrator/components/com_users/src/View/Debuguser/HtmlView.php @@ -107,6 +107,11 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_users/src/View/Group/HtmlView.php b/administrator/components/com_users/src/View/Group/HtmlView.php index 6e7fed5737c36..8f4554368b8d6 100644 --- a/administrator/components/com_users/src/View/Group/HtmlView.php +++ b/administrator/components/com_users/src/View/Group/HtmlView.php @@ -83,6 +83,10 @@ public function display($tpl = null) throw new GenericDataException(implode("\n", $errors), 500); } + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); } diff --git a/administrator/components/com_users/src/View/Groups/HtmlView.php b/administrator/components/com_users/src/View/Groups/HtmlView.php index 27eaef554984b..07cbc25beedb8 100644 --- a/administrator/components/com_users/src/View/Groups/HtmlView.php +++ b/administrator/components/com_users/src/View/Groups/HtmlView.php @@ -87,6 +87,11 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); } diff --git a/administrator/components/com_users/src/View/Level/HtmlView.php b/administrator/components/com_users/src/View/Level/HtmlView.php index 239b653d82c76..b0821a7334bad 100644 --- a/administrator/components/com_users/src/View/Level/HtmlView.php +++ b/administrator/components/com_users/src/View/Level/HtmlView.php @@ -74,6 +74,10 @@ public function display($tpl = null) throw new GenericDataException(implode("\n", $errors), 500); } + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); } diff --git a/administrator/components/com_users/src/View/Levels/HtmlView.php b/administrator/components/com_users/src/View/Levels/HtmlView.php index 5ce9a9ff6b535..ca36fb0755a52 100644 --- a/administrator/components/com_users/src/View/Levels/HtmlView.php +++ b/administrator/components/com_users/src/View/Levels/HtmlView.php @@ -87,6 +87,11 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); } diff --git a/administrator/components/com_users/src/View/Mail/HtmlView.php b/administrator/components/com_users/src/View/Mail/HtmlView.php index 501aacf8a7880..646e2edd23778 100644 --- a/administrator/components/com_users/src/View/Mail/HtmlView.php +++ b/administrator/components/com_users/src/View/Mail/HtmlView.php @@ -57,6 +57,10 @@ public function display($tpl = null) // Get data from the model $this->form = $model->getForm(); + // Add form control fields + $this->form + ->addControlField('task'); + $this->addToolbar(); parent::display($tpl); } diff --git a/administrator/components/com_users/src/View/Note/HtmlView.php b/administrator/components/com_users/src/View/Note/HtmlView.php index aafbaa17fb600..a777fd425012e 100644 --- a/administrator/components/com_users/src/View/Note/HtmlView.php +++ b/administrator/components/com_users/src/View/Note/HtmlView.php @@ -81,6 +81,10 @@ public function display($tpl = null) throw new GenericDataException(implode("\n", $errors), 500); } + // Add form control fields + $this->form + ->addControlField('task'); + parent::display($tpl); $this->addToolbar(); } diff --git a/administrator/components/com_users/src/View/Notes/HtmlView.php b/administrator/components/com_users/src/View/Notes/HtmlView.php index 35d332ac04b85..4285ea4cf0a53 100644 --- a/administrator/components/com_users/src/View/Notes/HtmlView.php +++ b/administrator/components/com_users/src/View/Notes/HtmlView.php @@ -119,6 +119,11 @@ public function display($tpl = null) $item->cparams = new Registry($item->category_params); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); } diff --git a/administrator/components/com_users/src/View/User/HtmlView.php b/administrator/components/com_users/src/View/User/HtmlView.php index a4b00358769df..fb4e51dd001a3 100644 --- a/administrator/components/com_users/src/View/User/HtmlView.php +++ b/administrator/components/com_users/src/View/User/HtmlView.php @@ -136,6 +136,11 @@ public function display($tpl = null) } } + // Add form control fields + $this->form + ->addControlField('task') + ->addControlField('return', Factory::getApplication()->getInput()->getBase64('return', '')); + parent::display($tpl); $this->addToolbar(); @@ -190,6 +195,26 @@ function (Toolbar $childBar) use ($canDo, $isProfile) { $toolbar->cancel('user.cancel'); } + // Check lastvisitDate for allow resend the activation email + $userIsNotActive = !empty($this->item->activation) || \is_null($this->item->lastvisitDate); + + if ($this->item->id > 0 && $userIsNotActive) { + $buttonText = !empty($this->item->activation) + ? Text::_('COM_USERS_USER_ACTIVATE_AND_MAIL') + : Text::_('COM_USERS_USER_ACTIVATION_REMINDER'); + + $toolbar->standardButton('activate', $buttonText) + ->buttonClass('btn activate-send-mail') + ->attributes([ + 'data-option' => 'com_users', + 'data-task' => 'user.active', + 'data-format' => 'json', + 'data-userid' => $this->item->id, + ]) + ->icon('icon-mail') + ->onclick(''); + } + $toolbar->divider(); $toolbar->help('Users:_Edit_Profile'); } diff --git a/administrator/components/com_users/src/View/Users/HtmlView.php b/administrator/components/com_users/src/View/Users/HtmlView.php index d2f819015fcbf..31e64fcfa86a8 100644 --- a/administrator/components/com_users/src/View/Users/HtmlView.php +++ b/administrator/components/com_users/src/View/Users/HtmlView.php @@ -10,14 +10,12 @@ namespace Joomla\Component\Users\Administrator\View\Users; -use Joomla\CMS\Factory; use Joomla\CMS\Helper\ContentHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; use Joomla\CMS\Toolbar\Button\DropdownButton; use Joomla\CMS\Toolbar\ToolbarHelper; use Joomla\Component\Users\Administrator\Model\UsersModel; -use Joomla\Database\DatabaseDriver; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -79,18 +77,6 @@ class HtmlView extends BaseHtmlView */ protected $canDo; - /** - * An instance of DatabaseDriver. - * - * @var DatabaseDriver - * @since 3.6.3 - * - * @deprecated 4.3 will be removed in 6.0 - * Will be removed without replacement use database from the container instead - * Example: Factory::getContainer()->get(DatabaseInterface::class); - */ - protected $db; - /** * Display the view * @@ -110,7 +96,11 @@ public function display($tpl = null) $this->filterForm = $model->getFilterForm(); $this->activeFilters = $model->getActiveFilters(); $this->canDo = ContentHelper::getActions('com_users'); - $this->db = Factory::getDbo(); + + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); $this->addToolbar(); parent::display($tpl); @@ -169,6 +159,7 @@ protected function addToolbar() if ($canDo->get('core.delete')) { $childBar->delete('users.delete', 'JTOOLBAR_DELETE') + ->icon('icon-exclamation-triangle') ->message('JGLOBAL_CONFIRM_DELETE') ->listCheck(true); } diff --git a/administrator/components/com_users/tmpl/captive/default.php b/administrator/components/com_users/tmpl/captive/default.php index 56ccc18ea80d2..3579ea8897fdc 100644 --- a/administrator/components/com_users/tmpl/captive/default.php +++ b/administrator/components/com_users/tmpl/captive/default.php @@ -117,7 +117,7 @@ class="btn btn-danger btn-sm" records) > 1) : ?> + href=""> diff --git a/administrator/components/com_users/tmpl/captive/select.php b/administrator/components/com_users/tmpl/captive/select.php index e3afe6ef28f05..a062464d23ccb 100644 --- a/administrator/components/com_users/tmpl/captive/select.php +++ b/administrator/components/com_users/tmpl/captive/select.php @@ -14,9 +14,8 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; use Joomla\CMS\Uri\Uri; -use Joomla\Component\Users\Administrator\View\Captive\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Users\Administrator\View\Captive\HtmlView $this */ $shownMethods = []; diff --git a/administrator/components/com_users/tmpl/debuggroup/default.php b/administrator/components/com_users/tmpl/debuggroup/default.php index 105c04627585c..7e8e3a4360e3a 100644 --- a/administrator/components/com_users/tmpl/debuggroup/default.php +++ b/administrator/components/com_users/tmpl/debuggroup/default.php @@ -154,9 +154,7 @@ pagination->getListFooter(); ?> - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_users/tmpl/debuguser/default.php b/administrator/components/com_users/tmpl/debuguser/default.php index c7af6108f9fe6..b9a831ca10143 100644 --- a/administrator/components/com_users/tmpl/debuguser/default.php +++ b/administrator/components/com_users/tmpl/debuguser/default.php @@ -157,9 +157,7 @@ pagination->getListFooter(); ?> - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_users/tmpl/group/edit.php b/administrator/components/com_users/tmpl/group/edit.php index 77af501d105ec..4fb32df00674f 100644 --- a/administrator/components/com_users/tmpl/group/edit.php +++ b/administrator/components/com_users/tmpl/group/edit.php @@ -37,6 +37,5 @@ - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_users/tmpl/groups/default.php b/administrator/components/com_users/tmpl/groups/default.php index d016623675712..0384da71b69dc 100644 --- a/administrator/components/com_users/tmpl/groups/default.php +++ b/administrator/components/com_users/tmpl/groups/default.php @@ -137,9 +137,7 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_users/tmpl/level/edit.php b/administrator/components/com_users/tmpl/level/edit.php index 60f15b12bcfb6..1ad17237b9c2d 100644 --- a/administrator/components/com_users/tmpl/level/edit.php +++ b/administrator/components/com_users/tmpl/level/edit.php @@ -20,37 +20,18 @@ $wa = $this->getDocument()->getWebAssetManager(); $wa->useScript('keepalive') ->useScript('form.validate'); - ?>
- 'details', 'recall' => true, 'breakpoint' => 768]); ?> - - -
- -
-
- form->getLabel('title'); ?> -
-
- form->getInput('title'); ?> -
-
-
- - - + 'groups', 'recall' => true, 'breakpoint' => 768]); ?> + + form->renderField('title'); ?>
-
- item->rules, true); ?> -
+ item->rules, true); ?>
- - - + form->renderControlFields(); ?>
diff --git a/administrator/components/com_users/tmpl/levels/default.php b/administrator/components/com_users/tmpl/levels/default.php index baf162c273f81..f59078ab215f0 100644 --- a/administrator/components/com_users/tmpl/levels/default.php +++ b/administrator/components/com_users/tmpl/levels/default.php @@ -136,9 +136,8 @@ pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_users/tmpl/mail/default.php b/administrator/components/com_users/tmpl/mail/default.php index 212e57bc93e32..3e5bcb81e948f 100644 --- a/administrator/components/com_users/tmpl/mail/default.php +++ b/administrator/components/com_users/tmpl/mail/default.php @@ -11,7 +11,6 @@ defined('_JEXEC') or die; use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -57,6 +56,6 @@ form->renderField('group'); ?> - - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_users/tmpl/method/backupcodes.php b/administrator/components/com_users/tmpl/method/backupcodes.php index 56cb30780d3dc..942d2b9c63e34 100644 --- a/administrator/components/com_users/tmpl/method/backupcodes.php +++ b/administrator/components/com_users/tmpl/method/backupcodes.php @@ -15,9 +15,8 @@ use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; -use Joomla\Component\Users\Administrator\View\Method\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Users\Administrator\View\Method\HtmlView $this */ HTMLHelper::_('bootstrap.tooltip', '.hasTooltip'); diff --git a/administrator/components/com_users/tmpl/method/edit.php b/administrator/components/com_users/tmpl/method/edit.php index 74a86977a401a..5b8cd6866a4d1 100644 --- a/administrator/components/com_users/tmpl/method/edit.php +++ b/administrator/components/com_users/tmpl/method/edit.php @@ -14,10 +14,9 @@ use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; -use Joomla\Component\Users\Administrator\View\Method\HtmlView; use Joomla\Utilities\ArrayHelper; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Users\Administrator\View\Method\HtmlView $this */ $cancelURL = Route::_('index.php?option=com_users&task=methods.display&user_id=' . $this->user->id); diff --git a/administrator/components/com_users/tmpl/methods/default.php b/administrator/components/com_users/tmpl/methods/default.php index f9a325a3436a2..c1edba9148dbe 100644 --- a/administrator/components/com_users/tmpl/methods/default.php +++ b/administrator/components/com_users/tmpl/methods/default.php @@ -14,9 +14,8 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; -use Joomla\Component\Users\Administrator\View\Methods\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Users\Administrator\View\Methods\HtmlView $this */ ?>
diff --git a/administrator/components/com_users/tmpl/methods/firsttime.php b/administrator/components/com_users/tmpl/methods/firsttime.php index 58c474bb12076..8c1360697f3c8 100644 --- a/administrator/components/com_users/tmpl/methods/firsttime.php +++ b/administrator/components/com_users/tmpl/methods/firsttime.php @@ -14,9 +14,8 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; -use Joomla\Component\Users\Administrator\View\Methods\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Users\Administrator\View\Methods\HtmlView $this */ $headingLevel = 2; ?> diff --git a/administrator/components/com_users/tmpl/methods/list.php b/administrator/components/com_users/tmpl/methods/list.php index 889209626334b..557fb28a7a37b 100644 --- a/administrator/components/com_users/tmpl/methods/list.php +++ b/administrator/components/com_users/tmpl/methods/list.php @@ -18,9 +18,8 @@ use Joomla\CMS\Uri\Uri; use Joomla\Component\Users\Administrator\Helper\Mfa as MfaHelper; use Joomla\Component\Users\Administrator\Model\MethodsModel; -use Joomla\Component\Users\Administrator\View\Methods\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Users\Administrator\View\Methods\HtmlView $this */ HTMLHelper::_('bootstrap.tooltip', '.hasTooltip'); diff --git a/administrator/components/com_users/tmpl/note/edit.php b/administrator/components/com_users/tmpl/note/edit.php index 9387a31e49929..2cd299cbbca14 100644 --- a/administrator/components/com_users/tmpl/note/edit.php +++ b/administrator/components/com_users/tmpl/note/edit.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -35,13 +34,13 @@ form->renderField('review_time'); ?> form->renderField('version_note'); ?> - - - + form->renderControlFields(); ?>
form->renderField('body'); ?>
+ +
diff --git a/administrator/components/com_users/tmpl/notes/default.php b/administrator/components/com_users/tmpl/notes/default.php index d1665b2b956bc..81b016c4df119 100644 --- a/administrator/components/com_users/tmpl/notes/default.php +++ b/administrator/components/com_users/tmpl/notes/default.php @@ -119,11 +119,7 @@ -
- - - -
+ filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_users/tmpl/notes/emptystate.php b/administrator/components/com_users/tmpl/notes/emptystate.php index 87792bafa261d..9ca2946029231 100644 --- a/administrator/components/com_users/tmpl/notes/emptystate.php +++ b/administrator/components/com_users/tmpl/notes/emptystate.php @@ -19,6 +19,8 @@ 'formURL' => 'index.php?option=com_users&view=notes', 'helpURL' => 'https://docs.joomla.org/Special:MyLanguage/Help5.x:User_Notes', 'icon' => 'icon-users user', + + 'controlFields' => $this->filterForm->renderControlFields(), ]; if ($this->getCurrentUser()->authorise('core.create', 'com_users')) { diff --git a/administrator/components/com_users/tmpl/user/edit.php b/administrator/components/com_users/tmpl/user/edit.php index 69f400e57cf8e..8dc949474038b 100644 --- a/administrator/components/com_users/tmpl/user/edit.php +++ b/administrator/components/com_users/tmpl/user/edit.php @@ -21,7 +21,8 @@ /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->getDocument()->getWebAssetManager(); $wa->useScript('keepalive') - ->useScript('form.validate'); + ->useScript('form.validate') + ->useScript('com_users.activate-user-send-email'); $input = Factory::getApplication()->getInput(); @@ -76,7 +77,5 @@ - - - + form->renderControlFields(); ?> diff --git a/administrator/components/com_users/tmpl/user/edit_groups.php b/administrator/components/com_users/tmpl/user/edit_groups.php index 4525c00d0dd08..24f8aa377d40d 100644 --- a/administrator/components/com_users/tmpl/user/edit_groups.php +++ b/administrator/components/com_users/tmpl/user/edit_groups.php @@ -11,8 +11,7 @@ defined('_JEXEC') or die; use Joomla\CMS\HTML\HTMLHelper; -use Joomla\Component\Users\Administrator\View\User\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Users\Administrator\View\User\HtmlView $this */ echo HTMLHelper::_('access.usergroups', 'jform[groups]', $this->groups, true); diff --git a/administrator/components/com_users/tmpl/users/default.php b/administrator/components/com_users/tmpl/users/default.php index b02e1b66fe5ee..3d2c8400f2d9c 100644 --- a/administrator/components/com_users/tmpl/users/default.php +++ b/administrator/components/com_users/tmpl/users/default.php @@ -220,9 +220,7 @@ - - - + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_workflow/layouts/toolbar/shortcuts.php b/administrator/components/com_workflow/layouts/toolbar/shortcuts.php new file mode 100644 index 0000000000000..9602fecf29a63 --- /dev/null +++ b/administrator/components/com_workflow/layouts/toolbar/shortcuts.php @@ -0,0 +1,35 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; + +Factory::getApplication()->getDocument()->getWebAssetManager() + ->useScript('webcomponent.toolbar-button'); + +$shortcutsPopupOptions = json_encode([ + 'src' => '#shortcuts-popup-content', + 'width' => '800px', + 'height' => 'fit-content', + 'textHeader' => Text::_('COM_WORKFLOW_GRAPH_SHORTCUTS_TITLE'), + 'preferredParent' => 'body', +]); +?> + + + diff --git a/administrator/components/com_workflow/src/Controller/DisplayController.php b/administrator/components/com_workflow/src/Controller/DisplayController.php index d78369db70b8d..030e0aad3ccaf 100644 --- a/administrator/components/com_workflow/src/Controller/DisplayController.php +++ b/administrator/components/com_workflow/src/Controller/DisplayController.php @@ -10,13 +10,13 @@ namespace Joomla\Component\Workflow\Administrator\Controller; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\Application\CMSApplication; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\BaseController; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\Router\Route; use Joomla\Input\Input; -use Joomla\String\Inflector; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -110,7 +110,9 @@ public function display($cachable = false, $urlparams = []) $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id), 'error'); } - $url = 'index.php?option=com_workflow&view=' . Inflector::pluralize($view) . '&extension=' . $this->input->getCmd('extension'); + $inflector = InflectorFactory::create()->build(); + + $url = 'index.php?option=com_workflow&view=' . $inflector->pluralize($view) . '&extension=' . $this->input->getCmd('extension'); $this->setRedirect(Route::_($url, false)); diff --git a/administrator/components/com_workflow/src/Controller/GraphController.php b/administrator/components/com_workflow/src/Controller/GraphController.php new file mode 100644 index 0000000000000..6ea2d0dffcbbf --- /dev/null +++ b/administrator/components/com_workflow/src/Controller/GraphController.php @@ -0,0 +1,513 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Workflow\Administrator\Controller; + +use Joomla\CMS\Helper\ContentHelper; +use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\Controller\AdminController; +use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\CMS\Response\JsonResponse; +use Joomla\Utilities\ArrayHelper; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + + +/** + * The workflow Graphical View and Api controller + * + * @since 6.1.0 + */ +class GraphController extends AdminController +{ + /** + * Present workflow id + * + * @var integer + * @since 6.1.0 + */ + protected $workflowId; + + /** + * The extension + * + * @var string + * @since 6.1.0 + */ + protected $extension; + + /** + * The component name + * + * @var string + * @since 6.1.0 + */ + protected $component; + + /** + * The section of the current extension + * + * @var string + * @since 6.1.0 + */ + protected $section; + + /** + * The prefix to use with controller messages. + * + * @var string + * @since 6.1.0 + */ + protected $text_prefix = 'COM_WORKFLOW_GRAPH'; + + /** + * Transitions of present workflow, used for permission checks + * + * @var array + * @since 6.1.0 + */ + protected $transitions; + + + public function __construct($config = [], ?MVCFactoryInterface $factory = null, $app = null, $input = null) + { + parent::__construct($config, $factory, $app, $input); + + $this->registerTask('trash', 'publish'); + + // If workflow id is not set try to get it from input or throw an exception + if (empty($this->workflowId)) { + $this->workflowId = $this->input->getInt('id'); + if (empty($this->workflowId)) { + $this->workflowId = $this->input->getInt('workflow_id'); + } + + if (empty($this->workflowId)) { + throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_GRAPH_ERROR_WORKFLOW_ID_NOT_SET')); + } + } + + // If extension is not set try to get it from input or throw an exception + if (empty($this->extension)) { + $extension = $this->input->getCmd('extension'); + + $parts = explode('.', $extension); + + $this->component = reset($parts); + + $this->extension = array_shift($parts); + + if (!empty($parts)) { + $this->section = array_shift($parts); + } + + if (empty($this->extension)) { + throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_GRAPH_ERROR_EXTENSION_NOT_SET')); + } + } + } + + + /** + * Retrieves workflow data for graphical display in the workflow graph view. + * + * This method fetches the workflow details by ID, checks user permissions, + * and returns the workflow information as a JSON response for use in the + * graphical workflow editor or API consumers. + * + * @return void Outputs a JSON response with workflow data or error message. + * + * @since 6.1.0 + */ + public function getWorkflow(): void + { + + try { + $id = $this->workflowId; + $model = $this->getModel('Workflow'); + + if (empty($id)) { + throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_GRAPH_ERROR_INVALID_ID')); + } + + $workflow = $model->getItem($id); + + if (empty($workflow->id)) { + throw new \RuntimeException(Text::_('COM_WORKFLOW_GRAPH_ERROR_WORKFLOW_NOT_FOUND')); + } + + $user = $this->app->getIdentity(); + + // Check permissions + if (!$user->authorise('core.edit', $this->extension . '.workflow.' . $id) && !$this->hasAnyTransitionPermission($id)) { + throw new \RuntimeException(Text::_('JERROR_ALERTNOAUTHOR')); + } + + $canDo = ContentHelper::getActions($this->extension, 'workflow', $workflow->id); + $canCreate = $canDo->get('core.create'); + + $response = [ + 'id' => $workflow->id, + 'title' => Text::_($workflow->title), + 'description' => Text::_($workflow->description), + 'published' => (bool) $workflow->published, + 'default' => (bool) $workflow->default, + 'extension' => $workflow->extension, + 'canCreate' => $canCreate, + ]; + + echo new JsonResponse($response); + } catch (\Exception $e) { + $this->app->setHeader('status', 500); + echo new JsonResponse($e->getMessage(), 'error', true); + } + + $this->app->close(); + } + + /** + * Retrieves all stages for the specified workflow to be used in the workflow graph view. + * + * Fetches stages by workflow ID, decodes position data if available, and returns + * the result as a JSON response for graphical editors or API consumers. + * + * @return void Outputs a JSON response with stages data or error message. + * + * @since 6.1.0 + */ + public function getStages() + { + try { + $workflowId = $this->workflowId; + $model = $this->getModel('Stages'); + + if (empty($workflowId)) { + throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_GRAPH_ERROR_INVALID_ID')); + } + + $user = $this->app->getIdentity(); + + if (!$user->authorise('core.edit', $this->extension . '.workflow.' . $workflowId) && !$this->hasAnyTransitionPermission($workflowId)) { + throw new \RuntimeException(Text::_('JERROR_ALERTNOAUTHOR')); + } + + + $model->setState('filter.workflow_id', $workflowId); + $model->setState('list.limit', 0); // Get all stages + + $stages = $model->getItems(); + + if (empty($stages)) { + throw new \RuntimeException(Text::_('COM_WORKFLOW_GRAPH_ERROR_STAGES_NOT_FOUND')); + } + + $response = []; + $canEditWorkflow = $user->authorise('core.edit', $this->extension . '.workflow.' . $workflowId); + + $allowedStageIds = []; + + if (!$canEditWorkflow) { + $transitions = $this->getWorkflowTransitions($workflowId); + + foreach ($transitions as $transition) { + if ( + $user->authorise('core.execute.transition', $this->extension . '.transition.' . (int) $transition->id) + || $user->authorise('core.edit', $this->extension . '.transition.' . (int) $transition->id) + || $user->authorise('core.delete', $this->extension . '.transition.' . (int) $transition->id) + ) { + if ((int) $transition->from_stage_id !== -1) { + $allowedStageIds[] = (int) $transition->from_stage_id; + } + $allowedStageIds[] = (int) $transition->to_stage_id; + } + } + $allowedStageIds = array_unique($allowedStageIds); + } + + foreach ($stages as $stage) { + $canEdit = $user->authorise('core.edit', $this->extension . '.stage.' . $stage->id); + $canDelete = $user->authorise('core.delete', $this->extension . '.stage.' . $stage->id); + + if (!$canEditWorkflow && !$canEdit && !$canDelete && !\in_array((int) $stage->id, $allowedStageIds)) { + continue; + } + + $response[] = [ + 'id' => (int) $stage->id, + 'title' => Text::_($stage->title), + 'description' => Text::_($stage->description), + 'published' => (bool) $stage->published, + 'default' => (bool) $stage->default, + 'ordering' => (int) $stage->ordering, + 'position' => $stage->position ? json_decode($stage->position, true) : null, + 'workflow_id' => $stage->workflow_id, + 'permissions' => [ + 'edit' => $canEdit, + 'delete' => $canDelete, + ], + ]; + } + echo new JsonResponse($response); + } catch (\Exception $e) { + $this->app->setHeader('status', 500); + echo new JsonResponse($e->getMessage(), 'error', true); + } + + $this->app->close(); + } + + + /** + * Retrieves all transitions for the specified workflow to be used in the workflow graph view. + * + * Fetches transitions by workflow ID and returns the result as a JSON response + * for graphical editors or API consumers. + * + * @return void Outputs a JSON response with transitions data or error message. + * + * @since 6.1.0 + */ + public function getTransitions() + { + + try { + $workflowId = $this->workflowId; + + if (empty($workflowId)) { + throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_GRAPH_ERROR_INVALID_ID')); + } + + $user = $this->app->getIdentity(); + + if ( + !$user->authorise('core.edit', $this->extension . '.workflow.' . $workflowId) + && !$this->hasAnyTransitionPermission($workflowId) + ) { + throw new \RuntimeException(Text::_('JERROR_ALERTNOAUTHOR')); + } + + $transitions = $this->getWorkflowTransitions($workflowId); + + $response = []; + + $canEditWorkflow = $user->authorise('core.edit', $this->extension . '.workflow.' . $workflowId); + foreach ($transitions as $transition) { + $canEdit = $user->authorise('core.edit', $this->extension . '.transition.' . (int) $transition->id); + $canDelete = $user->authorise('core.delete', $this->extension . '.transition.' . (int) $transition->id); + $canRun = $user->authorise('core.execute.transition', $this->extension . '.transition.' . (int) $transition->id); + + if (!$canEditWorkflow && !$canEdit && !$canDelete && !$canRun) { + continue; + } + + $response[] = [ + 'id' => (int) $transition->id, + 'title' => Text::_($transition->title), + 'description' => Text::_($transition->description), + 'published' => (bool) $transition->published, + 'from_stage_id' => (int) $transition->from_stage_id, + 'to_stage_id' => (int) $transition->to_stage_id, + 'ordering' => (int) $transition->ordering, + 'workflow_id' => (int) $transition->workflow_id, + 'permissions' => [ + 'edit' => $canEdit, + 'delete' => $canDelete, + 'run_transition' => $canRun, + ], + ]; + } + + echo new JsonResponse($response); + } catch (\Exception $e) { + $this->app->setHeader('status', 500); + echo new JsonResponse($e->getMessage(), 'error', true); + } + + $this->app->close(); + } + + + public function publish($type = 'stage') + { + + try { + // Check for request forgeries + if (!$this->checkToken('post', false)) { + throw new \RuntimeException(Text::_('JINVALID_TOKEN')); + } + + // Check if the user has permission to publish items + if (!$this->app->getIdentity()->authorise('core.edit.state', $this->extension . '.workflow.' . $this->workflowId)) { + throw new \RuntimeException(Text::_('JERROR_ALERTNOAUTHOR')); + } + + // Get items to publish from the request. + $cid = (array) $this->input->get('cid', [], 'int'); + $data = ['publish' => 1, 'unpublish' => 0, 'archive' => 2, 'trash' => -2, 'report' => -3]; + $task = $this->getTask(); + $type = $this->input->getCmd('type'); + $value = ArrayHelper::getValue($data, $task, 0, 'int'); + + if (empty($type)) { + throw new \RuntimeException(Text::_($this->text_prefix . '_' . strtoupper($type) . '_NO_ITEM_SELECTED')); + } + + // Remove zero values resulting from input filter + $cid = array_filter($cid); + + if (empty($cid)) { + throw new \RuntimeException(Text::_($this->text_prefix . '_' . strtoupper($type) . '_NO_ITEM_SELECTED')); + } + // Get the model. + $model = $this->getModel($type); + + + $model->publish($cid, $value); + $errors = $model->getErrors(); + $ntext = null; + + if ($value === 1) { + if ($errors) { + echo new JsonResponse(Text::plural($this->text_prefix . '_' . strtoupper($type) . '_N_ITEMS_FAILED_PUBLISHING', \count($cid)), 'error', true); + } else { + $ntext = $this->text_prefix . '_' . strtoupper($type) . '_N_ITEMS_PUBLISHED'; + } + } elseif ($value === 0) { + $ntext = $this->text_prefix . '_' . strtoupper($type) . '_N_ITEMS_UNPUBLISHED'; + } elseif ($value === 2) { + $ntext = $this->text_prefix . '_' . strtoupper($type) . '_N_ITEMS_ARCHIVED'; + } else { + $ntext = $this->text_prefix . '_' . strtoupper($type) . '_N_ITEMS_TRASHED'; + } + + $response = [ + 'success' => true, + 'message' => Text::plural($ntext, \count($cid)), + ]; + + if (\count($cid)) { + echo new JsonResponse($response); + } + } catch (\Exception $e) { + $this->app->setHeader('status', 500); + echo new JsonResponse($e->getMessage(), 'error', true); + } + $this->app->close(); + } + + public function delete($type = 'stage') + { + try { + // Check for request forgeries + if (!$this->checkToken('post', false)) { + throw new \RuntimeException(Text::_('JINVALID_TOKEN')); + } + + // Get items to remove from the request. + $cid = (array) $this->input->get('cid', [], 'int'); + $type = $this->input->getCmd('type'); + $cid = array_filter($cid); + + if (empty($cid)) { + throw new \RuntimeException(Text::_($this->text_prefix . '_' . strtoupper($type) . '_NO_ITEM_SELECTED')); + } + // Get the model. + $model = $this->getModel($type); + + // Remove the items. + if ($model->delete($cid)) { + $response = [ + 'success' => true, + 'message' => Text::plural($this->text_prefix . '_' . strtoupper($type) . '_N_ITEMS_DELETED', \count($cid)), + ]; + } else { + throw new \RuntimeException(Text::plural($this->text_prefix . '_' . strtoupper($type) . '_N_ITEMS_FAILED_DELETING', \count($cid))); + } + + if (isset($response)) { + echo new JsonResponse($response); + } + + // Invoke the postDelete method to allow for the child class to access the model. + $this->postDeleteHook($model, $cid); + } catch (\Exception $e) { + $this->app->setHeader('status', 500); + echo new JsonResponse($e->getMessage(), 'error', true); + } + + $this->app->close(); + } + + /** + * Method to get a model object, loading it if required. + * + * @param string $name The model name. Optional. + * @param string $prefix The class prefix. Optional. + * @param array $config Configuration array for model. Optional. + * + * @return BaseDatabaseModel|boolean Model object on success; otherwise false on failure. + * + * @since 6.1.0 + */ + public function getModel($name = '', $prefix = 'Administrator', $config = ['ignore_request' => true]) + { + return parent::getModel($name, $prefix, $config); + } + + /** + * Get the transitions for a workflow. + * + * @param integer $workflowId The workflow id + * + * @return array + * + * @since 6.1.0 + */ + protected function getWorkflowTransitions($workflowId): array + { + if ($this->transitions === null) { + $model = $this->getModel('Transitions'); + $model->setState('filter.workflow_id', $workflowId); + $model->setState('list.limit', 0); + $this->transitions = $model->getItems(); + } + + return $this->transitions; + } + + /** + * Check if the user has permission to at least one transition in the workflow. + * + * @param integer $workflowId The workflow id + * + * @return boolean + * + * @since 6.1.0 + */ + protected function hasAnyTransitionPermission($workflowId): bool + { + $transitions = $this->getWorkflowTransitions($workflowId); + $user = $this->app->getIdentity(); + + foreach ($transitions as $transition) { + if ( + $user->authorise('core.execute.transition', $this->extension . '.transition.' . (int) $transition->id) + || $user->authorise('core.edit', $this->extension . '.transition.' . (int) $transition->id) + || $user->authorise('core.delete', $this->extension . '.transition.' . (int) $transition->id) + ) { + return true; + } + } + + return false; + } +} diff --git a/administrator/components/com_workflow/src/Controller/StageController.php b/administrator/components/com_workflow/src/Controller/StageController.php index b113d32619212..4c191984b229e 100644 --- a/administrator/components/com_workflow/src/Controller/StageController.php +++ b/administrator/components/com_workflow/src/Controller/StageController.php @@ -14,6 +14,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\FormController; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\CMS\Router\Route; use Joomla\Input\Input; // phpcs:disable PSR1.Files.SideEffects @@ -174,4 +175,56 @@ protected function getRedirectToListAppend() return $append; } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 6.1.0 + */ + public function save($key = null, $urlVar = null) + { + $result = parent::save($key, $urlVar); + $input = $this->input; + $isModal = $input->get('layout') === 'modal' || $input->get('tmpl') === 'component'; + $task = $this->getTask(); + + if ($isModal && $result && $task === 'save') { + $id = $this->input->get('id'); + $return = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($id) + . '&layout=modalreturn&from-task=save'; + + $this->setRedirect(Route::_($return, false)); + } + return $result; + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 6.1.0 + */ + public function cancel($key = null) + { + $result = parent::cancel($key); + $input = $this->input; + $isModal = $input->get('layout') === 'modal' || $input->get('tmpl') === 'component'; + + if ($isModal) { + $id = $this->input->get('id'); + $return = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($id) + . '&layout=modalreturn&from-task=cancel'; + + $this->setRedirect(Route::_($return, false)); + } + return $result; + } } diff --git a/administrator/components/com_workflow/src/Controller/StagesController.php b/administrator/components/com_workflow/src/Controller/StagesController.php index bd5c25f62b935..ae86156575217 100644 --- a/administrator/components/com_workflow/src/Controller/StagesController.php +++ b/administrator/components/com_workflow/src/Controller/StagesController.php @@ -14,6 +14,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\AdminController; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\CMS\Response\JsonResponse; use Joomla\CMS\Router\Route; use Joomla\Input\Input; use Joomla\Utilities\ArrayHelper; @@ -195,4 +196,45 @@ protected function getRedirectToListAppend() { return '&extension=' . $this->extension . ($this->section ? '.' . $this->section : '') . '&workflow_id=' . $this->workflowId; } + + /** + * Method to save stage positions + * + * @return boolean True if successful, false otherwise. + * + * @since 6.1.0 + */ + public function updateStagesPosition() + { + try { + // Check for request forgeries + if (!$this->checkToken('post', false)) { + throw new \RuntimeException(Text::_('JINVALID_TOKEN')); + } + + // Check if the user has permission to publish items + if (!$this->app->getIdentity()->authorise('core.edit.state', $this->extension . '.workflow.' . $this->workflowId)) { + throw new \RuntimeException(Text::_('JERROR_ALERTNOAUTHOR')); + } + + $app = $this->app; + $input = $app->getInput(); + $workflowId = $input->getInt('id'); + $positions = $input->get('positions', [], 'array'); + $model = $this->getModel('Stages', 'Administrator'); + + $response = []; + $success = $model->updatePositions($positions, $workflowId); + + $response = [ + 'success' => true, + 'message' => Text::_('COM_WORKFLOW_POSITIONS_SAVED'), + ]; + echo new JsonResponse($response); + } catch (\Exception $e) { + $this->app->setHeader('status', 500); + echo new JsonResponse($e->getMessage(), 'error', true); + } + $this->app->close(); + } } diff --git a/administrator/components/com_workflow/src/Controller/TransitionController.php b/administrator/components/com_workflow/src/Controller/TransitionController.php index e78227550dab3..c63b65f741c18 100644 --- a/administrator/components/com_workflow/src/Controller/TransitionController.php +++ b/administrator/components/com_workflow/src/Controller/TransitionController.php @@ -14,6 +14,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\FormController; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\CMS\Router\Route; use Joomla\Input\Input; // phpcs:disable PSR1.Files.SideEffects @@ -175,4 +176,56 @@ protected function getRedirectToListAppend() return $append; } + + /** + * Method to save a request. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 6.1.0 + */ + public function save($key = null, $urlVar = null) + { + $result = parent::save($key, $urlVar); + $input = $this->input; + $isModal = $input->get('layout') === 'modal' || $input->get('tmpl') === 'component'; + $task = $this->getTask(); + + if ($isModal && $result && $task === 'save') { + $id = $this->input->get('id'); + $return = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($id) + . '&layout=modalreturn&from-task=save'; + + $this->setRedirect(Route::_($return, false)); + } + return $result; + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 6.1.0 + */ + public function cancel($key = null) + { + $result = parent::cancel($key); + $input = $this->input; + $isModal = $input->get('layout') === 'modal' || $input->get('tmpl') === 'component'; + + if ($isModal) { + $id = $this->input->get('id'); + $return = 'index.php?option=' . $this->option . '&view=' . $this->view_item . $this->getRedirectToItemAppend($id) + . '&layout=modalreturn&from-task=cancel'; + + $this->setRedirect(Route::_($return, false)); + } + return $result; + } } diff --git a/administrator/components/com_workflow/src/Controller/WorkflowController.php b/administrator/components/com_workflow/src/Controller/WorkflowController.php index 077e43c0445ae..af0c52bfdfb12 100644 --- a/administrator/components/com_workflow/src/Controller/WorkflowController.php +++ b/administrator/components/com_workflow/src/Controller/WorkflowController.php @@ -184,7 +184,7 @@ public function postSaveHook(BaseDatabaseModel $model, $validData = []) // @todo Moves queries out of the controller. $db = $model->getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select('*') ->from($db->quoteName('#__workflow_stages')) @@ -214,7 +214,7 @@ public function postSaveHook(BaseDatabaseModel $model, $validData = []) $mapping[$oldID] = (int) $table->id; } - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__workflow_transitions')) ->where($db->quoteName('workflow_id') . ' = :id') diff --git a/administrator/components/com_workflow/src/Dispatcher/Dispatcher.php b/administrator/components/com_workflow/src/Dispatcher/Dispatcher.php index 5633363111185..77acbe6da1a16 100644 --- a/administrator/components/com_workflow/src/Dispatcher/Dispatcher.php +++ b/administrator/components/com_workflow/src/Dispatcher/Dispatcher.php @@ -31,12 +31,26 @@ class Dispatcher extends ComponentDispatcher */ protected function checkAccess() { - $extension = $this->getApplication()->getInput()->getCmd('extension'); + $input = $this->app->getInput(); + $view = $input->getCmd('view'); + $layout = $input->getCmd('layout'); + $task = $input->getCmd('task'); + $extension = $input->getCmd('extension'); + $parts = explode('.', $extension); - $parts = explode('.', $extension); + $allowedTasks = [ + 'graph.getWorkflow', + 'graph.getStages', + 'graph.getTransitions', + ]; - // Check the user has permission to access this component if in the backend - if ($this->app->isClient('administrator') && !$this->app->getIdentity()->authorise('core.manage.workflow', $parts[0])) { + // Allow access to the 'graph' view for all users with access + if ($this->app->isClient('administrator') && $view === 'graph' && \in_array($task, $allowedTasks, true)) { + return; + } + + // Check the user has permission to edit this component + if (!$this->app->getIdentity()->authorise('core.manage.workflow', $parts[0])) { throw new NotAllowed($this->app->getLanguage()->_('JERROR_ALERTNOAUTHOR'), 403); } } diff --git a/administrator/components/com_workflow/src/Field/ComponentsWorkflowField.php b/administrator/components/com_workflow/src/Field/ComponentsWorkflowField.php index cd4ed6361082a..8b520e005b55d 100644 --- a/administrator/components/com_workflow/src/Field/ComponentsWorkflowField.php +++ b/administrator/components/com_workflow/src/Field/ComponentsWorkflowField.php @@ -48,7 +48,7 @@ protected function getOptions() // Initialise variable. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT a.name AS text, a.element AS value') ->from('#__extensions as a') ->where('a.enabled >= 1') diff --git a/administrator/components/com_workflow/src/Model/GraphModel.php b/administrator/components/com_workflow/src/Model/GraphModel.php new file mode 100644 index 0000000000000..840ac089026d3 --- /dev/null +++ b/administrator/components/com_workflow/src/Model/GraphModel.php @@ -0,0 +1,74 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * @since 6.1.0 + */ + +namespace Joomla\Component\Workflow\Administrator\Model; + +use Joomla\CMS\Factory; +use Joomla\CMS\MVC\Model\AdminModel; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Model class for Graphical View of the workflow + * + * @since 6.1.0 + */ +class GraphModel extends AdminModel +{ + /** + * Auto-populate the model state. + * + * Note. Calling getState in this method will result in recursion. + * + * @return void + * + * @since 6.1.0 + */ + public function populateState() + { + parent::populateState(); + + $app = Factory::getApplication(); + $context = $this->option . '.' . $this->name; + $extension = $app->getUserStateFromRequest($context . '.filter.extension', 'extension', null, 'cmd'); + + $this->setState('filter.extension', $extension); + } + + /** + * Method to get the name of the model. + * + * @return string The name of the model. + * + * @since 6.1.0 + */ + public function getName() + { + return 'workflow'; // TODO: change it to to handle dynamically + } + + /** + * Method to get the form. + * + * @param array $data An optional array of data for the form to interrogate. + * @param bool $loadData True if the form is to load its own data (default case), false if not. + * + * @return mixed A \Joomla\CMS\Form\Form object on success, false on failure. + * + * @since 6.1.0 + */ + public function getForm($data = [], $loadData = true) + { + return false; + } +} diff --git a/administrator/components/com_workflow/src/Model/StageModel.php b/administrator/components/com_workflow/src/Model/StageModel.php index 1c3148e155454..bda6664101ab6 100644 --- a/administrator/components/com_workflow/src/Model/StageModel.php +++ b/administrator/components/com_workflow/src/Model/StageModel.php @@ -203,9 +203,10 @@ protected function canEditState($record) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|boolean A Form object on success, false on failure + * @return Form A Form object, false on failure * * @since 4.0.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -219,10 +220,6 @@ public function getForm($data = [], $loadData = true) ] ); - if (empty($form)) { - return false; - } - $id = $data['id'] ?? $form->getValue('id'); $item = $this->getItem($id); diff --git a/administrator/components/com_workflow/src/Model/StagesModel.php b/administrator/components/com_workflow/src/Model/StagesModel.php index bd26a985bc8ea..8a600e5cd225a 100644 --- a/administrator/components/com_workflow/src/Model/StagesModel.php +++ b/administrator/components/com_workflow/src/Model/StagesModel.php @@ -12,6 +12,7 @@ namespace Joomla\Component\Workflow\Administrator\Model; use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; use Joomla\Database\ParameterType; @@ -130,7 +131,7 @@ public function getTable($type = 'Stage', $prefix = 'Administrator', $config = [ public function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select( @@ -140,9 +141,11 @@ public function getListQuery() $db->quoteName('s.ordering'), $db->quoteName('s.default'), $db->quoteName('s.published'), + $db->quoteName('s.workflow_id'), $db->quoteName('s.checked_out'), $db->quoteName('s.checked_out_time'), $db->quoteName('s.description'), + $db->quoteName('s.position'), $db->quoteName('uc.name', 'editor'), ] ) @@ -200,4 +203,70 @@ public function getWorkflow() return (object) $table->getProperties(); } + + /** + * Update positions for multiple workflow stages + * + * @param array $stages Array of stage data, each with id, x, y values + * + * + * @return boolean True on success, false on failure + * + * @since 6.1.0 + */ + public function updatePositions($stagePositions, $workflowId) + { + if (empty($stagePositions) || !\is_array($stagePositions)) { + throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_GRAPH_ERROR_INVALID_STAGE_POSITIONS')); + } + + // Convert the stage positions to the expected format + $stages = []; + foreach ($stagePositions as $id => $position) { + if (isset($position['x'], $position['y'])) { + $stages[] = [ + 'id' => (int) $id, + 'x' => (float) $position['x'], + 'y' => (float) $position['y'], + ]; + } else { + throw new \InvalidArgumentException(Text::sprintf('COM_WORKFLOW_GRAPH_ERROR_INVALID_POSITION_DATA', $id)); + } + } + + $db = $this->getDatabase(); + + try { + $db->transactionStart(); + + foreach ($stages as $stage) { + if (!isset($stage['id']) || !isset($stage['x']) || !isset($stage['y'])) { + throw new \InvalidArgumentException(Text::_('COM_WORKFLOW_GRAPH_ERROR_INVALID_POSITION_DATA', $stage['id'])); + } + + $id = (int) $stage['id']; + $x = (float) $stage['x']; + $y = (float) $stage['y']; + + // Format the position as a text which can later converted to json + $point = '{"x":' . $x . ', "y":' . $y . '}'; + + $query = $db->getQuery(true) + ->update($db->quoteName('#__workflow_stages')) + ->set($db->quoteName('position') . ' = :position') + ->where($db->quoteName('id') . ' = :id') + ->bind(':position', $point, ParameterType::STRING) + ->bind(':id', $id, ParameterType::INTEGER); + $db->setQuery($query); + $db->execute(); + } + + $db->transactionCommit(); + } catch (\Exception $e) { + $db->transactionRollback(); + throw new \RuntimeException(Text::_('COM_WORKFLOW_GRAPH_ERROR_FAILED_TO_UPDATE_STAGE_POSITIONS') . ': ' . $e->getMessage()); + } + + return true; + } } diff --git a/administrator/components/com_workflow/src/Model/TransitionModel.php b/administrator/components/com_workflow/src/Model/TransitionModel.php index e5b26901f64c2..448625d4dc658 100644 --- a/administrator/components/com_workflow/src/Model/TransitionModel.php +++ b/administrator/components/com_workflow/src/Model/TransitionModel.php @@ -105,7 +105,7 @@ protected function canEditState($record) * * @param integer $pk The id of the primary key. * - * @return \Joomla\CMS\Object\CMSObject|boolean Object on success, false on failure. + * @return \stdClass|boolean Object on success, false on failure. * * @since 4.0.0 */ @@ -210,9 +210,10 @@ protected function generateNewTitle($categoryId, $alias, $title) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 4.0.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -226,10 +227,6 @@ public function getForm($data = [], $loadData = true) ] ); - if (empty($form)) { - return false; - } - $id = $data['id'] ?? $form->getValue('id'); $item = $this->getItem($id); diff --git a/administrator/components/com_workflow/src/Model/TransitionsModel.php b/administrator/components/com_workflow/src/Model/TransitionsModel.php index 7a3171c9cc6ce..68c8349e55c0a 100644 --- a/administrator/components/com_workflow/src/Model/TransitionsModel.php +++ b/administrator/components/com_workflow/src/Model/TransitionsModel.php @@ -131,7 +131,7 @@ protected function getReorderConditions($table) public function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select( @@ -141,6 +141,7 @@ public function getListQuery() $db->quoteName('t.from_stage_id'), $db->quoteName('t.to_stage_id'), $db->quoteName('t.published'), + $db->quoteName('t.workflow_id'), $db->quoteName('t.checked_out'), $db->quoteName('t.checked_out_time'), $db->quoteName('t.ordering'), diff --git a/administrator/components/com_workflow/src/Model/WorkflowModel.php b/administrator/components/com_workflow/src/Model/WorkflowModel.php index ea47b4a7f5282..9ca07c065f60f 100644 --- a/administrator/components/com_workflow/src/Model/WorkflowModel.php +++ b/administrator/components/com_workflow/src/Model/WorkflowModel.php @@ -146,9 +146,10 @@ public function save($data) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return \Joomla\CMS\Form\Form|boolean A Form object on success, false on failure + * @return Form A Form object * * @since 4.0.0 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { @@ -162,10 +163,6 @@ public function getForm($data = [], $loadData = true) ] ); - if (empty($form)) { - return false; - } - $id = $data['id'] ?? $form->getValue('id'); $item = $this->getItem($id); diff --git a/administrator/components/com_workflow/src/Model/WorkflowsModel.php b/administrator/components/com_workflow/src/Model/WorkflowsModel.php index 1a2f14a0a1585..a660ad10d12cd 100644 --- a/administrator/components/com_workflow/src/Model/WorkflowsModel.php +++ b/administrator/components/com_workflow/src/Model/WorkflowsModel.php @@ -165,7 +165,7 @@ protected function countItems($items) $item->count_transitions = 0; } - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ @@ -180,7 +180,7 @@ protected function countItems($items) $status = $db->setQuery($query)->loadObjectList('workflow_id'); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ @@ -216,7 +216,7 @@ protected function countItems($items) public function getListQuery() { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( [ diff --git a/administrator/components/com_workflow/src/Table/StageTable.php b/administrator/components/com_workflow/src/Table/StageTable.php index 9392b80750140..f3fa0738d597d 100644 --- a/administrator/components/com_workflow/src/Table/StageTable.php +++ b/administrator/components/com_workflow/src/Table/StageTable.php @@ -67,7 +67,7 @@ public function delete($pk = null) $app = Factory::getApplication(); $pk = (int) $pk; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('default')) ->from($db->quoteName('#__workflow_stages')) ->where($db->quoteName('id') . ' = :id') @@ -82,7 +82,7 @@ public function delete($pk = null) } try { - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__workflow_transitions')) ->where( [ @@ -135,7 +135,7 @@ public function check() } } else { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select($db->quoteName('id')) diff --git a/administrator/components/com_workflow/src/Table/WorkflowTable.php b/administrator/components/com_workflow/src/Table/WorkflowTable.php index 58d634d1b5b15..e0b269cb3bf7f 100644 --- a/administrator/components/com_workflow/src/Table/WorkflowTable.php +++ b/administrator/components/com_workflow/src/Table/WorkflowTable.php @@ -73,7 +73,7 @@ public function delete($pk = null) $pk = (int) $pk; // Gets the workflow information that is going to be deleted. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('default')) ->from($db->quoteName('#__workflows')) ->where($db->quoteName('id') . ' = :id') @@ -89,14 +89,14 @@ public function delete($pk = null) // Delete the workflow states, then transitions from all tables. try { - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__workflow_stages')) ->where($db->quoteName('workflow_id') . ' = :id') ->bind(':id', $pk, ParameterType::INTEGER); $db->setQuery($query)->execute(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__workflow_transitions')) ->where($db->quoteName('workflow_id') . ' = :id') ->bind(':id', $pk, ParameterType::INTEGER); @@ -143,7 +143,7 @@ public function check() } } else { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select($db->quoteName('id')) @@ -301,7 +301,7 @@ protected function _getAssetParentId(?Table $table = null, $id = null) // Build the query to get the asset id for the parent category. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__assets')) ->where($db->quoteName('name') . ' = :extension') diff --git a/administrator/components/com_workflow/src/View/Graph/HtmlView.php b/administrator/components/com_workflow/src/View/Graph/HtmlView.php new file mode 100644 index 0000000000000..fb75e4e498e80 --- /dev/null +++ b/administrator/components/com_workflow/src/View/Graph/HtmlView.php @@ -0,0 +1,159 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Workflow\Administrator\View\Graph; + +use Joomla\CMS\Factory; +use Joomla\CMS\Helper\ContentHelper; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Layout\FileLayout; +use Joomla\CMS\MVC\View\GenericDataException; +use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView; +use Joomla\CMS\Router\Route; +use Joomla\CMS\Toolbar\ToolbarHelper; +use Joomla\Component\Workflow\Administrator\Model\GraphModel; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * View class to display the entire workflow graph + * + * @since 6.1.0 + */ +class HtmlView extends BaseHtmlView +{ + /** + * The model state + * + * @var object + * @since 6.1.0 + */ + protected $state; + + /** + * Items array + * + * @var object + * @since 6.1.0 + */ + protected $item; + + /** + * The name of current extension + * + * @var string + * @since 6.1.0 + */ + protected $extension; + + /** + * The ID of current workflow + * + * @var integer + * @since 6.1.0 + */ + protected $workflow; + + /** + * The section of the current extension + * + * @var string + * @since 6.1.0 + */ + protected $section; + + /** + * Display the view + * + * @param string $tpl The name of the template file to parse; automatically searches through the template paths. + * + * @return void + * + * @since 6.1.0 + */ + public function display($tpl = null) + { + /** @var GraphModel $model */ + $model = $this->getModel(); + + // Get the data + try { + $this->state = $model->getState(); + $this->item = $model->getItem(); + } catch (\Exception $e) { + throw new GenericDataException(Text::_('COM_WORKFLOW_GRAPH_ERROR_FETCHING_MODEL') . $e->getMessage(), 500, $e); + } + + $extension = $this->state->get('filter.extension'); + + $parts = explode('.', $extension); + + $this->extension = array_shift($parts); + + if (!empty($parts)) { + $this->section = array_shift($parts); + } + + // Prepare workflow data for frontend + $options = [ + 'apiBaseUrl' => Route::_('index.php?option=com_workflow'), + 'extension' => $this->escape($this->extension), + 'workflowId' => $this->item->id, + ]; + + + // Set the toolbar + $this->addToolbar(); + + // Inject workflow data as JS options for frontend + $this->getDocument()->addScriptOptions('com_workflow', $options); + + // Display the template + parent::display($tpl); + } + + /** + * Add the page title and toolbar. + * + * @return void + * + * @since 6.1.0 + */ + protected function addToolbar() + { + Factory::getApplication()->getInput()->set('hidemainmenu', true); + + $user = $this->getCurrentUser(); + $userId = $user->id; + $toolbar = $this->getDocument()->getToolbar(); + + $canDo = ContentHelper::getActions($this->extension, 'workflow', $this->item->id); + + ToolbarHelper::title(Text::_('COM_WORKFLOW_GRAPH_WORKFLOWS_EDIT'), 'file-alt contact'); + + // Since it's an existing record, check the edit permission, or fall back to edit own if the owner. + $itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId); + + $toolbar->link( + 'JTOOLBAR_CLOSE', + Route::_('index.php?option=com_workflow&view=workflows&extension=' . $this->escape($this->item->extension)) + ) + ->icon('icon-cancel')->buttonClass('btn btn-danger'); + + if ($itemEditable) { + $toolbar->help('Workflow'); + $shortcutsLayout = new FileLayout('toolbar.shortcuts', JPATH_ADMINISTRATOR . '/components/com_workflow/layouts'); + $toolbar->customButton('Shortcuts') + ->html($shortcutsLayout->render([])); + } + } +} diff --git a/administrator/components/com_workflow/src/View/Stage/HtmlView.php b/administrator/components/com_workflow/src/View/Stage/HtmlView.php index 98dfda3cc8229..60b1c9d9b68e3 100644 --- a/administrator/components/com_workflow/src/View/Stage/HtmlView.php +++ b/administrator/components/com_workflow/src/View/Stage/HtmlView.php @@ -100,6 +100,10 @@ public function display($tpl = null) $this->section = array_shift($parts); } + // Add form control fields + $this->form + ->addControlField('task', 'stage.edit'); + // Set the toolbar $this->addToolbar(); diff --git a/administrator/components/com_workflow/src/View/Stages/HtmlView.php b/administrator/components/com_workflow/src/View/Stages/HtmlView.php index 151303cfa9e68..da1edabcb3ab0 100644 --- a/administrator/components/com_workflow/src/View/Stages/HtmlView.php +++ b/administrator/components/com_workflow/src/View/Stages/HtmlView.php @@ -150,6 +150,13 @@ public function display($tpl = null) $this->section = array_shift($parts); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0') + ->addControlField('workflow_id', $this->workflowID) + ->addControlField('extension', $this->extension); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_workflow/src/View/Transition/HtmlView.php b/administrator/components/com_workflow/src/View/Transition/HtmlView.php index 02be9638117d2..5e4c4a04ab5e8 100644 --- a/administrator/components/com_workflow/src/View/Transition/HtmlView.php +++ b/administrator/components/com_workflow/src/View/Transition/HtmlView.php @@ -65,7 +65,7 @@ class HtmlView extends BaseHtmlView /** * The application input object. * - * @var \Joomla\CMS\Input\Input + * @var \Joomla\Input\Input * @since 4.0.0 */ protected $input; @@ -138,6 +138,10 @@ public function display($tpl = null) // Get the ID of workflow $this->workflowID = $this->input->getCmd("workflow_id"); + // Add form control fields + $this->form + ->addControlField('task', 'transition.edit'); + // Set the toolbar $this->addToolbar(); diff --git a/administrator/components/com_workflow/src/View/Transitions/HtmlView.php b/administrator/components/com_workflow/src/View/Transitions/HtmlView.php index aeb0ddbef80e5..1c21f2677fc43 100644 --- a/administrator/components/com_workflow/src/View/Transitions/HtmlView.php +++ b/administrator/components/com_workflow/src/View/Transitions/HtmlView.php @@ -143,6 +143,13 @@ public function display($tpl = null) $this->section = array_shift($parts); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0') + ->addControlField('workflow_id', $this->workflowID) + ->addControlField('extension', $this->extension); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_workflow/src/View/Workflow/HtmlView.php b/administrator/components/com_workflow/src/View/Workflow/HtmlView.php index 30ff34caddfee..21cb043217a1b 100644 --- a/administrator/components/com_workflow/src/View/Workflow/HtmlView.php +++ b/administrator/components/com_workflow/src/View/Workflow/HtmlView.php @@ -104,6 +104,10 @@ public function display($tpl = null) $this->section = array_shift($parts); } + // Add form control fields + $this->form + ->addControlField('task', 'workflow.edit'); + // Set the toolbar $this->addToolbar(); diff --git a/administrator/components/com_workflow/src/View/Workflows/HtmlView.php b/administrator/components/com_workflow/src/View/Workflows/HtmlView.php index adf2797c1959d..a132d883a8855 100644 --- a/administrator/components/com_workflow/src/View/Workflows/HtmlView.php +++ b/administrator/components/com_workflow/src/View/Workflows/HtmlView.php @@ -123,6 +123,11 @@ public function display($tpl = null) $this->section = array_shift($parts); } + // Add form control fields + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + $this->addToolbar(); parent::display($tpl); diff --git a/administrator/components/com_workflow/tmpl/graph/default.php b/administrator/components/com_workflow/tmpl/graph/default.php new file mode 100644 index 0000000000000..24033f0c2183e --- /dev/null +++ b/administrator/components/com_workflow/tmpl/graph/default.php @@ -0,0 +1,74 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * @since 6.1.0 + */ + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +use Joomla\CMS\Language\Text; + +/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ +$wa = $this->getDocument()->getWebAssetManager(); +$wa->useScript('joomla.dialog-autocreate') + ->useScript('com_workflow.workflowgraph') + ->useStyle('com_workflow.workflowgraph'); + +// Populate the language +$this->loadTemplate('texts'); + +$shortcuts = [ + ['key' => 'Alt + N', 'description' => Text::_('COM_WORKFLOW_GRAPH_ADD_STAGE')], + ['key' => 'Alt + M', 'description' => Text::_('COM_WORKFLOW_GRAPH_ADD_TRANSITION')], + ['key' => 'Enter / SpaceBar', 'description' => Text::_('COM_WORKFLOW_GRAPH_SELECT_ITEM')], + ['key' => 'Select + E', 'description' => Text::_('COM_WORKFLOW_GRAPH_EDIT_ITEM')], + ['key' => 'Select + Delete', 'description' => Text::_('COM_WORKFLOW_GRAPH_TRASH_ITEM')], + ['key' => 'Select + Backspace', 'description' => Text::_('COM_WORKFLOW_GRAPH_TRASH_ITEM')], + ['key' => 'Select + Shift + Arrows', 'description' => Text::_('COM_WORKFLOW_GRAPH_MOVE_STAGE')], + ['key' => 'Escape', 'description' => Text::_('COM_WORKFLOW_GRAPH_CLEAR_SELECTION')], + ['key' => '+ / =', 'description' => Text::_('COM_WORKFLOW_GRAPH_ZOOM_IN')], + ['key' => '- / _', 'description' => Text::_('COM_WORKFLOW_GRAPH_ZOOM_OUT')], + ['key' => 'F', 'description' => Text::_('COM_WORKFLOW_GRAPH_FIT_VIEW')], + ['key' => 'Tab', 'description' => Text::_('COM_WORKFLOW_GRAPH_FOCUS_TYPE_CHANGE')], + ['key' => 'Arrows', 'description' => Text::_('COM_WORKFLOW_GRAPH_NAVIGATE_NODES')], + ['key' => 'Shift + Arrows', 'description' => Text::_('COM_WORKFLOW_GRAPH_MOVE_VIEW')], +]; + +$col1 = \array_slice($shortcuts, 0, ceil(\count($shortcuts) / 2)); +$col2 = \array_slice($shortcuts, ceil(\count($shortcuts) / 2)); + +$shortcutsHtml = []; +$shortcutsHtml[] = '
'; +$shortcutsHtml[] = '
'; +$renderColumn = function ($column) { + $html = '
'; + $html .= ''; + $html .= '' . Text::_('COM_WORKFLOW_GRAPH_SHORTCUTS_TITLE') . ''; + foreach ($column as $item) { + $html .= ''; + $html .= ''; + $html .= ''; + $html .= ''; + } + $html .= '
' . htmlspecialchars($item['key']) . '' . $item['description'] . '
'; + return $html; +}; + +$shortcutsHtml[] = $renderColumn($col1); +$shortcutsHtml[] = $renderColumn($col2); + +$shortcutsHtml[] = '
'; +$shortcutsHtml[] = '
'; +?> + + +
diff --git a/administrator/components/com_workflow/tmpl/graph/default_texts.php b/administrator/components/com_workflow/tmpl/graph/default_texts.php new file mode 100644 index 0000000000000..6b5feef6ed435 --- /dev/null +++ b/administrator/components/com_workflow/tmpl/graph/default_texts.php @@ -0,0 +1,109 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + * @since 6.1.0 + */ + +use Joomla\CMS\Language\Text; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +// Populate the language +$translationStrings = [ + 'COM_WORKFLOW_GRAPH', + 'COM_WORKFLOW_GRAPH_ADD_STAGE', + 'COM_WORKFLOW_GRAPH_ADD_STAGE_DIALOG_OPENED', + 'COM_WORKFLOW_GRAPH_ADD_TRANSITION_DIALOG_OPENED', + 'COM_WORKFLOW_GRAPH_ADD_TRANSITION', + 'COM_WORKFLOW_GRAPH_API_NOT_SET', + 'COM_WORKFLOW_GRAPH_BACKGROUND', + 'COM_WORKFLOW_GRAPH_CANVAS_DESCRIPTION', + 'COM_WORKFLOW_GRAPH_CANVAS_LABEL', + 'COM_WORKFLOW_GRAPH_CANVAS_VIEW_CONTROLS', + 'COM_WORKFLOW_GRAPH_CLEAR_SELECTION', + 'COM_WORKFLOW_GRAPH_CLOSE_ACTIONS_MENU', + 'COM_WORKFLOW_GRAPH_CONTROLS', + 'COM_WORKFLOW_GRAPH_CREATING_TRANSITION', + 'COM_WORKFLOW_GRAPH_DEFAULT', + 'COM_WORKFLOW_GRAPH_DISABLED', + 'COM_WORKFLOW_GRAPH_EDIT_ITEM', + 'COM_WORKFLOW_GRAPH_EDIT_STAGE', + 'COM_WORKFLOW_GRAPH_EDIT_TRANSITION', + 'COM_WORKFLOW_GRAPH_ENABLED', + 'COM_WORKFLOW_GRAPH_ERROR_CSRF_TOKEN_NOT_SET', + 'COM_WORKFLOW_GRAPH_ERROR_EXTENSION_NOT_SET', + 'COM_WORKFLOW_GRAPH_ERROR_FAILED_TO_UPDATE_STAGE_POSITIONS', + 'COM_WORKFLOW_GRAPH_ERROR_FETCHING_MODEL', + 'COM_WORKFLOW_GRAPH_ERROR_INVALID_ID', + 'COM_WORKFLOW_GRAPH_ERROR_INVALID_POSITION_DATA', + 'COM_WORKFLOW_GRAPH_ERROR_INVALID_STAGE_POSITIONS', + 'COM_WORKFLOW_GRAPH_ERROR_STAGES_NOT_FOUND', + 'COM_WORKFLOW_GRAPH_ERROR_STAGE_DEFAULT_CANT_DELETED', + 'COM_WORKFLOW_GRAPH_ERROR_STAGE_HAS_TRANSITIONS', + 'COM_WORKFLOW_GRAPH_ERROR_UNKNOWN', + 'COM_WORKFLOW_GRAPH_ERROR_WORKFLOW_ID_NOT_SET', + 'COM_WORKFLOW_GRAPH_ERROR_WORKFLOW_NOT_FOUND', + 'COM_WORKFLOW_GRAPH_FIT_VIEW', + 'COM_WORKFLOW_GRAPH_FOCUS_TYPE_CHANGE', + 'COM_WORKFLOW_GRAPH_FROM_ANY', + 'COM_WORKFLOW_GRAPH_LOADING', + 'COM_WORKFLOW_GRAPH_MINIMAP_HIDE', + 'COM_WORKFLOW_GRAPH_MINIMAP_LABEL', + 'COM_WORKFLOW_GRAPH_MINIMAP_SHOW', + 'COM_WORKFLOW_GRAPH_MOVE_STAGE', + 'COM_WORKFLOW_GRAPH_MOVE_VIEW', + 'COM_WORKFLOW_GRAPH_NAVIGATE_NODES', + 'COM_WORKFLOW_GRAPH_OPEN_ACTIONS_MENU', + 'COM_WORKFLOW_GRAPH_SELECTION_CLEARED', + 'COM_WORKFLOW_GRAPH_SELECT_ITEM', + 'COM_WORKFLOW_GRAPH_SHORTCUTS', + 'COM_WORKFLOW_GRAPH_SHORTCUTS_TITLE', + 'COM_WORKFLOW_GRAPH_STAGE', + 'COM_WORKFLOW_GRAPH_STAGES', + 'COM_WORKFLOW_GRAPH_STAGE_ACTIONS', + 'COM_WORKFLOW_GRAPH_STAGE_COUNT', + 'COM_WORKFLOW_GRAPH_STAGE_DEFAULT', + 'COM_WORKFLOW_GRAPH_STAGE_DESCRIPTION', + 'COM_WORKFLOW_GRAPH_STAGE_POSITIONS_UPDATED', + 'COM_WORKFLOW_GRAPH_STAGE_REF', + 'COM_WORKFLOW_GRAPH_STAGE_SELECTED', + 'COM_WORKFLOW_GRAPH_STAGE_STATUS_ENABLED', + 'COM_WORKFLOW_GRAPH_STAGE_STATUS_DISABLED', + 'COM_WORKFLOW_GRAPH_STATUS', + 'COM_WORKFLOW_GRAPH_TRANSITION', + 'COM_WORKFLOW_GRAPH_TRANSITIONS', + 'COM_WORKFLOW_GRAPH_TRANSITION_ACTIONS', + 'COM_WORKFLOW_GRAPH_TRANSITION_COUNT', + 'COM_WORKFLOW_GRAPH_TRANSITION_DESCRIPTION', + 'COM_WORKFLOW_GRAPH_TRANSITION_PATH', + 'COM_WORKFLOW_GRAPH_TRANSITION_REF', + 'COM_WORKFLOW_GRAPH_TRANSITION_SELECTED', + 'COM_WORKFLOW_GRAPH_TRANSITION_STATUS_ENABLED', + 'COM_WORKFLOW_GRAPH_TRANSITION_STATUS_DISABLED', + 'COM_WORKFLOW_GRAPH_TRASH_ITEM', + 'COM_WORKFLOW_GRAPH_TRASH_STAGE', + 'COM_WORKFLOW_GRAPH_TRASH_STAGE_CONFIRM', + 'COM_WORKFLOW_GRAPH_TRASH_STAGE_FAILED', + 'COM_WORKFLOW_GRAPH_TRASH_TRANSITION', + 'COM_WORKFLOW_GRAPH_TRASH_TRANSITION_CONFIRM', + 'COM_WORKFLOW_GRAPH_TRASH_TRANSITION_FAILED', + 'COM_WORKFLOW_GRAPH_UNSAVED_CHANGES', + 'COM_WORKFLOW_GRAPH_UPDATE_STAGE_POSITION_FAILED', + 'COM_WORKFLOW_GRAPH_UP_TO_DATE', + 'COM_WORKFLOW_GRAPH_WORKFLOWS_EDIT', + 'COM_WORKFLOW_GRAPH_ZOOM_IN', + 'COM_WORKFLOW_GRAPH_ZOOM_OUT', + 'JNO', + 'JYES', +]; + +foreach ($translationStrings as $string) { + Text::script($string); +} diff --git a/administrator/components/com_workflow/tmpl/stage/edit.php b/administrator/components/com_workflow/tmpl/stage/edit.php index 37aaaf22b4dac..83eae9b3757a6 100644 --- a/administrator/components/com_workflow/tmpl/stage/edit.php +++ b/administrator/components/com_workflow/tmpl/stage/edit.php @@ -85,7 +85,7 @@ form->getInput('workflow_id'); ?> - - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_workflow/tmpl/stage/modal.php b/administrator/components/com_workflow/tmpl/stage/modal.php new file mode 100644 index 0000000000000..7159da0909b34 --- /dev/null +++ b/administrator/components/com_workflow/tmpl/stage/modal.php @@ -0,0 +1,21 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +/** @var \Joomla\Component\Workflow\Administrator\View\Stage\HtmlView $this */ +?> +
+ getDocument()->getToolbar('toolbar')->render(); ?> +
+
+ setLayout('edit'); ?> + loadTemplate(); ?> +
diff --git a/administrator/components/com_workflow/tmpl/stage/modalreturn.php b/administrator/components/com_workflow/tmpl/stage/modalreturn.php new file mode 100644 index 0000000000000..ee959b6796ba2 --- /dev/null +++ b/administrator/components/com_workflow/tmpl/stage/modalreturn.php @@ -0,0 +1,43 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +$item = $this->get('Item'); + +$icon = 'icon-check'; +$title = $item ? $item->title : ''; +$content = ''; +$data = ['contentType' => 'com_workflow.stage']; + +if ($item) { + $data['id'] = $item->id; + $data['title'] = $item->title; + $data['workflow'] = $item->workflow_id ?? ''; +} + +// Add Content select script +/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ +$wa = $this->getDocument()->getWebAssetManager(); +$wa->useScript('modal-content-select'); + +// The data for Content select script +$this->getDocument()->addScriptOptions('content-select-on-load', $data, false); +?> + +
+ +

escape($title); ?>

+
+

+ +

+
+
diff --git a/administrator/components/com_workflow/tmpl/stages/default.php b/administrator/components/com_workflow/tmpl/stages/default.php index c9a053226c9b1..22ba1d112bf35 100644 --- a/administrator/components/com_workflow/tmpl/stages/default.php +++ b/administrator/components/com_workflow/tmpl/stages/default.php @@ -149,11 +149,8 @@ pagination->getListFooter(); ?> - - - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_workflow/tmpl/transition/edit.php b/administrator/components/com_workflow/tmpl/transition/edit.php index 27e39dfb63392..e6894ba30c9f1 100644 --- a/administrator/components/com_workflow/tmpl/transition/edit.php +++ b/administrator/components/com_workflow/tmpl/transition/edit.php @@ -44,6 +44,16 @@
+ getInput()->get('from_stage_id'); + $toStage = $app->getInput()->get('to_stage_id'); + if ($fromStage && $toStage) { + $this->form->setFieldAttribute('from_stage_id', 'default', $fromStage); + $this->form->setFieldAttribute('to_stage_id', 'default', $toStage); + } + } + ?> form->renderField('from_stage_id'); ?> form->renderField('to_stage_id'); ?> form->renderField('description'); ?> @@ -68,6 +78,6 @@
form->getInput('workflow_id'); ?> - - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_workflow/tmpl/transition/modal.php b/administrator/components/com_workflow/tmpl/transition/modal.php new file mode 100644 index 0000000000000..a30f0b983281b --- /dev/null +++ b/administrator/components/com_workflow/tmpl/transition/modal.php @@ -0,0 +1,23 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** @var \Joomla\Component\Workflow\Administrator\View\Transition\HtmlView $this */ +?> +
+ getDocument()->getToolbar('toolbar')->render(); ?> +
+
+ setLayout('edit'); ?> + loadTemplate(); ?> +
diff --git a/administrator/components/com_workflow/tmpl/transition/modalreturn.php b/administrator/components/com_workflow/tmpl/transition/modalreturn.php new file mode 100644 index 0000000000000..253ccca36d24c --- /dev/null +++ b/administrator/components/com_workflow/tmpl/transition/modalreturn.php @@ -0,0 +1,43 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +$item = $this->get('Item'); + +$icon = 'icon-check'; +$title = $item ? $item->title : ''; +$content = ''; +$data = ['contentType' => 'com_workflow.transition']; + +if ($item) { + $data['id'] = $item->id; + $data['title'] = $item->title; + $data['workflow'] = $item->workflow_id ?? ''; +} + +// Add Content select script +/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ +$wa = $this->getDocument()->getWebAssetManager(); +$wa->useScript('modal-content-select'); + +// The data for Content select script +$this->getDocument()->addScriptOptions('content-select-on-load', $data, false); +?> + +
+ +

escape($title); ?>

+
+

+ +

+
+
diff --git a/administrator/components/com_workflow/tmpl/transitions/default.php b/administrator/components/com_workflow/tmpl/transitions/default.php index 4f5967a2e040a..c416ff7e2acfc 100644 --- a/administrator/components/com_workflow/tmpl/transitions/default.php +++ b/administrator/components/com_workflow/tmpl/transitions/default.php @@ -156,11 +156,8 @@ pagination->getListFooter(); ?> - - - - - + + filterForm->renderControlFields(); ?>
diff --git a/administrator/components/com_workflow/tmpl/workflow/edit.php b/administrator/components/com_workflow/tmpl/workflow/edit.php index 5ba15fef7dd43..8c0e2a8ae1d0a 100644 --- a/administrator/components/com_workflow/tmpl/workflow/edit.php +++ b/administrator/components/com_workflow/tmpl/workflow/edit.php @@ -87,6 +87,6 @@ form->getInput('extension'); ?> - - + + form->renderControlFields(); ?> diff --git a/administrator/components/com_workflow/tmpl/workflows/default.php b/administrator/components/com_workflow/tmpl/workflows/default.php index 6409e3e6e1e5e..4aef59dca7797 100644 --- a/administrator/components/com_workflow/tmpl/workflows/default.php +++ b/administrator/components/com_workflow/tmpl/workflows/default.php @@ -98,7 +98,10 @@ - + + + + @@ -110,6 +113,7 @@ $states = Route::_('index.php?option=com_workflow&view=stages&workflow_id=' . $item->id . '&extension=' . $extension); $transitions = Route::_('index.php?option=com_workflow&view=transitions&workflow_id=' . $item->id . '&extension=' . $extension); $edit = Route::_('index.php?option=com_workflow&task=workflow.edit&id=' . $item->id . '&extension=' . $extension); + $graph = Route::_('index.php?option=com_workflow&view=graph&id=' . $item->id . '&extension=' . $extension); $canEdit = $user->authorise('core.edit', $extension . '.workflow.' . $item->id); $canCheckin = $user->authorise('core.admin', 'com_workflow') || $item->checked_out == $userId || is_null($item->checked_out); @@ -174,19 +178,27 @@ - + + + + + + + id; ?> + pagination->getListFooter(); ?> - - - + + filterForm->renderControlFields(); ?> diff --git a/administrator/components/com_workflow/workflow.xml b/administrator/components/com_workflow/workflow.xml index eab5374c25ca8..b4f782472383f 100644 --- a/administrator/components/com_workflow/workflow.xml +++ b/administrator/components/com_workflow/workflow.xml @@ -15,6 +15,8 @@ workflow.xml forms + layouts + resources services src tmpl diff --git a/administrator/help/en-GB/toc.json b/administrator/help/en-GB/toc.json deleted file mode 100644 index 5af8c2abd5c5b..0000000000000 --- a/administrator/help/en-GB/toc.json +++ /dev/null @@ -1 +0,0 @@ -{"Articles":"ARTICLES","Articles:_Categories":"ARTICLES:_CATEGORIES","Articles:_Edit":"ARTICLES:_EDIT","Articles:_Edit_Category":"ARTICLES:_EDIT_CATEGORY","Articles:_Featured":"ARTICLES:_FEATURED","Banners":"BANNERS","Banners:_Categories":"BANNERS:_CATEGORIES","Banners:_Clients":"BANNERS:_CLIENTS","Banners:_Edit":"BANNERS:_EDIT","Banners:_New_or_Edit_Category":"BANNERS:_NEW_OR_EDIT_CATEGORY","Banners:_New_or_Edit_Client":"BANNERS:_NEW_OR_EDIT_CLIENT","Banners:_Tracks":"BANNERS:_TRACKS","Contacts":"CONTACTS","Contacts:_Categories":"CONTACTS:_CATEGORIES","Contacts:_Edit":"CONTACTS:_EDIT","Contacts:_Edit_Category":"CONTACTS:_EDIT_CATEGORY","Admin_Modules:_Action_Logs_-_Latest":"ADMIN_MODULES:_ACTION_LOGS_-_LATEST","Admin_Modules:_Administrator_Dashboard_Menu":"ADMIN_MODULES:_ADMINISTRATOR_DASHBOARD_MENU","Admin_Modules:_Administrator_Menu":"ADMIN_MODULES:_ADMINISTRATOR_MENU","Admin_Modules:_Articles_-_Latest":"ADMIN_MODULES:_ARTICLES_-_LATEST","Admin_Modules:_Custom":"ADMIN_MODULES:_CUSTOM","Admin_Modules:_Feed_Display":"ADMIN_MODULES:_FEED_DISPLAY","Admin_Modules:_Frontend_Link":"ADMIN_MODULES:_FRONTEND_LINK","Admin_Modules:_Guided_Tours":"ADMIN_MODULES:_GUIDED_TOURS","Admin_Modules:_Joomla_Version_Information":"ADMIN_MODULES:_JOOMLA_VERSION_INFORMATION","Admin_Modules:_Login_Form":"ADMIN_MODULES:_LOGIN_FORM","Admin_Modules:_Login_Support_Information":"ADMIN_MODULES:_LOGIN_SUPPORT_INFORMATION","Admin_Modules:_Messages":"ADMIN_MODULES:_MESSAGES","Admin_Modules:_Multilingual_Status":"ADMIN_MODULES:_MULTILINGUAL_STATUS","Admin_Modules:_Popular_Articles":"ADMIN_MODULES:_POPULAR_ARTICLES","Admin_Modules:_Post_Installation_Messages":"ADMIN_MODULES:_POST_INSTALLATION_MESSAGES","Admin_Modules:_Privacy_Dashboard":"ADMIN_MODULES:_PRIVACY_DASHBOARD","Admin_Modules:_Privacy_Status_Check":"ADMIN_MODULES:_PRIVACY_STATUS_CHECK","Admin_Modules:_Quick_Icons":"ADMIN_MODULES:_QUICK_ICONS","Admin_Modules:_Sample_Data":"ADMIN_MODULES:_SAMPLE_DATA","Admin_Modules:_Title":"ADMIN_MODULES:_TITLE","Admin_Modules:_Toolbar":"ADMIN_MODULES:_TOOLBAR","Articles:_Options":"ARTICLES:_OPTIONS","Banners:_Options":"BANNERS:_OPTIONS","Cache:_Options":"CACHE:_OPTIONS","Check-in:_Options":"CHECK-IN:_OPTIONS","Contacts:_Options":"CONTACTS:_OPTIONS","Edit_Update_Site":"EDIT_UPDATE_SITE","Editors":"EDITORS","Extensions:_Discover":"EXTENSIONS:_DISCOVER","Extensions:_Install":"EXTENSIONS:_INSTALL","Extensions:_Languages":"EXTENSIONS:_LANGUAGES","Extensions:_Manage":"EXTENSIONS:_MANAGE","Extensions:_Update":"EXTENSIONS:_UPDATE","Extensions:_Update_Sites":"EXTENSIONS:_UPDATE_SITES","Field_Groups":"FIELD_GROUPS","Field_Groups:_Edit":"FIELD_GROUPS:_EDIT","Fields":"FIELDS","Fields:_Edit":"FIELDS:_EDIT","Guided_Tours":"GUIDED_TOURS","Guided_Tours:_New_or_Edit_Step":"GUIDED_TOURS:_NEW_OR_EDIT_STEP","Guided_Tours:_New_or_Edit_Tour":"GUIDED_TOURS:_NEW_OR_EDIT_TOUR","Guided_Tours:_Options":"GUIDED_TOURS:_OPTIONS","Guided_Tours:_Steps":"GUIDED_TOURS:_STEPS","Home_Dashboard":"HOME_DASHBOARD","Information:_Database":"INFORMATION:_DATABASE","Information:_Warnings":"INFORMATION:_WARNINGS","Installer:_Options":"INSTALLER:_OPTIONS","Joomla_Update":"JOOMLA_UPDATE","Joomla_Update:_Options":"JOOMLA_UPDATE:_OPTIONS","Languages:_Content":"LANGUAGES:_CONTENT","Languages:_Edit_Content_Language":"LANGUAGES:_EDIT_CONTENT_LANGUAGE","Languages:_Edit_Override":"LANGUAGES:_EDIT_OVERRIDE","Languages:_Installed":"LANGUAGES:_INSTALLED","Languages:_Options":"LANGUAGES:_OPTIONS","Languages:_Overrides":"LANGUAGES:_OVERRIDES","Mail_Template:_Edit":"MAIL_TEMPLATE:_EDIT","Mail_Templates":"MAIL_TEMPLATES","Mail_Templates:_Options":"MAIL_TEMPLATES:_OPTIONS","Maintenance:_Clear_Cache":"MAINTENANCE:_CLEAR_CACHE","Maintenance:_Global_Check-in":"MAINTENANCE:_GLOBAL_CHECK-IN","Mass_Mail_Users":"MASS_MAIL_USERS","Media":"MEDIA","Media:_Options":"MEDIA:_OPTIONS","Menu_Item:_Alias":"MENU_ITEM:_ALIAS","Menu_Item:_Article_Archived":"MENU_ITEM:_ARTICLE_ARCHIVED","Menu_Item:_Compact_List_of_Tagged_Items":"MENU_ITEM:_COMPACT_LIST_OF_TAGGED_ITEMS","Menu_Item:_Components_Menu_Container":"MENU_ITEM:_COMPONENTS_MENU_CONTAINER","Menu_Item:_Confirm_Request":"MENU_ITEM:_CONFIRM_REQUEST","Menu_Item:_Create_Article":"MENU_ITEM:_CREATE_ARTICLE","Menu_Item:_Create_Contact":"MENU_ITEM:_CREATE_CONTACT","Menu_Item:_Create_Request":"MENU_ITEM:_CREATE_REQUEST","Menu_Item:_Display_Template_Options":"MENU_ITEM:_DISPLAY_TEMPLATE_OPTIONS","Menu_Item:_Extend_Consent":"MENU_ITEM:_EXTEND_CONSENT","Menu_Item:_Featured_Articles":"MENU_ITEM:_FEATURED_ARTICLES","Menu_Item:_Featured_Contacts":"MENU_ITEM:_FEATURED_CONTACTS","Menu_Item:_Heading":"MENU_ITEM:_HEADING","Menu_Item:_Iframe_Wrapper":"MENU_ITEM:_IFRAME_WRAPPER","Menu_Item:_List_All_Tags":"MENU_ITEM:_LIST_ALL_TAGS","Menu_Item:_Login_Form":"MENU_ITEM:_LOGIN_FORM","Menu_Item:_Logout":"MENU_ITEM:_LOGOUT","Menu_Item:_New_Item":"MENU_ITEM:_NEW_ITEM","Menu_Item:_Password_Reset":"MENU_ITEM:_PASSWORD_RESET","Menu_Item:_Registration_Form":"MENU_ITEM:_REGISTRATION_FORM","Menu_Item:_Search":"MENU_ITEM:_SEARCH","Menu_Item:_Separator":"MENU_ITEM:_SEPARATOR","Menu_Item:_Single_Article":"MENU_ITEM:_SINGLE_ARTICLE","Menu_Item:_Single_Contact":"MENU_ITEM:_SINGLE_CONTACT","Menu_Item:_Single_News_Feed":"MENU_ITEM:_SINGLE_NEWS_FEED","Menu_Item:_Site_Configuration_Options":"MENU_ITEM:_SITE_CONFIGURATION_OPTIONS","Menu_Item:_Tagged_Items":"MENU_ITEM:_TAGGED_ITEMS","Menu_Item:_URL":"MENU_ITEM:_URL","Menus":"MENUS","Menus:_Edit":"MENUS:_EDIT","Menus:_Items":"MENUS:_ITEMS","Menus:_Options":"MENUS:_OPTIONS","Messages:_Options":"MESSAGES:_OPTIONS","Modules":"MODULES","Modules:_Options":"MODULES:_OPTIONS","Multilingual_Associations":"MULTILINGUAL_ASSOCIATIONS","Multilingual_Associations:_Edit":"MULTILINGUAL_ASSOCIATIONS:_EDIT","Multilingual_Associations:_Options":"MULTILINGUAL_ASSOCIATIONS:_OPTIONS","My_Profile":"MY_PROFILE","News_Feed:_Options":"NEWS_FEED:_OPTIONS","News_Feeds":"NEWS_FEEDS","News_Feeds:_Categories":"NEWS_FEEDS:_CATEGORIES","News_Feeds:_Edit":"NEWS_FEEDS:_EDIT","News_Feeds:_Edit_Category":"NEWS_FEEDS:_EDIT_CATEGORY","Permissions_for_Group":"PERMISSIONS_FOR_GROUP","Permissions_for_User":"PERMISSIONS_FOR_USER","Plugin:_Options":"PLUGIN:_OPTIONS","Plugins":"PLUGINS","Plugins:_Name_of_Plugin":"PLUGINS:_NAME_OF_PLUGIN","Post-installation_Messages_for_Joomla_CMS":"POST-INSTALLATION_MESSAGES_FOR_JOOMLA_CMS","Post-installation_Messages:_Options":"POST-INSTALLATION_MESSAGES:_OPTIONS","Privacy_Dashboard":"PRIVACY_DASHBOARD","Privacy:_Consents":"PRIVACY:_CONSENTS","Privacy:_Extension_Capabilities":"PRIVACY:_EXTENSION_CAPABILITIES","Privacy:_Information_Requests":"PRIVACY:_INFORMATION_REQUESTS","Privacy:_New_Information_Request":"PRIVACY:_NEW_INFORMATION_REQUEST","Privacy:_Options":"PRIVACY:_OPTIONS","Privacy:_Review_Information_Request":"PRIVACY:_REVIEW_INFORMATION_REQUEST","Private_Messages":"PRIVATE_MESSAGES","Private_Messages:_Read":"PRIVATE_MESSAGES:_READ","Private_Messages:_Write":"PRIVATE_MESSAGES:_WRITE","Redirect:_Options":"REDIRECT:_OPTIONS","Redirects:_Links":"REDIRECTS:_LINKS","Redirects:_New_or_Edit":"REDIRECTS:_NEW_OR_EDIT","Scheduled_Tasks":"SCHEDULED_TASKS","Scheduled_Tasks:_Edit":"SCHEDULED_TASKS:_EDIT","Scheduled_Tasks:_Options":"SCHEDULED_TASKS:_OPTIONS","Site_Global_Configuration":"SITE_GLOBAL_CONFIGURATION","Site_Modules:_Articles":"SITE_MODULES:_ARTICLES","Site_Modules:_Articles_-_Archived":"SITE_MODULES:_ARTICLES_-_ARCHIVED","Site_Modules:_Articles_-_Latest":"SITE_MODULES:_ARTICLES_-_LATEST","Site_Modules:_Articles_-_Most_Read":"SITE_MODULES:_ARTICLES_-_MOST_READ","Site_Modules:_Articles_-_Newsflash":"SITE_MODULES:_ARTICLES_-_NEWSFLASH","Site_Modules:_Articles_-_Related":"SITE_MODULES:_ARTICLES_-_RELATED","Site_Modules:_Banners":"SITE_MODULES:_BANNERS","Site_Modules:_Breadcrumbs":"SITE_MODULES:_BREADCRUMBS","Site_Modules:_Custom":"SITE_MODULES:_CUSTOM","Site_Modules:_Feed_Display":"SITE_MODULES:_FEED_DISPLAY","Site_Modules:_Footer":"SITE_MODULES:_FOOTER","Site_Modules:_Language_Switcher":"SITE_MODULES:_LANGUAGE_SWITCHER","Site_Modules:_Login":"SITE_MODULES:_LOGIN","Site_Modules:_Menu":"SITE_MODULES:_MENU","Site_Modules:_Random_Image":"SITE_MODULES:_RANDOM_IMAGE","Site_Modules:_Smart_Search":"SITE_MODULES:_SMART_SEARCH","Site_Modules:_Statistics":"SITE_MODULES:_STATISTICS","Site_Modules:_Syndication_Feeds":"SITE_MODULES:_SYNDICATION_FEEDS","Site_Modules:_Tags_-_Popular":"SITE_MODULES:_TAGS_-_POPULAR","Site_Modules:_Tags_-_Similar":"SITE_MODULES:_TAGS_-_SIMILAR","Site_Modules:_Wrapper":"SITE_MODULES:_WRAPPER","Site_System_Information":"SITE_SYSTEM_INFORMATION","Smart_Search:_Content_Maps":"SMART_SEARCH:_CONTENT_MAPS","Smart_Search:_Indexed_Content":"SMART_SEARCH:_INDEXED_CONTENT","Smart_Search:_New_or_Edit_Filter":"SMART_SEARCH:_NEW_OR_EDIT_FILTER","Smart_Search:_Options":"SMART_SEARCH:_OPTIONS","Smart_Search:_Search_Filters":"SMART_SEARCH:_SEARCH_FILTERS","Smart_Search:_Search_Term_Analysis":"SMART_SEARCH:_SEARCH_TERM_ANALYSIS","Stages_List:_Basic_Workflow":"STAGES_LIST:_BASIC_WORKFLOW","Start_Here":"START_HERE","Tags":"TAGS","Tags:_New_or_Edit":"TAGS:_NEW_OR_EDIT","Tags:_Options":"TAGS:_OPTIONS","Template:_Options":"TEMPLATE:_OPTIONS","Templates:_Customise":"TEMPLATES:_CUSTOMISE","Templates:_Customise_Source":"TEMPLATES:_CUSTOMISE_SOURCE","Templates:_Edit_Style":"TEMPLATES:_EDIT_STYLE","Templates:_Styles":"TEMPLATES:_STYLES","Templates:_Templates":"TEMPLATES:_TEMPLATES","Transitions_List:_Basic_Workflow":"TRANSITIONS_LIST:_BASIC_WORKFLOW","User_Actions_Log":"USER_ACTIONS_LOG","User_Actions_Log:_Options":"USER_ACTIONS_LOG:_OPTIONS","User_Notes":"USER_NOTES","User_Notes:_New_or_Edit":"USER_NOTES:_NEW_OR_EDIT","Users":"USERS","Users:_Edit_Profile":"USERS:_EDIT_PROFILE","Users:_Edit_Viewing_Access_Level":"USERS:_EDIT_VIEWING_ACCESS_LEVEL","Users:_Groups":"USERS:_GROUPS","Users:_New_or_Edit_Group":"USERS:_NEW_OR_EDIT_GROUP","Users:_Options":"USERS:_OPTIONS","Users:_Viewing_Access_Levels":"USERS:_VIEWING_ACCESS_LEVELS","Workflows_List":"WORKFLOWS_LIST"} diff --git a/administrator/includes/framework.php b/administrator/includes/framework.php index e24951cdfeae1..48f307125ad40 100644 --- a/administrator/includes/framework.php +++ b/administrator/includes/framework.php @@ -9,6 +9,7 @@ \defined('_JEXEC') or die; +use Joomla\CMS\Exception\ExceptionHandler; use Joomla\CMS\Version; use Joomla\Utilities\IpHelper; @@ -85,7 +86,7 @@ set_error_handler(null, E_USER_DEPRECATED); } else { // Make sure handler for E_USER_DEPRECATED is registered - set_error_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleUserDeprecatedErrors'], E_USER_DEPRECATED); + set_error_handler([ExceptionHandler::class, 'handleUserDeprecatedErrors'], E_USER_DEPRECATED); } if (JDEBUG || $config->error_reporting === 'maximum') { diff --git a/administrator/index.php b/administrator/index.php index 480d1fce34f93..50e10b63f495a 100644 --- a/administrator/index.php +++ b/administrator/index.php @@ -10,7 +10,7 @@ // NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message // Define the application's minimum supported PHP version as a constant so it can be referenced within the application. -\define('JOOMLA_MINIMUM_PHP', '8.1.0'); +\define('JOOMLA_MINIMUM_PHP', '8.3.0'); if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<')) { die( diff --git a/administrator/language/en-GB/com_actionlogs.ini b/administrator/language/en-GB/com_actionlogs.ini index d7e71dc5098e8..3abd2f2d8e7fa 100644 --- a/administrator/language/en-GB/com_actionlogs.ini +++ b/administrator/language/en-GB/com_actionlogs.ini @@ -58,7 +58,7 @@ COM_ACTIONLOGS_OPTION_RANGE_PAST_YEAR="In the last year" COM_ACTIONLOGS_OPTION_RANGE_POST_YEAR="More than a year ago" COM_ACTIONLOGS_OPTION_RANGE_TODAY="Today" COM_ACTIONLOGS_OPTIONS="Options" -COM_ACTIONLOGS_POSTINSTALL_BODY="

With the release of Joomla 3.9.0 you can now log all administrative actions performed by your users in supported extensions. It is now easy to see who did what and when they did it.

The logs can be reviewed in Joomla or exported for external use.

For further information on this new feature read the User Action Logs documentation.

" +COM_ACTIONLOGS_POSTINSTALL_BODY="

With the release of Joomla 3.9.0 you can now log all administrative actions performed by your users in supported extensions. It is now easy to see who did what and when they did it.

The logs can be reviewed in Joomla or exported for external use.

For further information on this new feature read the User Action Logs documentation.

" COM_ACTIONLOGS_POSTINSTALL_TITLE="User Actions Can Now Be Logged" COM_ACTIONLOGS_PURGE_CONFIRM="Are you sure want to delete all User Action logs?" COM_ACTIONLOGS_PURGE_FAIL="Failed to delete all User Action logs." diff --git a/administrator/language/en-GB/com_admin.ini b/administrator/language/en-GB/com_admin.ini index 450ecdeb052ae..7f0247def2b2e 100644 --- a/administrator/language/en-GB/com_admin.ini +++ b/administrator/language/en-GB/com_admin.ini @@ -24,6 +24,7 @@ COM_ADMIN_EXTENSIONS="Extensions" COM_ADMIN_FILE_UPLOADS="File Uploads" COM_ADMIN_GLOSSARY="Glossary" COM_ADMIN_HELP="Joomla! Help" +COM_ADMIN_HELP_ADMIN_MODULES="Administrator Modules" COM_ADMIN_HELP_ADMIN_MODULES:_ACTION_LOGS_-_LATEST="Admin Modules: Action Logs - Latest" COM_ADMIN_HELP_ADMIN_MODULES:_ADMINISTRATOR_DASHBOARD_MENU="Admin Modules: Administrator Dashboard Menu" COM_ADMIN_HELP_ADMIN_MODULES:_ADMINISTRATOR_MENU="Admin Modules: Administrator Menu" @@ -61,13 +62,16 @@ COM_ADMIN_HELP_BANNERS:_TRACKS="Banners: Tracks" COM_ADMIN_HELP_BANNERS="Banners" COM_ADMIN_HELP_CACHE:_OPTIONS="Cache: Options" COM_ADMIN_HELP_CHECK-IN:_OPTIONS="Check-in: Options" +COM_ADMIN_HELP_COMPONENTS="Components" COM_ADMIN_HELP_CONTACTS:_CATEGORIES="Contacts: Categories" COM_ADMIN_HELP_CONTACTS:_EDIT_CATEGORY="Contacts: Categories - New/Edit" COM_ADMIN_HELP_CONTACTS:_EDIT="Contacts: New/Edit" COM_ADMIN_HELP_CONTACTS:_OPTIONS="Contacts: Options" COM_ADMIN_HELP_CONTACTS="Contacts" +COM_ADMIN_HELP_CONTENT="Content" COM_ADMIN_HELP_EDIT_UPDATE_SITE="Edit Update Site" COM_ADMIN_HELP_EDITORS="Editors" +COM_ADMIN_HELP_EXTENSIONS="Extensions" COM_ADMIN_HELP_EXTENSIONS:_DISCOVER="Extensions: Discover" COM_ADMIN_HELP_EXTENSIONS:_INSTALL="Extensions: Install" COM_ADMIN_HELP_EXTENSIONS:_LANGUAGES="Extensions: Install Languages" @@ -78,6 +82,7 @@ COM_ADMIN_HELP_FIELD_GROUPS:_EDIT="Field Groups: New/Edit" COM_ADMIN_HELP_FIELD_GROUPS="Field Groups" COM_ADMIN_HELP_FIELDS:_EDIT="Fields: New/Edit" COM_ADMIN_HELP_FIELDS="Fields" +COM_ADMIN_HELP_FRAME_TITLE="Selected Help Page" COM_ADMIN_HELP_GLOSSARY="Glossary" COM_ADMIN_HELP_GUIDED_TOURS:_NEW_OR_EDIT_STEP="Guided Tours: New/Edit Step" COM_ADMIN_HELP_GUIDED_TOURS:_NEW_OR_EDIT_TOUR="Guided Tours: New/Edit Tour" @@ -85,25 +90,31 @@ COM_ADMIN_HELP_GUIDED_TOURS:_OPTIONS="Guided Tours: Options" COM_ADMIN_HELP_GUIDED_TOURS:_STEPS="Guided Tours: Steps" COM_ADMIN_HELP_GUIDED_TOURS="Guided Tours" COM_ADMIN_HELP_HOME_DASHBOARD="Home Dashboard" +COM_ADMIN_HELP_INDEX="Index of Help Pages" +COM_ADMIN_HELP_INFORMATION="Information" COM_ADMIN_HELP_INFORMATION:_DATABASE="Extensions: Check Database" COM_ADMIN_HELP_INFORMATION:_WARNINGS="Extensions: Warnings" COM_ADMIN_HELP_INSTALLER:_OPTIONS="Installer: Options" COM_ADMIN_HELP_JOOMLA_UPDATE:_OPTIONS="Joomla Update: Options" COM_ADMIN_HELP_JOOMLA_UPDATE="Joomla Update" +COM_ADMIN_HELP_LANGUAGES="Languages" COM_ADMIN_HELP_LANGUAGES:_CONTENT="Languages: Content" COM_ADMIN_HELP_LANGUAGES:_EDIT_CONTENT_LANGUAGE="Languages: New/Edit" COM_ADMIN_HELP_LANGUAGES:_EDIT_OVERRIDE="Languages: Overrides - New/Edit" COM_ADMIN_HELP_LANGUAGES:_INSTALLED="Languages: Installed" COM_ADMIN_HELP_LANGUAGES:_OPTIONS="Languages: Options" COM_ADMIN_HELP_LANGUAGES:_OVERRIDES="Languages: Overrides" +COM_ADMIN_HELP_LICENSE="License" COM_ADMIN_HELP_MAIL_TEMPLATE:_EDIT="Mail Templates: Edit" COM_ADMIN_HELP_MAIL_TEMPLATES:_OPTIONS="Mail Templates: Options" COM_ADMIN_HELP_MAIL_TEMPLATES="Mail Templates" +COM_ADMIN_HELP_MAINTENANCE="Maintenance" COM_ADMIN_HELP_MAINTENANCE:_CLEAR_CACHE="Cache: Clear Cache" COM_ADMIN_HELP_MAINTENANCE:_GLOBAL_CHECK-IN="Global Check-in" COM_ADMIN_HELP_MASS_MAIL_USERS="Mass Mail Users" COM_ADMIN_HELP_MEDIA:_OPTIONS="Media: Options" COM_ADMIN_HELP_MEDIA="Media" +COM_ADMIN_HELP_MENU_ITEMS="Menu Items" COM_ADMIN_HELP_MENU_ITEM:_ALIAS="Menu Item: Alias" COM_ADMIN_HELP_MENU_ITEM:_ARTICLE_ARCHIVED="Menu Item: Article Archived" COM_ADMIN_HELP_MENU_ITEM:_COMPACT_LIST_OF_TAGGED_ITEMS="Menu Item: Compact List of Tagged Items" @@ -142,6 +153,7 @@ COM_ADMIN_HELP_MODULES="Modules" COM_ADMIN_HELP_MULTILINGUAL_ASSOCIATIONS:_EDIT="Multilingual Associations: Select" COM_ADMIN_HELP_MULTILINGUAL_ASSOCIATIONS:_OPTIONS="Multilingual Associations: Options" COM_ADMIN_HELP_MULTILINGUAL_ASSOCIATIONS="Multilingual Associations" +; Deprecated, will be removed with 7.0 COM_ADMIN_HELP_MY_PROFILE="My Profile" COM_ADMIN_HELP_NEWS_FEEDS:_CATEGORIES="News Feeds: Categories" COM_ADMIN_HELP_NEWS_FEEDS:_EDIT_CATEGORY="News Feeds: Categories - New/Edit" @@ -155,6 +167,7 @@ COM_ADMIN_HELP_PLUGIN:_OPTIONS="Plugin: Options" COM_ADMIN_HELP_PLUGINS="Plugins" COM_ADMIN_HELP_POST-INSTALLATION_MESSAGES:_OPTIONS="Post-installation Messages: Options" COM_ADMIN_HELP_POST-INSTALLATION_MESSAGES_FOR_JOOMLA_CMS="Post-Installation Messages" +COM_ADMIN_HELP_PRIVACY="Privacy" COM_ADMIN_HELP_PRIVACY:_CONSENTS="Privacy: Consents" COM_ADMIN_HELP_PRIVACY:_EXTENSION_CAPABILITIES="Privacy: Extension Capabilities" COM_ADMIN_HELP_PRIVACY:_INFORMATION_REQUESTS="Privacy: Information Requests" @@ -165,6 +178,7 @@ COM_ADMIN_HELP_PRIVACY_DASHBOARD="Privacy: Dashboard" COM_ADMIN_HELP_PRIVATE_MESSAGES:_READ="Private Messages: Read" COM_ADMIN_HELP_PRIVATE_MESSAGES:_WRITE="Private Messages: Write" COM_ADMIN_HELP_PRIVATE_MESSAGES="Private Messages: Inbox" +COM_ADMIN_HELP_REDIRECTS="Redirects" COM_ADMIN_HELP_REDIRECTS:_LINKS="Redirect: Links" COM_ADMIN_HELP_REDIRECTS:_NEW_OR_EDIT="Redirect: Links - New/Edit" COM_ADMIN_HELP_REDIRECT:_OPTIONS="Redirect: Options" @@ -172,6 +186,7 @@ COM_ADMIN_HELP_SCHEDULED_TASKS="Scheduled Tasks" COM_ADMIN_HELP_SCHEDULED_TASKS:_EDIT="Scheduled Tasks: New/Edit" COM_ADMIN_HELP_SCHEDULED_TASKS:_OPTIONS="Scheduled Tasks: Options" COM_ADMIN_HELP_SITE_GLOBAL_CONFIGURATION="Global Configuration" +COM_ADMIN_HELP_SITE_MODULES="Site Modules" COM_ADMIN_HELP_SITE_MODULES:_ARTICLES="Site Modules: Articles" COM_ADMIN_HELP_SITE_MODULES:_ARTICLES_-_ARCHIVED="Site Modules: Articles - Archived" COM_ADMIN_HELP_SITE_MODULES:_ARTICLES_-_LATEST="Site Modules: Articles - Latest" @@ -195,6 +210,7 @@ COM_ADMIN_HELP_SITE_MODULES:_TAGS_-_SIMILAR="Site Modules: Tags - Similar" COM_ADMIN_HELP_SITE_MODULES:_WHO_IS_ONLINE="Site Modules: Who's Online" COM_ADMIN_HELP_SITE_MODULES:_WRAPPER="Site Modules: Wrapper" COM_ADMIN_HELP_SITE_SYSTEM_INFORMATION="System Information" +COM_ADMIN_HELP_SMART_SEARCH="Smart Search" COM_ADMIN_HELP_SMART_SEARCH:_CONTENT_MAPS="Smart Search: Content Maps" COM_ADMIN_HELP_SMART_SEARCH:_INDEXED_CONTENT="Smart Search: Indexed Content" COM_ADMIN_HELP_SMART_SEARCH:_NEW_OR_EDIT_FILTER="Smart Search: Filters - New/Edit" @@ -203,16 +219,19 @@ COM_ADMIN_HELP_SMART_SEARCH:_OPTIONS="Smart Search: Options" COM_ADMIN_HELP_SMART_SEARCH:_SEARCH_TERM_ANALYSIS="Smart Search: Search Term Analysis" COM_ADMIN_HELP_STAGES_LIST:_BASIC_WORKFLOW="Stages List: Basic Workflow" COM_ADMIN_HELP_START_HERE="Start Here" +COM_ADMIN_HELP_SYSTEM="System" COM_ADMIN_HELP_TAGS:_NEW_OR_EDIT="Tags: New/Edit" COM_ADMIN_HELP_TAGS:_OPTIONS="Tags: Options" COM_ADMIN_HELP_TAGS="Tags" COM_ADMIN_HELP_TEMPLATE:_OPTIONS="Template: Options" +COM_ADMIN_HELP_TEMPLATES="Templates" COM_ADMIN_HELP_TEMPLATES:_CUSTOMISE_SOURCE="Templates: Source - Edit" COM_ADMIN_HELP_TEMPLATES:_CUSTOMISE="Templates: Edit" COM_ADMIN_HELP_TEMPLATES:_EDIT_STYLE="Templates: Styles - Edit" COM_ADMIN_HELP_TEMPLATES:_STYLES="Templates: Styles" COM_ADMIN_HELP_TEMPLATES:_TEMPLATES="Templates" COM_ADMIN_HELP_TRANSITIONS_LIST:_BASIC_WORKFLOW="Transitions List: Basic Workflow" +COM_ADMIN_HELP_USER_ACTIONS="User Actions" COM_ADMIN_HELP_USER_ACTIONS_LOG:_OPTIONS="User Actions Log: Options" COM_ADMIN_HELP_USER_ACTIONS_LOG="Action Logs" COM_ADMIN_HELP_USER_NOTES:_NEW_OR_EDIT="Users: User Notes - New/Edit" @@ -224,10 +243,10 @@ COM_ADMIN_HELP_USERS:_NEW_OR_EDIT_GROUP="Users: Groups - New/Edit" COM_ADMIN_HELP_USERS:_OPTIONS="Users: Options" COM_ADMIN_HELP_USERS:_VIEWING_ACCESS_LEVELS="Users: Access Levels" COM_ADMIN_HELP_USERS="Users" +COM_ADMIN_HELP_WORKFLOWS="Workflows" COM_ADMIN_HELP_WORKFLOWS_LIST="Workflows List" COM_ADMIN_JOOMLA_COMPAT_PLUGIN="Joomla Backward Compatibility Plugin" COM_ADMIN_JOOMLA_VERSION="Joomla! Version" -COM_ADMIN_LICENSE="License" COM_ADMIN_LOG_DIRECTORY="(Log folder)" COM_ADMIN_MAX_INPUT_VARS="Maximum Input Variables" COM_ADMIN_MBSTRING_ENABLED="Multibyte String (mbstring) Enabled" diff --git a/administrator/language/en-GB/com_config.ini b/administrator/language/en-GB/com_config.ini index f52762f47327c..a512f603f88d9 100644 --- a/administrator/language/en-GB/com_config.ini +++ b/administrator/language/en-GB/com_config.ini @@ -36,6 +36,7 @@ COM_CONFIG_ERROR_SSL_NOT_AVAILABLE_HTTP_CODE="HTTPS version of the site returned COM_CONFIG_ERROR_TMP_PATH_NOTWRITABLE="The temp folder is not writable: %s" COM_CONFIG_ERROR_UNKNOWN_BEFORE_SAVING="A plugin reported an unknown error before saving the configuration." COM_CONFIG_ERROR_WRITE_FAILED="Could not write to the configuration file" +; Deprecated as never used. To be removed in Joomla 7.0 COM_CONFIG_FIELD_BODY_LABEL="Body" COM_CONFIG_FIELD_CACHE_HANDLER_LABEL="Cache Handler" COM_CONFIG_FIELD_CACHE_LABEL="System Cache" @@ -95,6 +96,7 @@ COM_CONFIG_FIELD_FORCE_SSL_DESC="HTTPS must be enabled on your server or load ba COM_CONFIG_FIELD_FORCE_SSL_LABEL="Force HTTPS" COM_CONFIG_FIELD_GZIP_COMPRESSION_DESC="Joomla can automatically compress the generated HTML pages with GZip, making them smaller and increasing your site's speed score. Disable it if your server is already doing that for you or if it conflicts with third party extensions." COM_CONFIG_FIELD_GZIP_COMPRESSION_LABEL="Gzip Page Compression" +; Deprecated as never used. To be removed in Joomla 7.0 COM_CONFIG_FIELD_HTMLBODY_LABEL="HTML Body" COM_CONFIG_FIELD_LOADBALANCER_ENABLE_DESC="If your site is behind a load balancer or reverse proxy, enable this setting so that IP addresses and other configurations within Joomla automatically take this into account." COM_CONFIG_FIELD_LOADBALANCER_ENABLE_LABEL="Behind Load Balancer" @@ -160,7 +162,7 @@ COM_CONFIG_FIELD_REDIS_HOST_LABEL="Redis Server Host/Sock" COM_CONFIG_FIELD_REDIS_PERSISTENT_LABEL="Persistent Redis" COM_CONFIG_FIELD_REDIS_PORT_DESC="Port discarded if connecting to Redis server over Unix sockets." COM_CONFIG_FIELD_REDIS_PORT_LABEL="Redis Server Port" -COM_CONFIG_FIELD_SEF_REWRITE_NOTE="Apache and Litespeed: Rename htaccess.txt to .htaccess
IIS: Rename web.config.txt to web.config
NginX: you must configure your server.
Other servers or if unsure: please consult your hosting company." +COM_CONFIG_FIELD_SEF_REWRITE_NOTE="Apache and Litespeed: Rename htaccess.txt to .htaccess
IIS: Rename web.config.txt to web.config
NginX: you must configure your server.
Other servers or if unsure: please consult your hosting company." COM_CONFIG_FIELD_SEF_REWRITE_DESC="Removes the index.php/ part from the URLs." COM_CONFIG_FIELD_SEF_REWRITE_LABEL="Use URL Rewriting" COM_CONFIG_FIELD_SEF_SUFFIX_DESC="By default, Joomla URLs are \"bare\", without an extension. This options tells Joomla to add an extension such as .html, .feed etc based on the type of content being displayed by the URL." @@ -181,6 +183,7 @@ COM_CONFIG_FIELD_SITE_DISPLAY_MESSAGE_LABEL="Offline Message" COM_CONFIG_FIELD_SITE_NAME_LABEL="Site Name" COM_CONFIG_FIELD_SITE_OFFLINE_LABEL="Site Offline" COM_CONFIG_FIELD_SITENAME_PAGETITLES_LABEL="Site Name in Page Titles" +; Deprecated as never used. To be removed in Joomla 7.0 COM_CONFIG_FIELD_SUBJECT_LABEL="Subject" COM_CONFIG_FIELD_TEMP_PATH_DESC="Joomla needs to temporarily store some files to perform actions such as installing / updating extensions or uploading files. Enter the absolute path of a directory that is writable by PHP. Do not use the system–wide temporary folder (e.g. /tmp) for security reasons." COM_CONFIG_FIELD_TEMP_PATH_LABEL="Path to Temp Folder" @@ -212,15 +215,20 @@ COM_CONFIG_FIELD_WEBSERVICES_CORS_OFF_LABEL="Enable CORS" COM_CONFIG_FIELD_WEBSERVICES_CORS_ALLOW_HEADERS_DESC="Specifies the header(s) sent back in response to a preflight request. Default: Content-Type,X-Joomla-Token" COM_CONFIG_FIELD_WEBSERVICES_CORS_ALLOW_METHODS_DESC="Specifies the Web service method(s) allowed to access on this site, sent back in response to a preflight request. Default: all methods available for the requested route." COM_CONFIG_FIELD_WEBSERVICES_CORS_ALLOW_ORIGIN_DESC="Specifies the origin allowed to access Web services on this site, sent back in response to a preflight request. Default: * (=all)." +; Deprecated as never used. To be removed in Joomla 7.0 COM_CONFIG_FIELDSET_TAGS_LABEL="Tags" +; Deprecated as never used. To be removed in Joomla 7.0 COM_CONFIG_FILTER_OPTION_SELECT_EXTENSION="- Select Extension -" COM_CONFIG_FRONTEDITING_DESC="Joomla can show an overlay in the public front–end, visible only to users with edit privileges, to directly modify the configuration of each module and/or menu displayed on the site. Set to \"None\" to disable this feature." COM_CONFIG_FRONTEDITING_LABEL="Frontend Editing" COM_CONFIG_FRONTEDITING_MENUSANDMODULES="Modules & Menus" COM_CONFIG_FRONTEDITING_MODULES="Modules" COM_CONFIG_GLOBAL_CONFIGURATION="Global Configuration" +; Deprecated as never used. To be removed in Joomla 7.0 COM_CONFIG_HEADING_COMPONENT="Component" +; Deprecated as never used. To be removed in Joomla 7.0 COM_CONFIG_HEADING_DESCRIPTION="Description" +; Deprecated as never used. To be removed in Joomla 7.0 COM_CONFIG_HEADING_LANUAGES="Languages" COM_CONFIG_LOCATION_SETTINGS="Location" COM_CONFIG_LOGGING="Logging" @@ -230,6 +238,7 @@ COM_CONFIG_MAIL_SETTINGS="Mail" COM_CONFIG_MAIL_TEST_MAIL_DESC="Sent when you click the "Send Test Mail" button in the Global Configuration. It is sent to the sending mail address that is set in the mail settings." COM_CONFIG_MAIL_TEST_MAIL_TITLE="Global Configuration: Test Mail" COM_CONFIG_METADATA_SETTINGS="Metadata" +; Deprecated as never used. To be removed in Joomla 7.0 COM_CONFIG_PAGE_EDIT_MAIL="Global Configuration: Edit Mail Template" COM_CONFIG_PERMISSION_SETTINGS="Permissions" COM_CONFIG_PERMISSIONS="Permissions" diff --git a/administrator/language/en-GB/com_content.ini b/administrator/language/en-GB/com_content.ini index dc5e50a580ad1..972328dfdf72e 100644 --- a/administrator/language/en-GB/com_content.ini +++ b/administrator/language/en-GB/com_content.ini @@ -58,6 +58,8 @@ COM_CONTENT_FEATURED_ORDER="Featured Articles Order" COM_CONTENT_FEATURED_TABLE_CAPTION="Featured Articles" COM_CONTENT_FEATURED_TITLE="Articles: Featured" COM_CONTENT_FIELD_ARTICLETEXT_LABEL="Article Text" +COM_CONTENT_FIELD_AUTHORFILTERING_LABEL="Author Filtering Type" +COM_CONTENT_FIELD_AUTHOR_LABEL="Authors" COM_CONTENT_FIELD_BROWSER_PAGE_TITLE_LABEL="Browser Page Title" COM_CONTENT_FIELD_CAPTCHA_LABEL="Allow Captcha on submit" COM_CONTENT_FIELD_CREATED_BY_ALIAS_LABEL="Created by Alias" @@ -65,14 +67,18 @@ COM_CONTENT_FIELD_CREATED_BY_LABEL="Created By" COM_CONTENT_FIELD_CREATED_LABEL="Created Date" COM_CONTENT_FIELD_FEATURED_DOWN_LABEL="Finish Featured" COM_CONTENT_FIELD_FEATURED_UP_LABEL="Start Featured" +COM_CONTENT_FIELD_FIGURE_CLASS_DESC="You can add any CSS class for your own styling ideas.
For image position use for example float-start and float-end." +COM_CONTENT_FIELD_FIGURE_CLASS_LABEL="Figure Class" COM_CONTENT_FIELD_FULL_LABEL="Full Article Image" COM_CONTENT_FIELD_FULLTEXT="Full text" COM_CONTENT_FIELD_IMAGE_ALT_EMPTY_DESC="Decorative Image - no description required" COM_CONTENT_FIELD_IMAGE_ALT_EMPTY_LABEL="No Description" COM_CONTENT_FIELD_IMAGE_ALT_LABEL="Image Description (Alt Text)" COM_CONTENT_FIELD_IMAGE_CAPTION_LABEL="Caption" +; Deprecated, will be removed with 8.0 COM_CONTENT_FIELD_IMAGE_CLASS_DESC="You can add any CSS class for your own styling ideas.
For image position use for example float-start and float-end." COM_CONTENT_FIELD_IMAGE_CLASS_LABEL="Image Class" +COM_CONTENT_FIELD_IMAGEONLY_CLASS_DESC="You can add any CSS class for your own styling ideas.
For example img-thumbnail." COM_CONTENT_FIELD_IMAGE_OPTIONS="Image Options" COM_CONTENT_FIELD_INFOBLOCK_POSITION_LABEL="Position of Article Info" COM_CONTENT_FIELD_INFOBLOCK_TITLE_LABEL="Article Info Title" @@ -82,6 +88,8 @@ COM_CONTENT_FIELD_NOTE_LABEL="Note" COM_CONTENT_FIELD_OPTION_ABOVE="Above" COM_CONTENT_FIELD_OPTION_BELOW="Below" COM_CONTENT_FIELD_OPTION_SPLIT="Split" +COM_CONTENT_FIELD_PREVIEW_TOKEN_EXPIRATION_DESC="Number of minutes before a preview token expires. Preview tokens allow unauthenticated users to view unpublished articles. Default is 15 minutes." +COM_CONTENT_FIELD_PREVIEW_TOKEN_EXPIRATION_LABEL="Preview Token Expiration (minutes)" COM_CONTENT_FIELD_PUBLISH_DOWN_LABEL="Finish Publishing" COM_CONTENT_FIELD_PUBLISH_UP_LABEL="Start Publishing" COM_CONTENT_FIELD_SELECT_ARTICLE_LABEL="Select Article" @@ -121,7 +129,11 @@ COM_CONTENT_HEADING_DATE_MODIFIED="Date Modified" COM_CONTENT_HEADING_DATE_PUBLISH_DOWN="Finish Publishing" COM_CONTENT_HEADING_DATE_PUBLISH_UP="Start Publishing" COM_CONTENT_ID_LABEL="ID" +COM_CONTENT_FIGURE_FULLTEXT_CLASS_LABEL="Full Text Figure Class" +COM_CONTENT_FIGURE_INTRO_CLASS_LABEL="Intro Figure Class" +; Deprecated, will be removed with 8.0 COM_CONTENT_IMAGE_FULLTEXT_CLASS_LABEL="Full Text Image Class" +; Deprecated, will be removed with 8.0 COM_CONTENT_IMAGE_INTRO_CLASS_LABEL="Intro Image Class" COM_CONTENT_MODIFIED_ASC="Date Modified ascending" COM_CONTENT_MODIFIED_DESC="Date Modified descending" @@ -152,6 +164,9 @@ COM_CONTENT_NEW_ARTICLE="New Article" COM_CONTENT_NO_ARTICLES_LABEL="No Articles Message" COM_CONTENT_NO_ITEM_SELECTED="Please first make a selection from the list." COM_CONTENT_NUMBER_CATEGORY_ITEMS_LABEL="# Articles in Category" +COM_CONTENT_OPTION_EXCLUSIVE_VALUE="Exclude" +COM_CONTENT_OPTION_INCLUSIVE_VALUE="Include" +COM_CONTENT_OPTION_ONLYCURRENTUSER_VALUE="Current User" COM_CONTENT_OTHER_OPTIONS="Options" COM_CONTENT_PAGE_ADD_ARTICLE="Articles: New" COM_CONTENT_PAGE_EDIT_ARTICLE="Articles: Edit" diff --git a/administrator/language/en-GB/com_cpanel.ini b/administrator/language/en-GB/com_cpanel.ini index 819dc30fd0f70..b9044b2da3b08 100644 --- a/administrator/language/en-GB/com_cpanel.ini +++ b/administrator/language/en-GB/com_cpanel.ini @@ -30,6 +30,6 @@ COM_CPANEL_MSG_TEXTFILTER3919_TITLE="Updated Text Filter Recommendations" COM_CPANEL_TITLE_SYSTEM_PANEL="System Panel" COM_CPANEL_UNPUBLISH_MODULE_ERROR="Error unpublishing the module" COM_CPANEL_UNPUBLISH_MODULE_SUCCESS="Module unpublished" -COM_CPANEL_WELCOME_BEGINNERS_MESSAGE="

Community resources are available for new users.

" +COM_CPANEL_WELCOME_BEGINNERS_MESSAGE="

Community resources are available for new users.

" COM_CPANEL_WELCOME_BEGINNERS_TITLE="Welcome to Joomla!" COM_CPANEL_XML_DESCRIPTION="Home Dashboard component" diff --git a/administrator/language/en-GB/com_fields.ini b/administrator/language/en-GB/com_fields.ini index ca7ab9f4c122c..d262ead0d9af4 100644 --- a/administrator/language/en-GB/com_fields.ini +++ b/administrator/language/en-GB/com_fields.ini @@ -21,8 +21,6 @@ COM_FIELDS_FIELD_EDITABLE_IN_BOTH="Both" COM_FIELDS_FIELD_EDITABLE_IN_LABEL="Editable In" COM_FIELDS_FIELD_EDITABLE_IN_SITE="Site" COM_FIELDS_FIELD_FORM_EDIT="Edit Field" -; The following string is deprecated and will be removed with 6.0 -COM_FIELDS_FIELD_FORM_LAYOUT_LABEL="Layout" COM_FIELDS_FIELD_FORM_NEW="New Field" COM_FIELDS_FIELD_FORMOPTIONS_HEADING="Form Options" COM_FIELDS_FIELD_GROUP_LABEL="Field Group" diff --git a/administrator/language/en-GB/com_finder.ini b/administrator/language/en-GB/com_finder.ini index 1623cd4df80b9..bcc3a1d2561ae 100644 --- a/administrator/language/en-GB/com_finder.ini +++ b/administrator/language/en-GB/com_finder.ini @@ -19,8 +19,6 @@ COM_FINDER_CONFIG_FILTER_NUMERICS_LABEL="Filter Numeric Terms" COM_FINDER_CONFIG_GATHER_SEARCH_STATISTICS_LABEL="Gather Search Statistics" COM_FINDER_CONFIG_HIGHLIGHT_CONTENT_SEARCH_TERMS_DESC="For performance reasons, this will not highlight more than 10 different terms in the search results." COM_FINDER_CONFIG_HIGHLIGHT_CONTENT_SEARCH_TERMS_LABEL="Highlight Search Terms" -; deprecated will be removed in 6.0 -COM_FINDER_CONFIG_HILIGHT_CONTENT_SEARCH_TERMS_LABEL="Highlight Search Terms" COM_FINDER_CONFIG_IMAGE_CLASS_LABEL="Image Class" COM_FINDER_CONFIG_LANGUAGE_DEFAULT_DEFAULT_LANGUAGE="Default Site Language" COM_FINDER_CONFIG_LANGUAGE_DEFAULT_DESC="Set the language to be used for non-multilingual sites or content marked as \"All\"." diff --git a/administrator/language/en-GB/com_installer.ini b/administrator/language/en-GB/com_installer.ini index 842ad7877b733..b01a65f8bec95 100644 --- a/administrator/language/en-GB/com_installer.ini +++ b/administrator/language/en-GB/com_installer.ini @@ -222,6 +222,11 @@ COM_INSTALLER_PREFERENCES_DESCRIPTION="Fine-tune how extensions installation and COM_INSTALLER_PREFERENCES_LABEL="Preferences" COM_INSTALLER_REINSTALL_ARIA="Reinstall %s" COM_INSTALLER_REINSTALL_BUTTON="Reinstall" +COM_INSTALLER_SECURITY_SEVERITY_0="Security release level: None" +COM_INSTALLER_SECURITY_SEVERITY_1="Security release level: Low" +COM_INSTALLER_SECURITY_SEVERITY_2="Security release level: Medium" +COM_INSTALLER_SECURITY_SEVERITY_3="Security release level: High" +COM_INSTALLER_SECURITY_SEVERITY_4="Security release level: Critical" COM_INSTALLER_SUBMENU_WARNINGS="Warnings" COM_INSTALLER_TOOLBAR_DATABASE_FIX="Update Structure" COM_INSTALLER_TOOLBAR_DISCOVER="Discover" @@ -255,9 +260,9 @@ COM_INSTALLER_TYPE_TYPE_PLUGIN="plugin" COM_INSTALLER_TYPE_TYPE_TEMPLATE="template" COM_INSTALLER_UNABLE_TO_FIND_INSTALL_PACKAGE="Unable to find install package." COM_INSTALLER_UNABLE_TO_INSTALL_JOOMLA_PACKAGE="The Joomla package cannot be installed through the Extension Manager. Please use the Joomla! Update component to update Joomla." -COM_INSTALLER_UNINSTALL_ERROR="Error uninstalling %s." +COM_INSTALLER_UNINSTALL_ERROR="Error uninstalling %1$s %2$s." COM_INSTALLER_UNINSTALL_ERROR_LOCKED_EXTENSION="The extension \"%1$s\" (ID %2$s) is locked and cannot be uninstalled." -COM_INSTALLER_UNINSTALL_SUCCESS="Uninstalling the %s was successful." +COM_INSTALLER_UNINSTALL_SUCCESS="Uninstalling the %1$s %2$s was successful." COM_INSTALLER_UNPACK_ERROR="Failed to extract file: %s" COM_INSTALLER_UPDATE_ERROR="Error updating: %1$s
%2$s
%3$s
" COM_INSTALLER_UPDATE_FILTER_SEARCH_DESC="Search in extension name. Prefix with ID:, UID: or EID: to search for an update ID, update site ID or extension ID." diff --git a/administrator/language/en-GB/com_joomlaupdate.ini b/administrator/language/en-GB/com_joomlaupdate.ini index 05ad25d33353d..5122280857f49 100644 --- a/administrator/language/en-GB/com_joomlaupdate.ini +++ b/administrator/language/en-GB/com_joomlaupdate.ini @@ -29,8 +29,6 @@ COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_CUSTOM_ERROR="The custom URL field is empty COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_DEFAULT="Default" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_LABEL="Update Channel" COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_NEXT="Joomla Next" -; Deprecated, will be removed with 6.0 -COM_JOOMLAUPDATE_CONFIG_UPDATESOURCE_TESTING="Testing" COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_DESC="The last time the automated updates server could reach this site. If this date is too old, something is wrong with the automated updates and you should re-initiate the process by re-saving the configuration." COM_JOOMLAUPDATE_CONFIG_UPDATE_LAST_CHECK_LABEL="Last Checked" COM_JOOMLAUPDATE_CONFIG_UPDATE_TOKEN_DESC="This is the update token that this site uses to authenticate with the Joomla Automated Updates server. It is used to ensure that only your site can update itself." @@ -137,11 +135,11 @@ COM_JOOMLAUPDATE_VIEW_DEFAULT_DATABASE_STRUCTURE_TITLE="Database Table Structure COM_JOOMLAUPDATE_VIEW_DEFAULT_DB_NOT_SUPPORTED="Your database type is not supported" COM_JOOMLAUPDATE_VIEW_DEFAULT_DB_NOT_SUPPORTED_DESC="An update to Joomla %1$s was found, but your current database type is not supported by the new version.
For further details take a look at the minimum requirements for Joomla %1$s." COM_JOOMLAUPDATE_VIEW_DEFAULT_DESCRIPTION_BREAK="Extensions marked with No or Missing Compatibility Tag might break your website. Please consult with the developer before updating." -COM_JOOMLAUPDATE_VIEW_DEFAULT_DESCRIPTION_MISSING_TAG="Extensions marked with Missing Compatibility Tag indicate the developer has not included compatibility information." +COM_JOOMLAUPDATE_VIEW_DEFAULT_DESCRIPTION_MISSING_TAG="Extensions marked with Missing Compatibility Tag indicate the developer has not included compatibility information." COM_JOOMLAUPDATE_VIEW_DEFAULT_DESCRIPTION_UPDATE_REQUIRED="Extensions marked with Yes (X.X.X) might require an update." COM_JOOMLAUPDATE_VIEW_DEFAULT_DIRECTIVE="Directive" COM_JOOMLAUPDATE_VIEW_DEFAULT_DOWNLOAD_IN_PROGRESS="Downloading update file. Please wait …" -COM_JOOMLAUPDATE_VIEW_DEFAULT_EXPLANATION_AND_LINK_TO_DOCS="The pre-update check provides you with information about the readiness of your server, settings and installed extensions for the update.
You can find more information about this page and how to prepare for updating Joomla in the pre-update check documentation." +COM_JOOMLAUPDATE_VIEW_DEFAULT_EXPLANATION_AND_LINK_TO_DOCS="The pre-update check provides you with information about the readiness of your server, settings and installed extensions for the update.
You can find more information about this page and how to prepare for updating Joomla in the pre-update check documentation." COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS="Extensions Pre-Update Check" COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_DESC="Extensions to check before update." COM_JOOMLAUPDATE_VIEW_DEFAULT_EXTENSIONS_NONE="No extensions installed." @@ -194,7 +192,7 @@ COM_JOOMLAUPDATE_VIEW_DEFAULT_PHP_VERSION_NEWER_NOT_SUPPORTED_NOTICE="Please che COM_JOOMLAUPDATE_VIEW_DEFAULT_PHP_VERSION_NOT_SUPPORTED="Your PHP version is not supported" COM_JOOMLAUPDATE_VIEW_DEFAULT_PHP_VERSION_NOT_SUPPORTED_DESC="An update to Joomla %1$s was found, but your currently installed PHP version does not match the minimum requirements for Joomla %1$s." COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_DISABLED_TITLE="The '%s' Plugin Must be Disabled" -COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_DISABLED_NOTICE="This plugin must be disabled and your site working correctly before updating.
Before disabling '%1$s' plugin, read the manual: Compatibility Plugin (Opens the Joomla Programmers Documentation site in a new tab or window)
Go to 'System - Manage - Plugins' and disable the plugin." +COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_DISABLED_NOTICE="This plugin must be disabled and your site working correctly before updating.
Before disabling '%1$s' plugin, read the manual: Compatibility Plugin (Opens the Joomla Programmers Documentation site in a new tab or window)
Go to 'System - Manage - Plugins' and disable the plugin." COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_BC_ENABLED_TITLE="The '%s' Plugin Must be Enabled" ; Deprecated, will be removed with 7.0 COM_JOOMLAUPDATE_VIEW_DEFAULT_PLUGIN_DISABLED_NOTICE="Go to 'System - Manage - Plugins' and disable the plugin." @@ -219,10 +217,8 @@ COM_JOOMLAUPDATE_VIEW_DEFAULT_TAB_PRE_UPDATE_CHECK="Pre-Update Check" COM_JOOMLAUPDATE_VIEW_DEFAULT_TAB_UPLOAD="Upload & Update" COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATEFOUND="A Joomla update was found." COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_CUSTOM="You are on the "%s" update channel. This is not an official Joomla update channel." -COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_DEFAULT="You are on the "%s" update channel. Through this channel you'll receive notifications for all updates of the current Joomla release (5.x)" -COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_NEXT="You are on the "%s" update channel. Through this channel you will be notified when the future major release (6.x) will be available. Before upgrading to 6.x you'll need to assess its compatibility with your environment. You will not be notified about updates of the current Joomla release (5.x)." -; Deprecated, will be removed with 6.0 -COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_TESTING="You are on the "%s" update channel. This channel is designed for testing new releases and fixes in Joomla.
It is only intended for JBS (Joomla Bug Squad™) members and others within the Joomla community who are testing. Do not use this setting on a production site." +COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_DEFAULT="You are on the "%s" update channel. Through this channel you'll receive notifications for all updates of the current Joomla release (6.x)" +COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATES_INFO_NEXT="You are on the "%s" update channel. Through this channel you will be notified when the future major release (7.x) will be available. Before upgrading to 7.x you'll need to assess its compatibility with your environment. You will not be notified about updates of the current Joomla release (6.x)." COM_JOOMLAUPDATE_VIEW_DEFAULT_UPDATE_NOTICE="Before you update Joomla, ensure that the installed extensions are available for the new Joomla version.
You are strongly advised to make a backup of your site's files and database before you start updating." COM_JOOMLAUPDATE_VIEW_DEFAULT_UPLOAD_INTRO="You can use this feature to update Joomla if your server is behind a firewall or otherwise unable to contact the update servers. First download the Joomla Update Package in ZIP format from the official Joomla download page. Then use the fields below to upload and install it." COM_JOOMLAUPDATE_VIEW_UPDATE_BYTESEXTRACTED="Bytes extracted" @@ -256,11 +252,7 @@ INSTL_EXTENSION_AVAILABLE="%s Available" INSTL_FILE_UPLOADS="File Uploads" INSTL_JSON_SUPPORT_AVAILABLE="JSON Support" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is Default" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICEMBLANGNOTDEFAULT="PHP mbstring language is not set to neutral. This can be set locally by entering php_value mbstring.language neutral in your .htaccess file." -; Deprecated, will be removed with 6.0 -INSTL_NOTICEMBSTRINGOVERLOAD="PHP mbstring function overload is set. This can be turned off locally by entering php_value mbstring.func_overload 0 in your .htaccess file." INSTL_OUTPUT_BUFFERING="Output Buffering" INSTL_PARSE_INI_FILE_AVAILABLE="INI Parser Support" INSTL_PHP_VERSION_NEWER="PHP Version >= %s" diff --git a/administrator/language/en-GB/com_languages.ini b/administrator/language/en-GB/com_languages.ini index 296154457c891..c33a4a527bdde 100644 --- a/administrator/language/en-GB/com_languages.ini +++ b/administrator/language/en-GB/com_languages.ini @@ -5,6 +5,14 @@ COM_LANGUAGES="Languages" COM_LANGUAGES_CONFIGURATION="Languages: Options" +COM_LANGUAGES_CONFIG_FALLBACK_FIELDSET_DESC="Define which language should be used as a fallback for strings that are missing in a regional language. For example, let de-CH (Swiss German) fall back to de-DE (German) before English. Missing strings are resolved per string; strings present in the regional language are never replaced." +COM_LANGUAGES_CONFIG_FALLBACK_FIELDSET_LABEL="Language Fallback" +COM_LANGUAGES_CONFIG_FALLBACK_OVERRIDES_DESC="Each row maps an installed language to the language used as a fallback for its missing strings. This overrides any fallback defined by the language pack. Fallbacks may be chained (for example gsw-CH to de-CH to de-DE)." +COM_LANGUAGES_CONFIG_FALLBACK_OVERRIDES_LABEL="Fallback Overrides" +COM_LANGUAGES_CONFIG_FALLBACK_TAG_DESC="The language tag whose missing strings should be resolved through a fallback language, for example de-CH." +COM_LANGUAGES_CONFIG_FALLBACK_TAG_LABEL="Language" +COM_LANGUAGES_CONFIG_FALLBACK_TARGET_DESC="The language tag used as a fallback for missing strings, for example de-DE." +COM_LANGUAGES_CONFIG_FALLBACK_TARGET_LABEL="Fallback Language" COM_LANGUAGES_CONTENT_TABLE_CAPTION="Content Languages" COM_LANGUAGES_ERR_NO_LANGUAGE_SELECTED="No language selected." COM_LANGUAGES_ERR_PUBLISH="Select a language to publish." @@ -126,9 +134,11 @@ COM_LANGUAGES_VIEW_LANGUAGE_EDIT_NEW_TITLE="Languages: New Content Language" COM_LANGUAGES_VIEW_LANGUAGES_TITLE="Languages: Content" COM_LANGUAGES_VIEW_OVERRIDE_CLIENT_ADMINISTRATOR="Administrator" COM_LANGUAGES_VIEW_OVERRIDE_CLIENT_SITE="Site" +COM_LANGUAGES_VIEW_OVERRIDES_CREATE="Create override in %s" COM_LANGUAGES_VIEW_OVERRIDE_EDIT_EDIT_OVERRIDE_LEGEND="Edit this Override" COM_LANGUAGES_VIEW_OVERRIDE_EDIT_NEW_OVERRIDE_LEGEND="Create a New Override" COM_LANGUAGES_VIEW_OVERRIDE_EDIT_TITLE="Languages: Edit Override" +COM_LANGUAGES_VIEW_OVERRIDES_EXISTS="Override exists in %s" COM_LANGUAGES_VIEW_OVERRIDE_FORM_EDIT="Edit Override" COM_LANGUAGES_VIEW_OVERRIDE_FORM_NEW="New Override" COM_LANGUAGES_VIEW_OVERRIDE_LANGUAGE="%1$s [%2$s]" @@ -149,6 +159,8 @@ COM_LANGUAGES_VIEW_OVERRIDES_LANGUAGES_BOX_ITEM="%1$s - %2$s" COM_LANGUAGES_VIEW_OVERRIDES_N_ITEMS_DELETED="%d language overrides were deleted." COM_LANGUAGES_VIEW_OVERRIDES_N_ITEMS_DELETED_1="Language override was deleted." COM_LANGUAGES_VIEW_OVERRIDES_NO_ITEM_SELECTED="You haven't selected any overrides." +COM_LANGUAGES_VIEW_OVERRIDES_NO_OVERRIDE="No Override" +COM_LANGUAGES_VIEW_OVERRIDES_OVERRIDE="Override" COM_LANGUAGES_VIEW_OVERRIDES_PURGE="Clear Cache" COM_LANGUAGES_VIEW_OVERRIDES_PURGE_SUCCESS="Overrider cache table cleared." COM_LANGUAGES_VIEW_OVERRIDES_TEXT="Text" diff --git a/administrator/language/en-GB/com_menus.ini b/administrator/language/en-GB/com_menus.ini index 05210e29cdcc2..a0e0baed6e4af 100644 --- a/administrator/language/en-GB/com_menus.ini +++ b/administrator/language/en-GB/com_menus.ini @@ -176,8 +176,6 @@ COM_MENUS_SELECT_A_MENUITEM="Select a Menu Item" COM_MENUS_SELECT_MENU="- Select Menu -" COM_MENUS_SELECT_MENU_FILTER="Select Menu" COM_MENUS_SELECT_MENU_FILTER_NOT_TRASHED="Filter the list by a state other than trashed or clear the filter." -; Deprecated, will be removed with 6.0 -COM_MENUS_SELECT_MENU_FIRST="To use batch processing, please first select a Menu in the manager." COM_MENUS_SELECT_MENU_FIRST_EXPORT="To use export, please first select a valid Menu in the manager." COM_MENUS_SUBMENU_ITEMS="Menu Items" COM_MENUS_SUBMENU_MENUS="Menus" diff --git a/administrator/language/en-GB/com_modules.ini b/administrator/language/en-GB/com_modules.ini index 339f9fae77b42..fc0e00e55f0e5 100644 --- a/administrator/language/en-GB/com_modules.ini +++ b/administrator/language/en-GB/com_modules.ini @@ -25,6 +25,7 @@ COM_MODULES_CONFIGURATION="Module: Options" COM_MODULES_CUSTOM_OUTPUT="Custom Output" COM_MODULES_CUSTOM_POSITION="Active Positions" COM_MODULES_DESELECT="Deselect" +COM_MODULES_EDIT_MODULE="Edit Module" COM_MODULES_EMPTYSTATE_BUTTON_ADD="Add a module" COM_MODULES_EMPTYSTATE_CONTENT="Modules are lightweight and flexible extensions used for page rendering. Use them to add small blocks of functionality to your page." COM_MODULES_EMPTYSTATE_TITLE_ADMINISTRATOR="No Administrator Modules have been created yet." @@ -65,6 +66,7 @@ COM_MODULES_GENERAL_FIELDSET_DESC="Configure module edit interface settings." COM_MODULES_GLOBAL="Assigning the Module to Menu Items" COM_MODULES_GLOBAL_ASSIGN="Assign to Menu Items" COM_MODULES_GLOBAL_TREE_EXPAND="Expand the Menu Subtrees" +COM_MODULES_HEADING_ASSOCIATION="Associations" COM_MODULES_HEADING_MODULE="Type" COM_MODULES_HEADING_MODULE_ASC="Type ascending" COM_MODULES_HEADING_MODULE_DESC="Type descending" @@ -79,6 +81,7 @@ COM_MODULES_HTML_PUBLISH_DISABLED="Publish module::Extension disabled" COM_MODULES_HTML_PUBLISH_ENABLED="Publish module::Extension enabled" COM_MODULES_HTML_UNPUBLISH_DISABLED="Unpublish module::Extension disabled" COM_MODULES_HTML_UNPUBLISH_ENABLED="Unpublish module::Extension enabled" +COM_MODULES_ITEM_FIELD_ASSOCIATION_NO_VALUE="Select a Module" COM_MODULES_MANAGER_MODULE="Modules: %s" COM_MODULES_MANAGER_MODULES_ADMIN="Modules (Administrator)" COM_MODULES_MANAGER_MODULES_SITE="Modules (Site)" @@ -90,6 +93,7 @@ COM_MODULES_MENU_ITEM_URL="URL" COM_MODULES_MODULE="Module" COM_MODULES_MODULE_ASSIGN="Module Assignment" COM_MODULES_MODULE_DESCRIPTION="Module Description" +COM_MODULES_MODULE_SPRINTF="Module: %s" COM_MODULES_MODULE_TEMPLATE_POSITION="%1$s (%2$s)" COM_MODULES_MODULES="Modules" COM_MODULES_MODULES_FILTER_SEARCH_DESC="Search in module title and note. Prefix with ID: to search for a module ID." @@ -116,6 +120,7 @@ COM_MODULES_N_QUICKICON_1="Module" COM_MODULES_N_QUICKICON_SRONLY="Modules: %d modules are available." COM_MODULES_N_QUICKICON_SRONLY_0="Modules: No module is available." COM_MODULES_N_QUICKICON_SRONLY_1="Modules: One module is available." +COM_MODULES_NEW_MODULE="New Module" COM_MODULES_NO_ITEM_SELECTED="No modules selected." COM_MODULES_NODESCRIPTION="No description available." COM_MODULES_NONE=":: None ::" @@ -185,6 +190,7 @@ COM_MODULES_POSITION_USER7="User 7" COM_MODULES_POSITION_USER8="User 8" COM_MODULES_SAVE_SUCCESS="Module saved." COM_MODULES_SEARCH_MENUITEM="Search for a Menu Item" +COM_MODULES_SELECT_A_MODULE="Select a module" COM_MODULES_SELECT_MODULE="Select module, %s" COM_MODULES_SUBITEMS="Sub-items" COM_MODULES_TABLE_CAPTION="Modules" diff --git a/administrator/language/en-GB/com_privacy.ini b/administrator/language/en-GB/com_privacy.ini index b171f4c6a5bad..94ed11d972982 100644 --- a/administrator/language/en-GB/com_privacy.ini +++ b/administrator/language/en-GB/com_privacy.ini @@ -8,15 +8,15 @@ COM_PRIVACY="Privacy" COM_PRIVACY_ACTION_DELETE_DATA="Delete Data" COM_PRIVACY_ACTION_EMAIL_EXPORT_DATA="Email Data Export" COM_PRIVACY_ACTION_EXPORT_DATA="Export Data" -COM_PRIVACY_ACTION_LOG_ADMIN_COMPLETED_REQUEST="User {username} completed request #{id} for {subjectemail}" -COM_PRIVACY_ACTION_LOG_ADMIN_CREATED_REQUEST="User {username} created request #{id} for {subjectemail}" -COM_PRIVACY_ACTION_LOG_ADMIN_INVALIDATED_REQUEST="User {username} invalidated request #{id} for {subjectemail}" -COM_PRIVACY_ACTION_LOG_CONFIRMED_REQUEST="{subjectemail} has confirmed request #{id}" -COM_PRIVACY_ACTION_LOG_CREATED_REQUEST="{subjectemail} has submitted request #{id}" -COM_PRIVACY_ACTION_LOG_EXPORT="User {username} exported the data for request #{id}" -COM_PRIVACY_ACTION_LOG_EXPORT_EMAILED="User {username} emailed the data export for request #{id} to the recipient" -COM_PRIVACY_ACTION_LOG_REMOVE="User {username} removed the data for request #{id}" -COM_PRIVACY_ACTION_LOG_REMOVE_BLOCKED="User {username} attempted to remove the data for request #{id} however this action was blocked" +COM_PRIVACY_ACTION_LOG_ADMIN_COMPLETED_REQUEST="User {username} completed request #{id} for {subjectemail}" +COM_PRIVACY_ACTION_LOG_ADMIN_CREATED_REQUEST="User {username} created request #{id} for {subjectemail}" +COM_PRIVACY_ACTION_LOG_ADMIN_INVALIDATED_REQUEST="User {username} invalidated request #{id} for {subjectemail}" +COM_PRIVACY_ACTION_LOG_CONFIRMED_REQUEST="{subjectemail} has confirmed request #{id}" +COM_PRIVACY_ACTION_LOG_CREATED_REQUEST="{subjectemail} has submitted request #{id}" +COM_PRIVACY_ACTION_LOG_EXPORT="User {username} exported the data for request #{id}" +COM_PRIVACY_ACTION_LOG_EXPORT_EMAILED="User {username} emailed the data export for request #{id} to the recipient" +COM_PRIVACY_ACTION_LOG_REMOVE="User {username} removed the data for request #{id}" +COM_PRIVACY_ACTION_LOG_REMOVE_BLOCKED="User {username} attempted to remove the data for request #{id} however this action was blocked" COM_PRIVACY_ACTION_VIEW="View Request" COM_PRIVACY_BADGE_URGENT_REQUEST="Urgent" COM_PRIVACY_CONFIGURATION="Privacy: Options" @@ -131,7 +131,7 @@ COM_PRIVACY_NOTIFY_LABEL="Days To Consider Request Urgent" COM_PRIVACY_N_CONSENTS_INVALIDATED="%d consents were invalidated." COM_PRIVACY_N_CONSENTS_INVALIDATED_1="The consent was invalidated." COM_PRIVACY_OPTION_LABEL="Options" -COM_PRIVACY_POSTINSTALL_BODY="

With the introduction of GDPR for EU citizens and similar regulations elsewhere in the world it may be necessary for you to request consent before storing any Personal Information of a user.

Joomla 3.9 introduces new capabilities to assist you in creating site privacy policies and collecting user consent. In addition a workflow is available to help you manage user information requests such as requests for removing their personal data from your site.

For further information on this new feature read the Privacy documentation.

" +COM_PRIVACY_POSTINSTALL_BODY="

With the introduction of GDPR for EU citizens and similar regulations elsewhere in the world it may be necessary for you to request consent before storing any Personal Information of a user.

Joomla 3.9 introduces new capabilities to assist you in creating site privacy policies and collecting user consent. In addition a workflow is available to help you manage user information requests such as requests for removing their personal data from your site.

For further information on this new feature read the Privacy documentation.

" COM_PRIVACY_POSTINSTALL_TITLE="Increased Management Of Users Privacy" COM_PRIVACY_REQUESTS_EMPTYSTATE_BUTTON_ADD="Add your first request" COM_PRIVACY_REQUESTS_EMPTYSTATE_CONTENT="This screen displays all Privacy: Information Requests that have been received and their status. You can also create a new request here." diff --git a/administrator/language/en-GB/com_scheduler.ini b/administrator/language/en-GB/com_scheduler.ini index 6b37b6c1d272d..23083dd1dd859 100644 --- a/administrator/language/en-GB/com_scheduler.ini +++ b/administrator/language/en-GB/com_scheduler.ini @@ -127,7 +127,7 @@ COM_SCHEDULER_OPTION_EXECUTION_MANUAL_LABEL="Manual Execution" COM_SCHEDULER_OPTION_ORPHANED_HIDE="Hide Orphaned" COM_SCHEDULER_OPTION_ORPHANED_ONLY="Only Orphaned" COM_SCHEDULER_OPTION_ORPHANED_SHOW="Show Orphaned" -COM_SCHEDULER_PERMISSION_TESTRUN="Test task" +COM_SCHEDULER_PERMISSION_TESTRUN="Run Manually" COM_SCHEDULER_ROUTINE_LOG_PREFIX="Task> " COM_SCHEDULER_RUNNING_SINCE="Running since %s" COM_SCHEDULER_SCHEDULER="Scheduler" @@ -158,15 +158,15 @@ COM_SCHEDULER_TASK_TIMES_DESC="Times descending" COM_SCHEDULER_TASK_TYPE="Task Type" COM_SCHEDULER_TASK_TYPE_ASC="Task Type ascending" COM_SCHEDULER_TASK_TYPE_DESC="Task Type descending" -COM_SCHEDULER_TEST_RUN="Run Test" +COM_SCHEDULER_TEST_RUN="Run Task" COM_SCHEDULER_TEST_RUN_DURATION="Duration: %s seconds" COM_SCHEDULER_TEST_RUN_OUTPUT="Output:
%s" COM_SCHEDULER_TEST_RUN_STATUS_COMPLETED="Status: Completed" COM_SCHEDULER_TEST_RUN_STATUS_STARTED="Status: Started" COM_SCHEDULER_TEST_RUN_STATUS_TERMINATED="Status: Terminated" COM_SCHEDULER_TEST_RUN_TASK="Task: \"%s\"" -COM_SCHEDULER_TEST_RUN_TITLE="Test task (ID: %d)" -COM_SCHEDULER_TEST_TASK="Test Task" +COM_SCHEDULER_TEST_RUN_TITLE="Run Task (ID: %d)" +COM_SCHEDULER_TEST_TASK="Run Manually" COM_SCHEDULER_TOOLBAR_PURGE="Clear History" COM_SCHEDULER_TOOLBAR_PURGE_CONFIRM="Are you sure you want to delete all Execution History?" COM_SCHEDULER_TOOLBAR_UNLOCK="Unlock" diff --git a/administrator/language/en-GB/com_tags.ini b/administrator/language/en-GB/com_tags.ini index 81e829358f7fe..4a4cf96e1d3fa 100644 --- a/administrator/language/en-GB/com_tags.ini +++ b/administrator/language/en-GB/com_tags.ini @@ -9,7 +9,10 @@ COM_TAGS_ALL_TAGS_DESCRIPTION_LABEL="Heading Description" COM_TAGS_ALL_TAGS_MEDIA_LABEL="Heading Image File" COM_TAGS_ANY="Any" COM_TAGS_BASIC_FIELDSET_LABEL="Options" +COM_TAGS_BATCH_COPY_MOVE_CANNOT_CREATE="You are not allowed to create new tags." +COM_TAGS_BATCH_COPY_MOVE_CANNOT_EDIT="You are not allowed to edit tags." COM_TAGS_BATCH_OPTIONS="Batch process the selected tags" +COM_TAGS_BATCH_TAG_LABEL="To Move or Copy your selection please select a Tag or parent item." COM_TAGS_COMPACT_COLUMNS_LABEL="Number of Columns" COM_TAGS_CONFIG_ALL_TAGS_FIELD_LAYOUT_LABEL="Default List All Tags Layout" COM_TAGS_CONFIG_ALL_TAGS_SETTINGS_DESC="These settings apply for a List of all Tags unless they are changed for a specific menu item." diff --git a/administrator/language/en-GB/com_templates.ini b/administrator/language/en-GB/com_templates.ini index f57bab877d5a4..aadc636762685 100644 --- a/administrator/language/en-GB/com_templates.ini +++ b/administrator/language/en-GB/com_templates.ini @@ -11,6 +11,7 @@ COM_TEMPLATES_BUTTON_CHECK="Check Overrides" COM_TEMPLATES_BUTTON_CHECK_LIST_ENTRY="Mark Checked" COM_TEMPLATES_BUTTON_CLOSE_FILE="Close" COM_TEMPLATES_BUTTON_COPY_FILE="Copy File" +COM_TEMPLATES_BUTTON_COPY_CHILD_TEMPLATE="Copy Child Template" COM_TEMPLATES_BUTTON_COPY_TEMPLATE="Copy Template" COM_TEMPLATES_BUTTON_CREATE="Create" COM_TEMPLATES_BUTTON_CROP="Crop" @@ -241,6 +242,7 @@ COM_TEMPLATES_TEMPLATE_CHILD_NAME_LABEL="Child Template Name" COM_TEMPLATES_TEMPLATE_CHILD_STYLE_LABEL="Additional Template Styles" COM_TEMPLATES_TEMPLATE_CLOSE="Close" COM_TEMPLATES_TEMPLATE_COPY="Copy Template" +COM_TEMPLATES_TEMPLATE_COPY_CHILD="Copy Child Template" COM_TEMPLATES_TEMPLATE_CORE_FILENAME="Original file "%s"." COM_TEMPLATES_TEMPLATE_DESCRIPTION="Template description." COM_TEMPLATES_TEMPLATE_DETAILS="%s Details and Files" diff --git a/administrator/language/en-GB/com_users.ini b/administrator/language/en-GB/com_users.ini index 334cb13e237f5..1cd983eb0de7f 100644 --- a/administrator/language/en-GB/com_users.ini +++ b/administrator/language/en-GB/com_users.ini @@ -203,6 +203,7 @@ COM_USERS_LBL_SELECT_INSTRUCTIONS="Please select how you would like to verify yo COM_USERS_LEVELS_N_ITEMS_DELETED="%d View Permission Levels deleted." COM_USERS_LEVELS_N_ITEMS_DELETED_1="View Permission Level deleted." COM_USERS_LEVELS_TABLE_CAPTION="Viewing Access Levels" +; The following string is deprecated and will be removed with 8.0 COM_USERS_LEVEL_DETAILS="Level Details" COM_USERS_LEVEL_FIELD_TITLE_LABEL="Level Title" COM_USERS_LEVEL_FORM_EDIT="Edit Viewing Access Level" @@ -397,6 +398,8 @@ COM_USERS_USERS_N_ITEMS_DELETED="%d users deleted." COM_USERS_USERS_N_ITEMS_DELETED_1="User deleted." COM_USERS_USERS_TABLE_CAPTION="Users" COM_USERS_USER_ACCOUNT_DETAILS="Account Details" +COM_USERS_USER_ACTIVATE_AND_MAIL="Activate & Send Email" +COM_USERS_USER_ACTIVATION_REMINDER="Send Activation Reminder" COM_USERS_USER_ALLOWTOURAUTOSTART_LABEL="Allow Auto Starting Tours" COM_USERS_USER_BACKUPCODE="Backup Code" COM_USERS_USER_BACKUPCODES="Backup Codes" diff --git a/administrator/language/en-GB/com_workflow.ini b/administrator/language/en-GB/com_workflow.ini index 6b5d01f1fcfa2..366e3fdb74369 100644 --- a/administrator/language/en-GB/com_workflow.ini +++ b/administrator/language/en-GB/com_workflow.ini @@ -46,7 +46,9 @@ COM_WORKFLOW_N_ITEMS_TRASHED="%d workflows trashed." COM_WORKFLOW_N_ITEMS_TRASHED_1="Workflow trashed." COM_WORKFLOW_N_ITEMS_UNPUBLISHED="%d workflows disabled." COM_WORKFLOW_N_ITEMS_UNPUBLISHED_1="Workflow disabled." +COM_WORKFLOW_PREVIEW="Preview" COM_WORKFLOW_PUBLISHED_LABEL="Status" +COM_WORKFLOW_REDO="Redo" COM_WORKFLOW_RULES_TAB="Permissions" COM_WORKFLOW_SELECT_FROM_STAGE="- Select Current Stage -" COM_WORKFLOW_SELECT_TO_STAGE="- Select Target Stage -" @@ -97,6 +99,7 @@ COM_WORKFLOW_TRANSITION_EDIT="Edit Transition" COM_WORKFLOW_TRANSITION_FORM_EDIT="Edit Transition" COM_WORKFLOW_TRANSITION_FORM_NEW="New Transition" COM_WORKFLOW_TRANSITION_NOTE="Note" +COM_WORKFLOW_UNDO="Undo" COM_WORKFLOW_UNPUBLISH_DEFAULT_ERROR="The default workflow cannot be disabled." COM_WORKFLOW_USE_DEFAULT_WORKFLOW="Use default (%s)" COM_WORKFLOW_WORKFLOWS_ADD="Add Workflow" @@ -106,3 +109,126 @@ COM_WORKFLOW_WORKFLOWS_TABLE_CAPTION="Workflows" COM_WORKFLOW_WORKFLOW_NOTE="Note" JLIB_HTML_PUBLISH_ITEM="Enable" JLIB_HTML_UNPUBLISH_ITEM="Disable" + +; Workflow Graph Editor +COM_WORKFLOW_GRAPH="Graph" +COM_WORKFLOW_GRAPH_ADD_STAGE="Add Stage" +COM_WORKFLOW_GRAPH_ADD_STAGE_DIALOG_OPENED="Add stage dialog opened." +COM_WORKFLOW_GRAPH_ADD_TRANSITION_DIALOG_OPENED="Add transition dialog opened." +COM_WORKFLOW_GRAPH_ADD_TRANSITION="Add Transition" +COM_WORKFLOW_GRAPH_API_NOT_SET="Workflow Graph is not initialized correctly." +COM_WORKFLOW_GRAPH_BACKGROUND="Workflow Graph Background" +COM_WORKFLOW_GRAPH_CANVAS_DESCRIPTION="Keyboard shortcuts: Alt+N to add stage, Alt+M to add transition, F to fit view, E to edit selected item, Delete to remove selected item." +COM_WORKFLOW_GRAPH_CANVAS_LABEL="Workflow Graph Canvas" +COM_WORKFLOW_GRAPH_CANVAS_VIEW_CONTROLS="Workflow Graph Canvas View Controls" +COM_WORKFLOW_GRAPH_CLEAR_SELECTION="Clear Selection" +COM_WORKFLOW_GRAPH_CLOSE_ACTIONS_MENU="Close actions menu for %s" +COM_WORKFLOW_GRAPH_CONTROLS="Workflow Graph Controls" +COM_WORKFLOW_GRAPH_CREATING_TRANSITION="Creating new transition from stage %s to %s." +COM_WORKFLOW_GRAPH_DEFAULT="Default" +COM_WORKFLOW_GRAPH_DISABLED="Disabled" +COM_WORKFLOW_GRAPH_EDIT_ITEM="Edit Item" +COM_WORKFLOW_GRAPH_EDIT_STAGE="Edit Stage" +COM_WORKFLOW_GRAPH_EDIT_TRANSITION="Edit Transition" +COM_WORKFLOW_GRAPH_ENABLED="Enabled" +COM_WORKFLOW_GRAPH_ERROR_API_RETURNED_ERROR="API returned an error." +COM_WORKFLOW_GRAPH_ERROR_CSRF_TOKEN_NOT_SET="Invalid token. Please try again." +COM_WORKFLOW_GRAPH_ERROR_EXTENSION_NOT_SET="Workflow extension is not set." +COM_WORKFLOW_GRAPH_ERROR_FAILED_TO_UPDATE_STAGE_POSITIONS="Failed to update stage positions." +COM_WORKFLOW_GRAPH_ERROR_FETCHING_MODEL="Error loading workflow." +COM_WORKFLOW_GRAPH_ERROR_INVALID_ID="The workflow is not set correctly." +COM_WORKFLOW_GRAPH_ERROR_INVALID_POSITION_DATA="Invalid position data for %s." +COM_WORKFLOW_GRAPH_ERROR_INVALID_STAGE_POSITIONS="Invalid stage positions." +COM_WORKFLOW_GRAPH_ERROR_NOT_AUTHENTICATED="You are not authenticated." +COM_WORKFLOW_GRAPH_ERROR_NO_PERMISSION="You do not have permission to access the workflows." +COM_WORKFLOW_GRAPH_ERROR_REQUEST_FAILED="Request failed with status %s" +COM_WORKFLOW_GRAPH_ERROR_STAGES_NOT_FOUND="Stages not found." +COM_WORKFLOW_GRAPH_ERROR_STAGE_DEFAULT_CANT_DELETED="The default stage cannot be deleted." +COM_WORKFLOW_GRAPH_ERROR_STAGE_HAS_TRANSITIONS="This stage has transitions and cannot be deleted." +COM_WORKFLOW_GRAPH_ERROR_UNKNOWN="An unknown error occurred." +COM_WORKFLOW_GRAPH_ERROR_WORKFLOW_ID_NOT_SET="Workflow ID is not set." +COM_WORKFLOW_GRAPH_ERROR_WORKFLOW_NOT_FOUND="Workflow not found." +COM_WORKFLOW_GRAPH_FIT_VIEW="Fit View" +COM_WORKFLOW_GRAPH_FOCUS_TYPE_CHANGE="Change Focus Type" +COM_WORKFLOW_GRAPH_FROM_ANY="From Any" +COM_WORKFLOW_GRAPH_FULL="Workflow Graph" +COM_WORKFLOW_GRAPH_LOADING="Loading..." +COM_WORKFLOW_GRAPH_MINIMAP_HIDE="Hide Minimap" +COM_WORKFLOW_GRAPH_MINIMAP_LABEL="Workflow Graph Minimap" +COM_WORKFLOW_GRAPH_MINIMAP_SHOW="Show Minimap" +COM_WORKFLOW_GRAPH_MOVE_STAGE="Move Stage" +COM_WORKFLOW_GRAPH_MOVE_VIEW="Move View" +COM_WORKFLOW_GRAPH_NAVIGATE_NODES="Navigate Nodes" +COM_WORKFLOW_GRAPH_N_ITEMS_ARCHIVED="%d items archived." +COM_WORKFLOW_GRAPH_N_ITEMS_ARCHIVED_1="Item archived." +COM_WORKFLOW_GRAPH_N_ITEMS_FAILED_PUBLISHING="%d items failed to be published." +COM_WORKFLOW_GRAPH_N_ITEMS_FAILED_PUBLISHING_1="Item failed to be published." +COM_WORKFLOW_GRAPH_N_ITEMS_PUBLISHED="%d items published." +COM_WORKFLOW_GRAPH_N_ITEMS_PUBLISHED_1="Item published." +COM_WORKFLOW_GRAPH_N_ITEMS_UNPUBLISHED="%d items unpublished." +COM_WORKFLOW_GRAPH_N_ITEMS_UNPUBLISHED_1="Item unpublished." +COM_WORKFLOW_GRAPH_OPEN_ACTIONS_MENU="Open actions menu for %s" +COM_WORKFLOW_GRAPH_SELECTION_CLEARED="Selection cleared." +COM_WORKFLOW_GRAPH_SELECT_ITEM="Select Item" +COM_WORKFLOW_GRAPH_SHORTCUTS="Shortcuts" +COM_WORKFLOW_GRAPH_SHORTCUTS_TITLE="Keyboard Shortcuts" +COM_WORKFLOW_GRAPH_STAGE="Stage" +COM_WORKFLOW_GRAPH_STAGES="Stages" +COM_WORKFLOW_GRAPH_STAGE_ACTIONS="Actions for stage %s." +COM_WORKFLOW_GRAPH_STAGE_COUNT="Number of Stages" +COM_WORKFLOW_GRAPH_STAGE_DEFAULT="Default Stage" +COM_WORKFLOW_GRAPH_STAGE_DESCRIPTION="Description of stage %s." +COM_WORKFLOW_GRAPH_STAGE_NO_ITEM_SELECTED="No stage selected." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_CHECKED_IN="%d stages checked in." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_CHECKED_IN_1="Stage checked in." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_DELETED="%d stages deleted." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_DELETED_1="Stage deleted." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_FAILED_DELETING="%d stages failed to be deleted." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_FAILED_DELETING_1="Stage failed to be deleted." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_TRASHED="%d stages trashed." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_TRASHED_1="Stage trashed." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_UNPUBLISHED="%d stages unpublished." +COM_WORKFLOW_GRAPH_STAGE_N_ITEMS_UNPUBLISHED_1="Stage unpublished." +COM_WORKFLOW_GRAPH_STAGE_POSITIONS_UPDATED="Stage positions updated." +COM_WORKFLOW_GRAPH_STAGE_REF="Stage: %s" +COM_WORKFLOW_GRAPH_STAGE_SELECTED="Stage selected: %s" +COM_WORKFLOW_GRAPH_STAGE_STATUS_ENABLED="Status of stage %s: Enabled." +COM_WORKFLOW_GRAPH_STAGE_STATUS_DISABLED="Status of stage %s: Disabled." +COM_WORKFLOW_GRAPH_STATUS="Status" +COM_WORKFLOW_GRAPH_TRANSITION="Transition" +COM_WORKFLOW_GRAPH_TRANSITIONS="Transitions" +COM_WORKFLOW_GRAPH_TRANSITION_ACTIONS="Actions for transition %s." +COM_WORKFLOW_GRAPH_TRANSITION_COUNT="Number of Transitions" +COM_WORKFLOW_GRAPH_TRANSITION_DESCRIPTION="Description of transition %s." +COM_WORKFLOW_GRAPH_TRANSITION_NO_ITEM_SELECTED="No transition selected." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_CHECKED_IN="%d transitions checked in." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_CHECKED_IN_1="Transition checked in." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_DELETED="%d transitions deleted." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_DELETED_1="Transition deleted." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_FAILED_DELETING="%d transitions failed to be deleted." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_FAILED_DELETING_1="Transition failed to be deleted." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_PUBLISHED="%d transitions published." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_PUBLISHED_1="Transition published." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_TRASHED="%d transitions trashed." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_TRASHED_1="Transition trashed." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_UNPUBLISHED="%d transitions unpublished." +COM_WORKFLOW_GRAPH_TRANSITION_N_ITEMS_UNPUBLISHED_1="Transition unpublished." +COM_WORKFLOW_GRAPH_TRANSITION_PATH="Transition path for %s." +COM_WORKFLOW_GRAPH_TRANSITION_REF="Transition: %s from stage %s to %s." +COM_WORKFLOW_GRAPH_TRANSITION_SELECTED="Transition selected: %s" +COM_WORKFLOW_GRAPH_TRANSITION_STATUS_ENABLED="Status of transition %s: Enabled." +COM_WORKFLOW_GRAPH_TRANSITION_STATUS_DISABLED="Status of transition %s: Disabled." +COM_WORKFLOW_GRAPH_TRASH_ITEM="Remove Item" +COM_WORKFLOW_GRAPH_TRASH_STAGE="Remove Stage" +COM_WORKFLOW_GRAPH_TRASH_STAGE_CONFIRM="Are you sure you want to remove the stage %s?" +COM_WORKFLOW_GRAPH_TRASH_STAGE_FAILED="Failed to remove stage." +COM_WORKFLOW_GRAPH_TRASH_TRANSITION="Remove Transition" +COM_WORKFLOW_GRAPH_TRASH_TRANSITION_CONFIRM="Are you sure you want to remove the transition %s?" +COM_WORKFLOW_GRAPH_TRASH_TRANSITION_FAILED="Failed to remove transition." +COM_WORKFLOW_GRAPH_UNSAVED_CHANGES="You have unsaved changes." +COM_WORKFLOW_GRAPH_UPDATE_STAGE_POSITION_FAILED="Failed to update stage position." +COM_WORKFLOW_GRAPH_UP_TO_DATE="All changes saved." +COM_WORKFLOW_GRAPH_VIEW="Graph View" +COM_WORKFLOW_GRAPH_WORKFLOWS_EDIT="Workflow Editor" +COM_WORKFLOW_GRAPH_ZOOM_IN="Zoom In" +COM_WORKFLOW_GRAPH_ZOOM_OUT="Zoom Out" diff --git a/administrator/language/en-GB/guidedtours.joomla_categories.ini b/administrator/language/en-GB/guidedtours.joomla_categories.ini index 999c5695cd374..4c96ca08c8ff6 100644 --- a/administrator/language/en-GB/guidedtours.joomla_categories.ini +++ b/administrator/language/en-GB/guidedtours.joomla_categories.ini @@ -3,5 +3,5 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -COM_GUIDEDTOURS_TOUR_CATEGORIES_TITLE="How to create categories?" -COM_GUIDEDTOURS_TOUR_CATEGORIES_DESCRIPTION="This tour will show you how you can create a category." +COM_GUIDEDTOURS_TOUR_CATEGORIES_TITLE="How to create article categories?" +COM_GUIDEDTOURS_TOUR_CATEGORIES_DESCRIPTION="This tour will show you how you can create a category for articles." diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_2.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_2.ini deleted file mode 100644 index c9f46d656d154..0000000000000 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_2.ini +++ /dev/null @@ -1,7 +0,0 @@ -; Joomla! Project -; (C) 2024 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 - -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_DESCRIPTION="

Welcome to Joomla 5.2!

\"The

Guided Tours Updates

Auto-start Tours

This feature will allow you to create your own auto-start Guided Tour. The contextual tour can be opted out for one or all users. Tours can be restarted from the Guided Tours menu.

Enhancements

  • For clarity, the Step Counter was positioned first in the tour header.
  • The modal window resizes automatically to accommodate larger content and images.

Core Updates

The new all-in-one 'Articles' module

Use one module to display latest, most read, specific or archived articles, from select categories - with filters, tags and more...

From Content -> Site Modules, create a new module of type 'Articles'.

Mail Template Layout

Take it a step further by creating an entirely unique layout (including logo) which can be applied to one or all mail templates.

From Global Configuration -> Mail Templates, layouts can be defined in HTML.

Other Enhancements and Fixes

  • Nested Subforms - Allows the nesting of Subform inside a Subform Custom Field.
  • Total Count - Shows the count and total number of list items in the console.
\"Mail
" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_TITLE="What’s New in Joomla 5.2!" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini deleted file mode 100644 index 279928d33f031..0000000000000 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3.ini +++ /dev/null @@ -1,7 +0,0 @@ -; Joomla! Project -; (C) 2025 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 - -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_DESCRIPTION="

Welcome to Joomla 5.3!

Guided Tours Updates

Guided Tours now has its own API. Joomla API Documentation

Stay tuned for other new enhancements coming soon!

\"The

Core Updates

Organize Files in their Own Location

Now you can see and select your stored/uploaded documents directly from the Media Manager. Find more information in the Joomla Community Magazine.

View Scheduled Task History

You now have the ability to view execution information directly in the backend without having to access log files. Look for the Execution History button located in the Scheduled Tasks page.

Other Enhancements and Fixes

  • Template Override Plugin Comparison - adds compare functionality to plugin overrides
  • Tag Alias Lookup Fixed - now instead of showing the tag id number in the URL the tag name is shown
" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_TITLE="What’s New in Joomla 5.3!" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini deleted file mode 100644 index fe8788b793d8c..0000000000000 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_3_steps.ini +++ /dev/null @@ -1,7 +0,0 @@ -; Joomla! Project -; (C) 2025 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 - -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_DESCRIPTION="

Joomla 5.3 Full Release Notes

View the full release notes on joomla.org


Help and Information

Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.

" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_3_STEP_0_TITLE="More Information and Help" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini deleted file mode 100644 index 423d157601db1..0000000000000 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4.ini +++ /dev/null @@ -1,7 +0,0 @@ -; Joomla! Project -; (C) 2025 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 - -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_DESCRIPTION="

Welcome to Joomla 5.4!

\"Display

Automated Updates are here!

Joomla! 5.4 now supports automated updates for better security and performance.

Stay safe and secure!

" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_TITLE="What’s New in Joomla 5.4!" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4_steps.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4_steps.ini deleted file mode 100644 index 6ee83abbbb253..0000000000000 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_4_steps.ini +++ /dev/null @@ -1,7 +0,0 @@ -; Joomla! Project -; (C) 2025 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 - -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_DESCRIPTION="

Joomla 5.4 Full Release Notes

View the full release notes on joomla.org


Help and Information

Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.

" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_4_STEP_0_TITLE="More Information and Help" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_0.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_0.ini new file mode 100644 index 0000000000000..150cd32bfeeb8 --- /dev/null +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_0.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2025 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 + +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_DESCRIPTION="

Welcome to Joomla 6!

\"Display

Cassiopeia Extended

Explore child templates with a new style that demonstrates advanced customisation features like font and colour modifications.

Extended Versioning

Joomla's versioning system has been enhanced to include custom fields, tags and categories, allowing all content changes to be tracked, compared and restored.

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_TITLE="What's New in Joomla 6!" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_0_steps.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_0_steps.ini new file mode 100644 index 0000000000000..c2754bee2eef5 --- /dev/null +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_0_steps.ini @@ -0,0 +1,9 @@ +; Joomla! Project +; (C) 2025 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 + +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_0_DESCRIPTION="

More Updates

Featured articles are now sharing the Article's Manager view.

If you missed it

Joomla! 6 supports automated updates with The Update Framework (TUF) for better security and performance.
Find automated update settings in the Joomla! Update configuration section.

Other Enhancements and Fixes

  • Notification email on admin registration approval PR#45802
  • Add custom classes to the class dropdown in the image dialog in TinyMCE PR#45676
  • Add the possibility to batch remove a tag PR#40613
  • And many, many under the hood improvements...
" +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_0_TITLE="Other Features" +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_1_DESCRIPTION="

Joomla 6.0 Release Information

View release information at 6.joomla.org


Help and Information

Many resources to help you can be found here, together with additional links to more resources, documentation, support, and how to become involved in Joomla.

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_0_STEP_1_TITLE="More Information and Help" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_1.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_1.ini new file mode 100644 index 0000000000000..40013a99234a8 --- /dev/null +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_1.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2026 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 + +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_DESCRIPTION="

Welcome to Joomla 6.1!

Joomla 6.1 introduces key improvements that make site building easier, safer, and more flexible. This tour gives you the essentials at a glance.

Spam Protection is BACK with Proof-of-Work CAPTCHA

No account or API required, privacy-friendly and accessible, this captcha silently solves math puzzles in the background, invisible to visitors.

To enable, go to Extensions -> Plugins, search for captcha, enable and set as default in Global Configuration.

\"The
\"Graphical

Content Pipeline at a Glance with the Visual Workflow Editor

Manage your content workflow more easily with the new interactive workflow diagram that allows you to see the entire publication process.

Enable Workflows in Article Manager -> Workflows and look for the graph button.

Three New Media Custom Field Options: Audio, Video & Documents

When creating Custom Fields for your content, you can now let content creators include any type of media, not just images.

The medias render as HTML5 <audio>, <video>, or document links (PDF, spreadsheets...).

\"The

Smarter Modules with Versioning and Multilingual Associations

Joomla has long had version history for articles. This same capability is now extended to modules.
If you run a multilingual website, you can now associate module instances across different languages, the same way you can associate articles across languages.

Other Enhancements Worth Noting

  • Abbreviation <abbr> support in TinyMCE rich text editor, semantically correct and improving accessibility (look for the new Abbreviation button in the TinyMCE toolbar when editing content).
  • Language override status & quick-create missing overrides UX improvements (status indicator, edit overrides easily).
" +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_TITLE="What’s New in Joomla 6.1!" diff --git a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_2_steps.ini b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_1_steps.ini similarity index 66% rename from administrator/language/en-GB/guidedtours.joomla_whatsnew_5_2_steps.ini rename to administrator/language/en-GB/guidedtours.joomla_whatsnew_6_1_steps.ini index 6bc9e5ac2d322..eaff1e627d6c6 100644 --- a/administrator/language/en-GB/guidedtours.joomla_whatsnew_5_2_steps.ini +++ b/administrator/language/en-GB/guidedtours.joomla_whatsnew_6_1_steps.ini @@ -1,7 +1,7 @@ ; Joomla! Project -; (C) 2024 Open Source Matters, Inc. +; (C) 2026 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 -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_STEP_0_DESCRIPTION="

Joomla 5.2 Full Release Notes

View the full release notes on joomla.org


Help and Information

Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.

" -COM_GUIDEDTOURS_TOUR_WHATSNEW_5_2_STEP_0_TITLE="More Information and Help" +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_STEP_0_DESCRIPTION="

Joomla 6.1 Full Release Notes

View the full release notes on joomla.org


Help and Information

Many resources to help you can be found here together with additional links to more resources, documentation, support and how to become involved in Joomla.

" +COM_GUIDEDTOURS_TOUR_WHATSNEW_6_1_STEP_0_TITLE="More Information and Help" diff --git a/administrator/language/en-GB/install.xml b/administrator/language/en-GB/install.xml index c855da94d9cdf..7abd9e1794e9c 100644 --- a/administrator/language/en-GB/install.xml +++ b/administrator/language/en-GB/install.xml @@ -2,7 +2,7 @@ English (en-GB) en-GB - 5.4.8 + 6.2.0 2026-08 Joomla! Project admin@joomla.org diff --git a/administrator/language/en-GB/joomla.ini b/administrator/language/en-GB/joomla.ini index efac7b0fb12aa..7ccabcf0c069a 100644 --- a/administrator/language/en-GB/joomla.ini +++ b/administrator/language/en-GB/joomla.ini @@ -221,8 +221,11 @@ JFIELD_COLOR_LABEL_SLIDER_HUE="Hue Slider" JFIELD_COLOR_LABEL_SLIDER_INPUT="Selected Colour Value" JFIELD_COLOR_LABEL_SLIDER_LIGHT="Light Slider" JFIELD_COLOR_LABEL_SLIDER_SATURATION="Saturation Slider" +; The following string is deprecated and will be removed with 7.0 JFIELD_COLOR_SELECT="Select a colour" +; The following string is deprecated and will be removed with 7.0 JFIELD_COLOR_TRANSPARENT="No colour, transparent" +; The following string is deprecated and will be removed with 7.0 JFIELD_COLOR_VALUE="Colour with hexadecimal value of" JFIELD_DISPLAY_READONLY_LABEL="Display When Read-Only" JFIELD_ENABLED_DESC="The enabled status of this item." @@ -306,6 +309,7 @@ JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL="Search Limit" JFIELD_PUBLISHED_DESC="Set publication status." JFIELD_READMORE_DESC="Add a custom text instead of Read More." JFIELD_READMORE_LABEL="Read More Text" +JFIELD_RULES_LABEL="Group Permissions" JFIELD_SPACER_LABEL="
" JFIELD_TITLE_DESC="Title" JFIELD_VERSION_HISTORY_DESC="This button allows you to open a window to view older versions of this item." @@ -651,6 +655,7 @@ JGLOBAL_SHOW_READMORE_TITLE_DESC="If set to show the title of the Article will b JGLOBAL_SHOW_READMORE_TITLE_LABEL="Read More with Title" JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC="Show or hide the subcategories descriptions." JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL="Subcategories Descriptions" +JGLOBAL_SHOW_SUBCATEGORIES_IMAGE_LABEL="Subcategories Image" JGLOBAL_SHOW_SUBCATEGORY_CONTENT_DESC="If None, only articles from this category will show. If a number, all articles from the category and the subcategories up to and including that level will show in the blog." JGLOBAL_SHOW_SUBCATEGORY_CONTENT_LABEL="Include Subcategories" JGLOBAL_SHOW_SUBCATEGORY_HEADING="Subcategories Heading" @@ -691,8 +696,6 @@ JGLOBAL_VOTES="Votes" JGLOBAL_VOTES_ASC="Votes ascending" JGLOBAL_VOTES_DESC="Votes descending" JGLOBAL_WARNCOOKIES="Warning! Cookies must be enabled to access the Administrator Backend." -; @deprecated 5.0 will be removed in 6.0 -JGLOBAL_WARNIE="Warning! Internet Explorer should not be used for proper operation of the Administrator Backend." JGLOBAL_WARNJAVASCRIPT="Warning! JavaScript must be enabled for proper operation of the Administrator Backend." JGLOBAL_WIDTH="Width" @@ -925,6 +928,7 @@ PHPMAILER_RECIPIENTS_FAILED="SMTP Error! The following recipients failed: " PHPMAILER_SIGNING_ERROR="Signing error: " PHPMAILER_SMTP_CONNECT_FAILED="SMTP connect failed" PHPMAILER_SMTP_ERROR="SMTP server error: " +; Deprecated, will be removed with 7.0 PHPMAILER_TLS="Could not start TLS" PHPMAILER_VARIABLE_SET="Can't set or reset variable: " diff --git a/administrator/language/en-GB/langmetadata.xml b/administrator/language/en-GB/langmetadata.xml index 7a3b83dfc7a28..da1e1570a326f 100644 --- a/administrator/language/en-GB/langmetadata.xml +++ b/administrator/language/en-GB/langmetadata.xml @@ -1,7 +1,7 @@ English (en-GB) - 5.4.8 + 6.2.0 2026-08 Joomla! Project admin@joomla.org diff --git a/administrator/language/en-GB/lib_joomla.ini b/administrator/language/en-GB/lib_joomla.ini index f921fdf193c4c..cbb1f370ea2de 100644 --- a/administrator/language/en-GB/lib_joomla.ini +++ b/administrator/language/en-GB/lib_joomla.ini @@ -256,6 +256,7 @@ JLIB_FILTER_PARAMS_TEXT="Text" JLIB_FORM_BUTTON_CLEAR="Clear" JLIB_FORM_BUTTON_SELECT="Select" +JLIB_FORM_CHANGE_FILE="Change File" JLIB_FORM_CHANGE_IMAGE="Change Image" JLIB_FORM_CHANGE_IMAGE_BUTTON="Change Image Button" JLIB_FORM_CHANGE_USER="Select User" @@ -272,11 +273,20 @@ JLIB_FORM_FIELD_INVALID_MIN_TIME="The time you entered is before the minimum tim JLIB_FORM_FIELD_INVALID_TIME_INPUT="Invalid time format. Please use hh:mm." JLIB_FORM_FIELD_INVALID_TIME_INPUT_SECONDS="Invalid time format. Please use hh:mm:ss." JLIB_FORM_FIELD_INVALID_VALUE="This value is not valid" -JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_LABEL="Media" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_LABEL="Media (%s)" JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_ALT_EMPTY_DESC="Decorative Image - no description required" JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_ALT_EMPTY_LABEL="No Description" JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_ALT_TEXT_LABEL="Image Description (Alt Text)" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_AUDIO_LABEL="Audio" JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_IMAGEFILE_LABEL="Image" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_LINKTEXT_DEFAULT_VALUE="Download {filename}" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_LINKTEXT_DESC="Specify the link text for non-image file." +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_LINKTEXT_LABEL="Link Text" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_AUDIOS="Audio" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_DOCUMENTS="Document" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_IMAGES="Image" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_VIDEOS="Video" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_VIDEO_POSTER_LABEL="Video Poster" JLIB_FORM_FIELD_PARAM_CALENDAR_FORMAT_DESC="The date format to be used. This is in the format used by PHP to specify date string formats (see below). If no format argument is given, '%Y-%m-%d' is assumed (giving dates like '2008-04-16')." JLIB_FORM_FIELD_PARAM_CALENDAR_FORMAT_LABEL="Format" JLIB_FORM_FIELD_PARAM_CHECKBOX_MULTIPLE_DESC="Allow multiple values to be selected." @@ -379,8 +389,11 @@ JLIB_HTML_BATCH_MOVE="Move" JLIB_HTML_BATCH_MOVE_QUESTION="Action to Perform" JLIB_HTML_BATCH_NO_CATEGORY="- Don't copy or move -" JLIB_HTML_BATCH_NOCHANGE="- Keep original Access Levels -" -JLIB_HTML_BATCH_TAG_LABEL="Add Tag" +JLIB_HTML_BATCH_TAG_ADD="Add" +JLIB_HTML_BATCH_TAG_ADDREMOVE_QUESTION="Action to Perform" +JLIB_HTML_BATCH_TAG_LABEL="Add or Remove Tag" JLIB_HTML_BATCH_TAG_NOCHANGE="- Keep original Tags -" +JLIB_HTML_BATCH_TAG_REMOVE="Remove" JLIB_HTML_BATCH_USER_LABEL="Set User." JLIB_HTML_BATCH_USER_NOCHANGE="- Keep original User -" JLIB_HTML_BATCH_USER_NOUSER="No User." @@ -625,8 +638,6 @@ JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MANIFEST_NOT_REMOVED="Package Uninstall: Err JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MISSING_EXTENSION="Package Uninstall: This extension is missing or has already been uninstalled: %s" JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MISSINGMANIFEST="Package Uninstall: Missing manifest file." JLIB_INSTALLER_ERROR_PACK_UNINSTALL_NOT_PROPER="Package Uninstall: This extension may have already been uninstalled or might not have been uninstalled properly: %s" -; The following string is deprecated and will be removed with 6.0 -JLIB_INSTALLER_ERROR_PACK_UNINSTALL_UNKNOWN_EXTENSION="Trying to uninstall unknown extension from package. This extension may have already been removed earlier." JLIB_INSTALLER_ERROR_PACK_UNINSTALL_WARNCOREPACK="Package Uninstall: Trying to uninstall core package." JLIB_INSTALLER_ERROR_PLG_DISCOVER_STORE_DETAILS="Plugin Discover install: Failed to store plugin details." JLIB_INSTALLER_ERROR_PLG_REFRESH_MANIFEST_CACHE="Plugin Refresh manifest cache: Failed to store plugin details." @@ -688,6 +699,7 @@ JLIB_JS_AJAX_ERROR_TIMEOUT="A timeout has occurred while fetching the JSON data. JLIB_LANGUAGE_ERROR_CANNOT_LOAD_METADATA="Could not load %s metadata from %s." JLIB_LANGUAGE_ERROR_CANNOT_LOAD_METAFILE="Could not load %s language XML file from %s." +JLIB_LANGUAGE_ERROR_CANNOT_WRITE_CACHE="Unable to write cache file for %s." JLIB_LOGIN_AUTHORISATION="Your access has been authorised." JLIB_LOGIN_DENIED="Your access has been denied." @@ -697,6 +709,8 @@ JLIB_MAIL_FUNCTION_DISABLED="The mail() function has been disabled and the mail JLIB_MAIL_FUNCTION_OFFLINE="The mail function has been disabled by an administrator." JLIB_MAIL_INVALID_EMAIL_SENDER="Invalid email sender: %s" +JLIB_MEDIA_ERROR_SVG_ISSUE="SVG Issue: %s" +JLIB_MEDIA_ERROR_SVG_UNKNOWN="Unknown SVG error" JLIB_MEDIA_ERROR_UPLOAD_INPUT="Unable to upload file." JLIB_MEDIA_ERROR_WARNFILENAME="File name must only have alphanumeric characters and no spaces." JLIB_MEDIA_ERROR_WARNFILETOOLARGE="This file is too large to upload. You can change the limits for your site in the component options." diff --git a/administrator/language/en-GB/mod_login.ini b/administrator/language/en-GB/mod_login.ini index 76515bc51edd6..bf6caadb4b011 100644 --- a/administrator/language/en-GB/mod_login.ini +++ b/administrator/language/en-GB/mod_login.ini @@ -5,7 +5,7 @@ MOD_LOGIN="Login Form" MOD_LOGIN_CREDENTIALS="Forgot your login details?" -MOD_LOGIN_CREDENTIALS_LINK="https://docs.joomla.org/Special:MyLanguage/How_do_you_recover_or_reset_your_admin_password%3F" +MOD_LOGIN_CREDENTIALS_LINK="https://guide.joomla.org/user-manual/users/users-admin-password-recovery" MOD_LOGIN_LANGUAGE="Language" MOD_LOGIN_LOGIN_TITLE="Administrator Log In" MOD_LOGIN_XML_DESCRIPTION="This module displays a username and password login form. It should not be unpublished." diff --git a/administrator/language/en-GB/mod_menu.ini b/administrator/language/en-GB/mod_menu.ini index 9beaa0eea7aab..303a7c1fc68f5 100644 --- a/administrator/language/en-GB/mod_menu.ini +++ b/administrator/language/en-GB/mod_menu.ini @@ -57,7 +57,7 @@ MOD_MENU_HELP_COMMUNITY="Community Portal" MOD_MENU_HELP_COMMUNITY_NEWS="Community News" MOD_MENU_HELP_COMMUNITY_NEWSLETTER="Community Newsletter" MOD_MENU_HELP_DEVELOPER="Developer Resources" -MOD_MENU_HELP_DOCUMENTATION="Documentation Wiki" +MOD_MENU_HELP_DOCUMENTATION="Documentation for Joomla! Users" MOD_MENU_HELP_EVENTS="Joomla Events" MOD_MENU_HELP_EXTENSIONS="Joomla! Extensions" MOD_MENU_HELP_GITHUB="Joomla on GitHub" @@ -141,5 +141,6 @@ MOD_MENU_UPDATE="Update" MOD_MENU_UPDATE_EXTENSIONS="Extensions" MOD_MENU_UPDATE_JOOMLA="Joomla" MOD_MENU_UPDATE_SOURCES="Update Sites" +; Deprecated, will be removed with 7.0 MOD_MENU_USER_PROFILE="My Profile" MOD_MENU_XML_DESCRIPTION="This module displays an administrator menu module." diff --git a/administrator/language/en-GB/mod_popular.ini b/administrator/language/en-GB/mod_popular.ini index 3669bb575d9f5..193680338e523 100644 --- a/administrator/language/en-GB/mod_popular.ini +++ b/administrator/language/en-GB/mod_popular.ini @@ -7,11 +7,23 @@ MOD_POPULAR="Popular Articles" MOD_POPULAR_CREATED="Created" MOD_POPULAR_FIELD_AUTHORS_LABEL="Authors" MOD_POPULAR_FIELD_COUNT_LABEL="Items to Display" +MOD_POPULAR_FIELD_DATEFILTERING_LABEL="Date Filtering" +MOD_POPULAR_FIELD_DATERANGEFIELD_LABEL="Date Range Field" +MOD_POPULAR_FIELD_ENDDATE_LABEL="End Date" +MOD_POPULAR_FIELD_RELATIVEDATE_LABEL="Relative Date" +MOD_POPULAR_FIELD_STARTDATE_LABEL="Start Date" MOD_POPULAR_FIELD_VALUE_ADDED_OR_MODIFIED_BY_ME="Added or modified by me" MOD_POPULAR_FIELD_VALUE_ANYONE="Anyone" MOD_POPULAR_FIELD_VALUE_NOT_ADDED_OR_MODIFIED_BY_ME="Not added or modified by me" MOD_POPULAR_ITEMS="Popular Items" +; The following string is deprecated and will be removed with 7.0 MOD_POPULAR_NO_MATCHING_RESULTS="No Matching Results" +MOD_POPULAR_OPTION_CREATED_VALUE="Created Date" +MOD_POPULAR_OPTION_DATERANGE_VALUE="Date Range" +MOD_POPULAR_OPTION_MODIFIED_VALUE="Modified Date" +MOD_POPULAR_OPTION_OFF_VALUE="Off" +MOD_POPULAR_OPTION_RELATIVEDAY_VALUE="Relative Date" +MOD_POPULAR_OPTION_STARTPUBLISHING_VALUE="Start Publishing Date" MOD_POPULAR_TITLE="Popular Articles" MOD_POPULAR_TITLE_1="Top Popular Article" MOD_POPULAR_TITLE_BY_ME="Top Popular Articles By Me" diff --git a/administrator/language/en-GB/mod_stats_admin.ini b/administrator/language/en-GB/mod_stats_admin.ini index a3f764172bcac..dd040a39b0d9a 100644 --- a/administrator/language/en-GB/mod_stats_admin.ini +++ b/administrator/language/en-GB/mod_stats_admin.ini @@ -12,10 +12,3 @@ MOD_STATS_GZIP="Gzip" MOD_STATS_PHP="PHP" MOD_STATS_USERS="Users" MOD_STATS_XML_DESCRIPTION="The Statistics Module shows information about your server installation together with statistics on the website users and the number of Articles in your database." -; Deprecated, will be removed with 6.0 -MOD_STATS_ARTICLES_VIEW_HITS="Articles View Hits" -MOD_STATS_FIELD_COUNTER_LABEL="Hit Counter" -MOD_STATS_FIELD_INCREASECOUNTER_LABEL="Increase Counter" -MOD_STATS_OS="OS" -MOD_STATS_TIME="Time" -MOD_STATS_WEBLINKS="Web Links" diff --git a/administrator/language/en-GB/mod_stats_admin.sys.ini b/administrator/language/en-GB/mod_stats_admin.sys.ini index 38bd731fb2e93..f9941b5d55480 100644 --- a/administrator/language/en-GB/mod_stats_admin.sys.ini +++ b/administrator/language/en-GB/mod_stats_admin.sys.ini @@ -6,6 +6,3 @@ MOD_STATS_ADMIN="Statistics" MOD_STATS_ADMIN_LAYOUT_DEFAULT="Default" MOD_STATS_XML_DESCRIPTION="The Statistics Module shows information about your server installation together with statistics on the website users and the number of Articles in your database." - -; Deprecated, will be removed with 6.0 -MOD_STATS_LAYOUT_DEFAULT="Default" diff --git a/administrator/language/en-GB/mod_user.ini b/administrator/language/en-GB/mod_user.ini index adbe9df8f39c7..e7d067241c2de 100644 --- a/administrator/language/en-GB/mod_user.ini +++ b/administrator/language/en-GB/mod_user.ini @@ -10,7 +10,3 @@ MOD_USER_LIGHTDARK_MODE="Light/Dark Mode" MOD_USER_MENU="User Menu" MOD_USER_TITLE="Signed in as %s" MOD_USER_XML_DESCRIPTION="This module shows the User Menu and is intended to be displayed in the 'status' position." - -; Deprecated, will be removed with 6.0 -MOD_USER_LIGHT_MODE="Light Mode" -MOD_USER_DARK_MODE="Dark Mode" diff --git a/administrator/language/en-GB/plg_actionlog_joomla.ini b/administrator/language/en-GB/plg_actionlog_joomla.ini index dc2d74017868f..58b2f1c3b911d 100644 --- a/administrator/language/en-GB/plg_actionlog_joomla.ini +++ b/administrator/language/en-GB/plg_actionlog_joomla.ini @@ -4,7 +4,7 @@ ; Note : All ini files need to be saved as UTF-8 PLG_ACTIONLOG_JOOMLA="Action Log - Joomla" -PLG_ACTIONLOG_JOOMLA_API="User {username} performed a {verb} on {url}" +PLG_ACTIONLOG_JOOMLA_API="User {username} performed a {verb} on {url}" PLG_ACTIONLOG_JOOMLA_APPLICATION_ADMINISTRATOR="admin" PLG_ACTIONLOG_JOOMLA_APPLICATION_API="api" PLG_ACTIONLOG_JOOMLA_APPLICATION_CLI="cli" @@ -41,32 +41,32 @@ PLG_ACTIONLOG_JOOMLA_TYPE_USER="user" PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP="user group" PLG_ACTIONLOG_JOOMLA_TYPE_USER_NOTE="user note" ; User actions -PLG_ACTIONLOG_JOOMLA_USER_BLOCK="User {username} blocked user {title}" -PLG_ACTIONLOG_JOOMLA_USER_CACHE="User {username} deleted cache group {group}" -PLG_ACTIONLOG_JOOMLA_USER_CHECKIN="User {username} performed a check in to table {table}" -PLG_ACTIONLOG_JOOMLA_USER_LOG="User {username} purged one or more rows from the action log" -PLG_ACTIONLOG_JOOMLA_USER_LOGEXPORT="User {username} exported one or more rows from the action log" -PLG_ACTIONLOG_JOOMLA_USER_LOGGED_IN="User {username} logged in to {app}" -PLG_ACTIONLOG_JOOMLA_USER_LOGGED_OUT="User {username} logged out from {app}" -PLG_ACTIONLOG_JOOMLA_USER_LOGIN_FAILED="A failed attempt was made to login as {username} to {app}" -PLG_ACTIONLOG_JOOMLA_USER_REGISTERED="User {username} registered for an account" -PLG_ACTIONLOG_JOOMLA_USER_REGISTRATION_ACTIVATE="User {username} activated the account" -PLG_ACTIONLOG_JOOMLA_USER_REMIND="User {username} requested a username reminder for their account" -PLG_ACTIONLOG_JOOMLA_USER_RESET_COMPLETE="User {username} completed the password reset for their account" -PLG_ACTIONLOG_JOOMLA_USER_RESET_REQUEST="User {username} requested a password reset for their account" -PLG_ACTIONLOG_JOOMLA_USER_UNBLOCK="User {username} unblocked user {title}" -PLG_ACTIONLOG_JOOMLA_USER_UPDATE="User {username} updated Joomla from {oldversion} to {version}" +PLG_ACTIONLOG_JOOMLA_USER_BLOCK="User {username} blocked user {title}" +PLG_ACTIONLOG_JOOMLA_USER_CACHE="User {username} deleted cache group {group}" +PLG_ACTIONLOG_JOOMLA_USER_CHECKIN="User {username} performed a check in to table {table}" +PLG_ACTIONLOG_JOOMLA_USER_LOG="User {username} purged one or more rows from the action log" +PLG_ACTIONLOG_JOOMLA_USER_LOGEXPORT="User {username} exported one or more rows from the action log" +PLG_ACTIONLOG_JOOMLA_USER_LOGGED_IN="User {username} logged in to {app}" +PLG_ACTIONLOG_JOOMLA_USER_LOGGED_OUT="User {username} logged out from {app}" +PLG_ACTIONLOG_JOOMLA_USER_LOGIN_FAILED="A failed attempt was made to login as {username} to {app}" +PLG_ACTIONLOG_JOOMLA_USER_REGISTERED="User {username} registered for an account" +PLG_ACTIONLOG_JOOMLA_USER_REGISTRATION_ACTIVATE="User {username} activated the account" +PLG_ACTIONLOG_JOOMLA_USER_REMIND="User {username} requested a username reminder for their account" +PLG_ACTIONLOG_JOOMLA_USER_RESET_COMPLETE="User {username} completed the password reset for their account" +PLG_ACTIONLOG_JOOMLA_USER_RESET_REQUEST="User {username} requested a password reset for their account" +PLG_ACTIONLOG_JOOMLA_USER_UNBLOCK="User {username} unblocked user {title}" +PLG_ACTIONLOG_JOOMLA_USER_UPDATE="User {username} updated Joomla from {oldversion} to {version}" ; Automatic updates PLG_ACTIONLOG_JOOMLA_SYSTEM_UPDATE="An automated process updated Joomla from {oldversion} to {version}" ; Config -PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED="User {username} changed settings of the application configuration" -PLG_ACTIONLOG_JOOMLA_COMPONENT_CONFIG_UPDATED="User {username} changed settings of the component {extension_name}" +PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED="User {username} changed settings of the application configuration" +PLG_ACTIONLOG_JOOMLA_COMPONENT_CONFIG_UPDATED="User {username} changed settings of the component {extension_name}" ; Extensions -PLG_ACTIONLOG_JOOMLA_EXTENSION_INSTALLED="User {username} installed the {type} {extension_name}" -PLG_ACTIONLOG_JOOMLA_EXTENSION_UNINSTALLED="User {username} uninstalled the {type} {extension_name}" -PLG_ACTIONLOG_JOOMLA_EXTENSION_UPDATED="User {username} updated the {type} {extension_name}" -PLG_ACTIONLOG_JOOMLA_PLUGIN_INSTALLED="User {username} installed the plugin {extension_name}" +PLG_ACTIONLOG_JOOMLA_EXTENSION_INSTALLED="User {username} installed the {type} {extension_name}" +PLG_ACTIONLOG_JOOMLA_EXTENSION_UNINSTALLED="User {username} uninstalled the {type} {extension_name}" +PLG_ACTIONLOG_JOOMLA_EXTENSION_UPDATED="User {username} updated the {type} {extension_name}" +PLG_ACTIONLOG_JOOMLA_PLUGIN_INSTALLED="User {username} installed the plugin {extension_name}" ; Guided Tours -PLG_ACTIONLOG_JOOMLA_GUIDEDTOURS_TOURCOMPLETED="User {username} completed the tour '{title}'" -PLG_ACTIONLOG_JOOMLA_GUIDEDTOURS_TOURDELAYED="User {username} delayed the tour '{title}'" -PLG_ACTIONLOG_JOOMLA_GUIDEDTOURS_TOURSKIPPED="User {username} skipped the tour '{title}'" +PLG_ACTIONLOG_JOOMLA_GUIDEDTOURS_TOURCOMPLETED="User {username} completed the tour '{title}'" +PLG_ACTIONLOG_JOOMLA_GUIDEDTOURS_TOURDELAYED="User {username} delayed the tour '{title}'" +PLG_ACTIONLOG_JOOMLA_GUIDEDTOURS_TOURSKIPPED="User {username} skipped the tour '{title}'" diff --git a/administrator/language/en-GB/plg_behaviour_compat.ini b/administrator/language/en-GB/plg_behaviour_compat.ini deleted file mode 100644 index 3dfab0d6abd68..0000000000000 --- a/administrator/language/en-GB/plg_behaviour_compat.ini +++ /dev/null @@ -1,13 +0,0 @@ -; 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_BEHAVIOUR_COMPAT="Behaviour - Backward Compatibility" -PLG_COMPAT_FIELD_CLASSES_ALIASES_LABEL="Classes Aliases" -PLG_COMPAT_FIELD_CLASSES_ALIASES_DESCRIPTION="Add class aliases for classes which have been renamed or moved to a namespace." -PLG_COMPAT_FIELD_ES5_ASSETS_DESCRIPTION="Activate this option if your extension requires *.es5 assets which has resulted in an exception. The assets provided are empty but prevent the exception." -PLG_COMPAT_FIELD_ES5_ASSETS_LABEL="ES5 Assets" -PLG_COMPAT_FIELD_REMOVED_ASSETS_DESCRIPTION="Activate this option if your extension requires removed assets which has resulted in an exception. The assets provided are empty but prevent the exception." -PLG_COMPAT_FIELD_REMOVED_ASSETS_LABEL="Removed Assets" -PLG_COMPAT_XML_DESCRIPTION="If you use extensions which are not using the current Joomla Coding standards then this plugin, when enabled, will provide backward compatibility to the prior major version." diff --git a/administrator/language/en-GB/plg_behaviour_compat.sys.ini b/administrator/language/en-GB/plg_behaviour_compat.sys.ini deleted file mode 100644 index 405d5a6c97b0d..0000000000000 --- a/administrator/language/en-GB/plg_behaviour_compat.sys.ini +++ /dev/null @@ -1,7 +0,0 @@ -; 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_BEHAVIOUR_COMPAT="Behaviour - Backward Compatibility" -PLG_COMPAT_XML_DESCRIPTION="Provides backward compatibility to the prior major version." diff --git a/administrator/language/en-GB/plg_behaviour_compat6.ini b/administrator/language/en-GB/plg_behaviour_compat6.ini index d550624dcc1b9..421c8d8d8890a 100644 --- a/administrator/language/en-GB/plg_behaviour_compat6.ini +++ b/administrator/language/en-GB/plg_behaviour_compat6.ini @@ -4,4 +4,10 @@ ; Note : All ini files need to be saved as UTF-8 PLG_BEHAVIOUR_COMPAT6="Behaviour - Backward Compatibility 6" -PLG_COMPAT6_XML_DESCRIPTION="This plugin should be enabled before updating to Joomla 6." +PLG_COMPAT6_FIELD_CLASSES_ALIASES_DESCRIPTION="Add class aliases for classes which have been renamed or moved to a namespace." +PLG_COMPAT6_FIELD_CLASSES_ALIASES_LABEL="Classes Aliases" +PLG_COMPAT6_FIELD_LEGACY_CLASSES_DESCRIPTION="Activate this option if your extension requires previously deprecated classes removed from the current version of Joomla. These removed classes can be found in the folder /plugins/behavior/compat6/classes/." +PLG_COMPAT6_FIELD_LEGACY_CLASSES_LABEL="Include Deprecated Classes" +PLG_COMPAT6_FIELD_REMOVED_ASSETS_DESCRIPTION="Activate this option if your extension requires removed assets which has resulted in an exception. The assets provided are empty but prevent the exception." +PLG_COMPAT6_FIELD_REMOVED_ASSETS_LABEL="Removed Assets" +PLG_COMPAT6_XML_DESCRIPTION="If you use extensions which are not using the current Joomla Coding standards then this plugin, when enabled, will provide backward compatibility to the previous major version, Joomla 5." diff --git a/administrator/language/en-GB/plg_behaviour_compat6.sys.ini b/administrator/language/en-GB/plg_behaviour_compat6.sys.ini index d550624dcc1b9..e412f703d03f9 100644 --- a/administrator/language/en-GB/plg_behaviour_compat6.sys.ini +++ b/administrator/language/en-GB/plg_behaviour_compat6.sys.ini @@ -4,4 +4,4 @@ ; Note : All ini files need to be saved as UTF-8 PLG_BEHAVIOUR_COMPAT6="Behaviour - Backward Compatibility 6" -PLG_COMPAT6_XML_DESCRIPTION="This plugin should be enabled before updating to Joomla 6." +PLG_COMPAT6_XML_DESCRIPTION="If you use extensions which are not using the current Joomla Coding standards then this plugin, when enabled, will provide backward compatibility to the previous major version, Joomla 5." diff --git a/administrator/language/en-GB/plg_captcha_powcaptcha.ini b/administrator/language/en-GB/plg_captcha_powcaptcha.ini new file mode 100644 index 0000000000000..04fe2e6410978 --- /dev/null +++ b/administrator/language/en-GB/plg_captcha_powcaptcha.ini @@ -0,0 +1,39 @@ +; Joomla! Project +; (C) 2025 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_CAPTCHA_POWCAPTCHA="CAPTCHA - Proof of Work" +PLG_CAPTCHA_POWCAPTCHA_XML_DESCRIPTION="This CAPTCHA plugin presents a math task to the user's browser that the browser can solve automatically. It's not supposed to prove that the user is human, but to prove that the user is willing to invest the necessary time to solve the task. Currently based on the Altcha (altcha.org) library." + +; Admin parameters +PLG_CAPTCHA_POWCAPTCHA_AUTOSOLVE_DESC="Should the CAPTCHA be solved automatically, without requiring the user to actively interact with the respective box?" +PLG_CAPTCHA_POWCAPTCHA_AUTOSOLVE_LABEL="Automatic Solution" +PLG_CAPTCHA_POWCAPTCHA_AUTOSOLVE_OFF="Off" +PLG_CAPTCHA_POWCAPTCHA_AUTOSOLVE_ONFOCUS="When CAPTCHA field receives focus" +PLG_CAPTCHA_POWCAPTCHA_AUTOSOLVE_ONLOAD="When page is loaded" +PLG_CAPTCHA_POWCAPTCHA_AUTOSOLVE_ONSUBMIT="When form is submitted" +PLG_CAPTCHA_POWCAPTCHA_DIFFICULTY_DESC="The harder the CAPTCHA gets, the more computing time will be required to solve it." +PLG_CAPTCHA_POWCAPTCHA_DIFFICULTY_LABEL="Difficulty" +PLG_CAPTCHA_POWCAPTCHA_DIFFICULTY_CUSTOM="Custom" +PLG_CAPTCHA_POWCAPTCHA_DIFFICULTY_EASY="Easy" +PLG_CAPTCHA_POWCAPTCHA_DIFFICULTY_HARD="Hard" +PLG_CAPTCHA_POWCAPTCHA_DIFFICULTY_MODERATE="Moderate" +PLG_CAPTCHA_POWCAPTCHA_EXPIRATION_DESC="How long should a solution be valid?" +PLG_CAPTCHA_POWCAPTCHA_EXPIRATION_LABEL="Expiration" +PLG_CAPTCHA_POWCAPTCHA_EXPIRATION_1MIN="1 minute" +PLG_CAPTCHA_POWCAPTCHA_EXPIRATION_5MIN="5 minutes" +PLG_CAPTCHA_POWCAPTCHA_EXPIRATION_10MIN="10 minutes" +PLG_CAPTCHA_POWCAPTCHA_EXPIRATION_1HOUR="1 hour" +PLG_CAPTCHA_POWCAPTCHA_MAXNUMBER_DESC="Defines the maximum number that's used in the task that needs to be solved. The higher the number, the harder to solve." +PLG_CAPTCHA_POWCAPTCHA_MAXNUMBER_LABEL="Maximum Number" + +; Client-side interface customisation +PLG_CAPTCHA_POWCAPTCHA_ARIALINKLABEL="Visit Altcha.org" +PLG_CAPTCHA_POWCAPTCHA_ERROR="Verification failed. Try again later." +PLG_CAPTCHA_POWCAPTCHA_EXPIRED="Verification expired. Try again." +PLG_CAPTCHA_POWCAPTCHA_FOOTER="Protected by ALTCHA" +PLG_CAPTCHA_POWCAPTCHA_LABEL="I'm not a robot" +PLG_CAPTCHA_POWCAPTCHA_VERIFIED="Verified" +PLG_CAPTCHA_POWCAPTCHA_VERIFYING="Verifying..." +PLG_CAPTCHA_POWCAPTCHA_WAITALERT="Verifying... please wait." diff --git a/administrator/language/en-GB/plg_captcha_powcaptcha.sys.ini b/administrator/language/en-GB/plg_captcha_powcaptcha.sys.ini new file mode 100644 index 0000000000000..59b0c44e46fbb --- /dev/null +++ b/administrator/language/en-GB/plg_captcha_powcaptcha.sys.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2025 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_CAPTCHA_POWCAPTCHA="CAPTCHA - Proof of Work" +PLG_CAPTCHA_POWCAPTCHA_XML_DESCRIPTION="This CAPTCHA plugin presents a math task to the user's browser that the browser can solve automatically. It's not supposed to prove that the user is human, but to prove that the user is willing to invest the necessary time to solve the task. Currently based on the Altcha (altcha.org) library." diff --git a/administrator/language/en-GB/plg_content_joomla.ini b/administrator/language/en-GB/plg_content_joomla.ini index 5b818a07e48e6..6ef078e4cc78c 100644 --- a/administrator/language/en-GB/plg_content_joomla.ini +++ b/administrator/language/en-GB/plg_content_joomla.ini @@ -8,6 +8,10 @@ PLG_CONTENT_JOOMLA_FIELD_CHECK_CATEGORIES_DESC="Check that categories are fully PLG_CONTENT_JOOMLA_FIELD_CHECK_CATEGORIES_LABEL="Check Category Deletion" PLG_CONTENT_JOOMLA_FIELD_EMAIL_NEW_FE_DESC="Email users if 'Send email' is on when there is a new article submitted via the Frontend." PLG_CONTENT_JOOMLA_FIELD_EMAIL_NEW_FE_LABEL="Email on New Site Article" +PLG_CONTENT_JOOMLA_MAIL_NEWARTICLE_DESC="Sent when a new article is submitted via frontend." +PLG_CONTENT_JOOMLA_MAIL_NEWARTICLE_TITLE="Content: New Article Submitted" +PLG_CONTENT_JOOMLA_NEW_ARTICLE_BODY="A new Article has been submitted by {NAME} entitled {TITLE}." +PLG_CONTENT_JOOMLA_NEW_ARTICLE_SUBJECT="[{SITENAME}] - New Article Submitted" PLG_CONTENT_JOOMLA_SCHEMA_CONTACT_DESC="When active, generate contact rich snippets from the default data" PLG_CONTENT_JOOMLA_SCHEMA_CONTACT_LABEL="Contact Schema" PLG_CONTENT_JOOMLA_SCHEMA_CONTENT_DESC="When active, generate content rich snippets from the default data" diff --git a/administrator/language/en-GB/plg_content_loadmodule.ini b/administrator/language/en-GB/plg_content_loadmodule.ini index 281917efff08d..fed8665c44efd 100644 --- a/administrator/language/en-GB/plg_content_loadmodule.ini +++ b/administrator/language/en-GB/plg_content_loadmodule.ini @@ -9,6 +9,3 @@ PLG_LOADMODULE_FIELD_VALUE_DIVS="Wrapped by Divs" PLG_LOADMODULE_FIELD_VALUE_RAW="No wrapping (raw output)" PLG_LOADMODULE_FIELD_VALUE_TABLE="Wrapped by table (column)" PLG_LOADMODULE_XML_DESCRIPTION="Within content this plugin loads a Module by ID, Syntax: {loadmoduleid 1} or a Module by position, Syntax: {loadposition user1} or a Module by name, Syntax: {loadmodule mod_login}. Optionally can specify module style and for loadmodule a specific module by title, Syntax: {loadmodule mod_login,module title,style}." -; Deprecated, will be removed with 6.0 -PLG_LOADMODULE_FIELD_VALUE_HORIZONTAL="Wrapped by table (horizontal)" -PLG_LOADMODULE_FIELD_VALUE_MULTIPLEDIVS="Wrapped by Multiple Divs" diff --git a/administrator/language/en-GB/plg_editors_codemirror.ini b/administrator/language/en-GB/plg_editors_codemirror.ini index 7d8715301b6f9..6409f720fc1d0 100644 --- a/administrator/language/en-GB/plg_editors_codemirror.ini +++ b/administrator/language/en-GB/plg_editors_codemirror.ini @@ -3,15 +3,16 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 +PLG_CODEMIRROR_FIELD_ACTIVELINE_LABEL="Highlight Active Line" PLG_CODEMIRROR_FIELD_AUTOCLOSEBRACKET_LABEL="Bracket Completion" PLG_CODEMIRROR_FIELD_CODEFOLDING_LABEL="Code Folding" PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_LABEL="Custom Extensions" PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_METHOD_DESC="Method name, provided by module for extension initialisation. Or multiple, separated by comma. Eg: bracketMatching (from module @codemirror/language)." -; deprecated will be removed in 6.0 +; deprecated will be removed in 7.0 PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_METHOD_DESCR="Method name, provided by module for extension initialisation. Or multiple, separated by comma. Eg: bracketMatching (from module @codemirror/language)." PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_METHOD_LABEL="Initialisation Method(s)" PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_MODULE_DESC="Relative path to the module file, eg: media/my-assets/js/my-codemirror-module.js. Or module name, eg: @codemirror/language." -; deprecated will be removed in 6.0 +; deprecated will be removed in 7.0 PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_MODULE_DESCR="Relative path to the module file, eg: media/my-assets/js/my-codemirror-module.js. Or module name, eg: @codemirror/language." PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_MODULE_LABEL="Module File or Module Name" PLG_CODEMIRROR_FIELD_FULLSCREEN_LABEL="Toggle Fullscreen" @@ -30,26 +31,3 @@ PLG_CODEMIRROR_FIELDSET_TOOLBAR_OPTIONS_LABEL="Toolbar Options" PLG_CODEMIRROR_TOGGLE_FULL_SCREEN="Press %s to toggle Full Screen editing." PLG_CODEMIRROR_XML_DESCRIPTION="This plugin loads the CodeMirror editor." PLG_EDITORS_CODEMIRROR="Editor - CodeMirror" - -; Deprecated, will be removed with 6.0 -PLG_CODEMIRROR_FIELDSET_APPEARANCE_OPTIONS_LABEL="Appearance Options" -PLG_CODEMIRROR_FIELD_ACTIVELINE_COLOR_LABEL="Active Line Colour" -PLG_CODEMIRROR_FIELD_ACTIVELINE_LABEL="Highlight Active Line" -PLG_CODEMIRROR_FIELD_AUTOCLOSETAGS_LABEL="Tag Completion" -PLG_CODEMIRROR_FIELD_FONT_FAMILY_LABEL="Font" -PLG_CODEMIRROR_FIELD_FONT_SIZE_LABEL="Font Size (px)" -PLG_CODEMIRROR_FIELD_HIGHLIGHT_MATCH_COLOR_LABEL="Matching Tag Colour" -PLG_CODEMIRROR_FIELD_KEYMAP_SUBLIME="Sublime Text" -PLG_CODEMIRROR_FIELD_KEYMAP_VIM="Vim" -PLG_CODEMIRROR_FIELD_LINE_HEIGHT_LABEL="Line Height (em)" -PLG_CODEMIRROR_FIELD_MARKERGUTTER_LABEL="Gutters" -PLG_CODEMIRROR_FIELD_MATCHBRACKETS_LABEL="Match Brackets" -PLG_CODEMIRROR_FIELD_MATCHTAGS_LABEL="Match Tags" -PLG_CODEMIRROR_FIELD_PREVIEW_LABEL="Preview" -PLG_CODEMIRROR_FIELD_THEME_LABEL="Theme" -PLG_CODEMIRROR_FIELD_VALUE_FONT_FAMILY_DEFAULT="Browser Default" -PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_DEFAULT="Default" -PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_LABEL="Scrollbar Style" -PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_OVERLAY="Overlay" -PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_SIMPLE="Simple" -PLG_CODEMIRROR_FIELD_VIM_KEYBINDING_LABEL="Vim Keybinding" diff --git a/administrator/language/en-GB/plg_editors_tinymce.ini b/administrator/language/en-GB/plg_editors_tinymce.ini index 6ea1c2bd444f9..ec8ae0b79e6f2 100644 --- a/administrator/language/en-GB/plg_editors_tinymce.ini +++ b/administrator/language/en-GB/plg_editors_tinymce.ini @@ -4,6 +4,12 @@ ; Note : All ini files need to be saved as UTF-8 PLG_EDITORS_TINYMCE="Editor - TinyMCE" +PLG_TINY_ABBREVIATION_DESCRIPTION_LABEL="Abbreviation Description" +PLG_TINY_ABBREVIATION_EDIT="Edit Abbreviation" +PLG_TINY_ABBREVIATION_INSERT="Insert Abbreviation" +PLG_TINY_ABBREVIATION_WARNING_NO_DESCRIPTION="Please enter a description for the abbreviation." +PLG_TINY_ABBREVIATION_WARNING_NO_SELECTION="Please select text or place the cursor inside an abbreviation." +PLG_TINY_ABBREVIATION_WARNING_REMOVE="Cursor is not inside an abbreviation." PLG_TINY_BUILDER="TinyMCE Configuration Builder" PLG_TINY_BUTTON_TOGGLE_EDITOR="Toggle Editor" PLG_TINY_CONFIG_TEXTFILTER_ACL_DESC="If on, the text filter from the Joomla Global Configuration is applied. If off, the filters as defined here are used." @@ -41,8 +47,15 @@ PLG_TINY_FIELD_EXTERNALPLUGINS_DESC="Provide a pair made up of a Plugin Name and PLG_TINY_FIELD_EXTERNALPLUGINS_LABEL="External Plugin URLs" PLG_TINY_FIELD_EXTERNALPLUGINS_NAME_LABEL="Plugin Name" PLG_TINY_FIELD_EXTERNALPLUGINS_PATH_LABEL="Path" +PLG_TINY_FIELD_HTMLHEIGHT_DESC="Set the height of the editor. The default value is 550px. A numeric value can be used or a value with valid CSS units (for example: 50vh or 50rem)." PLG_TINY_FIELD_HTMLHEIGHT_LABEL="HTML Height" +PLG_TINY_FIELD_HTMLWIDTH_DESC="Set the width of the editor. The default value is 100%. A numeric value can be used or a value with valid CSS units (for example: 50vw or 50em)." PLG_TINY_FIELD_HTMLWIDTH_LABEL="HTML Width" +PLG_TINY_FIELD_IMG_CLASS_LIST_LABEL="Class List" +PLG_TINY_FIELD_IMG_CLASS_NAME_LABEL="Name" +PLG_TINY_FIELD_IMG_CLASS_NO_CLASS="No Class Selected" +PLG_TINY_FIELD_IMG_CLASSES_LIST_DESC="Add classes to the image class dropdown in the image dialog." +PLG_TINY_FIELD_IMG_CLASSES_LIST_LABEL="Image Classes List" PLG_TINY_FIELD_LABEL_ADVANCEDPARAMS="Advanced" PLG_TINY_FIELD_LANGCODE_LABEL="Language Code" PLG_TINY_FIELD_LANGSELECT_LABEL="Automatic Language Selection" @@ -59,6 +72,9 @@ PLG_TINY_FIELD_PROHIBITED_LABEL="Prohibited Elements" PLG_TINY_FIELD_RESIZE_HORIZONTAL_LABEL="Horizontal Resizing" PLG_TINY_FIELD_RESIZING_LABEL="Resizing" PLG_TINY_FIELD_SANDBOX_IFRAMES_DESC="This is a security feature that restricts what the iframe can do by setting a sandbox attribute for each iframe. It is recommended to enable this feature for security reasons. Only disable if the iframe is not loading and you're sure that the iframed content is safe." +PLG_TINY_FIELD_SANDBOX_IFRAMES_EXCLUSIONS_LIST_DESC="Additional domain names can be added to be excluded from iframe sandboxing. The current domain and this list of common domains are excluded by default. 'youtube.com', 'youtu.be', 'vimeo.com', 'player.vimeo.com', 'dailymotion.com', 'embed.music.apple.com', 'open.spotify.com', 'giphy.com', 'dai.ly', 'codepen.io'." +PLG_TINY_FIELD_SANDBOX_IFRAMES_EXCLUSIONS_LIST_LABEL="Sandbox Iframe Exclusions List" +PLG_TINY_FIELD_SANDBOX_IFRAMES_EXCLUSION_DOMAIN_LABEL="Domain Name" PLG_TINY_FIELD_SANDBOX_IFRAMES_LABEL="Sandbox Iframes" PLG_TINY_FIELD_SETACCESS_LABEL="Assign this Set to" PLG_TINY_FIELD_SKIN_ADMIN_DARK_LABEL="Administrator Skin (Dark Mode)" @@ -90,6 +106,8 @@ PLG_TINY_FIELD_VALUE_SLIDING="Sliding" PLG_TINY_FIELD_VALUE_WRAP="Wrap" PLG_TINY_FIELD_WORDCOUNT_LABEL="Word Count" PLG_TINY_LEGACY_WARNING="

The TinyMCE Editor Plugin has been updated. Currently it uses your existing configuration. By editing the plugin, you can now assign and customise various layouts to specific user groups.

Warning: when editing the plugin, you will lose all your previous settings!

" +PLG_TINY_LINK_MEDIA="Media" +PLG_TINY_LINK_PICKER_TITLE="Insert Link" PLG_TINY_MENU_CONTAINER="Container" PLG_TINY_SET_PRESET_BUTTON_ADVANCED="Use advanced preset" PLG_TINY_SET_PRESET_BUTTON_MEDIUM="Use medium preset" @@ -98,9 +116,12 @@ PLG_TINY_SET_SOURCE_PANEL_DESCRIPTION="All available menus and buttons.< PLG_TINY_SET_TARGET_PANEL_DESCRIPTION="Use the panel below to customise (drag and drop) TinyMCE for each set." PLG_TINY_SET_TARGET_PANEL_TITLE="TinyMCE Sets" PLG_TINY_SET_TITLE="Set %d" +PLG_TINY_TOOLBAR_BUTTON_ABBREVIATION="Insert/Edit Abbreviation" PLG_TINY_TOOLBAR_BUTTON_FONTSELECT="Font Select" PLG_TINY_TOOLBAR_BUTTON_FONTSIZESELECT="Font Size Select" PLG_TINY_TOOLBAR_BUTTON_FORMATSELECT="Format Select" +PLG_TINY_TOOLBAR_BUTTON_READMORE="Insert Read More" +PLG_TINY_TOOLBAR_BUTTON_REMOVE_ABBREVIATION="Remove Abbreviation" PLG_TINY_TOOLBAR_BUTTON_SEPARATOR="Separator" PLG_TINY_TOOLBAR_BUTTON_STYLESELECT="Style Select" PLG_TINY_XML_DESCRIPTION="TinyMCE is a platform independent web based JavaScript HTML WYSIWYG Editor. Using sets you can configure and customise the editor for every user group." diff --git a/administrator/language/en-GB/plg_fields_list.ini b/administrator/language/en-GB/plg_fields_list.ini index 4208cf647e8e3..abd1f80635d64 100644 --- a/administrator/language/en-GB/plg_fields_list.ini +++ b/administrator/language/en-GB/plg_fields_list.ini @@ -5,8 +5,6 @@ PLG_FIELDS_LIST="Fields - List" PLG_FIELDS_LIST_LABEL="List (%s)" -; The following string is deprecated and will be removed with 6.0 -PLG_FIELDS_LIST_PARAMS_FORM_LAYOUT_FANCY_SELECT="Enhanced select" PLG_FIELDS_LIST_PARAMS_HEADER_DESC="Add a string with no value at the top of the dropdown list eg ' - Select Article - '." PLG_FIELDS_LIST_PARAMS_HEADER_LABEL="Header" PLG_FIELDS_LIST_PARAMS_MULTIPLE_LABEL="Multiple" diff --git a/administrator/language/en-GB/plg_fields_media.ini b/administrator/language/en-GB/plg_fields_media.ini index c53599cd7cb18..de91cccc7f767 100644 --- a/administrator/language/en-GB/plg_fields_media.ini +++ b/administrator/language/en-GB/plg_fields_media.ini @@ -4,9 +4,23 @@ ; Note : All ini files need to be saved as UTF-8 PLG_FIELDS_MEDIA="Fields - Media" +PLG_FIELDS_MEDIA_AUDIO_LABEL="Audio (%s)" +PLG_FIELDS_MEDIA_DOCUMENT_LABEL="Document (%s)" PLG_FIELDS_MEDIA_LABEL="Media (%s)" +PLG_FIELDS_MEDIA_PARAMS_AUTOPLAY_LABEL="Autoplay" +PLG_FIELDS_MEDIA_PARAMS_CONTROLS_LABEL="Show Controls" +PLG_FIELDS_MEDIA_PARAMS_CSS_CLASS_LABEL="CSS Class" PLG_FIELDS_MEDIA_PARAMS_DIRECTORY_LABEL="Directory" PLG_FIELDS_MEDIA_PARAMS_IMAGE_CLASS_LABEL="Image Class" +PLG_FIELDS_MEDIA_PARAMS_LOOP_LABEL="Loop Playback" +PLG_FIELDS_MEDIA_PARAMS_MUTED_LABEL="Muted" +PLG_FIELDS_MEDIA_PARAMS_PRELOAD_AUTO="Preload Automatically" +PLG_FIELDS_MEDIA_PARAMS_PRELOAD_LABEL="Preload" +PLG_FIELDS_MEDIA_PARAMS_PRELOAD_METADATA="Metadata Only" +PLG_FIELDS_MEDIA_PARAMS_PRELOAD_NONE="None" PLG_FIELDS_MEDIA_PARAMS_PREVIEW_INLINE="Inline" PLG_FIELDS_MEDIA_PARAMS_PREVIEW_LABEL="Preview" +PLG_FIELDS_MEDIA_PARAMS_VIDEO_PLAYSINLINE_LABEL="Play Inline" +PLG_FIELDS_MEDIA_PARAMS_VIDEO_POSTER_LABEL="Poster Image" +PLG_FIELDS_MEDIA_VIDEO_LABEL="Video (%s)" PLG_FIELDS_MEDIA_XML_DESCRIPTION="This plugin lets you create new fields of type 'media' in any extensions where custom fields are supported." diff --git a/administrator/language/en-GB/plg_fields_note.ini b/administrator/language/en-GB/plg_fields_note.ini new file mode 100644 index 0000000000000..80296ed76299e --- /dev/null +++ b/administrator/language/en-GB/plg_fields_note.ini @@ -0,0 +1,16 @@ +; Joomla! Project +; (C) 2025 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_FIELDS_NOTE="Fields - Note" +PLG_FIELDS_NOTE_LABEL="Note (%s)" +PLG_FIELDS_NOTE_PARAMS_CLASS_DESC="The class used on the div of the note." +PLG_FIELDS_NOTE_PARAMS_CLASS_LABEL="Note Class" +PLG_FIELDS_NOTE_PARAMS_CLOSE_DESC="This field controls the display of an \"x\" to close the note. It takes a value of 'true' (for alerts) or the value for the data-dismiss of the Bootstrap close icon." +PLG_FIELDS_NOTE_PARAMS_CLOSE_LABEL="Show Close Button" +PLG_FIELDS_NOTE_PARAMS_DESCRIPTION_LABEL="Note Content" +PLG_FIELDS_NOTE_PARAMS_DISPLAY_FRONTEND_LABEL="Display In Frontend" +PLG_FIELDS_NOTE_PARAMS_HEADING_LABEL="Heading Tag" +PLG_FIELDS_NOTE_PARAMS_LABEL_LABEL="Note Heading" +PLG_FIELDS_NOTE_XML_DESCRIPTION="This plugin lets you create new fields of type 'note' in any extensions where custom fields are supported." diff --git a/administrator/language/en-GB/plg_fields_note.sys.ini b/administrator/language/en-GB/plg_fields_note.sys.ini new file mode 100644 index 0000000000000..8a9a7565e6923 --- /dev/null +++ b/administrator/language/en-GB/plg_fields_note.sys.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2025 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_FIELDS_NOTE="Fields - Note" +PLG_FIELDS_NOTE_XML_DESCRIPTION="This plugin lets you create new fields of type 'note' in any extensions where custom fields are supported." diff --git a/administrator/language/en-GB/plg_fields_number.ini b/administrator/language/en-GB/plg_fields_number.ini new file mode 100644 index 0000000000000..5d8e95d46a19c --- /dev/null +++ b/administrator/language/en-GB/plg_fields_number.ini @@ -0,0 +1,19 @@ +; Joomla! Project +; (C) 2025 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_FIELDS_NUMBER="Fields - Number" +PLG_FIELDS_NUMBER_LABEL="Number (%s)" +PLG_FIELDS_NUMBER_PARAMS_CURRENCY_LABEL="Format as Currency" +PLG_FIELDS_NUMBER_PARAMS_DECIMALS_LABEL="Number of Decimals" +PLG_FIELDS_NUMBER_PARAMS_MAX_DESC="Maximum value that can be chosen (only limits the up/down arrows)." +PLG_FIELDS_NUMBER_PARAMS_MAX_LABEL="Maximum" +PLG_FIELDS_NUMBER_PARAMS_MIN_DESC="Minimum value that can be chosen (only limits the up/down arrows)." +PLG_FIELDS_NUMBER_PARAMS_MIN_LABEL="Minimum" +PLG_FIELDS_NUMBER_PARAMS_POSITION_LABEL="Symbol Position" +PLG_FIELDS_NUMBER_PARAMS_POSITION_OPTION_AFTER="After" +PLG_FIELDS_NUMBER_PARAMS_POSITION_OPTION_BEFORE="Before" +PLG_FIELDS_NUMBER_PARAMS_STEP_LABEL="Step Increment" +PLG_FIELDS_NUMBER_PARAMS_SYMBOL_LABEL="Currency Symbol" +PLG_FIELDS_NUMBER_XML_DESCRIPTION="This plugin lets you create new fields of type 'number' in any extensions where custom fields are supported." diff --git a/administrator/language/en-GB/plg_fields_number.sys.ini b/administrator/language/en-GB/plg_fields_number.sys.ini new file mode 100644 index 0000000000000..fb94567cd845e --- /dev/null +++ b/administrator/language/en-GB/plg_fields_number.sys.ini @@ -0,0 +1,7 @@ +; Joomla! Project +; (C) 2025 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_FIELDS_NUMBER="Fields - Number" +PLG_FIELDS_NUMBER_XML_DESCRIPTION="This plugin lets you create new fields of type 'number' in any extensions where custom fields are supported." diff --git a/administrator/language/en-GB/plg_fields_sql.ini b/administrator/language/en-GB/plg_fields_sql.ini index 0354e65bde29b..69403cdbc53c5 100644 --- a/administrator/language/en-GB/plg_fields_sql.ini +++ b/administrator/language/en-GB/plg_fields_sql.ini @@ -6,8 +6,6 @@ PLG_FIELDS_SQL="Fields - SQL" PLG_FIELDS_SQL_CREATE_NOT_POSSIBLE="Only a Super User can create or edit an SQL field!" PLG_FIELDS_SQL_LABEL="SQL (%s)" -; The following string is deprecated and will be removed with 6.0 -PLG_FIELDS_SQL_PARAMS_FORM_LAYOUT_FANCY_SELECT="Enhanced select" PLG_FIELDS_SQL_PARAMS_HEADER_DESC="Add a string with no value at the top of the dropdown list eg ' - Select Article - '." PLG_FIELDS_SQL_PARAMS_HEADER_LABEL="Header" PLG_FIELDS_SQL_PARAMS_MULTIPLE_LABEL="Multiple" diff --git a/administrator/language/en-GB/plg_fields_subform.ini b/administrator/language/en-GB/plg_fields_subform.ini index e920859e598ea..72d787eeee665 100644 --- a/administrator/language/en-GB/plg_fields_subform.ini +++ b/administrator/language/en-GB/plg_fields_subform.ini @@ -7,6 +7,7 @@ PLG_FIELDS_SUBFORM="Fields - Subform" PLG_FIELDS_SUBFORM_LABEL="Subform (%s)" PLG_FIELDS_SUBFORM_PARAMS_CUSTOMFIELD_LABEL="Field" PLG_FIELDS_SUBFORM_PARAMS_EDIT_LAYOUT_OPTION_REPEATABLE_FORM_LABEL="Form" +PLG_FIELDS_SUBFORM_PARAMS_EDIT_LAYOUT_OPTION_REPEATABLE_GRID_LABEL="Form Grid" PLG_FIELDS_SUBFORM_PARAMS_EDIT_LAYOUT_OPTION_REPEATABLE_TABLE_LABEL="Table" PLG_FIELDS_SUBFORM_PARAMS_MAX_ROWS_LABEL="Maximum Rows" PLG_FIELDS_SUBFORM_PARAMS_OPTIONS_LABEL="Fields" diff --git a/administrator/language/en-GB/plg_media-action_crop.ini b/administrator/language/en-GB/plg_media-action_crop.ini index 57c9846ad67a0..9c5c13dd7d82c 100644 --- a/administrator/language/en-GB/plg_media-action_crop.ini +++ b/administrator/language/en-GB/plg_media-action_crop.ini @@ -4,6 +4,8 @@ ; Note : All ini files need to be saved as UTF-8 PLG_MEDIA-ACTION_CROP="Media Action - Crop" +PLG_MEDIA-ACTION_CROP_ASPECT_RATIOS_DESC="Configure custom aspect ratios for the crop tool. Each ratio needs a label (e.g. '16:9'), a value (e.g. '16/9' or '1'), and optionally a group (landscape/portrait)." +PLG_MEDIA-ACTION_CROP_ASPECT_RATIOS_LABEL="Aspect Ratios" PLG_MEDIA-ACTION_CROP_LABEL="Crop" PLG_MEDIA-ACTION_CROP_PARAM_ASPECT="Aspect Ratio" PLG_MEDIA-ACTION_CROP_PARAM_DEFAULT_RATIO="Default aspect ratio" @@ -15,4 +17,11 @@ PLG_MEDIA-ACTION_CROP_PARAM_WIDTH="Width" PLG_MEDIA-ACTION_CROP_PARAM_X="X-Axis" PLG_MEDIA-ACTION_CROP_PARAM_Y="Y-Axis" PLG_MEDIA-ACTION_CROP_QUALITY="Quality" +PLG_MEDIA-ACTION_CROP_RATIO_GROUP_LABEL="Group" +PLG_MEDIA-ACTION_CROP_RATIO_GROUP_DESC="Optionally group this ratio under landscape or portrait" +PLG_MEDIA-ACTION_CROP_RATIO_GROUP_NONE="No group" +PLG_MEDIA-ACTION_CROP_RATIO_LABEL_LABEL="Label" +PLG_MEDIA-ACTION_CROP_RATIO_LABEL_DESC="The label to display for this ratio (e.g. '16:9', '4:3', 'thumbnail', etc.)" +PLG_MEDIA-ACTION_CROP_RATIO_VALUE_LABEL="Value" +PLG_MEDIA-ACTION_CROP_RATIO_VALUE_DESC="The aspect ratio as numerator/denominator or number (e.g. 16/9, 4/3, 1)." PLG_MEDIA-ACTION_CROP_XML_DESCRIPTION="Adds crop functionality for images." diff --git a/administrator/language/en-GB/plg_media-action_resize.ini b/administrator/language/en-GB/plg_media-action_resize.ini index d070e2a631360..67a926e1b8e76 100644 --- a/administrator/language/en-GB/plg_media-action_resize.ini +++ b/administrator/language/en-GB/plg_media-action_resize.ini @@ -4,7 +4,11 @@ ; Note : All ini files need to be saved as UTF-8 PLG_MEDIA-ACTION_RESIZE="Media Action - Resize" +PLG_MEDIA-ACTION_RESIZE_AUTOMATIC_DESC="Settings for automatic processing when images are created or uploaded to the server." +PLG_MEDIA-ACTION_RESIZE_AUTOMATIC_LABEL="Automatic Processing" +; The following string is deprecated and will be removed with 8.0 PLG_MEDIA-ACTION_RESIZE_BATCH_DESC="Settings for server side actions when images are created." +; The following string is deprecated and will be removed with 8.0 PLG_MEDIA-ACTION_RESIZE_BATCH_LABEL="Batch Settings" PLG_MEDIA-ACTION_RESIZE_BATCH_MAX_HEIGHT_LABEL="Image Max Height" PLG_MEDIA-ACTION_RESIZE_BATCH_MAX_WIDTH_LABEL="Image Max Width" diff --git a/administrator/language/en-GB/plg_quickicon_eos.ini b/administrator/language/en-GB/plg_quickicon_eos.ini index 64e44bf0bda4a..48de33159f95b 100644 --- a/administrator/language/en-GB/plg_quickicon_eos.ini +++ b/administrator/language/en-GB/plg_quickicon_eos.ini @@ -3,11 +3,11 @@ ; 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 5 End Of Support Notification" -PLG_QUICKICON_EOS_MESSAGE_ERROR_SUPPORT_ENDED="

Support has ended for your version of Joomla 5. Upgrade to Joomla 6 as soon as possible.

" -PLG_QUICKICON_EOS_MESSAGE_INFO_01="

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

" -PLG_QUICKICON_EOS_MESSAGE_INFO_02="

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

" -PLG_QUICKICON_EOS_MESSAGE_WARNING_SECURITY_ONLY="

Joomla 5 has entered security only mode. Support ends %1$s. Start planning to upgrade to Joomla 6 today.

" -PLG_QUICKICON_EOS_MESSAGE_WARNING_SUPPORT_ENDING="

Support ends on %1$s for Joomla 5 Upgrade to Joomla 6 as soon as possible.

" +PLG_QUICKICON_EOS="Quick Icon - Joomla 6 End Of Support Notification" +PLG_QUICKICON_EOS_MESSAGE_ERROR_SUPPORT_ENDED="

Support has ended for your version of Joomla 6. Upgrade to Joomla 7 as soon as possible.

" +PLG_QUICKICON_EOS_MESSAGE_INFO_01="

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

" +PLG_QUICKICON_EOS_MESSAGE_INFO_02="

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

" +PLG_QUICKICON_EOS_MESSAGE_WARNING_SECURITY_ONLY="

Joomla 6 has entered security only mode. Support ends %1$s. Start planning to upgrade to Joomla 7 today.

" +PLG_QUICKICON_EOS_MESSAGE_WARNING_SUPPORT_ENDING="

Support ends on %1$s for Joomla 6 Upgrade to Joomla 7 as soon as possible.

" 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 5 and notifies you when visiting the Control Panel page." +PLG_QUICKICON_EOS_XML_DESCRIPTION="Checks for the end of support status of Joomla 6 and notifies you when visiting the Control Panel page." diff --git a/administrator/language/en-GB/plg_quickicon_eos.sys.ini b/administrator/language/en-GB/plg_quickicon_eos.sys.ini index 78cfc1cff5fdb..b2b3febed2225 100644 --- a/administrator/language/en-GB/plg_quickicon_eos.sys.ini +++ b/administrator/language/en-GB/plg_quickicon_eos.sys.ini @@ -3,5 +3,5 @@ ; 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 5 End Of Support Notification" -PLG_QUICKICON_EOS_XML_DESCRIPTION="Checks for the end of support status of Joomla 5 and notifies you when visiting the Control Panel page." +PLG_QUICKICON_EOS="Quick Icon - Joomla 6 End Of Support Notification" +PLG_QUICKICON_EOS_XML_DESCRIPTION="Checks for the end of support status of Joomla 6 and notifies you when visiting the Control Panel page." diff --git a/administrator/language/en-GB/plg_quickicon_extensionupdate.ini b/administrator/language/en-GB/plg_quickicon_extensionupdate.ini index 84398346ff8aa..4b123d0dba781 100644 --- a/administrator/language/en-GB/plg_quickicon_extensionupdate.ini +++ b/administrator/language/en-GB/plg_quickicon_extensionupdate.ini @@ -9,5 +9,6 @@ PLG_QUICKICON_EXTENSIONUPDATE_ERROR="Unknown extensions …" PLG_QUICKICON_EXTENSIONUPDATE_GROUP_DESC="The group of this plugin (this value is compared with the group value used in Quick Icons modules to inject icons)." PLG_QUICKICON_EXTENSIONUPDATE_GROUP_LABEL="Group" PLG_QUICKICON_EXTENSIONUPDATE_UPDATEFOUND="Updates are available! %s" +PLG_QUICKICON_EXTENSIONUPDATE_SECURITY_UPDATEFOUND="* Security update is available for %s!" PLG_QUICKICON_EXTENSIONUPDATE_UPTODATE="Extensions are up to date." PLG_QUICKICON_EXTENSIONUPDATE_XML_DESCRIPTION="Checks for updates of your installed third-party extensions and notifies you when you visit the Home Dashboard page." diff --git a/administrator/language/en-GB/plg_sampledata_blog.ini b/administrator/language/en-GB/plg_sampledata_blog.ini index f74353b67259c..63e84e2715047 100644 --- a/administrator/language/en-GB/plg_sampledata_blog.ini +++ b/administrator/language/en-GB/plg_sampledata_blog.ini @@ -10,7 +10,7 @@ PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_0_FULLTEXT="" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_0_INTROTEXT="

This tells you a bit about this blog and the person who writes it.

When you are logged in you will be able to edit this page by selecting the edit icon.

" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_0_TITLE="About" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_1_FULLTEXT="" -PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_1_INTROTEXT="

Here are some basic tips for working on your site.

  • Joomla! has a 'front end' that you are looking at now and an 'administrator' or 'back end' which is where you do the more advanced work of creating your site such as setting up the menus and deciding what modules to show. You need to login to the administrator separately using the same user name and password that you used to login to this part of the site.
  • One of the first things you will probably want to do is change the site title and tag line and to add a logo. To do this select the Template Settings link in the menu which is visible if you log in. To change your site description, browser title, default email and other items, select Site Settings. More advanced configuration options are available in the administrator.
  • To totally change the look of your site you will probably want to install a new template. Go to System, select Install - Extensions from the list and the extension installer will open. There are many free and commercial templates available for Joomla.
  • As you have already seen, you can control who can see different parts of you site. When you work with modules and articles, setting the Access level to Registered will mean that only logged in users can see them.
  • When you create a new article or other kind of content you also can save it as Published or Unpublished. If it is Unpublished site visitors will not be able to see it but you will.
  • You can learn much more about working with Joomla from the Joomla documentation site and get help from other users at the Joomla forums. In the administrator there are help buttons on every page that provide detailed information about the functions on that page.
" +PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_1_INTROTEXT="

Here are some basic tips for working on your site.

  • Joomla! has a 'front end' that you are looking at now and an 'administrator' or 'back end' which is where you do the more advanced work of creating your site such as setting up the menus and deciding what modules to show. You need to login to the administrator separately using the same user name and password that you used to login to this part of the site.
  • One of the first things you will probably want to do is change the site title and tag line and to add a logo. To do this select the Template Settings link in the menu which is visible if you log in. To change your site description, browser title, default email and other items, select Site Settings. More advanced configuration options are available in the administrator.
  • To totally change the look of your site you will probably want to install a new template. Go to System, select Install - Extensions from the list and the extension installer will open. There are many free and commercial templates available for Joomla.
  • As you have already seen, you can control who can see different parts of you site. When you work with modules and articles, setting the Access level to Registered will mean that only logged in users can see them.
  • When you create a new article or other kind of content you also can save it as Published or Unpublished. If it is Unpublished site visitors will not be able to see it but you will.
  • You can learn much more about working with Joomla from the Joomla documentation site and get help from other users at the Joomla forums. In the administrator there are help buttons on every page that provide detailed information about the functions on that page.
" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_1_TITLE="Working on Your Site" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_10_FULLTEXT="" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_10_INTROTEXT="

Colour Scheme

secondary primary info success warning danger

text-secondary text-primary text-info text-success text-warning text-danger

Typography (h1)

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex. (p)

Lorem Ipsum Dolor Sit Amet (h2)

Lorem ipsum dolor sit amet, consectetuer adipiscing elit (strong), sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex. (p)

Lorem Ipsum Dolor Sit Amet (h3)

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex. (p)

Lorem Ipsum Dolor Sit Amet (h4)

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex. (p)

Lorem Ipsum Dolor Sit Amet (h5)

Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex. (p)

Lorem ipsum dolor (a)

Lists

(ol)(li)

  1. Lorem ipsum dolor sit amet consectetur
  2. Lorem ipsum dolor sit amet consectetur

(ul)(li)

  • Lorem ipsum dolor sit amet consectetur
  • Lorem ipsum dolor sit amet consectetur

Displays

Lorem (display-1)

Lorem (display-2)

Lorem ipsum (display-3)

Lorem ipsum (display-4)

Lorem ipsum arma virumque cano (lead)

" @@ -37,7 +37,7 @@ PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_7_FULLTEXT="

Uurnip greens yarr PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_7_INTROTEXT="

We love Joomla to the moon and back!

Thank you to all volunteers who have contributed!

" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_7_TITLE="Love" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_8_FULLTEXT="

Cupcake ipsum dolor. Sit amet cotton candy ice cream sesame snaps cake marshmallow powder. Ice cream chocolate cake marshmallow halvah bonbon. Dragée carrot cake danish candy muffin brownie. Candy sugar plum ice cream chupa chups macaroon tiramisu soufflé oat cake. Topping cheesecake lollipop gummi bears icing sweet roll donut liquorice. Pie jelly-o candy donut oat cake cotton candy.

" -PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_8_INTROTEXT="

We proudly present Joomla Version 5!

Learn more about workflows in Joomla.

" +PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_8_INTROTEXT="

We proudly present Joomla Version 6!

Learn more about workflows in Joomla.

" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_8_TITLE="Joomla" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_9_FIELD_0="Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua." PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_9_FULLTEXT="" @@ -127,14 +127,14 @@ PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_4_TITLE="Latest Posts" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_5_TITLE="Older Posts" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_6_TITLE="Bottom Menu" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_7_TITLE="Search" -PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_8_CONTENT="

Welcome to Joomla on Cassiopeia!

You have chosen one of the most powerful CMS Systems in the world.

Cassiopeia is the multi-purpose frontend template for Joomla 5.

Typography »

" +PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_8_CONTENT="

Welcome to Joomla on Cassiopeia!

You have chosen one of the most powerful CMS Systems in the world.

Cassiopeia is the multi-purpose frontend template for Joomla.

Typography »

" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_8_TITLE="Image" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_9_TITLE="Popular Tags" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_NEWSFEEDS_TITLE="My Blog" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_TAG_0_TITLE="Millions" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_TAG_1_TITLE="Worldwide" PLG_SAMPLEDATA_BLOG_SAMPLEDATA_TAG_2_TITLE="Love" -PLG_SAMPLEDATA_BLOG_SAMPLEDATA_TAG_3_TITLE="Joomla 5" +PLG_SAMPLEDATA_BLOG_SAMPLEDATA_TAG_3_TITLE="Joomla 6" PLG_SAMPLEDATA_BLOG_STEP1_SUCCESS="Step 1: Tags, Articles, Fields and Workflow done!" PLG_SAMPLEDATA_BLOG_STEP2_SUCCESS="Step 2: Menus done!" PLG_SAMPLEDATA_BLOG_STEP3_SUCCESS="Step 3: Modules done!" diff --git a/administrator/language/en-GB/plg_system_actionlogs.ini b/administrator/language/en-GB/plg_system_actionlogs.ini index 1f0ec95576f52..44b614c314bf1 100644 --- a/administrator/language/en-GB/plg_system_actionlogs.ini +++ b/administrator/language/en-GB/plg_system_actionlogs.ini @@ -13,14 +13,10 @@ PLG_SYSTEM_ACTIONLOGS_NOTIFICATIONS="Email Notifications" PLG_SYSTEM_ACTIONLOGS_OPTIONS="User Actions Log Options" PLG_SYSTEM_ACTIONLOGS_XML_DESCRIPTION="Records the actions of users on the site so they can be reviewed if required." ; Common content type log messages -PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED="User {username} added new {type} {title}" -PLG_SYSTEM_ACTIONLOGS_CONTENT_ARCHIVED="User {username} archived the {type} {title}" -PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED="User {username} deleted the {type} {title}" -PLG_SYSTEM_ACTIONLOGS_CONTENT_PUBLISHED="User {username} published the {type} {title}" -PLG_SYSTEM_ACTIONLOGS_CONTENT_TRASHED="User {username} trashed the {type} {title}" -PLG_SYSTEM_ACTIONLOGS_CONTENT_UNPUBLISHED="User {username} unpublished the {type} {title}" -PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED="User {username} updated the {type} {title}" - -; All the following strings are deprecated and will be removed with 6.0 -PLG_SYSTEM_ACTIONLOGS_LOG_DELETE_PERIOD="Days to delete logs after" -PLG_SYSTEM_ACTIONLOGS_LOG_DELETE_PERIOD_DESC="Enter 0 if you don't want to delete the logs." +PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED="User {username} added new {type} {title}" +PLG_SYSTEM_ACTIONLOGS_CONTENT_ARCHIVED="User {username} archived the {type} {title}" +PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED="User {username} deleted the {type} {title}" +PLG_SYSTEM_ACTIONLOGS_CONTENT_PUBLISHED="User {username} published the {type} {title}" +PLG_SYSTEM_ACTIONLOGS_CONTENT_TRASHED="User {username} trashed the {type} {title}" +PLG_SYSTEM_ACTIONLOGS_CONTENT_UNPUBLISHED="User {username} unpublished the {type} {title}" +PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED="User {username} updated the {type} {title}" diff --git a/administrator/language/en-GB/plg_system_httpheaders.ini b/administrator/language/en-GB/plg_system_httpheaders.ini index 3c291db2b175b..45f986259144e 100644 --- a/administrator/language/en-GB/plg_system_httpheaders.ini +++ b/administrator/language/en-GB/plg_system_httpheaders.ini @@ -37,7 +37,7 @@ PLG_SYSTEM_HTTPHEADERS_HSTS_PRELOAD_NOTE_DESC="HSTS means that your domain can n PLG_SYSTEM_HTTPHEADERS_HSTS_SUBDOMAINS="Also for subdomains" PLG_SYSTEM_HTTPHEADERS_HSTS_SUBDOMAINS_DESC="HSTS should also be enabled for subdomains usually the subdomain 'www' is taken into account when creating the SSL certificate. If further subdomains are used, please note that they are also provided with a valid SSL certificate." PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_ACTION="Enable default security headers" -PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_BODY="

Joomla! comes with a built-in set of tools that help you to handle http security headers. These headers help your browser for example to protect your website from XSS and Clickjacking attacks.

You can find more details in the HTTP Header Management Tutorial in the Joomla! Documentation.

" +PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_BODY="

Joomla! comes with a built-in set of tools that help you to handle http security headers. These headers help your browser for example to protect your website from XSS and Clickjacking attacks.

You can find more details in the HTTP Header Management Tutorial in the Joomla! Documentation.

" PLG_SYSTEM_HTTPHEADERS_POSTINSTALL_INTRODUCTION_TITLE="HTTP Security Headers" PLG_SYSTEM_HTTPHEADERS_REFERRERPOLICY="Referrer-Policy" ; Do not translate PLG_SYSTEM_HTTPHEADERS_XFRAMEOPTIONS="X-Frame-Options" ; Do not translate diff --git a/administrator/language/en-GB/plg_system_jooa11y.ini b/administrator/language/en-GB/plg_system_jooa11y.ini index d4965027c6ed0..bb5aab27ca20e 100644 --- a/administrator/language/en-GB/plg_system_jooa11y.ini +++ b/administrator/language/en-GB/plg_system_jooa11y.ini @@ -19,146 +19,3 @@ PLG_SYSTEM_JOOA11Y_FIELD_SHOW_ALWAYS_DESC="Load the accessibility checker on all PLG_SYSTEM_JOOA11Y_KEY="Key" PLG_SYSTEM_JOOA11Y_VALUE="Value" PLG_SYSTEM_JOOA11Y_XML_DESCRIPTION="The Joomla Accessibility Checker visually highlights common accessibility and usability issues. Geared towards content authors, the plugin identifies errors or warnings and provides guidance on how to fix them. Please be aware that this plugin does not offer an exhaustive analysis of your website, nor does it automatically ensure your website's accessibility. It's important to select a template that is inherently accessible to ensure your site meets accessibility standards." - -; All the following strings are deprecated and will be removed with 6.0 -PLG_SYSTEM_JOOA11Y_ALERT_CLOSE="Close" -PLG_SYSTEM_JOOA11Y_ALERT_TEXT="Alert" -PLG_SYSTEM_JOOA11Y_AVG_WORD_PER_SENTENCE="Average words per sentence:" -PLG_SYSTEM_JOOA11Y_COMPLEX_WORDS="Complex words:" -PLG_SYSTEM_JOOA11Y_CONTAINER_LABEL="Accessibility Checker" -PLG_SYSTEM_JOOA11Y_CONTRAST="Contrast" -PLG_SYSTEM_JOOA11Y_CONTRAST_ERROR_INPUT_MESSAGE="The text within this input does not have enough contrast with the background. The contrast ratio should be at least 4.5:1 for normal text and 3:1 for large text." -PLG_SYSTEM_JOOA11Y_CONTRAST_ERROR_INPUT_MESSAGE_INFO="The contrast ratio is %(cratio)." -PLG_SYSTEM_JOOA11Y_CONTRAST_ERROR_MESSAGE="This text does not have enough contrast with the background. The contrast ratio should be at least 4.5:1 for normal text and 3:1 for large text." -PLG_SYSTEM_JOOA11Y_CONTRAST_ERROR_MESSAGE_INFO="The contrast ratio is %(cratio) for the following text: %(nodetext)" -PLG_SYSTEM_JOOA11Y_CONTRAST_WARNING_MESSAGE="The contrast of this text is unknown and needs to be manually reviewed. Ensure the text and the background have strong contrasting colours. The contrast ratio should be at least 4.5:1 for normal text and 3:1 for large text." -PLG_SYSTEM_JOOA11Y_CONTRAST_WARNING_MESSAGE_INFO="Please review contrast of the following text:
%(nodetext)" -PLG_SYSTEM_JOOA11Y_DARK_MODE="Dark Mode" -PLG_SYSTEM_JOOA11Y_DIFFICULT_READABILITY="Difficult" -PLG_SYSTEM_JOOA11Y_EMBED_AUDIO="Please ensure to provide a transcript for all podcasts. Providing transcripts for audio content is a mandatory Level A requirement. Transcripts support people who are D/deaf or hard-of-hearing, but can benefit everyone. Consider placing the transcript below or within an accordion panel." -PLG_SYSTEM_JOOA11Y_EMBED_GENERAL_WARNING="Unable to check embedded content. Please make sure that images have alt text, videos have captions, text has sufficient contrast, and interactive components are keyboard accessible." -PLG_SYSTEM_JOOA11Y_EMBED_MISSING_TITLE="Embedded content requires an accessible name that describes its contents. Please provide a unique title or aria-label attribute on the iframe element. Learn more about iFrames." -PLG_SYSTEM_JOOA11Y_EMBED_VIDEO="Please ensure all videos have closed captioning. Providing captions for all audio and video content is a mandatory Level A requirement. Captions support people who are D/deaf or hard-of-hearing." -PLG_SYSTEM_JOOA11Y_ERROR="Error" -PLG_SYSTEM_JOOA11Y_FAIRLY_DIFFICULT_READABILITY="Fairly difficult" -PLG_SYSTEM_JOOA11Y_FIELD_ADDITIONAL_CHECKS="Additional Checks Always On" -PLG_SYSTEM_JOOA11Y_FIELD_ADDITIONAL_CHECKS_DESC="Enabling this option will visually hide the toggle switches for Form Labels, Contrast, Links (Advanced) in the Settings panel." -PLG_SYSTEM_JOOA11Y_FIELD_COLOUR_FILTER="Colour Filter" -PLG_SYSTEM_JOOA11Y_FIELD_COLOUR_FILTER_DESC="Show Colour Filter toggle in Settings panel. Colour filters help identify colour combinations that may be difficult for people to distinguish." -PLG_SYSTEM_JOOA11Y_FIELD_CONTRAST="Contrast" -PLG_SYSTEM_JOOA11Y_FIELD_CONTRAST_DESC="Show Contrast toggle in Settings panel. Check for WCAG 2.0 Level AA contrast issues between foreground text and background elements." -PLG_SYSTEM_JOOA11Y_FIELD_FORM_LABELS="Form Labels" -PLG_SYSTEM_JOOA11Y_FIELD_FORM_LABELS_DESC="Show Form Labels toggle in Settings panel. Check for form inputs missing a corresponding label. Not necessarily a content author issue, and usually not an issue when using a reputable, accessible forms plugin." -PLG_SYSTEM_JOOA11Y_FIELD_LINKS_ADVANCED="Links (Advanced)" -PLG_SYSTEM_JOOA11Y_FIELD_LINKS_ADVANCED_DESC="Show Links (Advanced) toggle in Settings panel. Check for additional issues such as: links that open in a new tab without warning, have identical names but different purpose, or points to a PDF and other files without warning." -PLG_SYSTEM_JOOA11Y_FIELD_WEB_COMPONENTS="Web Components to Check" -PLG_SYSTEM_JOOA11Y_FIELD_WEB_COMPONENTS_DESC="Provide a list of all known web components or containers with an open shadow DOM." -PLG_SYSTEM_JOOA11Y_FILE_TYPE_WARNING="Link points to a PDF or downloadable file (e.g. MP3, Zip, Word Doc) without warning. Indicate the file type within the link text. If it is a large file, consider including the file size." -PLG_SYSTEM_JOOA11Y_FILE_TYPE_WARNING_TIP="Example: Executive Report (PDF, 3MB)" -PLG_SYSTEM_JOOA11Y_FORM_LABELS="Form labels" -PLG_SYSTEM_JOOA11Y_GOOD="Good" -PLG_SYSTEM_JOOA11Y_GOOD_READABILITY="Good" -PLG_SYSTEM_JOOA11Y_HEADING_EMPTY="Empty heading found! To fix, delete this line or change its format from Heading %(level) to Normal or Paragraph." -PLG_SYSTEM_JOOA11Y_HEADING_EMPTY_WITH_IMAGE="Heading has no text, but contains an image. If this is not a heading, change its format from Heading %(level) to Normal or Paragraph. Otherwise, please add alt text to the image if it is not decorative." -PLG_SYSTEM_JOOA11Y_HEADING_FIRST="The first heading on a page should usually be a Heading 1 or Heading 2. Heading 1 should be the start of the main content section, and is the main heading that describes the overall purpose of the page. Learn more about Heading Structure." -PLG_SYSTEM_JOOA11Y_HEADING_LONG="Heading is long! Headings should be used to organize content and convey structure. They should be brief, informative, and unique. Please keep headings less than 160 characters (no more than a sentence)." -PLG_SYSTEM_JOOA11Y_HEADING_LONG_INFO="Character Count: %(headingLength)." -PLG_SYSTEM_JOOA11Y_HEADING_MISSING_ONE="Missing Heading 1. Heading 1 should be the start of the main content area, and is the main heading that describes the overall purpose of the page. Learn more about Heading Structure." -PLG_SYSTEM_JOOA11Y_HEADING_NON_CONSECUTIVE_LEVEL="Non-consecutive heading level used. Headings should never skip levels, or go from Heading %(prevLevel) to Heading %(level)." -PLG_SYSTEM_JOOA11Y_HIDE_OUTLINE="Hide Outline" -PLG_SYSTEM_JOOA11Y_HIDE_SETTINGS="Hide Settings" -PLG_SYSTEM_JOOA11Y_HYPERLINK_ALT_LENGTH_MESSAGE="Alt text description on a linked image is too long. The alt text on linked images should describe where the link takes you, not a literal description of the image. Consider using the title of the page it links to as the alt text." -PLG_SYSTEM_JOOA11Y_HYPERLINK_ALT_LENGTH_MESSAGE_INFO="The alt text is %(altLength) characters: %(altText)" -PLG_SYSTEM_JOOA11Y_IMAGE_FIGURE_DECORATIVE="Image is marked as decorative and will be ignored by assistive technology." -PLG_SYSTEM_JOOA11Y_IMAGE_FIGURE_DECORATIVE_INFO="Although a caption was provided, the image should also have alt text in most cases.
  • The alt text should provide a concise description of what is in the image.
  • The caption should usually provide context to relate the image back to the surrounding content, or give attention to a particular piece of information.
Learn more: alt versus figcaption." -PLG_SYSTEM_JOOA11Y_IMAGE_FIGURE_DUPLICATE_ALT="Do not use the exact same words for both the alt and caption text. Screen readers will announce the information twice." -PLG_SYSTEM_JOOA11Y_LABELS_ARIA_LABEL_INPUT_MESSAGE="Input has an accessible name, although please ensure there is a visible label too." -PLG_SYSTEM_JOOA11Y_LABELS_ARIA_LABEL_INPUT_MESSAGE_INFO="The accessible name for this input is: %(ariaLabel)" -PLG_SYSTEM_JOOA11Y_LABELS_INPUT_RESET_MESSAGE="Reset buttons should not be used unless specifically needed because they are easy to activate by mistake." -PLG_SYSTEM_JOOA11Y_LABELS_INPUT_RESET_MESSAGE_TIP="Tip! Learn why Reset and Cancel buttons pose usability issues." -PLG_SYSTEM_JOOA11Y_LABELS_MISSING_IMAGE_INPUT_MESSAGE="Image button is missing alt text. Please add alt text to provide an accessible name. For example: Search or Submit." -PLG_SYSTEM_JOOA11Y_LABELS_MISSING_LABEL_MESSAGE="There is no label associated with this input. Please add an id to this input, and add a matching for attribute to the label." -PLG_SYSTEM_JOOA11Y_LABELS_NO_FOR_ATTRIBUTE_MESSAGE="There is no label associated with this input. Add a for attribute to the label that matches the id of this input." -PLG_SYSTEM_JOOA11Y_LABELS_NO_FOR_ATTRIBUTE_MESSAGE_INFO="The ID for this input is: id="%(t)"" -PLG_SYSTEM_JOOA11Y_LANG_CODE="en" -PLG_SYSTEM_JOOA11Y_LINK_ALT_HAS_BAD_WORD_MESSAGE="File extension within the alt text found. If the image conveys a story, mood, or important information - be sure to describe the image." -PLG_SYSTEM_JOOA11Y_LINK_ALT_HAS_BAD_WORD_MESSAGE_INFO="Remove: %(error).
The alt text for this image is: %(altText)" -PLG_SYSTEM_JOOA11Y_LINK_ALT_HAS_SUS_WORD_MESSAGE="Assistive technologies already indicate that this is an image, so "%(error)" or "%(error) of" may be redundant." -PLG_SYSTEM_JOOA11Y_LINK_ALT_HAS_SUS_WORD_MESSAGE_INFO="The alt text for this image is: %(altText)" -PLG_SYSTEM_JOOA11Y_LINK_ALT_PLACEHOLDER_MESSAGE="Non-descript or placeholder alt text found. Replace the following alt text with something more meaningful: %(altText)." -PLG_SYSTEM_JOOA11Y_LINK_ALT_TOO_LONG_MESSAGE="Alt text description is too long. Alt text should be concise, yet meaningful like a tweet (around 100 characters). If this is a complex image or a graph, consider putting the long description of the image in the text below or an accordion component." -PLG_SYSTEM_JOOA11Y_LINK_ALT_TOO_LONG_MESSAGE_INFO="The alt text is %(altLength) characters: %(altText)" -PLG_SYSTEM_JOOA11Y_LINK_ANCHOR_LINK_AND_ALT_MESSAGE="Image link contains both alt text and surrounding link text. If this image is decorative and is being used as a functional link to another page, consider marking the image as decorative - the surrounding link text should suffice." -PLG_SYSTEM_JOOA11Y_LINK_ANCHOR_LINK_AND_ALT_MESSAGE_INFO="Alt text: %(altText)" -PLG_SYSTEM_JOOA11Y_LINK_BEST_PRACTICES="Consider replacing the link text: %(error)" -PLG_SYSTEM_JOOA11Y_LINK_BEST_PRACTICES_DETAILS="
  • "Click here" places focus on mouse mechanics, when many people do not use a mouse or may be viewing this website on a mobile device. Consider using a different verb that relates to the task.
  • Avoid using HTML symbols as call to actions unless they are hidden to assistive technologies.
" -PLG_SYSTEM_JOOA11Y_LINK_DECORATIVE_MESSAGE="Image is marked as decorative and will be ignored by assistive technology. If the image conveys a story, mood or important information - be sure to add alt text." -PLG_SYSTEM_JOOA11Y_LINK_EMPTY="Remove empty links without any text." -PLG_SYSTEM_JOOA11Y_LINK_EMPTY_LINK_NO_LABEL="Link does not have discernable text that is visible to screen readers and other assistive technology. To fix:
  • Add some concise text that describes where the link takes you.
  • If it is an icon link or SVG it is likely missing a descriptive label.
  • If you think this link is an error due to a copy/paste bug, consider deleting it.
" -PLG_SYSTEM_JOOA11Y_LINK_HYPERLINKED_IMAGE_ARIA_HIDDEN="Link around image has aria-hidden="true" but is still keyboard focusable. If you are intending to hide a redundant or duplicate link, add tabindex="-1" as well." -PLG_SYSTEM_JOOA11Y_LINK_IDENTICAL_NAME="Link has identical text as another link, although it points to a different page. Multiple links with the same text may cause confusion for people who use screen readers." -PLG_SYSTEM_JOOA11Y_LINK_IDENTICAL_NAME_TIP="Consider making the following link more descriptive to help distinguish it from other links: %(linkText)" -PLG_SYSTEM_JOOA11Y_LINK_IMAGE_BAD_ALT_MESSAGE="File extension within the alt text found. Ensure the alt text describes the destination of the link, not a literal description of the image. Remove: %(error)." -PLG_SYSTEM_JOOA11Y_LINK_IMAGE_BAD_ALT_MESSAGE_INFO="The alt text for this image is: %(altText)" -PLG_SYSTEM_JOOA11Y_LINK_IMAGE_LINK_ALT_TEXT_MESSAGE="Image link contains alt text, although please ensure alt text describes the destination page. Consider using the title of the page it links to as the alt text. Does the alt text describe where the link takes you?" -PLG_SYSTEM_JOOA11Y_LINK_IMAGE_LINK_ALT_TEXT_MESSAGE_INFO="Alt text: %(altText)" -PLG_SYSTEM_JOOA11Y_LINK_IMAGE_LINK_NULL_ALT_NO_TEXT_MESSAGE="Image within link is marked as decorative and there is no link text. Please add alt text to the image that describes the destination of the link." -PLG_SYSTEM_JOOA11Y_LINK_IMAGE_PLACEHOLDER_ALT_MESSAGE="Non-descript or placeholder alt text within a linked image found. Ensure the alt text describes the destination of the link, not a literal description of the image. Replace the following alt text: %(altText)." -PLG_SYSTEM_JOOA11Y_LINK_IMAGE_SUS_ALT_MESSAGE="Assistive technologies already indicate that this is an image, so "%(error)" or "%(error) of" may be redundant. Ensure the alt text describes the destination of the link, not a literal description of the image." -PLG_SYSTEM_JOOA11Y_LINK_IMAGE_SUS_ALT_MESSAGE_INFO="The alt text for this image is: %(altText)." -PLG_SYSTEM_JOOA11Y_LINK_LABEL="The descriptive label for this link is: %(linkText)" -PLG_SYSTEM_JOOA11Y_LINK_LINK_HAS_ALT_MESSAGE="Image is marked as decorative, although the link is using the surrounding text as a descriptive label." -PLG_SYSTEM_JOOA11Y_LINK_PASS_ALT="The alt text for this image is: %(altText)" -PLG_SYSTEM_JOOA11Y_LINK_STOPWORD="Link text may not be descriptive enough out of context: %(error)" -PLG_SYSTEM_JOOA11Y_LINK_STOPWORD_TIP="Tip! Link text should always be clear, unique, and meaningful. Avoid common words like \"click here\"; or \"learn more\"." -PLG_SYSTEM_JOOA11Y_LINK_URL="Longer, less intelligible URLs used as link text might be difficult to listen to with assistive technology. In most cases, it is better to use human-readable text instead of the URL. Short URLs (such as a site's homepage) are okay." -PLG_SYSTEM_JOOA11Y_LINK_URL_TIP="Tip! Link text should always be clear, unique, and meaningful so it could be understood out of context." -PLG_SYSTEM_JOOA11Y_LINKS_ADVANCED="Links (Advanced)" -PLG_SYSTEM_JOOA11Y_MAIN_TOGGLE_LABEL="Check Accessibility" -PLG_SYSTEM_JOOA11Y_MISSING_ALT_LINK_BUT_HAS_TEXT_MESSAGE="Image is being used as a link with surrounding text, although the alt attribute should be marked as decorative." -PLG_SYSTEM_JOOA11Y_MISSING_ALT_LINK_MESSAGE="Image is being used as a link but is missing alt text! Please ensure alt text describes where the link takes you." -PLG_SYSTEM_JOOA11Y_MISSING_ALT_MESSAGE="Missing alt text! If the image conveys a story, mood, or important information - be sure to describe the image." -PLG_SYSTEM_JOOA11Y_NEW_TAB_WARNING="Link opens in a new tab or window without warning. Doing so can be disorienting, especially for people who have difficulty perceiving visual content. Secondly, it is not always a good practice to control someone's experience or make decisions for them. Indicate that the link opens in a new window within the link text." -PLG_SYSTEM_JOOA11Y_NEW_TAB_WARNING_TIP="Tip! Learn best practices: opening links in new browser windows and tabs." -PLG_SYSTEM_JOOA11Y_OFF="Off" -PLG_SYSTEM_JOOA11Y_ON="On" -PLG_SYSTEM_JOOA11Y_PAGE_OUTLINE="Page Outline" -PLG_SYSTEM_JOOA11Y_PANEL_HEADING_MISSING_ONE="Missing Heading 1!" -PLG_SYSTEM_JOOA11Y_PANEL_STATUS_BOTH="Accessibility Errors: %(errorCount). Accessibility Warnings: %(warningCount)." -PLG_SYSTEM_JOOA11Y_PANEL_STATUS_ERRORS="Accessibility Errors: %(errorCount)." -PLG_SYSTEM_JOOA11Y_PANEL_STATUS_HIDDEN="The item you are trying to view is not visible; it may be hidden or inside of an accordion or tab component. Here's a preview: " -PLG_SYSTEM_JOOA11Y_PANEL_STATUS_ICON="Total issues found: %(totalCount)" -PLG_SYSTEM_JOOA11Y_PANEL_STATUS_NONE="No accessibility errors found." -PLG_SYSTEM_JOOA11Y_PANEL_STATUS_WARNINGS="Accessibility Warnings: %(warningCount)." -PLG_SYSTEM_JOOA11Y_QA_BAD_ITALICS="Bold and italic tags have semantic meaning, and should not be used to highlight entire paragraphs. Bolded text should be used to provide strong emphasis on a word or phrase. Italics should be used to highlight proper names (i.e. book and article titles), foreign words, quotes. Long quotes should be formatted as a blockquote." -PLG_SYSTEM_JOOA11Y_QA_BAD_LINK="Bad link found. Link appears to point to a development environment. This link points to: %(el)" -PLG_SYSTEM_JOOA11Y_QA_BLOCKQUOTE_MESSAGE="Is this a heading? %(bqHeadingText)" -PLG_SYSTEM_JOOA11Y_QA_BLOCKQUOTE_MESSAGE_TIP="Blockquotes should be used for quotes only. If this is intended to be a heading, change this blockquote to a semantic heading (e.g. Heading 2 or Heading 3)." -PLG_SYSTEM_JOOA11Y_QA_DUPLICATE_ID="Found duplicate ID. Duplicate ID errors are known to cause problems for assistive technologies when they are trying to interact with content." -PLG_SYSTEM_JOOA11Y_QA_DUPLICATE_ID_TIP="Please remove or change the following ID: %(id)" -PLG_SYSTEM_JOOA11Y_QA_FAKE_HEADING="Is this a heading? %(boldtext)" -PLG_SYSTEM_JOOA11Y_QA_FAKE_HEADING_INFO="A line of bold text might look like a heading, but someone using a screen reader cannot tell that it is important or jump to its content. Bolded text should never replace semantic headings (Heading 2 to Heading 6)." -PLG_SYSTEM_JOOA11Y_QA_PAGE_LANGUAGE_MESSAGE="Page language not declared! Please declare language on HTML tag." -PLG_SYSTEM_JOOA11Y_QA_PDF_COUNT="PDFs are considered web content and must be made accessible as well. PDFs often contain issues for people who use screen readers (missing structural tags or missing form field labels) and people who have low vision (text does not reflow when enlarged).
  • If this is a form, consider using an accessible HTML form as an alternative.
  • If this is a document, consider converting it into a web page.

Otherwise, please check %(pdfCount) PDF(s) for accessibility in Acrobat DC." -PLG_SYSTEM_JOOA11Y_QA_SHOULD_BE_LIST="Are you trying to create a list? Possible list item found: %(firstPrefix)" -PLG_SYSTEM_JOOA11Y_QA_SHOULD_BE_LIST_TIP="Make sure to use semantic lists by using the bullet or number formatting buttons instead. When using a semantic list, assistive technologies are able to convey information such as the total number of items and the relative position of each item in the list. Learn more about semantic lists." -PLG_SYSTEM_JOOA11Y_QA_UPPERCASE_WARNING="Found all caps. Some screen readers may interpret all caps text as an acronym and will read each letter individually. Additionally, some people find all caps more difficult to read and it may give the appearance of SHOUTING." -PLG_SYSTEM_JOOA11Y_READABILITY="Readability:" -PLG_SYSTEM_JOOA11Y_READABILITY_NO_P_OR_LI_MESSAGE="Unable to calculate readability score. No paragraph <p> or list content <li> found." -PLG_SYSTEM_JOOA11Y_READABILITY_NOT_ENOUGH_CONTENT_MESSAGE="Not enough content to calculate readability score." -PLG_SYSTEM_JOOA11Y_SETTINGS="Settings" -PLG_SYSTEM_JOOA11Y_SHORTCUT_SR="Skip to issue. Keyboard shortcut: Alt period" -PLG_SYSTEM_JOOA11Y_SHORTCUT_TOOLTIP="Skip to issue" -PLG_SYSTEM_JOOA11Y_SHOW_OUTLINE="Show Outline" -PLG_SYSTEM_JOOA11Y_SHOW_SETTINGS="Show Settings" -PLG_SYSTEM_JOOA11Y_TABLES_EMPTY_HEADING="Empty table header found! Table headers should never be empty. It is important to designate row and/or column headers to convey their relationship. This information provides context to people who use assistive technology. Please keep in mind that tables should be used for tabular data only." -PLG_SYSTEM_JOOA11Y_TABLES_EMPTY_HEADING_INFO="Learn more about accessible tables." -PLG_SYSTEM_JOOA11Y_TABLES_MISSING_HEADINGS="Missing table headers! Accessible tables need HTML markup that indicates header cells and data cells which defines their relationship. This information provides context to people who use assistive technology. Tables should be used for tabular data only." -PLG_SYSTEM_JOOA11Y_TABLES_MISSING_HEADINGS_INFO="Learn more about accessible tables." -PLG_SYSTEM_JOOA11Y_TABLES_SEMANTIC_HEADING="Semantic headings such as Heading 2 or Heading 3 should only be used for sections of content; not in HTML tables. Indicate table headings using the th element instead." -PLG_SYSTEM_JOOA11Y_TABLES_SEMANTIC_HEADING_INFO="Learn more about accessible tables." -PLG_SYSTEM_JOOA11Y_TEXT_UNDERLINE_WARNING="Underlined text can be confused with links." -PLG_SYSTEM_JOOA11Y_TEXT_UNDERLINE_WARNING_TIP="Consider using a different style such as <em>emphasis</em>." -PLG_SYSTEM_JOOA11Y_TOTAL_WORDS="Words:" -PLG_SYSTEM_JOOA11Y_VERY_DIFFICULT_READABILITY="Very difficult" -PLG_SYSTEM_JOOA11Y_WARNING="Warning" diff --git a/administrator/language/en-GB/plg_system_privacyconsent.ini b/administrator/language/en-GB/plg_system_privacyconsent.ini index f15388b120217..8585c2a58710a 100644 --- a/administrator/language/en-GB/plg_system_privacyconsent.ini +++ b/administrator/language/en-GB/plg_system_privacyconsent.ini @@ -5,7 +5,7 @@ PLG_SYSTEM_PRIVACYCONSENT="System - Privacy Consent" PLG_SYSTEM_PRIVACYCONSENT_BODY="

The user consented to storing their user information using the IP address %s

The user agent string of the user's browser was:
%s

This information was automatically recorded when the user submitted their details on the website and checked the confirm box.

" -PLG_SYSTEM_PRIVACYCONSENT_CONSENT="User {username} consented to the privacy policy." +PLG_SYSTEM_PRIVACYCONSENT_CONSENT="User {username} consented to the privacy policy." PLG_SYSTEM_PRIVACYCONSENT_FIELD_ARTICLE_DESC="Select the article from the list or create a new one." PLG_SYSTEM_PRIVACYCONSENT_FIELD_ARTICLE_LABEL="Privacy Article" PLG_SYSTEM_PRIVACYCONSENT_FIELD_ERROR="Agreement to the site's Privacy Policy is required." @@ -25,20 +25,3 @@ PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_DESC="Custom message to be displayed PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_LABEL="Redirect Message" PLG_SYSTEM_PRIVACYCONSENT_SUBJECT="Privacy Policy" PLG_SYSTEM_PRIVACYCONSENT_XML_DESCRIPTION="Basic plugin to request user's consent to the site's privacy policy. Existing users who have not consented yet will be redirected on login to update their profile." - -; All the following strings are deprecated and will be removed with 6.0 -PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_DESC="How often the check is performed." -PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_LABEL="Periodic check (days)" -PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_DESC="Number of days after which the privacy consent shall expire." -PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_LABEL="Expiration" -PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_BODY="Your Privacy Consent given at {URL} will expire in few days, you can renew the privacy consent for this website.\n\nIn order to do this, you can complete one of the following tasks:\n\n1. Visit the following URL: {TOKENURL}\n\n2. Copy your token from this email, visit the referenced URL, and paste your token into the form.\nURL: {FORMURL}\nToken: {TOKEN}\n\nPlease note that this token is only valid for this account." -PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT="Privacy Consent at {SITENAME}" -PLG_SYSTEM_PRIVACYCONSENT_EXPIRATION_FIELDSET_LABEL="Expiration" -PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_DESC="When enabled it performs checks for consent expiration." -PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_LABEL="Enable" -PLG_SYSTEM_PRIVACYCONSENT_MAIL_REQUEST_REMINDER_DESC="Reminder to renew the privacy consent for this website." -PLG_SYSTEM_PRIVACYCONSENT_MAIL_REQUEST_REMINDER_TITLE="System - Privacy Consent: Renew Consent" -PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_MESSAGE="Privacy consent has expired for %1$s." -PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_SUBJECT="Privacy Consent Expired" -PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_DESC="Number of days to send a reminder before the expiration of the privacy consent." -PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_LABEL="Remind" diff --git a/administrator/language/en-GB/plg_system_schemaorg.ini b/administrator/language/en-GB/plg_system_schemaorg.ini index 617dedbfd5251..4e13d9795cd1a 100644 --- a/administrator/language/en-GB/plg_system_schemaorg.ini +++ b/administrator/language/en-GB/plg_system_schemaorg.ini @@ -9,9 +9,6 @@ PLG_SYSTEM_SCHEMAORG_BASETYPE_LABEL="Base Type" PLG_SYSTEM_SCHEMAORG_BASETYPE_OPTION_ORGANIZATION="Organization" PLG_SYSTEM_SCHEMAORG_BASETYPE_OPTION_PERSON="Person" PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_DESCRIPTION="Structured data is a standardised format for organising and representing information on the web. It provides a way to describe the content and meaning of data in a structured manner, making it easier for search engines and other applications to understand and process the information. More information on schema.org." -; The following two strings are deprecated and will be removed with 6.0 -PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_DESCRIPTION_NOT_CONFIGURATED="To use the schema.org functionality, you have to configure the plugin first. Please contact an administrator of the page to get it configured." -PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_DESCRIPTION_NOT_CONFIGURATED_ADMIN="To use the schema.org functionality, you have to configure the plugin first. Please select this link to open the plugin, configure and save." PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_DESCRIPTION_NOT_CONFIGURED="To use the schema.org functionality, you have to configure the plugin first. Please contact an administrator of the page to get it configured." PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_DESCRIPTION_NOT_CONFIGURED_ADMIN="To use the schema.org functionality, you have to configure the plugin first. Please select this link to open the plugin, configure and save." PLG_SYSTEM_SCHEMAORG_FIELD_SCHEMA_EXTEND_JED_DESC="Need more Schema types? Extend with Schema Plugins from Joomla! Extension Directory." diff --git a/administrator/language/en-GB/plg_system_webauthn.ini b/administrator/language/en-GB/plg_system_webauthn.ini index ceb3d0ed9242b..682b694af8054 100644 --- a/administrator/language/en-GB/plg_system_webauthn.ini +++ b/administrator/language/en-GB/plg_system_webauthn.ini @@ -27,7 +27,7 @@ PLG_SYSTEM_WEBAUTHN_ERR_USER_REMOVED="The user for this passkey seems to no long PLG_SYSTEM_WEBAUTHN_ERR_XHR_INITCREATE="Cannot get the passkey registration information from your site." PLG_SYSTEM_WEBAUTHN_FIELD_ATTESTATION_SUPPORT_DESC="Only allow passkeys with verifiable cryptographic signatures to be used for passkey logins. Strongly recommended for high security environments. Requires the system temporary directory being writable by PHP, and the OpenSSL extension. May prevent some cheaper, non-certified passkeys from working at all. Disabling it also prevents Joomla from identifying the make and model of the passkey you are using (no icon will be displayed next to the passkey Name)." PLG_SYSTEM_WEBAUTHN_FIELD_ATTESTATION_SUPPORT_LABEL="Attestation Support" -PLG_SYSTEM_WEBAUTHN_FIELD_DESC="Lets you manage passwordless login methods using passkeys. You need a supported browser and passkey (eg Google Chrome or Firefox with a FIDO2 certified security key).

MacOS/iOS/watchOS: Touch/Face ID.
Windows: Hello (Fingerprint / Facial Recognition / PIN).
Android: Biometric screen lock.

You can find more details in the Passkey Passwordless Login documentation." +PLG_SYSTEM_WEBAUTHN_FIELD_DESC="Lets you manage passwordless login methods using passkeys. You need a supported browser and passkey (eg Google Chrome or Firefox with a FIDO2 certified security key).

MacOS/iOS/watchOS: Touch/Face ID.
Windows: Hello (Fingerprint / Facial Recognition / PIN).
Android: Biometric screen lock.

You can find more details in the Passkey Passwordless Login documentation." PLG_SYSTEM_WEBAUTHN_FIELD_LABEL="Passkey Login" PLG_SYSTEM_WEBAUTHN_FIELD_N_AUTHENTICATORS_REGISTERED="%d passkeys already set up: %s" PLG_SYSTEM_WEBAUTHN_FIELD_N_AUTHENTICATORS_REGISTERED_0="No passkey has been set up yet" diff --git a/administrator/language/en-GB/plg_task_deleteactionlogs.ini b/administrator/language/en-GB/plg_task_deleteactionlogs.ini index bc1c00ebed271..f17d1b1eb78ba 100644 --- a/administrator/language/en-GB/plg_task_deleteactionlogs.ini +++ b/administrator/language/en-GB/plg_task_deleteactionlogs.ini @@ -6,5 +6,7 @@ PLG_TASK_DELETEACTIONLOGS="Task - Delete Action Logs" PLG_TASK_DELETEACTIONLOGS_DELETE_DESC="Delete Action logs after specified days." PLG_TASK_DELETEACTIONLOGS_DELETE_TITLE="Delete ActionLogs" +PLG_TASK_DELETEACTIONLOGS_LOG_DELETE_AFTER="Delete Logs after %d days" +PLG_TASK_DELETEACTIONLOGS_LOG_DELETE_END="Delete Logs end" PLG_TASK_DELETEACTIONLOGS_LOG_DELETE_PERIOD="Days to delete action logs after" PLG_TASK_DELETEACTIONLOGS_XML_DESCRIPTION="This plugin for schedule Action Logs delete Tasks." diff --git a/administrator/language/en-GB/plg_task_privacyconsent.ini b/administrator/language/en-GB/plg_task_privacyconsent.ini index 4cd98a977c0d4..87d524b3b2107 100644 --- a/administrator/language/en-GB/plg_task_privacyconsent.ini +++ b/administrator/language/en-GB/plg_task_privacyconsent.ini @@ -10,6 +10,7 @@ PLG_TASK_PRIVACYCONSENT_INVALIDATE_TITLE="Expiration of privacy consents" PLG_TASK_PRIVACYCONSENT_INVALIDATE_DESC="Manage the expiration of privacy consents" PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_BODY="Your Privacy Consent given at {URL} will expire in few days, you can renew the privacy consent for this website.\n\nIn order to do this, you can complete one of the following tasks:\n\n1. Visit the following URL: {TOKENURL}\n\n2. Copy your token from this email, visit the referenced URL, and paste your token into the form.\nURL: {FORMURL}\nToken: {TOKEN}\n\nPlease note that this token is only valid for this account." PLG_TASK_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT="Privacy Consent at {SITENAME}" +PLG_TASK_PRIVACYCONSENT_LOG_REMIND_END="Remind End" PLG_TASK_PRIVACYCONSENT_MAIL_REQUEST_REMINDER_DESC="Reminder to renew the privacy consent for this website." PLG_TASK_PRIVACYCONSENT_MAIL_REQUEST_REMINDER_TITLE="Task - Privacy Consent: Renew Consent" PLG_TASK_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_MESSAGE="Privacy consent has expired for %1$s." diff --git a/administrator/language/en-GB/plg_task_requests.ini b/administrator/language/en-GB/plg_task_requests.ini index 8b47db87f5543..89f8e02d5171f 100644 --- a/administrator/language/en-GB/plg_task_requests.ini +++ b/administrator/language/en-GB/plg_task_requests.ini @@ -9,6 +9,9 @@ PLG_TASK_REQUESTS_JOOMLA_TOKEN="X-Joomla-Token" PLG_TASK_REQUESTS_LABEL_AUTH="Authorization" PLG_TASK_REQUESTS_LABEL_AUTH_HEADER="Authorization Header" PLG_TASK_REQUESTS_LABEL_AUTH_KEY="Authorization Key" +PLG_TASK_REQUESTS_LABEL_CUSTOM_HEADERS="Custom Headers" +PLG_TASK_REQUESTS_LABEL_CUSTOM_HEADER_NAME="Header Name" +PLG_TASK_REQUESTS_LABEL_CUSTOM_HEADER_VALUE="Header Value" PLG_TASK_REQUESTS_LABEL_REQUEST_TIMEOUT="Request Timeout" PLG_TASK_REQUESTS_LABEL_REQUEST_URL="Request URL" PLG_TASK_REQUESTS_TASK_GET_REQUEST_DESC="Make GET requests to a server. Supports a custom timeout and authorization headers." diff --git a/administrator/language/en-GB/plg_task_updatenotification.ini b/administrator/language/en-GB/plg_task_updatenotification.ini index 141df42dbb937..b5a556df49df1 100644 --- a/administrator/language/en-GB/plg_task_updatenotification.ini +++ b/administrator/language/en-GB/plg_task_updatenotification.ini @@ -4,6 +4,7 @@ ; Note : All ini files need to be saved as UTF-8 PLG_TASK_UPDATENOTIFICATION="Task - Joomla! Update Notification" +PLG_TASK_UPDATENOTIFICATION_END="Update Notification end" PLG_TASK_UPDATENOTIFICATION_EMAIL_DESC="A comma separated list of the email addresses which will receive the update notification emails. The addresses in the list MUST belong to existing users of your site who have the Super User privilege. If none of the listed emails belongs to Super Users, or if it's left blank, all Super Users of this site will receive the update notification email." PLG_TASK_UPDATENOTIFICATION_EMAIL_LBL="Super User Emails" PLG_TASK_UPDATENOTIFICATION_SEND_TITLE="Joomla! Update Notification" diff --git a/administrator/language/en-GB/plg_user_terms.ini b/administrator/language/en-GB/plg_user_terms.ini index 389ef20109358..6c9fceb44c023 100644 --- a/administrator/language/en-GB/plg_user_terms.ini +++ b/administrator/language/en-GB/plg_user_terms.ini @@ -9,7 +9,7 @@ PLG_USER_TERMS_FIELD_ARTICLE_LABEL="Terms & Conditions Article" PLG_USER_TERMS_FIELD_ERROR="Agreement to the site's Terms & Conditions is required." PLG_USER_TERMS_FIELD_LABEL="Terms & Conditions" PLG_USER_TERMS_LABEL="Terms & Conditions" -PLG_USER_TERMS_LOGGING_CONSENT_TO_TERMS="User {username} consented to the terms and conditions during registration." +PLG_USER_TERMS_LOGGING_CONSENT_TO_TERMS="User {username} consented to the terms and conditions during registration." PLG_USER_TERMS_NOTE_FIELD_DEFAULT="By signing up to this website you accept the Terms & Conditions." PLG_USER_TERMS_NOTE_FIELD_DESC="A summary of the site's terms & conditions. If left blank then the default message will be used." PLG_USER_TERMS_NOTE_FIELD_LABEL="Short Terms & Conditions" diff --git a/administrator/language/en-GB/tpl_atum.ini b/administrator/language/en-GB/tpl_atum.ini index 13d9f6ca31423..0486957b489ad 100644 --- a/administrator/language/en-GB/tpl_atum.ini +++ b/administrator/language/en-GB/tpl_atum.ini @@ -21,13 +21,17 @@ TPL_ATUM_COLORS_SETTINGS_TEXT_DARK_LABEL="Dark Text" TPL_ATUM_COLORS_SETTINGS_TEXT_LIGHT_LABEL="Light Text" TPL_ATUM_IMAGE_LABEL="Image" TPL_ATUM_IMAGE_SETTINGS_LABEL="Image Settings" +TPL_ATUM_LOGIN_LOGO_DESCRIPTION="The recommended size is 70px x 70px" TPL_ATUM_LOGIN_LOGO_LABEL="Login Logo" +TPL_ATUM_LOGIN_SIDEBAR_HEADING="Help and support" TPL_ATUM_LOGIN_SIDEBAR_VIEW_WEBSITE="View website" TPL_ATUM_LOGO_ALT_EMPTY_DESC="Decorative Image - no description required" TPL_ATUM_LOGO_ALT_EMPTY_LABEL="No Description" TPL_ATUM_LOGO_ALT_LABEL="Image Description (Alt Text)" TPL_ATUM_MORE_ELEMENTS="More Elements" +TPL_ATUM_SITE_LOGO_DESCRIPTION="The recommended size is 150px x 30px" TPL_ATUM_SITE_LOGO_LABEL="Brand Large" +TPL_ATUM_SITE_LOGO_SMALL_DESCRIPTION="The recommended size is 20px x 20px" TPL_ATUM_SITE_LOGO_SMALL_LABEL="Brand Small" TPL_ATUM_TOOLBAR="Toolbar" -TPL_ATUM_XML_DESCRIPTION="Continuing the Egyptian god/goddess theme (Khepri from 1.5, Hathor from 1.6, Isis from 3.0), Atum is the name of the Joomla 4 and Joomla 5 administrator template." +TPL_ATUM_XML_DESCRIPTION="Continuing the Egyptian god/goddess theme (Khepri from 1.5, Hathor from 1.6, Isis from 3.0), Atum is the name of the Joomla administrator template." diff --git a/administrator/language/en-GB/tpl_atum.sys.ini b/administrator/language/en-GB/tpl_atum.sys.ini index 50eb38f0c5918..9388cdad5d1d6 100644 --- a/administrator/language/en-GB/tpl_atum.sys.ini +++ b/administrator/language/en-GB/tpl_atum.sys.ini @@ -16,4 +16,4 @@ TPL_ATUM_POSITION_STATUS="Status" TPL_ATUM_POSITION_TITLE="Title" TPL_ATUM_POSITION_TOOLBAR="Toolbar" TPL_ATUM_POSITION_TOP="Top" -TPL_ATUM_XML_DESCRIPTION="Continuing the Egyptian god/goddess theme (Khepri from 1.5, Hathor from 1.6, Isis from 3.0), Atum is the name of the Joomla 4 and Joomla 5 administrator template." +TPL_ATUM_XML_DESCRIPTION="Continuing the Egyptian god/goddess theme (Khepri from 1.5, Hathor from 1.6, Isis from 3.0), Atum is the name of the Joomla administrator template." diff --git a/administrator/manifests/files/joomla.xml b/administrator/manifests/files/joomla.xml index 25c1db0739c93..4573e1c025501 100644 --- a/administrator/manifests/files/joomla.xml +++ b/administrator/manifests/files/joomla.xml @@ -6,7 +6,7 @@ www.joomla.org (C) 2019 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt - 5.4.8-rc3-dev + 6.2.0-beta2-dev 2026-08 FILES_JOOMLA_XML_DESCRIPTION diff --git a/administrator/manifests/packages/pkg_en-GB.xml b/administrator/manifests/packages/pkg_en-GB.xml index 977b3f624f65f..3e0746076cd9b 100644 --- a/administrator/manifests/packages/pkg_en-GB.xml +++ b/administrator/manifests/packages/pkg_en-GB.xml @@ -2,7 +2,7 @@ English (en-GB) Language Pack en-GB - 5.4.8.1 + 6.2.0.1 2026-08 Joomla! Project admin@joomla.org @@ -21,7 +21,7 @@
- https://update.joomla.org/language/translationlist_5.xml + https://update.joomla.org/language/translationlist_6.xml diff --git a/administrator/modules/mod_logged/src/Helper/LoggedHelper.php b/administrator/modules/mod_logged/src/Helper/LoggedHelper.php index bcefae12b6e81..e7cf40b87333a 100644 --- a/administrator/modules/mod_logged/src/Helper/LoggedHelper.php +++ b/administrator/modules/mod_logged/src/Helper/LoggedHelper.php @@ -44,11 +44,12 @@ class LoggedHelper public function getUsers(Registry $params, CMSApplication $app, DatabaseInterface $db): mixed { $user = $app->getIdentity(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('s.time, s.client_id, u.id, u.name, u.username') ->from('#__session AS s') ->join('RIGHT', '#__users AS u ON s.userid = u.id') ->where('s.guest = 0') + ->order('s.time DESC') ->setLimit($params->get('count', 5), 0); $db->setQuery($query); diff --git a/administrator/modules/mod_menu/mod_menu.xml b/administrator/modules/mod_menu/mod_menu.xml index f78fbb68da710..1019bf57c4fc0 100644 --- a/administrator/modules/mod_menu/mod_menu.xml +++ b/administrator/modules/mod_menu/mod_menu.xml @@ -88,7 +88,7 @@ description="MOD_MENU_FIELD_FORUMURL_DESC" filter="url" default="" - showon="menutype:*" + showon="preset:alternate" validate="url" />
diff --git a/administrator/modules/mod_menu/tmpl/default_submenu.php b/administrator/modules/mod_menu/tmpl/default_submenu.php index 8dc08f0d446fb..efca38b33a5c8 100644 --- a/administrator/modules/mod_menu/tmpl/default_submenu.php +++ b/administrator/modules/mod_menu/tmpl/default_submenu.php @@ -38,13 +38,7 @@ } } -if ($current->level == 1) { - $class .= ' item-level-1'; -} elseif ($current->level == 2) { - $class .= ' item-level-2'; -} elseif ($current->level == 3) { - $class .= ' item-level-3'; -} +$class .= ' item-level-' . (int) $current->level; // Set the correct aria role and print the item if ($current->type == 'separator') { @@ -55,17 +49,12 @@ // Print a link if it exists $linkClass = []; -$dataToggle = ''; $iconClass = ''; $itemIconClass = ''; $itemImage = ''; if ($current->hasChildren()) { $linkClass[] = 'has-arrow'; - - if ($current->level > 2) { - $dataToggle = ' data-bs-toggle="dropdown"'; - } } else { $linkClass[] = 'no-dropdown'; @@ -119,15 +108,15 @@ } if ($link != '' && $current->target != '') { - echo '' + echo '' . $iconClass . '' . $itemImage . Text::_($current->title) . '' . $ajax . ''; } elseif ($link != '' && $current->type !== 'separator') { - echo '' + echo '' . $iconClass . '' . $itemImage . Text::_($current->title) . '' . $iconImage . ''; } elseif ($current->title != '' && $current->type !== 'separator') { - echo '' + echo '' . $iconClass . '' . $itemImage . Text::_($current->title) . '' . $ajax . ''; } elseif ($current->title != '' && $current->type === 'separator') { diff --git a/administrator/modules/mod_popular/mod_popular.php b/administrator/modules/mod_popular/mod_popular.php deleted file mode 100644 index 1896c3d58aff5..0000000000000 --- a/administrator/modules/mod_popular/mod_popular.php +++ /dev/null @@ -1,49 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -\defined('_JEXEC') or die; - -use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Helper\ModuleHelper; -use Joomla\CMS\Layout\LayoutHelper; -use Joomla\Module\Popular\Administrator\Helper\PopularHelper; - -$model = $app->bootComponent('com_content')->getMVCFactory()->createModel('Articles', 'Administrator', ['ignore_request' => true]); -$list = PopularHelper::getList($params, $model); - -// Get module data. -if ($params->get('automatic_title', 0)) { - $module->title = PopularHelper::getTitle($params); -} - -// If recording of hits is disabled. -if (!ComponentHelper::getParams('com_content')->get('record_hits', 1)) { - echo LayoutHelper::render('joomla.content.emptystate_module', [ - 'title' => 'JGLOBAL_RECORD_HITS_DISABLED', - 'icon' => 'icon-minus-circle', - ]); - - return; -} - -// If there are some articles to display. -if (\count($list)) { - require ModuleHelper::getLayoutPath('mod_popular', $params->get('layout', 'default')); - - return; -} - -// If there are no articles to display, show empty state. -$app->getLanguage()->load('com_content'); - -echo LayoutHelper::render('joomla.content.emptystate_module', [ - 'textPrefix' => 'COM_CONTENT', - 'icon' => 'icon-copy', - ]); diff --git a/administrator/modules/mod_popular/mod_popular.xml b/administrator/modules/mod_popular/mod_popular.xml index 5d1c3e00fcb65..c4ccf1e0e550c 100644 --- a/administrator/modules/mod_popular/mod_popular.xml +++ b/administrator/modules/mod_popular/mod_popular.xml @@ -11,7 +11,7 @@ MOD_POPULAR_XML_DESCRIPTION Joomla\Module\Popular - mod_popular.php + services src tmpl @@ -55,6 +55,66 @@ + + + + + + + + + + + + + + + + + + + +
diff --git a/administrator/modules/mod_popular/services/provider.php b/administrator/modules/mod_popular/services/provider.php new file mode 100644 index 0000000000000..67f2c33aef3cc --- /dev/null +++ b/administrator/modules/mod_popular/services/provider.php @@ -0,0 +1,41 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +\defined('_JEXEC') or die; + +use Joomla\CMS\Extension\Service\Provider\HelperFactory; +use Joomla\CMS\Extension\Service\Provider\Module; +use Joomla\CMS\Extension\Service\Provider\ModuleDispatcherFactory; +use Joomla\DI\Container; +use Joomla\DI\ServiceProviderInterface; + +/** + * The latest articles module service provider. + * + * @since 6.0.0 + */ +return new class () implements ServiceProviderInterface { + /** + * Registers the service provider with a DI container. + * + * @param Container $container The DI container. + * + * @return void + * + * @since 6.0.0 + */ + public function register(Container $container) + { + $container->registerServiceProvider(new ModuleDispatcherFactory('\\Joomla\\Module\\Popular')); + $container->registerServiceProvider(new HelperFactory('\\Joomla\\Module\\Popular\\Administrator\\Helper')); + + $container->registerServiceProvider(new Module()); + } +}; diff --git a/administrator/modules/mod_popular/src/Dispatcher/Dispatcher.php b/administrator/modules/mod_popular/src/Dispatcher/Dispatcher.php new file mode 100644 index 0000000000000..498b0dd42bd94 --- /dev/null +++ b/administrator/modules/mod_popular/src/Dispatcher/Dispatcher.php @@ -0,0 +1,59 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Module\Popular\Administrator\Dispatcher; + +use Joomla\CMS\Component\ComponentHelper; +use Joomla\CMS\Dispatcher\AbstractModuleDispatcher; +use Joomla\CMS\Helper\HelperFactoryAwareInterface; +use Joomla\CMS\Helper\HelperFactoryAwareTrait; +use Joomla\Module\Popular\Administrator\Helper\PopularHelper; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Dispatcher class for mod_popular + * + * @since 6.0.0 + */ +class Dispatcher extends AbstractModuleDispatcher implements HelperFactoryAwareInterface +{ + use HelperFactoryAwareTrait; + + /** + * Returns the layout data. + * + * @return array + * + * @since 6.0.0 + */ + protected function getLayoutData() + { + $data = parent::getLayoutData(); + /** @var PopularHelper $helper */ + $helper = $this->getHelperFactory()->getHelper('PopularHelper', $data); + $articleModel = $this + ->getApplication() + ->bootComponent('com_content') + ->getMVCFactory() + ->createModel('Articles', 'Administrator', ['ignore_request' => true]); + + if ($data['params']->get('automatic_title', 0)) { + $data['module']->title = $helper->getModuleTitle($data['params']); + } + + $data['list'] = $helper->getArticles($data['params'], $articleModel); + $data['record_hits'] = (int) ComponentHelper::getParams('com_content')->get('record_hits', 1); + + return $data; + } +} diff --git a/administrator/modules/mod_popular/src/Helper/PopularHelper.php b/administrator/modules/mod_popular/src/Helper/PopularHelper.php index 926196117773e..cab46309e19f6 100644 --- a/administrator/modules/mod_popular/src/Helper/PopularHelper.php +++ b/administrator/modules/mod_popular/src/Helper/PopularHelper.php @@ -10,8 +10,7 @@ namespace Joomla\Module\Popular\Administrator\Helper; -use Joomla\CMS\Categories\Categories; -use Joomla\CMS\Factory; +use Joomla\CMS\Application\CMSApplicationInterface; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; use Joomla\Component\Content\Administrator\Model\ArticlesModel; @@ -26,8 +25,35 @@ * * @since 1.6 */ -abstract class PopularHelper +class PopularHelper { + /** + * @var CMSApplicationInterface + * + * @since 6.0.0 + */ + protected $app; + + /** + * @var Registry + * + * @since 6.0.0 + */ + protected $params; + + /** + * Helper class constructor + * + * @param array $config Parameters we are using + * + * @since 6.0.0 + */ + public function __construct($config) + { + $this->app = $config['app']; + $this->params = $config['params']; + } + /** * Get a list of the most popular articles. * @@ -37,14 +63,16 @@ abstract class PopularHelper * @return mixed An array of articles, or false on error. * * @throws \Exception + * + * @since 6.0.0 */ - public static function getList(Registry $params, ArticlesModel $model) + public function getArticles(Registry $params, ArticlesModel $model): mixed { - $user = Factory::getUser(); + $user = $this->app->getIdentity(); // Set List SELECT $model->setState('list.select', 'a.id, a.title, a.checked_out, a.checked_out_time, ' . - ' a.created_by, a.publish_up, a.hits'); + ' a.created, a.modified, a.publish_up, a.created_by, a.hits'); // Set Ordering filter $model->setState('list.ordering', 'a.hits'); @@ -75,6 +103,21 @@ public static function getList(Registry $params, ArticlesModel $model) $model->setState('list.start', 0); $model->setState('list.limit', $params->get('count', 5)); + // Set date filtering using ArticlesModel's built-in filter + $dateFiltering = $params->get('date_filtering', 'off'); + + if ($dateFiltering !== 'off') { + $model->setState('filter.date_filtering', $dateFiltering); + $model->setState('filter.date_field', $params->get('date_field', 'a.created')); + + if ($dateFiltering === 'range') { + $model->setState('filter.start_date_range', $params->get('start_date_range', '1000-01-01 00:00:00')); + $model->setState('filter.end_date_range', $params->get('end_date_range', '9999-12-31 23:59:59')); + } elseif ($dateFiltering === 'relative') { + $model->setState('filter.relative_date', (int) $params->get('relative_date', 30)); + } + } + $items = $model->getItems(); if ($error = $model->getError()) { @@ -102,15 +145,17 @@ public static function getList(Registry $params, ArticlesModel $model) * @param Registry $params The module parameters. * * @return string The alternate title for the module. + * + * @since 6.0.0 */ - public static function getTitle($params) + public function getModuleTitle(Registry $params): string { $who = $params->get('user_id', 0); $catid = (int) $params->get('catid', null); $title = ''; if ($catid) { - $category = Categories::getInstance('Content')->get($catid); + $category = $this->app->bootComponent('com_content')->getCategory()->get($catid); $title = Text::_('MOD_POPULAR_UNEXISTING'); if ($category) { diff --git a/administrator/modules/mod_popular/tmpl/default.php b/administrator/modules/mod_popular/tmpl/default.php index 4949093a8177e..bbec31bf7f940 100644 --- a/administrator/modules/mod_popular/tmpl/default.php +++ b/administrator/modules/mod_popular/tmpl/default.php @@ -12,52 +12,66 @@ use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; +use Joomla\CMS\Layout\LayoutHelper; $moduleId = str_replace(' ', '', $module->title) . $module->id; ?> - - - - - - - - - - - - $item) : ?> - - hits; ?> - = 10000 ? 'danger' : ($hits >= 1000 ? 'warning' : ($hits >= 100 ? 'info' : 'secondary'))); ?> - - - - - - + + 'JGLOBAL_RECORD_HITS_DISABLED', + 'icon' => 'icon-minus-circle', + ]); ?> + + +
title; ?>
- checked_out) : ?> - editor, $item->checked_out_time); ?> - - link) : ?> - - title, ENT_QUOTES, 'UTF-8'); ?> - - - title, ENT_QUOTES, 'UTF-8'); ?> - - - hits; ?> - - publish_up, Text::_('DATE_FORMAT_LC4')); ?> -
+ + + + + + + + + + $item) : ?> + + hits; ?> + = 10000 ? 'danger' : ($hits >= 1000 ? 'warning' : ($hits >= 100 ? 'info' : 'secondary'))); ?> + + + + + + + +
title; ?>
+ checked_out) : ?> + editor, $item->checked_out_time); ?> + + link) : ?> + + title, ENT_QUOTES, 'UTF-8'); ?> + + + title, ENT_QUOTES, 'UTF-8'); ?> + + + hits; ?> + + publish_up, Text::_('DATE_FORMAT_LC4')); ?> +
+ - - - - - + getLanguage()->load('com_content'); + + echo LayoutHelper::render('joomla.content.emptystate_module', [ + 'textPrefix' => 'COM_CONTENT', + 'icon' => 'icon-copy', + ]); + ?> + - - + diff --git a/administrator/modules/mod_privacy_dashboard/src/Helper/PrivacyDashboardHelper.php b/administrator/modules/mod_privacy_dashboard/src/Helper/PrivacyDashboardHelper.php index 2d8e5d2f08ab5..121455ad14658 100644 --- a/administrator/modules/mod_privacy_dashboard/src/Helper/PrivacyDashboardHelper.php +++ b/administrator/modules/mod_privacy_dashboard/src/Helper/PrivacyDashboardHelper.php @@ -38,7 +38,7 @@ class PrivacyDashboardHelper implements DatabaseAwareInterface public function getPrivacyRequests(): array { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ 'COUNT(*) AS count', diff --git a/administrator/modules/mod_privacy_status/src/Helper/PrivacyStatusHelper.php b/administrator/modules/mod_privacy_status/src/Helper/PrivacyStatusHelper.php index 75195a0828775..2d0e75331100b 100644 --- a/administrator/modules/mod_privacy_status/src/Helper/PrivacyStatusHelper.php +++ b/administrator/modules/mod_privacy_status/src/Helper/PrivacyStatusHelper.php @@ -86,7 +86,7 @@ public function getRequestFormMenuStatus(CMSApplicationInterface $app) $lang = ''; $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('id'), @@ -129,7 +129,7 @@ public function getRequestFormMenuStatus(CMSApplicationInterface $app) $params = ComponentHelper::getParams('com_languages'); $defaultSiteLanguage = $params->get('site'); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->where( @@ -173,7 +173,7 @@ public function getNumberOfUrgentRequests() $period = '-' . $notify; $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select('COUNT(*)') ->from($db->quoteName('#__privacy_requests')) ->where( diff --git a/administrator/modules/mod_quickicon/src/Helper/QuickIconHelper.php b/administrator/modules/mod_quickicon/src/Helper/QuickIconHelper.php index caad7839758ea..0bc6b9beb8a0b 100644 --- a/administrator/modules/mod_quickicon/src/Helper/QuickIconHelper.php +++ b/administrator/modules/mod_quickicon/src/Helper/QuickIconHelper.php @@ -15,6 +15,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Router\Route; +use Joomla\Event\DispatcherInterface; use Joomla\Module\Quickicon\Administrator\Event\QuickIconsEvent; use Joomla\Registry\Registry; @@ -258,14 +259,14 @@ public function getButtons(Registry $params, ?CMSApplication $application = null if ($params->get('show_featured')) { $tmp = [ 'image' => 'icon-star featured', - 'link' => Route::_('index.php?option=com_content&view=featured'), + 'link' => Route::_('index.php?option=com_content&view=articles&filter[featured]=1'), 'name' => 'MOD_QUICKICON_FEATURED_MANAGER', 'access' => ['core.manage', 'com_content'], 'group' => 'MOD_QUICKICON_SITE', ]; if ($params->get('show_featured') == 2) { - $tmp['ajaxurl'] = 'index.php?option=com_content&task=featured.getQuickiconContent&format=json'; + $tmp['ajaxurl'] = 'index.php?option=com_content&task=articles.getQuickiconFeatured&format=json'; } $this->buttons[$key][] = $tmp; @@ -382,10 +383,12 @@ public function getButtons(Registry $params, ?CMSApplication $application = null } PluginHelper::importPlugin('quickicon'); - $arrays = (array) $application->triggerEvent( - 'onGetIcons', - new QuickIconsEvent('onGetIcons', ['context' => $context]) - ); + $arrays = (array) Factory::getContainer() + ->get(DispatcherInterface::class) + ->dispatch( + 'onGetIcons', + new QuickIconsEvent('onGetIcons', ['context' => $context]) + )->getArgument('result', []); foreach ($arrays as $response) { if (!\is_array($response)) { diff --git a/administrator/modules/mod_stats_admin/src/Helper/StatsAdminHelper.php b/administrator/modules/mod_stats_admin/src/Helper/StatsAdminHelper.php index 4ee2df3276851..3df2cc3f1585c 100644 --- a/administrator/modules/mod_stats_admin/src/Helper/StatsAdminHelper.php +++ b/administrator/modules/mod_stats_admin/src/Helper/StatsAdminHelper.php @@ -44,7 +44,7 @@ public function getStatsData(Registry $params, CMSApplication $app, DatabaseInte $user = $app->getIdentity(); $rows = []; - $query = $db->getQuery(true); + $query = $db->createQuery(); $serverinfo = $params->get('serverinfo', 0); $siteinfo = $params->get('siteinfo', 0); diff --git a/administrator/templates/atum/error.php b/administrator/templates/atum/error.php index eb209be779fdb..926066ea25b68 100644 --- a/administrator/templates/atum/error.php +++ b/administrator/templates/atum/error.php @@ -15,7 +15,7 @@ /** @var \Joomla\CMS\Document\ErrorDocument $this */ // Authenticated versus guest have different displays -$user = Factory::getUser(); +$user = Factory::getApplication()->getIdentity(); if ($user->guest) { require __DIR__ . '/error_login.php'; diff --git a/administrator/templates/atum/error_login.php b/administrator/templates/atum/error_login.php index 58bffd8ebf139..a12d685347116 100644 --- a/administrator/templates/atum/error_login.php +++ b/administrator/templates/atum/error_login.php @@ -177,9 +177,10 @@ - + diff --git a/administrator/templates/atum/joomla.asset.json b/administrator/templates/atum/joomla.asset.json index acd22c1bf3dfc..edb2c2bd05943 100644 --- a/administrator/templates/atum/joomla.asset.json +++ b/administrator/templates/atum/joomla.asset.json @@ -2,7 +2,7 @@ "$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json", "name": "atum", "version": "4.0.0", - "description": "This file contains details of the assets used by Atum, the default Joomla 4 administrator template.", + "description": "This file contains details of the assets used by Atum, the default Joomla administrator template.", "license": "GPL-2.0-or-later", "assets": [ { diff --git a/administrator/templates/atum/login.php b/administrator/templates/atum/login.php index 8e3700d8885b2..9f7be79a5a541 100644 --- a/administrator/templates/atum/login.php +++ b/administrator/templates/atum/login.php @@ -134,29 +134,31 @@
- -
+
+
- +
diff --git a/administrator/templates/atum/templateDetails.xml b/administrator/templates/atum/templateDetails.xml index d4ec535fdf700..ab3df8c85f27e 100644 --- a/administrator/templates/atum/templateDetails.xml +++ b/administrator/templates/atum/templateDetails.xml @@ -126,7 +126,10 @@
-
+
-
+
-
+
input->get('filter', [], 'array'); + $filter = InputFilter::getInstance(); + + if (\array_key_exists('state', $apiFilterInfo)) { + $this->modelState->set('filter.published', $filter->clean($apiFilterInfo['state'], 'INT')); + } + + return parent::displayList(); + } } diff --git a/api/components/com_categories/src/Controller/CategoriesController.php b/api/components/com_categories/src/Controller/CategoriesController.php index fe44d00fa4416..6b11683d191c7 100644 --- a/api/components/com_categories/src/Controller/CategoriesController.php +++ b/api/components/com_categories/src/Controller/CategoriesController.php @@ -132,6 +132,10 @@ public function displayList() $this->modelState->set('filter.search', $filter->clean($apiFilterInfo['search'], 'STRING')); } + if (\array_key_exists('state', $apiFilterInfo)) { + $this->modelState->set('filter.published', $filter->clean($apiFilterInfo['state'], 'INT')); + } + $this->modelState->set('filter.extension', $this->getExtensionFromInput()); return parent::displayList(); @@ -149,4 +153,92 @@ private function getExtensionFromInput() return $this->input->exists('extension') ? $this->input->get('extension') : $this->input->post->get('extension'); } + + /** + * Method to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 6.1.3 + */ + protected function allowAdd($data = []) + { + $user = $this->app->getIdentity(); + $extension = $this->getExtensionFromInput(); + + // Require generic management permissions for the component + if (!$user->authorise('core.manage', $extension)) { + return false; + } + + return $user->authorise('core.create', $extension) || \count($user->getAuthorisedCategories($extension, 'core.create')); + } + + + /** + * Method to check if you can edit a record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 6.1.3 + */ + protected function allowEdit($data = [], $key = 'id') + { + $recordId = isset($data[$key]) ? (int) $data[$key] : 0; + $user = $this->app->getIdentity(); + $extension = $this->getExtensionFromInput(); + + // Require generic management permissions for the component + if (!$user->authorise('core.manage', $extension)) { + return false; + } + + // Need to do a lookup from the model to get the owner + $record = $this->getModel('Category')->getItem($recordId); + + if (empty($record) || $record->extension !== $extension) { + return false; + } + + // Check "edit" permission on record asset (explicit or inherited) + if ($user->authorise('core.edit', $extension . '.category.' . $recordId)) { + return true; + } + + // Check "edit own" permission on record asset (explicit or inherited) + if ($user->authorise('core.edit.own', $extension . '.category.' . $recordId)) { + $ownerId = $record->created_user_id; + + // If the owner matches 'me' then do the test. + if ($ownerId == $user->id) { + return true; + } + } + + return false; + } + + /** + * Method to check if it's allowed to delete a record + * + * @return boolean + * + * @since 6.1.3 + */ + protected function allowDelete(): bool + { + $extension = $this->getExtensionFromInput(); + $user = $this->app->getIdentity(); + + // Require generic management permissions for the component + if (!$user->authorise('core.manage', $extension)) { + return false; + } + + return $user->authorise('core.delete', $extension); + } } diff --git a/api/components/com_config/src/Controller/ComponentController.php b/api/components/com_config/src/Controller/ComponentController.php index 15809e9a093a3..0992ed165b5a0 100644 --- a/api/components/com_config/src/Controller/ComponentController.php +++ b/api/components/com_config/src/Controller/ComponentController.php @@ -172,6 +172,7 @@ public function edit() * @return boolean * * @since 5.4.6 + * @since 6.1.1 */ protected function allowEdit($data = [], $key = 'id') { diff --git a/api/components/com_contact/src/Controller/ContactController.php b/api/components/com_contact/src/Controller/ContactController.php index 5bbe70b31e375..e9f77ec0a790c 100644 --- a/api/components/com_contact/src/Controller/ContactController.php +++ b/api/components/com_contact/src/Controller/ContactController.php @@ -10,14 +10,19 @@ namespace Joomla\Component\Contact\Api\Controller; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Event\Contact\SubmitContactEvent; use Joomla\CMS\Event\Contact\ValidateContactEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\Mail\Exception\MailDisabledException; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Controller\ApiController; use Joomla\CMS\MVC\Controller\Exception\SendEmail; @@ -29,7 +34,6 @@ use Joomla\CMS\User\UserFactoryAwareTrait; use Joomla\Component\Fields\Administrator\Helper\FieldsHelper; use Joomla\Registry\Registry; -use Joomla\String\Inflector; use PHPMailer\PHPMailer\Exception as phpMailerException; use Tobscure\JsonApi\Exception\InvalidParameterException; @@ -42,9 +46,11 @@ * * @since 4.0.0 */ -class ContactController extends ApiController implements UserFactoryAwareInterface +class ContactController extends ApiController implements UserFactoryAwareInterface, MailerFactoryAwareInterface, LanguageFactoryAwareInterface { use UserFactoryAwareTrait; + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; /** * The content type of the item. @@ -99,7 +105,8 @@ public function submitForm($id = null) $id = $this->input->post->get('id', 0, 'int'); } - $modelName = Inflector::singularize($this->contentType); + $inflector = InflectorFactory::create()->build(); + $modelName = $inflector->singularize($this->contentType); /** @var \Joomla\Component\Contact\Site\Model\ContactModel $model */ $model = $this->getModel($modelName, 'Site'); @@ -231,7 +238,12 @@ private function _sendEmail($data, $contact, $emailCopyToSender) } try { - $mailer = new MailTemplate('com_contact.mail', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_contact.mail', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addRecipient($contact->email_to); $mailer->setReplyTo($templateData['email'], $templateData['name']); $mailer->addTemplateData($templateData); @@ -239,7 +251,12 @@ private function _sendEmail($data, $contact, $emailCopyToSender) // If we are supposed to copy the sender, do so. if ($emailCopyToSender && !empty($data['contact_email_copy'])) { - $mailer = new MailTemplate('com_contact.mail.copy', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_contact.mail.copy', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addRecipient($templateData['email']); $mailer->setReplyTo($templateData['email'], $templateData['name']); $mailer->addTemplateData($templateData); diff --git a/api/components/com_contact/src/View/Contacts/JsonapiView.php b/api/components/com_contact/src/View/Contacts/JsonapiView.php index 4036a77638264..00d8dfa5e24ed 100644 --- a/api/components/com_contact/src/View/Contacts/JsonapiView.php +++ b/api/components/com_contact/src/View/Contacts/JsonapiView.php @@ -10,8 +10,11 @@ namespace Joomla\Component\Contact\Api\View\Contacts; +use Joomla\CMS\Event\Model\PrepareDataEvent; +use Joomla\CMS\Factory; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; +use Joomla\CMS\Plugin\PluginHelper; use Joomla\Component\Contact\Api\Serializer\ContactSerializer; use Joomla\Component\Content\Api\Helper\ContentHelper; use Joomla\Component\Fields\Administrator\Helper\FieldsHelper; @@ -71,6 +74,7 @@ class JsonapiView extends BaseApiView 'sortname1', 'sortname2', 'sortname3', + 'schemaorg', ]; /** @@ -92,6 +96,7 @@ class JsonapiView extends BaseApiView 'image', 'tags', 'user_id', + 'schemaorg', ]; /** @@ -209,6 +214,37 @@ protected function prepareItem($item) $item->image = ContentHelper::resolve($item->image); } + // Add schema.org data using existing plugin system + if (PluginHelper::isEnabled('system', 'schemaorg')) { + $item->schemaorg = $this->getSchemaOrg($item); + } + return parent::prepareItem($item); } + + /** + * Get schema.org structured data for a contact using the plugin system + * + * @param object $item The contact item + * + * @return array|null + * + * @since 6.1.0 + */ + protected function getSchemaOrg($item) + { + $context = 'com_contact.contact'; + + $event = new PrepareDataEvent('onContentPrepareData', ['context' => $context, 'data' => $item]); + + PluginHelper::importPlugin('system', 'schemaorg'); + Factory::getApplication()->getDispatcher()->dispatch('onContentPrepareData', $event); + + if (isset($item->schema) && !empty($item->schema['schemaType'])) { + $schemaType = $item->schema['schemaType']; + return $item->schema[$schemaType] ?? null; + } + + return null; + } } diff --git a/api/components/com_content/src/Controller/ArticlesController.php b/api/components/com_content/src/Controller/ArticlesController.php index e8873c291aade..8c972f9431168 100644 --- a/api/components/com_content/src/Controller/ArticlesController.php +++ b/api/components/com_content/src/Controller/ArticlesController.php @@ -82,10 +82,22 @@ public function displayList() $this->modelState->set('filter.language', $filter->clean($apiFilterInfo['language'], 'STRING')); } + if (\array_key_exists('modified_start', $apiFilterInfo)) { + $this->modelState->set('filter.modified_start', $filter->clean($apiFilterInfo['modified_start'], 'STRING')); + } + + if (\array_key_exists('modified_end', $apiFilterInfo)) { + $this->modelState->set('filter.modified_end', $filter->clean($apiFilterInfo['modified_end'], 'STRING')); + } + if (\array_key_exists('checked_out', $apiFilterInfo)) { $this->modelState->set('filter.checked_out', $filter->clean($apiFilterInfo['checked_out'], 'INT')); } + if (\array_key_exists('stage', $apiFilterInfo)) { + $this->modelState->set('filter.stage', $filter->clean($apiFilterInfo['stage'], 'INT')); + } + $apiListInfo = $this->input->get('list', [], 'array'); if (\array_key_exists('ordering', $apiListInfo)) { diff --git a/api/components/com_content/src/View/Articles/JsonapiView.php b/api/components/com_content/src/View/Articles/JsonapiView.php index 57274e0b6bac7..af8a96a5b32ae 100644 --- a/api/components/com_content/src/View/Articles/JsonapiView.php +++ b/api/components/com_content/src/View/Articles/JsonapiView.php @@ -10,7 +10,8 @@ namespace Joomla\Component\Content\Api\View\Articles; -use Joomla\CMS\Factory; +use Joomla\CMS\Event\Content\ContentPrepareEvent; +use Joomla\CMS\Event\Model\PrepareDataEvent; use Joomla\CMS\Helper\TagsHelper; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\MVC\View\JsonApiView as BaseApiView; @@ -42,7 +43,13 @@ class JsonapiView extends BaseApiView 'typeAlias', 'asset_id', 'title', + /** + * @deprecated 6.2.0 will be removed in 8.0 + * Will be removed without replacement. + */ 'text', + 'introtext', + 'fulltext', 'tags', 'language', 'state', @@ -67,6 +74,7 @@ class JsonapiView extends BaseApiView 'version', 'featured_up', 'featured_down', + 'schemaorg', ]; /** @@ -80,7 +88,13 @@ class JsonapiView extends BaseApiView 'typeAlias', 'asset_id', 'title', + /** + * @deprecated 6.2.0 will be removed in 8.0 + * Will be removed without replacement. + */ 'text', + 'introtext', + 'fulltext', 'tags', 'language', 'state', @@ -104,6 +118,7 @@ class JsonapiView extends BaseApiView 'version', 'featured_up', 'featured_down', + 'schemaorg', ]; /** @@ -193,11 +208,24 @@ protected function prepareItem($item) return $item; } + /** + * @deprecated 6.2.0 will be removed in 8.0 + * Will be removed without replacement. + */ $item->text = $item->introtext . ' ' . $item->fulltext; + $params = new Registry($item->params ?? '{}'); + // Process the content plugins. - PluginHelper::importPlugin('content'); - Factory::getApplication()->triggerEvent('onContentPrepare', ['com_content.article', &$item, &$item->params]); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); + $dispatcher->dispatch( + 'onContentPrepare', + new ContentPrepareEvent( + 'onContentPrepare', + ['context' => 'com_content.article', 'subject' => $item, 'params' => $params, 'page' => 0] + ) + ); foreach (FieldsHelper::getFields('com_content.article', $item, true) as $field) { $item->{$field->name} = $field->apivalue ?? $field->rawvalue; @@ -245,6 +273,37 @@ protected function prepareItem($item) } } + // Add schema.org data using existing plugin system + if (PluginHelper::isEnabled('system', 'schemaorg')) { + $item->schemaorg = $this->getSchemaOrg($item); + } + return parent::prepareItem($item); } + + /** + * Get schema.org structured data for an article using the plugin system + * + * @param object $item The article item + * + * @return array|null + * + * @since 6.1.0 + */ + protected function getSchemaOrg($item) + { + $context = 'com_content.article'; + $event = new PrepareDataEvent('onContentPrepareData', ['context' => $context, 'data' => $item]); + + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('system', 'schemaorg', true, $dispatcher); + $dispatcher->dispatch('onContentPrepareData', $event); + + if (isset($item->schema) && !empty($item->schema['schemaType'])) { + $schemaType = $item->schema['schemaType']; + return $item->schema[$schemaType] ?? null; + } + + return null; + } } diff --git a/api/components/com_fields/src/Controller/FieldsController.php b/api/components/com_fields/src/Controller/FieldsController.php index f98abb8eef2c2..da1fe66357dca 100644 --- a/api/components/com_fields/src/Controller/FieldsController.php +++ b/api/components/com_fields/src/Controller/FieldsController.php @@ -10,7 +10,7 @@ namespace Joomla\Component\Fields\Api\Controller; -use Joomla\CMS\Access\Exception\NotAllowed; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\MVC\Controller\ApiController; // phpcs:disable PSR1.Files.SideEffects @@ -92,13 +92,19 @@ private function getContextFromInput() * * @return boolean * - * @since 5.4.7 + * @since 6.1.2 */ protected function allowAdd($data = []) { + $user = $this->app->getIdentity(); [$option] = explode('.', $this->getContextFromInput()); - return $this->app->getIdentity()->authorise('core.create', $option); + // Require generic management permissions for the component + if (!$user->authorise('core.manage', $option)) { + return false; + } + + return $user->authorise('core.create', $option); } /** @@ -111,7 +117,7 @@ protected function allowAdd($data = []) * * @return boolean * - * @since 5.4.7 + * @since 6.1.2 */ protected function allowEdit($data = [], $key = 'id') { @@ -119,11 +125,31 @@ protected function allowEdit($data = [], $key = 'id') $user = $this->app->getIdentity(); [$option] = explode('.', $this->getContextFromInput()); + // Require generic management permissions for the component + if (!$user->authorise('core.manage', $option)) { + return false; + } + // Zero record (id:0), return component edit permission by calling parent controller method if (!$recordId) { return $user->authorise('core.edit', $option); } + // Get existing record + $inflector = InflectorFactory::create()->build(); + $record = $this->getModel($inflector->singularize($this->contentType))->getItem($recordId); + + if (empty($record)) { + return false; + } + + [$recordOption] = explode('.', $record->context); + + // Validate request context and field context match + if ($recordOption !== $option) { + return false; + } + // Check edit on the record asset (explicit or inherited) if ($user->authorise('core.edit', $option . '.field.' . $recordId)) { return true; @@ -131,13 +157,6 @@ protected function allowEdit($data = [], $key = 'id') // Check edit own on the record asset (explicit or inherited) if ($user->authorise('core.edit.own', $option . '.field.' . $recordId)) { - // Existing record already has an owner, get it - $record = $this->getModel()->getItem($recordId); - - if (empty($record)) { - return false; - } - // Grant if current user is owner of the record return $user->id == $record->created_user_id; } @@ -146,22 +165,22 @@ protected function allowEdit($data = [], $key = 'id') } /** - * Removes an item. - * - * @param integer $id The primary key to delete item. + * Method to check if it's allowed to delete a record * - * @return void + * @return boolean * - * @since 5.4.7 + * @since 6.1.3 */ - public function delete($id = null) + protected function allowDelete(): bool { [$option] = explode('.', $this->getContextFromInput()); + $user = $this->app->getIdentity(); - if (!$this->app->getIdentity()->authorise('core.delete', $option)) { - throw new NotAllowed('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED', 403); + // Require generic management permissions for the component + if (!$user->authorise('core.manage', $option)) { + return false; } - parent::delete($id); + return $user->authorise('core.delete', $option); } } diff --git a/api/components/com_fields/src/Controller/GroupsController.php b/api/components/com_fields/src/Controller/GroupsController.php index aafe4b64625f4..d70b58872db27 100644 --- a/api/components/com_fields/src/Controller/GroupsController.php +++ b/api/components/com_fields/src/Controller/GroupsController.php @@ -10,7 +10,7 @@ namespace Joomla\Component\Fields\Api\Controller; -use Joomla\CMS\Access\Exception\NotAllowed; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\MVC\Controller\ApiController; // phpcs:disable PSR1.Files.SideEffects @@ -92,13 +92,18 @@ private function getContextFromInput() * * @return boolean * - * @since 5.4.7 + * @since 6.1.2 */ protected function allowAdd($data = []) { + $user = $this->app->getIdentity(); [$option] = explode('.', $this->getContextFromInput()); - return $this->app->getIdentity()->authorise('core.create', $option); + if (!$user->authorise('core.manage', $option)) { + return false; + } + + return $user->authorise('core.create', $option); } /** @@ -111,7 +116,7 @@ protected function allowAdd($data = []) * * @return boolean * - * @since 5.4.7 + * @since 6.1.2 */ protected function allowEdit($data = [], $key = 'parent_id') { @@ -119,11 +124,31 @@ protected function allowEdit($data = [], $key = 'parent_id') $user = $this->app->getIdentity(); [$option] = explode('.', $this->getContextFromInput()); + // Require generic management permissions for the component + if (!$user->authorise('core.manage', $option)) { + return false; + } + // Zero record (id:0), return component edit permission by calling parent controller method if (!$recordId) { return $user->authorise('core.edit', $option); } + // Get existing record + $inflector = InflectorFactory::create()->build(); + $record = $this->getModel($inflector->singularize($this->contentType))->getItem($recordId); + + if (empty($record)) { + return false; + } + + [$recordOption] = explode('.', $record->context); + + // Validate request context and field context match + if ($recordOption !== $option) { + return false; + } + // Check edit on the record asset (explicit or inherited) if ($user->authorise('core.edit', $option . '.fieldgroup.' . $recordId)) { return true; @@ -146,22 +171,22 @@ protected function allowEdit($data = [], $key = 'parent_id') } /** - * Removes an item. + * Method to check if it's allowed to delete a record * - * @param integer $id The primary key to delete item. - * - * @return void + * @return boolean * - * @since 5.4.7 + * @since 6.1.3 */ - public function delete($id = null) + protected function allowDelete(): bool { [$option] = explode('.', $this->getContextFromInput()); + $user = $this->app->getIdentity(); - if (!$this->app->getIdentity()->authorise('core.delete', $option)) { - throw new NotAllowed('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED', 403); + // Require generic management permissions for the component + if (!$user->authorise('core.manage', $option)) { + return false; } - parent::delete($id); + return $user->authorise('core.delete', $option); } } diff --git a/api/components/com_joomlaupdate/src/Controller/BaseController.php b/api/components/com_joomlaupdate/src/Controller/BaseController.php index 01921242d5726..4c2125a00266d 100644 --- a/api/components/com_joomlaupdate/src/Controller/BaseController.php +++ b/api/components/com_joomlaupdate/src/Controller/BaseController.php @@ -22,7 +22,7 @@ abstract class BaseController extends ApiController * * @return void * - * @since 5.4.0 + * @since 6.0.0 * * @throws \Exception */ diff --git a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php index 044949636d224..57998b47f40c8 100644 --- a/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php +++ b/api/components/com_joomlaupdate/src/Controller/HealthcheckController.php @@ -20,7 +20,7 @@ /** * The healthcheck controller * - * @since 5.4.0 + * @since 6.0.0 */ class HealthcheckController extends BaseController { @@ -28,7 +28,7 @@ class HealthcheckController extends BaseController * The content type of the item. * * @var string - * @since 5.4.0 + * @since 6.0.0 */ protected $contentType = 'healthcheck'; @@ -36,7 +36,7 @@ class HealthcheckController extends BaseController * The default view for the display method. * * @var string - * @since 5.4.0 + * @since 6.0.0 */ protected $default_view = 'healthcheck'; @@ -45,7 +45,7 @@ class HealthcheckController extends BaseController * * @return HealthcheckController * - * @since 5.4.0 + * @since 6.0.0 */ public function show() { @@ -94,7 +94,7 @@ public function show() * * @return static A \JControllerLegacy object to support chaining. * - * @since 5.4.0 + * @since 6.0.0 */ public function displayItem($id = null) { @@ -106,7 +106,7 @@ public function displayItem($id = null) * * @return static A BaseController object to support chaining. * - * @since 5.4.0 + * @since 6.0.0 */ public function displayList() { @@ -120,7 +120,7 @@ public function displayList() * * @return void * - * @since 5.4.0 + * @since 6.0.0 */ public function delete($id = null) { @@ -137,7 +137,7 @@ public function delete($id = null) * * @return boolean * - * @since 5.4.0 + * @since 6.0.0 */ protected function allowEdit($data = [], $key = 'id') { @@ -153,7 +153,7 @@ protected function allowEdit($data = [], $key = 'id') * * @return boolean * - * @since 5.4.0 + * @since 6.0.0 */ protected function allowAdd($data = []) { diff --git a/api/components/com_joomlaupdate/src/Controller/NotificationController.php b/api/components/com_joomlaupdate/src/Controller/NotificationController.php index da52aa37fc63b..359004d8ab0c8 100644 --- a/api/components/com_joomlaupdate/src/Controller/NotificationController.php +++ b/api/components/com_joomlaupdate/src/Controller/NotificationController.php @@ -21,7 +21,7 @@ /** * The updates controller * - * @since 5.4.0 + * @since 6.0.0 */ class NotificationController extends BaseController { @@ -29,7 +29,7 @@ class NotificationController extends BaseController * The content type of the item. * * @var string - * @since 5.4.0 + * @since 6.0.0 */ protected $contentType = 'notification'; @@ -37,7 +37,7 @@ class NotificationController extends BaseController * The default view for the display method. * * @var string - * @since 5.4.0 + * @since 6.0.0 */ protected $default_view = 'notification'; @@ -65,7 +65,7 @@ public function failed() * * @return NotificationController * - * @since 5.4.0 + * @since 6.0.0 */ public function success() { @@ -126,7 +126,7 @@ protected function prepareView() * * @return static A \JControllerLegacy object to support chaining. * - * @since 5.4.0 + * @since 6.0.0 */ public function displayItem($id = null) { @@ -138,7 +138,7 @@ public function displayItem($id = null) * * @return static A BaseController object to support chaining. * - * @since 5.4.0 + * @since 6.0.0 */ public function displayList() { @@ -152,7 +152,7 @@ public function displayList() * * @return void * - * @since 5.4.0 + * @since 6.0.0 */ public function delete($id = null) { @@ -169,7 +169,7 @@ public function delete($id = null) * * @return boolean * - * @since 5.4.0 + * @since 6.0.0 */ protected function allowEdit($data = [], $key = 'id') { @@ -185,7 +185,7 @@ protected function allowEdit($data = [], $key = 'id') * * @return boolean * - * @since 5.4.0 + * @since 6.0.0 */ protected function allowAdd($data = []) { diff --git a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php index 957906812dde0..439ca63955943 100644 --- a/api/components/com_joomlaupdate/src/Controller/UpdatesController.php +++ b/api/components/com_joomlaupdate/src/Controller/UpdatesController.php @@ -20,7 +20,7 @@ /** * The updates controller * - * @since 5.4.0 + * @since 6.0.0 */ class UpdatesController extends BaseController { @@ -28,7 +28,7 @@ class UpdatesController extends BaseController * The content type of the item. * * @var string - * @since 5.4.0 + * @since 6.0.0 */ protected $contentType = 'updates'; @@ -36,7 +36,7 @@ class UpdatesController extends BaseController * The default view for the display method. * * @var string - * @since 5.4.0 + * @since 6.0.0 */ protected $default_view = 'updates'; @@ -61,7 +61,7 @@ public function getUpdate() * * @return UpdatesController * - * @since 5.4.0 + * @since 6.0.0 */ public function prepareUpdate() { @@ -154,7 +154,7 @@ protected function prepareView() * * @return static A \JControllerLegacy object to support chaining. * - * @since 5.4.0 + * @since 6.0.0 */ public function displayItem($id = null) { @@ -166,7 +166,7 @@ public function displayItem($id = null) * * @return static A BaseController object to support chaining. * - * @since 5.4.0 + * @since 6.0.0 */ public function displayList() { @@ -180,7 +180,7 @@ public function displayList() * * @return void * - * @since 5.4.0 + * @since 6.0.0 */ public function delete($id = null) { @@ -197,7 +197,7 @@ public function delete($id = null) * * @return boolean * - * @since 5.4.0 + * @since 6.0.0 */ protected function allowEdit($data = [], $key = 'id') { @@ -213,7 +213,7 @@ protected function allowEdit($data = [], $key = 'id') * * @return boolean * - * @since 5.4.0 + * @since 6.0.0 */ protected function allowAdd($data = []) { diff --git a/api/components/com_languages/src/Controller/OverridesController.php b/api/components/com_languages/src/Controller/OverridesController.php index 3bc20ec0ef9e8..1eb8e3528e378 100644 --- a/api/components/com_languages/src/Controller/OverridesController.php +++ b/api/components/com_languages/src/Controller/OverridesController.php @@ -10,11 +10,11 @@ namespace Joomla\Component\Languages\Api\Controller; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\ApiController; use Joomla\CMS\MVC\Controller\Exception; -use Joomla\String\Inflector; use Tobscure\JsonApi\Exception\InvalidParameterException; // phpcs:disable PSR1.Files.SideEffects @@ -87,8 +87,11 @@ public function displayList() */ protected function save($recordKey = null) { + $inflector = InflectorFactory::create()->build(); + $modelName = $inflector->singularize($this->contentType); + /** @var \Joomla\CMS\MVC\Model\AdminModel $model */ - $model = $this->getModel(Inflector::singularize($this->contentType)); + $model = $this->getModel($modelName); if (!$model) { throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_MODEL_CREATE')); diff --git a/api/components/com_media/src/Controller/MediaController.php b/api/components/com_media/src/Controller/MediaController.php index eb53e194a85d6..3dd34e09488c4 100644 --- a/api/components/com_media/src/Controller/MediaController.php +++ b/api/components/com_media/src/Controller/MediaController.php @@ -10,6 +10,7 @@ namespace Joomla\Component\Media\Api\Controller; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\Access\Exception\NotAllowed; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Filter\InputFilter; @@ -19,7 +20,6 @@ use Joomla\Component\Media\Administrator\Exception\InvalidPathException; use Joomla\Component\Media\Administrator\Provider\ProviderManagerHelperTrait; use Joomla\Component\Media\Api\Model\MediumModel; -use Joomla\String\Inflector; use Tobscure\JsonApi\Exception\InvalidParameterException; // phpcs:disable PSR1.Files.SideEffects @@ -243,6 +243,11 @@ protected function allowAdd($data = []): bool { $user = $this->app->getIdentity(); + // Require generic management permissions for the component + if (!$user->authorise('core.manage', 'com_media')) { + return false; + } + // In the override mode, adding a file will override and therefore edit an existing file if ($this->input->json->get('override', false)) { return $user->authorise('core.edit', 'com_media'); @@ -303,6 +308,11 @@ protected function allowEdit($data = [], $key = 'id'): bool { $user = $this->app->getIdentity(); + // Require generic management permissions for the component + if (!$user->authorise('core.manage', 'com_media')) { + return false; + } + // com_media's access rules contains no specific update rule. return $user->authorise('core.edit', 'com_media'); } @@ -319,7 +329,8 @@ protected function allowEdit($data = [], $key = 'id'): bool protected function save($recordKey = null) { // Explicitly get the single item model name. - $modelName = $this->input->get('model', Inflector::singularize($this->contentType)); + $inflector = InflectorFactory::create()->build(); + $modelName = $this->input->get('model', $inflector->singularize($this->contentType)); /** @var MediumModel $model */ $model = $this->getModel($modelName, '', ['ignore_request' => true, 'state' => $this->modelState]); @@ -382,7 +393,8 @@ public function delete($id = null): void $this->modelState->set('path', $this->input->get('path', '', 'STRING')); - $modelName = $this->input->get('model', Inflector::singularize($this->contentType)); + $inflector = InflectorFactory::create()->build(); + $modelName = $this->input->get('model', $inflector->singularize($this->contentType)); $model = $this->getModel($modelName, '', ['ignore_request' => true, 'state' => $this->modelState]); $model->delete(); @@ -401,6 +413,11 @@ protected function allowDelete(): bool { $user = $this->app->getIdentity(); + // Require generic management permissions for the component + if (!$user->authorise('core.manage', 'com_media')) { + return false; + } + return $user->authorise('core.delete', 'com_media'); } } diff --git a/api/components/com_plugins/src/Controller/PluginsController.php b/api/components/com_plugins/src/Controller/PluginsController.php index a402d46dd2a11..f487cf0d53e07 100644 --- a/api/components/com_plugins/src/Controller/PluginsController.php +++ b/api/components/com_plugins/src/Controller/PluginsController.php @@ -10,12 +10,12 @@ namespace Joomla\Component\Plugins\Api\Controller; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\Filter\InputFilter; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Controller\ApiController; use Joomla\CMS\MVC\Controller\Exception; use Joomla\CMS\Router\Exception\RouteNotFoundException; -use Joomla\String\Inflector; use Tobscure\JsonApi\Exception\InvalidParameterException; // phpcs:disable PSR1.Files.SideEffects @@ -70,7 +70,8 @@ public function edit() } /** @var \Joomla\Component\Plugins\Administrator\Model\PluginModel $model */ - $model = $this->getModel(Inflector::singularize($this->contentType), '', ['ignore_request' => true]); + $inflector = InflectorFactory::create()->build(); + $model = $this->getModel($inflector->singularize($this->contentType), '', ['ignore_request' => true]); if (!$model) { throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_MODEL_CREATE')); diff --git a/api/components/com_privacy/src/Controller/ConsentsController.php b/api/components/com_privacy/src/Controller/ConsentsController.php index 770a2e26491f9..950bcdd4b83f7 100644 --- a/api/components/com_privacy/src/Controller/ConsentsController.php +++ b/api/components/com_privacy/src/Controller/ConsentsController.php @@ -69,7 +69,7 @@ public function displayItem($id = null) * * @return static A \JControllerLegacy object to support chaining. * - * @since 5.4.7 + * @since 6.1.2 */ public function displayList() { diff --git a/api/components/com_privacy/src/Controller/RequestsController.php b/api/components/com_privacy/src/Controller/RequestsController.php index a301a318bb473..eddfde719cafc 100644 --- a/api/components/com_privacy/src/Controller/RequestsController.php +++ b/api/components/com_privacy/src/Controller/RequestsController.php @@ -48,7 +48,7 @@ class RequestsController extends ApiController * * @return static A \JControllerLegacy object to support chaining. * - * @since 5.4.7 + * @since 6.1.2 */ public function displayItem($id = null) { @@ -64,7 +64,7 @@ public function displayItem($id = null) * * @return static A \JControllerLegacy object to support chaining. * - * @since 5.4.7 + * @since 6.1.2 */ public function displayList() { diff --git a/api/components/com_templates/src/Controller/StylesController.php b/api/components/com_templates/src/Controller/StylesController.php index e973c2bfb50fc..319a3ed77dc46 100644 --- a/api/components/com_templates/src/Controller/StylesController.php +++ b/api/components/com_templates/src/Controller/StylesController.php @@ -10,8 +10,8 @@ namespace Joomla\Component\Templates\Api\Controller; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\MVC\Controller\ApiController; -use Joomla\String\Inflector; use Tobscure\JsonApi\Exception\InvalidParameterException; // phpcs:disable PSR1.Files.SideEffects @@ -91,7 +91,8 @@ protected function preprocessSaveData(array $data): array unset($data['template']); } - $model = $this->getModel(Inflector::singularize($this->contentType), '', ['ignore_request' => true]); + $inflector = InflectorFactory::create()->build(); + $model = $this->getModel($inflector->singularize($this->contentType), '', ['ignore_request' => true]); $data['template'] = $model->getItem($this->input->getInt('id'))->template; } diff --git a/api/components/com_users/src/Controller/GroupsController.php b/api/components/com_users/src/Controller/GroupsController.php index beb644d7b606d..4d55cd5b3827c 100644 --- a/api/components/com_users/src/Controller/GroupsController.php +++ b/api/components/com_users/src/Controller/GroupsController.php @@ -48,6 +48,7 @@ class GroupsController extends ApiController * @return void * * @since 5.4.6 + * @since 6.1.1 */ public function delete($id = null) { @@ -65,7 +66,7 @@ public function delete($id = null) * * @return boolean * - * @since 5.4.6 + * @since 6.1.1 */ public function allowAdd($data = []) { @@ -81,7 +82,7 @@ public function allowAdd($data = []) * * @return boolean * - * @since 5.4.6 + * @since 6.1.1 */ public function allowEdit($data = [], $key = 'id') { diff --git a/api/components/com_users/src/Controller/LevelsController.php b/api/components/com_users/src/Controller/LevelsController.php index f9ba6fbaeb965..65ffeac9c231c 100644 --- a/api/components/com_users/src/Controller/LevelsController.php +++ b/api/components/com_users/src/Controller/LevelsController.php @@ -46,7 +46,7 @@ class LevelsController extends ApiController * * @return array * - * @since 5.4.7 + * @since 6.2.0 */ protected function preprocessSaveData(array $data): array { diff --git a/api/index.php b/api/index.php index 39b7bd8adceda..1c5503555e75d 100644 --- a/api/index.php +++ b/api/index.php @@ -10,7 +10,7 @@ // NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message // Define the application's minimum supported PHP version as a constant so it can be referenced within the application. -\define('JOOMLA_MINIMUM_PHP', '8.1.0'); +\define('JOOMLA_MINIMUM_PHP', '8.3.0'); if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<')) { header('HTTP/1.1 500 Internal Server Error'); diff --git a/api/language/en-GB/install.xml b/api/language/en-GB/install.xml index 5140dd502989d..893b7100a260d 100644 --- a/api/language/en-GB/install.xml +++ b/api/language/en-GB/install.xml @@ -2,7 +2,7 @@ English (en-GB) en-GB - 5.4.8 + 6.2.0 2026-08 Joomla! Project admin@joomla.org diff --git a/api/language/en-GB/joomla.ini b/api/language/en-GB/joomla.ini index 3ec784a0409df..18fde5672d4c2 100644 --- a/api/language/en-GB/joomla.ini +++ b/api/language/en-GB/joomla.ini @@ -219,8 +219,11 @@ JFIELD_COLOR_LABEL_SLIDER_HUE="Hue Slider" JFIELD_COLOR_LABEL_SLIDER_INPUT="Selected Colour Value" JFIELD_COLOR_LABEL_SLIDER_LIGHT="Light Slider" JFIELD_COLOR_LABEL_SLIDER_SATURATION="Saturation Slider" +; The following string is deprecated and will be removed with 7.0 JFIELD_COLOR_SELECT="Select a colour" +; The following string is deprecated and will be removed with 7.0 JFIELD_COLOR_TRANSPARENT="No colour, transparent" +; The following string is deprecated and will be removed with 7.0 JFIELD_COLOR_VALUE="Colour with hexadecimal value of" JFIELD_DISPLAY_READONLY_LABEL="Display When Read-Only" JFIELD_ENABLED_DESC="The enabled status of this item." @@ -643,6 +646,7 @@ JGLOBAL_SHOW_READMORE_TITLE_DESC="If set to show the title of the Article will b JGLOBAL_SHOW_READMORE_TITLE_LABEL="Read More with Title" JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_DESC="Show or hide the subcategories descriptions." JGLOBAL_SHOW_SUBCATEGORIES_DESCRIPTION_LABEL="Subcategories Descriptions" +JGLOBAL_SHOW_SUBCATEGORIES_IMAGE_LABEL="Subcategories Image" JGLOBAL_SHOW_SUBCATEGORY_CONTENT_DESC="If None, only articles from this category will show. If a number, all articles from the category and the subcategories up to and including that level will show in the blog." JGLOBAL_SHOW_SUBCATEGORY_CONTENT_LABEL="Include Subcategories" JGLOBAL_SHOW_SUBCATEGORY_HEADING="Subcategories Heading" @@ -683,8 +687,6 @@ JGLOBAL_VOTES="Votes" JGLOBAL_VOTES_ASC="Votes ascending" JGLOBAL_VOTES_DESC="Votes descending" JGLOBAL_WARNCOOKIES="Warning! Cookies must be enabled to access the Administrator Backend." -; @deprecated 5.0 will be removed in 6.0 -JGLOBAL_WARNIE="Warning! Internet Explorer should not be used for proper operation of the Administrator Backend." JGLOBAL_WARNJAVASCRIPT="Warning! JavaScript must be enabled for proper operation of the Administrator Backend." JGLOBAL_WIDTH="Width" @@ -915,6 +917,7 @@ PHPMAILER_RECIPIENTS_FAILED="SMTP Error! The following recipients failed: " PHPMAILER_SIGNING_ERROR="Signing error: " PHPMAILER_SMTP_CONNECT_FAILED="SMTP connect failed" PHPMAILER_SMTP_ERROR="SMTP server error: " +; Deprecated, will be removed with 7.0 PHPMAILER_TLS="Could not start TLS" PHPMAILER_VARIABLE_SET="Can't set or reset variable: " diff --git a/api/language/en-GB/langmetadata.xml b/api/language/en-GB/langmetadata.xml index eb2060e268897..b4225492b0423 100644 --- a/api/language/en-GB/langmetadata.xml +++ b/api/language/en-GB/langmetadata.xml @@ -1,7 +1,7 @@ English (en-GB) - 5.4.8 + 6.2.0 2026-08 Joomla! Project admin@joomla.org diff --git a/build.xml b/build.xml deleted file mode 100644 index 494ad4fd69769..0000000000000 --- a/build.xml +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/build/README.md b/build/README.md index d9509e73624da..fd7d2899f6d2b 100644 --- a/build/README.md +++ b/build/README.md @@ -6,65 +6,34 @@ Joomla provides a set of tools for managing static assets and dependencies based The responsibilities of these tools are: - To copy files from the `node-modules` folder to the `media` folder. - Do any transformations on the copied files. -- Update the version numbers on the XML files of the TinyMCE and CodeMirror editors. -- Copy files from the `build/media_source` folder to the `media` folder. +- Copy files from the `media_source/` folder to the `media` folder. - Transform any modern JS to ES2017 and transpile it to ES5. - Transform any SCSS file to the respective CSS file. For some of these operations, conventions were established to simplify and speed up the process. -## Javascript -There are three options here: -- Modern Javascript files must have an extension `.es6.js`. - This allows ESLint to check the code style, Joomla is using the Airbnb preset https://github.com/airbnb/javascript. - It also instructs Rollup to do the transforms for ES2017. This step creates both normal and minified files. - Production code WILL NOT have the `.es6` part for ES2017+ files. +Read more at [CMS Media source](../media_source/README.md). -- Web Component Javascript files must have an extension `.w-c.es6.js`. - This allows ESLint to check the code style and instructs Rollup to do the transforms for ES2017. This step creates normal and minified files. The difference with the `.es6` files is that the tools will automate the minification of the CSS (assuming that the appropriate SCSS file exists), which is then injected into the JS file in place of the placeholder `{{CSS_CONTENTS_PLACEHOLDER}}` (ie: `build/media_source/system/js/joomla-core-loader.w-c.es6.js`) - Production code WILL NOT have the `.w-c.es6` part for ES2017+. -- Legacy Javascript files must have an extension `.es5.js`. - This instructs ESLint to skip checking this file. - Also, it instructs the tools to create a minified version (production code WILL NOT have the `.es5` part) - -- Javascript files with only an extension `.js`. - These files will be ignored by the build tools. - -## SCSS -- SCSS files starting with `_` will not become entry points for SCSS. - SCSS files will be transformed to CSS, both normal and minified versions. - -## CSS -- CSS files will only get minified. +## NPM Commands +- `npm run builders-list` Show list of available builders in order of execution. +- `npm run build` Build assets with production env. Extra arguments are required. Check [CMS Media source](../media_source/README.md#building-assets). +- `npm run build:dev` Build assets with development env. Extra arguments are required. Check [CMS Media source](../media_source/README.md#building-assets). +- `npm run watch` Start files watcher for specified asset with production env\ +Example `npm run watch -- -n com_content` for `com_content` assets.\ +Example `npm run watch -- --all` for all assets. +- `npm run watch:dev` Start files watcher for specified asset with development env. +- `npm run lint:js` Checks the code style for the JavaScript/Vue files +- `npm run lint:testjs` Checks the code style for the JavaScript/Vue files under `tests/System` used for testing. +- `npm run lint:css` Checks the code style for all SCSS files. +- `npm run gzip` Creates `.gz` files for all the `.min.js` and `.min.css`. -## NPM Commands -- `npm run build:js`: compiles ALL the JS (excluding Bootstrap and Media Manager). -- `npm run build:js -- build/media_source/com_actionlogs`: compiles ALL the JS ONLY in the folder `build/media_source/com_actionlogs`. -- `npm run build:css`: compiles ALL the SCSS. -- `npm run build:css -- templates/cassiopeia`: compiles ALL the SCSS ONLY in the folder `templates/cassiopeia`. -- `npm run build:bs5`: Builds the Bootstrap Javascript components. -- `npm run build:com_media`: Builds the Media Manager Vue Application. -- `npm run build:com_media:dev`: Builds the Media Manager Vue Application but in DEV mode, (no minification, no es5 and all flags for the vue devtools) -- `npm run lint:js`: Checks the code style for all the Javascript/Vue files. -- `npm run lint:js -- --fix`: Checks and fixes the code style for all the Javascript/Vue files (might not fix everything). -- `npm run lint:css`: Checks the code style for all SCSS files. -- `npm run lint:css -- --fix`: Checks and fixes the code style for all SCSS files (might not fix everything). -- `npm run gzip`: Creates `.gz` files for all the `.min.js` and `.min.css`. -- `npm run versioning`: Creates the correct version hash for all the assets inside the joomla.asset.json files (excluding templates). ## Working Efficiently with the Joomla Build Tools Usually, the scope of a single contribution to the project should be limited. For example: fixing a CSS bug, a Javascript bug, some Markup, or a bug that involves changes in all these areas. The build tools were created so that you spend less time on compiling assets than testing a possible solution. -*Embrace the watchers* -Let the computer help you succeed faster and safer. There are 2 watchers at the moment: one for the Media Manager (client app based on VueJS) and another one that handles templates and the source (build) folder. - -Assuming that you are working on the Media Manager, you can run in your terminal (already in the root folder of the Joomla repo) `npm run watch:com_media`. This watcher will automatically recompile the app on every save (there is a debounce of 0.3s, so if you have autosave it will be a clever way to minimise the wait). - -Assuming that you are working on the Web Authentication JavaScript, you can run in your terminal (already in the root folder of the Joomla repo) `npm run watch -- build/media_source/plg_system_webauthn`. This watcher will automatically recompile any JavaScript file inside the folder `build/media_source/plg_system_webauthn/js` on every save. But there's more! Since you asked the watcher to check the parent folder (eg `build/media_source/plg_system_webauthn`), you can also edit the SCSS files in the `build/media_source/plg_system_webauthn/scss` or the CSS files in `build/media_source/plg_system_webauthn/css`. The same example for editing some SCSS in the Cassiopeia template would require a command like: `npm run watch -- templates/cassiopeia/scss`. - Once you get your code doing what it is meant to do, make sure that you check you are not breaking any of the Code Style rules by running `npm run lint:css -- --fix` and `npm run lint:js -- --fix` (the `-- --fix` will try to fix anything that's not trivial). Happy coding diff --git a/build/build-modules-js/builder/builder-factory.mjs b/build/build-modules-js/builder/builder-factory.mjs new file mode 100644 index 0000000000000..c3a41f485883c --- /dev/null +++ b/build/build-modules-js/builder/builder-factory.mjs @@ -0,0 +1,83 @@ +/** + * Builder factory class + */ +import { pathToFileURL } from 'node:url'; +import path from 'node:path'; +import fs from 'node:fs'; +import DefaultModuleBuilder from './default-module-builder.mjs'; + +export class BuilderFactory { + constructor(basePath = '', targetPath = '', cmdOptions = {}) { + this.basePath = basePath; + this.targetPath = targetPath; + this.cmdOptions = cmdOptions; + } + + async createBuilder(name) { + // Module path + let modulePath = path.join(this.basePath, name, 'builder.mjs'); + + // Check if we have the builder module + if (!fs.existsSync(modulePath)) { + // Use default module + return new DefaultModuleBuilder(name, this.basePath, this.targetPath, this.cmdOptions); + } + let resolvedPath = path.resolve(modulePath); + resolvedPath = resolvedPath.replace(/\\/g, '/'); + const fileURL = pathToFileURL(resolvedPath).href; + + return import(fileURL).then((module) => { + return new module.default(name, this.basePath, this.targetPath, this.cmdOptions); + }); + } +} + +/** + * Create and run the builder + * + * @param { Command } program + * @param { String } name + * @param { BuilderFactory } factory + * @param { string[] } tasksToRun + * @param { boolean } skipUndefinedTask + * @return { Promise } + */ +export const createAndRunBuilder = async (program, name, factory, tasksToRun = [], skipUndefinedTask = false) => { + return factory.createBuilder(name) + .then((builder) => { + if (!builder.getBuildTasks) { + program.error(`Builder module for "${name}" should provide "getBuildTasks()" method. This is used to determine which task can be run for the builder.`); + } + console.log(`Initialize build [${name}]`); + + // Run tasks for given builder + const allTasks = builder.getAllTasks ? builder.getAllTasks() : builder.getBuildTasks(); + let lastPromise = Promise.resolve(); + (tasksToRun.length ? tasksToRun : builder.getBuildTasks()).forEach((taskName) => { + // Check whether the task is allowed for active builder + if (!allTasks.includes(taskName)) { + // Show error when the builder and the task was specified, and it is not applicable for active builder. + if (!skipUndefinedTask) { + program.error(`Task "${taskName}" is not applicable for "${name}" builder.`); + } + return; + } + + // Execute the task sequentially, this is needed because task may depend on each other + lastPromise = lastPromise.then(() => { + console.log(`Start task [${name}::${taskName}]`); + + return builder[taskName]().then(async () => { + console.log('\x1b[32m%s\x1b[0m', `Completed task [${name}::${taskName}]`); + }).catch((error) => { + console.log('\x1b[31m%s\x1b[0m', `Failed Task [${name}::${taskName}]`); + console.trace(error); + program.error(error.message); + }); + }); + }); + return lastPromise; + }).then(() => { + console.log('\x1b[32m%s\x1b[0m', `Completed build [${name}]`); + }); +}; diff --git a/build/build-modules-js/builder/default-module-builder.mjs b/build/build-modules-js/builder/default-module-builder.mjs new file mode 100644 index 0000000000000..2fbcefa18ef0d --- /dev/null +++ b/build/build-modules-js/builder/default-module-builder.mjs @@ -0,0 +1,304 @@ +/** + * Default Assets Builder + */ + +import fs from 'node:fs'; +import fsp from 'node:fs/promises'; +import path, { sep } from 'node:path'; +import chokidar from 'chokidar'; +import { handleCSSFile } from '../stylesheets/css-handler.mjs'; +import { handleSCSSFile } from '../stylesheets/scss-handler.mjs'; +import { handleMJSFile, handleJSFile } from '../javascript/js-handle.mjs'; +import { compressFileAndSave } from '../utils/compressFile.mjs'; + +export default class DefaultModuleBuilder { + /** + * List of tasks to be executed by default for the build process. + * Basically list all of the class methods that are allowed to be called from CLI. + * + * @type {string[]} + */ + tasksBuild = ['clear', 'copy', 'css', 'js']; + + /** + * List of extra tasks that the builder can run, but which are not executed during the build process. + * + * @type {string[]} + */ + tasksExtras = ['gzip']; + + /** + * Class constructor. + * + * @param { string } name The folder (builder) name. Relative to media/. + * @param { string } basePath Base path to the media source, without builder name. + * @param { string } targetPath Path to the media target, without builder name. + * @param { object } options Options object, from cmd or etc. + */ + constructor(name = '', basePath = '', targetPath = '', options = {}) { + if (!name) { + throw new Error('Argument "name" is required for ModuleBuilder.'); + } + + if (!basePath || !targetPath) { + throw new Error(`Arguments "basePath" and "targetPath" is required for "${name}" ModuleBuilder.`); + } + + this.name = name; + this.basePath = path.join(basePath, name); + this.targetPath = path.join(targetPath, name); + this.options = options; + } + + getAllTasks() { + return [...this.tasksBuild, ...this.tasksExtras]; + } + + getBuildTasks() { + return this.tasksBuild; + } + + /** + * Remove files on target location + * @returns { Promise } + */ + async clear() { + if (!fs.existsSync(this.targetPath)) { + return; + } + + return fsp.rm(this.targetPath, { recursive: true }); + } + + /** + * Copy files to target location. + * Skip: + * - css and js files + * - build.mjs and src/ and folders contain builder.mjs or .buildignore + * + * @returns { Promise } + */ + async copy() { + const ignoreName = { + 'builder.mjs': true, + src: true, + '.buildignore': true, + }; + const ignoreExt = { + '.js': true, + '.css': true, + }; + + const filterFunc = (src, dest) => { + if (dest === this.targetPath) { + return true; + } + + const baseName = path.basename(src); + const fileStat = fs.statSync(src); + + // Skip ignored files/folders + if (ignoreName[baseName]) { + return false; + } + + // Skip files with extensions + if (fileStat.isFile() && ignoreExt[path.extname(baseName)]) { + return false; + } + + // Skip folders for child modules or explicitly ignored + if (fs.existsSync(path.join(src, 'builder.mjs')) || fs.existsSync(path.join(src, '.buildignore'))) { + return false; + } + + return true; + }; + + return fsp.cp(this.basePath, this.targetPath, { filter: filterFunc, recursive: true }); + } + + /** + * Process CSS files + * @returns { Promise } + */ + async css() { + // Collect files + const cssFiles = []; + const scssFiles = []; + + return fsp.readdir(this.basePath, { recursive: true, withFileTypes: true }) + .then((files) => { + // Filter and handle the files + files.forEach((file) => { + if (!file.isFile()) return; + + const baseName = file.name; + const ext = path.extname(baseName); + const fullSrcPath = path.join(file.parentPath, file.name); + const relativePath = fullSrcPath.replace(this.basePath, ''); + + // Ignore paths from src/ those requiring custom builder + if (relativePath.includes(`${sep}src${sep}`)) return; + + if (ext === '.css' && !baseName.endsWith('.min.css')) { + // Handle the CSS file + cssFiles.push(handleCSSFile( + fullSrcPath, + path.join(this.targetPath, relativePath)), + ); + } else if (ext === '.scss' && baseName[0] !== '_') { + // Handle the SCSS file + scssFiles.push(handleSCSSFile( + fullSrcPath, + path.join(this.targetPath, relativePath.replace(`${sep}scss${sep}`, `${sep}css${sep}`).replace('.scss', '.css')), + this.options.sassSilent, + )); + } + }); + + return Promise.all([...cssFiles, ...scssFiles]); + }); + } + + /** + * Process JavaScript files and Modules + * @returns { Promise } + */ + async js() { + // Collect files + const jsFiles = []; + const mjsFiles = []; + + return fsp.readdir(this.basePath, { recursive: true, withFileTypes: true }) + .then((files) => { + // Filter and handle the files + files.forEach((file) => { + if (!file.isFile()) return; + + const baseName = file.name; + const ext = path.extname(baseName); + const fullSrcPath = path.join(file.parentPath, file.name); + const relativePath = fullSrcPath.replace(this.basePath, ''); + + // Ignore paths from src/ those requiring custom builder + if (relativePath.includes(`${sep}src${sep}`)) return; + + // Pick only js files + if ((ext !== '.js' && ext !== '.mjs') || baseName.endsWith('.min.js')) return; + + if (baseName === 'builder.mjs') { + // Ignore builders of active asset, which is in the root of the asset folder + if (relativePath.replace('/', '').replace('\\', '') === 'builder.mjs') { + return; + } + + // This should never happen + throw new Error(`Trying to build script from another builder "${fullSrcPath}". Make sure that each builder is separated.`); + } + + if ((ext === '.mjs' || baseName.endsWith('.es6.js') || baseName.endsWith('.w-c.es6.js')) && !baseName.startsWith('_')) { + mjsFiles.push(handleMJSFile( + fullSrcPath, + path.join(this.targetPath, relativePath.replace(/\.w-c\.es6\.js$/, '.js').replace(/\.es6\.js$/, '.js')), + )); + } else { + jsFiles.push(handleJSFile( + fullSrcPath, + path.join(this.targetPath, relativePath.replace(/\.es5\.js$/, '.js')), + )); + } + }); + + return Promise.all([...jsFiles, ...mjsFiles]); + }); + } + + /** + * Create compressed (gzip) .css/.js files + * @returns { Promise } + */ + async gzip() { + return fsp.readdir(this.targetPath, { recursive: true, withFileTypes: true }).then((files) => { + const promises = []; + + files.forEach((file) => { + if (!file.isFile()) return; + + const fullSrcPath = path.join(file.parentPath, file.name); + + // Compress only minified + if (!file.name.endsWith('.min.js') && !file.name.endsWith('.min.css')) return; + + promises.push(compressFileAndSave(fullSrcPath)); + }); + + return Promise.all(promises); + }); + } + + /** + * Watch handler + * @returns { Promise } + */ + async watch() { + const watcher = chokidar.watch(this.basePath, { + ignored: /(^|[/\\])\../, // ignore dotfiles + persistent: true, + ignoreInitial: true, + }); + + // Rebuild everything + const rebuild = () => { + console.log(`Watcher rebuild everything in [${this.name}]...`); + + const buildTasks = this.getBuildTasks(); + const nextTask = () => { + if (!buildTasks.length) return; + const task = buildTasks.shift(); + + return this[task]().then(() => nextTask()); + }; + return nextTask(); + }; + // Wait for initial rebuild + await rebuild(); + + // File type checker + let lastPromise = Promise.resolve(); + const checkFile = (file) => { + const ext = path.extname(file); + + switch (ext) { + case '.css': + case '.scss': + console.log(`Watcher updating css/scss for [${this.name}]...`); + lastPromise = lastPromise.then(() => this.css().catch((error) => { + console.error(`Watcher for [${this.name}] got an error:`); + console.error(error); + })); + break; + + case '.js': + case '.vue': + console.log(`Watcher updating js for [${this.name}]...`); + lastPromise = lastPromise.then(() => this.js().catch((error) => { + console.error(`Watcher for [${this.name}] got an error:`); + console.error(error); + })); + break; + + default: + console.log(`Watcher updating static files for [${this.name}]...`); + lastPromise = lastPromise.then(() => this.copy()); + break; + } + }; + + // Go and watch + watcher + .on('add', checkFile) + .on('change', checkFile) + .on('unlink', rebuild); + } +} diff --git a/build/build-modules-js/builders-registry.mjs b/build/build-modules-js/builders-registry.mjs new file mode 100644 index 0000000000000..2df2aa2339f7c --- /dev/null +++ b/build/build-modules-js/builders-registry.mjs @@ -0,0 +1,107 @@ +/** + * Builders registry for Media resources + */ + +// List of media resources. A folder (extension) name under media_source/ +// By default, is used DefaultModuleBuilder class. +// However, each resource may have own builder.mjs script, for this it should be placed in root of its folder. +export const builders = [ + // Libraries + 'vendor', // Many extensions depending on it, should be run first + 'system', + 'vendor/bootstrap', // Customised bootstrap + 'vendor/jquery', // jQuery extras + 'vendor/short-and-sweet', // Customised short-and-sweet + 'layouts', + 'legacy', + 'mailto', + + // Components + 'cache', + 'com_actionlogs', + 'com_admin', + 'com_associations', + 'com_banners', + 'com_cache', + 'com_categories', + 'com_config', + 'com_contact', + 'com_content', + 'com_contenthistory', + 'com_cpanel', + 'com_fields', + 'com_finder', + 'com_guidedtours', + 'com_installer', + 'com_joomlaupdate', + 'com_languages', + 'com_mails', + 'com_media', + 'com_menus', + 'com_modules', + 'com_scheduler', + 'com_tags', + 'com_templates', + 'com_users', + 'com_workflow', + 'com_wrapper', + + // Modules + 'mod_articles', + 'mod_articles_news', + 'mod_languages', + 'mod_login', + 'mod_menu', + 'mod_quickicon', + 'mod_sampledata', + + // Plugins + 'plg_behaviour_compat6', + 'plg_content_vote', + 'plg_editors-xtd_image', + 'plg_editors_codemirror', + 'plg_editors_none', + 'plg_editors_tinymce', + 'plg_installer_folderinstaller', + 'plg_installer_packageinstaller', + 'plg_installer_urlinstaller', + 'plg_installer_webinstaller', + 'plg_media-action_crop', + 'plg_media-action_resize', + 'plg_media-action_rotate', + 'plg_multifactorauth_email', + 'plg_multifactorauth_fixed', + 'plg_multifactorauth_totp', + 'plg_multifactorauth_webauthn', + 'plg_multifactorauth_yubikey', + 'plg_quickicon_autoupdate', + 'plg_quickicon_eos', + 'plg_quickicon_extensionupdate', + 'plg_quickicon_joomlaupdate', + 'plg_quickicon_overridecheck', + 'plg_quickicon_privacycheck', + 'plg_system_debug', + 'plg_system_guidedtours', + 'plg_system_jooa11y', + 'plg_system_schedulerunner', + 'plg_system_shortcut', + 'plg_system_stats', + 'plg_system_webauthn', + 'plg_user_token', + + // Templates + 'templates/administrator/atum', + 'templates/site/cassiopeia', + 'templates/site/cassiopeia_extended', + 'installation/template', + + // Additional builders, which are not distributed under media/ + 'error-pages', +]; + +// Builders which should be completed before any following builder starts. +// Used for mass-execution to prevent collisions. +export const blockingBuilders = [ + 'vendor', // Blocking many extensions depending on it + 'system', // Blocking because 'error-pages' writes in to the same folder, so 'system' should be completed before that +]; diff --git a/build/build-modules-js/command/build-command.mjs b/build/build-modules-js/command/build-command.mjs new file mode 100644 index 0000000000000..cbf1bc4a828f3 --- /dev/null +++ b/build/build-modules-js/command/build-command.mjs @@ -0,0 +1,88 @@ +/** + * Build command module + */ + +import path from 'node:path'; +import { BuilderFactory, createAndRunBuilder } from '../builder/builder-factory.mjs'; + +/** + * Build command: + * build -a + * build -n builder1,builder2 + * build -t css,js + * build -n builder1,builder2 -t css,js + * + * @param { Command } program CMD program instance + * @param { Object } cmdOptions Command options and arguments + * @param { Array } builders List of builder names + * @param { Array } blockingBuilders List of blocking builder names + * + * @return { Promise } + */ +export default async function buildCommand(program, cmdOptions = {}, builders = [], blockingBuilders = []) { + // Get list of builders to run + let buildersToRun = []; + let runAll = false; + if (cmdOptions.all) { + runAll = true; + buildersToRun = builders; + } else if (cmdOptions.name) { + cmdOptions.name.split(',').forEach((name) => { + // Check if builder exists + if (!builders.includes(name)) { + program.error(`Builder "${name}" does not exists.`); + } + buildersToRun.push(name); + }); + } + + // Get list of tasks to run + let tasksToRun = []; + if (cmdOptions.task) { + cmdOptions.task.split(',').forEach((name) => { + tasksToRun.push(name); + }); + } + + if (!buildersToRun.length) { + console.log('Nothing to run. Please specify the builder name or use -a to run all builders.'); + return; + } + + const factory = new BuilderFactory( + path.resolve('./media_source'), + path.resolve('./media'), + cmdOptions, + ); + + // Create builder queue + const queue = []; + buildersToRun.forEach((name) => { + queue.push([ + name, + blockingBuilders.includes(name), + ]); + }); + + // Go through queue and execute each builder. + // The blocking builder will halt Queue lookup. + const danglingPromises = []; + const checkQueue = async () => { + if (!queue.length) return; + const [name, isBlocking] = queue.shift(); + + if (isBlocking) { + // Halt Queue lookup until the builder completes + return createAndRunBuilder(program, name, factory, tasksToRun, runAll).then(() => checkQueue()); + } + + // Collect dangling promises to be sure all are resolved in the end + danglingPromises.push(createAndRunBuilder(program, name, factory, tasksToRun, runAll)); + + return checkQueue(); + }; + + return checkQueue().then(() => { + return Promise.all(danglingPromises); + }); +}; diff --git a/build/build-modules-js/command/watch-command.mjs b/build/build-modules-js/command/watch-command.mjs new file mode 100644 index 0000000000000..6ecdbdce83ae5 --- /dev/null +++ b/build/build-modules-js/command/watch-command.mjs @@ -0,0 +1,92 @@ +/** + * Watch command module + */ +import path from 'node:path'; +import { BuilderFactory } from '../builder/builder-factory.mjs'; + +const isWatchNotImplementedError = (error) => error?.message?.startsWith('Watch is not implemented for ['); + +export default async function watchCommand(program, cmdOptions = {}, builders = []) { + let buildersToWatch = []; + const unsupportedBuilders = []; + const getUnsupportedWatchSummary = (names) => `Skipped builders (watch not supported): ${names.join(', ')}`; + const addUnsupportedBuilder = (name) => { + if (!unsupportedBuilders.includes(name)) { + unsupportedBuilders.push(name); + } + }; + const handleUnsupportedBuilder = (name) => { + addUnsupportedBuilder(name); + + if (!cmdOptions.all) { + program.error(`Builder "${name}" does not support watch mode.`); + } + }; + const logUnsupportedBuilders = () => { + if (!unsupportedBuilders.length) { + return; + } + + console.log( + '\x1b[33m%s\x1b[0m', + getUnsupportedWatchSummary(unsupportedBuilders), + ); + }; + + if (cmdOptions.all) { + buildersToWatch = builders; + } else if (cmdOptions.name) { + cmdOptions.name.split(',').map((name) => name.trim()).filter(Boolean).forEach((name) => { + // Check if builder exists + if (!builders.includes(name)) { + program.error(`Builder "${name}" does not exists.`); + } + + buildersToWatch.push(name); + }); + } + + if (!buildersToWatch.length) { + logUnsupportedBuilders(); + console.log('Nothing to watch. Please specify the builder name to watch.'); + return; + } + + const factory = new BuilderFactory( + path.resolve('./media_source'), + path.resolve('./media'), + cmdOptions, + ); + + const watchers = []; + buildersToWatch.forEach((name) => { + const watcher = factory.createBuilder(name) + .then(async (builder) => { + if (!builder.watch || typeof builder.watch !== 'function') { + handleUnsupportedBuilder(name); + return; + } + + console.log(`Initialize watch [${name}]`); + + return builder.watch(); + }) + .catch((error) => { + if (isWatchNotImplementedError(error)) { + handleUnsupportedBuilder(name); + return; + } + + console.log('\x1b[31m%s\x1b[0m', `Failed Watch [${name}]`); + console.trace(error); + program.error(error.message); + }); + watchers.push(watcher); + }); + + return Promise.all(watchers).then((result) => { + logUnsupportedBuilders(); + + return result; + }); +}; diff --git a/build/build-modules-js/compilecss.mjs b/build/build-modules-js/compilecss.mjs deleted file mode 100644 index f1caa3758c80a..0000000000000 --- a/build/build-modules-js/compilecss.mjs +++ /dev/null @@ -1,88 +0,0 @@ -import { sep } from 'node:path'; - -import recursive from 'recursive-readdir'; -import pkg from 'fs-extra'; - -import { handleScssFile } from './stylesheets/handle-scss.mjs'; -import { handleCssFile } from './stylesheets/handle-css.mjs'; - -const { stat } = pkg; -const RootPath = process.cwd(); - -/** - * Method that will crawl the media_source folder - * and compile any scss files to css and .min.css - * copy any css files to the appropriate destination and - * minify them in place - * - * Expects scss files to have ext: .scss - * css files to have ext: .css - * Ignores scss files that their filename starts with `_` - * - * @param {object} options The options - * @param {string} path The folder that needs to be compiled, optional - */ -export const stylesheets = async (options, path) => { - const files = []; - let folders = []; - - if (path) { - const stats = await stat(`${RootPath}/${path}`); - - if (stats.isDirectory()) { - folders.push(`${RootPath}/${path}`); - } else if (stats.isFile()) { - files.push(`${RootPath}/${path}`); - } else { - console.error(`Unknown path ${path}`); - process.exitCode = 1; - } - } else { - folders = [ - `${RootPath}/build/media_source`, - `${RootPath}/templates`, - `${RootPath}/administrator/templates`, - `${RootPath}/installation/template`, - `${RootPath}/media/vendor/debugbar`, - ]; - } - - const folderPromises = []; - - // Loop to get the files that should be compiled via parameter - for (const folder of folders) { - folderPromises.push(recursive(folder, ['!*.+(scss|css)'])); - } - - const computedFiles = await Promise.all(folderPromises); - - const cssFilesPromises = []; - const scssFilesPromises = []; - - // Loop to get the files that should be compiled via parameter - [].concat(...computedFiles).forEach((file) => { - if (file.endsWith('.css') && !file.endsWith('.min.css')) { - cssFilesPromises.push(handleCssFile(file)); - } - - // Don't take files with "_" but "file" has the full path, so check via match - if (file.endsWith('.scss') && !file.match(/(\/|\\)_[^/\\]+$/)) { - // Bail out for non Joomla convention folders, eg: scss - if (!(file.match(/\/scss\//) || file.match(/\\scss\\/))) { - return; - } - - files.push(file); - } - }); - - for (const file of files) { - const outputFile = file.replace(`${sep}scss${sep}`, `${sep}css${sep}`) - .replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`) - .replace('.scss', '.css'); - - scssFilesPromises.push(handleScssFile(file, outputFile)); - } - - return Promise.all([...cssFilesPromises, ...scssFilesPromises]); -}; diff --git a/build/build-modules-js/compilejs.mjs b/build/build-modules-js/compilejs.mjs deleted file mode 100644 index e8c4c2644ec9b..0000000000000 --- a/build/build-modules-js/compilejs.mjs +++ /dev/null @@ -1,74 +0,0 @@ -import { stat } from 'node:fs/promises'; -import { sep } from 'node:path'; - -import recursive from 'recursive-readdir'; - -import { handleES5File } from './javascript/handle-es5.mjs'; -import { handleESMFile } from './javascript/compile-to-es2017.mjs'; - -const RootPath = process.cwd(); - -/** - * Method that will crawl the media_source folder and - * compile ES6 to ES5 and ES6 - * copy any ES5 files to the appropriate destination and - * minify them in place - * compile any custom elements/webcomponents - * - * Expects ES6 files to have ext: .es6.js - * ES5 files to have ext: .es5.js - * WC/CE files to have ext: .w-c.es6.js - * - * @param { object } options The options from settings.json - * @param { string } path The folder that needs to be compiled, optional - * @param { string } mode esm for ES2017, es5 for ES5, both for both - */ -export const scripts = async (options, path) => { - const files = []; - let folders = []; - - if (path) { - const stats = await stat(`${RootPath}/${path}`); - - if (stats.isDirectory()) { - folders.push(`${RootPath}/${path}`); - } else if (stats.isFile()) { - files.push(`${RootPath}/${path}`); - } else { - console.error(`Unknown path ${path}`); - process.exitCode = 1; - } - } else { - folders = [ - `${RootPath}/build/media_source`, - `${RootPath}/templates/cassiopeia`, - ]; - } - - const folderPromises = []; - - // Loop to get the files that should be compiled via parameter - for (const folder of folders) { - folderPromises.push(recursive(folder, ['!*.+(m|js)'])); - } - - const computedFiles = await Promise.all(folderPromises); - const computedFilesFlat = [].concat(...computedFiles); - const jsFilesPromises = []; - const esmFilesPromises = []; - - // Loop to get the files that should be compiled via parameter - computedFilesFlat.forEach((file) => { - if (file.includes(`build${sep}media_source${sep}vendor${sep}bootstrap${sep}js`)) { - return; - } - - if (file.endsWith('.es5.js')) { - jsFilesPromises.push(handleES5File(file)); - } else if ((file.endsWith('.es6.js') || file.endsWith('.w-c.es6.js')) && !file.startsWith('_')) { - esmFilesPromises.push(handleESMFile(file)); - } - }); - - Promise.all([...jsFilesPromises, ...esmFilesPromises]); -}; diff --git a/build/build-modules-js/compress.mjs b/build/build-modules-js/compress.mjs deleted file mode 100644 index a7ba3b91640f3..0000000000000 --- a/build/build-modules-js/compress.mjs +++ /dev/null @@ -1,39 +0,0 @@ -import { readdir } from 'node:fs/promises'; -import { extname } from 'node:path'; - -import { compressFile } from './utils/compressFile.mjs'; -import { Timer } from './utils/timer.mjs'; - -/** - * Get files recursively - * - * @param {string} path The path - */ -async function getFiles(path) { - // Get files within the current directory - return (await readdir(path, { withFileTypes: true, recursive: true })) - .filter((file) => !file.isDirectory() && ['.js', '.css'].includes(extname(file.name))) - .map((file) => `${file.parentPath}/${file.name}`); -} - -/** - * Method that will pre compress (gzip) all .css/.js files - * in the templates and in the media folder - */ -export const compressFiles = async (enableBrotli = false) => { - const bench = new Timer('Gzip'); - const paths = [ - `${process.cwd()}/media`, - `${process.cwd()}/installation/template`, - `${process.cwd()}/templates`, - `${process.cwd()}/administrator/templates`, - ]; - - const compressTasks = []; - const files = await Promise.all(paths.map((path) => getFiles(`${path}`))); - [].concat(...files).map((file) => compressTasks.push(compressFile(file, enableBrotli))); - - await Promise.all(compressTasks); - console.log('✅ Done 👍'); - bench.stop(); -}; diff --git a/build/build-modules-js/error-pages.mjs b/build/build-modules-js/error-pages.mjs deleted file mode 100644 index 544bab2c6f8cc..0000000000000 --- a/build/build-modules-js/error-pages.mjs +++ /dev/null @@ -1,164 +0,0 @@ -import { - access, mkdir, readFile, writeFile, -} from 'node:fs/promises'; -import { dirname } from 'node:path'; - -import Ini from 'ini'; -import Recurs from 'recursive-readdir'; -import { transform } from 'esbuild'; -import { transform as transformCss } from 'lightningcss'; - -const RootPath = process.cwd(); -const dir = `${RootPath}/installation/language`; -const srcPath = `${RootPath}/build/warning_page`; - -/** - * Will produce as many .html files as defined in settings.json - * Expects three files: - * build/warning_page/template.css - * build/warning_page/template.html - * build/warning_page/template.js - * - * And also specific strings in the languages in the installation folder! - * Also the base strings are held in build/build-modules-js/settings.json - */ -export const createErrorPages = async (options) => { - const iniFilesProcess = []; - const processPages = []; - global.incompleteObj = {}; - global.unsupportedObj = {}; - global.fatalObj = {}; - global.noxmlObj = {}; - - const initTemplate = await readFile(`${srcPath}/template.html`, { encoding: 'utf8' }); - let cssContent = await readFile(`${srcPath}/template.css`, { encoding: 'utf8' }); - let jsContent = await readFile(`${srcPath}/template.js`, { encoding: 'utf8' }); - - const { code } = transformCss({ - code: Buffer.from(cssContent), - minify: true, - }); - - cssContent = code; - jsContent = await transform(jsContent, { minify: true }); - - const processIni = async (file) => { - const languageStrings = Ini.parse(await readFile(file, { encoding: 'utf8' })); - - // Build the variables into json for the unsupported page - if (languageStrings.BUILD_MIN_PHP_ERROR_LANGUAGE) { - const name = dirname(file).replace(/.+\//, '').replace(/.+\\/, ''); - global.unsupportedObj = { - ...global.unsupportedObj, - [name]: { - language: Ini.unsafe(languageStrings.BUILD_MIN_PHP_ERROR_LANGUAGE), - header: languageStrings.BUILD_MIN_PHP_ERROR_HEADER, - text1: languageStrings.BUILD_MIN_PHP_ERROR_TEXT, - 'help-url-text': languageStrings.BUILD_MIN_PHP_ERROR_URL_TEXT, - }, - }; - } - - // Build the variables into json for the build incomplete page - if (languageStrings.BUILD_INCOMPLETE_LANGUAGE) { - const name = dirname(file).replace(/.+\//, '').replace(/.+\\/, ''); - global.incompleteObj = { - ...global.incompleteObj, - [name]: { - language: Ini.unsafe(languageStrings.BUILD_INCOMPLETE_LANGUAGE), - header: languageStrings.BUILD_INCOMPLETE_HEADER, - text1: languageStrings.BUILD_INCOMPLETE_TEXT, - 'help-url-text': languageStrings.BUILD_INCOMPLETE_URL_TEXT, - }, - }; - } - - // Build the variables into json for the fatal error page - if (languageStrings.BUILD_FATAL_LANGUAGE) { - const name = dirname(file).replace(/.+\//, '').replace(/.+\\/, ''); - global.fatalObj = { - ...global.fatalObj, - [name]: { - language: Ini.unsafe(languageStrings.BUILD_FATAL_LANGUAGE), - header: languageStrings.BUILD_FATAL_HEADER, - text1: languageStrings.BUILD_FATAL_TEXT, - 'help-url-text': languageStrings.BUILD_FATAL_URL_TEXT, - }, - }; - } - - // Build the variables into json for the missing XML error page - if (languageStrings.BUILD_NOXML_LANGUAGE) { - const name = dirname(file).replace(/.+\//, '').replace(/.+\\/, ''); - global.noxmlObj = { - ...global.noxmlObj, - [name]: { - language: Ini.unsafe(languageStrings.BUILD_NOXML_LANGUAGE), - header: languageStrings.BUILD_NOXML_HEADER, - text1: languageStrings.BUILD_NOXML_TEXT, - 'help-url-text': languageStrings.BUILD_NOXML_URL_TEXT, - }, - }; - } - }; - - const files = await Recurs(dir); - files.sort().forEach((file) => { - if (file.endsWith('langmetadata.xml')) { - return; - } - iniFilesProcess.push(processIni(file)); - }); - - await Promise.all(iniFilesProcess).catch((err) => { - console.error(err); - process.exitCode = -1; - }); - - const processPage = async (name) => { - const sortedJson = Object.fromEntries(Object.entries(global[`${name}Obj`]).sort()); - const jsonContent = `window.errorLocale=${JSON.stringify(sortedJson)};`; - - let template = initTemplate; - - template = template.replace('{{jsonContents}}', jsonContent); - template = template.replace('{{Title}}', options.settings.errorPages[name].title); - template = template.replace('{{Header}}', options.settings.errorPages[name].header); - template = template.replace('{{Description}}', options.settings.errorPages[name].text); - template = template.replace('{{Link}}', options.settings.errorPages[name].link); - template = template.replace('{{LinkText}}', options.settings.errorPages[name].linkText); - - if (cssContent) { - template = template.replace('{{cssContents}}', cssContent); - } - - if (jsContent) { - template = template.replace('{{jsContents}}', jsContent.code); - } - - options.settings.errorPages[name].destFile.forEach(async (folder) => { - let mediaExists = false; - try { - await access(dirname(`${RootPath}${folder}`)); - mediaExists = true; - } catch (err) { - // Do nothing - } - - if (!mediaExists) { - await mkdir(dirname(`${RootPath}${folder}`), { recursive: true, mode: 0o755 }); - } - - await writeFile(`${RootPath}${folder}`, template, { encoding: 'utf8', mode: 0o644 }); - - console.error(`✅ Created the file: ${folder}`); - }); - }; - - Object.keys(options.settings.errorPages).forEach((name) => processPages.push(processPage(name))); - - return Promise.all(processPages).catch((err) => { - console.error(err); - process.exitCode = -1; - }); -}; diff --git a/build/build-modules-js/init/cleanup-media.mjs b/build/build-modules-js/init/cleanup-media.mjs deleted file mode 100644 index 184ae41ab0c1d..0000000000000 --- a/build/build-modules-js/init/cleanup-media.mjs +++ /dev/null @@ -1,43 +0,0 @@ -import { join } from 'node:path'; - -import pkg from 'fs-extra'; - -const RootPath = process.cwd(); -const { - stat, mkdir, copy, remove, -} = pkg; - -/** - * Method that will erase the media/vendor folder - * and populate the debugbar assets - * - * @returns {Promise} - */ -export const cleanVendors = async () => { - if (process.env.SKIP_COMPOSER_CHECK === 'YES') { - await mkdir('media/vendor/debugbar', { recursive: true, mode: 0o755 }); - console.log('Skipping the DebugBar assets...'); - return; - } - - console.log('Cleanup the Vendor '); - - const mediaFolder = await stat(join(RootPath, 'libraries/vendor/php-debugbar/php-debugbar/src/DebugBar/Resources')); - - if (await mediaFolder.isDirectory()) { - // Remove the vendor folder - // await remove(join(RootPath, 'media')); - // console.error('/media has been removed.'); - - // Recreate the media folder - await mkdir(join(RootPath, 'media/vendor/debugbar'), { recursive: true, mode: 0o755 }); - - // Copy some assets from a PHP package - await copy(join(RootPath, 'libraries/vendor/php-debugbar/php-debugbar/src/DebugBar/Resources'), join(RootPath, 'media/vendor/debugbar'), { preserveTimestamps: true }); - await remove(join(RootPath, 'media/vendor/debugbar/vendor/font-awesome')); - await remove(join(RootPath, 'media/vendor/debugbar/vendor/jquery')); - } else { - console.error("You need to run `npm install` AFTER the command `composer install`!!!. The debug plugin HASN'T installed all its front end assets"); - process.exitCode = 1; - } -}; diff --git a/build/build-modules-js/init/common/concat-files.mjs b/build/build-modules-js/init/common/concat-files.mjs deleted file mode 100644 index a611ed92a10d6..0000000000000 --- a/build/build-modules-js/init/common/concat-files.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import { readFile, writeFile, existsSync } from 'fs-extra'; - -const RootPath = process.cwd(); - -/** - * Method to concatenate some files - * - * @param {array} files the array of files to be be concatenated - * @param {string} output the name of the output file - * - * @returns {void} - */ -export const concatFiles = async (files, output) => { - const promises = []; - - for (const file of files) { - if (existsSync(`${RootPath}/${file}`)) { - promises.push(readFile(`${RootPath}/${file}`, { encoding: 'utf8' })); - } - } - - const res = await Promise.all(promises); - - await writeFile(`${RootPath}/${output}`, res.join(' '), { encoding: 'utf8', mode: 0o644 }); -}; diff --git a/build/build-modules-js/init/common/copy-all-files.mjs b/build/build-modules-js/init/common/copy-all-files.mjs deleted file mode 100644 index 3037ec32d5cc7..0000000000000 --- a/build/build-modules-js/init/common/copy-all-files.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import { join } from 'node:path'; - -import { copy } from 'fs-extra'; - -const RootPath = process.cwd(); - -/** - * Copies all the files from a directory - * - * @param {string} dirName the name of the source folder - * @param {string} name the name of the destination folder - * @param {string} type the type of the folder, eg: js, css, fonts, images - * - * @returns { void } - */ -export const copyAllFiles = async (dirName, name, type) => { - const folderName = dirName === '/' ? '/' : `/${dirName}`; - await copy( - join(RootPath, `node_modules/${name}/${folderName}`), - join(RootPath, `media/vendor/${name.replace(/.+\//, '')}/${type}`), - { - preserveTimestamps: true, - }, - ); -}; diff --git a/build/build-modules-js/init/common/resolve-package.cjs b/build/build-modules-js/init/common/resolve-package.cjs deleted file mode 100644 index 9a2159acd5da4..0000000000000 --- a/build/build-modules-js/init/common/resolve-package.cjs +++ /dev/null @@ -1,49 +0,0 @@ -const { existsSync, readdirSync } = require('node:fs'); - -/** - * Find full path for package file. - * Replacement for require.resolve(), as it is broken for packages with "exports" property. - * - * @param {string} relativePath Relative path to the file to resolve, in format packageName/file-name.js - * @returns {string|boolean} - */ -module.exports.resolvePackageFile = (relativePath) => { - for (let i = 0, l = module.paths.length; i < l; i += 1) { - const path = module.paths[i]; - const fullPath = `${path}/${relativePath}`; - if (existsSync(fullPath)) { - return fullPath; - } - } - - return false; -}; - -/** - * Find a list of modules under given scope, - * eg: @foobar will look for all submodules @foobar/foo, @foobar/bar - * - * @param scope - * @returns {[]} - */ -module.exports.getPackagesUnderScope = (scope) => { - const cmModules = new Set(); - - // Get the scope roots - const roots = []; - module.paths.forEach((path) => { - const fullPath = `${path}/${scope}`; - if (existsSync(fullPath)) { - roots.push(fullPath); - } - }); - - // List of modules - roots.forEach((rootPath) => { - readdirSync(rootPath).forEach((subModule) => { - cmModules.add(`${scope}/${subModule}`); - }); - }); - - return [...cmModules]; -}; diff --git a/build/build-modules-js/init/exemptions/tinymce.mjs b/build/build-modules-js/init/exemptions/tinymce.mjs deleted file mode 100644 index c4b9fb7005b26..0000000000000 --- a/build/build-modules-js/init/exemptions/tinymce.mjs +++ /dev/null @@ -1,80 +0,0 @@ -import { existsSync } from 'node:fs'; -import { mkdir, readFile, writeFile } from 'node:fs/promises'; -import { join } from 'node:path'; - -import pkg from 'fs-extra'; - -import { copyAllFiles } from '../common/copy-all-files.mjs'; - -const { copy, removeSync } = pkg; -const RootPath = process.cwd(); -const xmlVersionStr = /()(.+)(<\/version>)/; - -/** - * Copies an array of files from a directory - * - * @param {string} dirName the name of the source folder - * @param {array} files the array of files to be be copied - * @param {string} name the name of the destination folder - * @param {string} type the type of the folder, eg: js, css, fonts, images - * - * @returns { void } - */ -const copyArrayFiles = async (dirName, files, name, type) => { - const promises = []; - for (const file of files) { - const folderName = dirName === '/' ? '/' : `/${dirName}/`; - - if (existsSync(`node_modules/${name}${folderName}${file}`)) { - promises.push(copy(`node_modules/${name}${folderName}${file}`, `media/vendor/${name.replace(/.+\//, '')}${type ? `/${type}` : ''}/${file}`, { preserveTimestamps: true })); - } - } - - await Promise.all(promises); -}; - -/** - * tinyMCE needs special treatment - */ -export const tinyMCE = async (packageName, version) => { - const itemvendorPath = join(RootPath, `media/vendor/${packageName}`); - - if (!(await existsSync(itemvendorPath))) { - await mkdir(itemvendorPath, { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'icons'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'plugins'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'langs'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'skins'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'themes'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'templates'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'models'), { mode: 0o755 }); - } - - await copyAllFiles('icons', 'tinymce', 'icons'); - await copyAllFiles('plugins', 'tinymce', 'plugins'); - await copyAllFiles('skins', 'tinymce', 'skins'); - await copyAllFiles('themes', 'tinymce', 'themes'); - await copyAllFiles('models', 'tinymce', 'models'); - - await copyArrayFiles('', ['tinymce.js', 'tinymce.min.js', 'changelog.txt', 'license.txt'], 'tinymce', ''); - - // Update the XML file for tinyMCE - let tinyXml = await readFile(`${RootPath}/plugins/editors/tinymce/tinymce.xml`, { encoding: 'utf8' }); - tinyXml = tinyXml.replace(xmlVersionStr, `$1${version}$3`); - await writeFile(`${RootPath}/plugins/editors/tinymce/tinymce.xml`, tinyXml, { encoding: 'utf8', mode: 0o644 }); - - // Remove that sourcemap... - let tinyWrongMap = await readFile(`${RootPath}/media/vendor/tinymce/skins/ui/oxide/skin.min.css`, { encoding: 'utf8' }); - tinyWrongMap = tinyWrongMap.replace( - '/*# sourceMappingURL=skin.min.css.map */', - '', - ); - await writeFile(`${RootPath}/media/vendor/tinymce/skins/ui/oxide/skin.min.css`, tinyWrongMap, { encoding: 'utf8', mode: 0o644 }); - - // Restore our code on the vendor folders - await copy(join(RootPath, 'build/media_source/vendor/tinymce/templates'), join(RootPath, 'media/vendor/tinymce/templates'), { preserveTimestamps: true }); - // Drop the template plugin - if (existsSync(join(RootPath, 'media/vendor/tinymce/plugins/template'))) { - removeSync(join(RootPath, 'media/vendor/tinymce/plugins/template')); - } -}; diff --git a/build/build-modules-js/init/localise-packages.mjs b/build/build-modules-js/init/localise-packages.mjs deleted file mode 100644 index e155761405ba6..0000000000000 --- a/build/build-modules-js/init/localise-packages.mjs +++ /dev/null @@ -1,144 +0,0 @@ -import { dirname, join } from 'node:path'; -import { createRequire } from 'node:module'; -import { existsSync } from 'node:fs'; - -import pkg from 'fs-extra'; - -import { tinyMCE } from './exemptions/tinymce.mjs'; -import { resolvePackageFile } from './common/resolve-package.cjs'; - -const require = createRequire(import.meta.url); -const { - copy, mkdirs, mkdir, ensureDir, writeFile, -} = pkg; - -const RootPath = process.cwd(); - -/** - * - * @param {object} files the object of files map, eg {"src.js": "js/src.js"} - * @param {string} srcDir the name of the package root dir - * @param {string} destDir the name of the Vendor destination dir - * - * @returns {Promise} - */ -const copyFilesTo = async (files, srcDir, destDir) => { - const copyPromises = []; - - async function doTheCopy(source, dest) { - await ensureDir(dirname(dest)); - await copy(source, dest, { preserveTimestamps: true }); - } - - // Copy each file - for (const srcFile in files) { - copyPromises.push(doTheCopy(join(srcDir, srcFile), join(destDir, files[srcFile]))); - } - - return Promise.all(copyPromises); -}; - -/** - * Main method that will resolve each vendor package - * - * @returns {Promise} - */ -const resolvePackage = async (vendor, packageName, mediaVendorPath, options, registry) => { - const vendorName = vendor.name || packageName; - const modulePathJson = resolvePackageFile(`${packageName}/package.json`); - const modulePathRoot = dirname(modulePathJson); - const moduleOptions = require(modulePathJson); - - const promises = []; - - if (packageName === 'tinymce') { - promises.push(tinyMCE(packageName, moduleOptions.version)); - } else { - await mkdirs(join(mediaVendorPath, vendorName)); - - ['js', 'css', 'filesExtra'].forEach((type) => { - if (!vendor[type]) return; - - promises.push(copyFilesTo(vendor[type], modulePathRoot, join(mediaVendorPath, vendorName), type)); - }); - } - - // Copy the license if existsSync - if (options.settings.vendors[packageName].licenseFilename - && (await existsSync(`${join(RootPath, `node_modules/${packageName}`)}/${options.settings.vendors[packageName].licenseFilename}`))) { - const dest = join(mediaVendorPath, vendorName); - await copy( - `${join(RootPath, `node_modules/${packageName}`)}/${options.settings.vendors[packageName].licenseFilename}`, - `${dest}/${options.settings.vendors[packageName].licenseFilename}`, - { preserveTimestamps: true }, - ); - } - - await Promise.all(promises); - - // Add provided Assets to a registry, if any - if (vendor.provideAssets && vendor.provideAssets.length) { - vendor.provideAssets.forEach((assetInfo) => { - const registryItemBase = { - package: packageName, - name: assetInfo.name || vendorName, - version: moduleOptions.version, - type: assetInfo.type, - }; - - const registryItem = Object.assign(assetInfo, registryItemBase); - - // Update path to file - if (assetInfo.uri && (assetInfo.type === 'script' || assetInfo.type === 'style' || assetInfo.type === 'webcomponent')) { - let itemPath = assetInfo.uri; - - // Check for external path - if (itemPath.indexOf('http://') !== 0 && itemPath.indexOf('https://') !== 0 && itemPath.indexOf('//') !== 0) { - itemPath = `vendor/${vendorName}/${itemPath}`; - } - - registryItem.uri = itemPath; - } - - registry.assets.push(registryItem); - }); - } - - console.log(`${packageName} was updated.`); -}; - -/** - * Main method that will copy all vendor files according to Joomla's specs - * - * @param options The options from setting.json - * - * @returns {Promise} - */ -export const localisePackages = async (options) => { - const mediaVendorPath = join(RootPath, 'media/vendor'); - const registry = { - $schema: 'https://developer.joomla.org/schemas/json-schema/web_assets.json', - name: options.name, - version: options.version, - description: options.description, - license: options.license, - assets: [], - }; - const promises = []; - - if (!(await existsSync(mediaVendorPath))) { - await mkdir(mediaVendorPath, { recursive: true, mode: 0o755 }); - } - - // Loop to get some text for the package.json - for (const packageName in options.settings.vendors) { - const vendor = options.settings.vendors[packageName]; - - promises.push(resolvePackage(vendor, packageName, mediaVendorPath, options, registry)); - } - - await Promise.all(promises); - - // Write assets registry - await writeFile(join(mediaVendorPath, 'joomla.asset.json'), JSON.stringify(registry, null, 2), { encoding: 'utf8', mode: 0o644 }); -}; diff --git a/build/build-modules-js/init/minify-vendor.mjs b/build/build-modules-js/init/minify-vendor.mjs deleted file mode 100644 index 78c45c84800bc..0000000000000 --- a/build/build-modules-js/init/minify-vendor.mjs +++ /dev/null @@ -1,92 +0,0 @@ -import { sep, basename } from 'node:path'; -import { lstat, readFile, writeFile } from 'node:fs/promises'; - -import recursive from 'recursive-readdir'; -import { transform } from 'esbuild'; - -const RootPath = process.cwd(); - -const folders = [ - 'media/vendor/accessibility/js', - 'media/vendor/chosen/js', - 'media/vendor/debugbar', - 'media/vendor/diff/js', - 'media/vendor/es-module-shims/js', - 'media/vendor/qrcode/js', - 'media/vendor/webcomponentsjs/js', -]; - -let allFiles = []; - -const noMinified = ['accessibility.min.js']; - -const alreadyMinified = [ - 'media/vendor/webcomponentsjs/js/webcomponents-bundle.js', - 'media/vendor/debugbar/vendor/highlightjs/highlight.pack.js', -]; - -/** - * Check if a file exists - * - * @param file - * @returns {Promise} - */ -const minifiedExists = async (file) => { - try { - return (await lstat(file)).isFile(); - } catch (e) { - return false; - } -}; - -/** - * - * @param {string} file - * - * @returns {Promise} - */ -const minifyJS = async (file) => { - const needsDotJS = noMinified.includes(basename(file)); - if (file.endsWith('.min.js') && !needsDotJS) { - return; - } - - console.log(`Processing Vendor file: ${file}`); - - let minified; - const fileExists = await minifiedExists(file); - if (!fileExists) { - return; - } - - const content = await readFile(file, { encoding: 'utf8' }); - const isMinified = alreadyMinified.includes(file.replace(`${RootPath}${sep}`, '')); - - if (isMinified || needsDotJS) { - minified = content; - } else { - minified = (await transform(content, { minify: true })).code; - } - - const newFile = needsDotJS ? file.replace('.min.js', '.js') : file.replace('.js', '.min.js'); - // Write the file - await writeFile(newFile, minified, { encoding: 'utf8', mode: 0o644 }); -}; - -/** - * Method that will minify a set of vendor javascript files - * - * @returns {Promise} - */ -export const minifyVendor = async () => { - const folderPromises = []; - const filesPromises = []; - - folders.map((folder) => folderPromises.push(recursive(folder, ['!*.+(js)']))); - - const computedFiles = await Promise.all(folderPromises); - allFiles = [...allFiles, ...[].concat(...computedFiles)]; - allFiles.map((file) => filesPromises.push(minifyJS(file))); - - return Promise.all(filesPromises); -}; diff --git a/build/build-modules-js/init/patches.mjs b/build/build-modules-js/init/patches.mjs deleted file mode 100644 index 1a20efff1c513..0000000000000 --- a/build/build-modules-js/init/patches.mjs +++ /dev/null @@ -1,35 +0,0 @@ -import { join } from 'node:path'; -import { readFile, writeFile } from 'node:fs/promises'; - -const RootPath = process.cwd(); - -/** - * Main method that will patch files... - * - * @param options The options from setting.json - * - * @returns {Promise} - */ -export const patchPackages = async (options) => { - const mediaVendorPath = join(RootPath, 'media/vendor'); - - // Joomla's hack to expose the chosen base classes so we can extend it ourselves - // (it was better than the many hacks we had before. But I'm still ashamed of myself). - const dest = join(mediaVendorPath, 'chosen'); - const chosenPath = `${dest}/${options.settings.vendors['chosen-js'].js['chosen.jquery.js']}`; - let ChosenJs = await readFile(chosenPath, { encoding: 'utf8' }); - ChosenJs = ChosenJs.replace( - '}).call(this);', - ` document.AbstractChosen = AbstractChosen; - document.Chosen = Chosen; -}).call(this);`, - ); - await writeFile(chosenPath, ChosenJs, { encoding: 'utf8', mode: 0o644 }); - - // Include the v5 shim for Font Awesome - const faPath = join(mediaVendorPath, 'fontawesome-free/scss/fontawesome.scss'); - const newScss = (await readFile(faPath, { encoding: 'utf8' })).concat(` -@import 'shims'; -`); - await writeFile(faPath, newScss, { encoding: 'utf8', mode: 0o644 }); -}; diff --git a/build/build-modules-js/init/recreate-media.mjs b/build/build-modules-js/init/recreate-media.mjs deleted file mode 100644 index e30a66220a416..0000000000000 --- a/build/build-modules-js/init/recreate-media.mjs +++ /dev/null @@ -1,85 +0,0 @@ -import { - stat, readFile, writeFile, readdir, -} from 'node:fs/promises'; -import { join, extname } from 'node:path'; - -import pkg from 'fs-extra'; -import recursive from 'recursive-readdir'; - -const { copy, existsSync, emptyDirSync } = pkg; -const RootPath = process.cwd(); -const knownDirs = [ - 'templates/site/cassiopeia', - 'templates/administrator/atum', -]; - -/** - * Will scan all the installed extensions and rebuild the cleanUpFolders registry. - */ -const updateSettings = async (options) => { - const extensionsScanned = await readdir(`${RootPath}/build/media_source`, { withFileTypes: true }); - const extensions = [...extensionsScanned] - .filter((x) => !['.DS_Store', 'templates', 'vendor', 'cache'].includes(x.name) && x.isDirectory()) - .map((x) => x.name); - - options.settings.cleanUpFolders = [...extensions, ...knownDirs]; -}; - -/** - * Method to recreate the basic media folder structure - * After execution the media folder is populated with empty js and css subdirectories - * images subfolders with their relative files and any other files except .js, .css - * - * @returns {Promise} - */ -export const recreateMediaFolder = async (options) => { - await updateSettings(options); - const installedVendors = Object.keys(options.settings.vendors).map((vendor) => { - if (vendor === 'choices.js') { - return 'vendor/choicesjs'; - } - if (vendor === '@fortawesome/fontawesome-free') { - return 'vendor/fontawesome-free'; - } - if (vendor === '@claviska/jquery-minicolors') { - return 'vendor/minicolors'; - } - if (vendor === '@webcomponents/webcomponentsjs') { - return 'vendor/webcomponentsjs'; - } - if (vendor === 'joomla-ui-custom-elements') { - return 'vendor/joomla-custom-elements'; - } - return `vendor/${vendor}`; - }); - - // Clean up existing folders - [...options.settings.cleanUpFolders, ...installedVendors].forEach((folder) => { - const folderPath = join(`${RootPath}/media`, folder); - if (existsSync(folderPath)) { - emptyDirSync(folderPath); - } - }); - - console.log('Recreating the media folder...'); - - const filterFunc = async (src) => { - const fileStat = await stat(src); - if (fileStat.isFile() && (extname(src) === '.js' || extname(src) === '.css')) { - return false; - } - - return true; - }; - - await copy(join(RootPath, 'build/media_source'), join(RootPath, 'media'), { filter: filterFunc, preserveTimestamps: true }); - - const SCSSMediafolders = await recursive(join(RootPath, 'media/templates'), ['!*.+(scss)']); - - // Patch the scss files - Object.keys(SCSSMediafolders).forEach(async (file) => { - const contents = await readFile(SCSSMediafolders[file], 'utf8'); - // Transform this `../../../../../../media/` to `../../../../` - await writeFile(SCSSMediafolders[file], contents.replace(/\.\.\/\.\.\/\.\.\/\.\.\/\.\.\/\.\.\/media\//g, '../../../../')); - }); -}; diff --git a/build/build-modules-js/javascript/build-bootstrap-js.mjs b/build/build-modules-js/javascript/build-bootstrap-js.mjs deleted file mode 100644 index 7c4e75063595a..0000000000000 --- a/build/build-modules-js/javascript/build-bootstrap-js.mjs +++ /dev/null @@ -1,118 +0,0 @@ -import { - readdir, readFile, writeFile, unlink, -} from 'node:fs/promises'; -import { resolve } from 'node:path'; -import { transform } from 'esbuild'; -import { rimrafSync } from 'rimraf'; -import { rollup } from 'rollup'; -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import replace from '@rollup/plugin-replace'; -import { babel } from '@rollup/plugin-babel'; -import { createRequire } from 'node:module'; - -const require = createRequire(import.meta.url); -const opts = require('../../../package.json'); - -const bsVersion = opts.dependencies.bootstrap.replace(/^\^|~/, ''); -const tasks = []; -const inputFolder = 'build/media_source/vendor/bootstrap/js'; -const outputFolder = 'media/vendor/bootstrap/js'; - -const createMinified = async (file) => { - const initial = await readFile(resolve(outputFolder, file), { - encoding: 'utf8', - }); - const mini = await transform( - initial.replace('./popper.js', `./popper.min.js?${bsVersion}`).replace('./dom.js', `./dom.min.js?${bsVersion}`), - { minify: true }, - ); - await writeFile( - resolve(outputFolder, file), - initial.replace('./popper.js', `./popper.js?${bsVersion}`).replace('./dom.js', `./dom.js?${bsVersion}`), - { encoding: 'utf8', mode: 0o644 }, - ); - await writeFile(resolve(outputFolder, file.replace('.js', '.min.js')), mini.code, { encoding: 'utf8', mode: 0o644 }); -}; - -const build = async () => { - console.log('Building ES6 Components...'); - - const domImports = await readdir(resolve('node_modules/bootstrap', 'js/src/dom')); - const utilImports = await readdir(resolve('node_modules/bootstrap', 'js/src/util')); - - const bundle = await rollup({ - input: resolve(inputFolder, 'index.es6.js'), - plugins: [ - nodeResolve(), - replace({ - preventAssignment: true, - 'process.env.NODE_ENV': "'production'", - }), - babel({ - exclude: 'node_modules/core-js/**', - babelHelpers: 'bundled', - babelrc: false, - presets: [ - [ - '@babel/preset-env', - { - targets: { - browsers: ['> 1%', 'not op_mini all'], - }, - }, - ], - ], - }), - ], - }); - - await bundle.write({ - format: 'es', - sourcemap: false, - dir: outputFolder, - chunkFileNames: '[name].js', - manualChunks: { - alert: ['build/media_source/vendor/bootstrap/js/alert.es6.js'], - button: ['build/media_source/vendor/bootstrap/js/button.es6.js'], - carousel: ['build/media_source/vendor/bootstrap/js/carousel.es6.js'], - collapse: ['build/media_source/vendor/bootstrap/js/collapse.es6.js'], - dropdown: ['build/media_source/vendor/bootstrap/js/dropdown.es6.js'], - modal: ['build/media_source/vendor/bootstrap/js/modal.es6.js'], - offcanvas: ['build/media_source/vendor/bootstrap/js/offcanvas.es6.js'], - popover: ['build/media_source/vendor/bootstrap/js/popover.es6.js'], - scrollspy: ['build/media_source/vendor/bootstrap/js/scrollspy.es6.js'], - tab: ['build/media_source/vendor/bootstrap/js/tab.es6.js'], - toast: ['build/media_source/vendor/bootstrap/js/toast.es6.js'], - popper: ['@popperjs/core'], - dom: [ - 'node_modules/bootstrap/js/src/base-component.js', - ...domImports.map((file) => `node_modules/bootstrap/js/src/dom/${file}`), - ...utilImports.map((file) => `node_modules/bootstrap/js/src/util/${file}`), - ], - }, - }); - - // closes the bundle - await bundle.close(); -}; - -export const bootstrapJs = async () => { - rimrafSync(resolve(outputFolder)); - - try { - await build(resolve(inputFolder, 'index.es6.js')); - await unlink(resolve(outputFolder, 'index.es6.js')); - } catch (error) { - console.error(error); - process.exitCode = 1; - } - - (await readdir(outputFolder)).forEach((file) => { - tasks.push(createMinified(file)); - }); - - return Promise.all(tasks).catch((er) => { - console.log(er); - process.exitCode = 1; - }); -}; diff --git a/build/build-modules-js/javascript/build-codemirror.mjs b/build/build-modules-js/javascript/build-codemirror.mjs deleted file mode 100644 index 0801efeaef2d1..0000000000000 --- a/build/build-modules-js/javascript/build-codemirror.mjs +++ /dev/null @@ -1,137 +0,0 @@ -/** - * Build codemirror modules - */ -import { readFileSync } from 'node:fs'; -import { writeFile } from 'node:fs/promises'; -import { createRequire } from 'node:module'; - -import cliProgress from 'cli-progress'; -import { rollup } from 'rollup'; -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import replace from '@rollup/plugin-replace'; -import { transform } from 'esbuild'; - -const require = createRequire(import.meta.url); - -const { - resolvePackageFile, - getPackagesUnderScope, -} = require('../init/common/resolve-package.cjs'); - -// Build the module -const buildModule = async (module, externalModules, destFile) => { - const build = await rollup({ - input: module, - external: externalModules || [], - plugins: [ - nodeResolve(), - replace({ preventAssignment: true, 'process.env.NODE_ENV': '"production"' }), - ], - }); - - await build.write({ - format: 'es', - sourcemap: false, - file: destFile, - }); - await build.close(); -}; - -// Minify a js file -const createMinified = async (filePath) => { - const destFile = filePath.replace('.js', '.min.js'); - // Read source - const src = readFileSync(filePath, { encoding: 'utf8' }); - // Minify - const min = await transform(src, { minify: true }); - // Save result - await writeFile(destFile, min.code, { encoding: 'utf8', mode: 0o644 }); -}; - -// Update joomla.asset.json for codemirror -const updateAssetRegistry = async (modules, externalModules) => { - const srcPath = 'build/media_source/plg_editors_codemirror/joomla.asset.json'; - const destPath = 'media/plg_editors_codemirror/joomla.asset.json'; - - // Get base JSON and update - const registry = JSON.parse(readFileSync(srcPath, { encoding: 'utf8' })); - - // Add dependencies to base codemirror asset - registry.assets.forEach((asset) => { - if (asset.name === 'codemirror' && asset.type === 'script') { - asset.dependencies = externalModules; - } - }); - - // Create asset for each module - modules.forEach((module) => { - const packageName = module.package; - const modulePathJson = resolvePackageFile(`${packageName}/package.json`); - const moduleOptions = require(modulePathJson); - const asset = { - type: 'script', - name: module.package, - uri: module.uri.replace('.js', '.min.js'), - importmap: true, - version: moduleOptions.version, - }; - - registry.assets.push(asset); - }); - - // Write assets registry - await writeFile(destPath, JSON.stringify(registry, null, 2), { encoding: 'utf8', mode: 0o644 }); -}; - -export const compileCodemirror = async () => { - console.log('Building Codemirror Components...'); - - const cmModules = getPackagesUnderScope('@codemirror'); - const lModules = getPackagesUnderScope('@lezer'); - const externalModules = [...cmModules, ...lModules]; - const destBasePath = 'media/vendor/codemirror/js'; - const assets = []; - const tasks = []; - - const progressBar = new cliProgress.SingleBar({ - stopOnComplete: true, - format: '{bar} {percentage}% | {value}/{total} files done', - }, cliProgress.Presets.shades_classic); - const totalSteps = (cmModules.length + lModules.length) * 2; - progressBar.start(totalSteps, 0); - - // Prepare @codemirror modules - cmModules.forEach((module) => { - const destFile = `${module.replace('@codemirror/', 'codemirror-')}.js`; - const destPath = `${destBasePath}/${destFile}`; - assets.push({ package: module, uri: destPath }); - - const task = buildModule(module, externalModules, destPath).then(() => { - progressBar.increment(); - return createMinified(destPath).then(() => { - progressBar.increment(); - }); - }); - tasks.push(task); - }); - - // Prepare @lezer modules which @codemirror depends on - lModules.forEach((module) => { - const destFile = `${module.replace('@lezer/', 'lezer-')}.js`; - const destPath = `${destBasePath}/${destFile}`; - assets.push({ package: module, uri: destPath }); - - const task2 = buildModule(module, externalModules, destPath).then(() => { - progressBar.increment(); - return createMinified(destPath).then(() => { - progressBar.increment(); - }); - }); - tasks.push(task2); - }); - - return Promise.all(tasks).then(() => { - progressBar.stop(); - return updateAssetRegistry(assets, externalModules); - }); -}; diff --git a/build/build-modules-js/javascript/build-com_media-js.mjs b/build/build-modules-js/javascript/build-com_media-js.mjs deleted file mode 100644 index 0d0af95307008..0000000000000 --- a/build/build-modules-js/javascript/build-com_media-js.mjs +++ /dev/null @@ -1,161 +0,0 @@ -import { writeFile, copyFile } from 'node:fs/promises'; -import { resolve } from 'node:path'; - -import { rollup, watch } from 'rollup'; -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import replace from '@rollup/plugin-replace'; -import { babel } from '@rollup/plugin-babel'; -import VuePlugin from 'rollup-plugin-vue'; -import commonjs from '@rollup/plugin-commonjs'; -import dotenv from 'dotenv'; - -import { minifyCode } from './minify.mjs'; - -dotenv.config(); - -const inputJS = 'administrator/components/com_media/resources/scripts/mediamanager.es6.js'; -const isProduction = process.env.NODE_ENV !== 'DEVELOPMENT'; - -export const mediaManager = async () => { - console.log('Building Media Manager ES Module...'); - - const bundle = await rollup({ - input: resolve(inputJS), - plugins: [ - VuePlugin({ - target: 'browser', - css: false, - compileTemplate: true, - template: { - isProduction, - }, - }), - nodeResolve(), - commonjs(), - replace({ - 'process.env.NODE_ENV': JSON.stringify((process.env.NODE_ENV && process.env.NODE_ENV.toLocaleLowerCase()) || 'production'), - __VUE_OPTIONS_API__: true, - __VUE_PROD_DEVTOOLS__: !isProduction, - preventAssignment: true, - }), - babel({ - exclude: 'node_modules/core-js/**', - babelHelpers: 'bundled', - babelrc: false, - presets: [ - [ - '@babel/preset-env', - { - targets: { - browsers: [ - '> 1%', - 'not op_mini all', - /** https://caniuse.com/es6-module */ - 'chrome >= 61', - 'safari >= 11', - 'edge >= 16', - 'Firefox >= 60', - ], - }, - loose: true, - bugfixes: false, - ignoreBrowserslistConfig: true, - }, - ], - ], - }), - ], - }); - - bundle - .write({ - format: 'es', - sourcemap: !isProduction ? 'inline' : false, - file: 'media/com_media/js/media-manager.js', - }) - .then((value) => (isProduction ? minifyCode(value.output[0].code) : value.output[0])) - .then((content) => { - if (isProduction) { - console.log('✅ ES2017 Media Manager ready'); - return writeFile(resolve('media/com_media/js/media-manager.min.js'), content.code, { encoding: 'utf8', mode: 0o644 }); - } - console.log('✅ ES2017 Media Manager ready'); - return copyFile(resolve('media/com_media/js/media-manager.js'), resolve('media/com_media/js/media-manager.min.js')); - }) - .catch((error) => { - console.error(error); - }); - - // closes the bundle - await bundle.close(); -}; - -export const watchMediaManager = async () => { - console.log('Watching Media Manager js+vue files...'); - console.log('========='); - const watcher = watch({ - input: resolve(inputJS), - plugins: [ - VuePlugin({ - target: 'browser', - css: false, - compileTemplate: true, - template: { - isProduction: true, - }, - }), - nodeResolve(), - commonjs(), - replace({ - 'process.env.NODE_ENV': JSON.stringify('development'), - __VUE_OPTIONS_API__: true, - __VUE_PROD_DEVTOOLS__: true, - preventAssignment: true, - }), - babel({ - exclude: 'node_modules/core-js/**', - babelHelpers: 'bundled', - babelrc: false, - presets: [ - [ - '@babel/preset-env', - { - targets: { - browsers: [ - '> 1%', - 'not op_mini all', - /** https://caniuse.com/es6-module */ - 'chrome 61', - 'safari 11', - 'edge 16', - 'Firefox 60', - ], - }, - loose: true, - bugfixes: false, - ignoreBrowserslistConfig: true, - }, - ], - ], - }), - ], - output: [ - { - format: 'es', - sourcemap: 'inline', - file: 'media/com_media/js/media-manager.js', - }, - { - format: 'es', - sourcemap: 'inline', - file: 'media/com_media/js/media-manager.min.js', - }, - ], - }); - - watcher.on('event', ({ code, result, error }) => { - if (result) result.close(); - if (error) console.log(error); - if (code === 'BUNDLE_END') console.log('Files updated ✅'); - }); -}; diff --git a/build/build-modules-js/javascript/compile-to-es2017.mjs b/build/build-modules-js/javascript/compile-to-es2017.mjs deleted file mode 100644 index af1cf740cf747..0000000000000 --- a/build/build-modules-js/javascript/compile-to-es2017.mjs +++ /dev/null @@ -1,101 +0,0 @@ -import { writeFile } from 'node:fs/promises'; -import { basename, sep, resolve } from 'node:path'; - -import { rollup } from 'rollup'; -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import { babel } from '@rollup/plugin-babel'; - -import { minifyCode } from './minify.mjs'; -import { getPackagesUnderScope } from '../init/common/resolve-package.cjs'; - -// List of external modules that should not be resolved by rollup -const externalModules = []; -const collectExternals = () => { - if (externalModules.length) { - return; - } - - // Joomla and Vendor modules - externalModules.push( - 'cropper-module', - 'codemirror', - 'joomla.dialog', - 'editor-api', - 'editor-decorator', - 'sa11y', - 'sa11y-lang', - ); - - // Codemirror modules - const cmModules = getPackagesUnderScope('@codemirror'); - if (cmModules) { - externalModules.push(...cmModules); - } - const lezerModules = getPackagesUnderScope('@lezer'); - if (lezerModules) { - externalModules.push(...lezerModules); - } -}; - -/** - * Compiles es6 files to es5. - * - * @param file the full path to the file + filename + extension - */ -export const handleESMFile = async (file) => { - const newPath = file.replace(/\.w-c\.es6\.js$/, '').replace(/\.es6\.js$/, '').replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`); - - // Make sure externals are collected - collectExternals(); - - const bundle = await rollup({ - input: resolve(file), - plugins: [ - nodeResolve({ preferBuiltins: false }), - babel({ - exclude: 'node_modules/core-js/**', - babelHelpers: 'bundled', - babelrc: false, - presets: [ - [ - '@babel/preset-env', - { - targets: { - browsers: [ - '> 1%', - 'not op_mini all', - /** https://caniuse.com/es6-module */ - 'chrome >= 61', - 'safari >= 11', - 'edge >= 16', - 'Firefox >= 60', - ], - }, - bugfixes: true, - loose: true, - }, - ], - ], - }), - ], - external: externalModules, - }); - - bundle.write({ - format: file.endsWith('core.es6.js') ? 'iife' : 'es', - sourcemap: false, - file: resolve(`${newPath}.js`), - }) - .then((value) => minifyCode(value.output[0].code)) - .then((content) => { - console.log(`✅ ES2017 file: ${basename(file).replace('.es6.js', '.js')}: transpiled`); - - return writeFile(resolve(`${newPath}.min.js`), content.code, { encoding: 'utf8', mode: 0o644 }); - }) - .catch((error) => { - console.error(error); - }); - - // closes the bundle - await bundle.close(); -}; diff --git a/build/build-modules-js/javascript/handle-es5.mjs b/build/build-modules-js/javascript/handle-es5.mjs deleted file mode 100644 index a7eae972d7b09..0000000000000 --- a/build/build-modules-js/javascript/handle-es5.mjs +++ /dev/null @@ -1,20 +0,0 @@ -import { basename, dirname, sep } from 'node:path'; - -import FsExtra from 'fs-extra'; -import { minifyFile } from './minify.mjs'; - -export const handleES5File = async (file) => { - if (file.endsWith('.js')) { - // ES5 file, we will copy the file and then minify it in place - // Ensure that the directories exist or create them - await FsExtra.ensureDir(dirname(file).replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`)); - await FsExtra.copy( - file, - file.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`).replace('.es5.js', '.js'), - { preserveTimestamps: true }, - ); - console.log(`✅ Legacy js file: ${basename(file)}: copied`); - - minifyFile(file.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`).replace('.es5.js', '.js')); - } -}; diff --git a/build/build-modules-js/javascript/js-handle.mjs b/build/build-modules-js/javascript/js-handle.mjs new file mode 100644 index 0000000000000..35c8f76b6edad --- /dev/null +++ b/build/build-modules-js/javascript/js-handle.mjs @@ -0,0 +1,159 @@ +/** + * JS handler + */ + +import fsp from 'node:fs/promises'; +import path from 'node:path'; +import fs from 'node:fs'; + +import { transform } from 'esbuild'; +import { rollup } from 'rollup'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import { babel } from '@rollup/plugin-babel'; +import { getPackagesUnderScope } from '../utils/resolve-package.mjs'; + +// List of external modules that should not be resolved by rollup +// @TODO: Make it configurable somehow? +const externalModules = []; +const getExternalModules = async () => { + if (externalModules.length) { + return externalModules; + } + + // Joomla and Vendor modules + externalModules.push( + 'cropper-module', + 'codemirror', + 'joomla.dialog', + 'editor-api', + 'editor-decorator', + 'sa11y', + 'sa11y-lang', + ); + + // Codemirror modules + const cmModules = getPackagesUnderScope('@codemirror'); + if (cmModules) { + externalModules.push(...cmModules); + } + const lezerModules = getPackagesUnderScope('@lezer'); + if (lezerModules) { + externalModules.push(...lezerModules); + } + + return externalModules; +}; + +/** + * Minify JS content + * + * @param { String } content + * @returns { Promise } + */ +export const minifyJSContent = async (content = '') => transform(content, { minify: true }) + .then((result) => result.code); + +/** + * Handle JS file without extra processing. Just minification. + * + * @param { String } srcPath + * @param { String } targetPath + * @returns { Promise } + */ +export const handleJSFile = async (srcPath, targetPath) => { + const targetFolder = path.dirname(targetPath); + + if (!fs.existsSync(targetFolder)) { + fs.mkdirSync(targetFolder, { mode: 0o755, recursive: true }); + } + + return fsp.readFile(srcPath, { encoding: 'utf8' }).then((content) => { + return minifyJSContent(content).then((jsMin) => { + // Copy source + const saveCopy = (srcPath !== targetPath) ? fsp.copyFile(srcPath, targetPath) : Promise.resolve(); + + // Store minified version + const saveMin = fsp.writeFile( + targetPath.replace('.js', '.min.js'), + jsMin, + { encoding: 'utf8', mode: 0o644 }, + ); + + return Promise.all([saveCopy, saveMin]); + }); + }).catch((error) => { + throw new Error(`Processing failed for "${srcPath}".`, { cause: error }); + }); +}; + +/** + * Handle JS file which requires extra processing. + * + * @param { String } srcPath + * @param { String } targetPath + * @param { string[] } externalModulesList + * @returns { Promise } + */ +export const handleMJSFile = async (srcPath, targetPath, externalModulesList = []) => { + const externalModules = externalModulesList && externalModulesList.length ? externalModulesList : await getExternalModules(); + const targetFolder = path.dirname(targetPath); + + if (!fs.existsSync(targetFolder)) { + fs.mkdirSync(targetFolder, { mode: 0o755, recursive: true }); + } + + return rollup({ + input: srcPath, + plugins: [ + nodeResolve({ preferBuiltins: false }), + babel({ + exclude: 'node_modules/core-js/**', + babelHelpers: 'bundled', + babelrc: false, + presets: [ + [ + '@babel/preset-env', + { + targets: { + browsers: [ + '> 1%', + 'not op_mini all', + /** https://caniuse.com/es6-module */ + 'chrome >= 61', + 'safari >= 11', + 'edge >= 16', + 'Firefox >= 60', + ], + }, + bugfixes: true, + loose: true, + }, + ], + ], + }), + ], + external: externalModules, + }).then((bundle) => { + // Process and store source file + const result = bundle.write({ + format: targetPath.endsWith('core.js') ? 'iife' : 'es', + sourcemap: false, + file: targetPath, + }); + + // Minify the code and store + const saveMin = result + .then((value) => minifyJSContent(value.output[0].code)) + .then((jsMin) => { + return fsp.writeFile( + targetPath.replace('.js', '.min.js'), + jsMin, + { encoding: 'utf8', mode: 0o644 }, + ); + }); + + return saveMin.then(() => bundle.close()); + }).catch((error) => { + throw new Error(`Processing failed for "${srcPath}".`, { cause: error }); + }); +}; diff --git a/build/build-modules-js/javascript/minify.mjs b/build/build-modules-js/javascript/minify.mjs deleted file mode 100644 index a01b7b6b0faeb..0000000000000 --- a/build/build-modules-js/javascript/minify.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import { basename } from 'node:path'; -import { readFile, writeFile } from 'node:fs/promises'; - -import { transform } from 'esbuild'; - -/** - * Minify a js file using esbuild - * - * @param file - * @returns {Promise} - */ -export const minifyFile = async (file) => { - const fileContent = await readFile(file, { encoding: 'utf8' }); - const content = await transform(fileContent, { minify: true }); - await writeFile(file.replace('.js', '.min.js'), content.code, { encoding: 'utf8', mode: 0o644 }); - console.log(`✅ Legacy js file: ${basename(file)}: minified`); -}; - -/** - * Minify a chunk of js using esbuild - * - * @param code - * @returns {Promise} - */ -export const minifyCode = async (code) => transform(code, { minify: true }); diff --git a/build/build-modules-js/settings.json b/build/build-modules-js/settings.json index 2d781c7a2ef72..6351505685411 100644 --- a/build/build-modules-js/settings.json +++ b/build/build-modules-js/settings.json @@ -1,6 +1,43 @@ { "settings": { "vendors": { + "altcha": { + "name": "altcha", + "js": { + "dist_external/altcha.js": "js/altcha.js", + "dist_external/worker.js": "js/worker.js" + }, + "css": { + "dist_external/altcha.css": "css/altcha.css" + }, + "provideAssets": [ + { + "name": "altcha", + "type": "script", + "uri": "altcha.js", + "attributes": { + "defer": true, + "async": true, + "type": "module" + } + }, + { + "name": "altcha", + "type": "style", + "uri": "altcha.css" + }, + { + "name": "altcha", + "type": "preset", + "dependencies": [ + "altcha#script", + "altcha#style" + ] + } + ], + "dependencies": [], + "licenseFilename": "LICENSE.txt" + }, "awesomplete": { "name": "awesomplete", "js": { @@ -383,8 +420,8 @@ "@fortawesome/fontawesome-free": { "name": "fontawesome-free", "css": { - "css/fontawesome.css": "css/fontawesome.css", - "css/fontawesome.min.css": "css/fontawesome.min.css" + "css/all.css": "css/fontawesome.css", + "css/all.min.css": "css/fontawesome.min.css" }, "filesExtra": { "scss": "scss", @@ -432,6 +469,11 @@ "name": "jquery", "type": "script", "uri": "jquery.min.js" + }, + { + "name": "jquery-noconflict", + "type": "script", + "uri": "jquery-noconflict.min.js" } ], "dependencies": [], @@ -487,7 +529,7 @@ "defer": true }, "dependencies": [ - "wcpolyfill" + "core" ] }, { @@ -498,7 +540,7 @@ "type": "module" }, "dependencies": [ - "wcpolyfill" + "core" ] }, { @@ -515,7 +557,7 @@ "defer": true }, "dependencies": [ - "wcpolyfill" + "core" ] }, { @@ -526,7 +568,7 @@ "type": "module" }, "dependencies": [ - "wcpolyfill" + "core" ] } ], @@ -602,63 +644,7 @@ }, "tinymce": { "name": "tinymce", - "licenseFilename": "license.txt" - }, - "@webcomponents/webcomponentsjs": { - "name": "webcomponentsjs", - "js": { - "webcomponents-bundle.js": "js/webcomponents-bundle.js" - }, - "dependencies": [], - "licenseFilename": "LICENSE.md", - "provideAssets": [ - { - "name": "wcpolyfill", - "type": "script", - "uri": "webcomponents-bundle.js", - "attributes": { - "nomodule": true, - "defer": true - }, - "dependencies": [ - "core" - ] - } - ] - }, - "chosen-js": { - "name": "chosen", - "js": { - "chosen.jquery.js": "js/chosen.jquery.js" - }, - "css": { - "chosen.css": "css/chosen.css", - "chosen-sprite.png": "css/chosen-sprite.png", - "chosen-sprite@2x.png": "css/chosen-sprite@2x.png" - }, - "provideAssets": [ - { - "name": "chosen", - "type": "style", - "uri": "chosen.css" - }, - { - "name": "chosen", - "type": "script", - "uri": "chosen.jquery.js", - "dependencies": [ - "jquery" - ] - }, - { - "name": "chosen", - "type": "preset", - "dependencies": [ - "chosen#style", - "chosen#script" - ] - } - ] + "licenseFilename": "license.md" }, "accessibility": { "name": "accessibility", @@ -797,9 +783,9 @@ "qrcode-generator": { "name": "qrcode", "js": { - "qrcode.js": "js/qrcode.js", - "qrcode_SJIS.js": "js/qrcode_SJIS.js", - "qrcode_UTF8.js": "js/qrcode_UTF8.js" + "dist/qrcode.js": "js/qrcode.js", + "dist/qrcode_SJIS.js": "js/qrcode_SJIS.js", + "dist/qrcode_UTF8.js": "js/qrcode_UTF8.js" }, "provideAssets": [ { diff --git a/build/build-modules-js/stylesheets/css-handler.mjs b/build/build-modules-js/stylesheets/css-handler.mjs new file mode 100644 index 0000000000000..49b6c9c66e7fe --- /dev/null +++ b/build/build-modules-js/stylesheets/css-handler.mjs @@ -0,0 +1,109 @@ +/** + * CSS handler + */ + +import rtlcss from 'rtlcss'; +import path from 'node:path'; +import fsp from 'node:fs/promises'; +import fs from 'node:fs'; + +import { composeVisitors, transform as transformCss } from 'lightningcss'; +import { urlVersioning2 } from './css-versioning.mjs'; +import { createHash } from 'node:crypto'; + +/** + * Preprocess Css content + * + * @param { String } content + * @returns { Promise } + */ +export const preprocessCSS = async (content = '') => { + // Remove @charset "UTF-8" at beginning to preserve the license + // Because the license comment needs to start at the beginning of the file to be saved + content = content.startsWith('@charset "UTF-8";\n') ? content.replace('@charset "UTF-8";\n', '') : content; + + // Check the header comments and make sure it starts with /*! + // This need to force lightningcss to keep the license comments + if (content.substring(0, 50).includes('/**')) { + content = content.replace('/**', '/*!'); + } + + // Run url() versioning for the source + const hash = createHash('md5'); + hash.update(content); + const hashStr = hash.digest('hex').substring(0, 6); + + const { code: css } = transformCss({ + code: Buffer.from(content), + minify: false, + visitor: composeVisitors([urlVersioning2(hashStr)]), // Adds a hash to the url() parts of the static css + }); + + return css.toString(); +}; + +/** + * Minify Css content + * @param { String } content + * @returns { Promise } + */ +export const minifyCSS = async (content = '') => { + const { code: cssMin } = transformCss({ + code: Buffer.from(content), + minify: true, + }); + + return cssMin.toString(); +}; + +/** + * Handle CSS content and store it at the destination. + * Store source and minified version. + * + * @param { String } targetPath + * @param { String } content + * @returns { Promise } + */ +export const handleAndStoreCSSContent = async (targetPath, content = '') => { + if (targetPath.endsWith('-rtl.css')) { + content = rtlcss.process(content); + } + + const css = await preprocessCSS(content); + const cssMin = await minifyCSS(css); + const targetFolder = path.dirname(targetPath); + + if (!fs.existsSync(targetFolder)) { + fs.mkdirSync(targetFolder, { mode: 0o755, recursive: true }); + } + + const save = fsp.writeFile( + targetPath, + `@charset "UTF-8";\n${css}`, // Force "UTF-8" for all, also it is removed by preprocessCSS + { encoding: 'utf8', mode: 0o644 }, + ); + + // Save minified css file + const saveMin = fsp.writeFile( + targetPath.replace('.css', '.min.css'), + `@charset "UTF-8";${cssMin}`, + { encoding: 'utf8', mode: 0o644 }, + ); + + return Promise.all([save, saveMin]); +}; + +/** + * Read source CSS, handle its content and store it at the destination. + * + * @param { String } srcPath + * @param { String } targetPath + * @returns { Promise } + */ +export const handleCSSFile = async (srcPath, targetPath) => { + return fsp.readFile(srcPath, { encoding: 'utf8' }).then((content) => { + return handleAndStoreCSSContent(targetPath, content); + }).catch((error) => { + throw new Error(`Processing failed for "${srcPath}".`, { cause: error }); + }); +}; diff --git a/build/build-modules-js/stylesheets/css-versioning.mjs b/build/build-modules-js/stylesheets/css-versioning.mjs index 19ade2f165a2c..7c5ad8e444c17 100644 --- a/build/build-modules-js/stylesheets/css-versioning.mjs +++ b/build/build-modules-js/stylesheets/css-versioning.mjs @@ -1,15 +1,11 @@ import { createHash } from 'node:crypto'; -import { readdir, readFile, writeFile } from 'node:fs/promises'; import { existsSync, readFileSync } from 'node:fs'; -import { dirname, extname, resolve } from 'node:path'; -import { transform, composeVisitors } from 'lightningcss'; -import { Timer } from '../utils/timer.mjs'; +import { dirname, resolve } from 'node:path'; -const RootPath = process.cwd(); const skipExternal = true; const variable = 'v'; -function version(urlString, fromFile) { +function version(urlString, fromFile, withHash) { // Skip external URLs if (skipExternal && (urlString.startsWith('http') || urlString.startsWith('//'))) { return `${urlString}`; @@ -27,6 +23,10 @@ function version(urlString, fromFile) { return `${urlString}`; } + if (withHash) { + return `${urlString}?${variable}=${withHash}`; + } + if (fromFile && existsSync(resolve(`${dirname(fromFile)}/${urlString}`))) { const hash = createHash('md5'); hash.update(readFileSync(resolve(`${dirname(fromFile)}/${urlString}`))); @@ -50,58 +50,15 @@ const urlVersioning = (fromFile) => ({ }); /** - * Adds a hash to the url() parts of the static css - * - * @param file - * @returns {Promise} - */ -const fixVersion = async (file) => { - try { - let content = await readFile(file, { encoding: 'utf8' }); - // To preserve the licence the comment needs to start at the beginning of the file - const replaceUTF8String = file.endsWith('.min.css') ? '@charset "UTF-8";' : '@charset "UTF-8";\n'; - content = content.startsWith(replaceUTF8String) ? content.replace(replaceUTF8String, '') : content; - - // Preserve a leading license comment (/** ... */) - const firstLine = content.split(/\r?\n/)[0] || ''; - if (firstLine.includes('/*') && !firstLine.includes('/*!')) { - const endCommentIdx = content.indexOf('*/'); - if (endCommentIdx !== -1 - && (content.substring(0, endCommentIdx).includes('license') - || content.substring(0, endCommentIdx).includes('copyright')) - ) { - content = firstLine.includes('/**') ? content.replace('/**', '/*!') : content.replace('/*', '/*!'); - } - } - - const { code } = transform({ - code: Buffer.from(content), - minify: file.endsWith('.min.css'), - visitor: composeVisitors([urlVersioning(file)]), - }); - await writeFile(file, `@charset "UTF-8";${file.endsWith('.min.css') ? '' : '\n'}${code}`, { - encoding: 'utf8', - mode: 0o644, - }); - } catch (error) { - throw new Error(error); - } -}; - -/** - * Loop the media folder and add version to all url() entries in all the css files - * - * @returns {Promise} + * @param {withHash: String} - the filepath for the css file + * @returns {import('lightningcss').Visitor} - A visitor that replaces the url */ -const cssVersioningVendor = async () => { - const bench = new Timer('Versioning'); - - const cssFiles = (await readdir(`${RootPath}/media/vendor`, { withFileTypes: true, recursive: true })) - .filter((file) => (!file.isDirectory() && extname(file.name) === '.css')) - .map((file) => `${file.parentPath}/${file.name}`); - - Promise.all(cssFiles.map((file) => fixVersion(file))) - .then(() => bench.stop()); -}; +const urlVersioning2 = (withHash) => ({ + /** + * @param {import('lightningcss').Url} url - The url object to transform + * @returns {import('lightningcss').Url} - The transformed url object + */ + Url: (url) => ({ ...url, url: version(url.url, false, withHash) }), +}); -export { urlVersioning, cssVersioningVendor }; +export { urlVersioning, urlVersioning2 }; diff --git a/build/build-modules-js/stylesheets/handle-css.mjs b/build/build-modules-js/stylesheets/handle-css.mjs deleted file mode 100644 index e4609a8e84673..0000000000000 --- a/build/build-modules-js/stylesheets/handle-css.mjs +++ /dev/null @@ -1,55 +0,0 @@ -import { dirname, sep } from 'node:path'; - -import pkg from 'fs-extra'; -import { transform as transformCss, composeVisitors } from 'lightningcss'; -import { urlVersioning } from './css-versioning.mjs'; - -const { - readFile, writeFile, ensureDir, -} = pkg; - -export const handleCssFile = async (file) => { - const outputFile = file.replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`); - try { - // CSS file, we will process the file and then minify it in place - // Ensure that the directories exist or create them - await ensureDir(dirname(outputFile), { recursive: true, mode: 0o755 }); - - let content = await readFile(file, { encoding: 'utf8' }); - - // To preserve the licence the comment needs to start at the beginning of the file - content = content.startsWith('@charset "UTF-8";\n') ? content.replace('@charset "UTF-8";\n', '') : content; - - if (file !== outputFile) { - const { code: css } = transformCss({ - code: Buffer.from(content), - minify: false, - visitor: composeVisitors([urlVersioning(file)]), // Adds a hash to the url() parts of the static css - }); - - // Save optimized css file - await writeFile( - outputFile, - content.startsWith('@charset "UTF-8";') - ? css - : `@charset "UTF-8"; -${css}`, - { encoding: 'utf8', mode: 0o644 }, - ); - } - - // Process the file and minify it in place - const { code: cssMin } = transformCss({ - code: Buffer.from(content), - minify: true, - visitor: composeVisitors([urlVersioning(outputFile)]), // Adds a hash to the url() parts of the static css - }); - - // Save minified css file - await writeFile(outputFile.replace('.css', '.min.css'), `@charset "UTF-8";${cssMin}`, { encoding: 'utf8', mode: 0o644 }); - - console.log(`✅ CSS file copied/minified: ${file}`); - } catch (err) { - console.log(err); - } -}; diff --git a/build/build-modules-js/stylesheets/handle-scss.mjs b/build/build-modules-js/stylesheets/handle-scss.mjs deleted file mode 100644 index ee7a598167eff..0000000000000 --- a/build/build-modules-js/stylesheets/handle-scss.mjs +++ /dev/null @@ -1,66 +0,0 @@ -import { writeFile } from 'node:fs/promises'; -import { dirname, sep } from 'node:path'; - -import rtlcss from 'rtlcss'; -import { ensureDir } from 'fs-extra'; -import { transform as transformCss, Features, composeVisitors } from 'lightningcss'; -import { compileAsync } from 'sass-embedded'; -import { urlVersioning } from './css-versioning.mjs'; - -const getOutputFile = (file) => file.replace(`${sep}scss${sep}`, `${sep}css${sep}`).replace('.scss', '.css').replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`); - -export const handleScssFile = async (file) => { - let contents; - const cssFile = getOutputFile(file); - - try { - const { css } = await compileAsync(file); - contents = css.toString(); - } catch (error) { - throw new Error(error.formatted); - } - - if (cssFile.endsWith('-rtl.css')) { - contents = rtlcss.process(contents); - } - - // To preserve the licence the comment needs to start at the beginning of the file - contents = contents.startsWith('@charset "UTF-8";\n') ? contents.replace('@charset "UTF-8";\n', '') : contents; - - // Ensure the folder exists or create it - await ensureDir(dirname(cssFile), {}); - - const { code: css } = transformCss({ - code: Buffer.from(contents), - minify: false, - exclude: Features.VendorPrefixes, - visitor: composeVisitors([urlVersioning(file)]), // Adds a hash to the url() parts of the static css - }); - - // Save optimized css file - await writeFile( - cssFile, - contents.startsWith('@charset "UTF-8";') - ? css - : `@charset "UTF-8"; -${css}`, - { encoding: 'utf8', mode: 0o644 }, - ); - - const { code: cssMin } = transformCss({ - code: Buffer.from(contents), - minify: true, - exclude: Features.VendorPrefixes, - visitor: composeVisitors([urlVersioning(cssFile)]), // Adds a hash to the url() parts of the static css - }); - - // Ensure the folder exists or create it - await ensureDir(dirname(cssFile.replace('.css', '.min.css')), {}); - await writeFile( - cssFile.replace('.css', '.min.css'), - `@charset "UTF-8";${cssMin}`, - { encoding: 'utf8', mode: 0o644 }, - ); - - console.log(`✅ SCSS File compiled: ${cssFile}`); -}; diff --git a/build/build-modules-js/stylesheets/scss-handler.mjs b/build/build-modules-js/stylesheets/scss-handler.mjs new file mode 100644 index 0000000000000..61d44b14a484d --- /dev/null +++ b/build/build-modules-js/stylesheets/scss-handler.mjs @@ -0,0 +1,25 @@ +/** + * SCSS handler + */ +import { compileAsync } from 'sass-embedded'; +import { handleAndStoreCSSContent } from './css-handler.mjs'; + +/** + * Read source SCSS, compile it to CSS and store it at the destination. + * + * @param { String } srcPath + * @param { String } targetPath + * @param { boolean } silent + * @returns { Promise } + */ +export const handleSCSSFile = async (srcPath, targetPath, silent = false) => { + return compileAsync(srcPath, { + quietDeps: true, + silenceDeprecations: silent ? ['if-function', 'import', 'global-builtin', 'color-functions'] : [], + }) + .then(({ css: content }) => { + return handleAndStoreCSSContent(targetPath, content); + }).catch((error) => { + throw new Error(`Processing failed for "${srcPath}".`, { cause: error }); + }); +}; diff --git a/build/build-modules-js/utils/compressFile.mjs b/build/build-modules-js/utils/compressFile.mjs index c03dbe864c919..fe033f861f54f 100644 --- a/build/build-modules-js/utils/compressFile.mjs +++ b/build/build-modules-js/utils/compressFile.mjs @@ -19,17 +19,23 @@ const gzipEncode = (data) => gzipPromise(data, gzipOpts); const brotliPromise = promisify(brotliCompress); const brotliEncode = (data) => brotliPromise(data, brotliOpts); -export const compressFile = async (file, enableBrotli) => { - if (file.endsWith('.min.js') || file.endsWith('.min.css')) { - try { - const data = await readFile(file); - await writeFile(`${file}.gz`, await gzipEncode(data)); - if (enableBrotli) { - await writeFile(`${file}.br`, await brotliEncode(data)); - } - console.log(file); - } catch (err) { - console.info(`Error on ${file}: ${err.code}`); - } - } +/** + * Compress and store the result aside original file. + * @param { String } file + * @param { boolean } enableBrotli + * @return {Promise} + */ +export const compressFileAndSave = async (file, enableBrotli = false) => { + return readFile(file).then((content) => { + const gzipRun = gzipEncode(content).then((data) => { + return writeFile(`${file}.gz`, data); + }); + const brotliRun = !enableBrotli + ? Promise.resolve() + : brotliEncode(content).then(() => { + return writeFile(`${file}.br`, data); + }); + + return Promise.all([gzipRun, brotliRun]); + }); }; diff --git a/build/build-modules-js/utils/resolve-package.mjs b/build/build-modules-js/utils/resolve-package.mjs new file mode 100644 index 0000000000000..7b8201885eb29 --- /dev/null +++ b/build/build-modules-js/utils/resolve-package.mjs @@ -0,0 +1,63 @@ +/** + * Resolve Package Helper + */ +import path from 'node:path'; +import { existsSync, readdirSync } from 'node:fs'; +import { createRequire } from 'node:module'; + +/** + * Find full path for package file. + * Replacement for require.resolve(), as it is broken for packages with "exports" property. + * + * @param {string} relativePath Relative path to the file to resolve, in format packageName/file-name.js + * @returns {string|boolean} + */ +export const resolvePackageFile = (relativePath) => { + // Get list of node.js include paths + const paths = createRequire(import.meta.url).resolve.paths('node'); + + for (let i = 0, l = paths.length; i < l; i += 1) { + const fullPath = path.join(paths[i], relativePath); + + if (existsSync(fullPath)) { + return fullPath; + } + } + + return false; +}; + +/** + * Find a list of modules under given scope, + * eg: @foobar will look for all submodules @foobar/foo, @foobar/bar + * + * @param scope + * @returns {[]} + */ +export const getPackagesUnderScope = (scope) => { + const cmModules = new Set(); + + // Get list of node.js include paths + const paths = createRequire(import.meta.url).resolve.paths('node'); + + // Get the scope roots + const roots = []; + paths.forEach((pathBase) => { + const fullPath = path.join(pathBase, scope); + if (existsSync(fullPath)) { + roots.push(fullPath); + } + }); + + // List of modules + // Use forward slashes for module names (package specifiers always use forward slashes, + // even on Windows; using path.join() here would produce backslashes on Windows and + // break Rollup's external module matching). + roots.forEach((rootPath) => { + readdirSync(rootPath).forEach((subModule) => { + cmModules.add(`${scope}/${subModule}`); + }); + }); + + return [...cmModules]; +}; diff --git a/build/build-modules-js/versioning.mjs b/build/build-modules-js/versioning.mjs deleted file mode 100644 index 3eb985a6abbf5..0000000000000 --- a/build/build-modules-js/versioning.mjs +++ /dev/null @@ -1,128 +0,0 @@ -import { - lstat, readdir, readFile, writeFile, -} from 'node:fs/promises'; -import { - basename, dirname, resolve, sep, -} from 'node:path'; - -import { createHashFromFile } from './utils/hashfromfile.mjs'; -import { Timer } from './utils/timer.mjs'; - -const RootPath = process.cwd(); -const exclusion = [ - // We will skip these: - '.DS_Store', - 'index.html', - 'cache', - 'vendors', -]; -const final = {}; - -/** - * Update a given joomla.assets.json entry - * - * @param asset - * @param directory - * @returns {Promise<{type}|*>} - */ -const updateAsset = async (asset, directory) => { - const currentDir = `${RootPath}${sep}media${sep}${directory}`; - if (!asset.type) { - final[directory].push(asset); - return; - } - let subDir; - if (asset.type === 'script') { - subDir = 'js'; - } - if (asset.type === 'style') { - subDir = 'css'; - } - if (!subDir) { - final[directory].push(asset); - return; - } - - let path = `${currentDir}${sep}${subDir}${sep}${basename(asset.uri)}`; - if (`${directory}/${basename(asset.uri)}` !== asset.uri) { - if (dirname(asset.uri) === 'system/fields') { - path = `${currentDir}${sep}${subDir}${sep}fields${sep}${basename(asset.uri)}`; - } else { - final[directory].push(asset); - return; - } - } - - const jAssetFile = await lstat(path); - - if (!jAssetFile.isFile()) { - final[directory].push(asset); - return; - } - - const hash = await createHashFromFile(path); - - asset.version = hash.substring(0, 6); - final[directory].push(asset); -}; - -/** - * Read the joomla.assets.json and loop the assets - * - * @param directory - * @returns {Promise} - */ -const fixVersion = async (directory) => { - let jAssetFile; - try { - jAssetFile = await lstat(`${RootPath}${sep}media${sep}${directory}${sep}joomla.asset.json`); - } catch (err) { - return; - } - - if (!jAssetFile.isFile()) { - return; - } - - const jAssetFileContent = await readFile(`${RootPath}${sep}media${sep}${directory}${sep}joomla.asset.json`, { encoding: 'utf8' }); - let jsonData; - try { - jsonData = JSON.parse(jAssetFileContent); - } catch (err) { - throw new Error(`media\\${directory}\\joomla.asset.json is not a valid JSON file!!!`); - } - - if (!jsonData || !jsonData.assets.length) { - return; - } - - const processes = []; - jsonData.assets.map((asset) => processes.push(updateAsset(asset, directory))); - - await Promise.all(processes); - - jsonData.assets = final[directory]; - await writeFile(`${RootPath}${sep}media${sep}${directory}${sep}joomla.asset.json`, JSON.stringify(jsonData, '', 2), { encoding: 'utf8', mode: 0o644 }); -}; - -/** - * Loop the media folder and add version to all .js/.css entries in all - * the joomla.assets.json files - * - * @returns {Promise} - */ -export const versioning = async () => { - const bench = new Timer('Versioning'); - const tasks = []; - let mediaDirectories = await readdir(resolve(RootPath, 'media')); - mediaDirectories = mediaDirectories.filter((dir) => !exclusion.includes(dir)); - - mediaDirectories.forEach((directory) => { - final[directory] = []; - tasks.push(fixVersion(directory)); - }); - - await Promise.all(tasks); - - bench.stop(); -}; diff --git a/build/build-modules-js/watch.mjs b/build/build-modules-js/watch.mjs deleted file mode 100644 index 648dc468a82a8..0000000000000 --- a/build/build-modules-js/watch.mjs +++ /dev/null @@ -1,44 +0,0 @@ -import { - join, extname, basename, dirname, -} from 'node:path'; -import chokidar from 'chokidar'; - -import { handleESMFile } from './javascript/compile-to-es2017.mjs'; -import { handleES5File } from './javascript/handle-es5.mjs'; -import { handleScssFile } from './stylesheets/handle-scss.mjs'; -import { handleCssFile } from './stylesheets/handle-css.mjs'; -import { debounce } from './utils/debounce.mjs'; - -const RootPath = process.cwd(); - -const processFile = (file) => { - if (extname(file) === '.js' && !dirname(file).startsWith(join(RootPath, 'build/media_source/vendor/bootstrap/js'))) { - if ((file.endsWith('.w-c.es6.js') || file.endsWith('.es6.js')) && !file.startsWith('_')) { - debounce(handleESMFile(file), 300); - } - if (file.endsWith('.es5..js')) { - debounce(handleES5File(file), 300); - } - } - - if (extname(file) === '.scss' && !basename(file).startsWith('_')) { - debounce(handleScssFile(file), 300); - } - if (extname(file) === '.css') { - debounce(handleCssFile(file), 300); - } -}; - -export const watching = (path) => { - const watchingPath = path ? join(RootPath, path) : join(RootPath, 'build/media_source'); - const watcher = chokidar.watch(watchingPath, { - ignored: /(^|[/\\])\../, // ignore dotfiles - persistent: true, - }); - - watcher - .on('add', (file) => processFile(file)) - .on('change', (file) => processFile(file)); - // @todo Handle this case as well - // .on('unlink', path => log(`File ${path} has been removed`)); -}; diff --git a/build/build.mjs b/build/build.mjs index a82f28620594d..a53f31c131727 100644 --- a/build/build.mjs +++ b/build/build.mjs @@ -1,202 +1,61 @@ /** - * Command line helper - * - * To get the complete functional media folder please run: - * npm ci - * - * For dedicated tasks, please run: - * node build.mjs --build-pages will create the error pages (for incomplete repo build PHP+NPM) - * node build.mjs --copy-assets will clean the media/vendor folder and then will populate the folder from node_modules - * node build.mjs --compile-js will transpile ES6 files and also uglify the ES6,ES5 files - * node build.mjs --compile-css will compile all the scss defined files and also create a minified version of the css - * node build.mjs --compile-bs will compile all the Bootstrap javascript components - * node build.mjs --com-media will compile the media manager Vue application - * node build.mjs --watch-com-media will watch and compile the media manager Vue application - * node build.mjs --gzip will create gzip files for all the minified stylesheets and scripts. - * node build.mjs --versioning will update all the joomla.assets.json files providing accurate versions for stylesheets and scripts. + * Script used to build Joomla Web Assets content */ -import { createRequire } from 'node:module'; import { Command } from 'commander'; import semver from 'semver'; - -// Joomla Build modules -import { createErrorPages } from './build-modules-js/error-pages.mjs'; -import { stylesheets } from './build-modules-js/compilecss.mjs'; -import { scripts } from './build-modules-js/compilejs.mjs'; -import { bootstrapJs } from './build-modules-js/javascript/build-bootstrap-js.mjs'; -import { localisePackages } from './build-modules-js/init/localise-packages.mjs'; -import { minifyVendor } from './build-modules-js/init/minify-vendor.mjs'; -import { patchPackages } from './build-modules-js/init/patches.mjs'; -import { cleanVendors } from './build-modules-js/init/cleanup-media.mjs'; -import { recreateMediaFolder } from './build-modules-js/init/recreate-media.mjs'; -import { watching } from './build-modules-js/watch.mjs'; -import { mediaManager, watchMediaManager } from './build-modules-js/javascript/build-com_media-js.mjs'; -import { compressFiles } from './build-modules-js/compress.mjs'; -import { versioning } from './build-modules-js/versioning.mjs'; import { Timer } from './build-modules-js/utils/timer.mjs'; -import { compileCodemirror } from './build-modules-js/javascript/build-codemirror.mjs'; -import { cssVersioningVendor } from './build-modules-js/stylesheets/css-versioning.mjs'; - -const require = createRequire(import.meta.url); - -// The settings -const options = require('../package.json'); -const settings = require('./build-modules-js/settings.json'); +import buildCommand from './build-modules-js/command/build-command.mjs'; +import watchCommand from './build-modules-js/command/watch-command.mjs'; +import pkgOptions from '../package.json' with { type: 'json' }; +import { builders, blockingBuilders } from './build-modules-js/builders-registry.mjs'; -const handleError = (err, terminateCode) => { - console.error(err); - process.exitCode = terminateCode; -}; - -if (semver.gte(semver.minVersion(options.engines.node), semver.clean(process.version))) { - handleError( - `Node version ${semver.clean(process.version)} is not supported, please upgrade to Node version ${semver.clean(options.engines.node)}`, - 1, - ); +// Check minimum Node version +if (semver.gte(semver.minVersion(pkgOptions.engines.node), semver.clean(process.version))) { + throw new Error(`Node version ${semver.clean(process.version)} is not supported, please upgrade to Node version ${semver.clean(pkgOptions.engines.node)}`); } -// The command line -const Program = new Command(); - -// Merge Joomla's specific settings to the main package.json object -if ('settings' in settings) { - options.settings = settings.settings; -} - -const allowedVersion = () => { - if (!semver.satisfies(process.version.substring(1), options.engines.node)) { - handleError( - `Command line tools require Node Version ${options.engines.node} but found ${process.version}`, - -1, - ); - } -}; - -// Initialize the CLI -Program.allowUnknownOption() - .version(options.version) - .option('--copy-assets', 'Moving files from node_modules to media folder') - .option( - '--build-pages', - 'Creates the error pages for unsupported PHP version & incomplete environment', - ) - .option( - '--compile-js, --compile-js path', - 'Handles ES6, ES5 and web component scripts', - ) - .option( - '--compile-css, --compile-css path', - 'Compiles all the scss files to css', - ) - .option('--compile-bs', 'Compiles all the Bootstrap component scripts.') - .option('--compile-codemirror', 'Compiles all the codemirror modules.') - .option( - '--watch', - 'Watch file changes and re-compile (ATM only works for the js in the media_source).', - ) - .option('--com-media', 'Compile the Media Manager client side App.') - .option( - '--watch-com-media', - 'Watch and Compile the Media Manager client side App.', - ) - .option('--gzip', 'Compress all the minified stylesheets and scripts.') - .option('--prepare', 'Run all the needed tasks to initialise the repo') - .option( - '--versioning', - 'Update all the .js/.css versions on their relative joomla.assets.json', - ) +// The command line, initialize +const program = new Command(); +program + // Show correct command hint in the Help + .name('node build/build.mjs') + .version(pkgOptions.version) .addHelpText( 'after', ` -Version: ${options.version} +Version: ${pkgOptions.version} `, ); -Program.parse(process.argv); - -const cliOptions = Program.opts(); - -// Update the vendor folder -if (cliOptions.copyAssets) { - allowedVersion(); - recreateMediaFolder(options) - .then(() => cleanVendors()) - .then(() => localisePackages(options)) - .then(() => patchPackages(options)) - .then(() => cssVersioningVendor()) - .then(() => minifyVendor()) - .catch((error) => handleError(error, 1)); -} - -// Creates the error pages for unsupported PHP version & incomplete environment -if (cliOptions.buildPages) { - createErrorPages(options).catch((err) => handleError(err, 1)); -} - -// Convert scss to css -if (cliOptions.compileCss) { - stylesheets(options, Program.args[0]).catch((err) => handleError(err, 1)); -} - -// Compress/transpile the javascript files -if (cliOptions.compileJs) { - scripts(options, Program.args[0]).catch((err) => handleError(err, 1)); -} - -// Watch & Compile the javascript files in the media_source folder -if (cliOptions.watch) { - watching(Program.args[0]); -} - -// Compile the Bootstrap javascript components -if (cliOptions.compileBs) { - bootstrapJs(); -} - -// Compile codemirror -if (cliOptions.compileCodemirror) { - compileCodemirror(); -} - -// Gzip js/css files -if (cliOptions.gzip) { - compressFiles(); -} - -// Compile the media manager -if (cliOptions.comMedia) { - // false indicates "no watch" - mediaManager(false); -} - -// Watch & Compile the media manager -if (cliOptions.watchComMedia) { - watchMediaManager(true); -} - -// Update the .js/.css versions -if (cliOptions.versioning) { - versioning().catch((err) => handleError(err, 1)); -} - -// Prepare the repo for dev work -if (cliOptions.prepare) { - const bench = new Timer('Build'); - allowedVersion(); - recreateMediaFolder(options) - .then(() => cleanVendors()) - .then(() => localisePackages(options)) - .then(() => patchPackages(options)) - .then(() => minifyVendor()) - .then(() => createErrorPages(options)) - .then(() => stylesheets(options, Program.args[0])) - .then(() => cssVersioningVendor()) - .then(() => scripts(options, Program.args[0])) - .then(() => mediaManager()) - .then(() => bootstrapJs()) - .then(() => compileCodemirror()) - .then(() => bench.stop('Build')) - .catch((err) => handleError(err, -1)); -} +program + .command('builders-list') + .description('Show list of builders') + .action(() => { + console.log(builders.join('\n')); + }); + +program + .command('build') + .description('Build all or only specified asset') + .option('-a,--all', 'build all assets') + .option('-n,--name ', 'build specific resource(s)') + .option('-t,--task ', 'task(s) to run for specified resource(s)') + .option('--sass-silent', 'hide SASS deprecations and warnings') + .action((options) => { + const bench = new Timer('Build command'); + buildCommand(program, options, builders, blockingBuilders) + .then(() => bench.stop('Build command')); + }); + +program + .command('watch') + .description('Watch specified asset and rebuild on changes') + .option('-a,--all', 'watch all assets') + .option('-n,--name ', 'builder(s) to watch') + .action((options) => { + watchCommand(program, options, builders); + }); + +program.parse(process.argv); diff --git a/build/build.php b/build/build.php index 573a06db27dd6..a8408f2c12e64 100644 --- a/build/build.php +++ b/build/build.php @@ -86,6 +86,8 @@ function clean_checkout(string $dir) run_and_check('find libraries/vendor -name CODE_OF_CONDUCT.md | xargs rm -rf -'); run_and_check('find libraries/vendor -name CONDUCT.md | xargs rm -rf -'); run_and_check('find libraries/vendor -name docker-compose.yml | xargs rm -rf -'); + run_and_check('find libraries/vendor -name Dockerfile | xargs rm -rf -'); + run_and_check('find libraries/vendor -name compose.yml | xargs rm -rf -'); run_and_check('find libraries/vendor -name phpunit.xml | xargs rm -rf -'); run_and_check('find libraries/vendor -name README.md | xargs rm -rf -'); run_and_check('find libraries/vendor -name readme.md | xargs rm -rf -'); @@ -112,7 +114,6 @@ function clean_checkout(string $dir) run_and_check('find libraries/vendor -name .php_cs.dist | xargs rm -rf -'); run_and_check('find libraries/vendor -name phpcs.xsd | xargs rm -rf -'); run_and_check('find libraries/vendor -name phpcs.xml | xargs rm -rf -'); - run_and_check('find libraries/vendor -name build.xml | xargs rm -rf -'); run_and_check('find libraries/vendor -name infection.json.dist | xargs rm -rf -'); run_and_check('find libraries/vendor -name phpbench.json | xargs rm -rf -'); run_and_check('find libraries/vendor -name phpstan.neon.dist | xargs rm -rf -'); @@ -358,9 +359,6 @@ function capture_or_fail(string $command): string // Create gzipped version of the static assets run_and_check('npm run gzip'); -// Create version entries of the static assets in their respective joomla.asset.json -run_and_check('npm run versioning'); - // Clean the checkout of extra resources if (!$debugBuild) { clean_checkout($fullpath); @@ -446,15 +444,13 @@ function capture_or_fail(string $command): string '.gitignore', '.php-cs-fixer.dist.php', 'acceptance.suite.yml', - // Media Manager Node Assets - 'administrator/components/com_media/resources', 'build', - 'build.xml', 'CODE_OF_CONDUCT.md', 'composer.json', 'composer.lock', 'crowdin.yml', 'cypress.config.dist.mjs', + 'media_source', 'package-lock.json', 'package.json', 'phpstan-baseline.neon', diff --git a/build/bump.php b/build/bump.php index 5f266acc00c02..44c77a6144642 100644 --- a/build/bump.php +++ b/build/bump.php @@ -57,8 +57,6 @@ function usage($command) $languagePackXmlFile = '/administrator/manifests/packages/pkg_en-GB.xml'; -$antJobFile = '/build.xml'; - $packageJsonFiles = [ '/package.json', '/package-lock.json', @@ -162,7 +160,7 @@ function usage($command) 'build' => '', 'reldate' => $date->format('j-F-Y'), 'reltime' => $date->format('H:i'), - 'reltz' => 'GMT', + 'reltz' => 'UTC', 'credate' => $date->format('Y-m'), ]; @@ -243,13 +241,6 @@ function usage($command) file_put_contents($rootPath . $languagePackXmlFile, $fileContents); } -// Updates the version for the `phpdoc` task in the Ant job file. -if (file_exists($rootPath . $antJobFile)) { - $fileContents = file_get_contents($rootPath . $antJobFile); - $fileContents = preg_replace('##', '', $fileContents); - file_put_contents($rootPath . $antJobFile, $fileContents); -} - // Updates the version in the package.json file. foreach ($packageJsonFiles as $packageJsonFile) { if (file_exists($rootPath . $packageJsonFile)) { diff --git a/build/deleted_file_check.php b/build/deleted_file_check.php index c2d14e69f7583..b18fd3971cb2f 100644 --- a/build/deleted_file_check.php +++ b/build/deleted_file_check.php @@ -59,29 +59,14 @@ function usage($command) exit(1); } -// Directories to skip for the check (needs to include anything from J3 we want to keep) +// Directories to skip for the check (needs to include anything from previous versions which we want to keep) $previousReleaseExclude = [ - $options['from'] . '/administrator/components/com_search', - $options['from'] . '/components/com_search', $options['from'] . '/images/sampledata', $options['from'] . '/installation', - $options['from'] . '/media/com_cpanel/js', - $options['from'] . '/media/com_modules/js', - $options['from'] . '/media/legacy/js', - $options['from'] . '/media/mod_multilangstatus', - $options['from'] . '/media/plg_quickicon_eos310', - $options['from'] . '/media/system/images', - $options['from'] . '/modules/mod_search', - $options['from'] . '/plugins/captcha/recaptcha', - $options['from'] . '/plugins/captcha/recaptcha_invisible', - $options['from'] . '/plugins/fields/repeatable', - $options['from'] . '/plugins/quickicon/eos310', - $options['from'] . '/plugins/search', - $options['from'] . '/plugins/system/compat', - $options['from'] . '/plugins/system/logrotation', - $options['from'] . '/plugins/system/sessiongc', - $options['from'] . '/plugins/system/updatenotification', - $options['from'] . '/plugins/task/demotasks', + $options['from'] . '/media/plg_captcha_recaptcha', + $options['from'] . '/media/plg_captcha_recaptcha_invisible', + $options['from'] . '/media/plg_behaviour_compat', + $options['from'] . '/plugins/behaviour/compat', ]; /** @@ -159,50 +144,14 @@ function usage($command) // Specific files (e.g. language files) that we want to keep on upgrade $filesToKeep = [ - "'/administrator/language/en-GB/en-GB.com_search.ini',", - "'/administrator/language/en-GB/en-GB.com_search.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_editors-xtd_weblink.ini',", - "'/administrator/language/en-GB/en-GB.plg_editors-xtd_weblink.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_fields_repeatable.ini',", - "'/administrator/language/en-GB/en-GB.plg_fields_repeatable.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_quickicon_eos310.ini',", - "'/administrator/language/en-GB/en-GB.plg_quickicon_eos310.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_categories.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_categories.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_contacts.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_contacts.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_content.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_content.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_newsfeeds.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_newsfeeds.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_tags.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_tags.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_weblinks.ini',", - "'/administrator/language/en-GB/en-GB.plg_search_weblinks.sys.ini',", - "'/administrator/language/en-GB/en-GB.plg_system_weblinks.ini',", - "'/administrator/language/en-GB/en-GB.plg_system_weblinks.sys.ini',", - "'/administrator/language/en-GB/plg_captcha_recaptcha.ini',", - "'/administrator/language/en-GB/plg_captcha_recaptcha.sys.ini',", - "'/administrator/language/en-GB/plg_captcha_recaptcha_invisible.ini',", - "'/administrator/language/en-GB/plg_captcha_recaptcha_invisible.sys.ini',", - "'/administrator/language/en-GB/plg_system_compat.ini',", - "'/administrator/language/en-GB/plg_system_compat.sys.ini',", - "'/administrator/language/en-GB/plg_system_logrotation.ini',", - "'/administrator/language/en-GB/plg_system_logrotation.sys.ini',", - "'/administrator/language/en-GB/plg_system_sessiongc.ini',", - "'/administrator/language/en-GB/plg_system_sessiongc.sys.ini',", - "'/administrator/language/en-GB/plg_system_updatenotification.ini',", - "'/administrator/language/en-GB/plg_system_updatenotification.sys.ini',", - "'/administrator/language/en-GB/plg_task_demotasks.ini',", - "'/administrator/language/en-GB/plg_task_demotasks.sys.ini',", - "'/language/en-GB/en-GB.com_search.ini',", - "'/language/en-GB/en-GB.mod_search.ini',", - "'/language/en-GB/en-GB.mod_search.sys.ini',", + // Example: "'/administrator/language/en-GB/en-GB.com_search.ini',", + "'/administrator/language/en-GB/plg_behaviour_compat.ini',", + "'/administrator/language/en-GB/plg_behaviour_compat.sys.ini',", ]; // Specific folders that we want to keep on upgrade $foldersToKeep = [ - "'/bin',", + // Example: "'/bin',", ]; // Remove folders from the results which we want to keep on upgrade diff --git a/build/eslint-tests.mjs b/build/eslint-tests.mjs index 9a022681c132a..326f02027135e 100644 --- a/build/eslint-tests.mjs +++ b/build/eslint-tests.mjs @@ -1,12 +1,20 @@ import { defineConfig } from 'eslint/config'; +import cypressPlugin from 'eslint-plugin-cypress'; +import stylistic from '@stylistic/eslint-plugin'; export default defineConfig([ + stylistic.configs.customize({ + arrowParens: true, + braceStyle: '1tbs', + quoteProps: 'as-needed', + quotes: 'single', + semi: true, + }), + cypressPlugin.configs.recommended, { - files: [ - 'tests/**/*.js', - 'tests/**/*.mjs', - 'tests/**/*.es6', - 'tests/**/*.vue', - ], + rules: { + '@stylistic/quotes': ['error', 'single', { avoidEscape: true }], + 'cypress/unsafe-to-chain-command': 'off', + }, }, ]); diff --git a/build/eslint.config.mjs b/build/eslint.config.mjs index 94662bece8587..a948ebc6c23eb 100644 --- a/build/eslint.config.mjs +++ b/build/eslint.config.mjs @@ -1,14 +1,25 @@ import { defineConfig } from 'eslint/config'; +import stylistic from '@stylistic/eslint-plugin'; import vue from 'eslint-plugin-vue'; export default defineConfig([ + stylistic.configs.customize({ + arrowParens: true, + braceStyle: '1tbs', + quoteProps: 'as-needed', + quotes: 'single', + semi: true, + }), ...vue.configs['flat/recommended'], { - files: [ - 'build/**/*.js', - 'build/**/*.mjs', - 'build/**/*.es6', - 'build/**/*.vue', + ignores: [ + '**/*.es5.js', ], }, + { + rules: { + '@stylistic/quotes': ['error', 'single', { avoidEscape: true }], + '@stylistic/max-statements-per-line': 'off', + }, + }, ]); diff --git a/build/helpTOC.php b/build/helpTOC.php deleted file mode 100644 index ad8915276a86a..0000000000000 --- a/build/helpTOC.php +++ /dev/null @@ -1,236 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -// We are a valid entry point. -const _JEXEC = 1; - -// Import namespaced classes -use Joomla\CMS\Factory; -use Joomla\CMS\Http\HttpFactory; -use Joomla\CMS\Version; -use Joomla\Console\Application; -use Joomla\Console\Command\AbstractCommand; -use Joomla\Mediawiki\Http; -use Joomla\Mediawiki\Mediawiki; -use Joomla\Registry\Registry; -use Symfony\Component\Console\Input\ArrayInput; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; - -/** - * Define the application's minimum supported PHP version as a constant so it can be referenced within the application. - */ -const JOOMLA_MINIMUM_PHP = '8.1.0'; - -if (!\defined('_JDEFINES')) { - \define('JPATH_BASE', \dirname(__DIR__)); - require_once JPATH_BASE . '/includes/defines.php'; -} - -// Get the framework. -require_once JPATH_BASE . '/includes/framework.php'; - -$command = new class () extends AbstractCommand { - /** - * The default command name - * - * @var string - */ - protected static $defaultName = 'build-help-toc'; - - /** - * Initialise the command. - * - * @return void - */ - protected function configure(): void - { - $this->setDescription('Generates the help system table of contents file'); - } - - /** - * Internal function to execute the command. - * - * @param InputInterface $input The input to inject into the command. - * @param OutputInterface $output The output to inject into the command. - * - * @return integer The command exit code - */ - protected function doExecute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - if (!class_exists(Http::class)) { - $io->error( - 'The `joomla/mediawiki` package is not installed. To use this script, you must run `composer install` to install development' - . ' dependencies not tracked in this repo.' - ); - - return 1; - } - - // Set up HTTP driver for MediaWiki - $http = new Http([], HttpFactory::getAvailableDriver()); - - // Set up options for the Mediawiki class - $options = new Registry(); - $options->set('api.url', 'https://docs.joomla.org'); - - $mediawiki = new Mediawiki($options, $http); - - $io->comment('Fetching data from docs wiki'); - - $cleanMembers = []; - - $io->comment(\sprintf('Loop through docs wiki categories since Joomla Version %d.0 - Takes a while ...', Version::MAJOR_VERSION)); - - // Loop through the Versions since 5.0 to get all HelpTocs - Temporary fix - for ($helpScreenMinor=Version::MINOR_VERSION; $helpScreenMinor >= 0; $helpScreenMinor--) { - - // Get the category members (local hack) - $categoryMembers = $mediawiki->categories->getCategoryMembers( - \sprintf('Category:Help_screen_%s.%s', Version::MAJOR_VERSION, $helpScreenMinor), - null, - 'max' - ); - - $members = []; - - // Loop through the result objects to get every document - foreach ($categoryMembers->query->categorymembers as $catmembers) { - foreach ($catmembers as $member) { - $members[] = (string) $member['title']; - } - } - - /* - * Now we start fancy processing so we can get the language key for the titles - */ - - // Strip the namespace prefix off the titles and replace spaces with underscores - $namespace = \sprintf('Help%d.x:', Version::MAJOR_VERSION); - - foreach ($members as $member) { - $cleanMembers[str_replace([$namespace, ' '], ['', '_'], $member)] = trim(str_replace($namespace, ' ', $member)); - } - } - - // Make sure we only have an array of unique values before continuing - - $cleanMembers = array_unique($cleanMembers); - - // Get the language object - $language = Factory::getLanguage(); - - // Load the admin com_admin language file - $language->load('com_admin', JPATH_ADMINISTRATOR); - - $toc = []; - $missing = []; - - // filter for translated Media-Wiki articles - $translationLanguages = ['/de', '/en', '/fr', '/nl', '/pt-br', '/es', '/pt', '/it']; - - foreach ($cleanMembers as $key => $value) { - $string = strtoupper($key); - - // Validate the key exists - $io->comment(\sprintf('Validating key COM_ADMIN_HELP_%s', $string)); - - if ($language->hasKey('COM_ADMIN_HELP_' . $string)) { - $io->comment(\sprintf('Adding %s', $string)); - - $toc[$key] = $string; - } else { - // We check the string for words in singular/plural form and check again - $io->comment(\sprintf('Inflecting %s', $string)); - - $inflected = ''; - - if (strpos($string, '_CATEGORIES') !== false) { - $inflected = str_replace('_CATEGORIES', '_CATEGORY', $string); - } elseif (strpos($string, '_USERS') !== false) { - $inflected = str_replace('_USERS', '_USER', $string); - } elseif (strpos($string, '_CATEGORY') !== false) { - $inflected = str_replace('_CATEGORY', '_CATEGORIES', $string); - } elseif (strpos($string, '_USER') !== false) { - $inflected = str_replace('_USER', '_USERS', $string); - } - - if ($inflected === '' && !\in_array(substr($value, strrpos($value, '/')), $translationLanguages)) { - $missing[$string] = $value; - } - - // Now try to validate the key - if ($inflected !== '') { - $io->comment(\sprintf('Validating key COM_ADMIN_HELP_%s', $inflected)); - - if ($language->hasKey('COM_ADMIN_HELP_' . $inflected)) { - $io->comment(\sprintf('Adding %s', $inflected)); - - $toc[$key] = $inflected; - } - } - } - } - - $io->comment(\sprintf('Number of strings: %d', \count($toc))); - - // JSON encode the file and write it to JPATH_ADMINISTRATOR/help/en-GB/toc.json - file_put_contents(JPATH_ADMINISTRATOR . '/help/en-GB/toc.json', json_encode($toc)); - - if (\count($missing)) { - - $str_missing = ''; - - foreach ($missing as $string => $value) { - $str_missing .= 'COM_ADMIN_HELP_' . $string . '="' . $value . '"'. PHP_EOL; - } - - // write missing strings to JPATH_BASE/tmp/missing-helptoc.txt - file_put_contents(JPATH_BASE . '/tmp/missing-helptoc.txt', $str_missing); - - $io->caution(\sprintf('Number of media-wiki articles without string: %d', \count($missing))); - - $io->note(\sprintf('Missing strings are saved in: %s and should be revised and added to %s', 'tmp/missing-helptoc.txt', 'administrator/language/en-GB/com_admin.ini')); - - $io->caution('TODO: For a complete TOC, please run this script again after adding the missing language strings!'); - - } - - $io->success('Help Screen TOC written'); - - return 0; - } -}; - -$input = new ArrayInput( - [ - 'command' => $command::getDefaultName(), - ] -); - -$app = new class ($input) extends Application { - /** - * Retrieve the application configuration object. - * - * @return Registry - */ - public function getConfig() - { - return $this->config; - } -}; -$app->addCommand($command); - -// Register the application to the factory -Factory::$application = $app; - -$app->execute(); diff --git a/build/layouts/github.php b/build/layouts/github.php index 46c60ba2784b0..8c4d1f1dd08b9 100644 --- a/build/layouts/github.php +++ b/build/layouts/github.php @@ -1,8 +1,8 @@ $hashes) { if (str_ends_with($packageName, '.zip')) { $table[$type] .= "| [ZIP Archive (.zip)]"; - } else if (str_ends_with($packageName, '.tar.gz')) { + } elseif (str_ends_with($packageName, '.tar.gz')) { $table[$type] .= "| [GNU Zip Archive (.tar.gz)]"; - } else if (str_ends_with($packageName, '.tar.bz2')) { + } elseif (str_ends_with($packageName, '.tar.bz2')) { $table[$type] .= "| [Bzip2 Archive (.tar.zst)]"; - } else if (str_ends_with($packageName, '.tar.zst')) { + } elseif (str_ends_with($packageName, '.tar.zst')) { $table[$type] .= "| [Zstandard Archive (.tar.zst)]"; } else { // Unknown file types @@ -42,7 +42,7 @@ } } -$echo = function($item) use ($table) { +$echo = function ($item) use ($table) { return $table[$item] ?? ''; }; @@ -93,7 +93,7 @@ ### ✒️ Upgrade Packages > [!IMPORTANT] -> Don't update directly from a version lower than 4.4 it is important that you first update to 4.4 and then update to 5.x +> Don't update directly from a version lower than 5.4 it is important that you first update to 5.4 and then update to 6.x | Update from a previous version | SHA-256 Checksums | |--------------------------------|-------------------| diff --git a/build/media_source/com_admin/js/admin-help.es6.js b/build/media_source/com_admin/js/admin-help.es6.js deleted file mode 100644 index dd12ef11a920b..0000000000000 --- a/build/media_source/com_admin/js/admin-help.es6.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @copyright (C) 2021 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -const helpIndex = document.getElementById('help-index'); -if (helpIndex) { - helpIndex.querySelectorAll('a').forEach((element) => element.addEventListener('click', () => window.scroll(0, 0))); -} diff --git a/build/media_source/com_guidedtours/images/5_2/enhancedtourheader.png b/build/media_source/com_guidedtours/images/5_2/enhancedtourheader.png deleted file mode 100644 index 061bdb9602d73..0000000000000 Binary files a/build/media_source/com_guidedtours/images/5_2/enhancedtourheader.png and /dev/null differ diff --git a/build/media_source/com_guidedtours/images/5_2/mailtemplate.png b/build/media_source/com_guidedtours/images/5_2/mailtemplate.png deleted file mode 100644 index 93b6f79bf0748..0000000000000 Binary files a/build/media_source/com_guidedtours/images/5_2/mailtemplate.png and /dev/null differ diff --git a/build/media_source/com_guidedtours/images/5_3/filesdirectory.jpg b/build/media_source/com_guidedtours/images/5_3/filesdirectory.jpg deleted file mode 100644 index b4310f09a468c..0000000000000 Binary files a/build/media_source/com_guidedtours/images/5_3/filesdirectory.jpg and /dev/null differ diff --git a/build/media_source/com_guidedtours/images/5_4/automated-updates.jpg b/build/media_source/com_guidedtours/images/5_4/automated-updates.jpg deleted file mode 100644 index 294e2fa954e42..0000000000000 Binary files a/build/media_source/com_guidedtours/images/5_4/automated-updates.jpg and /dev/null differ diff --git a/build/media_source/com_workflow/joomla.asset.json b/build/media_source/com_workflow/joomla.asset.json deleted file mode 100644 index ed1cbf269248f..0000000000000 --- a/build/media_source/com_workflow/joomla.asset.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json", - "name": "com_workflow", - "version": "4.0.0", - "description": "Joomla CMS", - "license": "GPL-2.0-or-later", - "assets": [ - { - "name": "com_workflow.admin-items-workflow-buttons", - "type": "script", - "uri": "com_workflow/admin-items-workflow-buttons.min.js", - "dependencies": [ - "core" - ], - "attributes": { - "type": "module" - } - } - ] -} diff --git a/build/media_source/legacy/joomla.asset.json b/build/media_source/legacy/joomla.asset.json deleted file mode 100644 index f1849ef812c26..0000000000000 --- a/build/media_source/legacy/joomla.asset.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json", - "name": "joomla", - "version": "4.0.0", - "description": "Joomla CMS", - "license": "GPL-2.0-or-later", - "assets": [ - { - "name": "jquery-noconflict", - "type": "script", - "dependencies": [ - "jquery" - ], - "uri": "legacy/jquery-noconflict.min.js" - } - ] -} diff --git a/build/media_source/legacy/js/ajax-chosen.es5.js b/build/media_source/legacy/js/ajax-chosen.es5.js deleted file mode 100644 index 9790e596793e5..0000000000000 --- a/build/media_source/legacy/js/ajax-chosen.es5.js +++ /dev/null @@ -1,161 +0,0 @@ -/** - * @copyright (C) 2013 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -/** - * ajaxChosen javascript behavior - * - * Used for displaying tags - * - * @package Joomla.JavaScript - * @since 1.5 - * @version 1.0 - */ -(function($) { - return $.fn.ajaxChosen = function(settings, callback, chosenOptions) { - var chosenXhr, defaultOptions, options, select; - if (settings == null) { - settings = {}; - } - if (callback == null) { - callback = {}; - } - if (chosenOptions == null) { - chosenOptions = function() {}; - } - defaultOptions = { - minTermLength: 3, - afterTypeDelay: 500, - jsonTermKey: "term", - keepTypingMsg: Joomla.Text._('JGLOBAL_KEEP_TYPING'), - lookingForMsg: Joomla.Text._('JGLOBAL_LOOKING_FOR') - }; - select = this; - chosenXhr = null; - options = $.extend({}, defaultOptions, $(select).data(), settings); - this.jchosen(chosenOptions ? chosenOptions : {}); - return this.each(function() { - return $(this).next('.chosen-container').find(".search-field > input, .chosen-search > input").bind('keyup', function() { - var field, msg, success, untrimmed_val, val; - untrimmed_val = $(this).val(); - val = $.trim($(this).val()); - msg = val.length < options.minTermLength ? options.keepTypingMsg : options.lookingForMsg + (" '" + val + "'"); - select.next('.chosen-container').find('.no-results').text(msg); - if (val === $(this).data('prevVal')) { - return false; - } - $(this).data('prevVal', val); - if (this.timer) { - clearTimeout(this.timer); - } - if (val.length < options.minTermLength) { - return false; - } - field = $(this); - if (!(options.data != null)) { - options.data = {}; - } - options.data[options.jsonTermKey] = val; - if (options.dataCallback != null) { - options.data = options.dataCallback(options.data); - } - success = options.success; - options.success = function(data) { - var items, nbItems, selected_values; - if (!(data != null)) { - return; - } - selected_values = []; - select.find('option').each(function() { - if (!$(this).is(":selected")) { - return $(this).remove(); - } else { - return selected_values.push($(this).val() + "-" + $(this).text()); - } - }); - select.find('optgroup:empty').each(function() { - return $(this).remove(); - }); - items = callback.apply(null, data); - nbItems = 0; - $.each(items, function(i, element) { - var group, text, value; - nbItems++; - if (element.group) { - group = select.find("optgroup[label='" + element.text + "']"); - if (!group.size()) { - group = $(""); - } - group.attr('label', element.text).appendTo(select); - return $.each(element.items, function(i, element) { - var text, value; - if (typeof element === "string") { - value = i; - text = element; - } else { - value = element.value; - text = element.text; - } - if ($.inArray(value + "-" + text, selected_values) === -1) { - return $("'); - group.append(option); - this.form_field_jq.append(group); - this.form_field.options[this.form_field.options.length - 1].selected = true; - if (!evt.metaKey) { - this.results_hide(); - } - return this.results_build(); - } - - return JoomlaChosen.__super__.result_select.apply(this, arguments); - }; - - JoomlaChosen.prototype.find_custom_group = function () { - var found, group, _i, _len, _ref; - _ref = $('optgroup', this.form_field); - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - group = _ref[_i]; - if (group.getAttribute('label') === this.custom_group_text) { - found = group; - } - } - return found; - }; - - JoomlaChosen.prototype.add_unique_custom_group = function () { - var group; - group = this.find_custom_group(); - if (!group) { - group = $(''); - } - return $(group); - }; - - /** - * We choose to override this function so deliberately don't call super - */ - JoomlaChosen.prototype.container_width = function () { - if (this.options.width != null) { - return this.options.width; - } else { - // Original: return "" + this.form_field.offsetWidth + "px"; - return this.form_field_jq.css("width") || "" + this.form_field.offsetWidth + "px"; - } - }; - - return JoomlaChosen; - - })(Chosen); -})(jQuery, document.Chosen, document.AbstractChosen); diff --git a/build/media_source/legacy/js/jquery-noconflict.es5.js b/build/media_source/legacy/js/jquery-noconflict.es5.js deleted file mode 100644 index bf4ca21eff9cc..0000000000000 --- a/build/media_source/legacy/js/jquery-noconflict.es5.js +++ /dev/null @@ -1 +0,0 @@ -var $ = jQuery.noConflict(); diff --git a/build/media_source/legacy/js/tabs-state.es5.js b/build/media_source/legacy/js/tabs-state.es5.js deleted file mode 100644 index 0ee8bd82123d5..0000000000000 --- a/build/media_source/legacy/js/tabs-state.es5.js +++ /dev/null @@ -1,240 +0,0 @@ -/** - * @copyright (C) 2013 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -/** - * JavaScript behavior to allow selected tab to be remembered after save or page reload - * keeping state in sessionStorage with better handling of multiple tab widgets per page - * and not saving the state if there is no id in the url (like on the CREATE page of content) - */ - -jQuery(function ($) { - /** - * Tiny jQuery extension to allow getting of url params - * @use jQuery.urlParam('param') or $.urlParam('myRegex|anotherRegex') - * If no trailing equals sign in name, add one, allows for general reuse - */ - $.urlParam = function (name) { - if (!new RegExp("=$").exec(name)) { - name = name + '='; - } - var results = new RegExp("[\\?&](" + name + ")([^&#]*)").exec(window.location.href); - return results ? results[1] : null; - }; - - // jQuery extension to get the XPATH of a DOM element - $.getXpath = function (el) { - if (typeof el == "string") { - return document.evaluate(el, document, null, 0, null); - } - if (!el || el.nodeType != 1) { - return ""; - } - if (el.id) { - return "//*[@id='" + el.id + "']"; - } - var a = []; - var sames = a.filter.call(el.parentNode.children, function (x) { - return x.tagName == el.tagName; - }); - var b = []; - return $.getXpath(el.parentNode) + "/" + el.tagName.toLowerCase() + (sames.length > 1 ? "[" + (b.indexOf.call(sames, el) + 1) + "]" : ""); - }; - - // jQuery extension to get the DOM element from an XPATH - $.findXpath = function (exp, ctxt) { - var item; - var coll = []; - var result = document.evaluate(exp, ctxt || document, null, 5, null); - - while (item = result.iterateNext()) { - coll.push(item); - } - - return $(coll); - }; - - var loadTabs = function () { - - /** - * Remove an item from an array - */ - function remove_item(activeTabsHrefs, tabCollection) { - for (var i = 0; i < activeTabsHrefs.length; i++) { - if (activeTabsHrefs[i].indexOf(tabCollection) > -1) { - activeTabsHrefs.splice(i, 1); - } - } - - return activeTabsHrefs; - } - - /** - * Generate the sessionStorage key we will use - * This is the URL minus some cleanup - */ - function getStorageKey() { - return window.location.href.toString().split(window.location.host)[1].replace(/&return=[a-zA-Z0-9%]+/, "").split('#')[0]; - } - - /** - * Save this tab to the storage in the form of a pseudo keyed array - */ - function saveActiveTab(event) { - - if (!window.sessionStorage) { - return; - } - // Get a new storage key, normally the full url we are on with some cleanup - var storageKey = getStorageKey(); - - // get this tabs own href - var href = $(event.target).attr("href"); - - // find the collection of tabs this tab belongs to, and calculate the unique xpath to it - var tabCollection = $.getXpath($(event.target).closest(".nav-tabs").first().get(0)); - - // error handling - if (!tabCollection || typeof href == "undefined") { - return; - } - - // Create a dummy keyed array as js doesnt allow keyed arrays - var storageValue = tabCollection + "|" + href; - - // Get the current array from the storage - var activeTabsHrefs = JSON.parse(sessionStorage.getItem(storageKey)); - - // If none start a new array - if (!activeTabsHrefs) { - var activeTabsHrefs = []; - } else { - // Avoid Duplicates in the storage - remove_item(activeTabsHrefs, tabCollection); - } - - // Save clicked tab, with relationship to tabCollection to the array - activeTabsHrefs.push(storageValue); - - // Store the selected tabs as an array in sessionStorage - sessionStorage.setItem(storageKey, JSON.stringify(activeTabsHrefs)); - } - - // Array with active tabs hrefs - var activeTabsHrefs = JSON.parse(sessionStorage.getItem(getStorageKey())); - - // jQuery object with all tabs links - var alltabs = $("a[data-bs-toggle='tab']"); - - // When a tab is clicked, save its state! - alltabs.on("click", function (e) { - saveActiveTab(e); - }); - - // Clean default tabs - alltabs.parent(".active").removeClass("active"); - - // If we cannot find a tab storage for this url, see if we are coming from a save of a new item - if (!activeTabsHrefs) { - var unSavedStateUrl = getStorageKey().replace(/\&id=[0-9]*|[a-z]\&{1}_id=[0-9]*/, ''); - activeTabsHrefs = JSON.parse(sessionStorage.getItem(unSavedStateUrl)); - sessionStorage.removeItem(unSavedStateUrl); - } - - // we have some tab states to restore, if we see a hash then let that trump the saved state - if (activeTabsHrefs !== null && !window.location.hash) { - - // When moving from tab area to a different view - $.each(activeTabsHrefs, function (index, tabFakexPath) { - - // Click the tab - var parts = tabFakexPath.split("|"); - $.findXpath(parts[0]).find("a[data-bs-toggle='tab'][href='" + parts[1] + "']").get(0).click(); - - }); - - } else { // clean slate start - - // a list of tabs to click - var tabsToClick = []; - - // If we are passing a hash then this trumps everything - if (window.location.hash) { - - // for each set of tabs on the page - alltabs.parents("ul").each(function (index, ul) { - - // If no tabs is saved, activate first tab from each tab set and save it - var tabToClick = $(ul).find("a[href='" + window.location.hash + "']"); - - // If we found some|one - if (tabToClick.length) { - - // if we managed to locate its selector directly - if (tabToClick.selector) { - - // highlight tab of the tabs if the hash matches - tabsToClick.push(tabToClick); - } else { - - // highlight first tab of the tabs - tabsToClick.push(tabToClick.first()); - } - - var parentPane = tabToClick.closest('.tab-pane'); - - // bubble up for nested tabs (like permissions tabs in the permissions pane) - if (parentPane) { - var id = parentPane.attr('id'); - if (id) { - var parentTabToClick = $(parentPane).find("a[href='#" + id + "']"); - if (parentTabToClick) { - tabsToClick.push(parentTabToClick); - } - } - } - } - - // cleanup for another loop - parentTabToClick = null; - tabToClick = null; - parentPane = null; - id = null; - }); - - // run in the right order bubbling up - tabsToClick.reverse(); - - // for all queued tabs - for (var i = 0; i < tabsToClick.length; i++) { - - // click the tabs, thus storing them - jQuery(tabsToClick[i].selector).click(); - } - - // Remove the #hash in the url - with support for older browsers with no flicker - var scrollV, scrollH, loc = window.location; - if ("pushState" in history) - history.pushState("", document.title, loc.pathname + loc.search); - else { - // Prevent scrolling by storing the page's current scroll offset - scrollV = document.body.scrollTop; - scrollH = document.body.scrollLeft; - loc.hash = ""; - // Restore the scroll offset, should be flicker free - document.body.scrollTop = scrollV; - document.body.scrollLeft = scrollH; - } - - } else { - alltabs.parents("ul").each(function (index, ul) { - // If no tabs is saved, activate first tab from each tab set and save it - $(ul).find("a").first().click(); - }); - } - } - }; - - setTimeout(loadTabs, 100); -}); diff --git a/build/media_source/mod_menu/js/menu.es6.js b/build/media_source/mod_menu/js/menu.es6.js deleted file mode 100644 index eca867aed5711..0000000000000 --- a/build/media_source/mod_menu/js/menu.es6.js +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @copyright (C) 2019 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -(() => { - 'use strict'; - - function topLevelMouseOver(el, settings) { - const ulChild = el.querySelector('ul'); - if (ulChild) { - ulChild.setAttribute('aria-hidden', 'false'); - ulChild.classList.add(settings.menuHoverClass); - } - } - - function topLevelMouseOut(el, settings) { - const ulChild = el.querySelector('ul'); - if (ulChild) { - ulChild.setAttribute('aria-hidden', 'true'); - ulChild.classList.remove(settings.menuHoverClass); - } - } - - function setupNavigation(nav) { - const settings = { - menuHoverClass: 'show-menu', - dir: 'ltr', - }; - - // Set tabIndex to -1 so that top_level_childs can't receive focus until menu is open - nav.querySelectorAll(':scope > li').forEach((topLevelEl) => { - const linkEl = topLevelEl.querySelector('a'); - if (linkEl) { - linkEl.tabIndex = '0'; - linkEl.addEventListener('mouseover', topLevelMouseOver(topLevelEl, settings)); - linkEl.addEventListener('mouseout', topLevelMouseOut(topLevelEl, settings)); - } - const spanEl = topLevelEl.querySelector('span'); - if (spanEl) { - if (spanEl.parentNode.nodeName !== 'A') { - spanEl.tabIndex = '0'; - } - spanEl.addEventListener('mouseover', topLevelMouseOver(topLevelEl, settings)); - spanEl.addEventListener('mouseout', topLevelMouseOut(topLevelEl, settings)); - } - - topLevelEl.addEventListener('mouseover', ({ currentTarget }) => { - const ulChild = currentTarget.querySelector('ul'); - if (ulChild) { - ulChild.setAttribute('aria-hidden', 'false'); - ulChild.classList.add(settings.menuHoverClass); - } - }); - - topLevelEl.addEventListener('mouseout', ({ currentTarget }) => { - const ulChild = currentTarget.querySelector('ul'); - if (ulChild) { - ulChild.setAttribute('aria-hidden', 'true'); - ulChild.classList.remove(settings.menuHoverClass); - } - }); - - topLevelEl.addEventListener('focus', ({ currentTarget }) => { - const ulChild = currentTarget.querySelector('ul'); - if (ulChild) { - ulChild.setAttribute('aria-hidden', 'true'); - ulChild.classList.add(settings.menuHoverClass); - } - }); - - topLevelEl.addEventListener('blur', ({ currentTarget }) => { - const ulChild = currentTarget.querySelector('ul'); - if (ulChild) { - ulChild.setAttribute('aria-hidden', 'false'); - ulChild.classList.remove(settings.menuHoverClass); - } - }); - - topLevelEl.addEventListener('keydown', (event) => { - const keyName = event.key; - const curEl = event.target; - const curLiEl = curEl.parentElement; - const curUlEl = curLiEl.parentElement; - let prevLiEl = curLiEl.previousElementSibling; - let nextLiEl = curLiEl.nextElementSibling; - if (!prevLiEl) { - prevLiEl = curUlEl.children[curUlEl.children.length - 1]; - } - if (!nextLiEl) { - [nextLiEl] = curUlEl.children; - } - switch (keyName) { - case 'ArrowLeft': - event.preventDefault(); - if (settings.dir === 'rtl') { - nextLiEl.children[0].focus(); - } else { - prevLiEl.children[0].focus(); - } - break; - case 'ArrowRight': - event.preventDefault(); - if (settings.dir === 'rtl') { - prevLiEl.children[0].focus(); - } else { - nextLiEl.children[0].focus(); - } - break; - case 'ArrowUp': - { - event.preventDefault(); - const parent = curLiEl.parentElement.parentElement; - if (parent.nodeName === 'LI') { - parent.children[0].focus(); - } else { - prevLiEl.children[0].focus(); - } - break; - } - case 'ArrowDown': - event.preventDefault(); - if (curLiEl.classList.contains('parent')) { - const child = curLiEl.querySelector('ul'); - if (child != null) { - const childLi = child.querySelector('li'); - childLi.children[0].focus(); - } else { - nextLiEl.children[0].focus(); - } - } else { - nextLiEl.children[0].focus(); - } - break; - default: - break; - } - }); - }); - } - - document.addEventListener('DOMContentLoaded', () => { - document.querySelectorAll('.nav').forEach((nav) => setupNavigation(nav)); - }); -})(); diff --git a/build/media_source/plg_behaviour_compat/es5.asset.json b/build/media_source/plg_behaviour_compat/es5.asset.json deleted file mode 100644 index a2d72ce8e848b..0000000000000 --- a/build/media_source/plg_behaviour_compat/es5.asset.json +++ /dev/null @@ -1,1092 +0,0 @@ -{ - "$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json", - "name": "plg_behaviour_compat", - "version": "5.0.0", - "description": "Joomla CMS ES5 b/c entries, the entries are only placeholders without functionality.", - "license": "GPL-2.0-or-later", - "assets": [ - { - "name": "bootstrap.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_actionlogs.admin-actionlogs.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_admin.admin-help.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_associations.admin-associations-default.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_associations.admin-associations-modal.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_associations.associations-edit.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_banners.admin-banner-edit.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_cache.admin-cache.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_categories.shared-categories-accordion.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_config.config.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_config.modules.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_config.templates.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_config.filters.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_contact.admin-contacts-modal.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_contact.contacts-list.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_content.admin-article-pagebreak.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_content.admin-article-readmore.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_content.admin-articles-batch.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_content.admin-articles-stage.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_content.admin-articles-modal.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_content.form-edit.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_content.articles-list.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_content.articles-status.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_contenthistory.admin-compare-compare.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core", - "diff" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_contenthistory.admin-history-modal.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_contenthistory.admin-history-versions.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_cpanel.admin-addmodule.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_cpanel.admin-cpanel.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_cpanel.admin-system-loader.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_fields.admin-field-changecontext.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_fields.admin-field-edit.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_fields.admin-field-typehaschanged.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_fields.admin-fields-batch.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_fields.admin-fields-modal.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_finder.debug.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_finder.filters.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_finder.finder.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_finder.finder-edit.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_finder.indexer.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_finder.maps.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_installer.changelog.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_installer.installer.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_joomlaupdate.admin-update-es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core", - "bootstrap.modal" - ], - "attributes": { - "defer": true, - "nomodule": true - } - }, - { - "name": "com_joomlaupdate.default-es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "defer": true, - "nomodule": true - } - }, - { - "name": "com_languages.admin-language-edit-change-flag.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_languages.admin-override-edit-refresh-searchstring.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_languages.overrider.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_mails.admin-email-template-edit.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_media.edit-images.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_media.mediamanager.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core", - "messages" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_menus.admin-item-edit.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_menus.admin-item-edit-container.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_menus.admin-item-edit-modules.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_menus.admin-item-modal.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_menus.admin-items-modal.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_menus.admin-menus.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_menus.batch-body.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_modules.admin-module-edit.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_modules.admin-module-edit-assignment.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_modules.admin-module-search.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_modules.admin-modules-modal.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_modules.admin-select-modal.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_templates.admin-templates.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "showon.es5", - "type": "script", - "deprecated": true, - "dependencies": [ - "core" - ], - "uri": "", - "attributes": { - "defer": true, - "nomodule": true - } - }, - { - "name": "com_scheduler.test-task.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_scheduler.admin-view-select-task-search.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_scheduler.scheduler-config.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true - } - }, - { - "name": "com_tags.tag-default.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_tags.tag-list.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_tags.tags-default.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_templates.admin-template-toggle-assignment.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_templates.admin-template-toggle-switch.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_users.admin-users-groups.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_users.two-factor-focus.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_users.two-factor-list.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "com_workflow.admin-items-workflow-buttons.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "plg_multifactorauth_totp.setup.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "qrcode", - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "plg_multifactorauth_webauthn.webauthn.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "plg_system_guidedtours.guidedtours.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "plg_system_jooa11y.jooa11y-es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "defer": true, - "nomodule": true - } - }, - { - "name": "plg_system_schedulerunner.run-schedule.es5", - "type": "script", - "deprecated": true, - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "template.atum-es5", - "description": "The file containing the javascript for this template.", - "deprecated": true, - "type": "script", - "uri": "", - "dependencies": [ - "core" - ], - "attributes": { - "nomodule": true, - "defer": true - } - }, - { - "name": "keepalive.es5", - "type": "script", - "deprecated": true, - "dependencies": [ - "core" - ], - "uri": "", - "attributes": { - "defer": true, - "nomodule": true - } - } - ] -} diff --git a/build/media_source/plg_captcha_recaptcha/js/recaptcha.es6.js b/build/media_source/plg_captcha_recaptcha/js/recaptcha.es6.js deleted file mode 100644 index 9b5b2cd18747f..0000000000000 --- a/build/media_source/plg_captcha_recaptcha/js/recaptcha.es6.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @package Joomla.JavaScript - * @copyright (C) 2018 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -((window, document) => { - 'use strict'; - - window.JoomlainitReCaptcha2 = () => { - const optionKeys = ['sitekey', 'theme', 'size', 'tabindex', 'callback', 'expired-callback', 'error-callback']; - - document.querySelectorAll('.g-recaptcha').forEach((element) => { - let options = {}; - - if (element.dataset) { - options = element.dataset; - } else { - optionKeys.forEach((key) => { - const optionKeyFq = `data-${key}`; - if (element.hasAttribute(optionKeyFq)) { - options[key] = element.getAttribute(optionKeyFq); - } - }); - } - - // Set the widget id of the recaptcha item - element.setAttribute( - 'data-recaptcha-widget-id', - window.grecaptcha.render(element, options), - ); - }); - }; -})(window, document); diff --git a/build/media_source/plg_captcha_recaptcha_invisible/js/recaptcha.es6.js b/build/media_source/plg_captcha_recaptcha_invisible/js/recaptcha.es6.js deleted file mode 100644 index a4b05dbacd047..0000000000000 --- a/build/media_source/plg_captcha_recaptcha_invisible/js/recaptcha.es6.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @package Joomla.JavaScript - * @copyright (C) 2019 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -((window, document) => { - 'use strict'; - - window.JoomlainitReCaptchaInvisible = () => { - const optionKeys = ['sitekey', 'badge', 'size', 'tabindex', 'callback', 'expired-callback', 'error-callback']; - - document.querySelectorAll('.g-recaptcha').forEach((element) => { - let options = {}; - - if (element.dataset) { - options = element.dataset; - } else { - optionKeys.forEach((key) => { - const optionKeyFq = `data-${optionKeys[key]}`; - - if (element.hasAttribute(optionKeyFq)) { - options[optionKeys[key]] = element.getAttribute(optionKeyFq); - } - }); - } - - // Set the widget id of the recaptcha item - element.setAttribute( - 'data-recaptcha-widget-id', - window.grecaptcha.render(element, options), - ); - - // Execute the invisible reCAPTCHA - window.grecaptcha.execute(element.getAttribute('data-recaptcha-widget-id')); - }); - }; -})(window, document); diff --git a/build/media_source/plg_captcha_recaptcha_invisible/scss/recaptcha_invisible.scss b/build/media_source/plg_captcha_recaptcha_invisible/scss/recaptcha_invisible.scss deleted file mode 100644 index c4b2a412e877e..0000000000000 --- a/build/media_source/plg_captcha_recaptcha_invisible/scss/recaptcha_invisible.scss +++ /dev/null @@ -1,3 +0,0 @@ -.grecaptcha-badge { - z-index: 999999; -} diff --git a/build/media_source/system/js/fields/joomla-field-simple-color.w-c.es6.js b/build/media_source/system/js/fields/joomla-field-simple-color.w-c.es6.js deleted file mode 100644 index 6ce1e67346ed6..0000000000000 --- a/build/media_source/system/js/fields/joomla-field-simple-color.w-c.es6.js +++ /dev/null @@ -1,449 +0,0 @@ -/** - * Based on: - * Very simple jQuery Color Picker - * Copyright (C) 2012 Tanguy Krotoff - * Licensed under the MIT license - * - * ADAPTED BY: Dimitris Grammatikogiannis - * - * MIT License - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -((customElements) => { - const KEYCODE = { - TAB: 9, - ESC: 27, - }; - - const colorNames = { - aliceblue: '#f0f8ff', - antiquewhite: '#faebd7', - aqua: '#00ffff', - aquamarine: '#7fffd4', - azure: '#f0ffff', - beige: '#f5f5dc', - bisque: '#ffe4c4', - black: '#000000', - blanchedalmond: '#ffebcd', - blue: '#0000ff', - blueviolet: '#8a2be2', - brown: '#a52a2a', - burlywood: '#deb887', - cadetblue: '#5f9ea0', - chartreuse: '#7fff00', - chocolate: '#d2691e', - coral: '#ff7f50', - cornflowerblue: '#6495ed', - cornsilk: '#fff8dc', - crimson: '#dc143c', - cyan: '#00ffff', - darkblue: '#00008b', - darkcyan: '#008b8b', - darkgoldenrod: '#b8860b', - darkgray: '#a9a9a9', - darkgreen: '#006400', - darkgrey: '#a9a9a9', - darkkhaki: '#bdb76b', - darkmagenta: '#8b008b', - darkolivegreen: '#556b2f', - darkorange: '#ff8c00', - darkorchid: '#9932cc', - darkred: '#8b0000', - darksalmon: '#e9967a', - darkseagreen: '#8fbc8f', - darkslateblue: '#483d8b', - darkslategray: '#2f4f4f', - darkslategrey: '#2f4f4f', - darkturquoise: '#00ced1', - darkviolet: '#9400d3', - deeppink: '#ff1493', - deepskyblue: '#00bfff', - dimgray: '#696969', - dimgrey: '#696969', - dodgerblue: '#1e90ff', - firebrick: '#b22222', - floralwhite: '#fffaf0', - forestgreen: '#228b22', - fuchsia: '#ff00ff', - gainsboro: '#dcdcdc', - ghostwhite: '#f8f8ff', - gold: '#ffd700', - goldenrod: '#daa520', - gray: '#808080', - green: '#008000', - greenyellow: '#adff2f', - grey: '#808080', - honeydew: '#f0fff0', - hotpink: '#ff69b4', - indianred: '#cd5c5c', - indigo: '#4b0082', - ivory: '#fffff0', - khaki: '#f0e68c', - lavender: '#e6e6fa', - lavenderblush: '#fff0f5', - lawngreen: '#7cfc00', - lemonchiffon: '#fffacd', - lightblue: '#add8e6', - lightcoral: '#f08080', - lightcyan: '#e0ffff', - lightgoldenrodyellow: '#fafad2', - lightgray: '#d3d3d3', - lightgreen: '#90ee90', - lightgrey: '#d3d3d3', - lightpink: '#ffb6c1', - lightsalmon: '#ffa07a', - lightseagreen: '#20b2aa', - lightskyblue: '#87cefa', - lightslategray: '#778899', - lightslategrey: '#778899', - lightsteelblue: '#b0c4de', - lightyellow: '#ffffe0', - lime: '#00ff00', - limegreen: '#32cd32', - linen: '#faf0e6', - magenta: '#ff00ff', - maroon: '#800000', - mediumaquamarine: '#66cdaa', - mediumblue: '#0000cd', - mediumorchid: '#ba55d3', - mediumpurple: '#9370db', - mediumseagreen: '#3cb371', - mediumslateblue: '#7b68ee', - mediumspringgreen: '#00fa9a', - mediumturquoise: '#48d1cc', - mediumvioletred: '#c71585', - midnightblue: '#191970', - mintcream: '#f5fffa', - mistyrose: '#ffe4e1', - moccasin: '#ffe4b5', - navajowhite: '#ffdead', - navy: '#000080', - oldlace: '#fdf5e6', - olive: '#808000', - olivedrab: '#6b8e23', - orange: '#ffa500', - orangered: '#ff4500', - orchid: '#da70d6', - palegoldenrod: '#eee8aa', - palegreen: '#98fb98', - paleturquoise: '#afeeee', - palevioletred: '#db7093', - papayawhip: '#ffefd5', - peachpuff: '#ffdab9', - peru: '#cd853f', - pink: '#ffc0cb', - plum: '#dda0dd', - powderblue: '#b0e0e6', - purple: '#800080', - red: '#ff0000', - rosybrown: '#bc8f8f', - royalblue: '#4169e1', - saddlebrown: '#8b4513', - salmon: '#fa8072', - sandybrown: '#f4a460', - seagreen: '#2e8b57', - seashell: '#fff5ee', - sienna: '#a0522d', - silver: '#c0c0c0', - skyblue: '#87ceeb', - slateblue: '#6a5acd', - slategray: '#708090', - slategrey: '#708090', - snow: '#fffafa', - springgreen: '#00ff7f', - steelblue: '#4682b4', - tan: '#d2b48c', - teal: '#008080', - thistle: '#d8bfd8', - tomato: '#ff6347', - turquoise: '#40e0d0', - violet: '#ee82ee', - wheat: '#f5deb3', - white: '#ffffff', - whitesmoke: '#f5f5f5', - yellow: '#ffff00', - yellowgreen: '#9acd32', - }; - - class JoomlaFieldSimpleColor extends HTMLElement { - constructor() { - super(); - - // Define some variables - this.select = ''; - this.options = []; - this.icon = ''; - this.panel = ''; - this.buttons = []; - this.focusableElements = null; - this.focusableSelectors = [ - 'a[href]', - 'area[href]', - 'input:not([disabled])', - 'select:not([disabled])', - 'textarea:not([disabled])', - 'button:not([disabled])', - 'iframe', - 'object', - 'embed', - '[contenteditable]', - '[tabindex]:not([tabindex^="-"])']; - } - - connectedCallback() { - this.select = this.querySelector('select'); - - if (!this.select) { - throw new Error('Simple color field requires a select element'); - } - - this.options = this.select.querySelectorAll('option'); - - this.select.classList.add('hidden'); - - // Build the pop up - this.options.forEach((option) => { - let color = option.value; - let clss = 'swatch'; - - if (color === 'none') { - clss += ' nocolor'; - color = 'transparent'; - } - if (option.selected) { - clss += ' active'; - } - - const el = document.createElement('button'); - el.setAttribute('class', clss); - el.style.backgroundColor = color; - el.setAttribute('type', 'button'); - const a11yColor = color === 'transparent' ? this.textTransp : this.getColorName(color); - el.innerHTML = Joomla.sanitizeHtml(`${a11yColor}`); - - this.buttons.push(el); - }); - - // Add a close button - const close = document.createElement('button'); - close.setAttribute('class', 'btn-close'); - close.setAttribute('type', 'button'); - close.setAttribute('aria-label', this.textClose); - - this.buttons.push(close); - - let color = this.select.value; - let clss = ''; - - if (color === 'none') { - clss += ' nocolor'; - color = 'transparent'; - } - - this.icon = document.createElement('button'); - - if (clss) { - this.icon.setAttribute('class', clss); - } - - const uniqueId = `simple-color-${Math.random().toString(36).substring(2, 12)}`; - this.icon.setAttribute('type', 'button'); - this.icon.setAttribute('tabindex', '0'); - this.icon.style.backgroundColor = color; - this.icon.innerHTML = Joomla.sanitizeHtml(`${this.textSelect}`); - this.icon.id = uniqueId; - this.select.insertAdjacentElement('beforebegin', this.icon); - this.icon.addEventListener('click', this.show.bind(this)); - - this.panel = document.createElement('div'); - this.panel.classList.add('simplecolors-panel'); - this.panel.setAttribute('aria-labelledby', uniqueId); - this.hide = this.hide.bind(this); - this.colorSelect = this.colorSelect.bind(this); - - this.buttons.forEach((el) => { - if (el.classList.contains('btn-close')) { - el.addEventListener('click', this.hide); - } else { - el.addEventListener('click', this.colorSelect); - } - - this.panel.insertAdjacentElement('beforeend', el); - }); - - this.appendChild(this.panel); - - this.focusableElements = [].slice - .call(this.panel.querySelectorAll(this.focusableSelectors.join())); - - this.keys = this.keys.bind(this); - this.hide = this.hide.bind(this); - this.mousedown = this.mousedown.bind(this); - } - - static get observedAttributes() { - return ['text-select', 'text-color', 'text-close', 'text-transparent']; - } - - get textSelect() { return this.getAttribute('text-select'); } - - get textColor() { return this.getAttribute('text-color'); } - - get textClose() { return this.getAttribute('text-close'); } - - get textTransp() { return this.getAttribute('text-transparent'); } - - // Show the panel - show() { - document.addEventListener('mousedown', this.hide); - this.addEventListener('keydown', this.keys); - this.panel.addEventListener('mousedown', this.mousedown); - this.panel.setAttribute('data-open', ''); - - const focused = this.panel.querySelector('button'); - - if (focused) { - focused.focus(); - } - } - - // Hide panel - hide() { - document.removeEventListener('mousedown', this.hide, false); - this.removeEventListener('keydown', this.keys); - - if (this.panel.hasAttribute('data-open')) { - this.panel.removeAttribute('data-open'); - } - - this.icon.focus(); - } - - colorSelect(e) { - let color = ''; - let bgcolor = ''; - let clss = ''; - - if (e.target.classList.contains('nocolor')) { - color = 'none'; - bgcolor = 'transparent'; - clss = 'nocolor'; - } else { - color = this.rgb2hex(e.target.style.backgroundColor); - bgcolor = color; - } - - // Reset the active class - this.buttons.forEach((el) => { - if (el.classList.contains('active')) { - el.classList.remove('active'); - } - }); - - // Add the active class to the selected button - e.target.classList.add('active'); - - this.icon.classList.remove('nocolor'); - this.icon.setAttribute('class', clss); - this.icon.style.backgroundColor = bgcolor; - - // trigger change event both on the select and on the custom element - this.select.dispatchEvent(new Event('change')); - this.dispatchEvent(new CustomEvent('change', { - detail: { value: color }, - bubbles: true, - })); - - // Hide the panel - this.hide(); - - // Change select value - this.options.forEach((el) => { - if (el.selected) { - el.removeAttribute('selected'); - } - - if (el.value === bgcolor) { - el.setAttribute('selected', ''); - } - }); - } - - keys(e) { - if (e.keyCode === KEYCODE.ESC) { - this.hide(); - } - - if (e.keyCode === KEYCODE.TAB) { - // Get the index of the current active element - const focusedIndex = this.focusableElements.indexOf(document.activeElement); - - // If first element is focused and shiftkey is in use, focus last item within modal - if (e.shiftKey && (focusedIndex === 0 || focusedIndex === -1)) { - this.focusableElements[this.focusableElements.length - 1].focus(); - e.preventDefault(); - } - // If last element is focused and shiftkey is not in use, focus first item within modal - if (!e.shiftKey && focusedIndex === this.focusableElements.length - 1) { - this.focusableElements[0].focus(); - e.preventDefault(); - } - } - } - - // Prevents the mousedown event from "eating" the click event. - mousedown(e) { - e.stopPropagation(); - e.preventDefault(); - } - - getColorName(value) { - // Expand any short code - let newValue = value; - if (value.length === 4) { - const tmpValue = value.split(''); - newValue = tmpValue[0] + tmpValue[1] + tmpValue[1] + tmpValue[2] - + tmpValue[2] + tmpValue[3] + tmpValue[3]; - } - - for (const color in colorNames) { - if (colorNames.hasOwnProperty(color) && newValue.toLowerCase() === colorNames[color]) { - return color; - } - } - - return `${this.textColor} ${value.replace('#', '').split('').join(', ')}`; - } - - /** - * Converts a RGB color to its hexadecimal value. - * See http://stackoverflow.com/questions/1740700/get-hex-value-rather-than-rgb-value-using-$ - */ - rgb2hex(rgb) { - const hex = (x) => (`0${parseInt(x, 10).toString(16)}`).slice(-2); - const matches = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); - - return `#${hex(matches[1])}${hex(matches[2])}${hex(matches[3])}`; - } - } - - customElements.define('joomla-field-simple-color', JoomlaFieldSimpleColor); -})(customElements); diff --git a/build/media_source/system/js/fields/tag.es5.js b/build/media_source/system/js/fields/tag.es5.js deleted file mode 100644 index 0cc2af0634be0..0000000000000 --- a/build/media_source/system/js/fields/tag.es5.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @copyright (C) 2016 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -/** - * Field user - */ -jQuery(document).ready(function ($) { - - if (Joomla.getOptions('field-tag-custom')) { - - var options = Joomla.getOptions('field-tag-custom'), - customTagPrefix = '#new#'; - - // Method to add tags pressing enter - $(options.selector + '_chosen input').keyup(function(event) { - - var tagOption; - - // Tag is greater than the minimum required chars and enter pressed - if (this.value && this.value.length >= options.minTermLength && (event.which === 13 || event.which === 188)) { - - // Search a highlighted result - var highlighted = $(options.selector + '_chosen').find('li.active-result.highlighted').first(); - - // Add the highlighted option - if (event.which === 13 && highlighted.text() !== '') - { - // Extra check. If we have added a custom tag with this text remove it - var customOptionValue = customTagPrefix + highlighted.text(); - $(options.selector + ' option').filter(function () { return $(this).val() == customOptionValue; }).remove(); - - // Select the highlighted result - tagOption = $(options.selector + ' option').filter(function () { return $(this).html() == highlighted.text(); }); - tagOption.attr('selected', 'selected'); - } - // Add the custom tag option - else - { - var customTag = this.value; - - // Extra check. Search if the custom tag already exists (typed faster than AJAX ready) - tagOption = $(options.selector + ' option').filter(function () { return $(this).html() == customTag; }); - if (tagOption.text() !== '') - { - tagOption.attr('selected', 'selected'); - } - else - { - var option = $('
+ +
diff --git a/components/com_content/helpers/icon.php b/components/com_content/helpers/icon.php index 9906ef941646a..fef4d332e90a8 100644 --- a/components/com_content/helpers/icon.php +++ b/components/com_content/helpers/icon.php @@ -22,7 +22,7 @@ * * @since 1.5 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the class \Joomla\Component\Content\Administrator\Service\HTML\Icon instead */ abstract class JHtmlIcon @@ -37,7 +37,7 @@ abstract class JHtmlIcon * * @return string The HTML markup for the create item link * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Content\Administrator\Service\HTML\Icon::create instead * Example: * use Joomla\Component\Content\Administrator\Service\HTML\Icon; @@ -64,7 +64,7 @@ public static function create($category, $params, $attribs = [], $legacy = false * * @since 1.6 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Content\Administrator\Service\HTML\Icon::edit instead * Example: * use Joomla\Component\Content\Administrator\Service\HTML\Icon; @@ -86,7 +86,7 @@ public static function edit($article, $params, $attribs = [], $legacy = false) * * @return string The HTML markup for the popup link * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * No longer used, will be removed without replacement */ public static function print_popup($article, $params, $attribs = [], $legacy = false) @@ -104,7 +104,7 @@ public static function print_popup($article, $params, $attribs = [], $legacy = f * * @return string The HTML markup for the popup link * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Content\Administrator\Service\HTML\Icon::print_screen instead * Example: * use Joomla\Component\Content\Administrator\Service\HTML\Icon; @@ -121,7 +121,7 @@ public static function print_screen($article, $params, $attribs = [], $legacy = * * @return \Joomla\Component\Content\Administrator\Service\HTML\Icon * - * @deprecated 4.3 will be removed in 6.0 without replacement + * @deprecated 4.3 will be removed in 7.0 without replacement */ private static function getIcon() { diff --git a/components/com_content/src/Controller/DisplayController.php b/components/com_content/src/Controller/DisplayController.php index ebe4421cd602a..ddc70f104c62c 100644 --- a/components/com_content/src/Controller/DisplayController.php +++ b/components/com_content/src/Controller/DisplayController.php @@ -15,6 +15,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; +use Joomla\Input\Input; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -28,12 +29,12 @@ class DisplayController extends \Joomla\CMS\MVC\Controller\BaseController { /** - * @param array $config An optional associative array of configuration settings. - * Recognized key values include 'name', 'default_task', 'model_path', and - * 'view_path' (this list is not meant to be comprehensive). - * @param ?MVCFactoryInterface $factory The factory. - * @param ?CMSApplication $app The Application for the dispatcher - * @param ?\Joomla\CMS\Input\Input $input The Input object for the request + * @param array $config An optional associative array of configuration settings. + * Recognized key values include 'name', 'default_task', 'model_path', and + * 'view_path' (this list is not meant to be comprehensive). + * @param ?MVCFactoryInterface $factory The factory. + * @param ?CMSApplication $app The Application for the dispatcher + * @param ?Input $input The Input object for the request * * @since 3.0.1 */ diff --git a/components/com_content/src/Helper/AssociationHelper.php b/components/com_content/src/Helper/AssociationHelper.php index 04c3955044fc3..732b0f84b461e 100644 --- a/components/com_content/src/Helper/AssociationHelper.php +++ b/components/com_content/src/Helper/AssociationHelper.php @@ -30,11 +30,11 @@ abstract class AssociationHelper extends CategoryAssociationHelper /** * Method to get the associations for a given item * - * @param integer $id Id of the item - * @param string $view Name of the view - * @param string $layout View layout + * @param int|int[] $id ID of the item or array of IDs. + * @param string $view Name of the view + * @param string $layout View layout * - * @return array Array of associations for the item + * @return array Array of associations for the item, optionally grouped by ID * * @since 3.0 */ @@ -79,7 +79,7 @@ public static function getAssociations($id = 0, $view = null, $layout = null) 'com_content', '#__content', 'com_content.item', - $id, + (array) $id, 'id', 'alias', 'catid', @@ -88,11 +88,13 @@ public static function getAssociations($id = 0, $view = null, $layout = null) $return = []; - foreach ($associations as $tag => $item) { - $return[$tag] = RouteHelper::getArticleRoute($item->id, (int) $item->catid, $item->language, $layout); + foreach ($associations as $itemId => $itemAssociations) { + foreach ($itemAssociations as $tag => $item) { + $return[$itemId][$tag] = RouteHelper::getArticleRoute($item->id, (int) $item->catid, $item->language, $layout); + } } - return $return; + return \is_array($id) ? $return : ($return[$id] ?? []); } } @@ -106,9 +108,9 @@ public static function getAssociations($id = 0, $view = null, $layout = null) /** * Method to display in frontend the associations for a given article * - * @param integer $id Id of the article + * @param int|int[] $id ID of the article or array of IDs * - * @return array An array containing the association URL and the related language object + * @return array An array containing the association URL and the related language object, optionally grouped by article ID * * @since 3.7.0 */ @@ -116,35 +118,39 @@ public static function displayAssociations($id) { $return = []; - if ($associations = self::getAssociations($id, 'article')) { - $levels = Factory::getUser()->getAuthorisedViewLevels(); - $languages = LanguageHelper::getLanguages(); - - foreach ($languages as $language) { - // Do not display language when no association - if (empty($associations[$language->lang_code])) { - continue; - } - - // Do not display language without frontend UI - if (!\array_key_exists($language->lang_code, LanguageHelper::getInstalledLanguages(0))) { - continue; - } - - // Do not display language without specific home menu - if (!\array_key_exists($language->lang_code, Multilanguage::getSiteHomePages())) { - continue; - } - - // Do not display language without authorized access level - if (isset($language->access) && $language->access && !\in_array($language->access, $levels)) { - continue; + if ($associations = self::getAssociations((array) $id, 'article')) { + $levels = Factory::getUser()->getAuthorisedViewLevels(); + $languages = LanguageHelper::getLanguages(); + $installedLanguages = LanguageHelper::getInstalledLanguages(0); + $siteHomePages = Multilanguage::getSiteHomePages(); + + foreach ($associations as $itemId => $itemAssociations) { + foreach ($languages as $language) { + // Do not display language when no association + if (empty($itemAssociations[$language->lang_code])) { + continue; + } + + // Do not display language without frontend UI + if (!\array_key_exists($language->lang_code, $installedLanguages)) { + continue; + } + + // Do not display language without specific home menu + if (!\array_key_exists($language->lang_code, $siteHomePages)) { + continue; + } + + // Do not display language without authorized access level + if (isset($language->access) && $language->access && !\in_array($language->access, $levels)) { + continue; + } + + $return[$itemId][$language->lang_code] = ['item' => $itemAssociations[$language->lang_code], 'language' => $language]; } - - $return[$language->lang_code] = ['item' => $associations[$language->lang_code], 'language' => $language]; } } - return $return; + return \is_array($id) ? $return : ($return[$id] ?? []); } } diff --git a/components/com_content/src/Helper/QueryHelper.php b/components/com_content/src/Helper/QueryHelper.php index decf875b238e2..9366461af33a0 100644 --- a/components/com_content/src/Helper/QueryHelper.php +++ b/components/com_content/src/Helper/QueryHelper.php @@ -10,7 +10,6 @@ namespace Joomla\Component\Content\Site\Helper; -use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Database\DatabaseInterface; @@ -117,7 +116,7 @@ public static function orderbySecondary($orderby, $orderDate = 'created', ?Datab break; case 'random': - $orderby = $db->getQuery(true)->rand(); + $orderby = $db->createQuery()->rand(); break; case 'vote': @@ -193,36 +192,4 @@ public static function getQueryDate($orderDate, ?DatabaseInterface $db = null) return $queryDate; } - - /** - * Get join information for the voting query. - * - * @param \Joomla\Registry\Registry $params An options object for the article. - * - * @return array A named array with "select" and "join" keys. - * - * @since 1.5 - * - * @deprecated 4.3 will be removed in 6.0 - * Will be removed without replacement - */ - public static function buildVotingQuery($params = null) - { - if (!$params) { - $params = ComponentHelper::getParams('com_content'); - } - - $voting = $params->get('show_vote'); - - if ($voting) { - // Calculate voting count - $select = ' , ROUND(v.rating_sum / v.rating_count) AS rating, v.rating_count'; - $join = ' LEFT JOIN #__content_rating AS v ON a.id = v.content_id'; - } else { - $select = ''; - $join = ''; - } - - return ['select' => $select, 'join' => $join]; - } } diff --git a/components/com_content/src/Helper/RouteHelper.php b/components/com_content/src/Helper/RouteHelper.php index fc86fcf69b4e4..7276aa16ae31d 100644 --- a/components/com_content/src/Helper/RouteHelper.php +++ b/components/com_content/src/Helper/RouteHelper.php @@ -60,14 +60,14 @@ public static function getArticleRoute($id, $catid = 0, $language = null, $layou * Get the category route. * * @param integer $catid The category ID. - * @param integer $language The language code. + * @param string $language The language code. * @param string $layout The layout value. * * @return string The article route. * * @since 1.5 */ - public static function getCategoryRoute($catid, $language = 0, $layout = null) + public static function getCategoryRoute($catid, $language = null, $layout = null) { if ($catid instanceof CategoryNode) { $id = $catid->id; @@ -81,7 +81,7 @@ public static function getCategoryRoute($catid, $language = 0, $layout = null) $link = 'index.php?option=com_content&view=category&id=' . $id; - if ($language && $language !== '*' && Multilanguage::isEnabled()) { + if (!empty($language) && $language !== '*' && Multilanguage::isEnabled()) { $link .= '&lang=' . $language; } diff --git a/components/com_content/src/Model/ArchiveModel.php b/components/com_content/src/Model/ArchiveModel.php index d08cd94041293..cc4849ed6379e 100644 --- a/components/com_content/src/Model/ArchiveModel.php +++ b/components/com_content/src/Model/ArchiveModel.php @@ -157,7 +157,7 @@ public function getYears() { $db = $this->getDatabase(); $nowDate = Factory::getDate()->toSql(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $queryDate = QueryHelper::getQueryDate($this->state->get('params')->get('order_date'), $db); $years = $query->year($queryDate); $yearSort = $this->state->get('params')->get('year_sort_order', 'ASC'); diff --git a/components/com_content/src/Model/ArticleModel.php b/components/com_content/src/Model/ArticleModel.php index f451814aa4f09..1c91f19f43229 100644 --- a/components/com_content/src/Model/ArticleModel.php +++ b/components/com_content/src/Model/ArticleModel.php @@ -15,8 +15,9 @@ use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Model\ItemModel; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Content; use Joomla\Component\Content\Administrator\Extension\ContentComponent; +use Joomla\Component\Content\Administrator\Service\PreviewTokenService; use Joomla\Database\ParameterType; use Joomla\Registry\Registry; use Joomla\Utilities\IpHelper; @@ -68,6 +69,17 @@ protected function populateState() // If $pk is set then authorise on complete asset, else on component only $asset = empty($pk) ? 'com_content' : 'com_content.article.' . $pk; + // Validate preview token if present, before any permission checks. + $token = $app->getInput()->getString('preview_token', ''); + + if ($token !== '' && $pk > 0) { + $previewTokenHelper = new PreviewTokenService($app->get('secret')); + + if ($previewTokenHelper->validateToken($token, $pk)) { + $this->setState('article.preview', true); + } + } + if ((!$user->authorise('core.edit.state', $asset)) && (!$user->authorise('core.edit', $asset))) { $this->setState('filter.published', ContentComponent::CONDITION_PUBLISHED); $this->setState('filter.archived', ContentComponent::CONDITION_ARCHIVED); @@ -96,7 +108,7 @@ public function getItem($pk = null) if (!isset($this->_item[$pk])) { try { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select( $this->getState( @@ -177,8 +189,11 @@ public function getItem($pk = null) $query->whereIn($db->quoteName('a.language'), [Factory::getLanguage()->getTag(), '*'], ParameterType::STRING); } + $isPreview = $this->getState('article.preview', false); + if ( - !$user->authorise('core.edit.state', 'com_content.article.' . $pk) + !$isPreview + && !$user->authorise('core.edit.state', 'com_content.article.' . $pk) && !$user->authorise('core.edit', 'com_content.article.' . $pk) ) { // Filter by start and end dates. @@ -207,7 +222,7 @@ public function getItem($pk = null) $published = $this->getState('filter.published'); $archived = $this->getState('filter.archived'); - if (is_numeric($published)) { + if (!$isPreview && is_numeric($published)) { $query->whereIn($db->quoteName('a.state'), [(int) $published, (int) $archived]); } @@ -220,7 +235,7 @@ public function getItem($pk = null) } // Check for published state if filter set. - if ((is_numeric($published) || is_numeric($archived)) && ($data->state != $published && $data->state != $archived)) { + if (!$isPreview && (is_numeric($published) || is_numeric($archived)) && ($data->state != $published && $data->state != $archived)) { throw new \Exception(Text::_('COM_CONTENT_ERROR_ARTICLE_NOT_FOUND'), 404); } @@ -262,8 +277,8 @@ public function getItem($pk = null) } // Compute view access permissions. - if ($this->getState('filter.access')) { - // If the access filter has been set, we already know this user can view. + if ($isPreview || $this->getState('filter.access')) { + // Valid preview token or access filter set — user can view. $data->params->set('access-view', true); } else { // If no access filter is set, the layout takes some responsibility for display of limited information. @@ -307,7 +322,7 @@ public function hit($pk = 0) if ($hitcount) { $pk = (!empty($pk)) ? $pk : (int) $this->getState('article.id'); - $table = Table::getInstance('Content', '\\Joomla\\CMS\\Table\\'); + $table = new Content($this->getDatabase()); $table->hit($pk); } @@ -332,7 +347,7 @@ public function storeVote($pk = 0, $rate = 0) // Initialize variables. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Create the base select statement. $query->select('*') @@ -354,7 +369,7 @@ public function storeVote($pk = 0, $rate = 0) // There are no ratings yet, so lets insert our rating if (!$rating) { - $query = $db->getQuery(true); + $query = $db->createQuery(); // Create the base insert statement. $query->insert($db->quoteName('#__content_rating')) @@ -383,7 +398,7 @@ public function storeVote($pk = 0, $rate = 0) } } else { if ($userIP != $rating->lastip) { - $query = $db->getQuery(true); + $query = $db->createQuery(); // Create the base update statement. $query->update($db->quoteName('#__content_rating')) @@ -427,15 +442,13 @@ public function storeVote($pk = 0, $rate = 0) /** * Cleans the cache of com_content and content modules * - * @param string $group The cache group - * @param integer $clientId No longer used, will be removed without replacement - * @deprecated 4.3 will be removed in 6.0 + * @param string $group Cache group name. * * @return void * * @since 3.9.9 */ - protected function cleanCache($group = null, $clientId = 0) + protected function cleanCache($group = null) { parent::cleanCache('com_content'); parent::cleanCache('mod_articles'); diff --git a/components/com_content/src/Model/ArticlesModel.php b/components/com_content/src/Model/ArticlesModel.php index a87bb7fccb44a..e7700dfd5c465 100644 --- a/components/com_content/src/Model/ArticlesModel.php +++ b/components/com_content/src/Model/ArticlesModel.php @@ -195,7 +195,7 @@ protected function getListQuery() // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $nowDate = Factory::getDate()->toSql(); @@ -413,7 +413,7 @@ protected function getListQuery() $levels = (int) $this->getState('filter.max_category_levels', 1); // Create a subquery for the subcategory list - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select($db->quoteName('sub.id')) ->from($db->quoteName('#__categories', 'sub')) ->join( @@ -625,7 +625,7 @@ protected function getListQuery() $tagId = ArrayHelper::toInteger($tagId); if ($tagId) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('content_item_id')) ->from($db->quoteName('#__contentitem_tag_map')) ->where( @@ -682,10 +682,11 @@ public function getItems() // Get the global params $globalParams = ComponentHelper::getParams('com_content', true); - $taggedItems = []; + $taggedItems = []; + $associatedItems = []; // Convert the parameter fields into objects. - foreach ($items as $item) { + foreach ($items as $i => $item) { $articleParams = new Registry($item->attribs); // Unpack readmore and layout params @@ -782,11 +783,12 @@ public function getItems() // Some contexts may not use tags data at all, so we allow callers to disable loading tag data if ($this->getState('load_tags', $item->params->get('show_tags', '1'))) { $item->tags = new TagsHelper(); - $taggedItems[$item->id] = $item; + $taggedItems[$item->id] = $i; } + // Collect items for associations load if (Associations::isEnabled() && $item->params->get('show_associations')) { - $item->associations = AssociationHelper::displayAssociations($item->id); + $associatedItems[$item->id] = $i; } } @@ -796,7 +798,17 @@ public function getItems() $itemIds = array_keys($taggedItems); foreach ($tagsHelper->getMultipleItemTags('com_content.article', $itemIds) as $id => $tags) { - $taggedItems[$id]->tags->itemTags = $tags; + $items[$taggedItems[$id]]->tags->itemTags = $tags; + } + } + + // Load associations of all items. + if ($associatedItems) { + $itemIds = array_keys($associatedItems); + $associations = AssociationHelper::displayAssociations($itemIds); + + foreach ($associatedItems as $itemId => $i) { + $items[$i]->associations = $associations[$itemId] ?? []; } } @@ -826,7 +838,7 @@ public function countItemsByMonth() { // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Get the list query. $listQuery = $this->getListQuery(); diff --git a/components/com_content/src/Model/CategoriesModel.php b/components/com_content/src/Model/CategoriesModel.php index 5c25dc5f4227e..a7b5403ae978b 100644 --- a/components/com_content/src/Model/CategoriesModel.php +++ b/components/com_content/src/Model/CategoriesModel.php @@ -122,10 +122,13 @@ public function getItems($recursive = false) $params = new Registry(); } - $options = []; - $options['countItems'] = $params->get('show_cat_num_articles_cat', 1) || !$params->get('show_empty_categories_cat', 0); - $categories = Categories::getInstance('Content', $options); - $this->_parent = $categories->get($this->getState('filter.parentId', 'root')); + $params = (clone $this->getState('params'))->merge($params); + + $options = []; + $options['countItems'] = $params->get('show_cat_num_articles_cat', 1) || !$params->get('show_empty_categories_cat', 0); + $options['accessOnItems'] = !$params->get('show_noauth', 0); + $categories = Categories::getInstance('Content', $options); + $this->_parent = $categories->get($this->getState('filter.parentId', 'root')); if (\is_object($this->_parent)) { $this->cache[$store] = $this->_parent->getChildren($recursive); diff --git a/components/com_content/src/Model/CategoryModel.php b/components/com_content/src/Model/CategoryModel.php index 4ab90dc3247db..d64a842b75b7c 100644 --- a/components/com_content/src/Model/CategoryModel.php +++ b/components/com_content/src/Model/CategoryModel.php @@ -17,7 +17,7 @@ use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; use Joomla\CMS\Pagination\Pagination; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Category; use Joomla\Component\Content\Site\Helper\QueryHelper; use Joomla\Utilities\ArrayHelper; @@ -220,6 +220,16 @@ protected function populateState($ordering = null, $direction = null) // Set the featured articles state $this->setState('filter.featured', $params->get('show_featured')); + + $authorFilteringType = (int) $params->get('list_author_filtering_type', 1); + + if ($authorFilteringType === 2) { + $this->setState('filter.author_id', [(int) $user->id]); + $this->setState('filter.author_id.include', true); + } else { + $this->setState('filter.author_id', (array) $params->get('list_author', [])); + $this->setState('filter.author_id.include', (bool) $authorFilteringType); + } } /** @@ -259,6 +269,8 @@ public function getItems() $model->setState('list.direction', $this->getState('list.direction')); $model->setState('list.filter', $this->getState('list.filter')); $model->setState('filter.tag', $this->getState('filter.tag')); + $model->setState('filter.author_id', $this->getState('filter.author_id')); + $model->setState('filter.author_id.include', $this->getState('filter.author_id.include', true)); // Filter.subcategories indicates whether to include articles from subcategories in the list or blog $model->setState('filter.subcategories', $this->getState('filter.subcategories')); @@ -348,10 +360,11 @@ public function getCategory() { if (!\is_object($this->_item)) { if (isset($this->state) && !empty($this->state->get('params'))) { - $params = $this->state->get('params'); - $options = []; - $options['countItems'] = $params->get('show_cat_num_articles', 1) || !$params->get('show_empty_categories_cat', 0); - $options['access'] = $params->get('check_access_rights', 1); + $params = $this->state->get('params'); + $options = []; + $options['countItems'] = $params->get('show_cat_num_articles', 1) || !$params->get('show_empty_categories_cat', 0); + $options['access'] = $params->get('check_access_rights', 1); + $options['accessOnItems'] = !$params->get('show_noauth', 0); } else { $options['countItems'] = 0; } @@ -478,7 +491,7 @@ public function hit($pk = 0) if ($hitcount) { $pk = (!empty($pk)) ? $pk : (int) $this->getState('category.id'); - $table = Table::getInstance('Category', '\\Joomla\\CMS\\Table\\'); + $table = new Category($this->getDatabase()); $table->hit($pk); } diff --git a/components/com_content/src/Model/FormModel.php b/components/com_content/src/Model/FormModel.php index 4119f8d610e39..35933a855684e 100644 --- a/components/com_content/src/Model/FormModel.php +++ b/components/com_content/src/Model/FormModel.php @@ -15,7 +15,6 @@ use Joomla\CMS\Helper\TagsHelper; use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Multilanguage; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Table\Table; use Joomla\Database\ParameterType; use Joomla\Registry\Registry; @@ -100,7 +99,7 @@ public function getItem($itemId = null) } $properties = $table->getProperties(1); - $value = ArrayHelper::toObject($properties, CMSObject::class); + $value = ArrayHelper::toObject($properties); // Convert attrib field to Registry. $value->params = new Registry($value->attribs); @@ -158,7 +157,7 @@ public function getItem($itemId = null) if ($value->featured) { // Get featured dates. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('featured_up'), @@ -229,7 +228,7 @@ public function save($data) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|boolean A Form object on success, false on failure + * @return Form|boolean A Form object, false on failure * * @since 1.6 */ @@ -293,7 +292,7 @@ protected function preprocessForm(Form $form, $data, $group = 'content') $categoryId = (int) $params->get('catid'); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('language')) ->from($db->quoteName('#__categories')) ->where($db->quoteName('id') . ' = :categoryId') diff --git a/components/com_content/src/Service/Category.php b/components/com_content/src/Service/Category.php index db686a3f6bd03..ad5d8b055293b 100644 --- a/components/com_content/src/Service/Category.php +++ b/components/com_content/src/Service/Category.php @@ -32,8 +32,9 @@ class Category extends Categories */ public function __construct($options = []) { - $options['table'] = '#__content'; - $options['extension'] = 'com_content'; + $options['table'] = '#__content'; + $options['extension'] = 'com_content'; + $options['accessfield'] = 'access'; parent::__construct($options); } diff --git a/components/com_content/src/Service/Router.php b/components/com_content/src/Service/Router.php index d82ce68771e11..177f1d4ff091a 100644 --- a/components/com_content/src/Service/Router.php +++ b/components/com_content/src/Service/Router.php @@ -254,7 +254,7 @@ public function getCategoriesId($segment, $query) public function getArticleId($segment, $query) { if ($this->noIDs) { - $dbquery = $this->db->getQuery(true); + $dbquery = $this->db->createQuery(); $dbquery->select($this->db->quoteName('id')) ->from($this->db->quoteName('#__content')) ->where($this->db->quoteName('alias') . ' = :segment') @@ -280,7 +280,7 @@ public function getArticleId($segment, $query) $id = (int) $segment; if ($id) { - $dbquery = $this->db->getQuery(true); + $dbquery = $this->db->createQuery(); $dbquery->select($this->db->quoteName('alias')) ->from($this->db->quoteName('#__content')) ->where($this->db->quoteName('id') . ' = :id') diff --git a/components/com_content/src/View/Archive/HtmlView.php b/components/com_content/src/View/Archive/HtmlView.php index 3d0d925897c8b..204a882b8384b 100644 --- a/components/com_content/src/View/Archive/HtmlView.php +++ b/components/com_content/src/View/Archive/HtmlView.php @@ -10,6 +10,10 @@ namespace Joomla\Component\Content\Site\View\Archive; +use Joomla\CMS\Event\Content\AfterDisplayEvent; +use Joomla\CMS\Event\Content\AfterTitleEvent; +use Joomla\CMS\Event\Content\BeforeDisplayEvent; +use Joomla\CMS\Event\Content\ContentPrepareEvent; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; @@ -134,7 +138,8 @@ public function display($tpl = null) // Get the page/component configuration $params = $state->get('params'); - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); foreach ($items as $item) { $item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id; @@ -151,19 +156,32 @@ public function display($tpl = null) $item->text = $item->introtext; } - Factory::getApplication()->triggerEvent('onContentPrepare', ['com_content.archive', &$item, &$item->params, 0]); + $contentEventArguments = [ + 'context' => 'com_content.archive', + 'subject' => $item, + 'params' => $item->params, + 'page' => 0, + ]; + + $dispatcher->dispatch( + 'onContentPrepare', + new ContentPrepareEvent('onContentPrepare', $contentEventArguments) + ); // Old plugins: Use processed text as introtext $item->introtext = $item->text; - $results = Factory::getApplication()->triggerEvent('onContentAfterTitle', ['com_content.archive', &$item, &$item->params, 0]); - $item->event->afterDisplayTitle = trim(implode("\n", $results)); + $contentEvents = [ + 'afterDisplayTitle' => new AfterTitleEvent('onContentAfterTitle', $contentEventArguments), + 'beforeDisplayContent' => new BeforeDisplayEvent('onContentBeforeDisplay', $contentEventArguments), + 'afterDisplayContent' => new AfterDisplayEvent('onContentAfterDisplay', $contentEventArguments), + ]; - $results = Factory::getApplication()->triggerEvent('onContentBeforeDisplay', ['com_content.archive', &$item, &$item->params, 0]); - $item->event->beforeDisplayContent = trim(implode("\n", $results)); + foreach ($contentEvents as $resultKey => $event) { + $results = $dispatcher->dispatch($event->getName(), $event)->getArgument('result', []); - $results = Factory::getApplication()->triggerEvent('onContentAfterDisplay', ['com_content.archive', &$item, &$item->params, 0]); - $item->event->afterDisplayContent = trim(implode("\n", $results)); + $item->event->{$resultKey} = trim(implode("\n", $results)); + } } $form = new \stdClass(); diff --git a/components/com_content/src/View/Category/FeedView.php b/components/com_content/src/View/Category/FeedView.php index 72c1cb9febc28..55b257c46b689 100644 --- a/components/com_content/src/View/Category/FeedView.php +++ b/components/com_content/src/View/Category/FeedView.php @@ -57,7 +57,8 @@ protected function reconcileNames($item) $item->description = '

' . HTMLHelper::_('image', $obj->image_intro, $obj->image_intro_alt) . '

'; } - $item->description .= ($params->get('feed_summary', 0) ? $item->introtext . $item->fulltext : $item->introtext); + $item->description .= $item->params->get('show_intro', 1) ? $item->introtext : ''; + $item->description .= $params->get('feed_summary', 0) ? $item->fulltext : ''; // Add readmore link to description if introtext is shown, show_readmore is true and fulltext exists if (!$item->params->get('feed_summary', 0) && $item->params->get('feed_show_readmore', 0) && $item->fulltext) { diff --git a/components/com_content/src/View/Category/HtmlView.php b/components/com_content/src/View/Category/HtmlView.php index b735e92b17ca4..1bae9f30d2965 100644 --- a/components/com_content/src/View/Category/HtmlView.php +++ b/components/com_content/src/View/Category/HtmlView.php @@ -10,6 +10,10 @@ namespace Joomla\Component\Content\Site\View\Category; +use Joomla\CMS\Event\Content\AfterDisplayEvent; +use Joomla\CMS\Event\Content\AfterTitleEvent; +use Joomla\CMS\Event\Content\BeforeDisplayEvent; +use Joomla\CMS\Event\Content\ContentPrepareEvent; use Joomla\CMS\Factory; use Joomla\CMS\MVC\View\CategoryView; use Joomla\CMS\Plugin\PluginHelper; @@ -93,7 +97,8 @@ public function display($tpl = null) $numLinks = $params->def('num_links', 4); $this->vote = PluginHelper::isEnabled('content', 'vote'); - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); $app = Factory::getApplication(); @@ -113,19 +118,32 @@ public function display($tpl = null) $item->text = $item->introtext; } - $app->triggerEvent('onContentPrepare', ['com_content.category', &$item, &$item->params, 0]); + $contentEventArguments = [ + 'context' => 'com_content.category', + 'subject' => $item, + 'params' => $item->params, + 'page' => 0, + ]; + + $dispatcher->dispatch( + 'onContentPrepare', + new ContentPrepareEvent('onContentPrepare', $contentEventArguments) + ); // Old plugins: Use processed text as introtext $item->introtext = $item->text; - $results = $app->triggerEvent('onContentAfterTitle', ['com_content.category', &$item, &$item->params, 0]); - $item->event->afterDisplayTitle = trim(implode("\n", $results)); + $contentEvents = [ + 'afterDisplayTitle' => new AfterTitleEvent('onContentAfterTitle', $contentEventArguments), + 'beforeDisplayContent' => new BeforeDisplayEvent('onContentBeforeDisplay', $contentEventArguments), + 'afterDisplayContent' => new AfterDisplayEvent('onContentAfterDisplay', $contentEventArguments), + ]; - $results = $app->triggerEvent('onContentBeforeDisplay', ['com_content.category', &$item, &$item->params, 0]); - $item->event->beforeDisplayContent = trim(implode("\n", $results)); + foreach ($contentEvents as $resultKey => $event) { + $results = $dispatcher->dispatch($event->getName(), $event)->getArgument('result', []); - $results = $app->triggerEvent('onContentAfterDisplay', ['com_content.category', &$item, &$item->params, 0]); - $item->event->afterDisplayContent = trim(implode("\n", $results)); + $item->event->{$resultKey} = trim(implode("\n", $results)); + } } // For blog layouts, preprocess the breakdown of leading, intro and linked articles. diff --git a/components/com_content/src/View/Featured/FeedView.php b/components/com_content/src/View/Featured/FeedView.php index 2e58b28b84541..29672d7ddbba9 100644 --- a/components/com_content/src/View/Featured/FeedView.php +++ b/components/com_content/src/View/Featured/FeedView.php @@ -79,8 +79,9 @@ public function display($tpl = null) $description = '

' . HTMLHelper::_('image', $obj->image_intro, $obj->image_intro_alt) . '

'; } - $description .= ($params->get('feed_summary', 0) ? $row->introtext . $row->fulltext : $row->introtext); - $author = $row->created_by_alias ?: $row->author; + $description .= $row->params->get('show_intro', 1) ? $row->introtext : ''; + $description .= $params->get('feed_summary', 0) ? $row->fulltext : ''; + $author = $row->created_by_alias ?: $row->author; // Load individual item creator class $item = new FeedItem(); diff --git a/components/com_content/src/View/Featured/HtmlView.php b/components/com_content/src/View/Featured/HtmlView.php index 686a1b24a7fed..66ea89e12a144 100644 --- a/components/com_content/src/View/Featured/HtmlView.php +++ b/components/com_content/src/View/Featured/HtmlView.php @@ -10,6 +10,10 @@ namespace Joomla\Component\Content\Site\View\Featured; +use Joomla\CMS\Event\Content\AfterDisplayEvent; +use Joomla\CMS\Event\Content\AfterTitleEvent; +use Joomla\CMS\Event\Content\BeforeDisplayEvent; +use Joomla\CMS\Event\Content\ContentPrepareEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\GenericDataException; @@ -71,17 +75,6 @@ class HtmlView extends BaseHtmlView */ protected $link_items = []; - /** - * @var \Joomla\Database\DatabaseDriver - * - * @since 3.6.3 - * - * @deprecated 4.3 will be removed in 6.0 - * Will be removed without replacement use database from the container instead - * Example: Factory::getContainer()->get(DatabaseInterface::class); - */ - protected $db; - /** * The user object * @@ -141,7 +134,8 @@ public function display($tpl = null) $numLeading = (int) $params->def('num_leading_articles', 1); $numIntro = (int) $params->def('num_intro_articles', 4); - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); // Compute the article slugs and prepare introtext (runs content plugins). foreach ($items as &$item) { @@ -159,19 +153,32 @@ public function display($tpl = null) $item->text = $item->introtext; } - Factory::getApplication()->triggerEvent('onContentPrepare', ['com_content.featured', &$item, &$item->params, 0]); + $contentEventArguments = [ + 'context' => 'com_content.featured', + 'subject' => $item, + 'params' => $item->params, + 'page' => 0, + ]; + + $dispatcher->dispatch( + 'onContentPrepare', + new ContentPrepareEvent('onContentPrepare', $contentEventArguments) + ); // Old plugins: Use processed text as introtext $item->introtext = $item->text; - $results = Factory::getApplication()->triggerEvent('onContentAfterTitle', ['com_content.featured', &$item, &$item->params, 0]); - $item->event->afterDisplayTitle = trim(implode("\n", $results)); + $contentEvents = [ + 'afterDisplayTitle' => new AfterTitleEvent('onContentAfterTitle', $contentEventArguments), + 'beforeDisplayContent' => new BeforeDisplayEvent('onContentBeforeDisplay', $contentEventArguments), + 'afterDisplayContent' => new AfterDisplayEvent('onContentAfterDisplay', $contentEventArguments), + ]; - $results = Factory::getApplication()->triggerEvent('onContentBeforeDisplay', ['com_content.featured', &$item, &$item->params, 0]); - $item->event->beforeDisplayContent = trim(implode("\n", $results)); + foreach ($contentEvents as $resultKey => $event) { + $results = $dispatcher->dispatch($event->getName(), $event)->getArgument('result', []); - $results = Factory::getApplication()->triggerEvent('onContentAfterDisplay', ['com_content.featured', &$item, &$item->params, 0]); - $item->event->afterDisplayContent = trim(implode("\n", $results)); + $item->event->{$resultKey} = trim(implode("\n", $results)); + } } // Preprocess the breakdown of leading, intro and linked articles. @@ -205,7 +212,6 @@ public function display($tpl = null) $this->items = &$items; $this->pagination = &$pagination; $this->user = &$user; - $this->db = Factory::getDbo(); $this->_prepareDocument(); diff --git a/components/com_content/src/View/Form/HtmlView.php b/components/com_content/src/View/Form/HtmlView.php index 558dcafb42214..ef08938725b87 100644 --- a/components/com_content/src/View/Form/HtmlView.php +++ b/components/com_content/src/View/Form/HtmlView.php @@ -196,7 +196,7 @@ public function display($tpl = null) // Add form control fields $this->form - ->addControlField('task', '') + ->addControlField('task') ->addControlField('return', $this->return_page ?? ''); $this->_prepareDocument(); diff --git a/components/com_content/tmpl/archive/default.xml b/components/com_content/tmpl/archive/default.xml index 7e0fb8ececd38..9db86bab73dd4 100644 --- a/components/com_content/tmpl/archive/default.xml +++ b/components/com_content/tmpl/archive/default.xml @@ -19,9 +19,9 @@ extension="com_content" multiple="true" layout="joomla.form.field.list-fancy-select" - default=" " + default="" > - +
diff --git a/components/com_content/tmpl/article/default_links.php b/components/com_content/tmpl/article/default_links.php index 47ae3dcd21fac..746d43a877f49 100644 --- a/components/com_content/tmpl/article/default_links.php +++ b/components/com_content/tmpl/article/default_links.php @@ -10,7 +10,8 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; +/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ +$wa = $this->getDocument()->getWebAssetManager(); /** @var \Joomla\Component\Content\Site\View\Article\HtmlView $this */ // Create shortcut @@ -62,22 +63,13 @@ htmlspecialchars($label, ENT_COMPAT, 'UTF-8') . ''; break; case 3: - echo '' . + $wa->useScript('joomla.dialog-autocreate'); + $popupOptions = ['textHeader' => $label, 'className' => 'dialog-content-link', 'width' => '800px', 'height' => '500px', 'preferredParent' => 'body']; + + echo '' . htmlspecialchars($label, ENT_COMPAT, 'UTF-8') . ' '; - echo HTMLHelper::_( - 'bootstrap.renderModal', - 'linkModal', - [ - 'url' => $link, - 'title' => $label, - 'height' => '100%', - 'width' => '100%', - 'modalWidth' => '500', - 'bodyHeight' => '500', - 'footer' => '' - ] - ); + break; default: diff --git a/components/com_content/tmpl/category/blog.php b/components/com_content/tmpl/category/blog.php index 14904fab846d8..aeb5dbaedbae5 100644 --- a/components/com_content/tmpl/category/blog.php +++ b/components/com_content/tmpl/category/blog.php @@ -10,26 +10,52 @@ defined('_JEXEC') or die; +use Joomla\CMS\Event\Content\AfterDisplayEvent; +use Joomla\CMS\Event\Content\AfterTitleEvent; +use Joomla\CMS\Event\Content\BeforeDisplayEvent; +use Joomla\CMS\Event\Content\ContentPrepareEvent; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\FileLayout; use Joomla\CMS\Layout\LayoutHelper; +use Joomla\Event\DispatcherInterface; -$app = Factory::getApplication(); +$dispatcher = Factory::getContainer()->get(DispatcherInterface::class); /** @var \Joomla\Component\Content\Site\View\Category\HtmlView $this */ $this->category->text = $this->category->description; -$app->triggerEvent('onContentPrepare', [$this->category->extension . '.categories', &$this->category, &$this->params, 0]); + +$contentEventArguments = [ + 'context' => $this->category->extension . '.categories', + 'subject' => $this->category, + 'params' => $this->params, + 'page' => 0, +]; + +$dispatcher->dispatch('onContentPrepare', new ContentPrepareEvent('onContentPrepare', $contentEventArguments)); + $this->category->description = $this->category->text; -$results = $app->triggerEvent('onContentAfterTitle', [$this->category->extension . '.categories', &$this->category, &$this->params, 0]); +$results = $dispatcher->dispatch( + 'onContentAfterTitle', + new AfterTitleEvent('onContentAfterTitle', $contentEventArguments) +)->getArgument('result', []); + $afterDisplayTitle = trim(implode("\n", $results)); -$results = $app->triggerEvent('onContentBeforeDisplay', [$this->category->extension . '.categories', &$this->category, &$this->params, 0]); +$results = $dispatcher->dispatch( + 'onContentBeforeDisplay', + new BeforeDisplayEvent('onContentBeforeDisplay', $contentEventArguments) +)->getArgument('result', []); + $beforeDisplayContent = trim(implode("\n", $results)); -$results = $app->triggerEvent('onContentAfterDisplay', [$this->category->extension . '.categories', &$this->category, &$this->params, 0]); +$results = $dispatcher->dispatch( + 'onContentAfterDisplay', + new AfterDisplayEvent('onContentAfterDisplay', $contentEventArguments) +)->getArgument('result', []); + $afterDisplayContent = trim(implode("\n", $results)); $htag = $this->params->get('show_page_heading') ? 'h2' : 'h1'; diff --git a/components/com_content/tmpl/category/blog.xml b/components/com_content/tmpl/category/blog.xml index e369680ca62c8..c0d6031985a0c 100644 --- a/components/com_content/tmpl/category/blog.xml +++ b/components/com_content/tmpl/category/blog.xml @@ -171,7 +171,9 @@
-
+
JONLY + + + + + + + + JSHOW + + + + + JMONTH_PUBLISHED + + + + + + + + children[$this->category->id] as $id => $child) : ?> access, $groups)) : ?> + params); ?> params->get('show_empty_categories') || $child->getNumItems(true) || count($child->getChildren())) : ?> diff --git a/components/com_privacy/tmpl/remind/default.php b/components/com_privacy/tmpl/remind/default.php index bfec2924c1639..6155c3c13cccb 100644 --- a/components/com_privacy/tmpl/remind/default.php +++ b/components/com_privacy/tmpl/remind/default.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -46,6 +45,6 @@ - + form->renderControlFields(); ?> diff --git a/components/com_privacy/tmpl/request/default.php b/components/com_privacy/tmpl/request/default.php index c40ca0808eecb..1c5e10371955d 100644 --- a/components/com_privacy/tmpl/request/default.php +++ b/components/com_privacy/tmpl/request/default.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -47,7 +46,7 @@ - + form->renderControlFields(); ?>
diff --git a/components/com_tags/helpers/route.php b/components/com_tags/helpers/route.php index add993490d0f9..26ce8cffa5d12 100644 --- a/components/com_tags/helpers/route.php +++ b/components/com_tags/helpers/route.php @@ -21,7 +21,7 @@ * * @since 3.1 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use \Joomla\Component\Tags\Site\Helper\RouteHelper instead */ class TagsHelperRoute extends RouteHelper diff --git a/components/com_tags/src/Helper/RouteHelper.php b/components/com_tags/src/Helper/RouteHelper.php index 395f6765f76e8..224b2ec080003 100644 --- a/components/com_tags/src/Helper/RouteHelper.php +++ b/components/com_tags/src/Helper/RouteHelper.php @@ -86,7 +86,7 @@ public static function getItemRoute($contentItemId, $contentItemAlias, $contentC * @since 3.1 * @throws \Exception * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use RouteHelper::getComponentTagRoute() instead */ public static function getTagRoute($id) @@ -141,7 +141,7 @@ public static function getComponentTagRoute(string $id, string $language = '*'): * @since 3.7 * @throws \Exception * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use RouteHelper::getComponentTagsRoute() instead * */ diff --git a/components/com_tags/src/Model/TagModel.php b/components/com_tags/src/Model/TagModel.php index 751bdf1562374..8fe1181846741 100644 --- a/components/com_tags/src/Model/TagModel.php +++ b/components/com_tags/src/Model/TagModel.php @@ -16,7 +16,6 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\ListModel; -use Joomla\CMS\Object\CMSObject; use Joomla\Component\Tags\Site\Helper\RouteHelper; use Joomla\Database\QueryInterface; use Joomla\Utilities\ArrayHelper; @@ -261,7 +260,7 @@ protected function populateState($ordering = 'c.core_title', $direction = 'ASC') * * @param integer $pk An optional ID * - * @return array + * @return \stdClass|false * * @since 3.1 */ @@ -294,9 +293,9 @@ public function getItem($pk = null) continue; } - // Convert the Table to a clean CMSObject. + // Convert the Table to a clean object. $properties = $table->getProperties(1); - $this->item[] = ArrayHelper::toObject($properties, CMSObject::class); + $this->item[] = ArrayHelper::toObject($properties); } catch (\RuntimeException $e) { $this->setError($e->getMessage()); diff --git a/components/com_tags/src/Model/TagsModel.php b/components/com_tags/src/Model/TagsModel.php index 60e81d16a6e53..97b2dc1b51d81 100644 --- a/components/com_tags/src/Model/TagsModel.php +++ b/components/com_tags/src/Model/TagsModel.php @@ -103,7 +103,7 @@ protected function getListQuery() // Create a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select required fields from the tags. $query->select('a.*, u.name as created_by_user_name, u.email') diff --git a/components/com_tags/src/Service/Router.php b/components/com_tags/src/Service/Router.php index 4a89504ced9b0..45af977b8af2c 100644 --- a/components/com_tags/src/Service/Router.php +++ b/components/com_tags/src/Service/Router.php @@ -55,7 +55,7 @@ class Router extends RouterBase * * @var Registry * @since 5.2.0 - * @deprecated 5.2.0 will be removed in 6.0 + * @deprecated 5.2.0 will be removed in 7.0 * without replacement */ private $sefparams; @@ -107,7 +107,7 @@ public function preprocess($query) foreach ($query['id'] as &$item) { if (!strpos($item, ':')) { - $dbquery = $this->db->getQuery(true); + $dbquery = $this->db->createQuery(); $id = (int) $item; $dbquery->select($dbquery->quoteName('alias')) @@ -187,7 +187,7 @@ public function preprocess($query) } } - // TODO: Remove this whole block in 6.0 as it is a bug + // TODO: Remove this whole block in 7.0 as it is a bug if (!$this->sefparams->get('strictrouting', 0)) { // If not found, return language specific home link if (!isset($query['Itemid'])) { @@ -401,7 +401,7 @@ protected function buildLookup() continue; } - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $query->select($this->db->quoteName('a.id')) ->from($this->db->quoteName('#__tags', 'a')) ->leftJoin( @@ -436,7 +436,7 @@ protected function fixSegment($segment) // Try to find tag id $alias = str_replace(':', '-', $segment); - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('id')) ->from($this->db->quoteName('#__tags')) ->where($this->db->quoteName('alias') . ' = :alias') diff --git a/components/com_tags/src/View/Tag/HtmlView.php b/components/com_tags/src/View/Tag/HtmlView.php index eb26c247956f9..6d77e48cbdb27 100644 --- a/components/com_tags/src/View/Tag/HtmlView.php +++ b/components/com_tags/src/View/Tag/HtmlView.php @@ -10,6 +10,10 @@ namespace Joomla\Component\Tags\Site\View\Tag; +use Joomla\CMS\Event\Content\AfterDisplayEvent; +use Joomla\CMS\Event\Content\AfterTitleEvent; +use Joomla\CMS\Event\Content\BeforeDisplayEvent; +use Joomla\CMS\Event\Content\ContentPrepareEvent; use Joomla\CMS\Factory; use Joomla\CMS\Menu\MenuItem; use Joomla\CMS\MVC\View\GenericDataException; @@ -187,7 +191,8 @@ public function display($tpl = null) $itemElement->metadata = new Registry($itemElement->metadata); } - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); foreach ($this->items as $itemElement) { $itemElement->event = new \stdClass(); @@ -197,25 +202,29 @@ public function display($tpl = null) $itemElement->core_params = new Registry($itemElement->core_params); - $app->triggerEvent('onContentPrepare', ['com_tags.tag', &$itemElement, &$itemElement->core_params, 0]); + $contentEventArguments = [ + 'context' => 'com_tags.tag', + 'subject' => $itemElement, + 'params' => $itemElement->core_params, + 'page' => 0, + ]; - $results = $app->triggerEvent( - 'onContentAfterTitle', - ['com_tags.tag', &$itemElement, &$itemElement->core_params, 0] + $dispatcher->dispatch( + 'onContentPrepare', + new ContentPrepareEvent('onContentPrepare', $contentEventArguments) ); - $itemElement->event->afterDisplayTitle = trim(implode("\n", $results)); - $results = $app->triggerEvent( - 'onContentBeforeDisplay', - ['com_tags.tag', &$itemElement, &$itemElement->core_params, 0] - ); - $itemElement->event->beforeDisplayContent = trim(implode("\n", $results)); + $contentEvents = [ + 'afterDisplayTitle' => new AfterTitleEvent('onContentAfterTitle', $contentEventArguments), + 'beforeDisplayContent' => new BeforeDisplayEvent('onContentBeforeDisplay', $contentEventArguments), + 'afterDisplayContent' => new AfterDisplayEvent('onContentAfterDisplay', $contentEventArguments), + ]; - $results = $app->triggerEvent( - 'onContentAfterDisplay', - ['com_tags.tag', &$itemElement, &$itemElement->core_params, 0] - ); - $itemElement->event->afterDisplayContent = trim(implode("\n", $results)); + foreach ($contentEvents as $resultKey => $event) { + $results = $dispatcher->dispatch($event->getName(), $event)->getArgument('result', []); + + $itemElement->event->{$resultKey} = trim(implode("\n", $results)); + } // Write the results back into the body if (!empty($itemElement->core_body)) { diff --git a/components/com_users/forms/reset_complete.xml b/components/com_users/forms/reset_complete.xml index a5f292baf1ff6..a008ad6091fb4 100644 --- a/components/com_users/forms/reset_complete.xml +++ b/components/com_users/forms/reset_complete.xml @@ -1,6 +1,6 @@
-
+
-
+
-
+
loadForm('com_users.login', 'login', ['load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_users.login', 'login', ['load_data' => $loadData]); } /** @@ -137,7 +131,7 @@ public function getMenuLanguage(int $id): string } $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('language')) ->from($db->quoteName('#__menu')) ->where($db->quoteName('client_id') . ' = 0') diff --git a/components/com_users/src/Model/ProfileModel.php b/components/com_users/src/Model/ProfileModel.php index 99831c892194a..412d94c2b2bf8 100644 --- a/components/com_users/src/Model/ProfileModel.php +++ b/components/com_users/src/Model/ProfileModel.php @@ -112,19 +112,16 @@ public function getData() * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_users.profile', 'profile', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - // Check for username compliance and parameter set $isUsernameCompliant = true; $username = $loadData ? $form->getValue('username') : $this->loadFormData()->username; @@ -298,7 +295,7 @@ public function save($data) * * @since 3.2 * - * @deprecated 4.2 will be removed in 6.0. + * @deprecated 4.2 will be removed in 7.0. * Will be removed without replacement */ public function getTwofactorform($userId = null) @@ -315,7 +312,7 @@ public function getTwofactorform($userId = null) * * @since 3.2 * - * @deprecated 4.2 will be removed in 6.0. + * @deprecated 4.2 will be removed in 7.0. * Will be removed without replacement */ public function getOtpConfig($userId = null) diff --git a/components/com_users/src/Model/RegistrationModel.php b/components/com_users/src/Model/RegistrationModel.php index 87e1a6adaf61a..0b837abc4081e 100644 --- a/components/com_users/src/Model/RegistrationModel.php +++ b/components/com_users/src/Model/RegistrationModel.php @@ -14,12 +14,17 @@ use Joomla\CMS\Application\CMSApplicationInterface; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Date\Date; +use Joomla\CMS\Event\Model\PrepareDataEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; use Joomla\CMS\Form\FormFactoryInterface; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\FormModel; @@ -43,9 +48,11 @@ * * @since 1.6 */ -class RegistrationModel extends FormModel implements UserFactoryAwareInterface +class RegistrationModel extends FormModel implements UserFactoryAwareInterface, MailerFactoryAwareInterface, LanguageFactoryAwareInterface { use UserFactoryAwareTrait; + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; /** * @var object The user registration data. @@ -89,7 +96,7 @@ public function getUserIdFromToken($token) $db = $this->getDatabase(); // Get the user id based on the token. - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where($db->quoteName('activation') . ' = :activation') @@ -159,7 +166,7 @@ public function activate($token) // Get all admin users $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['name', 'email', 'sendEmail', 'id'])) ->from($db->quoteName('#__users')) ->where($db->quoteName('sendEmail') . ' = 1') @@ -181,7 +188,12 @@ public function activate($token) if ($usercreator->authorise('core.create', 'com_users') && $usercreator->authorise('core.manage', 'com_users')) { try { - $mailer = new MailTemplate('com_users.registration.admin.verification_request', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_users.registration.admin.verification_request', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addTemplateData($data); $mailer->addRecipient($row->email); $return = $mailer->send(); @@ -217,7 +229,12 @@ public function activate($token) $data['mailfrom'] = $app->get('mailfrom'); $data['sitename'] = $app->get('sitename'); $data['siteurl'] = Uri::base(); - $mailer = new MailTemplate('com_users.registration.user.admin_activated', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_users.registration.user.admin_activated', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addTemplateData($data); $mailer->addRecipient($data['email']); @@ -308,10 +325,14 @@ public function getData() unset($this->data->password1, $this->data->password2); // Get the dispatcher and load the users plugins. - PluginHelper::importPlugin('user'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('user', null, true, $dispatcher); // Trigger the data preparation event. - Factory::getApplication()->triggerEvent('onContentPrepareData', ['com_users.registration', $this->data]); + $dispatcher->dispatch('onContentPrepareData', new PrepareDataEvent('onContentPrepareData', [ + 'context' => 'com_users.registration', + 'data' => $this->data, + ])); } return $this->data; @@ -326,19 +347,16 @@ public function getData() * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { // Get the form. $form = $this->loadForm('com_users.registration', 'registration', ['control' => 'jform', 'load_data' => $loadData]); - if (empty($form)) { - return false; - } - // When multilanguage is set, a user's default site language should also be a Content Language if (Multilanguage::isEnabled()) { $form->setFieldAttribute('language', 'type', 'frontendlanguage', 'params'); @@ -466,7 +484,7 @@ public function register($temp) // From this moment the user is registered, so we don't return false anymore $app = Factory::getApplication(); $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Compile the notification mail values. $data = ArrayHelper::fromObject($user, false); @@ -512,7 +530,12 @@ public function register($temp) // Try to send the registration email. try { - $mailer = new MailTemplate($mailtemplate, $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + $mailtemplate, + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addTemplateData($data); $mailer->addRecipient($data['email']); $mailer->addUnsafeTags(['username', 'password_clear', 'name']); @@ -554,7 +577,12 @@ public function register($temp) } try { - $mailer = new MailTemplate('com_users.registration.admin.new_notification', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_users.registration.admin.new_notification', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addTemplateData($data); $mailer->addRecipient($row->email); $mailer->addUnsafeTags(['username', 'name']); diff --git a/components/com_users/src/Model/RemindModel.php b/components/com_users/src/Model/RemindModel.php index 0a6f23959592d..77a736d236e27 100644 --- a/components/com_users/src/Model/RemindModel.php +++ b/components/com_users/src/Model/RemindModel.php @@ -13,8 +13,12 @@ use Joomla\CMS\Event\User\AfterRemindEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Model\FormModel; use Joomla\CMS\Router\Route; @@ -30,28 +34,25 @@ * * @since 1.5 */ -class RemindModel extends FormModel +class RemindModel extends FormModel implements MailerFactoryAwareInterface, LanguageFactoryAwareInterface { + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; + /** * Method to get the username remind request form. * * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form|bool A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_users.remind', 'remind', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_users.remind', 'remind', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -133,7 +134,7 @@ public function processRemindRequest($data) // Find the user id for the given email address. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(:email)') @@ -176,7 +177,12 @@ public function processRemindRequest($data) $data['link_text'] = Route::link('site', $link, false, $mode, true); $data['link_html'] = Route::link('site', $link, true, $mode, true); - $mailer = new MailTemplate('com_users.reminder', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_users.reminder', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addTemplateData($data); $mailer->addRecipient($user->email, $user->name); diff --git a/components/com_users/src/Model/ResetModel.php b/components/com_users/src/Model/ResetModel.php index 36eb39d40f924..1642605dc8d2c 100644 --- a/components/com_users/src/Model/ResetModel.php +++ b/components/com_users/src/Model/ResetModel.php @@ -14,8 +14,12 @@ use Joomla\CMS\Event\AbstractEvent; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; +use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\Mail\MailTemplate; use Joomla\CMS\MVC\Model\FormModel; use Joomla\CMS\Router\Route; @@ -35,9 +39,11 @@ * * @since 1.5 */ -class ResetModel extends FormModel implements UserFactoryAwareInterface +class ResetModel extends FormModel implements UserFactoryAwareInterface, MailerFactoryAwareInterface, LanguageFactoryAwareInterface { use UserFactoryAwareTrait; + use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; /** * Method to get the password reset request form. @@ -48,20 +54,14 @@ class ResetModel extends FormModel implements UserFactoryAwareInterface * @param array $data An optional array of data for the form to interrogate. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_users.reset_request', 'reset_request', ['control' => 'jform', 'load_data' => $loadData]); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_users.reset_request', 'reset_request', ['control' => 'jform', 'load_data' => $loadData]); } /** @@ -70,20 +70,14 @@ public function getForm($data = [], $loadData = true) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 + * @throws \Exception on failure */ public function getResetCompleteForm($data = [], $loadData = true) { - // Get the form. - $form = $this->loadForm('com_users.reset_complete', 'reset_complete', ['control' => 'jform']); - - if (empty($form)) { - return false; - } - - return $form; + return $this->loadForm('com_users.reset_complete', 'reset_complete', ['control' => 'jform']); } /** @@ -92,7 +86,7 @@ public function getResetCompleteForm($data = [], $loadData = true) * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * - * @return Form A Form object on success, false on failure + * @return Form A Form object * * @since 1.6 * @throws \Exception @@ -102,10 +96,6 @@ public function getResetConfirmForm($data = [], $loadData = true) // Get the form. $form = $this->loadForm('com_users.reset_confirm', 'reset_confirm', ['control' => 'jform']); - if (empty($form)) { - return false; - } - $form->setValue('token', '', Factory::getApplication()->getInput()->get('token')); return $form; @@ -302,7 +292,7 @@ public function processResetConfirm($data) // Find the user id for the given token. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['activation', 'id', 'block'])) ->from($db->quoteName('#__users')) ->where($db->quoteName('username') . ' = :username') @@ -397,7 +387,7 @@ public function processResetRequest($data) // Find the user id for the given email address. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(:email)') @@ -476,7 +466,12 @@ public function processResetRequest($data) $data['link_html'] = Route::link('site', $link, true, $mode, true); $data['token'] = $token; - $mailer = new MailTemplate('com_users.password_reset', $app->getLanguage()->getTag()); + $mailer = new MailTemplate( + 'com_users.password_reset', + $app->getLanguage()->getTag(), + $this->getMailerFactory()->createMailer(), + $this->getLanguageFactory() + ); $mailer->addTemplateData($data); $mailer->addRecipient($user->email, $user->name); diff --git a/components/com_users/src/View/Login/HtmlView.php b/components/com_users/src/View/Login/HtmlView.php index 2f05588e2a1e7..da33bee87c1ab 100644 --- a/components/com_users/src/View/Login/HtmlView.php +++ b/components/com_users/src/View/Login/HtmlView.php @@ -65,17 +65,6 @@ class HtmlView extends BaseHtmlView */ protected $pageclass_sfx = ''; - /** - * No longer used - * - * @var boolean - * @since 4.0.0 - * - * @deprecated 4.3 will be removed in 6.0 - * Will be removed without replacement - */ - protected $tfa = false; - /** * Additional buttons to show on the login page * @@ -120,6 +109,12 @@ public function display($tpl = null) // Escape strings for HTML output $this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8'); + // Add form control fields + $return = $this->form->getValue('return', '', $this->params->get('login_redirect_url', $this->params->get('login_redirect_menuitem', ''))); + + $this->form + ->addControlField('return', base64_encode($return)); + $this->prepareDocument(); parent::display($tpl); diff --git a/components/com_users/src/View/Profile/HtmlView.php b/components/com_users/src/View/Profile/HtmlView.php index 651e27819105e..a2783c06e0100 100644 --- a/components/com_users/src/View/Profile/HtmlView.php +++ b/components/com_users/src/View/Profile/HtmlView.php @@ -10,6 +10,7 @@ namespace Joomla\Component\Users\Site\View\Profile; +use Joomla\CMS\Event\Content\ContentPrepareEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\View\GenericDataException; @@ -19,7 +20,6 @@ use Joomla\CMS\User\User; use Joomla\Component\Users\Administrator\Helper\Mfa; use Joomla\Component\Users\Site\Model\ProfileModel; -use Joomla\Database\DatabaseDriver; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -60,18 +60,6 @@ class HtmlView extends BaseHtmlView */ protected $state; - /** - * An instance of DatabaseDriver. - * - * @var DatabaseDriver - * @since 3.6.3 - * - * @deprecated 4.3 will be removed in 6.0 - * Will be removed without replacement use database from the container instead - * Example: Factory::getContainer()->get(DatabaseInterface::class); - */ - protected $db; - /** * The page class suffix * @@ -109,7 +97,6 @@ public function display($tpl = null) $this->state = $model->getState(); $this->params = $this->state->get('params'); $this->mfaConfigurationUI = Mfa::getConfigurationInterface($user); - $this->db = Factory::getDbo(); // Check for errors. if (\count($errors = $model->getErrors())) { @@ -132,9 +119,15 @@ public function display($tpl = null) throw new \Exception(Text::_('JERROR_USERS_PROFILE_NOT_FOUND'), 404); } - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); $this->data->text = ''; - Factory::getApplication()->triggerEvent('onContentPrepare', ['com_users.user', &$this->data, &$this->data->params, 0]); + $dispatcher->dispatch('onContentPrepare', new ContentPrepareEvent('onContentPrepare', [ + 'context' => 'com_users.user', + 'subject' => $this->data, + 'params' => $this->data->params, + 'page' => 0, + ])); unset($this->data->text); // Check for layout from menu item. diff --git a/components/com_users/tmpl/captive/default.php b/components/com_users/tmpl/captive/default.php index d99864080ce8f..57628677e1645 100644 --- a/components/com_users/tmpl/captive/default.php +++ b/components/com_users/tmpl/captive/default.php @@ -12,13 +12,11 @@ use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; -use Joomla\Component\Users\Site\Model\CaptiveModel; -use Joomla\Component\Users\Site\View\Captive\HtmlView; use Joomla\Utilities\ArrayHelper; /** - * @var HtmlView $this View object - * @var CaptiveModel $model The model + * @var \Joomla\Component\Users\Site\View\Captive\HtmlView $this View object + * @var \Joomla\Component\Users\Site\Model\CaptiveModel $model The model */ $model = $this->getModel(); @@ -117,7 +115,7 @@ class="btn btn-danger btn-sm" id="users-mfa-captive-button-logout"> records) > 1) : ?> diff --git a/components/com_users/tmpl/captive/select.php b/components/com_users/tmpl/captive/select.php index c09272c8d0346..a0d247e87acd0 100644 --- a/components/com_users/tmpl/captive/select.php +++ b/components/com_users/tmpl/captive/select.php @@ -14,9 +14,8 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; use Joomla\CMS\Uri\Uri; -use Joomla\Component\Users\Site\View\Captive\HtmlView; -/** @var HtmlView $this */ +/** @var \Joomla\Component\Users\Site\View\Captive\HtmlView $this */ $shownMethods = []; diff --git a/components/com_users/tmpl/login/default_login.php b/components/com_users/tmpl/login/default_login.php index f066d6c72734d..93d5ba4a0a3ec 100644 --- a/components/com_users/tmpl/login/default_login.php +++ b/components/com_users/tmpl/login/default_login.php @@ -109,9 +109,7 @@ class="btn btn-secondary w-100 "
- form->getValue('return', '', $this->params->get('login_redirect_url', $this->params->get('login_redirect_menuitem', ''))); ?> - - + form->renderControlFields(); ?>
- + + form->renderControlFields(); ?> diff --git a/components/com_users/tmpl/registration/default.php b/components/com_users/tmpl/registration/default.php index 04a312c42c0b5..26de906bfa92b 100644 --- a/components/com_users/tmpl/registration/default.php +++ b/components/com_users/tmpl/registration/default.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -57,6 +56,7 @@ - + + form->renderControlFields(); ?> diff --git a/components/com_users/tmpl/remind/default.php b/components/com_users/tmpl/remind/default.php index a0d4453f7a180..59110d441fc48 100644 --- a/components/com_users/tmpl/remind/default.php +++ b/components/com_users/tmpl/remind/default.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -45,6 +44,7 @@ - + + form->renderControlFields(); ?> diff --git a/components/com_users/tmpl/reset/complete.php b/components/com_users/tmpl/reset/complete.php index 13fe66290e8dc..7165addd18cfc 100644 --- a/components/com_users/tmpl/reset/complete.php +++ b/components/com_users/tmpl/reset/complete.php @@ -32,8 +32,11 @@
form->getFieldsets() as $fieldset) : ?>
- label)) : ?> - label); ?> + legend)) : ?> + legend); ?> + + description)) : ?> +

description); ?>

form->renderFieldset($fieldset->name); ?>
diff --git a/components/com_users/tmpl/reset/confirm.php b/components/com_users/tmpl/reset/confirm.php index 755240c7896c7..ee1e3b7ab9558 100644 --- a/components/com_users/tmpl/reset/confirm.php +++ b/components/com_users/tmpl/reset/confirm.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -32,8 +31,11 @@ form->getFieldsets() as $fieldset) : ?>
- label)) : ?> - label); ?> + legend)) : ?> + legend); ?> + + description)) : ?> +

description); ?>

form->renderFieldset($fieldset->name); ?>
@@ -45,6 +47,7 @@ - + + form->renderControlFields(); ?>
diff --git a/components/com_users/tmpl/reset/default.php b/components/com_users/tmpl/reset/default.php index 7fa7267a5c047..fc2809a1b7ee4 100644 --- a/components/com_users/tmpl/reset/default.php +++ b/components/com_users/tmpl/reset/default.php @@ -10,7 +10,6 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; @@ -32,8 +31,11 @@
form->getFieldsets() as $fieldset) : ?>
- label)) : ?> - label); ?> + legend)) : ?> + legend); ?> + + description)) : ?> +

description); ?>

form->renderFieldset($fieldset->name); ?>
@@ -45,6 +47,7 @@ - + + form->renderControlFields(); ?>
diff --git a/components/com_workflow/src/Dispatcher/Dispatcher.php b/components/com_workflow/src/Dispatcher/Dispatcher.php new file mode 100644 index 0000000000000..a9e26aabc4db0 --- /dev/null +++ b/components/com_workflow/src/Dispatcher/Dispatcher.php @@ -0,0 +1,87 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Workflow\Site\Dispatcher; + +use Joomla\CMS\Access\Exception\NotAllowed; +use Joomla\CMS\Dispatcher\ComponentDispatcher; +use Joomla\CMS\MVC\Controller\BaseController; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * ComponentDispatcher class for com_contenthistory + * + * @since 6.1.0 + */ +class Dispatcher extends ComponentDispatcher +{ + /** + * Load the language + * + * @since 6.1.0 + * + * @return void + */ + protected function loadLanguage() + { + // Load common and local language files. + $this->app->getLanguage()->load($this->option, JPATH_ADMINISTRATOR) || + $this->app->getLanguage()->load($this->option, JPATH_SITE); + } + + /** + * Method to check component access permission + * + * @since 6.1.0 + * + * @return void + * + * @throws \Exception|NotAllowed + */ + protected function checkAccess() + { + $input = $this->app->getInput(); + $view = $input->getCmd('view'); + $task = $input->getCmd('task'); + + $allowedTasks = [ + 'graph.getWorkflow', + 'graph.getStages', + 'graph.getTransitions', + ]; + + // Check the user has permission to access this component if in the backend + if ($this->app->getIdentity()->guest || $view !== 'graph' || !\in_array($task, $allowedTasks, true)) { + throw new NotAllowed($this->app->getLanguage()->_('JERROR_ALERTNOAUTHOR'), 403); + } + } + + /** + * Get a controller from the component + * + * @param string $name Controller name + * @param string $client Optional client (like Administrator, Site etc.) + * @param array $config Optional controller config + * + * @return BaseController + * + * @since 6.1.0 + */ + public function getController(string $name, string $client = '', array $config = []): BaseController + { + $config['base_path'] = JPATH_ADMINISTRATOR . '/components/com_workflow'; + $client = 'Administrator'; + + return parent::getController($name, $client, $config); + } +} diff --git a/composer.json b/composer.json index 1b95216d70f6e..b948a65c065af 100644 --- a/composer.json +++ b/composer.json @@ -11,16 +11,21 @@ "config": { "optimize-autoloader": true, "platform": { - "php": "8.1.0" + "php": "8.3.0" }, "vendor-dir": "libraries/vendor", - "github-protocols": ["https"] + "github-protocols": ["https"], + "audit": { + "ignore": { "PKSA-3mms-4n3p-ym65": "Temporary until Webauthn plugin has been updated." } + } }, "support": { + "github": "https://github.com/joomla/joomla-cms", "issues": "https://issues.joomla.org/", - "irc": "irc://chat.freenode.net/joomla/", + "chat": "https://joom.la/chat/", "forum": "https://forum.joomla.org/", - "docs": "https://docs.joomla.org/" + "docs": "https://guide.joomla.org/", + "developer docs": "https://manual.joomla.org/" }, "repositories": [ { @@ -32,11 +37,6 @@ "type": "vcs", "url": "https://github.com/joomla-backports/php-tuf.git", "no-api": true - }, - { - "type": "vcs", - "url": "https://github.com/joomla-backports/portable-utf8.git", - "no-api": true } ], "autoload": { @@ -51,46 +51,45 @@ } }, "require": { - "php": "^8.1.0", - "joomla/application": "^3.0.4", - "joomla/archive": "^3.0.4", - "joomla/authentication": "^3.0.3", - "joomla/console": "^3.0.3", - "joomla/crypt": "^3.0.3", - "joomla/data": "^3.0.3", - "joomla/database": "^3.4", - "joomla/di": "^3.1.1", - "joomla/event": "^3.0.2", - "joomla/filter": "^3.0.6", - "joomla/filesystem": "^3.3.0", - "joomla/http": "^3.1.4", - "joomla/input": "~3.0", - "joomla/language": "~3.0", - "joomla/oauth1": "~3.0", - "joomla/oauth2": "~3.0", - "joomla/registry": "~3.0", - "joomla/router": "~3.0", - "joomla/session": "^3.0.3", - "joomla/string": "^3.0.4", - "joomla/uri": "~3.0", - "joomla/utilities": "~3.0", - "algo26-matthias/idna-convert": "^3.2.1", + "php": "^8.3.0", + "joomla/application": "^4.0", + "joomla/archive": "^4.0", + "joomla/authentication": "^4.0", + "joomla/console": "^4.0", + "joomla/crypt": "^4.0", + "joomla/data": "^4.0", + "joomla/database": "^4.0", + "joomla/di": "^4.0", + "joomla/event": "^4.0", + "joomla/filter": "^4.1.0", + "joomla/filesystem": "^4.2.1", + "joomla/http": "^4.0", + "joomla/input": "^4.0", + "joomla/language": "^4.0", + "joomla/oauth1": "^4.0", + "joomla/oauth2": "^4.0", + "joomla/registry": "^4.0", + "joomla/router": "^4.0", + "joomla/session": "^4.0", + "joomla/string": "^4.0", + "joomla/uri": "^4.0", + "joomla/utilities": "^4.0", + "algo26-matthias/idna-convert": "^4.2.1", "defuse/php-encryption": "^2.4.0", - "doctrine/inflector": "^1.4.4", + "doctrine/inflector": "^2.1.0", "fig/link-util": "^1.2.0", "google/recaptcha": "^1.3.1", - "laminas/laminas-diactoros": "^2.26.0", + "laminas/laminas-diactoros": "^3.8.0", "paragonie/sodium_compat": "^1.24.0", - "phpmailer/phpmailer": "^6.10.0", + "phpmailer/phpmailer": "^6.12.0", "psr/link": "~1.1.1", - "symfony/console": "^6.4.25", - "symfony/error-handler": "^6.4.24", - "symfony/ldap": "^6.4.24", - "symfony/options-resolver": "^6.4.25", + "symfony/console": "^7", + "symfony/error-handler": "^7", + "symfony/ldap": "^7", + "symfony/options-resolver": "^7", "symfony/polyfill-mbstring": "^1.33.0", - "symfony/web-link": "^6.4.24", - "symfony/yaml": "^6.4.41", - "typo3/phar-stream-wrapper": "^3.1.8", + "symfony/web-link": "^6.4.32", + "symfony/yaml": "^6.4.34", "wamania/php-stemmer": "^4.0.0", "tobscure/json-api": "dev-joomla-backports", "willdurand/negotiation": "^3.1.0", @@ -100,35 +99,32 @@ "ext-gd": "*", "web-auth/webauthn-lib": "4.5.2", "ext-dom": "*", - "composer/ca-bundle": "^1.5.8", - "dragonmantank/cron-expression": "^3.4.0", + "composer/ca-bundle": "^1.5.10", + "dragonmantank/cron-expression": "^3.6.0", "enshrined/svg-sanitize": "^0.22.0", "lcobucci/jwt": "^4.3.0", "web-token/jwt-library": "^3.4.10", "phpseclib/bcmath_compat": "^2.0.3", "jfcherng/php-diff": "^6.16.2", - "voku/portable-utf8": "dev-joomla-5.3 as 6.0.13", "php-tuf/php-tuf": "^1.0.3", - "php-debugbar/php-debugbar": "^2.2.4" + "php-debugbar/php-debugbar": "^2.2.6", + "altcha-org/altcha": "^1.3.2" }, "require-dev": { "phpunit/phpunit": "^9.6.34", - "friendsofphp/php-cs-fixer": "^3.88.0", - "squizlabs/php_codesniffer": "^3.13.4", - "joomla/mediawiki": "^3.0", - "joomla/test": "~3.0", - "phpstan/phpstan": "^2.1.29", - "phpstan/phpstan-deprecation-rules": "^2.0.3" + "friendsofphp/php-cs-fixer": "^3.94.2", + "squizlabs/php_codesniffer": "^3.13.5", + "joomla/mediawiki": "^4.0", + "joomla/test": "~4.0", + "phpstan/phpstan": "^2.1.40", + "phpstan/phpstan-deprecation-rules": "^2.0.4" }, "replace": { "paragonie/random_compat": "9.99.99", - "symfony/polyfill-php70": "*", - "symfony/polyfill-php71": "*", - "symfony/polyfill-php72": "*", - "symfony/polyfill-php73": "*", - "symfony/polyfill-php74": "*", "symfony/polyfill-php80": "*", - "symfony/polyfill-php81": "*" + "symfony/polyfill-php81": "*", + "symfony/polyfill-php82": "*", + "symfony/polyfill-php83": "*" }, "extra": { "composer-exit-on-patch-failure": true @@ -136,6 +132,8 @@ "scripts": { "post-install-cmd": [ "php build/update_fido_cache.php" - ] + ], + "phpcs": "./libraries/vendor/bin/phpcs --extensions=php -p --standard=ruleset.xml .", + "csfixer": "./libraries/vendor/bin/php-cs-fixer fix -vvv --dry-run --diff" } } diff --git a/composer.lock b/composer.lock index e34496e53527f..e36ba9b39d320 100644 --- a/composer.lock +++ b/composer.lock @@ -4,29 +4,29 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a57ffa9d593e21ab64d0dacd2c607920", + "content-hash": "2409c13ac45e0db9103c9377e0a7fd00", "packages": [ { "name": "algo26-matthias/idna-convert", - "version": "v3.2.1", + "version": "v4.2.1", "source": { "type": "git", "url": "https://github.com/algo26-matthias/idna-convert.git", - "reference": "82fe7b60e1a1620c72e68803cc5dcff0b5f59bdc" + "reference": "87bfcab8e453d7ede78eeec15d75c75f0e926f3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/algo26-matthias/idna-convert/zipball/82fe7b60e1a1620c72e68803cc5dcff0b5f59bdc", - "reference": "82fe7b60e1a1620c72e68803cc5dcff0b5f59bdc", + "url": "https://api.github.com/repos/algo26-matthias/idna-convert/zipball/87bfcab8e453d7ede78eeec15d75c75f0e926f3c", + "reference": "87bfcab8e453d7ede78eeec15d75c75f0e926f3c", "shasum": "" }, "require": { "ext-pcre": "*", "jakeasmith/http_build_url": "^1", - "php": ">=7.2.0" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "8.0" + "phpunit/phpunit": "^9 || ^10" }, "suggest": { "ext-iconv": "Install ext/iconv for using input / output other than UTF-8 or ISO-8859-1", @@ -50,7 +50,7 @@ } ], "description": "A library for encoding and decoding internationalized domain names", - "homepage": "http://idnaconv.net/", + "homepage": "https://github.com/algo26-matthias/idna-convert", "keywords": [ "idn", "idna", @@ -58,9 +58,55 @@ ], "support": { "issues": "https://github.com/algo26-matthias/idna-convert/issues", - "source": "https://github.com/algo26-matthias/idna-convert/tree/v3.2.1" + "source": "https://github.com/algo26-matthias/idna-convert/tree/v4.2.1" + }, + "time": "2025-10-10T11:39:49+00:00" + }, + { + "name": "altcha-org/altcha", + "version": "v1.3.3", + "source": { + "type": "git", + "url": "https://github.com/altcha-org/altcha-lib-php.git", + "reference": "9a9b98c48dea0b2e8c353ea991d5f5627cbdab36" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/altcha-org/altcha-lib-php/zipball/9a9b98c48dea0b2e8c353ea991d5f5627cbdab36", + "reference": "9a9b98c48dea0b2e8c353ea991d5f5627cbdab36", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.72", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^11.5.50" + }, + "type": "library", + "autoload": { + "psr-4": { + "AltchaOrg\\Altcha\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Regeci", + "email": "536331+ovx@users.noreply.github.com" + } + ], + "support": { + "issues": "https://github.com/altcha-org/altcha-lib-php/issues", + "source": "https://github.com/altcha-org/altcha-lib-php/tree/v1.3.3" }, - "time": "2025-10-10T11:40:12+00:00" + "time": "2026-04-02T12:13:35+00:00" }, { "name": "brick/math", @@ -124,16 +170,16 @@ }, { "name": "composer/ca-bundle", - "version": "1.5.8", + "version": "1.5.12", "source": { "type": "git", "url": "https://github.com/composer/ca-bundle.git", - "reference": "719026bb30813accb68271fee7e39552a58e9f65" + "reference": "00a2f4201641d5c53f7fc0195e6c8d9fcc321a78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/ca-bundle/zipball/719026bb30813accb68271fee7e39552a58e9f65", - "reference": "719026bb30813accb68271fee7e39552a58e9f65", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/00a2f4201641d5c53f7fc0195e6c8d9fcc321a78", + "reference": "00a2f4201641d5c53f7fc0195e6c8d9fcc321a78", "shasum": "" }, "require": { @@ -180,7 +226,7 @@ "support": { "irc": "irc://irc.freenode.org/composer", "issues": "https://github.com/composer/ca-bundle/issues", - "source": "https://github.com/composer/ca-bundle/tree/1.5.8" + "source": "https://github.com/composer/ca-bundle/tree/1.5.12" }, "funding": [ { @@ -192,7 +238,7 @@ "type": "github" } ], - "time": "2025-08-20T18:49:47+00:00" + "time": "2026-05-19T11:26:22+00:00" }, { "name": "defuse/php-encryption", @@ -263,38 +309,32 @@ }, { "name": "doctrine/inflector", - "version": "1.4.4", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9" + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9", - "reference": "4bd5c1cdfcd00e9e2d8c484f79150f67e5d355d9", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^8.0", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpstan/phpstan-strict-rules": "^0.12", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector", - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + "Doctrine\\Inflector\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -339,7 +379,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/1.4.4" + "source": "https://github.com/doctrine/inflector/tree/2.1.0" }, "funding": [ { @@ -355,33 +395,32 @@ "type": "tidelift" } ], - "time": "2021-04-16T17:34:40+00:00" + "time": "2025-08-10T19:31:58+00:00" }, { "name": "dragonmantank/cron-expression", - "version": "v3.4.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "8c784d071debd117328803d86b2097615b457500" + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", - "reference": "8c784d071debd117328803d86b2097615b457500", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/d61a8a9604ec1f8c3d150d09db6ce98b32675013", + "reference": "d61a8a9604ec1f8c3d150d09db6ce98b32675013", "shasum": "" }, "require": { - "php": "^7.2|^8.0", - "webmozart/assert": "^1.0" + "php": "^8.2|^8.3|^8.4|^8.5" }, "replace": { "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.0", - "phpunit/phpunit": "^7.0|^8.0|^9.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.32|^2.1.31", + "phpunit/phpunit": "^8.5.48|^9.0" }, "type": "library", "extra": { @@ -412,7 +451,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.6.0" }, "funding": [ { @@ -420,7 +459,7 @@ "type": "github" } ], - "time": "2024-10-09T13:47:03+00:00" + "time": "2025-10-31T18:51:33+00:00" }, { "name": "enshrined/svg-sanitize", @@ -582,24 +621,25 @@ }, { "name": "guzzlehttp/promises", - "version": "2.3.0", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "481557b130ef3790cf82b713667b43030dc9c957" + "reference": "4360e982f87f5f258bf872d094647791db2f4c8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", - "reference": "481557b130ef3790cf82b713667b43030dc9c957", + "url": "https://api.github.com/repos/guzzle/promises/zipball/4360e982f87f5f258bf872d094647791db2f4c8e", + "reference": "4360e982f87f5f258bf872d094647791db2f4c8e", "shasum": "" }, "require": { - "php": "^7.2.5 || ^8.0" + "php": "^7.2.5 || ^8.0", + "symfony/deprecation-contracts": "^2.5 || ^3.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "type": "library", "extra": { @@ -645,7 +685,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.3.0" + "source": "https://github.com/guzzle/promises/tree/2.5.0" }, "funding": [ { @@ -661,20 +701,20 @@ "type": "tidelift" } ], - "time": "2025-08-22T14:34:08+00:00" + "time": "2026-06-02T12:23:43+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.12.3", + "version": "2.12.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d" + "reference": "172ef2f4e9824c1e058b7f30be8ae25a02c0f2b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/7ec62dc3f44aa218487dbed81a9bf9bc647be55d", - "reference": "7ec62dc3f44aa218487dbed81a9bf9bc647be55d", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/172ef2f4e9824c1e058b7f30be8ae25a02c0f2b7", + "reference": "172ef2f4e9824c1e058b7f30be8ae25a02c0f2b7", "shasum": "" }, "require": { @@ -683,7 +723,7 @@ "psr/http-message": "^1.1 || ^2.0", "ralouphie/getallheaders": "^3.0", "symfony/deprecation-contracts": "^2.5 || ^3.0", - "symfony/polyfill-php80": "^1.25" + "symfony/polyfill-php80": "^1.24" }, "provide": { "psr/http-factory-implementation": "1.0", @@ -764,7 +804,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.12.3" + "source": "https://github.com/guzzle/psr7/tree/2.12.1" }, "funding": [ { @@ -780,7 +820,7 @@ "type": "tidelift" } ], - "time": "2026-06-23T15:21:08+00:00" + "time": "2026-06-18T09:49:37+00:00" }, { "name": "jakeasmith/http_build_url", @@ -1058,58 +1098,52 @@ }, { "name": "joomla/application", - "version": "3.0.4", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/application.git", - "reference": "3ab2450f712136f1893337a38bb4c4f951cc853b" + "reference": "878d1f4a2dc03b6197d0e6cfb4a969ec06a3314d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/application/zipball/3ab2450f712136f1893337a38bb4c4f951cc853b", - "reference": "3ab2450f712136f1893337a38bb4c4f951cc853b", + "url": "https://api.github.com/repos/joomla-framework/application/zipball/878d1f4a2dc03b6197d0e6cfb4a969ec06a3314d", + "reference": "878d1f4a2dc03b6197d0e6cfb4a969ec06a3314d", "shasum": "" }, "require": { - "joomla/event": "^3.0", - "joomla/registry": "^3.0", - "laminas/laminas-diactoros": "^2.24.0", - "php": "^8.1.0", - "psr/http-message": "^1.0", + "joomla/event": "^4.0", + "joomla/registry": "^4.0", + "laminas/laminas-diactoros": "^3.6.0", + "php": "^8.3.0", + "psr/http-message": "^2.0", "psr/log": "^1.0|^2.0|^3.0", "symfony/deprecation-contracts": "^2|^3" }, "require-dev": { "ext-json": "*", - "joomla/controller": "^3.0", - "joomla/di": "^3.0", - "joomla/input": "^3.0", - "joomla/router": "^3.0", - "joomla/session": "^3.0", - "joomla/test": "^3.0", - "joomla/uri": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", + "joomla/controller": "^4.0", + "joomla/di": "^4.0", + "joomla/input": "^4.0", + "joomla/router": "^4.0", + "joomla/session": "^4.0", + "joomla/test": "^4.0", + "joomla/uri": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", "phpunit/phpunit": "^10.0", "squizlabs/php_codesniffer": "~3.10.2", "symfony/phpunit-bridge": "^7.0" }, "suggest": { "ext-json": "To use JSON format, ext-json is required", - "joomla/controller": "^3.0 To support resolving ControllerInterface objects in ControllerResolverInterface, install joomla/controller", - "joomla/input": "^3.0 To use WebApplicationInterface, install joomla/input", - "joomla/router": "^3.0 To use WebApplication or ControllerResolverInterface implementations, install joomla/router", - "joomla/session": "^3.0 To use SessionAwareWebApplicationInterface, install joomla/session", - "joomla/uri": "^3.0 To use AbstractWebApplication, install joomla/uri", - "psr/container": "^1.0 To use the ContainerControllerResolver, install any PSR-11 compatible container" + "joomla/controller": "^4.0 To support resolving ControllerInterface objects in ControllerResolverInterface, install joomla/controller", + "joomla/input": "^4.0 To use WebApplicationInterface, install joomla/input", + "joomla/router": "^4.0 To use WebApplication or ControllerResolverInterface implementations, install joomla/router", + "joomla/session": "^4.0 To use SessionAwareWebApplicationInterface, install joomla/session", + "joomla/uri": "^4.0 To use AbstractWebApplication, install joomla/uri", + "psr/container": "^2.0 To use the ContainerControllerResolver, install any PSR-11 compatible container" }, "type": "library", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Application\\": "src/" @@ -1150,32 +1184,32 @@ "type": "github" } ], - "time": "2025-07-11T09:17:42+00:00" + "time": "2025-07-24T09:55:44+00:00" }, { "name": "joomla/archive", - "version": "3.0.4", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/archive.git", - "reference": "1d506857685f3537c1193f4e77b12f24cc9afe49" + "reference": "7a8d0eda637bd37bc3de744aa3e4ce516d4356b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/archive/zipball/1d506857685f3537c1193f4e77b12f24cc9afe49", - "reference": "1d506857685f3537c1193f4e77b12f24cc9afe49", + "url": "https://api.github.com/repos/joomla-framework/archive/zipball/7a8d0eda637bd37bc3de744aa3e4ce516d4356b0", + "reference": "7a8d0eda637bd37bc3de744aa3e4ce516d4356b0", "shasum": "" }, "require": { - "joomla/filesystem": "^3.0", - "php": "^8.1.0" + "joomla/filesystem": "^4.0", + "php": "^8.3.0" }, "require-dev": { - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^10.0", - "squizlabs/php_codesniffer": "~3.10.2" + "joomla/test": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.0", + "squizlabs/php_codesniffer": "^3.10.2" }, "suggest": { "ext-bz2": "To extract bzip2 compressed packages", @@ -1183,12 +1217,6 @@ "ext-zlib": "To extract gzip or zip compressed packages" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Archive\\": "src/" @@ -1207,47 +1235,41 @@ ], "support": { "issues": "https://github.com/joomla-framework/archive/issues", - "source": "https://github.com/joomla-framework/archive/tree/3.0.4" + "source": "https://github.com/joomla-framework/archive/tree/4.0.0" }, - "time": "2025-07-11T10:54:02+00:00" + "time": "2025-07-24T08:04:38+00:00" }, { "name": "joomla/authentication", - "version": "3.0.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/authentication.git", - "reference": "ea3a263985a40c231a42d050ccd3f822b7b5e778" + "reference": "1d9b946410ac43c8d206d9d6bf741173b83a8e4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/authentication/zipball/ea3a263985a40c231a42d050ccd3f822b7b5e778", - "reference": "ea3a263985a40c231a42d050ccd3f822b7b5e778", + "url": "https://api.github.com/repos/joomla-framework/authentication/zipball/1d9b946410ac43c8d206d9d6bf741173b83a8e4c", + "reference": "1d9b946410ac43c8d206d9d6bf741173b83a8e4c", "shasum": "" }, "require": { - "php": "^8.1.0" + "php": "^8.3.0" }, "require-dev": { - "joomla/database": "^3.0", - "joomla/input": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^10.0", - "squizlabs/php_codesniffer": "~3.10.2", - "symfony/phpunit-bridge": "^7.0" + "joomla/database": "^4.0", + "joomla/input": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.0", + "squizlabs/php_codesniffer": "^3.10.2", + "symfony/phpunit-bridge": "^8.0" }, "suggest": { "joomla/database": "Required if you want to use Joomla\\Authentication\\Strategies\\DatabaseStrategy", "joomla/input": "Required if you want to use classes in the Joomla\\Authentication\\Strategies namespace" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Authentication\\": "src/" @@ -1266,50 +1288,44 @@ ], "support": { "issues": "https://github.com/joomla-framework/authentication/issues", - "source": "https://github.com/joomla-framework/authentication/tree/3.0.3" + "source": "https://github.com/joomla-framework/authentication/tree/4.0.0" }, - "time": "2025-07-17T14:56:13+00:00" + "time": "2025-07-24T08:02:13+00:00" }, { "name": "joomla/console", - "version": "3.0.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/console.git", - "reference": "839ac3e759a9c8bf962175906480923a7b680c36" + "reference": "b58fb572436ad9e230061ff6929aa1446849efe8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/console/zipball/839ac3e759a9c8bf962175906480923a7b680c36", - "reference": "839ac3e759a9c8bf962175906480923a7b680c36", + "url": "https://api.github.com/repos/joomla-framework/console/zipball/b58fb572436ad9e230061ff6929aa1446849efe8", + "reference": "b58fb572436ad9e230061ff6929aa1446849efe8", "shasum": "" }, "require": { - "joomla/application": "^3.0", - "joomla/event": "^3.0", - "joomla/string": "^3.0", - "php": "^8.1.0", - "symfony/console": "^v6.2.0", - "symfony/error-handler": "^6" + "joomla/application": "^4.0", + "joomla/event": "^4.0", + "joomla/string": "^4.0", + "php": "^8.3.0", + "symfony/console": "^v7.0.0", + "symfony/error-handler": "^7" }, "require-dev": { - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^10.0", - "psr/container": "^1.0", + "joomla/test": "^4.0", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpunit/phpunit": "^12.0", + "psr/container": "^2.0", "squizlabs/php_codesniffer": "~3.10.2" }, "suggest": { "psr/container-implementation": "To use the ContainerLoader" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Console\\": "src/" @@ -1328,35 +1344,34 @@ ], "support": { "issues": "https://github.com/joomla-framework/console/issues", - "source": "https://github.com/joomla-framework/console/tree/3.0.3" + "source": "https://github.com/joomla-framework/console/tree/4.0.0" }, - "time": "2025-07-17T14:55:35+00:00" + "time": "2025-07-24T08:33:34+00:00" }, { "name": "joomla/crypt", - "version": "3.0.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/crypt.git", - "reference": "0cfd0a3ab2fc64015030319348a16f4fa6e0355a" + "reference": "9b069827a7875ae3bff409695624071f4d356aca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/crypt/zipball/0cfd0a3ab2fc64015030319348a16f4fa6e0355a", - "reference": "0cfd0a3ab2fc64015030319348a16f4fa6e0355a", + "url": "https://api.github.com/repos/joomla-framework/crypt/zipball/9b069827a7875ae3bff409695624071f4d356aca", + "reference": "9b069827a7875ae3bff409695624071f4d356aca", "shasum": "" }, "require": { - "php": "^8.1.0" + "php": "^8.3.0" }, "require-dev": { "defuse/php-encryption": "^2.0", "paragonie/sodium_compat": "^1|^2", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "~3.7.2", - "symfony/phpunit-bridge": "^5.0", "symfony/polyfill-util": "^1.0" }, "suggest": { @@ -1366,12 +1381,6 @@ "paragonie/sodium_compat": "To use Sodium cipher if neither ext/sodium or ext/libsodium are available" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Crypt\\": "src/" @@ -1390,42 +1399,36 @@ ], "support": { "issues": "https://github.com/joomla-framework/crypt/issues", - "source": "https://github.com/joomla-framework/crypt/tree/3.0.3" + "source": "https://github.com/joomla-framework/crypt/tree/4.0.0" }, - "time": "2025-07-19T11:01:54+00:00" + "time": "2025-07-24T07:56:55+00:00" }, { "name": "joomla/data", - "version": "3.0.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/data.git", - "reference": "8eaa08b07b84dce217b1735e5c51d66285ff93ae" + "reference": "e00293048e893dc3c5e793b091e87da84faf3963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/data/zipball/8eaa08b07b84dce217b1735e5c51d66285ff93ae", - "reference": "8eaa08b07b84dce217b1735e5c51d66285ff93ae", + "url": "https://api.github.com/repos/joomla-framework/data/zipball/e00293048e893dc3c5e793b091e87da84faf3963", + "reference": "e00293048e893dc3c5e793b091e87da84faf3963", "shasum": "" }, "require": { - "joomla/registry": "^3.0", - "php": "^8.1.0" + "joomla/registry": "^4.0", + "php": "^8.3.0" }, "require-dev": { - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", - "squizlabs/php_codesniffer": "~3.7.2" + "joomla/test": "^4.0", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpunit/phpunit": "^12.0", + "squizlabs/php_codesniffer": "~3.10.2" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Data\\": "src/" @@ -1444,42 +1447,43 @@ ], "support": { "issues": "https://github.com/joomla-framework/data/issues", - "source": "https://github.com/joomla-framework/data/tree/3.0.3" + "source": "https://github.com/joomla-framework/data/tree/4.0.0" }, - "time": "2025-07-19T12:27:51+00:00" + "time": "2025-07-24T08:48:07+00:00" }, { "name": "joomla/database", - "version": "3.4.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/database.git", - "reference": "6a8aedaea444cd78912153c4d8361eb06ba2a9cd" + "reference": "2e744e7959368891fe52ccb35790e201251f6f39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/database/zipball/6a8aedaea444cd78912153c4d8361eb06ba2a9cd", - "reference": "6a8aedaea444cd78912153c4d8361eb06ba2a9cd", + "url": "https://api.github.com/repos/joomla-framework/database/zipball/2e744e7959368891fe52ccb35790e201251f6f39", + "reference": "2e744e7959368891fe52ccb35790e201251f6f39", "shasum": "" }, "require": { - "joomla/event": "^3.0", - "php": "^8.1.0", + "joomla/event": "^4.0", + "php": "^8.3.0", "symfony/deprecation-contracts": "^2|^3" }, "require-dev": { - "joomla/archive": "^3.0", - "joomla/console": "^3.0", - "joomla/di": "^3.0", - "joomla/filesystem": "^3.0", - "joomla/registry": "^3.0", - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", - "psr/log": "^1.1", - "squizlabs/php_codesniffer": "~3.7.2", - "symfony/phpunit-bridge": "^5.0" + "colinodell/psr-testlogger": "^1.3.0", + "joomla/archive": "^4.0", + "joomla/console": "^4.0", + "joomla/di": "^4.0", + "joomla/filesystem": "^4.0", + "joomla/registry": "^4.0", + "joomla/test": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.0", + "psr/log": "^3.0.2", + "squizlabs/php_codesniffer": "^3.10.2", + "symfony/phpunit-bridge": "^8.0" }, "suggest": { "ext-mysqli": "To connect to a MySQL database via MySQLi", @@ -1493,12 +1497,6 @@ "psr/log": "To use the LoggingMonitor, install psr/log." }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Database\\": "src/" @@ -1517,46 +1515,40 @@ ], "support": { "issues": "https://github.com/joomla-framework/database/issues", - "source": "https://github.com/joomla-framework/database/tree/3.4.3" + "source": "https://github.com/joomla-framework/database/tree/4.0.0" }, - "time": "2025-07-19T15:40:51+00:00" + "time": "2025-07-24T09:46:18+00:00" }, { "name": "joomla/di", - "version": "3.1.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/di.git", - "reference": "fd98d11dddf65adf9c6eff68a4c80f9f2f34b2b9" + "reference": "e8511111e2b5b239f75116f9ff75b43c18809868" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/di/zipball/fd98d11dddf65adf9c6eff68a4c80f9f2f34b2b9", - "reference": "fd98d11dddf65adf9c6eff68a4c80f9f2f34b2b9", + "url": "https://api.github.com/repos/joomla-framework/di/zipball/e8511111e2b5b239f75116f9ff75b43c18809868", + "reference": "e8511111e2b5b239f75116f9ff75b43c18809868", "shasum": "" }, "require": { - "php": "^8.1.0", - "psr/container": "^1.0", + "php": "^8.3.0", + "psr/container": "^2.0", "symfony/deprecation-contracts": "^2|^3" }, "provide": { "psr/container-implementation": "~1.0" }, "require-dev": { - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "joomla/test": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "~3.7.2" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\DI\\": "src/" @@ -1578,47 +1570,41 @@ ], "support": { "issues": "https://github.com/joomla-framework/di/issues", - "source": "https://github.com/joomla-framework/di/tree/3.1.1" + "source": "https://github.com/joomla-framework/di/tree/4.0.0" }, - "time": "2025-07-19T16:11:41+00:00" + "time": "2025-07-24T07:51:22+00:00" }, { "name": "joomla/event", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/event.git", - "reference": "d1a5dd4c5c8aa1d1c7a7101da93e677ec5d3ef3f" + "reference": "4bbbfb0a3444cb3e3f9abd57d623caa06e9207b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/event/zipball/d1a5dd4c5c8aa1d1c7a7101da93e677ec5d3ef3f", - "reference": "d1a5dd4c5c8aa1d1c7a7101da93e677ec5d3ef3f", + "url": "https://api.github.com/repos/joomla-framework/event/zipball/4bbbfb0a3444cb3e3f9abd57d623caa06e9207b5", + "reference": "4bbbfb0a3444cb3e3f9abd57d623caa06e9207b5", "shasum": "" }, "require": { - "php": "^8.1.0", + "php": "^8.3.0", "symfony/deprecation-contracts": "^2|^3" }, "require-dev": { - "joomla/console": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", - "psr/container": "^1.0", - "squizlabs/php_codesniffer": "~3.7.2" + "joomla/console": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.7", + "psr/container": "^2.0", + "squizlabs/php_codesniffer": "^3.7.2" }, "suggest": { "joomla/console": "If you want to use the DebugEventDispatcherCommand class, please install joomla/console", "psr/container-implementation": "If you want to use the LazyServiceEventListener class, please install a PSR-11 container" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Event\\": "src/" @@ -1637,42 +1623,36 @@ ], "support": { "issues": "https://github.com/joomla-framework/event/issues", - "source": "https://github.com/joomla-framework/event/tree/3.0.2" + "source": "https://github.com/joomla-framework/event/tree/4.0.0" }, - "time": "2025-07-19T18:30:21+00:00" + "time": "2025-07-24T09:34:33+00:00" }, { "name": "joomla/filesystem", - "version": "3.3.0", + "version": "4.2.1", "source": { "type": "git", "url": "https://github.com/joomla-framework/filesystem.git", - "reference": "0452f6ce0365d90a39fe9d005059aa245613f4e1" + "reference": "a79ed5044970b81a5aed22049199c1d6bc902d9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/filesystem/zipball/0452f6ce0365d90a39fe9d005059aa245613f4e1", - "reference": "0452f6ce0365d90a39fe9d005059aa245613f4e1", + "url": "https://api.github.com/repos/joomla-framework/filesystem/zipball/a79ed5044970b81a5aed22049199c1d6bc902d9a", + "reference": "a79ed5044970b81a5aed22049199c1d6bc902d9a", "shasum": "" }, "require": { - "php": "^8.1.0" + "php": "^8.3.0" }, "require-dev": { - "joomla/test": "^3.0", + "joomla/test": "^4.0", "mikey179/vfsstream": "^1.6.11", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", - "squizlabs/php_codesniffer": "^3.7.2" + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.7", + "squizlabs/php_codesniffer": "^3.13.2" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Filesystem\\": "src/" @@ -1691,45 +1671,39 @@ ], "support": { "issues": "https://github.com/joomla-framework/filesystem/issues", - "source": "https://github.com/joomla-framework/filesystem/tree/3.3.0" + "source": "https://github.com/joomla-framework/filesystem/tree/4.2.1" }, - "time": "2026-06-25T19:30:56+00:00" + "time": "2026-08-18T15:44:34+00:00" }, { "name": "joomla/filter", - "version": "3.0.6", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/filter.git", - "reference": "dde731979af1a34a0b5610281c227274628c1b6f" + "reference": "f61782cddb50f3d27a970b355ac1712bc6b16689" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/filter/zipball/dde731979af1a34a0b5610281c227274628c1b6f", - "reference": "dde731979af1a34a0b5610281c227274628c1b6f", + "url": "https://api.github.com/repos/joomla-framework/filter/zipball/f61782cddb50f3d27a970b355ac1712bc6b16689", + "reference": "f61782cddb50f3d27a970b355ac1712bc6b16689", "shasum": "" }, "require": { - "joomla/string": "^3.0", - "php": "^8.1.0" + "joomla/string": "^4.0", + "php": "^8.3.0" }, "require-dev": { - "joomla/language": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "joomla/language": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.7", "squizlabs/php_codesniffer": "^3.7.2" }, "suggest": { "joomla/language": "Required only if you want to use `OutputFilter::stringURLSafe`." }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Filter\\": "src/" @@ -1748,49 +1722,43 @@ ], "support": { "issues": "https://github.com/joomla-framework/filter/issues", - "source": "https://github.com/joomla-framework/filter/tree/3.0.6" + "source": "https://github.com/joomla-framework/filter/tree/4.1.0" }, - "time": "2026-05-26T16:06:28+00:00" + "time": "2026-08-14T10:06:10+00:00" }, { "name": "joomla/http", - "version": "3.1.4", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/joomla-framework/http.git", - "reference": "493dc254d9fa9277c7ab3488573ddb4f3bbfa9bc" + "reference": "3c494722385f556e022ea57b9e9c7474d95452c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/http/zipball/493dc254d9fa9277c7ab3488573ddb4f3bbfa9bc", - "reference": "493dc254d9fa9277c7ab3488573ddb4f3bbfa9bc", + "url": "https://api.github.com/repos/joomla-framework/http/zipball/3c494722385f556e022ea57b9e9c7474d95452c3", + "reference": "3c494722385f556e022ea57b9e9c7474d95452c3", "shasum": "" }, "require": { "composer/ca-bundle": "^1.3.5", - "joomla/uri": "^3.0", - "laminas/laminas-diactoros": "^2.24.0", - "php": "^8.1.0", + "joomla/uri": "^4.0", + "laminas/laminas-diactoros": "^3.6.0", + "php": "^8.3.0", "psr/http-client": "^1.0", - "psr/http-message": "^1.0" + "psr/http-message": "^2.0" }, "require-dev": { - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "joomla/test": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "^3.7.2" }, "suggest": { "ext-curl": "To use cURL for HTTP connections" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Http\\": "src/" @@ -1809,43 +1777,37 @@ ], "support": { "issues": "https://github.com/joomla-framework/http/issues", - "source": "https://github.com/joomla-framework/http/tree/3.1.4" + "source": "https://github.com/joomla-framework/http/tree/4.0.2" }, - "time": "2026-01-07T16:36:43+00:00" + "time": "2026-01-08T07:18:39+00:00" }, { "name": "joomla/input", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/input.git", - "reference": "b4ef792308e7adb42fb71a8118025ced899e4386" + "reference": "f366f97b143bd9d15f57dad74b21f72ac99d89ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/input/zipball/b4ef792308e7adb42fb71a8118025ced899e4386", - "reference": "b4ef792308e7adb42fb71a8118025ced899e4386", + "url": "https://api.github.com/repos/joomla-framework/input/zipball/f366f97b143bd9d15f57dad74b21f72ac99d89ec", + "reference": "f366f97b143bd9d15f57dad74b21f72ac99d89ec", "shasum": "" }, "require": { - "joomla/filter": "^3.0", - "php": "^8.1.0", + "joomla/filter": "^4.0", + "php": "^8.3.0", "symfony/deprecation-contracts": "^2|^3" }, "require-dev": { - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", - "squizlabs/php_codesniffer": "^3.7.2" + "joomla/test": "^4.0", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpunit/phpunit": "^12.0", + "squizlabs/php_codesniffer": "^3.10.2" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Input\\": "src/" @@ -1864,49 +1826,43 @@ ], "support": { "issues": "https://github.com/joomla-framework/input/issues", - "source": "https://github.com/joomla-framework/input/tree/3.0.2" + "source": "https://github.com/joomla-framework/input/tree/4.0.0" }, - "time": "2025-07-19T12:57:48+00:00" + "time": "2025-07-23T19:52:44+00:00" }, { "name": "joomla/language", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/language.git", - "reference": "7bd3d468ffad1e9639468a17751ec4324fc57d09" + "reference": "371507d84103e9e7b48253e72b3bcc8d91cf5a63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/language/zipball/7bd3d468ffad1e9639468a17751ec4324fc57d09", - "reference": "7bd3d468ffad1e9639468a17751ec4324fc57d09", + "url": "https://api.github.com/repos/joomla-framework/language/zipball/371507d84103e9e7b48253e72b3bcc8d91cf5a63", + "reference": "371507d84103e9e7b48253e72b3bcc8d91cf5a63", "shasum": "" }, "require": { "ext-xml": "*", - "joomla/string": "^3.0", - "php": "^8.1.0", + "joomla/string": "^4.0", + "php": "^8.3.0", "symfony/deprecation-contracts": "^2|^3" }, "require-dev": { - "joomla/di": "^3.0", - "joomla/registry": "^3.0", - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "joomla/di": "^4.0", + "joomla/registry": "^4.0", + "joomla/test": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "^3.7.2" }, "suggest": { "joomla/di": "To use the Language ServiceProviderInterface objects, install joomla/di." }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Language\\": "src/" @@ -1925,48 +1881,42 @@ ], "support": { "issues": "https://github.com/joomla-framework/language/issues", - "source": "https://github.com/joomla-framework/language/tree/3.0.2" + "source": "https://github.com/joomla-framework/language/tree/4.0.0" }, - "time": "2025-07-19T13:19:12+00:00" + "time": "2025-07-23T19:48:37+00:00" }, { "name": "joomla/oauth1", - "version": "3.0.1", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/joomla-framework/oauth1.git", - "reference": "4c1407cc98e0689ff36fa566906673829a8627ec" + "reference": "e48c0af2173222494cbac414e971c807f32a9eb9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/oauth1/zipball/4c1407cc98e0689ff36fa566906673829a8627ec", - "reference": "4c1407cc98e0689ff36fa566906673829a8627ec", + "url": "https://api.github.com/repos/joomla-framework/oauth1/zipball/e48c0af2173222494cbac414e971c807f32a9eb9", + "reference": "e48c0af2173222494cbac414e971c807f32a9eb9", "shasum": "" }, "require": { - "joomla/application": "^3.0", - "joomla/http": "^3.0", - "joomla/input": "^3.0", - "joomla/registry": "^3.0", - "joomla/session": "^3.0", - "joomla/uri": "^3.0", - "php": "^8.1.0" + "joomla/application": "^4.0", + "joomla/http": "^4.0", + "joomla/input": "^4.0", + "joomla/registry": "^4.0", + "joomla/session": "^4.0", + "joomla/uri": "^4.0", + "php": "^8.3.0" }, "require-dev": { - "joomla/event": "^3.0", - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", - "squizlabs/php_codesniffer": "^3.7.2" + "joomla/event": "^4.0", + "joomla/test": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.7", + "squizlabs/php_codesniffer": "^3.13.2" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\OAuth1\\": "src/" @@ -1985,45 +1935,39 @@ ], "support": { "issues": "https://github.com/joomla-framework/oauth1/issues", - "source": "https://github.com/joomla-framework/oauth1/tree/3.0.1" + "source": "https://github.com/joomla-framework/oauth1/tree/4.0.1" }, - "time": "2025-07-19T19:54:15+00:00" + "time": "2025-08-06T11:59:19+00:00" }, { "name": "joomla/oauth2", - "version": "3.0.3", + "version": "4.0.2", "source": { "type": "git", "url": "https://github.com/joomla-framework/oauth2.git", - "reference": "318bae49ddfe67f83626bc05e0d0c82d20c365d0" + "reference": "bb24c0a969fcc62c97997ba33a476ec888c34b00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/oauth2/zipball/318bae49ddfe67f83626bc05e0d0c82d20c365d0", - "reference": "318bae49ddfe67f83626bc05e0d0c82d20c365d0", + "url": "https://api.github.com/repos/joomla-framework/oauth2/zipball/bb24c0a969fcc62c97997ba33a476ec888c34b00", + "reference": "bb24c0a969fcc62c97997ba33a476ec888c34b00", "shasum": "" }, "require": { - "joomla/application": "^3.0", - "joomla/http": "^3.0", - "joomla/input": "^3.0", - "joomla/session": "^3.0", - "joomla/uri": "^3.0", - "php": "^8.1.0" + "joomla/application": "^4.0", + "joomla/http": "^4.0", + "joomla/input": "^4.0", + "joomla/session": "^4.0", + "joomla/uri": "^4.0", + "php": "^8.3.0" }, "require-dev": { - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", - "squizlabs/php_codesniffer": "^3.7.2" + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.0", + "squizlabs/php_codesniffer": "^3.10.2" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\OAuth2\\": "src/" @@ -2042,34 +1986,34 @@ ], "support": { "issues": "https://github.com/joomla-framework/oauth2/issues", - "source": "https://github.com/joomla-framework/oauth2/tree/3.0.3" + "source": "https://github.com/joomla-framework/oauth2/tree/4.0.2" }, - "time": "2026-04-19T10:05:06+00:00" + "time": "2026-04-15T17:57:50+00:00" }, { "name": "joomla/registry", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/registry.git", - "reference": "4452de9c66abfec59b535e27c62af3528a539311" + "reference": "5692d8423c9b568627df701e9fd505eae5ea8f72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/registry/zipball/4452de9c66abfec59b535e27c62af3528a539311", - "reference": "4452de9c66abfec59b535e27c62af3528a539311", + "url": "https://api.github.com/repos/joomla-framework/registry/zipball/5692d8423c9b568627df701e9fd505eae5ea8f72", + "reference": "5692d8423c9b568627df701e9fd505eae5ea8f72", "shasum": "" }, "require": { - "joomla/utilities": "^3.0", - "php": "^8.1.0" + "joomla/utilities": "^4.0", + "php": "^8.3.0" }, "require-dev": { - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "^3.7.2", - "symfony/yaml": "^5.0" + "symfony/yaml": "^7.3" }, "suggest": { "ext-json": "ext-json is needed for JSON support", @@ -2077,12 +2021,6 @@ "symfony/yaml": "Install symfony/yaml if you require YAML support." }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Registry\\": "src/" @@ -2101,49 +2039,40 @@ ], "support": { "issues": "https://github.com/joomla-framework/registry/issues", - "source": "https://github.com/joomla-framework/registry/tree/3.0.2" + "source": "https://github.com/joomla-framework/registry/tree/4.0.0" }, - "time": "2025-07-19T16:26:22+00:00" + "time": "2025-07-23T19:26:22+00:00" }, { "name": "joomla/router", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/router.git", - "reference": "8aa0013a6ba59ef250496b47855498e9a83156d1" + "reference": "d0552ac09b92712a140fff2323579b84fbaa12b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/router/zipball/8aa0013a6ba59ef250496b47855498e9a83156d1", - "reference": "8aa0013a6ba59ef250496b47855498e9a83156d1", + "url": "https://api.github.com/repos/joomla-framework/router/zipball/d0552ac09b92712a140fff2323579b84fbaa12b8", + "reference": "d0552ac09b92712a140fff2323579b84fbaa12b8", "shasum": "" }, "require": { - "php": "^8.1.0" - }, - "conflict": { - "jeremeamia/superclosure": "<2.4" + "php": "^8.3.0" }, "require-dev": { - "jeremeamia/superclosure": "^2.4", - "joomla/console": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "joomla/console": "^4.0", + "opis/closure": "^4.3.1", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "^3.7.2" }, "suggest": { - "jeremeamia/superclosure": "If you use Closure based controllers and want to be able to serialize the router, please install jeremeamia/superclosure", - "joomla/console": "If you want to use the DebugRouterCommand class, please install joomla/console" + "joomla/console": "If you want to use the DebugRouterCommand class, please install joomla/console", + "opis/closure": "If you use Closure based controllers and want to be able to serialize the router, please install opis/closure" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Router\\": "src/" @@ -2162,39 +2091,39 @@ ], "support": { "issues": "https://github.com/joomla-framework/router/issues", - "source": "https://github.com/joomla-framework/router/tree/3.0.2" + "source": "https://github.com/joomla-framework/router/tree/4.0.0" }, - "time": "2025-07-19T13:51:10+00:00" + "time": "2025-07-23T19:21:30+00:00" }, { "name": "joomla/session", - "version": "3.0.3", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/session.git", - "reference": "6bebada5dccf70be0d18db673aa3a68af19b3972" + "reference": "3d1d8bc093d659053c46eec4962bef4c1e9e0206" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/session/zipball/6bebada5dccf70be0d18db673aa3a68af19b3972", - "reference": "6bebada5dccf70be0d18db673aa3a68af19b3972", + "url": "https://api.github.com/repos/joomla-framework/session/zipball/3d1d8bc093d659053c46eec4962bef4c1e9e0206", + "reference": "3d1d8bc093d659053c46eec4962bef4c1e9e0206", "shasum": "" }, "require": { - "php": "^8.1.0", + "php": "^8.3.0", "symfony/deprecation-contracts": "^2|^3" }, "require-dev": { - "joomla/console": "^3.0", - "joomla/database": "^3.0", - "joomla/event": "^3.0", - "joomla/input": "^3.0", - "joomla/test": "^3.0", - "joomla/utilities": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", - "squizlabs/php_codesniffer": "^3.7.2" + "joomla/console": "^4.0", + "joomla/database": "^4.0", + "joomla/event": "^4.0", + "joomla/input": "^4.0", + "joomla/test": "^4.0", + "joomla/utilities": "^4.0", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpunit/phpunit": "^12.0", + "squizlabs/php_codesniffer": "^3.10.2" }, "suggest": { "ext-apcu": "To use APCu cache as a session handler", @@ -2208,12 +2137,6 @@ "joomla/input": "The joomla/input package is required to use Address and Forwarded session validators." }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.x-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Session\\": "src/" @@ -2232,37 +2155,35 @@ ], "support": { "issues": "https://github.com/joomla-framework/session/issues", - "source": "https://github.com/joomla-framework/session/tree/3.0.3" + "source": "https://github.com/joomla-framework/session/tree/4.0.0" }, - "time": "2025-07-19T15:19:54+00:00" + "time": "2025-07-23T19:16:20+00:00" }, { "name": "joomla/string", - "version": "3.0.4", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/string.git", - "reference": "0b3d33564db389e27346f7e275c694897c939434" + "reference": "da2329e05f1f5fc98b709f8638f279513bcd1108" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/string/zipball/0b3d33564db389e27346f7e275c694897c939434", - "reference": "0b3d33564db389e27346f7e275c694897c939434", + "url": "https://api.github.com/repos/joomla-framework/string/zipball/da2329e05f1f5fc98b709f8638f279513bcd1108", + "reference": "da2329e05f1f5fc98b709f8638f279513bcd1108", "shasum": "" }, "require": { - "php": "^8.1.0", - "symfony/deprecation-contracts": "^2|^3" - }, - "conflict": { - "doctrine/inflector": "<1.2" + "php": "^8.3.0", + "symfony/deprecation-contracts": "^2|^3", + "symfony/polyfill-mbstring": "^1.31.0" }, "require-dev": { - "doctrine/inflector": "^1.2", - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "doctrine/inflector": "^2.0.10", + "joomla/test": "^4.0", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "^3.7.2" }, "suggest": { @@ -2270,30 +2191,7 @@ "ext-mbstring": "For improved processing" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { - "files": [ - "src/phputf8/utf8.php", - "src/phputf8/ord.php", - "src/phputf8/str_ireplace.php", - "src/phputf8/str_pad.php", - "src/phputf8/str_split.php", - "src/phputf8/strcasecmp.php", - "src/phputf8/strcspn.php", - "src/phputf8/stristr.php", - "src/phputf8/strrev.php", - "src/phputf8/strspn.php", - "src/phputf8/trim.php", - "src/phputf8/ucfirst.php", - "src/phputf8/ucwords.php", - "src/phputf8/utils/ascii.php", - "src/phputf8/utils/validation.php" - ], "psr-4": { "Joomla\\String\\": "src/" } @@ -2311,43 +2209,37 @@ ], "support": { "issues": "https://github.com/joomla-framework/string/issues", - "source": "https://github.com/joomla-framework/string/tree/3.0.4" + "source": "https://github.com/joomla-framework/string/tree/4.0.0" }, - "time": "2025-07-19T15:25:56+00:00" + "time": "2025-07-23T18:42:26+00:00" }, { "name": "joomla/uri", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/uri.git", - "reference": "ac18b410b58c5d2cb652eac7c13acb4971cb5e0d" + "reference": "9fa4fac811bf63e830d46d83031c353cf2765bcd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/uri/zipball/ac18b410b58c5d2cb652eac7c13acb4971cb5e0d", - "reference": "ac18b410b58c5d2cb652eac7c13acb4971cb5e0d", + "url": "https://api.github.com/repos/joomla-framework/uri/zipball/9fa4fac811bf63e830d46d83031c353cf2765bcd", + "reference": "9fa4fac811bf63e830d46d83031c353cf2765bcd", "shasum": "" }, "require": { - "php": "^8.1.0" + "php": "^8.3.0" }, "require-dev": { - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "^3.7.2" }, "suggest": { "ext-mbstring": "Used to speed up url parsing" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Uri\\": "src/" @@ -2366,41 +2258,35 @@ ], "support": { "issues": "https://github.com/joomla-framework/uri/issues", - "source": "https://github.com/joomla-framework/uri/tree/3.0.2" + "source": "https://github.com/joomla-framework/uri/tree/4.0.0" }, - "time": "2025-07-12T12:01:42+00:00" + "time": "2025-07-23T19:02:38+00:00" }, { "name": "joomla/utilities", - "version": "3.0.2", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/joomla-framework/utilities.git", - "reference": "bec074fa469cfdb30fae168899cf65159bf7890d" + "reference": "5f234527f7dad7111830b091aef52787c3c07cc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/utilities/zipball/bec074fa469cfdb30fae168899cf65159bf7890d", - "reference": "bec074fa469cfdb30fae168899cf65159bf7890d", + "url": "https://api.github.com/repos/joomla-framework/utilities/zipball/5f234527f7dad7111830b091aef52787c3c07cc8", + "reference": "5f234527f7dad7111830b091aef52787c3c07cc8", "shasum": "" }, "require": { - "joomla/string": "^3.0", - "php": "^8.1.0" + "joomla/string": "^4.0", + "php": "^8.3.0" }, "require-dev": { "phpstan/phpstan": "^2.1.17", "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpunit/phpunit": "^9.5.28", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "^3.7.2" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Utilities\\": "src/" @@ -2419,47 +2305,47 @@ ], "support": { "issues": "https://github.com/joomla-framework/utilities/issues", - "source": "https://github.com/joomla-framework/utilities/tree/3.0.2" + "source": "https://github.com/joomla-framework/utilities/tree/4.0.0" }, - "time": "2025-07-19T16:29:29+00:00" + "time": "2025-07-23T18:52:12+00:00" }, { "name": "laminas/laminas-diactoros", - "version": "2.26.0", + "version": "3.8.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-diactoros.git", - "reference": "6584d44eb8e477e89d453313b858daac6183cddc" + "reference": "60c182916b2749480895601649563970f3f12ec4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/6584d44eb8e477e89d453313b858daac6183cddc", - "reference": "6584d44eb8e477e89d453313b858daac6183cddc", + "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/60c182916b2749480895601649563970f3f12ec4", + "reference": "60c182916b2749480895601649563970f3f12ec4", "shasum": "" }, "require": { - "php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "psr/http-factory": "^1.0", - "psr/http-message": "^1.1" + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", + "psr/http-factory": "^1.1", + "psr/http-message": "^1.1 || ^2.0" }, "conflict": { - "zendframework/zend-diactoros": "*" + "amphp/amp": "<2.6.4" }, "provide": { - "psr/http-factory-implementation": "1.0", - "psr/http-message-implementation": "1.0" + "psr/http-factory-implementation": "^1.0", + "psr/http-message-implementation": "^1.1 || ^2.0" }, "require-dev": { "ext-curl": "*", "ext-dom": "*", "ext-gd": "*", "ext-libxml": "*", - "http-interop/http-factory-tests": "^0.9.0", - "laminas/laminas-coding-standard": "^2.5", - "php-http/psr7-integration-tests": "^1.2", - "phpunit/phpunit": "^9.5.28", - "psalm/plugin-phpunit": "^0.18.4", - "vimeo/psalm": "^5.6" + "http-interop/http-factory-tests": "^2.2.0", + "laminas/laminas-coding-standard": "~3.1.0", + "php-http/psr7-integration-tests": "^1.4.0", + "phpunit/phpunit": "^10.5.36", + "psalm/plugin-phpunit": "^0.19.5", + "vimeo/psalm": "^6.13" }, "type": "library", "extra": { @@ -2474,18 +2360,9 @@ "src/functions/marshal_headers_from_sapi.php", "src/functions/marshal_method_from_sapi.php", "src/functions/marshal_protocol_version_from_sapi.php", - "src/functions/marshal_uri_from_sapi.php", "src/functions/normalize_server.php", "src/functions/normalize_uploaded_files.php", - "src/functions/parse_cookie_header.php", - "src/functions/create_uploaded_file.legacy.php", - "src/functions/marshal_headers_from_sapi.legacy.php", - "src/functions/marshal_method_from_sapi.legacy.php", - "src/functions/marshal_protocol_version_from_sapi.legacy.php", - "src/functions/marshal_uri_from_sapi.legacy.php", - "src/functions/normalize_server.legacy.php", - "src/functions/normalize_uploaded_files.legacy.php", - "src/functions/parse_cookie_header.legacy.php" + "src/functions/parse_cookie_header.php" ], "psr-4": { "Laminas\\Diactoros\\": "src/" @@ -2518,38 +2395,38 @@ "type": "community_bridge" } ], - "time": "2023-10-29T16:17:44+00:00" + "time": "2025-10-12T15:31:36+00:00" }, { "name": "lcobucci/clock", - "version": "3.0.0", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/lcobucci/clock.git", - "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc" + "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/039ef98c6b57b101d10bd11d8fdfda12cbd996dc", - "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/a3139d9e97d47826f27e6a17bb63f13621f86058", + "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058", "shasum": "" }, "require": { - "php": "~8.1.0 || ~8.2.0", + "php": "~8.3.0 || ~8.4.0 || ~8.5.0", "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" }, "require-dev": { - "infection/infection": "^0.26", - "lcobucci/coding-standard": "^9.0", - "phpstan/extension-installer": "^1.2", - "phpstan/phpstan": "^1.9.4", - "phpstan/phpstan-deprecation-rules": "^1.1.1", - "phpstan/phpstan-phpunit": "^1.3.2", - "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^9.5.27" + "infection/infection": "^0.31", + "lcobucci/coding-standard": "^11.2.0", + "phpstan/extension-installer": "^1.3.1", + "phpstan/phpstan": "^2.0.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0.0", + "phpstan/phpstan-strict-rules": "^2.0.0", + "phpunit/phpunit": "^12.0.0" }, "type": "library", "autoload": { @@ -2570,7 +2447,7 @@ "description": "Yet another clock abstraction", "support": { "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.0.0" + "source": "https://github.com/lcobucci/clock/tree/3.5.0" }, "funding": [ { @@ -2582,7 +2459,7 @@ "type": "patreon" } ], - "time": "2022-12-19T15:00:24+00:00" + "time": "2025-10-27T09:03:17+00:00" }, { "name": "lcobucci/jwt", @@ -2813,31 +2690,32 @@ }, { "name": "php-debugbar/php-debugbar", - "version": "v2.2.4", + "version": "v2.2.6", "source": { "type": "git", "url": "https://github.com/php-debugbar/php-debugbar.git", - "reference": "3146d04671f51f69ffec2a4207ac3bdcf13a9f35" + "reference": "abb9fa3c5c8dbe7efe03ddba56782917481de3e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/3146d04671f51f69ffec2a4207ac3bdcf13a9f35", - "reference": "3146d04671f51f69ffec2a4207ac3bdcf13a9f35", + "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/abb9fa3c5c8dbe7efe03ddba56782917481de3e8", + "reference": "abb9fa3c5c8dbe7efe03ddba56782917481de3e8", "shasum": "" }, "require": { - "php": "^8", + "php": "^8.1", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^4|^5|^6|^7" + "symfony/var-dumper": "^5.4|^6.4|^7.3|^8.0" }, "replace": { "maximebf/debugbar": "self.version" }, "require-dev": { "dbrekelmans/bdi": "^1", - "phpunit/phpunit": "^8|^9", + "phpunit/phpunit": "^10", + "symfony/browser-kit": "^6.0|7.0", "symfony/panther": "^1|^2.1", - "twig/twig": "^1.38|^2.7|^3.0" + "twig/twig": "^3.11.2" }, "suggest": { "kriswallsmith/assetic": "The best way to manage assets", @@ -2847,7 +2725,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "2.2-dev" } }, "autoload": { @@ -2880,9 +2758,9 @@ ], "support": { "issues": "https://github.com/php-debugbar/php-debugbar/issues", - "source": "https://github.com/php-debugbar/php-debugbar/tree/v2.2.4" + "source": "https://github.com/php-debugbar/php-debugbar/tree/v2.2.6" }, - "time": "2025-07-22T14:01:30+00:00" + "time": "2025-12-22T13:21:32+00:00" }, { "name": "php-tuf/php-tuf", @@ -2960,16 +2838,16 @@ }, { "name": "phpmailer/phpmailer", - "version": "v6.10.0", + "version": "v6.12.0", "source": { "type": "git", "url": "https://github.com/PHPMailer/PHPMailer.git", - "reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144" + "reference": "d1ac35d784bf9f5e61b424901d5a014967f15b12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144", - "reference": "bf74d75a1fde6beaa34a0ddae2ec5fce0f72a144", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/d1ac35d784bf9f5e61b424901d5a014967f15b12", + "reference": "d1ac35d784bf9f5e61b424901d5a014967f15b12", "shasum": "" }, "require": { @@ -3029,7 +2907,7 @@ "description": "PHPMailer is a full-featured email creation and transfer class for PHP", "support": { "issues": "https://github.com/PHPMailer/PHPMailer/issues", - "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.10.0" + "source": "https://github.com/PHPMailer/PHPMailer/tree/v6.12.0" }, "funding": [ { @@ -3037,7 +2915,7 @@ "type": "github" } ], - "time": "2025-04-24T15:19:31+00:00" + "time": "2025-10-15T16:49:08+00:00" }, { "name": "phpseclib/bcmath_compat", @@ -3310,22 +3188,27 @@ }, { "name": "psr/container", - "version": "1.1.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/php-fig/container.git", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", - "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", "shasum": "" }, "require": { "php": ">=7.4.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, "autoload": { "psr-4": { "Psr\\Container\\": "src/" @@ -3352,9 +3235,9 @@ ], "support": { "issues": "https://github.com/php-fig/container/issues", - "source": "https://github.com/php-fig/container/tree/1.1.2" + "source": "https://github.com/php-fig/container/tree/2.0.2" }, - "time": "2021-11-05T16:50:12+00:00" + "time": "2021-11-05T16:47:00+00:00" }, { "name": "psr/event-dispatcher", @@ -3515,16 +3398,16 @@ }, { "name": "psr/http-message", - "version": "1.1", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { @@ -3533,7 +3416,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -3548,7 +3431,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -3562,9 +3445,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2023-04-04T09:50:52+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "psr/link", @@ -3715,40 +3598,28 @@ }, { "name": "spomky-labs/cbor-php", - "version": "3.1.1", + "version": "3.2.3", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/cbor-php.git", - "reference": "5404f3e21cbe72f5cf612aa23db2b922fd2f43bf" + "reference": "dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/5404f3e21cbe72f5cf612aa23db2b922fd2f43bf", - "reference": "5404f3e21cbe72f5cf612aa23db2b922fd2f43bf", + "url": "https://api.github.com/repos/Spomky-Labs/cbor-php/zipball/dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32", + "reference": "dd6eb84e6d92f7b8bd0da56b4b4dd7235aed0c32", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13", + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", "ext-mbstring": "*", "php": ">=8.0" }, "require-dev": { - "deptrac/deptrac": "^3.0", - "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", "ext-json": "*", - "infection/infection": "^0.29", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.0|^2.0", - "phpstan/phpstan-beberlei-assert": "^1.0|^2.0", - "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", - "phpstan/phpstan-phpunit": "^1.0|^2.0", - "phpstan/phpstan-strict-rules": "^1.0|^2.0", - "phpunit/phpunit": "^10.1|^11.0|^12.0", - "rector/rector": "^1.0|^2.0", "roave/security-advisories": "dev-latest", - "symfony/var-dumper": "^6.0|^7.0", - "symplify/easy-coding-standard": "^12.0" + "symfony/error-handler": "^6.4|^7.1|^8.0", + "symfony/var-dumper": "^6.4|^7.1|^8.0" }, "suggest": { "ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags", @@ -3782,7 +3653,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/cbor-php/issues", - "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.1.1" + "source": "https://github.com/Spomky-Labs/cbor-php/tree/3.2.3" }, "funding": [ { @@ -3794,44 +3665,45 @@ "type": "patreon" } ], - "time": "2025-06-13T11:57:55+00:00" + "time": "2026-04-01T12:15:20+00:00" }, { "name": "spomky-labs/pki-framework", - "version": "1.3.0", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/Spomky-Labs/pki-framework.git", - "reference": "eced5b5ce70518b983ff2be486e902bbd15135ae" + "reference": "aa576cbd07128075bef97ac2f8af9854e67513d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/eced5b5ce70518b983ff2be486e902bbd15135ae", - "reference": "eced5b5ce70518b983ff2be486e902bbd15135ae", + "url": "https://api.github.com/repos/Spomky-Labs/pki-framework/zipball/aa576cbd07128075bef97ac2f8af9854e67513d8", + "reference": "aa576cbd07128075bef97ac2f8af9854e67513d8", "shasum": "" }, "require": { - "brick/math": "^0.10|^0.11|^0.12|^0.13", + "brick/math": "^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", "ext-mbstring": "*", - "php": ">=8.1" + "php": ">=8.1", + "psr/clock": "^1.0" }, "require-dev": { "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", "ext-gmp": "*", "ext-openssl": "*", - "infection/infection": "^0.28|^0.29", + "infection/infection": "^0.28|^0.29|^0.31|^0.32", "php-parallel-lint/php-parallel-lint": "^1.3", "phpstan/extension-installer": "^1.3|^2.0", "phpstan/phpstan": "^1.8|^2.0", "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", "phpstan/phpstan-phpunit": "^1.1|^2.0", "phpstan/phpstan-strict-rules": "^1.3|^2.0", - "phpunit/phpunit": "^10.1|^11.0|^12.0", + "phpunit/phpunit": "^10.1|^11.0|^12.0|^13.0", "rector/rector": "^1.0|^2.0", "roave/security-advisories": "dev-latest", - "symfony/string": "^6.4|^7.0", - "symfony/var-dumper": "^6.4|^7.0", - "symplify/easy-coding-standard": "^12.0" + "symfony/string": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0", + "symplify/easy-coding-standard": "^12.0|^13.0" }, "suggest": { "ext-bcmath": "For better performance (or GMP)", @@ -3891,7 +3763,7 @@ ], "support": { "issues": "https://github.com/Spomky-Labs/pki-framework/issues", - "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.3.0" + "source": "https://github.com/Spomky-Labs/pki-framework/tree/1.4.2" }, "funding": [ { @@ -3903,51 +3775,51 @@ "type": "patreon" } ], - "time": "2025-06-13T08:35:04+00:00" + "time": "2026-03-23T22:56:56+00:00" }, { "name": "symfony/console", - "version": "v6.4.25", + "version": "v7.4.13", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "273fd29ff30ba0a88ca5fb83f7cf1ab69306adae" + "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/273fd29ff30ba0a88ca5fb83f7cf1ab69306adae", - "reference": "273fd29ff30ba0a88ca5fb83f7cf1ab69306adae", + "url": "https://api.github.com/repos/symfony/console/zipball/85095d2573eaefaf35e40b9513a9bf09f72cd217", + "reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" + "symfony/string": "^7.2|^8.0" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/event-dispatcher": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/lock": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -3981,7 +3853,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.25" + "source": "https://github.com/symfony/console/tree/v7.4.13" }, "funding": [ { @@ -4001,20 +3873,20 @@ "type": "tidelift" } ], - "time": "2025-08-22T10:21:53+00:00" + "time": "2026-05-24T08:56:14+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b", + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b", "shasum": "" }, "require": { @@ -4027,7 +3899,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -4052,7 +3924,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0" }, "funding": [ { @@ -4063,40 +3935,47 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-04-13T15:52:40+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.24", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "30fd0b3cf0e972e82636038ce4db0e4fe777112c" + "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/30fd0b3cf0e972e82636038ce4db0e4fe777112c", - "reference": "30fd0b3cf0e972e82636038ce4db0e4fe777112c", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa", + "reference": "8dd79d8af777ee6cba2fd4d98da6ffb839f3c0fa", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/polyfill-php85": "^1.32", + "symfony/var-dumper": "^6.4|^7.0|^8.0" }, "conflict": { "symfony/deprecation-contracts": "<2.5", "symfony/http-kernel": "<6.4" }, "require-dev": { + "symfony/console": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^5.4|^6.0|^7.0" + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/serializer": "^6.4|^7.0|^8.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -4127,7 +4006,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.24" + "source": "https://github.com/symfony/error-handler/tree/v7.4.8" }, "funding": [ { @@ -4147,24 +4026,24 @@ "type": "tidelift" } ], - "time": "2025-07-24T08:25:04+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/http-client", - "version": "v6.4.25", + "version": "v7.4.13", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "b8e9dce2d8acba3c32af467bb58e0c3656886181" + "reference": "e8a112b8415707265a7e614278136a9d92989a6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/b8e9dce2d8acba3c32af467bb58e0c3656886181", - "reference": "b8e9dce2d8acba3c32af467bb58e0c3656886181", + "url": "https://api.github.com/repos/symfony/http-client/zipball/e8a112b8415707265a7e614278136a9d92989a6a", + "reference": "e8a112b8415707265a7e614278136a9d92989a6a", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-client-contracts": "~3.4.4|^3.5.2", @@ -4172,8 +4051,10 @@ "symfony/service-contracts": "^2.5|^3" }, "conflict": { + "amphp/amp": "<2.5", + "amphp/socket": "<1.1", "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.3" + "symfony/http-foundation": "<6.4" }, "provide": { "php-http/async-client-implementation": "*", @@ -4182,19 +4063,20 @@ "symfony/http-client-implementation": "3.0" }, "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", - "amphp/socket": "^1.1", + "amphp/http-client": "^4.2.1|^5.0", + "amphp/http-tunnel": "^1.0|^2.0", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0" + "symfony/amphp-http-client-meta": "^1.0|^2.0", + "symfony/cache": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/messenger": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/rate-limiter": "^6.4|^7.0|^8.0", + "symfony/stopwatch": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -4225,7 +4107,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.25" + "source": "https://github.com/symfony/http-client/tree/v7.4.13" }, "funding": [ { @@ -4245,20 +4127,20 @@ "type": "tidelift" } ], - "time": "2025-08-27T07:01:16+00:00" + "time": "2026-05-24T09:57:54+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "75d7043853a42837e68111812f4d964b01e5101c" + "reference": "4a2d00c37651c0bdc2b9e1c773487a8bf4edb12d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", - "reference": "75d7043853a42837e68111812f4d964b01e5101c", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/4a2d00c37651c0bdc2b9e1c773487a8bf4edb12d", + "reference": "4a2d00c37651c0bdc2b9e1c773487a8bf4edb12d", "shasum": "" }, "require": { @@ -4271,7 +4153,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -4307,7 +4189,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.7.0" }, "funding": [ { @@ -4318,40 +4200,42 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-29T11:18:49+00:00" + "time": "2026-03-06T13:17:50+00:00" }, { "name": "symfony/ldap", - "version": "v6.4.24", + "version": "v7.4.10", "source": { "type": "git", "url": "https://github.com/symfony/ldap.git", - "reference": "2eda8a14000f804d55adfa189f148f6b1cb020e1" + "reference": "bba9e535d29c15bd6842bf85bc341debfbb4bcb3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/ldap/zipball/2eda8a14000f804d55adfa189f148f6b1cb020e1", - "reference": "2eda8a14000f804d55adfa189f148f6b1cb020e1", + "url": "https://api.github.com/repos/symfony/ldap/zipball/bba9e535d29c15bd6842bf85bc341debfbb4bcb3", + "reference": "bba9e535d29c15bd6842bf85bc341debfbb4bcb3", "shasum": "" }, "require": { "ext-ldap": "*", - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/options-resolver": "^5.4|^6.0|^7.0" + "php": ">=8.2", + "symfony/options-resolver": "^7.3|^8.0" }, "conflict": { - "symfony/options-resolver": "<5.4", - "symfony/security-core": "<5.4" + "symfony/security-core": "<6.4" }, "require-dev": { - "symfony/security-core": "^5.4|^6.0|^7.0", - "symfony/security-http": "^5.4|^6.0|^7.0" + "symfony/security-core": "^6.4|^7.0|^8.0", + "symfony/security-http": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -4383,7 +4267,7 @@ "ldap" ], "support": { - "source": "https://github.com/symfony/ldap/tree/v6.4.24" + "source": "https://github.com/symfony/ldap/tree/v7.4.10" }, "funding": [ { @@ -4403,24 +4287,24 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2026-05-04T13:25:50+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.4.25", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "d28e7e2db8a73e9511df892d36445f61314bbebe" + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d28e7e2db8a73e9511df892d36445f61314bbebe", - "reference": "d28e7e2db8a73e9511df892d36445f61314bbebe", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", + "reference": "2888fcdc4dc2fd5f7c7397be78631e8af12e02b4", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3" }, "type": "library", @@ -4454,7 +4338,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.25" + "source": "https://github.com/symfony/options-resolver/tree/v7.4.8" }, "funding": [ { @@ -4474,20 +4358,20 @@ "type": "tidelift" } ], - "time": "2025-08-04T17:06:28+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + "reference": "141046a8f9477948ff284fa65be2095baafb94f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", - "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/141046a8f9477948ff284fa65be2095baafb94f2", + "reference": "141046a8f9477948ff284fa65be2095baafb94f2", "shasum": "" }, "require": { @@ -4537,7 +4421,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.37.0" }, "funding": [ { @@ -4557,111 +4441,27 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { - "name": "symfony/polyfill-iconv", - "version": "v1.33.0", + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.38.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "5f3b930437ae03ae5dff61269024d8ea1b3774aa" + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "e9247d281d694a5120554d9afaf54e070e88a603" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/5f3b930437ae03ae5dff61269024d8ea1b3774aa", - "reference": "5f3b930437ae03ae5dff61269024d8ea1b3774aa", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603", + "reference": "e9247d281d694a5120554d9afaf54e070e88a603", "shasum": "" }, "require": { "php": ">=7.2" }, - "provide": { - "ext-iconv": "*" - }, "suggest": { - "ext-iconv": "For best performance" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Iconv\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Iconv extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "iconv", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-iconv/tree/v1.33.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-17T14:58:18+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "v1.33.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", - "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "suggest": { - "ext-intl": "For best performance" + "ext-intl": "For best performance" }, "type": "library", "extra": { @@ -4703,7 +4503,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1" }, "funding": [ { @@ -4723,20 +4523,20 @@ "type": "tidelift" } ], - "time": "2025-06-27T09:58:17+00:00" + "time": "2026-05-26T05:58:03+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.33.0", + "version": "v1.38.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "3833d7255cc303546435cb650316bff708a1c75c" + "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", - "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b", + "reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b", "shasum": "" }, "require": { @@ -4788,7 +4588,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0" }, "funding": [ { @@ -4808,20 +4608,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-05-25T13:48:31+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.38.2", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", + "reference": "d3d318bad5e7a1bfbd026009c8bfb8d8f99ae6b6", "shasum": "" }, "require": { @@ -4873,7 +4673,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.2" }, "funding": [ { @@ -4893,20 +4693,20 @@ "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2026-05-27T06:59:30+00:00" }, { - "name": "symfony/polyfill-php83", - "version": "v1.33.0", + "name": "symfony/polyfill-php85", + "version": "v1.38.1", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" + "url": "https://github.com/symfony/polyfill-php85.git", + "reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", - "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", + "reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", "shasum": "" }, "require": { @@ -4924,7 +4724,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php83\\": "" + "Symfony\\Polyfill\\Php85\\": "" }, "classmap": [ "Resources/stubs" @@ -4944,7 +4744,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -4953,7 +4753,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php85/tree/v1.38.1" }, "funding": [ { @@ -4973,20 +4773,20 @@ "type": "tidelift" } ], - "time": "2025-07-08T02:45:35+00:00" + "time": "2026-05-26T02:25:22+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.33.0", + "version": "v1.37.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2" + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/21533be36c24be3f4b1669c4725c7d1d2bab4ae2", - "reference": "21533be36c24be3f4b1669c4725c7d1d2bab4ae2", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/26dfec253c4cf3e51b541b52ddf7e42cb0908e94", + "reference": "26dfec253c4cf3e51b541b52ddf7e42cb0908e94", "shasum": "" }, "require": { @@ -5036,7 +4836,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.37.0" }, "funding": [ { @@ -5056,20 +4856,20 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2026-04-10T16:19:22+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d25d82433a80eba6aa0e6c24b61d7370d99e444a", + "reference": "d25d82433a80eba6aa0e6c24b61d7370d99e444a", "shasum": "" }, "require": { @@ -5087,7 +4887,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -5123,7 +4923,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.7.0" }, "funding": [ { @@ -5134,31 +4934,36 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2025-04-25T09:37:31+00:00" + "time": "2026-03-28T09:44:51+00:00" }, { "name": "symfony/string", - "version": "v6.4.25", + "version": "v7.4.13", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "7cdec7edfaf2cdd9c18901e35bcf9653d6209ff1" + "reference": "961683010db3b27ec6ebcd7308e6e1ee8fa7ffde" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/7cdec7edfaf2cdd9c18901e35bcf9653d6209ff1", - "reference": "7cdec7edfaf2cdd9c18901e35bcf9653d6209ff1", + "url": "https://api.github.com/repos/symfony/string/zipball/961683010db3b27ec6ebcd7308e6e1ee8fa7ffde", + "reference": "961683010db3b27ec6ebcd7308e6e1ee8fa7ffde", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-grapheme": "~1.33", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, @@ -5166,11 +4971,11 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", + "symfony/emoji": "^7.1|^8.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/intl": "^6.4|^7.0|^8.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/var-exporter": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -5209,7 +5014,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.25" + "source": "https://github.com/symfony/string/tree/v7.4.13" }, "funding": [ { @@ -5229,20 +5034,20 @@ "type": "tidelift" } ], - "time": "2025-08-22T12:33:20+00:00" + "time": "2026-05-23T15:23:29+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/0ab302977a952b42fd51475c4ebac81f8da0a95d", + "reference": "0ab302977a952b42fd51475c4ebac81f8da0a95d", "shasum": "" }, "require": { @@ -5255,7 +5060,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -5291,7 +5096,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.7.0" }, "funding": [ { @@ -5302,25 +5107,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-27T08:32:26+00:00" + "time": "2026-01-05T13:30:16+00:00" }, { "name": "symfony/uid", - "version": "v6.4.24", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "17da16a750541a42cf2183935e0f6008316c23f7" + "reference": "6b973c385f00341b246f697d82dc01a09107acdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/17da16a750541a42cf2183935e0f6008316c23f7", - "reference": "17da16a750541a42cf2183935e0f6008316c23f7", + "url": "https://api.github.com/repos/symfony/uid/zipball/6b973c385f00341b246f697d82dc01a09107acdd", + "reference": "6b973c385f00341b246f697d82dc01a09107acdd", "shasum": "" }, "require": { @@ -5365,7 +5174,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.24" + "source": "https://github.com/symfony/uid/tree/v6.4.32" }, "funding": [ { @@ -5385,20 +5194,20 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2025-12-23T15:07:59+00:00" }, { "name": "symfony/validator", - "version": "v6.4.25", + "version": "v6.4.37", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "9352177c0e937793423053846f80bee805552324" + "reference": "72cfcf7925746d9950bbdab1362f6bda3b4046cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/9352177c0e937793423053846f80bee805552324", - "reference": "9352177c0e937793423053846f80bee805552324", + "url": "https://api.github.com/repos/symfony/validator/zipball/72cfcf7925746d9950bbdab1362f6bda3b4046cf", + "reference": "72cfcf7925746d9950bbdab1362f6bda3b4046cf", "shasum": "" }, "require": { @@ -5466,7 +5275,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.25" + "source": "https://github.com/symfony/validator/tree/v6.4.37" }, "funding": [ { @@ -5486,37 +5295,36 @@ "type": "tidelift" } ], - "time": "2025-08-27T11:31:57+00:00" + "time": "2026-04-29T06:33:37+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.25", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "c6cd92486e9fc32506370822c57bc02353a5a92c" + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c6cd92486e9fc32506370822c57bc02353a5a92c", - "reference": "c6cd92486e9fc32506370822c57bc02353a5a92c", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9510c3966f749a1d1ff0059e1eabef6cc621e7fd", + "reference": "9510c3966f749a1d1ff0059e1eabef6cc621e7fd", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/console": "<5.4" + "symfony/console": "<6.4" }, "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^6.3|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/uid": "^5.4|^6.0|^7.0", - "twig/twig": "^2.13|^3.0.4" + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0", + "symfony/uid": "^6.4|^7.0|^8.0", + "twig/twig": "^3.12" }, "bin": [ "Resources/bin/var-dump-server" @@ -5554,7 +5362,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.25" + "source": "https://github.com/symfony/var-dumper/tree/v7.4.8" }, "funding": [ { @@ -5574,20 +5382,20 @@ "type": "tidelift" } ], - "time": "2025-08-13T09:41:44+00:00" + "time": "2026-03-30T13:44:50+00:00" }, { "name": "symfony/web-link", - "version": "v6.4.24", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/web-link.git", - "reference": "75ffbb304f26a716969863328c8c6a11eadcfa5a" + "reference": "636d5e34cd5c4a2538b02ba48a3c02989bfdf06b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-link/zipball/75ffbb304f26a716969863328c8c6a11eadcfa5a", - "reference": "75ffbb304f26a716969863328c8c6a11eadcfa5a", + "url": "https://api.github.com/repos/symfony/web-link/zipball/636d5e34cd5c4a2538b02ba48a3c02989bfdf06b", + "reference": "636d5e34cd5c4a2538b02ba48a3c02989bfdf06b", "shasum": "" }, "require": { @@ -5630,254 +5438,75 @@ "homepage": "https://symfony.com", "keywords": [ "dns-prefetch", - "http", - "http2", - "link", - "performance", - "prefetch", - "preload", - "prerender", - "psr13", - "push" - ], - "support": { - "source": "https://github.com/symfony/web-link/tree/v6.4.24" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2025-07-10T08:14:14+00:00" - }, - { - "name": "symfony/yaml", - "version": "v6.4.41", - "source": { - "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "e8fdf3408c85806198d5826e604ffc6830d33152" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/e8fdf3408c85806198d5826e604ffc6830d33152", - "reference": "e8fdf3408c85806198d5826e604ffc6830d33152", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "symfony/console": "<5.4" - }, - "require-dev": { - "symfony/console": "^5.4|^6.0|^7.0" - }, - "bin": [ - "Resources/bin/yaml-lint" - ], - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Loads and dumps YAML files", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.41" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-05-25T06:03:23+00:00" - }, - { - "name": "tobscure/json-api", - "version": "dev-joomla-backports", - "source": { - "type": "git", - "url": "https://github.com/joomla-backports/json-api-php.git", - "reference": "6ce73102280c9c70b41e3407d2504279fa07d158" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/joomla-backports/json-api-php/zipball/6ce73102280c9c70b41e3407d2504279fa07d158", - "reference": "6ce73102280c9c70b41e3407d2504279fa07d158", - "shasum": "" - }, - "require": { - "php": "^7.0 || ^8.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0 || ^7.0 || ^8.0 || ^9.0", - "yoast/phpunit-polyfills": "^1.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "psr-4": { - "Tobscure\\JsonApi\\": "src/" - } - }, - "autoload-dev": { - "psr-4": { - "Tobscure\\Tests\\JsonApi\\": "tests/" - } - }, - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Toby Zerner", - "email": "toby.zerner@gmail.com" - } - ], - "description": "JSON-API responses in PHP", - "keywords": [ - "api", - "json", - "jsonapi", - "standard" - ], - "time": "2025-08-17T07:17:47+00:00" - }, - { - "name": "typo3/phar-stream-wrapper", - "version": "v3.1.8", - "source": { - "type": "git", - "url": "https://github.com/TYPO3/phar-stream-wrapper.git", - "reference": "a931b28f422a60052db85c0a84a05a366453b2c0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/TYPO3/phar-stream-wrapper/zipball/a931b28f422a60052db85c0a84a05a366453b2c0", - "reference": "a931b28f422a60052db85c0a84a05a366453b2c0", - "shasum": "" - }, - "require": { - "ext-json": "*", - "php": "^7.0 || ~8.0 || ~8.1 || ~8.2 || ~8.3" - }, - "require-dev": { - "ext-xdebug": "*", - "phpspec/prophecy": "^1.10", - "symfony/phpunit-bridge": "^5.1" - }, - "suggest": { - "ext-fileinfo": "For PHP builtin file type guessing, otherwise uses internal processing" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "v3.x-dev" - } - }, - "autoload": { - "psr-4": { - "TYPO3\\PharStreamWrapper\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Interceptors for PHP's native phar:// stream handling", - "homepage": "https://typo3.org/", - "keywords": [ - "phar", - "php", - "security", - "stream-wrapper" + "http", + "http2", + "link", + "performance", + "prefetch", + "preload", + "prerender", + "psr13", + "push" ], "support": { - "issues": "https://github.com/TYPO3/phar-stream-wrapper/issues", - "source": "https://github.com/TYPO3/phar-stream-wrapper/tree/v3.1.8" + "source": "https://github.com/symfony/web-link/tree/v6.4.32" }, - "time": "2024-12-09T23:06:33+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-01T13:45:34+00:00" }, { - "name": "voku/portable-ascii", - "version": "2.0.3", + "name": "symfony/yaml", + "version": "v6.4.41", "source": { "type": "git", - "url": "https://github.com/voku/portable-ascii.git", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" + "url": "https://github.com/symfony/yaml.git", + "reference": "e8fdf3408c85806198d5826e604ffc6830d33152" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", - "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e8fdf3408c85806198d5826e604ffc6830d33152", + "reference": "e8fdf3408c85806198d5826e604ffc6830d33152", "shasum": "" }, "require": { - "php": ">=7.0.0" + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8" }, - "require-dev": { - "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0" + "conflict": { + "symfony/console": "<5.4" }, - "suggest": { - "ext-intl": "Use Intl for transliterator_transliterate() support" + "require-dev": { + "symfony/console": "^5.4|^6.0|^7.0" }, + "bin": [ + "Resources/bin/yaml-lint" + ], "type": "library", "autoload": { "psr-4": { - "voku\\": "src/voku/" - } + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -5885,125 +5514,94 @@ ], "authors": [ { - "name": "Lars Moelleken", - "homepage": "https://www.moelleken.org/" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", - "homepage": "https://github.com/voku/portable-ascii", - "keywords": [ - "ascii", - "clean", - "php" - ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", "support": { - "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.3" + "source": "https://github.com/symfony/yaml/tree/v6.4.41" }, "funding": [ { - "url": "https://www.paypal.me/moelleken", + "url": "https://symfony.com/sponsor", "type": "custom" }, { - "url": "https://github.com/voku", + "url": "https://github.com/fabpot", "type": "github" }, { - "url": "https://opencollective.com/portable-ascii", - "type": "open_collective" - }, - { - "url": "https://www.patreon.com/voku", - "type": "patreon" + "url": "https://github.com/nicolas-grekas", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-11-21T01:49:47+00:00" + "time": "2026-05-25T06:03:23+00:00" }, { - "name": "voku/portable-utf8", - "version": "dev-joomla-5.3", + "name": "tobscure/json-api", + "version": "dev-joomla-backports", "source": { "type": "git", - "url": "https://github.com/joomla-backports/portable-utf8.git", - "reference": "eeb3d9e390411cd31af808caa7f7de337ea3a24c" + "url": "https://github.com/joomla-backports/json-api-php.git", + "reference": "6ce73102280c9c70b41e3407d2504279fa07d158" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-backports/portable-utf8/zipball/eeb3d9e390411cd31af808caa7f7de337ea3a24c", - "reference": "eeb3d9e390411cd31af808caa7f7de337ea3a24c", + "url": "https://api.github.com/repos/joomla-backports/json-api-php/zipball/6ce73102280c9c70b41e3407d2504279fa07d158", + "reference": "6ce73102280c9c70b41e3407d2504279fa07d158", "shasum": "" }, "require": { - "php": ">=7.0.0", - "symfony/polyfill-iconv": "~1.0", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php72": "~1.0", - "voku/portable-ascii": "~2.0.0" + "php": "^7.0 || ^8.0" }, "require-dev": { - "phpstan/phpstan": "1.9.*@dev", - "phpstan/phpstan-strict-rules": "1.4.*@dev", - "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0", - "thecodingmachine/phpstan-strict-rules": "1.0.*@dev", - "voku/phpstan-rules": "3.1.*@dev" - }, - "suggest": { - "ext-ctype": "Use Ctype for e.g. hexadecimal digit detection", - "ext-fileinfo": "Use Fileinfo for better binary file detection", - "ext-iconv": "Use iconv for best performance", - "ext-intl": "Use Intl for best performance", - "ext-json": "Use JSON for string detection", - "ext-mbstring": "Use Mbstring for best performance" + "phpunit/phpunit": "^6.0 || ^7.0 || ^8.0 || ^9.0", + "yoast/phpunit-polyfills": "^1.0" }, + "default-branch": true, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "psr-4": { - "voku\\": "src/voku/" - }, - "files": [ - "bootstrap.php" - ] + "Tobscure\\JsonApi\\": "src/" + } }, "autoload-dev": { "psr-4": { - "voku\\tests\\": "tests/" + "Tobscure\\Tests\\JsonApi\\": "tests/" } }, "license": [ - "(Apache-2.0 or GPL-2.0)" + "MIT" ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Hamid Sarfraz", - "homepage": "http://pageconfig.com/" - }, - { - "name": "Lars Moelleken", - "homepage": "http://www.moelleken.org/" + "name": "Toby Zerner", + "email": "toby.zerner@gmail.com" } ], - "description": "Portable UTF-8 library - performance optimized (unicode) string functions for php.", - "homepage": "https://github.com/voku/portable-utf8", + "description": "JSON-API responses in PHP", "keywords": [ - "clean", - "php", - "unicode", - "utf", - "utf-8", - "utf8" + "api", + "json", + "jsonapi", + "standard" ], - "time": "2024-11-20T09:42:04+00:00" + "time": "2025-08-17T07:17:47+00:00" }, { "name": "wamania/php-stemmer", @@ -6056,43 +5654,32 @@ }, { "name": "web-auth/cose-lib", - "version": "4.4.2", + "version": "4.5.2", "source": { "type": "git", "url": "https://github.com/web-auth/cose-lib.git", - "reference": "a93b61c48fb587855f64a9ec11ad7b60e867cb15" + "reference": "5b38660f90070a8e45f3dbc9528ade3b608dd77d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/a93b61c48fb587855f64a9ec11ad7b60e867cb15", - "reference": "a93b61c48fb587855f64a9ec11ad7b60e867cb15", + "url": "https://api.github.com/repos/web-auth/cose-lib/zipball/5b38660f90070a8e45f3dbc9528ade3b608dd77d", + "reference": "5b38660f90070a8e45f3dbc9528ade3b608dd77d", "shasum": "" }, "require": { - "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13", + "brick/math": "^0.9|^0.10|^0.11|^0.12|^0.13|^0.14|^0.15|^0.16|^0.17", "ext-json": "*", "ext-openssl": "*", "php": ">=8.1", "spomky-labs/pki-framework": "^1.0" }, "require-dev": { - "deptrac/deptrac": "^3.0", - "ekino/phpstan-banned-code": "^1.0|^2.0|^3.0", - "infection/infection": "^0.29", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.7|^2.0", - "phpstan/phpstan-deprecation-rules": "^1.0|^2.0", - "phpstan/phpstan-phpunit": "^1.1|^2.0", - "phpstan/phpstan-strict-rules": "^1.0|^2.0", - "phpunit/phpunit": "^10.1|^11.0|^12.0", - "rector/rector": "^2.0", - "symfony/phpunit-bridge": "^6.4|^7.0", - "symplify/easy-coding-standard": "^12.0" + "spomky-labs/cbor-php": "^3.2.2" }, "suggest": { "ext-bcmath": "For better performance, please install either GMP (recommended) or BCMath extension", - "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension" + "ext-gmp": "For better performance, please install either GMP (recommended) or BCMath extension", + "spomky-labs/cbor-php": "For COSE Signature support" }, "type": "library", "autoload": { @@ -6122,7 +5709,7 @@ ], "support": { "issues": "https://github.com/web-auth/cose-lib/issues", - "source": "https://github.com/web-auth/cose-lib/tree/4.4.2" + "source": "https://github.com/web-auth/cose-lib/tree/4.5.2" }, "funding": [ { @@ -6134,7 +5721,7 @@ "type": "patreon" } ], - "time": "2025-08-14T20:33:29+00:00" + "time": "2026-05-03T09:49:50+00:00" }, { "name": "web-auth/metadata-service", @@ -6392,64 +5979,6 @@ ], "time": "2026-06-06T16:30:13+00:00" }, - { - "name": "webmozart/assert", - "version": "1.11.0", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", - "shasum": "" - }, - "require": { - "ext-ctype": "*", - "php": "^7.2 || ^8.0" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.10-dev" - } - }, - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" - }, - "time": "2022-06-03T18:03:27+00:00" - }, { "name": "willdurand/negotiation", "version": "3.1.0", @@ -6574,28 +6103,29 @@ }, { "name": "composer/pcre", - "version": "3.3.2", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", - "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "url": "https://api.github.com/repos/composer/pcre/zipball/d5a341b3fb61f3001970940afb1d332968a183ed", + "reference": "d5a341b3fb61f3001970940afb1d332968a183ed", "shasum": "" }, "require": { "php": "^7.4 || ^8.0" }, "conflict": { - "phpstan/phpstan": "<1.11.10" + "phpstan/phpstan": "<2.2.2" }, "require-dev": { - "phpstan/phpstan": "^1.12 || ^2", - "phpstan/phpstan-strict-rules": "^1 || ^2", - "phpunit/phpunit": "^8 || ^9" + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^9" }, "type": "library", "extra": { @@ -6633,7 +6163,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.2" + "source": "https://github.com/composer/pcre/tree/3.4.0" }, "funding": [ { @@ -6643,13 +6173,9 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2024-11-12T16:29:46+00:00" + "time": "2026-06-07T11:47:49+00:00" }, { "name": "composer/semver", @@ -6864,6 +6390,75 @@ ], "time": "2022-12-30T00:23:10+00:00" }, + { + "name": "ergebnis/agent-detector", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/ergebnis/agent-detector.git", + "reference": "e211f17928c8b95a51e06040792d57f5462fb271" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ergebnis/agent-detector/zipball/e211f17928c8b95a51e06040792d57f5462fb271", + "reference": "e211f17928c8b95a51e06040792d57f5462fb271", + "shasum": "" + }, + "require": { + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0 || ~8.6.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.51.0", + "ergebnis/license": "^2.7.0", + "ergebnis/php-cs-fixer-config": "^6.60.2", + "ergebnis/phpstan-rules": "^2.13.1", + "ergebnis/phpunit-slow-test-detector": "^2.24.0", + "ergebnis/rector-rules": "^1.18.1", + "fakerphp/faker": "^1.24.1", + "infection/infection": "^0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.54", + "phpstan/phpstan-deprecation-rules": "^2.0.4", + "phpstan/phpstan-phpunit": "^2.0.16", + "phpstan/phpstan-strict-rules": "^2.0.10", + "phpunit/phpunit": "^9.6.34", + "rector/rector": "^2.4.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.2-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + } + }, + "autoload": { + "psr-4": { + "Ergebnis\\AgentDetector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" + } + ], + "description": "Provides a detector for detecting the presence of an agent.", + "homepage": "https://github.com/ergebnis/agent-detector", + "support": { + "issues": "https://github.com/ergebnis/agent-detector/issues", + "security": "https://github.com/ergebnis/agent-detector/blob/main/.github/SECURITY.md", + "source": "https://github.com/ergebnis/agent-detector" + }, + "time": "2026-05-07T08:19:07+00:00" + }, { "name": "evenement/evenement", "version": "v3.0.2", @@ -6974,22 +6569,23 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.88.0", + "version": "v3.95.10", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "f23469674ae50d40e398bfff8018911a2a2b0dbe" + "reference": "93e1ab3e1f153024bd3ab23c8a349556063c6f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/f23469674ae50d40e398bfff8018911a2a2b0dbe", - "reference": "f23469674ae50d40e398bfff8018911a2a2b0dbe", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/93e1ab3e1f153024bd3ab23c8a349556063c6f17", + "reference": "93e1ab3e1f153024bd3ab23c8a349556063c6f17", "shasum": "" }, "require": { "clue/ndjson-react": "^1.3", "composer/semver": "^3.4", "composer/xdebug-handler": "^3.0.5", + "ergebnis/agent-detector": "^1.2", "ext-filter": "*", "ext-hash": "*", "ext-json": "*", @@ -6998,34 +6594,34 @@ "php": "^7.4 || ^8.0", "react/child-process": "^0.6.6", "react/event-loop": "^1.5", - "react/promise": "^3.3", "react/socket": "^1.16", "react/stream": "^1.4", - "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", - "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0", - "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0", - "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0", - "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0", - "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0", - "symfony/polyfill-mbstring": "^1.33", - "symfony/polyfill-php80": "^1.33", - "symfony/polyfill-php81": "^1.33", - "symfony/polyfill-php84": "^1.33", - "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2", - "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0" + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0 || ^9.0", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.37", + "symfony/polyfill-php80": "^1.37", + "symfony/polyfill-php81": "^1.37", + "symfony/polyfill-php84": "^1.37", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" }, "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.7", - "infection/infection": "^0.31.0", - "justinrainbow/json-schema": "^6.5", - "keradus/cli-executor": "^2.2", + "facile-it/paraunit": "^1.3.1 || ^2.11.0", + "infection/infection": "^0.32.7", + "justinrainbow/json-schema": "^6.9.0", + "keradus/cli-executor": "^2.3", "mikey179/vfsstream": "^1.6.12", - "php-coveralls/php-coveralls": "^2.8", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34", - "symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2", - "symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2" + "php-coveralls/php-coveralls": "^2.9.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.8", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.8", + "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.55", + "symfony/polyfill-php85": "^1.38", + "symfony/var-dumper": "^5.4.48 || ^6.4.36 || ^7.4.8 || ^8.1.0", + "symfony/yaml": "^5.4.53 || ^6.4.41 || ^7.4.13 || ^8.1.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -7040,7 +6636,7 @@ "PhpCsFixer\\": "src/" }, "exclude-from-classmap": [ - "src/Fixer/Internal/*" + "src/**/Internal/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -7066,7 +6662,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.88.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.10" }, "funding": [ { @@ -7074,43 +6670,37 @@ "type": "github" } ], - "time": "2025-09-24T21:31:42+00:00" + "time": "2026-06-19T14:45:22+00:00" }, { "name": "joomla/mediawiki", - "version": "3.0.1", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/joomla-framework/mediawiki-api.git", - "reference": "9db43585a71148b0168e1758c298e09e31c6fef6" + "reference": "34f5b81eb61586938df86388fee2236f8fbc7131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/mediawiki-api/zipball/9db43585a71148b0168e1758c298e09e31c6fef6", - "reference": "9db43585a71148b0168e1758c298e09e31c6fef6", + "url": "https://api.github.com/repos/joomla-framework/mediawiki-api/zipball/34f5b81eb61586938df86388fee2236f8fbc7131", + "reference": "34f5b81eb61586938df86388fee2236f8fbc7131", "shasum": "" }, "require": { - "joomla/http": "^3.0", - "joomla/registry": "^3.0", - "joomla/uri": "^3.0", - "php": "^8.1.0" + "joomla/http": "^4.0", + "joomla/registry": "^4.0", + "joomla/uri": "^4.0", + "php": "^8.3.0" }, "require-dev": { "ext-simplexml": "*", - "joomla/test": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", + "joomla/test": "^4.0", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpunit/phpunit": "^12.2.6", "squizlabs/php_codesniffer": "^3.7.2" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-2.0-dev": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Mediawiki\\": "src/" @@ -7129,48 +6719,39 @@ ], "support": { "issues": "https://github.com/joomla-framework/mediawiki-api/issues", - "source": "https://github.com/joomla-framework/mediawiki-api/tree/3.0.1" + "source": "https://github.com/joomla-framework/mediawiki-api/tree/4.0.1" }, - "time": "2025-07-11T23:18:33+00:00" + "time": "2025-08-06T10:10:33+00:00" }, { "name": "joomla/test", - "version": "3.0.4", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/joomla-framework/test.git", - "reference": "184bc36c0abeb4fa9471be472ecd5480125f1530" + "reference": "cfc3ca98f363dc76c4e3cf7a0cd089eeb93e2480" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/joomla-framework/test/zipball/184bc36c0abeb4fa9471be472ecd5480125f1530", - "reference": "184bc36c0abeb4fa9471be472ecd5480125f1530", + "url": "https://api.github.com/repos/joomla-framework/test/zipball/cfc3ca98f363dc76c4e3cf7a0cd089eeb93e2480", + "reference": "cfc3ca98f363dc76c4e3cf7a0cd089eeb93e2480", "shasum": "" }, "require": { - "php": "^8.1.0" - }, - "conflict": { - "joomla/database": "<2.0" + "php": "^8.3.0" }, "require-dev": { - "joomla/database": "^3.0", - "phpstan/phpstan": "1.12.27", - "phpstan/phpstan-deprecation-rules": "1.2.1", - "phpunit/phpunit": "^9.5.28", - "squizlabs/php_codesniffer": "^3.7.2" + "joomla/database": "^4.0", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-deprecation-rules": "2.0.3", + "phpunit/phpunit": "^12.0", + "squizlabs/php_codesniffer": "^3.10.2" }, "suggest": { "joomla/database": "To use the database test case, install joomla/database", "phpunit/phpunit": "To use the database test case, install phpunit/phpunit" }, "type": "joomla-package", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev", - "dev-3.x-dev": "3.0-dev" - } - }, "autoload": { "psr-4": { "Joomla\\Test\\": "src/" @@ -7191,9 +6772,9 @@ ], "support": { "issues": "https://github.com/joomla-framework/test/issues", - "source": "https://github.com/joomla-framework/test/tree/3.0.4" + "source": "https://github.com/joomla-framework/test/tree/4.0.1" }, - "time": "2025-10-17T08:19:16+00:00" + "time": "2025-10-17T08:21:47+00:00" }, { "name": "myclabs/deep-copy", @@ -7257,16 +6838,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.6.1", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", - "reference": "f103601b29efebd7ff4a1ca7b3eeea9e3336a2a2", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { @@ -7309,9 +6890,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2025-08-13T20:13:15+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "phar-io/manifest", @@ -7433,16 +7014,11 @@ }, { "name": "phpstan/phpstan", - "version": "2.1.29", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan-phar-composer-source.git", - "reference": "git" - }, + "version": "2.2.2", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/d618573eed4a1b6b75e37b2e0b65ac65c885d88e", - "reference": "d618573eed4a1b6b75e37b2e0b65ac65c885d88e", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e5cc34d491a90e79c216d824f60fe21fd4d93bd6", + "reference": "e5cc34d491a90e79c216d824f60fe21fd4d93bd6", "shasum": "" }, "require": { @@ -7465,6 +7041,17 @@ "license": [ "MIT" ], + "authors": [ + { + "name": "Ondřej Mirtes" + }, + { + "name": "Markus Staab" + }, + { + "name": "Vincent Langlet" + } + ], "description": "PHPStan - PHP Static Analysis Tool", "keywords": [ "dev", @@ -7487,25 +7074,25 @@ "type": "github" } ], - "time": "2025-09-25T06:58:18+00:00" + "time": "2026-06-05T09:00:01+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", - "reference": "468e02c9176891cc901143da118f09dc9505fc2f" + "reference": "6b5571001a7f04fa0422254c30a0017ec2f2cacc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/468e02c9176891cc901143da118f09dc9505fc2f", - "reference": "468e02c9176891cc901143da118f09dc9505fc2f", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/6b5571001a7f04fa0422254c30a0017ec2f2cacc", + "reference": "6b5571001a7f04fa0422254c30a0017ec2f2cacc", "shasum": "" }, "require": { "php": "^7.4 || ^8.0", - "phpstan/phpstan": "^2.1.15" + "phpstan/phpstan": "^2.1.39" }, "require-dev": { "php-parallel-lint/php-parallel-lint": "^1.2", @@ -7530,11 +7117,14 @@ "MIT" ], "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", + "keywords": [ + "static analysis" + ], "support": { "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", - "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.3" + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.4" }, - "time": "2025-05-14T10:56:57+00:00" + "time": "2026-02-09T13:21:14+00:00" }, { "name": "phpunit/php-code-coverage", @@ -8040,16 +7630,16 @@ }, { "name": "react/child-process", - "version": "v0.6.6", + "version": "v0.6.7", "source": { "type": "git", "url": "https://github.com/reactphp/child-process.git", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", - "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3", + "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3", "shasum": "" }, "require": { @@ -8103,7 +7693,7 @@ ], "support": { "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.6" + "source": "https://github.com/reactphp/child-process/tree/v0.6.7" }, "funding": [ { @@ -8111,20 +7701,20 @@ "type": "open_collective" } ], - "time": "2025-01-01T16:37:48+00:00" + "time": "2025-12-23T15:25:20+00:00" }, { "name": "react/dns", - "version": "v1.13.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", "shasum": "" }, "require": { @@ -8179,7 +7769,7 @@ ], "support": { "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.13.0" + "source": "https://github.com/reactphp/dns/tree/v1.14.0" }, "funding": [ { @@ -8187,20 +7777,20 @@ "type": "open_collective" } ], - "time": "2024-06-13T14:18:03+00:00" + "time": "2025-11-18T19:34:28+00:00" }, { "name": "react/event-loop", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", "shasum": "" }, "require": { @@ -8251,7 +7841,7 @@ ], "support": { "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" }, "funding": [ { @@ -8259,7 +7849,7 @@ "type": "open_collective" } ], - "time": "2023-11-13T13:48:05+00:00" + "time": "2025-11-17T20:46:25+00:00" }, { "name": "react/promise", @@ -8336,16 +7926,16 @@ }, { "name": "react/socket", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", "shasum": "" }, "require": { @@ -8404,7 +7994,7 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.16.0" + "source": "https://github.com/reactphp/socket/tree/v1.17.0" }, "funding": [ { @@ -8412,7 +8002,7 @@ "type": "open_collective" } ], - "time": "2024-07-26T10:38:09+00:00" + "time": "2025-11-19T20:47:34+00:00" }, { "name": "react/stream", @@ -9505,16 +9095,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.13.4", + "version": "3.13.5", "source": { "type": "git", "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", - "reference": "ad545ea9c1b7d270ce0fc9cbfb884161cd706119" + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ad545ea9c1b7d270ce0fc9cbfb884161cd706119", - "reference": "ad545ea9c1b7d270ce0fc9cbfb884161cd706119", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4", + "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4", "shasum": "" }, "require": { @@ -9531,11 +9121,6 @@ "bin/phpcs" ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -9585,28 +9170,28 @@ "type": "thanks_dev" } ], - "time": "2025-09-05T05:47:09+00:00" + "time": "2025-11-04T16:30:35+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.25", + "version": "v7.4.9", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b0cf3162020603587363f0551cd3be43958611ff" + "reference": "e4a2e29753c7801f7a8340e066cfa788f3bc8101" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b0cf3162020603587363f0551cd3be43958611ff", - "reference": "b0cf3162020603587363f0551cd3be43958611ff", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/e4a2e29753c7801f7a8340e066cfa788f3bc8101", + "reference": "e4a2e29753c7801f7a8340e066cfa788f3bc8101", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.4", "symfony/service-contracts": "<2.5" }, "provide": { @@ -9615,13 +9200,14 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/expression-language": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", + "symfony/error-handler": "^6.4|^7.0|^8.0", + "symfony/expression-language": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4|^7.0|^8.0", + "symfony/http-foundation": "^6.4|^7.0|^8.0", "symfony/service-contracts": "^2.5|^3", - "symfony/stopwatch": "^5.4|^6.0|^7.0" + "symfony/stopwatch": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -9649,7 +9235,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.25" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.4.9" }, "funding": [ { @@ -9669,20 +9255,20 @@ "type": "tidelift" } ], - "time": "2025-08-13T09:41:44+00:00" + "time": "2026-04-18T13:18:21+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586" + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", - "reference": "59eb412e93815df44f05f342958efa9f46b1e586", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/ccba7060602b7fed0b03c85bf025257f76d9ef32", + "reference": "ccba7060602b7fed0b03c85bf025257f76d9ef32", "shasum": "" }, "require": { @@ -9696,7 +9282,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -9729,7 +9315,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.7.0" }, "funding": [ { @@ -9740,34 +9326,38 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-01-05T13:30:16+00:00" }, { "name": "symfony/filesystem", - "version": "v6.4.24", + "version": "v7.4.11", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "75ae2edb7cdcc0c53766c30b0a2512b8df574bd8" + "reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/75ae2edb7cdcc0c53766c30b0a2512b8df574bd8", - "reference": "75ae2edb7cdcc0c53766c30b0a2512b8df574bd8", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/d721ea61b4a5fba8c5b6e7c1feda19efea144b50", + "reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^5.4|^6.4|^7.0" + "symfony/process": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -9795,7 +9385,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.24" + "source": "https://github.com/symfony/filesystem/tree/v7.4.11" }, "funding": [ { @@ -9815,27 +9405,27 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2026-05-11T16:38:44+00:00" }, { "name": "symfony/finder", - "version": "v6.4.24", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "73089124388c8510efb8d2d1689285d285937b08" + "reference": "e0be088d22278583a82da281886e8c3592fbf149" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/73089124388c8510efb8d2d1689285d285937b08", - "reference": "73089124388c8510efb8d2d1689285d285937b08", + "url": "https://api.github.com/repos/symfony/finder/zipball/e0be088d22278583a82da281886e8c3592fbf149", + "reference": "e0be088d22278583a82da281886e8c3592fbf149", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.0|^7.0" + "symfony/filesystem": "^6.4|^7.0|^8.0" }, "type": "library", "autoload": { @@ -9863,7 +9453,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.24" + "source": "https://github.com/symfony/finder/tree/v7.4.8" }, "funding": [ { @@ -9883,20 +9473,20 @@ "type": "tidelift" } ], - "time": "2025-07-15T12:02:45+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/polyfill-php84", - "version": "v1.33.0", + "version": "v1.38.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", - "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa", + "reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa", "shasum": "" }, "require": { @@ -9943,7 +9533,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1" }, "funding": [ { @@ -9963,24 +9553,24 @@ "type": "tidelift" } ], - "time": "2025-06-24T13:30:11+00:00" + "time": "2026-05-26T12:51:13+00:00" }, { "name": "symfony/process", - "version": "v6.4.33", + "version": "v7.4.13", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "c46e854e79b52d07666e43924a20cb6dc546644e" + "reference": "f5804be144caceb570f6747519999636b664f24c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/c46e854e79b52d07666e43924a20cb6dc546644e", - "reference": "c46e854e79b52d07666e43924a20cb6dc546644e", + "url": "https://api.github.com/repos/symfony/process/zipball/f5804be144caceb570f6747519999636b664f24c", + "reference": "f5804be144caceb570f6747519999636b664f24c", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "type": "library", "autoload": { @@ -10008,7 +9598,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.33" + "source": "https://github.com/symfony/process/tree/v7.4.13" }, "funding": [ { @@ -10028,24 +9618,24 @@ "type": "tidelift" } ], - "time": "2026-01-23T16:02:12+00:00" + "time": "2026-05-23T16:05:06+00:00" }, { "name": "symfony/stopwatch", - "version": "v6.4.24", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "b67e94e06a05d9572c2fa354483b3e13e3cb1898" + "reference": "70a852d72fec4d51efb1f48dcd968efcaf5ccb89" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/b67e94e06a05d9572c2fa354483b3e13e3cb1898", - "reference": "b67e94e06a05d9572c2fa354483b3e13e3cb1898", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/70a852d72fec4d51efb1f48dcd968efcaf5ccb89", + "reference": "70a852d72fec4d51efb1f48dcd968efcaf5ccb89", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/service-contracts": "^2.5|^3" }, "type": "library", @@ -10074,7 +9664,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.24" + "source": "https://github.com/symfony/stopwatch/tree/v7.4.8" }, "funding": [ { @@ -10094,20 +9684,20 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -10136,7 +9726,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -10144,34 +9734,26 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" - } - ], - "aliases": [ - { - "package": "voku/portable-utf8", - "version": "dev-joomla-5.3", - "alias": "6.0.13", - "alias_normalized": "6.0.13.0" + "time": "2025-11-17T20:03:58+00:00" } ], + "aliases": [], "minimum-stability": "stable", "stability-flags": { - "tobscure/json-api": 20, - "voku/portable-utf8": 20 + "tobscure/json-api": 20 }, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^8.1.0", + "php": "^8.3.0", "ext-json": "*", "ext-simplexml": "*", "ext-gd": "*", "ext-dom": "*" }, - "platform-dev": {}, + "platform-dev": [], "platform-overrides": { - "php": "8.1.0" + "php": "8.3.0" }, - "plugin-api-version": "2.9.0" + "plugin-api-version": "2.6.0" } diff --git a/cypress.config.dist.mjs b/cypress.config.dist.mjs index 612b9e0c1dee8..f1c04e514f47d 100644 --- a/cypress.config.dist.mjs +++ b/cypress.config.dist.mjs @@ -25,8 +25,9 @@ export default defineConfig({ browser: 'firefox', screenshotOnRunFailure: true, video: false, + allowCypressEnv: false, }, - env: { + expose: { sitename: 'Joomla CMS Test', name: 'jane doe', email: 'admin@example.com', diff --git a/includes/incompatible.html b/includes/incompatible.html index 513d0941d61e5..113843b4b6b14 100644 --- a/includes/incompatible.html +++ b/includes/incompatible.html @@ -5,8 +5,8 @@ Joomla: unsupported PHP version - - + +
diff --git a/index.php b/index.php index b070eda182c8c..2798b9482c169 100644 --- a/index.php +++ b/index.php @@ -10,14 +10,14 @@ // NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message // Define the application's minimum supported PHP version as a constant so it can be referenced within the application. -define('JOOMLA_MINIMUM_PHP', '8.1.0'); +\define('JOOMLA_MINIMUM_PHP', '8.3.0'); if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<')) { die( str_replace( '{{phpversion}}', JOOMLA_MINIMUM_PHP, - file_get_contents(dirname(__FILE__) . '/includes/incompatible.html') + file_get_contents(\dirname(__FILE__) . '/includes/incompatible.html') ) ); } @@ -26,7 +26,7 @@ * Constant that is checked in included files to prevent direct access. * define() is used rather than "const" to not error for PHP 5.2 and lower */ -define('_JEXEC', 1); +\define('_JEXEC', 1); // Load global path definitions if (file_exists(__DIR__ . '/defines.php')) { diff --git a/installation/forms/setup.xml b/installation/forms/setup.xml index 467d9046571ba..9018395ab466f 100644 --- a/installation/forms/setup.xml +++ b/installation/forms/setup.xml @@ -7,6 +7,7 @@ label="INSTL_SELECT_LANGUAGE_TITLE" class="required" default="en-GB" + labelclass="hidden" /> '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}', 'text_file' => 'error.php', ], \Joomla\CMS\Log\Log::ALL, diff --git a/installation/includes/cli.php b/installation/includes/cli.php index 4562a6bfaa66b..b9e04e8f3aff3 100644 --- a/installation/includes/cli.php +++ b/installation/includes/cli.php @@ -19,7 +19,7 @@ if (!file_exists(JPATH_LIBRARIES . '/vendor/autoload.php') || !is_dir(JPATH_ROOT . '/media/vendor')) { echo 'It looks like you are trying to run Joomla! from our git repository.' . PHP_EOL; echo 'To do so requires you complete a couple of extra steps first.' . PHP_EOL; - echo 'Please see https://docs.joomla.org/Special:MyLanguage/J5.x:Setting_Up_Your_Local_Environment for further details.' . PHP_EOL; + echo 'Please see https://guide.joomla.org/user-manual/hosting/local-environment-setup for further details.' . PHP_EOL; exit; } @@ -31,7 +31,6 @@ if (is_writable(JPATH_ADMINISTRATOR . '/logs')) { \Joomla\CMS\Log\Log::addLogger( [ - 'format' => '{DATE}\t{TIME}\t{LEVEL}\t{CODE}\t{MESSAGE}', 'text_file' => 'error.php', ], \Joomla\CMS\Log\Log::ALL, diff --git a/installation/index.php b/installation/index.php index 099e5daf1d835..fb05cf85bbe24 100644 --- a/installation/index.php +++ b/installation/index.php @@ -10,7 +10,7 @@ // NOTE: This file should remain compatible with PHP 5.2 to allow us to run our PHP minimum check and show a friendly error message // Define the application's minimum supported PHP version as a constant so it can be referenced within the application. -\define('JOOMLA_MINIMUM_PHP', '8.1.0'); +\define('JOOMLA_MINIMUM_PHP', '8.3.0'); if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<')) { die( diff --git a/installation/joomla.php b/installation/joomla.php index 50756491049ec..99bb5d23592a3 100644 --- a/installation/joomla.php +++ b/installation/joomla.php @@ -14,7 +14,7 @@ /** * Define the application's minimum supported PHP version as a constant so it can be referenced within the application. */ -\define('JOOMLA_MINIMUM_PHP', '8.1.0'); +\define('JOOMLA_MINIMUM_PHP', '8.3.0'); if (version_compare(PHP_VERSION, JOOMLA_MINIMUM_PHP, '<')) { echo 'Sorry, your PHP version is not supported.' . PHP_EOL; diff --git a/installation/language/af-ZA/joomla.ini b/installation/language/af-ZA/joomla.ini index 76a2d184673d6..7822d7e43d613 100644 --- a/installation/language/af-ZA/joomla.ini +++ b/installation/language/af-ZA/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Jou gasheer moet PHP weergawe {{phpversion}} of nuwer BUILD_MIN_PHP_ERROR_URL_TEXT="Help my om dit op te los" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Verander" INSTL_SELECT_INSTALL_LANG="Kies Installasietaal" INSTL_SELECT_LANGUAGE_TITLE="Kies Taal" INSTL_SETUP_LOGIN_DATA="Stel Aanteken Data" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Jou PHP installasie het nodig dat JSON geaktiveerd is vir Joomla INSTL_DATABASE_SUPPORT="Databasis Hulp:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Ondersteuning" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Taal is Verstek" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Oorlading Af" INSTL_NOTICE_DATABASE_SUPPORT="Geen ondersteunende databasisse is gevind nie." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Jou PHP installasie het nodig dat JSON geaktiveerd is vir Joomla om te installeer!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring taal is nie gestel op neutraal nie. Dit kan lokaal gestel word deur php_value mbstring.language neutral in te skryf in jou .htaccess lêer." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring funksie oorlading is gestel. Dit kan lokaal af geskakel word deur php_value mbstring.func_overload 0 in te skryf in jou .htaccess lêer." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Die vereiste php funksies parse_ini_file en parse_ini_string is gedeaktiveer op jou bediener." INSTL_NOTICE_XML_SUPPORT="XML Hulp is nie beskikbaar nie. Dit behoort by verstek geaktiveerd wees in php, maar Ubuntu verbruikers mag nog hê om dit te installeer deur sudo apt-get install php-xml gevolg deur die web bediener te herbegin." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib kompressie in nie gestel nie. Dit kan lokaal aan geskakel word deur zlib.output_compression = On in te skryf in jou php.ini lêer." diff --git a/installation/language/af-ZA/langmetadata.xml b/installation/language/af-ZA/langmetadata.xml index ffd6d340c86c5..36f98a5efa56d 100644 --- a/installation/language/af-ZA/langmetadata.xml +++ b/installation/language/af-ZA/langmetadata.xml @@ -1,7 +1,7 @@ Afrikaans (Suid-Afrika) - 5.4.8 + 6.1.3 2026-07 Afrikaans Translation Team (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ar-AA/joomla.ini b/installation/language/ar-AA/joomla.ini index db39e07eb138e..36c6fbedb55a1 100644 --- a/installation/language/ar-AA/joomla.ini +++ b/installation/language/ar-AA/joomla.ini @@ -5,55 +5,52 @@ ; Fatal error page ; These will be processed by the JavaScript Build -BUILD_FATAL_HEADER="عذرًا، كانت هناك مشكلة لم نتمكن من تجاوزها." +BUILD_FATAL_HEADER="عذرًا ، كانت هناك مشكلة لم نتمكن من تجاوزها." BUILD_FATAL_LANGUAGE="اللغة العربية بالكود الموحد" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_FATAL_TEXT="أرجع الخادم \"{{statusCode_statusText}}\"" +BUILD_FATAL_TEXT="أعاد الخادم ملف \"{{statusCode_statusText}}\"" BUILD_FATAL_URL_TEXT="ساعدني في حل هذا" ; Build incomplete error page ; These will be processed by the JavaScript Build BUILD_INCOMPLETE_HEADER="إعداد البيئة غير مكتمل" BUILD_INCOMPLETE_LANGUAGE="اللغة العربية بالكود الموحد" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_INCOMPLETE_TEXT="يبدو أنك تحاول تشغيل جوملا! من مستودع git الخاص بنا. يتطلب هذا منك إكمال خطوتين إضافيتين أولاً." -BUILD_INCOMPLETE_URL_TEXT="المزيد من التفاصيل" +BUILD_INCOMPLETE_TEXT="يبدو أنك تحاول تشغيل جوملا! من مستودع git الخاص بك. للقيام بذلك يتطلب منك إكمال خطوتين إضافيتين أولاً." +BUILD_INCOMPLETE_URL_TEXT="[ المزيد من التفاصيل %s]" ; No XML PHP error page ; These will be processed by the JavaScript Build -BUILD_NOXML_HEADER="عذرًا، PHP الخاص بك يفتقد مكتبة حيوية" +BUILD_NOXML_HEADER="عذرا ، PHP الخاص بك يفتقد مكتبة حيوية" BUILD_NOXML_LANGUAGE="اللغة العربية بالكود الموحد" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_NOXML_TEXT="يحتاج الخادم الخاص بك إلى استخدام PHP مع دعم مكتبة XML لتشغيل هذا الإصدار من جوملا!" +BUILD_NOXML_TEXT="يحتاج مضيفك إلى استخدام PHP مع دعم مكتبة XML لتشغيل هذا الإصدار من جوملا!" BUILD_NOXML_URL_TEXT="ساعدني في حل هذا" ; Minimum PHP error page ; These will be processed by the JavaScript Build -BUILD_MIN_PHP_ERROR_HEADER="عذرًا، إصدار PHP الخاص بك غير مدعوم." +BUILD_MIN_PHP_ERROR_HEADER="عذرًا ، إصدار PHP الخاص بك غير مدعوم." BUILD_MIN_PHP_ERROR_LANGUAGE="اللغة العربية بالكود الموحد" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_MIN_PHP_ERROR_TEXT="يحتاج الخادم الخاص بك إلى استخدام إصدار PHP {{phpversion}} أو أحدث لتشغيل هذا الإصدار من جوملا." +BUILD_MIN_PHP_ERROR_TEXT="يحتاج مضيفك إلى استخدام إصدار PHP {{phpversion}} أو أحدث لتشغيل هذا الإصدار من جوملا." BUILD_MIN_PHP_ERROR_URL_TEXT="ساعدني في حل هذا" ; Main Config -INSTL_SELECT_INSTALL_LANG="حدد لغة التثبيت" -INSTL_SELECT_LANGUAGE_TITLE="اختر اللغة" +INSTL_CHANGE_INSTALL_LANG_SHORT="تغيير الموضع" +INSTL_SELECT_INSTALL_LANG="حدد لغة التنصيب" +INSTL_SELECT_LANGUAGE_TITLE="اختار اللغة" INSTL_SETUP_LOGIN_DATA="إعداد بيانات تسجيل الدخول" -INSTL_WARNJAVASCRIPT="تحذير! يجب تمكين الجافاسكربت لكي يتم تثبيت نظام جوملا! بشكل صحيح." -INSTL_WARNJSON="يجب تفعيل JSON في نسخة PHP الخاصة بك لتتمكن من تثبيت جوملا!" +INSTL_WARNJAVASCRIPT="تحذير! يجب تمكين الجافا سكريبت لكي يتم تثبيت نظتم جوملا! بشكل صحيح" +INSTL_WARNJSON="PHP خلال تثبيتكم JSON للتمكن من تثيت جوملا . يجب تفعيل" ; Precheck view INSTL_DATABASE_SUPPORT="دعم قاعدة البيانات:" INSTL_JSON_SUPPORT_AVAILABLE="دعم JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="استخدام لغة افتراضية متعددة وحدات البايت" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="إيقاف التحميل الزائد للسلسة متعددة وحدات البايت" INSTL_NOTICE_DATABASE_SUPPORT="لم يتم العثور على قواعد البيانات المدعومة." -INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="يجب تفعيل JSON في نسخة PHP الخاصة بك لتتمكن من تثبيت جوملا!" -INSTL_NOTICE_MBLANG_NOTDEFAULT="لم يتم تعيين لغة PHP mbstring على الحيادية. يمكن تعيين ذلك محليًا عن طريق إدخال php_value mbstring.languageutral في مِلَفّ .htaccess الخاص بك." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="تم تعيين overload دالة PHP mbstring. يمكن إيقاف تشغيل هذه محليًا عن طريق إدخال php_value mbstring.func_overload 0 في مِلَفّ .htaccess الخاص بك." +INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="PHP خلال تثبيتكم JSON للتمكن من تثيت جوملا . يجب تفعيل" +INSTL_NOTICE_MBLANG_NOTDEFAULT="لم يتم تعيين لغة PHP mbstring على الحيادية. يمكن تعيين ذلك محليًا عن طريق إدخال php_value mbstring.languageutral في ملف .htaccess الخاص بك." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="وظائف php المطلوبة parse_ini_file و parse_ini_string معطلة على الخادم الخاص بك." INSTL_NOTICE_XML_SUPPORT="دعم XML غير متوفر. يجب تمكين هذا افتراضيًا في php ولكن قد يحتاج مستخدمو Ubuntu إلى تثبيت هذا عن طريق إجراء sudo apt-get install php-xml متبوعًا بإعادة تشغيل خادم الويب." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="لم يتم تعيين ضغط Zlib. يمكن تشغيل هذا محليًا عن طريق إدخال zlib.output_compression = On في ملف php.ini ." INSTL_PARSE_INI_FILE_AVAILABLE="دعم محلل INI" -INSTL_PRECHECK_ACTUAL="حاليًا" +INSTL_PRECHECK_ACTUAL="حالياً" INSTL_PRECHECK_DESC="إذا كان أي من هذه المناصر غير مدعوم \"أي غير متوفر\" سيكون مكتوب باللون الأحمر (لا) عندها يرجى القيام بالإجراءات اللازمة لتصحيحها.
لا يمكنك تنصيب جوملا! حتى توفير الإعدادت المطلوبة أدناه." INSTL_PRECHECK_DIRECTIVE="التوجيهات" INSTL_PRECHECK_RECOMMENDED="ينصح بها" @@ -135,8 +132,8 @@ INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE="اللغة" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_SELECT="اختار اللغة" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_TAG="كود اللغة" INSTL_LANGUAGES_COLUMN_HEADER_VERSION="الاصدار" -INSTL_LANGUAGES_DESC="واجهة Joomla متاحة بعدة لغات. اختر لغاتك المفضلة عن طريق اختيار خانات الاختيار ثم تثبيتها عن طريق تحديد زر \"تثبيت اللغات المحددة\".
ملاحظة: هذه العملية ستستغرق حوالي 10 ثوان لتنزيل وتثبيت كل لغة. لتجنب المهلة الزمنية يرجى تحديد ما لا يزيد عن 3 لغات للتثبيت." -INSTL_LANGUAGES_MESSAGE_PLEASE_WAIT="ستستغرق هذه العملية ما يصل إلى 10 ثوان في كل لغة للإكتمال
الرجاء الانتظار بينما نقوم بتنزيل وتثبيت اللغات …" +INSTL_LANGUAGES_DESC="واجهة جوملا متاحة بعدة لغات. اختر اللغات المفضلة لديك عن طريق اختيار خانات الاختيار ثم تثبيتها عن طريق تحديد زر \"تثبيت اللغات المحددة\".
ملاحظة: ستستغرق هذه العملية حوالي 10 ثوان لتحميل وتثبيت كل لغة. لتجنب المهلة الزمنية الرجاء تحديد ما لا يزيد عن 3 لغات للتثبيت." +INSTL_LANGUAGES_MESSAGE_PLEASE_WAIT="هذه العملية من الممكن ان تحتاج لأكثر من 10 ثوان لتنصيب اللغة
لطفاً انتظر بينما يتم تحميل و تنصيب اللغات..." INSTL_LANGUAGES_NO_LANGUAGE_SELECTED="لطفاً, حدد اللغة. إن لم تكن تريد تنصيب المزيد من اللغات فانقر على زر 'السابق' " INSTL_LANGUAGES_SELECTED="قم بتثبيت اللغات المحددة" INSTL_LANGUAGES_WARNING_BACK_BUTTON="العودة للمرحلة الأخيرة من التنصيب" @@ -222,8 +219,8 @@ INSTL_WRITABLE="%s قابل للكتابة" INSTL_ZIP_SUPPORT_AVAILABLE="توفر ZIP خاصية فك الملفات المضغوطة" ; Global strings -JADMINISTRATOR="الإدارة" -JCLOSE="أغلق" +JADMINISTRATOR="المدير" +JCLOSE="إغلاق" JEMAIL="البريد الإلكتروني" JERROR="خطأ" JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="لقد حدث خطأ أثناء معالجة طلبك." @@ -234,7 +231,7 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="لايوجد نتائج مشابهة" JGLOBAL_SELECT_SOME_OPTIONS="حدد بعض الخيارات" JHIDEPASSWORD="إخفاء كلمة المرور" JINVALID_TOKEN="رمز غير صالح" -JINVALID_TOKEN_NOTICE="قيم الكود الأمني غير متوافقة. تم رفض الطلب تفاديًا لأي خرق أمني محتمل. لطفاً حاول مرة أخرى." +JINVALID_TOKEN_NOTICE="لم يتطابق رمز الأمان. تم إلغاء الطلب لمنع أي خرق أمني. يُرجى المحاولة مرة أخرى." JNEXT="التالي" JNO="ابدا" JNOTICE="ملاحظة" @@ -257,7 +254,7 @@ JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="JFolder: :حذف: المسار لا JLIB_FORM_FIELD_INVALID="حقل غير صحيح: " JLIB_FORM_VALIDATE_FIELD_INVALID="حقل غير صالح: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="حقل مطلوب: %s" -JLIB_INSTALLER_ABORT="إيقاف تثبيت اللغة: %s" +JLIB_INSTALLER_ABORT="إحباط عملية تنصيب اللغة: %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="التطبيق %1$s: فشل انشاء الدليل باسم: %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="مسار التنصيب غير موجود" JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="الحزمة %1$s: حصل خطأ عند محاولة تنصيب الاضافة: %2$s" @@ -298,7 +295,7 @@ NOTICE="ملاحظة" WARNING="تحذير" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="فشل الاتصال عند محاولة الحصول على بيانات JSON." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="لقد حدث خطأ في الاتصال أثناء جلب بيانات JSON." JLIB_JS_AJAX_ERROR_NO_CONTENT="لايمكن استعادة المحتوى." JLIB_JS_AJAX_ERROR_OTHER="حدث خطأ أثناء جلب البيانات JSON: HTTP %s حالة الكود." JLIB_JS_AJAX_ERROR_PARSE="حدث خطأ في تحليل أثناء معالجة البيانات JSON التالية:
%s" diff --git a/installation/language/ar-AA/langmetadata.xml b/installation/language/ar-AA/langmetadata.xml index 7aecde22ae94b..30383c15681b5 100644 --- a/installation/language/ar-AA/langmetadata.xml +++ b/installation/language/ar-AA/langmetadata.xml @@ -1,7 +1,7 @@ Arabic (اللغة العربية) - 5.4.8 + 6.1.3 2026-07 Joomla! Project (Arabic Translation Team) (C) 2005 Open Source Matters, Inc. @@ -10,7 +10,7 @@ joomla.ini - Arabic (ar-AA) + Arabic Unitag (العربية الموحدة) Arabic (اللغة العربية) ar-AA 1 diff --git a/installation/language/be-BY/joomla.cli.ini b/installation/language/be-BY/joomla.cli.ini index b4258e140797d..3551cf61dff23 100644 --- a/installation/language/be-BY/joomla.cli.ini +++ b/installation/language/be-BY/joomla.cli.ini @@ -31,8 +31,8 @@ INSTL_DATABASE_TYPE_DESC="Тып базы даных. Падтрымліваюц INSTL_DATABASE_TYPE_DESC_SHORT="Тып базы даных. Падтрымліваюцца ў Joomla: mysql (=MySQL (PDO)), mysqli (=MySQLi), pgsql (=PostgreSQL (PDO))" INSTL_DATABASE_USER_DESC="Імя карыстальніка базы даных" INSTL_DATABASE_USER_DESC_SHORT="Імя карыстальніка базы даных" -INSTL_PUBLIC_FOLDER_DESC="Адносны або абсалютны шлях да агульнай (публічнай) папкі" -INSTL_PUBLIC_FOLDER_DESC_SHORT="Адносны або абсалютны шлях да агульнай (публічнай) папкі" +INSTL_PUBLIC_FOLDER_DESC="Адносны альбо абсалютны шлях да агульнай папкі" +INSTL_PUBLIC_FOLDER_DESC_SHORT="Адносны альбо абсалютны шлях да агульнай папкі" INSTL_SITE_NAME_DESC="Увядзіце назву вашага сайта" INSTL_SITE_NAME_DESC_SHORT="Назва вэб-сайта" diff --git a/installation/language/be-BY/joomla.ini b/installation/language/be-BY/joomla.ini index 49ce48cf401e0..3c98f64b07750 100644 --- a/installation/language/be-BY/joomla.ini +++ b/installation/language/be-BY/joomla.ini @@ -5,114 +5,113 @@ ; Fatal error page ; These will be processed by the JavaScript Build -BUILD_FATAL_HEADER="Выбачайце, здарылася непапраўная памылка." +BUILD_FATAL_HEADER="Выбачце, здарылася крытычная памылка, якой мы ня можам даць рады." BUILD_FATAL_LANGUAGE="Беларуская BY" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_FATAL_TEXT="Сервер вярнуў адказ: \"{{statusCode_statusText}}\"" -BUILD_FATAL_URL_TEXT="Дапамажыце мне выправіць гэта" +BUILD_FATAL_TEXT="Сервер звярнуў адказ \"{{statusCode_statusText}}\"" +BUILD_FATAL_URL_TEXT="Дапамажыце мне гэта вырашыць" ; Build incomplete error page ; These will be processed by the JavaScript Build -BUILD_INCOMPLETE_HEADER="Працоўнае асяроддзе не наладжанае" +BUILD_INCOMPLETE_HEADER="Наладжванне працоўнага асяроддзя не завершана" BUILD_INCOMPLETE_LANGUAGE="Беларуская BY" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_INCOMPLETE_TEXT="Здаецца, Вы спрабуеце ўсталяваць Joomla з нашага Git-сховішча. Для гэтага спачатку зрабіце некалькі дадатковых крокаў." -BUILD_INCOMPLETE_URL_TEXT="Падрабязней" +BUILD_INCOMPLETE_TEXT="Падобна на тое, што вы спрабуеце ўсталяваць Joomla з нашага Git-рэпазітара. Калі ласка, выканайце некалькі дадатковых крокаў перад пачаткам усталявання." +BUILD_INCOMPLETE_URL_TEXT="Больш дэталяў" ; No XML PHP error page ; These will be processed by the JavaScript Build -BUILD_NOXML_HEADER="Выбачайце, у Вашай версіі PHP няма важнай бібліятэкі" +BUILD_NOXML_HEADER="У версіі PHP, якую вы выкарыстоўваеце, адключана падтрымка XML" BUILD_NOXML_LANGUAGE="Беларуская BY" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_NOXML_TEXT="Каб запусціць гэтую версію Joomla, Ваш хост мусіць мець PHP з падтрымкай XML." -BUILD_NOXML_URL_TEXT="Дапамажыце мне выправіць гэта" +BUILD_NOXML_TEXT="Каб запусціць гэтую версію Joomla, на серверы трэба мець PHP з падтрымкай XML!" +BUILD_NOXML_URL_TEXT="Дапамажыце мне гэта вырашыць" ; Minimum PHP error page ; These will be processed by the JavaScript Build -BUILD_MIN_PHP_ERROR_HEADER="Выбачайце, Ваша версія PHP не падтрымліваецца" +BUILD_MIN_PHP_ERROR_HEADER="Выбачайце, Ваша версія PHP не падтрымліваецца." BUILD_MIN_PHP_ERROR_LANGUAGE="Беларуская BY" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_MIN_PHP_ERROR_TEXT="Каб запусціць гэтую версію Joomla, Ваш хост мусіць мець PHP {{phpversion}} або навейшы." -BUILD_MIN_PHP_ERROR_URL_TEXT="Дапамажыце мне выправіць гэта" +BUILD_MIN_PHP_ERROR_TEXT="Каб запусціць гэтую версію Joomla, на серверы трэба мець версію PHP {{phpversion}} або навейшую." +BUILD_MIN_PHP_ERROR_URL_TEXT="Дапамажыце мне гэта вырашыць" ; Main Config -INSTL_SELECT_INSTALL_LANG="Мова ў працэсе ўсталявання" +INSTL_CHANGE_INSTALL_LANG="Змяніць мову ўсталявання" +INSTL_CHANGE_INSTALL_LANG_SHORT="Выбар пазіцыі" +INSTL_SELECTED_INSTALL_LANGUAGE="Бягучая мова: %s" +INSTL_SELECT_INSTALL_LANG="Выберыце мову ўсталёўкі" INSTL_SELECT_LANGUAGE_TITLE="Выберыце мову" INSTL_SETUP_LOGIN_DATA="Параметры ўліковага запісу" -INSTL_WARNJAVASCRIPT="Увага! Трэба падлучыць JavaScript у Вашым браўзеры, каб правільна ўсталяваць Joomla." +INSTL_WARNJAVASCRIPT="Папярэджанне: Каб правільна ўсталяваць Joomla, у вашым браўзеры павінны быць уключаны JavaScript." INSTL_WARNJSON="У Вашай версіі PHP трэба мець падлучаны JSON, каб усталяваць Joomla." ; Precheck view -INSTL_DATABASE_SUPPORT="Базы даных якія падтрымліваюцца:" -INSTL_JSON_SUPPORT_AVAILABLE="JSON падтрымоўваецца:" +INSTL_DATABASE_SUPPORT="Падтрымка базы дадзеных:" +INSTL_JSON_SUPPORT_AVAILABLE="Падтрымка JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language выкарыстоўваецца па змаўчанні" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off - адключаная" -INSTL_NOTICE_DATABASE_SUPPORT="Прыдатная база даных не знойдзеная." +INSTL_NOTICE_DATABASE_SUPPORT="Не знойдзена базаў дадзеных якія падтрымліваюцца." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="У Вашай версіі PHP трэба мець падлучаны JSON, каб усталяваць Joomla." -INSTL_NOTICE_MBLANG_NOTDEFAULT="Мова PHP mbstring не ўстаноўлена ў нейтральнае значэнне. Гэта можна ўсталяваць лакальна, увёўшы php_value mbstring.language neutral ў вашым файле .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Заданае пераладаванне PHP-функцыі mbstring. Гэта можна лакальна змяніць, дадаўшы php_value mbstring.func_overload 0 у файл .htaccess." -INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Абавязковыя функцыі PHP parse_ini_file і parse_ini_string адлучаныя на Вашым серверы." -INSTL_NOTICE_XML_SUPPORT="Падтрымка XML недаступная. Трэба стандартна падлучыць модуль у PHP, але карыстальнікам Ubuntu можа спатрэбіцца ўсталяваць яго праз тэрмінал. Выканайце sudo apt-get install php-xml і перазапусціце вэб-сервер." -INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Сцісканне з дапамогай Zlib не заданае. Яго можна лакальна падлучыць, увёўшы zlib.output_compression = On у файле php.ini." -INSTL_PARSE_INI_FILE_AVAILABLE="Падтрымка парсера INI" -INSTL_PRECHECK_ACTUAL="Фактычна" -INSTL_PRECHECK_DESC="Калі якісьці з гэтых пунктаў не падтрымоўваецца (метка Не), спрабуйце яго выправіць.
Вы не зможаце ўсталяваць Joomla, пакуль Вашы налады не будуць адпавядаць патрабаванням." +INSTL_NOTICE_MBLANG_NOTDEFAULT="Для дырэктывы mbstring.language ўстаноўлена значэнне не neutral. Гэта можна ўсталяваць лакальна, увёўшы php_value mbstring.language neutral ў вашым файле .htaccess." +INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Неабходныя функцыі PHP parse_ini_file іparse_ini_string адключаныя на вашым серверы." +INSTL_NOTICE_XML_SUPPORT="Падтрымка XML недаступная на гэтым серверы. Трэба стандартна падлучыць модуль у PHP, але карыстальнікам Ubuntu можа спатрэбіцца ўсталяваць яго праз тэрмінал. Выканайце sudo apt-get install php-xml і перазапусціце вэб-сервер." +INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Падтрымка Zlib недаступная на гэтым серверы. Яго можна лакальна падлучыць, увёўшы zlib.output_compression = On у файл php.ini." +INSTL_PARSE_INI_FILE_AVAILABLE="Падтрымка INI Parser" +INSTL_PRECHECK_ACTUAL="Фактычны" +INSTL_PRECHECK_DESC="Калі якісьці з гэтых пунктаў не падтрымліваецца (метка Не), спрабуйце яго выправіць.
Вы не зможаце ўсталяваць Joomla, пакуль Вашы налады не будуць адпавядаць патрабаванням." INSTL_PRECHECK_DIRECTIVE="Параметр" INSTL_PRECHECK_RECOMMENDED="Рэкамендуецца" -INSTL_PRECHECK_RECOMMENDED_SETTINGS_DESC="Гэтыя налады рэкамендуюцца для поўнай сумяшчальнасці PHP з Joomla. Тым не менш Joomla можа працаваць, нават калі фактычныя налады не супадаюць з рэкамендаванымі." +INSTL_PRECHECK_RECOMMENDED_SETTINGS_DESC="Гэтыя налады рэкамендуюцца для поўнай сумяшчальнасці PHP з Joomla. Тым не менш Joomla можа працаваць, нават калі бягучыя значэнні не супадаюць з рэкамендаванымі." INSTL_PRECHECK_RECOMMENDED_SETTINGS_TITLE="Рэкамендаваныя налады" -INSTL_PRECHECK_TITLE="Кантроль перад усталяваннем" +INSTL_PRECHECK_TITLE="Праверка перад усталёўкай" INSTL_XML_SUPPORT="Падтрымка XML" -INSTL_ZLIB_COMPRESSION_SUPPORT="Zlib-сцісканне падтрымоўваецца:" +INSTL_ZLIB_COMPRESSION_SUPPORT="Падтрымка сціску Zlib" ; Database view -INSTL_DATABASE="Канфігурацыя базы даных" +INSTL_DATABASE="Канфігурацыя базы дадзеных" INSTL_DATABASE_ENCRYPTION_CA_LABEL="Шлях да файла CA" INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Шлях да файла сертыфіката" -INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="(Неабавязкова.) Набор шыфраў, які падтрымоўваецца" -INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Шлях да файла сакрэтнага ключа" +INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Падтрымліваемы набор шыфраў (неабавязкова)" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Шлях да файла прыватнага ключа" INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Шыфраванне злучэння" -INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="Стандартнае (кіруецца серверам)" +INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="Па змаўчанні (кіруецца серверам)" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_ONE_WAY="Аднабаковая аўтэнтыфікацыя" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_TWO_WAY="Двухбаковая аўтэнтыфікацыя" -INSTL_DATABASE_ENCRYPTION_MSG_CONN_NOT_ENCRYPT="Вы абралі падлучэнне да базы даных з шыфраваннем, і злучэнне можна ўсталяваць, але не зашыфраваць. Прычынай можа быць тое, што сервер базы даных наладжаны на зварот да незашыфраванага злучэння ў выпадку праблемных параметраў шыфравання. Або праверце і выпраўце параметры шыфравання, або змяніце поле \"Шыфраванне злучэння\" назад на \"Стандартнае (кіруецца серверам)\"." -INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="Файл, пазначаны ў полі \"%s\", не існуе або недаступны." +INSTL_DATABASE_ENCRYPTION_MSG_CONN_NOT_ENCRYPT="Вы абралі падлучэнне да базы дадзеных з шыфраваннем, якое можа быць ўсталяванае, але не зашыфраванае. Прычынай можа быць тое, што сервер базы дадзеных наладжаны на зварот да незашыфраванага злучэння ў выпадку праблемных параметраў шыфравання. Або праверце і выпраўце параметры шыфравання, або змяніце поле \"Шыфраванне злучэння\" назад на \"Стандартнае (кіруецца серверам)\"." +INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="Файл, уведзены ў поле \" %s\", не існуе або недаступны." INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_EMPTY="Поле \"%s\" не запоўненае або не змяшчае дапушчальнага шляху." -INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="Вы ўвялі \"localhost\" у якасці назвы хоста. У гэтым выпадку падлучэнне да базы даных з шыфраваннем можа не ўдацца. Або замяніце \"localhost\" на \"127.0.0.1\", ці \"::1\", ці іншую назву, або змяніце поле \"Шыфраванне злучэння\"на \"Стандартнае (кіруецца серверам)\"." -INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="Сервер базы даных не падтрымоўвае шыфравання злучэння. Або дазвольце падтрымка TLS (часта называецца SSL у дакументах) на серверы базы даных, або змяніце поле \"Шыфраванне злучэння\" на \"Стандартнае (кіруецца серверам)\"." -INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Спраўджваць сертыфікат сервера" -INSTL_DATABASE_ERROR_POSTGRESQL_QUERY="Памылка запыту да базы даных PostgreSQL." -INSTL_DATABASE_HOST_DESC="Назва хоста, звычайна \"localhost\" або назва, выданая Вашым правайдарам:" -INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE="Памылка стварэння файла. Стварыце файл \"%1$s\" уручную і заладуйце яго ў каталог \"%2$s\" Вашага сайта Joomla. Потым выберыце \"%3$s\", каб працягнуць." +INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="Вы ўвялі Значэнне \"localhost\" у якасці імя хаста. У такім выпадку падключэнне да базы дадзеных з шыфраваннем злучэння можа завяршыцца памылкай. Неабходна змяніць імя хаста \"localhost\" на \"127.0.0.1\", \"::1\" іншае імя, або змяніць значэнне поля \"Conection Encryption\"на \"Default (server controlled)\"." +INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="Сервер базы дадзеных не падтрымлівае шыфраванне злучэння. Альбо ўключыце падтрымку TLS (часта званую SSL у дакументах) на вашым серверы базы дадзеных, альбо змяніце поле \"Шыфраванне злучэння\" назад \"Па змаўчанні (кантралюецца серверам)\"." +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Праверка сертыфіката сервера" +INSTL_DATABASE_ERROR_POSTGRESQL_QUERY="Памылка запыту да базы дадзеных PostgreSQL." +INSTL_DATABASE_HOST_DESC="Увядзіце назву хоста (звычайна \"localhost\" або назва, якую Вам прадаставіў хостынг-правайдар)." +INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE="Памылка стварэння файла. Стварыце файл \"%1$s\" уручную і запампуйце яго ў каталог \"%2$s\" Вашага сайта Joomla. Потым выберыце \"%3$s\", каб працягнуць." INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE="Каб пацвердзіць, што Вы — уладальнік сайта, выдаліце файл \"%1$s\", створаны сістэмай у каталозе \"%2$s\" Вашага сайта Joomla. Потым выберыце \"%3$s\", каб працягнуць." -INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE="Вы спрабуеце выкарыстоўваць хост базы даных, якога няма на Вашым лакальным серверы. З прычын бяспекі Вам трэба спраўдзіць уласнасць на Ваш уліковы запіс вэб-хостынгу. Прачытайце дакументацыю, каб даведацца больш." +INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE="Вы спрабуеце выкарыстоўваць хост базы дадзеных, якога няма на Вашым лакальным серверы. З прычын бяспекі Вам трэба спраўдзіць уласнасць на Ваш уліковы запіс вэб-хостынгу. Прачытайце дакументацыю, каб даведацца больш." INSTL_DATABASE_HOST_LABEL="Назва хоста" -INSTL_DATABASE_NAME_DESC="Назва базы даных:" -INSTL_DATABASE_NAME_LABEL="Назва базы даных" -INSTL_DATABASE_NAME_MSG_MYSQL="Памылковая назва базы даных. Яна не можа змяшчаць гэтых знакаў: \ /" -INSTL_DATABASE_NAME_MSG_POSTGRES="Памылковая назва базы даных. Яна павінна складацца з лічбаў і лацінскіх літар і пачынацца з літары." -INSTL_DATABASE_NO_SCHEMA="Не існуе схемы базы даных для гэтага тыпу базы." +INSTL_DATABASE_NAME_DESC="Увядзіце імя базы дадзеных." +INSTL_DATABASE_NAME_LABEL="Імя базы дадзеных" +INSTL_DATABASE_NAME_MSG_MYSQL="Памылковая назва базы дадзеных. Яна не можа змяшчаць гэтых знакаў: \ /" +INSTL_DATABASE_NAME_MSG_POSTGRES="Памылковая назва базы дадзеных. Яна павінна складацца з лічбаў і лацінскіх літар і пачынацца з літары." +INSTL_DATABASE_NO_SCHEMA="Не існуе схемы базы дадзеных для гэтага тыпу базы." INSTL_DATABASE_PASSWORD_DESC="Пароль да базы даных, які створаны Вамі або Вашым хостынг-правайдарам:" -INSTL_DATABASE_PREFIX_DESC="Прэфікс табліц або скарыстайцеся выпадкова створаным:" -INSTL_DATABASE_PREFIX_DUPLICATE_DESC="Калі ўжо выкарыстоўваецца база даных з табліцамі з тым жа прэфіксам, Joomla зменіць назву яе табліц, дадаўшы прэфікс \"bak_\"." +INSTL_DATABASE_PREFIX_DESC="Увядзіце прэфікс табліц БД або скарыстайце выпадкова створаны." +INSTL_DATABASE_PREFIX_DUPLICATE_DESC="Калі вы выкарыстоўваеце існуючую базу дадзеных з табліцамі з аднолькавымі прэфіксамі, Joomla пераймянуе існуючыя табліцы, дадаўшы прэфікс \"bak_\"." INSTL_DATABASE_PREFIX_MSG="Прэфікс табліцы павінен пачынацца з літары, пасля чаго могуць ісці літарна-лічбавыя сімвалы, і ён павінен заканчвацца знакам падкрэслівання." -INSTL_DATABASE_RESPONSE_ERROR="Не ўдалося завяршыць усталяванне." -INSTL_DATABASE_TYPE_DESC="Выберыце тып базы даных" +INSTL_DATABASE_RESPONSE_ERROR="Працэс усталёўкі завяршыўся няўдачай." +INSTL_DATABASE_TYPE_DESC="Выберыце тып базы дадзеных." INSTL_DATABASE_USER_DESC="Імя карыстальніка БД, створанае Вамі або Вашым хостынг-правайдарам." -INSTL_DATABASE_VALIDATION_ERROR="Праверце свае ўліковыя звесткі, а таксама тып і назву базы даных і назву хоста. Калі ў Вас усталяваная MySQL 8, прачытайце гэтую дакументацыю, каб даведацца больш." +INSTL_DATABASE_VALIDATION_ERROR="Праверце свае ўліковыя звесткі, а таксама тып і назву базы дадзеных і назву хоста. Калі ў Вас усталявана MySQL 8, прачытайце гэтую дакументацыю, каб даведацца больш." -INSTL_CONNECT_DB="Канфігурацыя базы даных" +INSTL_CONNECT_DB="Параметры базы дадзеных" INSTL_INSTALL_JOOMLA="Усталяваць Joomla" ; Site View -INSTL_ADMIN_EMAIL_DESC="Адрас электроннай пошты суперкарыстальніка" -INSTL_ADMIN_PASSWORD_DESC="Задайце пароль для ўліковага запісу суперкарыстальніка" -INSTL_ADMIN_PASSWORD_LENGTH="Пароль павінны быць не менш за 12 знакаў." -INSTL_ADMIN_USERNAME_DESC="Задайце назву ўліковага запісу суперкарыстальніка (лагін)" -INSTL_ADMIN_USER_DESC="Сапраўднае імя Вашага суперкарыстальніка" +INSTL_ADMIN_EMAIL_DESC="Увядзіце E-mail адміністратара." +INSTL_ADMIN_PASSWORD_DESC="Задайце пароль для ўліковага запісу Суперкарыстальніка." +INSTL_ADMIN_PASSWORD_LENGTH="Увядзіце не менш за 12 знакаў." +INSTL_ADMIN_USERNAME_DESC="Задайце назву ўліковага запісу СуперКарыстальніка (лагіну)." +INSTL_ADMIN_USER_DESC="Увядзіце сапраўднае імя Вашага СуперКарыстальніка." INSTL_LOGIN_DATA="Параметры ўліковага запісу" INSTL_SETUP_SITE_NAME="Налады сайта" INSTL_SITE="Асноўная канфігурацыя" -INSTL_SITE_DEVMODE_LABEL="Выяўлены рэжым распрацоўвання" -INSTL_SITE_NAME_DESC="Якая назва будзе ў Вашага сайта" +INSTL_SITE_DEVMODE_LABEL="Выяўлены рэжым распрацоўкі" +INSTL_SITE_NAME_DESC="Увядзіце назву Вашага сайта." ; Expert View INSTL_PUBLIC_FOLDER_DESC="Адносны альбо абсалютны шлях да агульнай папкі" @@ -120,29 +119,29 @@ INSTL_PUBLIC_FOLDER_DESC_SHORT="Адносны альбо абсалютны ш ; Complete view INSTL_COMPLETE_ADD_EXTRA_LANGUAGE="Усталяваць дадатковыя моўныя пакеты" -INSTL_COMPLETE_ADMIN_BTN="Адкрыць панэль адміністратара" -INSTL_COMPLETE_CONGRAT="Усталяванне скончанае! " +INSTL_COMPLETE_ADMIN_BTN="Адкрыць панэль кіравання" +INSTL_COMPLETE_CONGRAT="Усталёўка скончаная! " INSTL_COMPLETE_ERROR_FOLDER_DELETE="Не ўдалося выдаліць каталог \"%s\". Выдаліце ​​яго ўручную." -INSTL_COMPLETE_FINAL="Усталяванне завершанае" -INSTL_COMPLETE_FINAL_DESC="Joomla ўсталяваная і гатовая да выкарыстання." +INSTL_COMPLETE_FINAL="Усталёўка завершана" +INSTL_COMPLETE_FINAL_DESC="Joomla паспяхова ўсталявана і гатова да выкарыстання." INSTL_COMPLETE_REMOVE_FOLDER="Выдаліць каталог \"%s\"" INSTL_COMPLETE_SITE_BTN="Адкрыць сайт" -INSTL_COMPLETE_TITLE="Віншуем! Вы ўсталявалі Joomla! Ваш сайт гатовы да працы." +INSTL_COMPLETE_TITLE="Віншуем! Вы паспяхова ўсталявалі Joomla! Ваш сайт гатовы да працы." INSTL_REMOVE_INST_FOLDER="Вы ўпэўнены? Пацвердзіўшы, Вы незваротна выдаліце каталог \"%s\"." ; Languages view INSTL_LANGUAGES="Усталяваць дадатковыя моўныя пакеты" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE="Мова" -INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_SELECT="Выбар мовы" -INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_TAG="Цэтлік мовы" +INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_SELECT="Выберыце мову" +INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_TAG="Тэг мовы" INSTL_LANGUAGES_COLUMN_HEADER_VERSION="Версія" -INSTL_LANGUAGES_DESC="Інтэрфейс Joomla даступны на мностве моў. Выберыце патрэбныя моўныя пакеты і націсніце \"Усталяваць выбраныя мовы\".

Увага: кожны моўны пакет заладоўваецца каля 10 секунд. Не рэкамендуецца ўсталёўваць больш за тры моўныя пакеты адначасова." -INSTL_LANGUAGES_MESSAGE_PLEASE_WAIT="Працэс зойме каля 10 секунд для кожнай мовы.
Пачакайце, пакуль усе моўныя пакеты ўсталююцца…" -INSTL_LANGUAGES_NO_LANGUAGE_SELECTED="Калі ласка, выберыце мову. Калі ўсталёўваць іншыя мовы не патрэбна, націсніце \"Прапусціць\"." -INSTL_LANGUAGES_SELECTED="Усталяваць выбраныя мовы" -INSTL_LANGUAGES_WARNING_BACK_BUTTON="Назад да папярэдняга кроку ўсталявання" -INSTL_LANGUAGES_WARNING_NO_INTERNET="Не ўдалося падлучыцца да сервера моўных пакетаў Joomla. Калі ласка, завяршыце ўсталяванне." -INSTL_LANGUAGES_WARNING_NO_INTERNET2="Увага: Вы зможаце ўсталяваць моўныя пакеты пазней у панэлі адміністратара Joomla." +INSTL_LANGUAGES_DESC="Інтэрфейс Joomla даступны на мностве моваў. Абярыце неабходныя моўныя пакеты і націсніце \"Далей\".

На ўсталёўку кожнага моўнага пакета неабходна каля 10 секунд. Не рэкамендуецца выбіраць больш за тры моўныя пакеты адначасова." +INSTL_LANGUAGES_MESSAGE_PLEASE_WAIT="На ўсталёўку кожнага моўнага пакета неабходна каля 10 секунд. Калі ласка, пачакайце пакуль моўныя пакеты будуць загружаны і ўсталяваны." +INSTL_LANGUAGES_NO_LANGUAGE_SELECTED="Калі ласка, абярыце моўныя пакеты для ўстаноўкі." +INSTL_LANGUAGES_SELECTED="Усталюйце выбраныя мовы" +INSTL_LANGUAGES_WARNING_BACK_BUTTON="Назад" +INSTL_LANGUAGES_WARNING_NO_INTERNET="Не ўдалося падключыцца да сервера моўных пакетаў Joomla! Калі ласка, завяршыце працэс усталёўкі." +INSTL_LANGUAGES_WARNING_NO_INTERNET2="Вы зможаце ўсталяваць моўныя пакеты пазней у панэлі кіравання Joomla." ; Automated Updates Opt Out INSTL_AUTOMATED_UPDATES="Аўтаматычныя абнаўленні" @@ -152,87 +151,87 @@ INSTL_COMPLETE_ERROR_AUTOMATED_UPDATES_DISABLE="Не атрымалася адк INSTL_DISABLE_AUTOUPDATE="Вы ўпэўненыя, што хочаце адключыць аўтаматычныя абнаўленні?" ; Default language view -INSTL_DEFAULTLANGUAGE_ADMINISTRATOR="Мова панэлі адміністратара" -INSTL_DEFAULTLANGUAGE_ADMIN_COULDNT_SET_DEFAULT="Не ўдалося задаць мову як стандартную. Англійская мова будзе заданая ў якасці стандартнай для панэлі адміністратара." -INSTL_DEFAULTLANGUAGE_ADMIN_SET_DEFAULT="Мова \"%s\" заданая стандартнай для панэлі адміністратара." +INSTL_DEFAULTLANGUAGE_ADMINISTRATOR="Мова панэлі кіравання" +INSTL_DEFAULTLANGUAGE_ADMIN_COULDNT_SET_DEFAULT="Не ўдалося задаць мову як стандартную. Англійская мова будзе заданая ў якасці стандартнай для панэлі кіравання." +INSTL_DEFAULTLANGUAGE_ADMIN_SET_DEFAULT="Мова \"%s\" усталявана па змаўчанні для панэлі кіравання." INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_LANGUAGE="Мова" -INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_SELECT="Выбар" +INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_SELECT="Выбраць" INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_TAG="Цэтлік" -INSTL_DEFAULTLANGUAGE_COULD_NOT_DOWNLOAD_PACKAGE="Не ўдалося заладаваць ці распакаваць моўны пакет з URL-адраса: %s" -INSTL_DEFAULTLANGUAGE_COULD_NOT_INSTALL_LANGUAGE="Не ўдалося ўсталяваць моўны пакет \"%s\"." -INSTL_DEFAULTLANGUAGE_DESC="Моўныя пакеты ўсталяваныя. Выберыце стандартную мову для панэлі адміністратара." -INSTL_DEFAULTLANGUAGE_DESC_FRONTEND="Моўныя пакеты ўсталяваныя. Выберыце стандартную мову для сайта." -INSTL_DEFAULTLANGUAGE_FRONTEND="Стандартная мова сайта" +INSTL_DEFAULTLANGUAGE_COULD_NOT_DOWNLOAD_PACKAGE="Не атрымалася загрузіць ці распакаваць моўны пакет па URL спасылцы: %s." +INSTL_DEFAULTLANGUAGE_COULD_NOT_INSTALL_LANGUAGE="Не атрымалася ўсталяваць моўны пакет \"%s\"." +INSTL_DEFAULTLANGUAGE_DESC="Моўныя пакеты ўсталяваны. Калі ласка, абярыце мову па змаўчанні для панэлі кіравання і націсніце \"Усталяваць па змаўчанні\"." +INSTL_DEFAULTLANGUAGE_DESC_FRONTEND="Моўныя пакеты ўсталяваны. Калі ласка, абярыце мову па змаўчанні для сайта і націсніце \"Усталяваць па змаўчанні\"." +INSTL_DEFAULTLANGUAGE_FRONTEND="Мова сайта па змаўчанні" INSTL_DEFAULTLANGUAGE_FRONTEND_COULDNT_SET_DEFAULT="Не ўдалося задаць мову як стандартную. Англійская мова будзе заданая ў якасці стандартнай для сайта." -INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Мова \"%s\" заданая стандартнай для сайта." -INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Задаць стандартныя мовы" -INSTL_DEFAULTLANGUAGE_TRY_LATER="Вы зможаце ўсталяваць пакет пазней у панэлі адміністратара Joomla." +INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Мова \"%s\" усталявана па змаўчанні для сайта." +INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Усталяваць па змаўчанні" +INSTL_DEFAULTLANGUAGE_TRY_LATER="Вы зможаце ўсталяваць яе пазней у панэлі кіравання Joomla." -INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Беларуская" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español +INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Беларуская (BY)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español ; Database Model -INSTL_DATABASE_COULD_NOT_CONNECT="Не ўдалося падлучыцца да базы даных. Тэкст памылкі: %s." -INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="Нельга падлучыцца да базы даных, і не ўдалося стварыць базу даных. Cпраўдзіце свае налады і пры патрэбе стварыце базу даных уручную." -INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="Не ўдалося абнавіць кэш маніфеста для пашырэння %s." -INSTL_DATABASE_ERROR_BACKINGUP="Пры стварэнні рэзервовай копіі базы даных узніклі некаторыя памылкі." -INSTL_DATABASE_ERROR_CREATE="Узнікла памылка пры спробе стварыць базу даных %s.
Можа быць, карыстальніку не стае прывілеяў для стварэння базы даных. Можа спатрэбіцца стварыць гэтую базу даных асобна, перш чым усталёўваць Joomla." -INSTL_DATABASE_ERROR_DELETE="Пры выдаленні базы даных узніклі некаторыя памылкі." -INSTL_DATABASE_ERROR_READING_SQL_FILE="Не ўдалося прачытаць файл SQL." -INSTL_DATABASE_FIELD_VALUE_BACKUP="Рэзерваваць" +INSTL_DATABASE_COULD_NOT_CONNECT="Не атрымалася падлучыцца да базы дадзеных: %s." +INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="Не атрымалася падлучыцца да базы дадзеных і не ўдалося стварыць базу дадзеных. Калі ласка, праверце параметры і пры неабходнасці стварыце базу дадзеных уручную." +INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="Не ўдалося абнавіць кэш маніфесту для пашырэння: %s" +INSTL_DATABASE_ERROR_BACKINGUP="Пры стварэнні рэзервовай копіі базы дадзеных адбыліся некаторыя памылкі." +INSTL_DATABASE_ERROR_CREATE="Адбылася памылка пры спробе стварыць базу дадзеных %s.
Магчыма, у карыстальніка недастаткова прывілеяў для стварэння базы дадзеных. Магчыма, спатрэбіцца стварыць неабходную базу дадзеных асобна, перш чым вы зможаце ўсталяваць Joomla" +INSTL_DATABASE_ERROR_DELETE="Пры выдаленні базы дадзеных адбыліся некаторыя памылкі." +INSTL_DATABASE_ERROR_READING_SQL_FILE="Не ўдалося прачытаць SQL файл." +INSTL_DATABASE_FIELD_VALUE_BACKUP="Рэзервовая копія" INSTL_DATABASE_FIELD_VALUE_REMOVE="Выдаліць" INSTL_DATABASE_FILE_DOES_NOT_EXIST="Файл %s не існуе." -INSTL_DATABASE_FIX_LOWERCASE="Прэфікс табліц PostgreSQL мусіць быць у ніжнім рэгістры." -INSTL_DATABASE_FIX_TOO_LONG="Прэфікс табліц MySQL мусіць змяшчаць не больш за 15 знакаў." -INSTL_DATABASE_INVALID_DB_DETAILS="Параметры базы даных няправільныя або не ўведзеныя." +INSTL_DATABASE_FIX_LOWERCASE="Прэфікс табліцы павінен ўтрымліваць сімвалы ў ніжнім рэгістры для PostgreSQL." +INSTL_DATABASE_FIX_TOO_LONG="Прэфікс табліцы MySQL павінен змяшчаць не больш 15 знакаў." +INSTL_DATABASE_INVALID_DB_DETAILS="Прадстаўленыя звесткі аб базе дадзеных няслушныя і/або пустыя." INSTL_DATABASE_INVALID_MARIADB_VERSION="Каб працягнуць усталяванне, Вам трэба MariaDB версіі %1$s або навейшай. Ваша версія: %2$s." -INSTL_DATABASE_INVALID_MYSQLI_VERSION="Каб працягнуць усталяванне, Вам трэба MySQL версіі %1$s або навейшай. Ваша версія: %2$s" -INSTL_DATABASE_INVALID_MYSQL_VERSION="Каб працягнуць усталяванне, Вам трэба MySQL версіі %1$s або навейшай. Ваша версія: %2$s" -INSTL_DATABASE_INVALID_PGSQL_VERSION="Каб працягнуць усталяванне, Вам трэба PostgreSQL версіі %1$s або навейшай. Ваша версія: %2$s" -INSTL_DATABASE_INVALID_POSTGRESQL_VERSION="Каб працягнуць усталяванне, Вам трэба PostgreSQL версіі %1$s або навейшай. Ваша версія: %2$s" -INSTL_DATABASE_INVALID_TYPE="Калі ласка, выберыце тып базы даных." -INSTL_DATABASE_NAME_INVALID_CHAR="Ідэнтыфікатар MySQL не можа змяшчаць NULL ASCII (0x00)." -INSTL_DATABASE_NAME_INVALID_SPACES="Назвы базы даных і табліц MySQL не могуць пачынацца ці канчацца прабеламі." -INSTL_DATABASE_NAME_TOO_LONG="Назва базы даных MySQL мусіць змяшчаць не больш за 64 знакі." +INSTL_DATABASE_INVALID_MYSQLI_VERSION="Каб працягуць усталяванне вам патрэбны MySQL %1$s або вышэй. Ваша версія: %2$s" +INSTL_DATABASE_INVALID_MYSQL_VERSION="Каб працягуць усталяванне вам патрэбны MySQL %1$s або вышэй. Ваша версія: %2$s" +INSTL_DATABASE_INVALID_PGSQL_VERSION="Для працягу ўсталёўкі вам спатрэбіцца PostgreSQL %1$s або вышэй. Ваша версія: %2$s" +INSTL_DATABASE_INVALID_POSTGRESQL_VERSION="Для працягу ўсталёўкі вам спатрэбіцца PostgreSQL %1$s або вышэй. Ваша версія: %2$s" +INSTL_DATABASE_INVALID_TYPE="Выберыце тып базы дадзеных." +INSTL_DATABASE_NAME_INVALID_CHAR="Ідэнтыфікатар MySQL не можа мець NULL ASCII (0x00)." +INSTL_DATABASE_NAME_INVALID_SPACES="Імёны баз дадзеных MySQL і імёны табліц не могуць пачынацца або заканчвацца прабеламі." +INSTL_DATABASE_NAME_TOO_LONG="Імя базы дадзеных MySQL павінна складацца максімум з 64 знакаў." ; Controllers -INSTL_COOKIES_NOT_ENABLED="Здаецца, у Вашым браўзеры не дазволеныя файлы cookie або на серверы ўзнікла праблема з інструкцыяй session.save_path. У такім разе звярніцеся да свайго хостынг-правайдара, калі Вы не ведаеце, як гэта праверыць ці выправіць самастойна." +INSTL_COOKIES_NOT_ENABLED="Файлы cookie, напэўна, не ўключаныя ў вашым браўзэры-кліенце. Вы не зможаце ўсталяваць прыкладанне з адключанай гэтай функцыяй. У якасці альтэрнатывы, таксама можа паўстаць праблема з session.save_path сервера . Калі гэта так, калі ласка, пракансультуйцеся з вашым хостынг-правайдэрам, калі вы не ведаеце, як праверыць ці выправіць гэта самастойна." INSTL_HEADER_ERROR="Памылка" ; Helpers -INSTL_PAGE_TITLE="Усталёўнік Joomla" +INSTL_PAGE_TITLE="Усталёўшчык Joomla" ; Configuration model -INSTL_ERROR_CONNECT_DB="Не ўдалося падлучыцца да базы даных. Код памылкі: %d." -INSTL_STD_OFFLINE_MSG="Сайт закрыты на тэхнічнае абслугоўванне.
Калі ласка, зайдзіце пазней." +INSTL_ERROR_CONNECT_DB="Не атрымалася падлучыцца да базы дадзеных. Тэкст памылкі: %d." +INSTL_STD_OFFLINE_MSG="Сайт закрыты на тэхнічнае абслугоўванне.
Калі ласка, зайдзіце крыху пазней." ; Languages model -INSTL_ERROR_INVALID_URL="Некарэктны URL-адрас" +INSTL_ERROR_INVALID_URL="Некарэктны URL-адрас." ; Others -INSTL_CONFPROBLEM="Ваш канфігурацыйны файл ці каталог недаступны для запісу, або ўзнікла праблема пры стварэнні канфігурацыйнага файла. Калі ласка, вылучыце ўвесь прыведзены код у тэкставай пляцоўцы і ўстаўце ў новы тэкставы файл. Назавіце файл \"configuration.php\" і заладуйце яго ў каранёвы каталог Вашага сайта." -INSTL_DISPLAY_ERRORS="Паказ памылак" +INSTL_CONFPROBLEM="Ваш канфігурацыйны файл або папка недаступныя для запісу або паўстала праблема са стварэннем канфігурацыйнага файла. Вам прыйдзецца загрузіць наступны код ўручную. Вылучыце ў тэкставай вобласці ўвесь код, а затым устаўце ў новы тэкставы файл. Назавіце гэты файл\"configuration.php \" і загрузіце яго ў каранёвую папку вашага сайта." +INSTL_DISPLAY_ERRORS="Адлюстраванне памылак" INSTL_ERROR="Памылка" -INSTL_ERROR_DB="Пры запаўненні базы даных узніклі некаторыя памылкі: %s." -INSTL_ERROR_INITIALISE_SCHEMA="Не ўдаецца ініцыялізаваць схему базы даных." -INSTL_EXTENSION_AVAILABLE="Даступнае %s" -INSTL_FILE_UPLOADS="Заладаванне файлаў" +INSTL_ERROR_DB="Пры запаўненні базы дадзеных адбыліся некаторыя памылкі: %s." +INSTL_ERROR_INITIALISE_SCHEMA="Не ўдаецца ініцыялізаваць схему базы дадзеных." +INSTL_EXTENSION_AVAILABLE="%s даступна" +INSTL_FILE_UPLOADS="Загрузка файлаў" INSTL_GNU_GPL_LICENSE="Агульная грамадская ліцэнзія GNU" -INSTL_HELP_LINK="Дапамога з усталяваннем Joomla" -INSTL_NOTICE_NEEDSTOBEWRITABLE="Вы ўсё яшчэ можаце працягнуць усталяванне, калі наладзіце дазволы." +INSTL_HELP_LINK="Дапамога ва ўсталёўцы Joomla" +INSTL_NOTICE_NEEDSTOBEWRITABLE="Вы ўсё яшчэ можаце працягнуць усталёўку, калі адновіце правы доступу." INSTL_OUTPUT_BUFFERING="Буферызацыя вываду" INSTL_PHP_VERSION="Версія PHP" -INSTL_PHP_VERSION_NEWER="Версія PHP >=%s" -INSTL_PROCESS_BUSY="Працэс ідзе поўным ходам. Калі ласка, пачакайце…" -INSTL_SESSION_AUTO_START="Аўтаматычны запуск сеанса" -INSTL_WRITABLE="Няма дазволу на стварэнне файла %s" +INSTL_PHP_VERSION_NEWER="Версія PHP > = %s" +INSTL_PROCESS_BUSY="Працэс ідзе поўным ходам. Калі ласка, пачакайце …" +INSTL_SESSION_AUTO_START="Аўтаматычны запуск сеансу" +INSTL_WRITABLE="Недастаткова дазволу для стварэння файла %s." INSTL_ZIP_SUPPORT_AVAILABLE="Убудаваная падтрымка ZIP" ; Global strings JADMINISTRATOR="Адміністратар" JCLOSE="Закрыць" -JEMAIL="Электронны адрас" +JEMAIL="Email" JERROR="Памылка" -JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="Узнікла памылка апрацавання Вашага запыту." +JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="Падчас апрацоўкі вашага запыту адбылася памылка." JGLOBAL_ISFREESOFTWARE="%s - з'яўляецца бясплатным праграмным забеспячэннем, што распаўсюджваецца па ліцэнзіі GNU General Public License." JGLOBAL_LANGUAGE_VERSION_NOT_PLATFORM="Моўны пакет не адпавядае гэтай версіі Joomla!. Некаторыя радкі могуць адсутнічаць і будуць адлюстроўвацца на англійскай мове." JGLOBAL_SELECT_AN_OPTION="Выберыце параметр" @@ -250,42 +249,42 @@ JPREVIOUS="Папярэдні" JSHOWPASSWORD="Паказаць пароль" JSITE="Сайт" JSKIP="Прапусціць" -JUSERNAME="Імя карыстальніка" +JUSERNAME="Лагін" JYES="Так" ; Framework strings necessary when no lang pack is available JLIB_DATABASE_ERROR_CONNECT_MYSQL="Не атрымалася падлучыцца да MySQL." -JLIB_DATABASE_ERROR_DATABASE="Узнікла памылка базы даных." -JLIB_DATABASE_ERROR_LOAD_DATABASE_DRIVER="Не атрымалася загрузіць драйвер базы даных: %s" -JLIB_DATABASE_ERROR_VALID_MAIL="Калі ласка, увядзіце правільны адрас электроннай пошты." -JLIB_ENVIRONMENT_SESSION_EXPIRED="Тэрмін Вашага сеанса скончыўся. Калі ласка, абнавіце старонку." -JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: Шлях не вядзе да каталога. Шлях: %2$s" -JLIB_FORM_FIELD_INVALID="Няправільна запоўненае поле: " -JLIB_FORM_VALIDATE_FIELD_INVALID="Няправільна запоўненае поле: %s." -JLIB_FORM_VALIDATE_FIELD_REQUIRED="Абавязковае поле: %s." -JLIB_INSTALLER_ABORT="Спыненне ўсталявання мовы: %s" -JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Пашырэнне %1$s: не ўдалося стварыць каталог: %2$s." -JLIB_INSTALLER_ABORT_NOINSTALLPATH="Шлях усталявання не існуе." -JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Пакет %1$s: узнікла памылка ўсталявання пашырэння: %2$s." -JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="Пакет %s: няма файлаў для ўсталявання!" -JLIB_INSTALLER_ERROR_DOWNLOAD_SERVER_CONNECT="Памылка падлучэння да сервера: %s." -JLIB_INSTALLER_ERROR_FAIL_COPY_FILE="JInstaller: :Install: не ўдалося скапіяваць файл %1$s у %2$s." +JLIB_DATABASE_ERROR_DATABASE="Адбылася памылка базы дадзеных." +JLIB_DATABASE_ERROR_LOAD_DATABASE_DRIVER="Не атрымалася загрузіць драйвер базы дадзеных: %s" +JLIB_DATABASE_ERROR_VALID_MAIL="Уведзены вамі адрас электроннай пошты несапраўдны. Калі ласка, увядзіце іншы адрас электроннай пошты." +JLIB_ENVIRONMENT_SESSION_EXPIRED="Тэрмін дзеяння вашага сеансу скончыўся, калі ласка, перазагрузіце старонку." +JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: Шлях не вядзе да каталогу. Шлях: %2$s" +JLIB_FORM_FIELD_INVALID="Недапушчальнае поле: " +JLIB_FORM_VALIDATE_FIELD_INVALID="Некарэктна запоўнена поле: %s" +JLIB_FORM_VALIDATE_FIELD_REQUIRED="Неабходна запоўніць - абавязковае поле: %s" +JLIB_INSTALLER_ABORT="Перапыненне ўсталявання моўнага пакету: %s" +JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Пашырэнне %1$s: не атрымалася стварыць каталог: %2$s" +JLIB_INSTALLER_ABORT_NOINSTALLPATH="Шлях да усталёўкі не існуе." +JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Пакет %1$s: Адбылася памылка падчас усталёўкі пашырэння: %2$s." +JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="Пакет %s: не атрымалася знайсці файлы для ўсталёўкі!" +JLIB_INSTALLER_ERROR_DOWNLOAD_SERVER_CONNECT="Памылка падключэння да сервера: %s" +JLIB_INSTALLER_ERROR_FAIL_COPY_FILE="JInstaller: :Install: Не атрымалася скапіяваць файл %1$s у %2$s." JLIB_INSTALLER_INSTALL="Усталяваць" -JLIB_INSTALLER_NOT_ERROR="Калі памылка звязаная з усталяваннем моўных файлаў TinyMCE, яна не ўплывае на ўсталяванне моў. Некаторыя моўныя пакеты, створаныя раней за Joomla 3.2.0, могуць спрабаваць усталяваць асобныя моўныя файлы TinyMCE. Цяпер яны змешчаныя ў ядры, таму іх больш не трэба ўсталёўваць." -JLIB_INSTALLER_WARNING_UNABLE_TO_INSTALL_CONTENT_LANGUAGE="Нельга стварыць мову змесціва для мовы %s: %s." -JLIB_UPDATER_ERROR_COLLECTION_FOPEN="Дырэктыва PHP allow_url_fopen мусіць быць падлучаная, каб інструмент абнаўлення працаваў." -JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL="Абнаўленне: :Collection: не ўдалося адкрыць %s." -JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL="Абнаўленне: :Collection: не ўдалося прааналізаваць %s." +JLIB_INSTALLER_NOT_ERROR="Калі памылка звязана з усталяваннем моўных файлаў TinyMCE, яна не ўплывае на ўсталяванне моваў. Некаторыя моўныя пакеты, створаныя да Joomla 3.2.0, могуць спрабаваць усталяваць асобныя моўныя файлы TinyMCE. Паколькі яны цяпер уключаны ў ядро, іх больш не трэба ўсталёўваць." +JLIB_INSTALLER_WARNING_UNABLE_TO_INSTALL_CONTENT_LANGUAGE="Немагчыма стварыць мову змесціва для мовы %s: %s." +JLIB_UPDATER_ERROR_COLLECTION_FOPEN="Дырэктыва PHP allow_url_fopen адключаная. Гэты параметр павінен быць уключаны, каб праграма абнаўлення працавала." +JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL="Update: :Collection: Немагчыма адкрыць %s" +JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL="Update: :Collection: не атрымалася разабраць %s" JLIB_UPDATER_ERROR_OPEN_UPDATE_SITE="Абнаўленне: не ўдалося адкрыць сайт абнаўлення #%d "%s", URL: %s." -JLIB_UTIL_ERROR_CONNECT_DATABASE="JDatabase: :getInstance: не ўдалося падлучыцца да базы даных
joomla.library: %1$s — %2$s." +JLIB_UTIL_ERROR_CONNECT_DATABASE="JDatabase: :getInstance: Немагчыма падключыцца да базы дадзеных.
joomla.library: %1$s - %2$s." ; Strings for the language debugger -JDEBUG_LANGUAGE_FILES_IN_ERROR="Памылкі аналізу ў моўных файлах" -JDEBUG_LANGUAGE_UNTRANSLATED_STRING="Неперакладзеныя радкі" +JDEBUG_LANGUAGE_FILES_IN_ERROR="Памылкі разбору ў моўных файлах" +JDEBUG_LANGUAGE_UNTRANSLATED_STRING="Не перакладзеныя радкі" JNONE="Не" ; Necessary for errors -ADMIN_EMAIL="Электронны адрас адміністратара" +ADMIN_EMAIL="E-mail адміністратара" ADMIN_PASSWORD="Пароль адміністратара" SITE_NAME="Назва сайта" @@ -305,10 +304,10 @@ WARNING="Папярэджанне" ; Javascript ajax error messages JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Падчас атрымання даных JSON адбылося перапыненне злучэння." -JLIB_JS_AJAX_ERROR_NO_CONTENT="Ніякае змесціва не вернутае." -JLIB_JS_AJAX_ERROR_OTHER="Узнікла памылка пры атрыманні даных JSON: код стану HTTP %d." -JLIB_JS_AJAX_ERROR_PARSE="Узнікла памылка аналізу прыведзеных даных JSON:
%s" -JLIB_JS_AJAX_ERROR_TIMEOUT="Перавышаны час чакання пры атрыманні даных JSON." +JLIB_JS_AJAX_ERROR_NO_CONTENT="Змест не вернуты." +JLIB_JS_AJAX_ERROR_OTHER="Адбылася памылка пры атрыманні даных JSON: код стану HTTP %s." +JLIB_JS_AJAX_ERROR_PARSE="Падчас апрацоўкі наступных даных JSON адбылася памылка разбору:
%s" +JLIB_JS_AJAX_ERROR_TIMEOUT="Перавышаны час чакання адказу падчас атрымання даных JSON." ; Field password messages JFIELD_PASSWORD_INDICATE_COMPLETE="Пароль прыняты" @@ -318,10 +317,10 @@ JFIELD_PASSWORD_TOO_LONG="Пароль занадта доўгі. Паролі JFIELD_PASSWORD_TOO_SHORT_N="Пароль занадта кароткі. Паролі павінны ўтрымліваць не менш %s сімвалаў." ; Javascript Form Validation Messages -JLIB_FORM_CONTAINS_INVALID_FIELDS="Форма не можа быць адпраўленая, бо ў ёй не стае патрэбных даных.
Выпраўце пазначаныя палі і паўтарыце спробу." -JLIB_FORM_FIELD_INVALID_VALUE="Гэтае значэнне няправільнае." +JLIB_FORM_CONTAINS_INVALID_FIELDS="Форма не можа быць адпраўлена, бо ў ёй адсутнічаюць неабходныя даныя.
Калі ласка, выпраўце пазначаныя палі і паўтарыце ізноў." +JLIB_FORM_FIELD_INVALID_VALUE="Гэта значэнне несапраўднае." JLIB_FORM_FIELD_REQUIRED_CHECK="Трэба выбраць адзін з варыянтаў." -JLIB_FORM_FIELD_REQUIRED_VALUE="Калі ласка, запоўніце гэтае поле." +JLIB_FORM_FIELD_REQUIRED_VALUE="Калі ласка, запоўніце гэта поле." ; Installation progress screen INSTL="Усталёўка" diff --git a/installation/language/be-BY/langmetadata.xml b/installation/language/be-BY/langmetadata.xml index fbd0f4ff0cc46..c77631c152f74 100644 --- a/installation/language/be-BY/langmetadata.xml +++ b/installation/language/be-BY/langmetadata.xml @@ -1,7 +1,7 @@ - Belarusian (Belarus) - 5.4.8 + Belarusian (be-BY) + 6.1.3 2026-07 Joomla Belarus Community (C) 2005 Open Source Matters, Inc. @@ -11,7 +11,7 @@ Belarusian (be-BY) - Belarusian (Belarus) + Belarusian (be-BY) be-BY 0 diff --git a/installation/language/bg-BG/joomla.cli.ini b/installation/language/bg-BG/joomla.cli.ini index 63389eb514a2b..08350fd9f72c8 100644 --- a/installation/language/bg-BG/joomla.cli.ini +++ b/installation/language/bg-BG/joomla.cli.ini @@ -1,11 +1,11 @@ -INSTL_ADMIN_EMAIL_DESC="Въведете имейл адреса на супер потребителя "_QQ_"Super User"_QQ_" на сайта" -INSTL_ADMIN_EMAIL_DESC_SHORT="Имейл адрес на акаунта на Супер потребителя на уебсайта" -INSTL_ADMIN_PASSWORD_DESC="Задайте паролата за вашия акаунт на супер потребител" -INSTL_ADMIN_PASSWORD_DESC_SHORT="Паролата на вашия Super User акаунт" +INSTL_ADMIN_EMAIL_DESC="Въведете имейл адреса на супер потребителя на сайта" +INSTL_ADMIN_EMAIL_DESC_SHORT="Имейл адресът на профила на супер потребителя на уебсайта" +INSTL_ADMIN_PASSWORD_DESC="Задайте паролата за вашия профил на супер потребител" +INSTL_ADMIN_PASSWORD_DESC_SHORT="Паролата на вашия профил на супер потребител" INSTL_ADMIN_USERNAME_DESC="Задайте потребителското име на вашия профил на супер потребител" -INSTL_ADMIN_USERNAME_DESC_SHORT="Потребителското име на вашия Super User акаунт" -INSTL_ADMIN_USER_DESC="Въведете реално име на вашия Super User" -INSTL_ADMIN_USER_DESC_SHORT="Реалното име на Super User акаунта" +INSTL_ADMIN_USERNAME_DESC_SHORT="Потребителско име на вашия профил на супер потребител" +INSTL_ADMIN_USER_DESC="Въведете реалното име на вашия супер потребител" +INSTL_ADMIN_USER_DESC_SHORT="Реално име на профила на супер потребителя" INSTL_DATABASE_COULD_NOT_CONNECT="%s" INSTL_DATABASE_ENCRYPTION_CA_LABEL="Път към CA файла за проверка на криптирането" INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Път към CA файла за проверка на криптирането" @@ -15,8 +15,8 @@ INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Поддържан шифър на па INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Поддържан шифър на пакети (по избор)" INSTL_DATABASE_ENCRYPTION_KEY_LABEL="SSL ключа за връзка с базата данни. Изисква се криптирането да бъде зададено на 2" INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="SSL ключа за връзка с базата данни. Изисква се криптирането да бъде зададено на 2" -INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Кодиране на връзката с базата данни. Стойности: 0=няма, 1=еднопосочно, 2=двупосочно" -INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="Кодиране на връзката с базата данни. Стойности: 0=няма, 1=еднопосочно, 2=двупосочно" +INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Криптиране на връзката с базата данни. Стойности: 0=няма, 1=еднопосочно, 2=двупосочно" +INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="Криптиране на връзката с базата данни. Стойности: 0=няма, 1=еднопосочно, 2=двупосочно" INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Проверете SSL сертификата за връзка с базата данни. Стойности: 0=Не, 1=Да. Изисква се криптирането да бъде зададено на 1 или 2" INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="Проверете SSL сертификата за връзка с базата данни. Стойности: 0=Не, 1=Да. Изисква се криптирането да бъде зададено на 1 или 2" INSTL_DATABASE_HOST_DESC="Хост на базата данни" @@ -33,6 +33,6 @@ INSTL_DATABASE_USER_DESC="Потребител на базата данни" INSTL_DATABASE_USER_DESC_SHORT="Потребител на базата данни" INSTL_PUBLIC_FOLDER_DESC="Относителен или абсолютен път към публичната папка" INSTL_PUBLIC_FOLDER_DESC_SHORT="Относителен или абсолютен път към публичната папка" -INSTL_SITE_NAME_DESC="Въведете име на Вашия Joomla сайт" +INSTL_SITE_NAME_DESC="Въведете името на Вашия Joomla сайт" INSTL_SITE_NAME_DESC_SHORT="Име на уебсайта" diff --git a/installation/language/bg-BG/joomla.ini b/installation/language/bg-BG/joomla.ini index 695459299f881..0980c8e1458b2 100644 --- a/installation/language/bg-BG/joomla.ini +++ b/installation/language/bg-BG/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Вашият хост трябва да използв BUILD_MIN_PHP_ERROR_URL_TEXT="Помогнете ми да разреша това" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Промяна" INSTL_SELECT_INSTALL_LANG="Изберете език за инсталиране" INSTL_SELECT_LANGUAGE_TITLE="Изберете език" INSTL_SETUP_LOGIN_DATA="Настройка на данни за вход" @@ -42,13 +43,9 @@ INSTL_WARNJSON="За да инсталирате Джумла! успешно JS INSTL_DATABASE_SUPPORT="Поддръжка на база данни:" INSTL_JSON_SUPPORT_AVAILABLE="Поддръжка на JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language е по подразбиране" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="Изключено претоварване на MB String" INSTL_NOTICE_DATABASE_SUPPORT="Не бяха намерени поддържани бази данни." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="За да инсталирате Джумла! успешно JSON трябва да бъде активиран в РНР файла!" INSTL_NOTICE_MBLANG_NOTDEFAULT="Функцията PHP mbstring language не е зададена като неутрална. Тя може да бъде променена локално като добавите следния код: php_value mbstring.language neutral във Вашия .htaccess файл." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Функцията PHP mbstring е включена. Тя може да бъде изключена локално като добавите следния код: php_value mbstring.func_overload 0 във Вашия .htaccess файл." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Необходимите php функции parse_ini_file и parse_ini_strin са деактивирани на вашия сървър." INSTL_NOTICE_XML_SUPPORT="Поддръжката на XML не е налична. Това трябва да бъде активирано по подразбиране в php, но потребителите на Ubuntu може да се наложи да го инсталират, като извършатsudo apt-get install php-xml последвано от рестартиране на уеб сървъра." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib компресирането не е настроена. Може да бъде включена локално чрез въвежданеzlib.output_compression = On във вашяphp.ini файл." diff --git a/installation/language/bg-BG/langmetadata.xml b/installation/language/bg-BG/langmetadata.xml index 9797cfb04f98f..cb5791a64ace6 100644 --- a/installation/language/bg-BG/langmetadata.xml +++ b/installation/language/bg-BG/langmetadata.xml @@ -1,7 +1,7 @@ Bulgarian (bg-BG) - 5.4.8 + 6.1.3 2026-07 Joomla! Bulgaria (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ca-ES/joomla.ini b/installation/language/ca-ES/joomla.ini index 9db327b53b32c..a423c85c7813c 100644 --- a/installation/language/ca-ES/joomla.ini +++ b/installation/language/ca-ES/joomla.ini @@ -5,56 +5,55 @@ ; Fatal error page ; These will be processed by the JavaScript Build -BUILD_FATAL_HEADER="Ho sentim, hi ha hagut un problema que no hem pogut recuperar." -BUILD_FATAL_LANGUAGE="Català ca_ES" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_FATAL_HEADER="Ho sentim, hi ha hagut un problema del qual no ens hem pogut recuperar." +BUILD_FATAL_LANGUAGE="Anglès GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_FATAL_TEXT="El servidor ha retornat \"{{statusCode_statusText}}\"" BUILD_FATAL_URL_TEXT="Ajuda'm a resoldre això" ; Build incomplete error page ; These will be processed by the JavaScript Build BUILD_INCOMPLETE_HEADER="Configuració de l'entorn incomplerta" -BUILD_INCOMPLETE_LANGUAGE="Català ca_ES" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_INCOMPLETE_TEXT="Sembla que estàs intentant executar Joomla! des del nostre repositori a git. Per a fer-ho, primer has de completar un parell de passos addicionals." +BUILD_INCOMPLETE_LANGUAGE="Anglès GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_INCOMPLETE_TEXT="Sembla que està intentant executar Joomla! des del nostre repositori en Git. Per a fer-ho, primer has de completar un parell de passos addicionals." BUILD_INCOMPLETE_URL_TEXT="Més detalls" ; No XML PHP error page ; These will be processed by the JavaScript Build BUILD_NOXML_HEADER="Ho sentim, al PHP li falta una llibreria imprescindible" -BUILD_NOXML_LANGUAGE="Català ca_ES" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_NOXML_LANGUAGE="Anglès GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_NOXML_TEXT="El teu servidor necessita fer servir PHP amb suport de la llibreria XML per executar aquesta versió de Joomla!" BUILD_NOXML_URL_TEXT="Ajuda'm a resoldre això" ; Minimum PHP error page ; These will be processed by the JavaScript Build -BUILD_MIN_PHP_ERROR_HEADER="Ho sentim, la teva versió de PHP no és compatible." -BUILD_MIN_PHP_ERROR_LANGUAGE="Català ca_ES" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_MIN_PHP_ERROR_HEADER="Ho sentim, la teva versió de PHP no es compatible." +BUILD_MIN_PHP_ERROR_LANGUAGE="Anglès GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_MIN_PHP_ERROR_TEXT="Cal que el teu servidor utilitzi la versió de PHP {{phpversion}} o posterior per executar aquesta versió de Joomla." BUILD_MIN_PHP_ERROR_URL_TEXT="Ajuda'm a resoldre això" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Canvia l'idioma d'instal·lació" +INSTL_CHANGE_INSTALL_LANG_SHORT="Canviar" +INSTL_SELECTED_INSTALL_LANGUAGE="Idioma actual: %s" INSTL_SELECT_INSTALL_LANG="Selecciona l'idioma d'instal·lació" INSTL_SELECT_LANGUAGE_TITLE="Triar idioma" INSTL_SETUP_LOGIN_DATA="Configurar dades d'entrada" -INSTL_WARNJAVASCRIPT="Avís! Cal que JavaScript estigui habilitat per a la correcta instal·lació de Joomla." -INSTL_WARNJSON="La teva instal·lació de PHP necessita tenir activat JSON perquè Joomla es pugui instal·lar!" +INSTL_WARNJAVASCRIPT="Avís! Cal que Javascript estigui habilitat per a la correcta instal·lació de Joomla." +INSTL_WARNJSON="La teva instal·lació de PHP necessita tenir activat JSON per Joomla per instal·lar-lo." ; Precheck view -INSTL_DATABASE_SUPPORT="Base de dades de Suport:" +INSTL_DATABASE_SUPPORT="Base de dades de suport: " INSTL_JSON_SUPPORT_AVAILABLE="Suport JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="Idioma MB és l'idioma per defecte" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="Sobrecàrrega Cadena MB deshabilitat" -INSTL_NOTICE_DATABASE_SUPPORT="No s'ha trobat cap base de dates compatible." -INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="La teva instal·lació de PHP necessita tenir activat JSON perquè Joomla es pugui instal·lar!" -INSTL_NOTICE_MBLANG_NOTDEFAULT="L'idioma mbstring de PHP no està definit com a neutre. Això es pot definir localment introduint php_value mbstring.language neutral al fitxer .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="La sobrecàrrega de la funció PHP mbstring està quantificada. Això es pot deshabilitar escrivint php_value mbstring.func_overload 0 al teu arxiu .htaccess." -INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Les funcions de PHP necessàries parse_ini_file and parse_ini_string estan deshabilitades al teu servidor." -INSTL_NOTICE_XML_SUPPORT="El suport XML no està disponible. Això hauria d'estar habilitat per defecte a PHP, però els usuaris d'Ubuntu poden necessitar instal·lar això des de la consola amb sudo apt-get install php-xml seguit d'un reinici del servidor web." +INSTL_NOTICE_DATABASE_SUPPORT="No es va trobar cap base de dates compatible." +INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="La teva instal·lació de PHP necessita tenir activat JSON per Joomla per instal·lar-lo." +INSTL_NOTICE_MBLANG_NOTDEFAULT="La cadena de Llenguatge PHP mbstring no s'ajusta a la posició neutral. Això es pot establir a nivell local mitjançant la introducció de mbstring.language php_value neutral al teu arxiu .htaccess ." +INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Les funciones de PHP necessàries parse_ini_file and parse_ini_string estan deshabilitades al teu servidor." +INSTL_NOTICE_XML_SUPPORT="No est'a disponible el suport de XML. Això hauria d'estar habilitat per defecte a PHP però els usuaris d'Ubuntu poden necessitar instal·lar-ho executant sudo apt-get install php-xml seguit d'una reiniciació del servidor." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="La compressió Zlib no està activada. Pot activar-se localment afegint zlib.output_compression = On al fitxer php.ini." INSTL_PARSE_INI_FILE_AVAILABLE="Suport Parser INI" INSTL_PRECHECK_ACTUAL="Actual" -INSTL_PRECHECK_DESC="Si algun d'aquests elements no està suportat, si us plau, emprèn les accions necessàries per a corregir-ho.
No es podrà instal·lar Joomla! fins que es compleixi amb els següents requisits." +INSTL_PRECHECK_DESC="Si algun d'aquests elements no està suportat, si us plau, emprengui les accions necessàries per a corregir-ho.
No podrà instal·lar Joomla! fins que es compleixin amb els següents requisits." INSTL_PRECHECK_DIRECTIVE="Directiva" INSTL_PRECHECK_RECOMMENDED="Recomanat" INSTL_PRECHECK_RECOMMENDED_SETTINGS_DESC="Aquesta configuració de PHP és la recomanada per assegurar una compatibilitat total amb Joomla." @@ -67,7 +66,7 @@ INSTL_ZLIB_COMPRESSION_SUPPORT="Suport a compressió Zlib" INSTL_DATABASE="Configuració de la Base de Dades" INSTL_DATABASE_ENCRYPTION_CA_LABEL="Ruta de l'arxiu CA" INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Ruta de l'arxiu del certificat" -INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Cipher Suite Suportada (opcional)" +INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Cipher Suite suportat (opcional)" INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Ruta a l'arxiu de clau privada" INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Encriptació de connexió" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="Per defecte (controlat pel servidor)" @@ -78,20 +77,20 @@ INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="L'arxiu introduït en el camp \"%s INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_EMPTY="El camp \"%s\"\ està buit o no conté una ruta vàlida." INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="Has introduït \"localhost\" com a nom de l'amfitrió. La connexió a la base de dades amb xifrat de connexió pot fallar amb això. Si canvies \"localhost\" a \"127.0.0.1\" o \ \"::1\" o un nom d'amfitrió diferent, o canvia el camp \"Encriptació de la connexió\" a \"Default (controlat pel servidor) \". " INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="El servidor de bases de dades no admet el xifrat de connexió. O bé activa el suport TLS (sovint anomenat SSL en documents) al servidor de bases de dades, o canvia el camp \"Encriptació de la connexió\ \" de nou a \"Per defecte (controlat per servidor) \"." -INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Verificar Certificat de Servidor" +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Verificar certificat de servidor" INSTL_DATABASE_ERROR_POSTGRESQL_QUERY="Ha fallat la consulta de base de dades PostgreSQL." -INSTL_DATABASE_HOST_DESC="Indiqui el nom del servidor, normalment \"localhost\" o un nom proporcionat pel vostre servei d'allotjament." +INSTL_DATABASE_HOST_DESC="Indiqui el nom del servidor, normalment \"localhost\" o un nom proporcionat pel seu servei de hospedatge." INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE="No vam ser capaços de crear l'arxiu. Si us plau, creï manualment un arxiu anomenat \"%1$s\" i pugi-ho a la carpeta \"%2$s\" del seu lloc Joomla i seleccioni \"%3$s\" per continuar." INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE="Per confirmar que ets el propietari d'aquest lloc web, si us plau, esborra el fitxer anomenat \"%1$s\" que s'ha creat a la carpeta \"%2$s\" del teu lloc Joomla i selecciona \"%3$s\" per continuar." -INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE="Esteu intentant utilitzar un amfitrió de base de dades que no es troba al vostre servidor local. Per motius de seguretat, heu de verificar la propietat del vostre compte d'allotjament web. Llegiu la documentació per obtenir més informació." +INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE="Està intentant usar un servidor de base de dades que no està en el seu servidor local. Per raons de seguretat, ha de verificar la propietat del seu compte d'allotjament web. Si us plau, llegeixi la documentació per a més infomració." INSTL_DATABASE_HOST_LABEL="Nom del servidor" -INSTL_DATABASE_NAME_DESC="Introduïu el nom de la base de dades." +INSTL_DATABASE_NAME_DESC="Nom de la base de dades." INSTL_DATABASE_NAME_LABEL="Nom de la base de dades" INSTL_DATABASE_NAME_MSG_MYSQL="El nom de la base de dades no és vàlid, no ha de contenir el següents caràcters: \ /" INSTL_DATABASE_NAME_MSG_POSTGRES="El nom de la base de dades no és vàlid. Ha de començar amb una lletra, seguida de caràcters alfanumèrics." INSTL_DATABASE_NO_SCHEMA="No hi ha esquema de base de dades per a aquest tipus de base de dades." INSTL_DATABASE_PASSWORD_DESC="Introduïu la contrasenya de la base de dades que heu creat o una contrasenya proporcionada pel vostre amfitrió." -INSTL_DATABASE_PREFIX_DESC="Introduïu un prefix de taula o utilitzeu el generat aleatòriament." +INSTL_DATABASE_PREFIX_DESC="Introdueix un prefix de taula o utilitza el generat aleatòriament." INSTL_DATABASE_PREFIX_DUPLICATE_DESC="Si utilitzeu una base de dades existent amb taules amb el mateix prefix, Joomla canviarà el nom d'aquestes taules existents afegint el prefix \"bak_\"." INSTL_DATABASE_PREFIX_MSG="El prefix de taula ha de començar per una lletra, opcionalment seguit par caràcters alfanumèrics i per un guió baix." INSTL_DATABASE_RESPONSE_ERROR="El procés d'instal·lació ha fallat." @@ -103,13 +102,13 @@ INSTL_CONNECT_DB="Configuració de la connexió de base de dades" INSTL_INSTALL_JOOMLA="Instal·lar Joomla" ; Site View -INSTL_ADMIN_EMAIL_DESC="Introduïu l'adreça electrònica del superusuari del lloc web." -INSTL_ADMIN_PASSWORD_DESC="Estableix la contrasenya del teu compte de Superusuari." +INSTL_ADMIN_EMAIL_DESC="Introdueix l'adreça de correu del superusuari del lloc web." +INSTL_ADMIN_PASSWORD_DESC="Contrasenya del compte de superusuari." INSTL_ADMIN_PASSWORD_LENGTH="Introdueix un mínim de 12 caràcters." -INSTL_ADMIN_USERNAME_DESC="Estableix el nom d'usuari per al teu compte de Superusuari." +INSTL_ADMIN_USERNAME_DESC="Pots canviar el nom del Superadministrador per defecte." INSTL_ADMIN_USER_DESC="Introdueix el nom real del superusuari." -INSTL_LOGIN_DATA="Dades d'Inici de Sessió" -INSTL_SETUP_SITE_NAME="Configurar Nom del Lloc" +INSTL_LOGIN_DATA="Dades d'entrades" +INSTL_SETUP_SITE_NAME="Configurar nom del lloc" INSTL_SITE="Configuració Principal" INSTL_SITE_DEVMODE_LABEL="Hem detectat el mode de desenvolupador" INSTL_SITE_NAME_DESC="Introdueix el nom del teu lloc Joomla." @@ -119,83 +118,83 @@ INSTL_PUBLIC_FOLDER_DESC="Camí relatiu o absolut a la carpeta pública" INSTL_PUBLIC_FOLDER_DESC_SHORT="Camí relatiu o absolut a la carpeta pública" ; Complete view -INSTL_COMPLETE_ADD_EXTRA_LANGUAGE="Instal·la Idiomes Addicionals" -INSTL_COMPLETE_ADMIN_BTN="Obrir Administrador" -INSTL_COMPLETE_CONGRAT="Enhorabona!" +INSTL_COMPLETE_ADD_EXTRA_LANGUAGE="Instal·lar idiomes addicionals" +INSTL_COMPLETE_ADMIN_BTN="Obrir administració" +INSTL_COMPLETE_CONGRAT="Felicitats!" INSTL_COMPLETE_ERROR_FOLDER_DELETE="La carpeta \"%s\" no s'ha pogut esborrar. Si us plau, esborra manualment la carpeta." INSTL_COMPLETE_FINAL="S'ha completat la instal·lació" INSTL_COMPLETE_FINAL_DESC="S'ha completat la instal·lació de Joomla i està llesta per utilitzar." INSTL_COMPLETE_REMOVE_FOLDER="Elimini la carpeta \"%s\"" -INSTL_COMPLETE_SITE_BTN="Obrir Lloc" -INSTL_COMPLETE_TITLE="Enhorabona! El vostre lloc web Joomla està a punt." -INSTL_REMOVE_INST_FOLDER="Esteu segur que voleu suprimir? Si ho confirmeu, la carpeta \"%s\" s'esborrarà permanentment." +INSTL_COMPLETE_SITE_BTN="Obrir lloc" +INSTL_COMPLETE_TITLE="Felicitats! Joomla! ja està instal·lat." +INSTL_REMOVE_INST_FOLDER="Estàs segur que vols esborrar? Si confirmes la carpeta \"%s\" s'esborrarà permanentment." ; Languages view -INSTL_LANGUAGES="Instal·la Idiomes Addicionals" +INSTL_LANGUAGES="Instal·lar idiomes addicionals" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE="Idioma" -INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_SELECT="Selecciona l'Idioma" -INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_TAG="Etiqueta de l'idioma" +INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_SELECT="Triar idioma" +INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_TAG="Etiqueta de l`idioma" INSTL_LANGUAGES_COLUMN_HEADER_VERSION="Versió" -INSTL_LANGUAGES_DESC="La interfície de Joomla està disponible en diversos idiomes. Trieu els idiomes que preferiu marcant les caselles de selecció i, a continuació, instal·leu-los seleccionant el botó \"Instal·la els Idiomes Seleccionats\".
Nota: Aquesta operació trigarà uns 10 segons a descarregar i instal·lar cada idioma. Per evitar temps d'espera, seleccioneu no més de 3 idiomes per instal·lar." -INSTL_LANGUAGES_MESSAGE_PLEASE_WAIT="Aquesta operació trigarà fins a 10 segons per idioma a completar-se.
Espereu mentre descarreguem i instal·lem els idiomes …" +INSTL_LANGUAGES_DESC="La interfície de Joomla està disponible en diversos idiomes. Triï els idiomes que desitgi seleccionant la seva casella de selecció i després premi el botó \"Instal·lar idioma seleccionat\".
Nota: aquesta operació pot trigar uns deu segons per idioma seleccionat a descarregar i instal·lar. Si us plau, no seleccioni més de 3 idiomes a instal·lar per evitar expiracions de temps." +INSTL_LANGUAGES_MESSAGE_PLEASE_WAIT="Aquesta operació pot trigar més de 10 segons per idioma per a completar-se.
Si us plau, esperi mentre es descarreguen i s'instal·len els idiomes...…" INSTL_LANGUAGES_NO_LANGUAGE_SELECTED="No s'han seleccionat idiomes per instal·lar." INSTL_LANGUAGES_SELECTED="Instal·leu els idiomes seleccionats" INSTL_LANGUAGES_WARNING_BACK_BUTTON="Tornar a la darrera etapa de la instal·lació" -INSTL_LANGUAGES_WARNING_NO_INTERNET="Joomla no s'ha pogut connectar al servidor d'idiomes. Si us plau, finalitzeu el procés d'instal·lació." -INSTL_LANGUAGES_WARNING_NO_INTERNET2="Nota: Podreu instal·lar idiomes més endavant amb l'Administrador de Joomla." +INSTL_LANGUAGES_WARNING_NO_INTERNET="Joomla! no ha pogut connectar amb el servidor d'idiomes. Finalitza el procés d'instal·lació." +INSTL_LANGUAGES_WARNING_NO_INTERNET2="Nota: Després podrà instal·lar altres idiomes des de l'administració de Joomla." ; Automated Updates Opt Out -INSTL_AUTOMATED_UPDATES="Actualitzacions Automatitzades" +INSTL_AUTOMATED_UPDATES="Actualitzacions automatitzades" INSTL_AUTOMATED_UPDATES_DESC="Joomla s'actualitza automàticament per a versions menors i de revisions.

Si us plau, tingueu en compte: Les actualitzacions automatitzades registraran el vostre lloc al servei respectiu proporcionat pel projecte Joomla!. El registre permet que el projecte Joomla accedeixi a informació sobre el vostre lloc i l'entorn del servidor, concretament l'URL del lloc, la versió de PHP, el tipus i la versió de la base de dades, la versió del CMS i el tipus i la versió del sistema operatiu del servidor. Aquesta informació només s'utilitza per millorar el servei.

Alternativament, podeu desactivar les actualitzacions automatitzades mitjançant el botó següent." INSTL_AUTOMATED_UPDATES_DISABLE="Desactiva les actualitzacions automàtiques" INSTL_COMPLETE_ERROR_AUTOMATED_UPDATES_DISABLE="No s'han pogut desactivar les actualitzacions automàtiques." INSTL_DISABLE_AUTOUPDATE="Esteu segur que voleu desactivar les actualitzacions automàtiques?" ; Default language view -INSTL_DEFAULTLANGUAGE_ADMINISTRATOR="Idioma per defecte de l'Administrador" -INSTL_DEFAULTLANGUAGE_ADMIN_COULDNT_SET_DEFAULT="Joomla no ha pogut establir l'idioma per defecte. L'anglès s'usarà com a predeterminat per a l'administració." -INSTL_DEFAULTLANGUAGE_ADMIN_SET_DEFAULT="Joomla ha establert %s com a idioma predeterminat de l'ADMINISTRADOR." +INSTL_DEFAULTLANGUAGE_ADMINISTRATOR="Idioma per defecte de l'administrador" +INSTL_DEFAULTLANGUAGE_ADMIN_COULDNT_SET_DEFAULT="Joomla no ha pogut assignar l'idioma com a predeterminat. S'usarà l'idioma anglès com a predeterminat per a l'administració." +INSTL_DEFAULTLANGUAGE_ADMIN_SET_DEFAULT="Joomla ha establert %s com a idioma per defecte per a la teva administració." INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_LANGUAGE="Idioma" INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_SELECT="Selecciona" INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_TAG="Etiqueta" -INSTL_DEFAULTLANGUAGE_COULD_NOT_DOWNLOAD_PACKAGE="Joomla ha fallat en descarregar o desempaquetar el paquet d'idiomes de: %s" +INSTL_DEFAULTLANGUAGE_COULD_NOT_DOWNLOAD_PACKAGE="Joomla no va poder descarregar o descomprimir el paquet d'idioma des de: %s" INSTL_DEFAULTLANGUAGE_COULD_NOT_INSTALL_LANGUAGE="Joomla no ha pogut instal·lar l'idioma %s." -INSTL_DEFAULTLANGUAGE_DESC="Joomla ha instal·lat els idiomes següents. Seleccioneu l'idioma predeterminat que vulgueu per a l'Administrador de Joomla." -INSTL_DEFAULTLANGUAGE_DESC_FRONTEND="Joomla ha instal·lat els idiomes següents. Seleccioneu l'idioma predeterminat que vulgueu per al Lloc de Joomla." -INSTL_DEFAULTLANGUAGE_FRONTEND="Idioma predeterminat del Lloc Web" -INSTL_DEFAULTLANGUAGE_FRONTEND_COULDNT_SET_DEFAULT="Joomla no ha pogut establir l'idioma per defecte. L'anglès s'utilitzarà com a idioma per defecte per al LLOC WEB." -INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Joomla ha establert %s com a idioma per defecte pel teu LLOC WEB." +INSTL_DEFAULTLANGUAGE_DESC="Joomla ha instal·lat els següents idiomes. Si us plau, seleccioni l'idioma que desitja usar com a predeterminat per a l'administració." +INSTL_DEFAULTLANGUAGE_DESC_FRONTEND="Joomla ha instal·lat els següents idiomes. Si us plau, seleccioni l'idioma que desitja usar com a predeterminat per a laweb." +INSTL_DEFAULTLANGUAGE_FRONTEND="Idioma per defecte del lloc web" +INSTL_DEFAULTLANGUAGE_FRONTEND_COULDNT_SET_DEFAULT="Joomla no ha pogut assignar l'idioma com a predeterminat. S'usarà l'idioma anglès com el predeterminat per al lloc web." +INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Joomla ha establert %s com a idioma per defecte pel teu lloc web." INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Assignar l'idioma predeterminat" -INSTL_DEFAULTLANGUAGE_TRY_LATER="Podreu instal·lar-lo més endavant amb l'Administrador de Joomla." +INSTL_DEFAULTLANGUAGE_TRY_LATER="Pots instal·lar-ho més endavant amb l'administració de Joomla." -INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Català (ca-ES)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español +INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Català (ES)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español ; Database Model -INSTL_DATABASE_COULD_NOT_CONNECT="No s'ha pogut connectar a la base de dades. El connector ha retornat el missatge d'error: %s" -INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="L'instal·lador no s'ha pogut connectar a la base de dades especificada i no ha pogut crear-la. Verifiqueu la configuració i, si cal, creeu la base de dades manualment." -INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="No s'ha pogut actualitzar la memòria cau del manifest per a l'extensió: %s" -INSTL_DATABASE_ERROR_BACKINGUP="S'han produït alguns errors en fer una còpia de seguretat de la base de dades." +INSTL_DATABASE_COULD_NOT_CONNECT="No es pot connectar amb la base de dades. El connector va retornar el missatge d'error %s" +INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="L'instal·lador no pot connectar a la base de dades especificada i no ha pogut crear la base de dades. Comprova la configuració i si és necessari crea manualment la base de dades." +INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="No s'ha pogut actualitzar la memòria cau per l'extensió: %s" +INSTL_DATABASE_ERROR_BACKINGUP="Ha hagut alguns errors en la còpia de seguretat de la base de dades." INSTL_DATABASE_ERROR_CREATE="S'ha produït un error quan s'intentava crear la base de dades %s.
Pot ser que l'usuari no tingui privilegis suficients per a crear una base de dades. Tal vegada necessita crear la base de dades abans d'intentar instal·lar Joomla" -INSTL_DATABASE_ERROR_DELETE="S'han produït alguns errors en suprimir la base de dades." +INSTL_DATABASE_ERROR_DELETE="Ha hagut alguns errors esborrant la base de dades." INSTL_DATABASE_ERROR_READING_SQL_FILE="No s'ha pogut llegir el fitxer SQL." INSTL_DATABASE_FIELD_VALUE_BACKUP="Còpia de seguretat" INSTL_DATABASE_FIELD_VALUE_REMOVE="Elimina" INSTL_DATABASE_FILE_DOES_NOT_EXIST="El fitxer %s no existeix." -INSTL_DATABASE_FIX_LOWERCASE="El prefix de la taula ha de ser en minúscula per a PostgreSQL." -INSTL_DATABASE_FIX_TOO_LONG="El prefix de la taula MySQL ha de tenir un màxim de 15 caràcters." -INSTL_DATABASE_INVALID_DB_DETAILS="Les dades de la base de dades proporcionades són incorrectes i/o buides." -INSTL_DATABASE_INVALID_MARIADB_VERSION="Necessiteu MariaDB %1$s o superior per continuar la instal·lació. La vostra versió és: %2$s" -INSTL_DATABASE_INVALID_MYSQLI_VERSION="Necessiteu MySQL %1$s o superior per continuar la instal·lació. La vostra versió és: %2$s" -INSTL_DATABASE_INVALID_MYSQL_VERSION="Necessiteu MySQL %1$s o superior per continuar la instal·lació. La vostra versió és: %2$s" +INSTL_DATABASE_FIX_LOWERCASE="El prefix ha de ser minúscula per Postgresql." +INSTL_DATABASE_FIX_TOO_LONG="El prefix de taula MySQL ha de tenir un màxim de 15 caràcters." +INSTL_DATABASE_INVALID_DB_DETAILS="Els detalls de la base de dades proporcionades són incorrectes o inexistents." +INSTL_DATABASE_INVALID_MARIADB_VERSION="Necessites MariaDB %1$s. o superior per continuar la instal·lació. La teva versió és: %2$s" +INSTL_DATABASE_INVALID_MYSQLI_VERSION="Necessites MySQL %1$s. o superior per continuar la instal·lació. La teva versió és: %2$s" +INSTL_DATABASE_INVALID_MYSQL_VERSION="Necessites MySQL %1$s. o superior per continuar la instal·lació. La teva versió és: %2$s" INSTL_DATABASE_INVALID_PGSQL_VERSION="Necessites Posrgre %1$s. o superior per continuar la instal·lació. La teva versió és: %2$s" -INSTL_DATABASE_INVALID_POSTGRESQL_VERSION="Necessiteu PostgreSQL %1$s o superior per continuar la instal·lació. La vostra versió és: %2$s" +INSTL_DATABASE_INVALID_POSTGRESQL_VERSION="Necessites Posrgre %1$s. o superior per continuar la instal·lació. La teva versió és: %2$s" INSTL_DATABASE_INVALID_TYPE="Si us plau,, selecciona el tipus de base de dades." -INSTL_DATABASE_NAME_INVALID_CHAR="Cap identificador de MySQL pot tenir un valor NULL ASCII(0x00)." -INSTL_DATABASE_NAME_INVALID_SPACES="Els noms de les bases de dades i les taules MySQL no poden començar ni acabar amb espais." -INSTL_DATABASE_NAME_TOO_LONG="El nom de la base de dades MySQL ha de tenir un màxim de 64 caràcters." +INSTL_DATABASE_NAME_INVALID_CHAR="Cap identificador de MySQL pot contenir un ASCII NUL (0x00)." +INSTL_DATABASE_NAME_INVALID_SPACES="Els noms de base de dades MySQL i els noms de taules no poden començar ni acabar amb espais." +INSTL_DATABASE_NAME_TOO_LONG="El nom de base de dades MySQL ha de tenir un màxim de 64 caràcters." ; Controllers -INSTL_COOKIES_NOT_ENABLED="Sembla que les galetes no estan habilitades al vostre client de navegador. No podreu instal·lar l'aplicació amb aquesta funció desactivada. Alternativament, també podria haver-hi un problema amb el fitxer session.save_path del servidor. Si aquest és el cas, consulteu el vostre proveïdor d'allotjament si no sabeu com comprovar-ho o solucionar-ho vosaltres mateixos." +INSTL_COOKIES_NOT_ENABLED="Les galetes no semblen estar habilitades al teu navegador. No seràs capaç d'instal·lar Joomla amb aquesta característica desactivada. Alternativament, també podria ser un problema amb session.save_path del servidor . Si és aquest el cas, si us plau consulta el teu hostatjament si no saps com comprovar-ho o reparar-ho tu." INSTL_HEADER_ERROR="Error" ; Helpers @@ -203,27 +202,27 @@ INSTL_PAGE_TITLE="Instal·lador de Joomla" ; Configuration model INSTL_ERROR_CONNECT_DB="No es pot connectar amb la base de dades. El connector va retornar el número %s." -INSTL_STD_OFFLINE_MSG="Aquest lloc web està fora de servei per manteniment.
Torneu-ho a comprovar aviat." +INSTL_STD_OFFLINE_MSG="Aquest lloc està desactivat per manteniment.
Torna més tard, gràcies." ; Languages model -INSTL_ERROR_INVALID_URL="URL no vàlida" +INSTL_ERROR_INVALID_URL="Adreça URL no vàlida" ; Others -INSTL_CONFPROBLEM="El fitxer o carpeta de configuració no és escrivible o hi ha hagut un problema en crear el fitxer de configuració. Haureu de carregar el codi següent manualment. Seleccioneu a l'àrea de text per ressaltar tot el codi i, a continuació, enganxeu-lo en un fitxer de text nou. Anomeneu aquest fitxer 'configuration.php' i pengeu-lo a la carpeta arrel del vostre lloc web." -INSTL_DISPLAY_ERRORS="Mostrar Errors" +INSTL_CONFPROBLEM="L'arxiu de configuració o directori no té permís d'escriptura o ha hagut un problema en crear el fitxer de configuració. Hauràs de pujar el següent codi a mà. Fes clic a l'àrea de text per ressaltar tot el codi i enganxa'l en un nou fitxer de text. Anomena'l 'configuration.php' i puja'l a la carpeta arrel del lloc." +INSTL_DISPLAY_ERRORS="Mostrar errors" INSTL_ERROR="Error" -INSTL_ERROR_DB="S'han produït alguns errors en omplir la base de dades: %s." +INSTL_ERROR_DB="S'ha produït un error en omplir la base de dades. %s." INSTL_ERROR_INITIALISE_SCHEMA="No es pot inicialitzar l'esquema de la base de dades." -INSTL_EXTENSION_AVAILABLE="%s Disponible" -INSTL_FILE_UPLOADS="Càrregues de Fitxers" +INSTL_EXTENSION_AVAILABLE="%s disponible" +INSTL_FILE_UPLOADS="Pujada de fitxers" INSTL_GNU_GPL_LICENSE="Llicència General Pública GNU" INSTL_HELP_LINK="Ajuda amb la instal·lació de Joomla" INSTL_NOTICE_NEEDSTOBEWRITABLE="Encara pots continuar amb la instal·lació si modifiques els permisos." -INSTL_OUTPUT_BUFFERING="Memòria intermèdia de sortida" +INSTL_OUTPUT_BUFFERING="buffer de sortida" INSTL_PHP_VERSION="Versió PHP" INSTL_PHP_VERSION_NEWER="Versió de PHP >= %s" -INSTL_PROCESS_BUSY="El procés està en curs. Si us plau, espereu …" -INSTL_SESSION_AUTO_START="Inici Automàtic de la Sessió" +INSTL_PROCESS_BUSY="Procés realitzant-se. Espera…" +INSTL_SESSION_AUTO_START="Autoinici de sessió" INSTL_WRITABLE="Permisos insuficients per crear %s." INSTL_ZIP_SUPPORT_AVAILABLE="Suport nadiu ZIP" @@ -238,16 +237,16 @@ JGLOBAL_LANGUAGE_VERSION_NOT_PLATFORM="El paquet d'idioma no concorda amb aquest JGLOBAL_SELECT_AN_OPTION="Selecciona una opció" JGLOBAL_SELECT_NO_RESULTS_MATCH="Cap resultat no coincideix" JGLOBAL_SELECT_SOME_OPTIONS="Selecciona algunes opcions" -JHIDEPASSWORD="Amaga la Contrasenya" -JINVALID_TOKEN="La petició més recent s'ha denegat perquè contenia un codi de seguretat no vàlid. Actualitzeu la pàgina i torneu-ho a provar." -JINVALID_TOKEN_NOTICE="Els testimonis de seguretat no coincideixen. La sol·licitud ha estat avortada per evitar qualsevol violació de la seguretat. Torna-ho a provar." +JHIDEPASSWORD="Amagar contrasenya" +JINVALID_TOKEN="La petició més recent s'ha denegat perquè contenia un codi de seguretat no vàlid. Actualitza la pàgina i torna-ho a provar." +JINVALID_TOKEN_NOTICE="El testimoni de seguretat no coincideix. La sol·licitud ha estat avortada per evitar qualsevol violació de la seguretat. Torna-ho a provar." JNEXT="Següent" JNO="No" -JNOTICE="Avís" +JNOTICE="Informació" JOFF="Desactivat" JON="Activat" JPREVIOUS="Anterior" -JSHOWPASSWORD="Mostrar Contrasenya" +JSHOWPASSWORD="Mostrar contrasenya" JSITE="Lloc" JSKIP="Ometre" JUSERNAME="Nom d'usuari" @@ -255,39 +254,39 @@ JYES="Sí" ; Framework strings necessary when no lang pack is available JLIB_DATABASE_ERROR_CONNECT_MYSQL="No s'ha pogut connectar a MySQL." -JLIB_DATABASE_ERROR_DATABASE="S'ha produït un error a la base de dades." +JLIB_DATABASE_ERROR_DATABASE="Ha hagut un error a la base de dades." JLIB_DATABASE_ERROR_LOAD_DATABASE_DRIVER="No s'ha pogut carregar el controlador de la base de dades: %s" -JLIB_DATABASE_ERROR_VALID_MAIL="L'adreça electrònica que has introduït no és vàlida. Si us plau, introdueix una altra adreça electrònica." +JLIB_DATABASE_ERROR_VALID_MAIL="L'adreça de correu que has introduït no és vàlida. Introdueix una adreça de correu electrònic diferent." JLIB_ENVIRONMENT_SESSION_EXPIRED="La teva sessió ha expirat, si us plau , recarrega la pàgina." JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: La ruta no és una carpeta. Ruta: %2$s" -JLIB_FORM_FIELD_INVALID="Camp no vàlid: " +JLIB_FORM_FIELD_INVALID="Camp no vàlid: " JLIB_FORM_VALIDATE_FIELD_INVALID="Camp no vàlid: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="Camp requerit: %s" -JLIB_INSTALLER_ABORT="S'està aturant la instal·lació de l'idioma: %s" +JLIB_INSTALLER_ABORT="Aturant la instal·lació de l'idioma: %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Extensió %1$s: No s'ha pogut crear el directori: %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="La ruta d'instal·lació no existeix." JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Paquet %1$s: S'ha produït un error en instal·lar una extensió: %2$s." -JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="Paquet %s: No hi ha fitxers per instal·lar!" +JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="Paquet %s: no hi ha arxius a instal·lar!" JLIB_INSTALLER_ERROR_DOWNLOAD_SERVER_CONNECT="Error connectant al servidor: %s" JLIB_INSTALLER_ERROR_FAIL_COPY_FILE="JInstaller: :Instal·lació: Error en copiar el fitxer %1$s a %2$s." JLIB_INSTALLER_INSTALL="Instal·la" JLIB_INSTALLER_NOT_ERROR="Si l'error està relacionat amb la instal·lació dels fitxers d'idioma de TinyMCE, no tindrà efecte en la instal·lació dels idiomes. Alguns paquets d'idioma creats abans de Joomla! 3.2.0 poden intentar instal·lar fitxers d'idioma per separat de TinyMCE. Com que ara s'inclouen al nucli, ja no cal instal·lar-los." JLIB_INSTALLER_WARNING_UNABLE_TO_INSTALL_CONTENT_LANGUAGE="No es pot crear un idioma de contingut per a l'idioma %s: %s." JLIB_UPDATER_ERROR_COLLECTION_FOPEN="La configuració de PHP allow_url_fopen està desactivada. Aquesta configuració ha d'estar activada perquè l'actualitzador funcioni." -JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL="Update: :Collection: No s'ha pogut obrir %s" +JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL="Update: :Collection: No es pot obrir %s" JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL="Update: :Collection: No s'ha pogut analitzar %s" JLIB_UPDATER_ERROR_OPEN_UPDATE_SITE="Actualització: No s'ha pogut obrir el lloc d'actualització #%d "%s", URL: %s." JLIB_UTIL_ERROR_CONNECT_DATABASE="JDatabase: :getInstance: No s'ha pogut connectar amb la base de dades
joomla.library: %1$s - %2$s." ; Strings for the language debugger -JDEBUG_LANGUAGE_FILES_IN_ERROR="Anàlisi d'errors en fitxers d'idioma" +JDEBUG_LANGUAGE_FILES_IN_ERROR="Parsejant errors als arxius d`idioma" JDEBUG_LANGUAGE_UNTRANSLATED_STRING="Cadenes sense traduir" JNONE="Cap" ; Necessary for errors -ADMIN_EMAIL="Correu electrònic de l'Administrador" -ADMIN_PASSWORD="Contrasenya d'Administrador" -SITE_NAME="Nom del Lloc" +ADMIN_EMAIL="Email de l'Administrador" +ADMIN_PASSWORD="Contrasenya d'administrador" +SITE_NAME="Nom del lloc" ; Database types (allows for a more descriptive label than the internal name) MYSQL="MySQL (DOP)" diff --git a/installation/language/ca-ES/langmetadata.xml b/installation/language/ca-ES/langmetadata.xml index 2e2fa30978ff7..87131f805f4c4 100644 --- a/installation/language/ca-ES/langmetadata.xml +++ b/installation/language/ca-ES/langmetadata.xml @@ -1,7 +1,7 @@ Catalan (ca-ES) - 5.4.8 + 6.1.3 2026-07 Catalan [ca-ES] Translation Team (C) 2005 Open Source Matters, Inc. @@ -11,7 +11,7 @@ Catalan (ca-ES) - Català (ca-ES) + Catalan (ca-ES) ca-ES 0 diff --git a/installation/language/cs-CZ/joomla.cli.ini b/installation/language/cs-CZ/joomla.cli.ini index 0efacc9ea04cb..8caca19b71b12 100644 --- a/installation/language/cs-CZ/joomla.cli.ini +++ b/installation/language/cs-CZ/joomla.cli.ini @@ -11,8 +11,8 @@ INSTL_DATABASE_ENCRYPTION_CA_LABEL="Cesta k souboru CA pro ověření šifrován INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Cesta k souboru CA pro ověření šifrování" INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Cesta k SSL certifikátu pro připojení k databázi. Vyžaduje nastavení šifrování na 2" INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Cesta k SSL certifikátu pro připojení k databázi. Vyžaduje nastavení šifrování na 2" -INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Podporovaná sada šifrovacích kódů (volitelné)" -INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Podporovaná sada šifrovacích kódů (volitelné)" +INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Podporovaná sada Cipher (volitelná)" +INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Podporovaná sada Cipher (volitelná)" INSTL_DATABASE_ENCRYPTION_KEY_LABEL="SSL klíč pro připojení k databázi. Vyžaduje šifrování nastavené na 2" INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="SSL klíč pro připojení k databázi. Vyžaduje šifrování nastavené na 2" INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Šifrování pro připojení k databázi. Hodnoty: 0=Žádné, 1=Jednosměrné, 2=Obousměrné" @@ -20,17 +20,17 @@ INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="Šifrování pro připojení k datab INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Ověřte SSL certifikát pro připojení k databázi. Hodnoty: 0=Ne, 1=Ano. Vyžaduje nastavení šifrování nastavené na 1 nebo 2" INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="Ověřte SSL certifikát pro připojení k databázi. Hodnoty: 0=Ne, 1=Ano. Vyžaduje nastavení šifrování nastavené na 1 nebo 2" INSTL_DATABASE_HOST_DESC="Hostitel databáze" -INSTL_DATABASE_HOST_DESC_SHORT="Host" +INSTL_DATABASE_HOST_DESC_SHORT="Hostitel databáze" INSTL_DATABASE_NAME_DESC="Název databáze" INSTL_DATABASE_NAME_DESC_SHORT="Název databáze" INSTL_DATABASE_PASSWORD_DESC="Heslo databáze" INSTL_DATABASE_PASSWORD_DESC_SHORT="Heslo databáze" INSTL_DATABASE_PREFIX_DESC="Předpona databázových tabulek" -INSTL_DATABASE_PREFIX_DESC_SHORT="Předpona tabulek" +INSTL_DATABASE_PREFIX_DESC_SHORT="Předpona databázových tabulek" INSTL_DATABASE_TYPE_DESC="Typ databáze. Podporováno mysql, mysqli, pgsql" INSTL_DATABASE_TYPE_DESC_SHORT="Typ databáze. Podporováno Joomla: mysql (=MySQL (CHOP)), mysqli (=MySQLi), pgsql (=PostgreSQL (CHOP))" INSTL_DATABASE_USER_DESC="Uživatelské jméno databáze" -INSTL_DATABASE_USER_DESC_SHORT="Uživatelské jméno" +INSTL_DATABASE_USER_DESC_SHORT="Uživatelské jméno databáze" INSTL_PUBLIC_FOLDER_DESC="Relativní nebo absolutní cesta do veřejné složky" INSTL_PUBLIC_FOLDER_DESC_SHORT="Relativní nebo absolutní cesta do veřejné složky" INSTL_SITE_NAME_DESC="Zadejte název vaší stránky Joomla" diff --git a/installation/language/cs-CZ/joomla.ini b/installation/language/cs-CZ/joomla.ini index 4ef29d6b2537d..90aa0afdcfb9a 100644 --- a/installation/language/cs-CZ/joomla.ini +++ b/installation/language/cs-CZ/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Pro spuštění této verze Joomla musí váš hostite BUILD_MIN_PHP_ERROR_URL_TEXT="Pomozte mi to vyřešit" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Změnit instalační jazyk" +INSTL_CHANGE_INSTALL_LANG_SHORT="Změnit" +INSTL_SELECTED_INSTALL_LANGUAGE="Aktuální jazyk: %s" INSTL_SELECT_INSTALL_LANG="Vyberte jazyk pro instalaci" INSTL_SELECT_LANGUAGE_TITLE="Zvolte jazyk" INSTL_SETUP_LOGIN_DATA="Nastavit přihlašovací údaje" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Aby mohla být Joomla! nainstalována, je třeba mít v PHP povo INSTL_DATABASE_SUPPORT="Podpora databáze:" INSTL_JSON_SUPPORT_AVAILABLE="Podpora JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language je Výchozí" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload vypnuto" INSTL_NOTICE_DATABASE_SUPPORT="Nebyly nalezeny žádné podporované databáze." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Aby mohla být Joomla! nainstalována, je třeba mít v PHP povolen JSON!" INSTL_NOTICE_MBLANG_NOTDEFAULT="Proměnná PHP mbstring language není nastavena na hodnotu neutral. Můžete to změnit zadáním hodnoty php_value mbstring.language neutral do souboru .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Je zapnuta funkce PHP mbstring. Lokálně ji můžete vypnout zadáním hodnoty php_value mbstring.func_overload 0 do souboru .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Požadované php funkce parse_ini_file a parse_ini_string jsou na vašem serveru zakázány." INSTL_NOTICE_XML_SUPPORT="Podpora XML není k dispozici. Toto by mělo být ve výchozím nastavení povoleno u uživatelů php, ale Ubuntu možná bude třeba nainstalovat tak, že sudo apt-get nainstaluje php-xml a poté restartuje webový server." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib komprese není nastavena. Lze ji lokálně zapnout zadáním zlib.output_compression = On do souboru php.ini." @@ -236,11 +235,11 @@ JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="Při zpracován JGLOBAL_ISFREESOFTWARE="%s je svobodný software šířený pod GNU General Public License." JGLOBAL_LANGUAGE_VERSION_NOT_PLATFORM="Jazykový balíček neodpovídá nainstalované verzi Joomla!, některé řetězce mohou chybět a budou zobrazeny v angličtině." JGLOBAL_SELECT_AN_OPTION="Vybrat možnost" -JGLOBAL_SELECT_NO_RESULTS_MATCH="Nebyly nalezeny žádné odpovídající výsledky" +JGLOBAL_SELECT_NO_RESULTS_MATCH="Nejsou odpovídající výsledky" JGLOBAL_SELECT_SOME_OPTIONS="Vyberte nějaké možnosti" JHIDEPASSWORD="Skrýt heslo" JINVALID_TOKEN="Nejnovější požadavek byl odmítnut, protože obsahuje neplatný bezpečnostní symbol. Obnovte stránku a zkuste to znovu." -JINVALID_TOKEN_NOTICE="Bezpečnostní klíče se neshodují. Požadavek byl přerušen, aby se zabránilo narušení bezpečnosti. Opakujte akci." +JINVALID_TOKEN_NOTICE="Bezpečnostní token se neshodoval. Požadavek byl přerušen, aby se zabránilo jakémukoli narušení bezpečnosti. Zkuste to znovu." JNEXT="Následující" JNO="Ne" JNOTICE="Upozornění" @@ -263,7 +262,7 @@ JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: Cesta není složka. Cesta: %2 JLIB_FORM_FIELD_INVALID="Neplatné pole:  " JLIB_FORM_VALIDATE_FIELD_INVALID="Neplatné pole: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="Povinné pole: %s" -JLIB_INSTALLER_ABORT="Instalace jazyku byla přerušena: %s" +JLIB_INSTALLER_ABORT="Instalace jazyka byla přerušena: %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="%1$s rozšíření: Nepodařilo se vytvořit složku %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="Cesta pro instalaci neexistuje" JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Balíček %1$s: Došlo k chybě při instalaci rozšíření: %2$s" @@ -304,7 +303,7 @@ NOTICE="Oznámení" WARNING="Varování" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Při načítání dat JSON došlo k přerušení připojení." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Při načítání dat formátu JSON došlo k přerušení spojení." JLIB_JS_AJAX_ERROR_NO_CONTENT="Nebyl vrácen žádný obsah." JLIB_JS_AJAX_ERROR_OTHER="Při načítání dat JSON došlo k chybě: stavový kód HTTP %d." JLIB_JS_AJAX_ERROR_PARSE="Při zpracování následující data JSON došlo k chybě parsování:
%s" diff --git a/installation/language/cs-CZ/langmetadata.xml b/installation/language/cs-CZ/langmetadata.xml index ea1a9a305ca69..7f3ac9f8cd6a7 100644 --- a/installation/language/cs-CZ/langmetadata.xml +++ b/installation/language/cs-CZ/langmetadata.xml @@ -1,7 +1,7 @@ Czech (Čeština) - 5.4.8 + 6.1.3 2026-07 Czech Translation Team (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/cy-GB/joomla.ini b/installation/language/cy-GB/joomla.ini index f948ff1b7b481..49210ebe52061 100644 --- a/installation/language/cy-GB/joomla.ini +++ b/installation/language/cy-GB/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Mae eich lletywr angen defnyddio fersiwn PHP {{phpvers BUILD_MIN_PHP_ERROR_URL_TEXT="Helpwch fi i ddatrys hyn" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Newid" INSTL_SELECT_INSTALL_LANG="Dewiswch Iaith Gosod" INSTL_SELECT_LANGUAGE_TITLE="Dewiswch iaith" INSTL_SETUP_LOGIN_DATA="Ffurfweddu Data Mewngofnodi" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Mae’n rhaid galluogi JSON yn eich gosodiad o PHP er mwyn gosod INSTL_DATABASE_SUPPORT="Cymorth cronfa ddata:" INSTL_JSON_SUPPORT_AVAILABLE="Cymorth JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="Iaith MB yw'r diofyn" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="Cyfarwyddeb MB String Overload wedi'i ddiffodd" INSTL_NOTICE_DATABASE_SUPPORT="Methu canfod cronfa ddata da ni'n gefnogi." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Mae’n rhaid galluogi JSON yn eich gosodiad o PHP er mwyn gosod Joomla!" INSTL_NOTICE_MBLANG_NOTDEFAULT="Nid yw iaith PHP mbstring wedi ei osod yn niwtral. Mae'n bosibl gosod hwn yn lleol trwy roi php_value mbstring.language neutral yng nghod eich ffeil .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Mae swyddogaeth PHP mbstring overload wedi ei osod. Gallwch ddiffodd hwn yn lleol trwy fewnbynnu php_value mbstring.func_overload 0 yng nghod eich ffeil .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Nid yw'r swyddogaethau php gofynnol parse_ini_file a parse_ini_string wedi eu galluogi ar eich gweinydd." INSTL_NOTICE_XML_SUPPORT="Does dim cefnogaeth ar gyfer XML ar gael. Dylai hyn fod wedi ei alluogi yn ddiofyn yn php ond gall fod angen i ddefnyddwyr Ubuntu ei osod drwy ddefnyddio sudo apt-get install php-xml ac yna ail gychwyn y gweinydd gwe." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Nid yw cywasgu Zlib wedi ei ffurfweddu. Gelir rhoi hyn ymlaen yn lleol drwy roi zlib.output_compression = On yn eich ffeil php.ini." diff --git a/installation/language/cy-GB/langmetadata.xml b/installation/language/cy-GB/langmetadata.xml index 77cc9ab916620..eb10056410377 100644 --- a/installation/language/cy-GB/langmetadata.xml +++ b/installation/language/cy-GB/langmetadata.xml @@ -1,7 +1,7 @@ Welsh (United Kingdom) - 5.4.8 + 6.1.3 2026-07 Joomla! Project - Welsh Translation Team (C) 2005 Open Source Matters, Inc. @@ -11,7 +11,7 @@ Welsh (cy-GB) - Welsh (United Kingdom) + Cymraeg cy-GB 0 diff --git a/installation/language/da-DK/joomla.cli.ini b/installation/language/da-DK/joomla.cli.ini index 0ccf3112f4424..980a88d0b8253 100644 --- a/installation/language/da-DK/joomla.cli.ini +++ b/installation/language/da-DK/joomla.cli.ini @@ -1,5 +1,5 @@ INSTL_ADMIN_EMAIL_DESC="Angiv e-mail adressen på webstedets superbruger" -INSTL_ADMIN_EMAIL_DESC_SHORT="E-mailadressen til webstedts super bruger konto" +INSTL_ADMIN_EMAIL_DESC_SHORT="E-mailadressen til webstedts superbruger konto" INSTL_ADMIN_PASSWORD_DESC="Angiv adgangskoden til din superbruger konto" INSTL_ADMIN_PASSWORD_DESC_SHORT="Adgangskode på din superbruger konto" INSTL_ADMIN_USERNAME_DESC="Sæt brugernavnet for din Superbruger konto" diff --git a/installation/language/da-DK/joomla.ini b/installation/language/da-DK/joomla.ini index c5ef87ec4f1f9..f94c25db8e954 100644 --- a/installation/language/da-DK/joomla.ini +++ b/installation/language/da-DK/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Din host skal anvende PHP version {{phpversion}} eller BUILD_MIN_PHP_ERROR_URL_TEXT="Hjælp mig med at løse dette" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Skift installationssprog" +INSTL_CHANGE_INSTALL_LANG_SHORT="Skift" +INSTL_SELECTED_INSTALL_LANGUAGE="Aktuelt sprog: %s" INSTL_SELECT_INSTALL_LANG="Vælg installationssprog" INSTL_SELECT_LANGUAGE_TITLE="Vælg sprog" INSTL_SETUP_LOGIN_DATA="Setup log på data" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Din PHP installation skal have JSON aktiveret for at Joomla kan INSTL_DATABASE_SUPPORT="Database understøttelse:" INSTL_JSON_SUPPORT_AVAILABLE="JSON understøttelse" INSTL_MB_LANGUAGE_IS_DEFAULT="MB sprog er standard" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB strenge overload off" INSTL_NOTICE_DATABASE_SUPPORT="Ingen understøttet database blev fundet." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Din PHP installation skal have JSON aktiveret for at Joomla kan installeres!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring sprog er ikke sat til neutral. Dette kan indstilles lokalt ved at indtaste php_value mbstring.language neutral i .htaccess" -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload er indstillet. Dette kan deaktiveres lokalt ved at indtaste php_value mbstring.func_overload 0 i .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="De krævede php funktioner parse_ini_file og parse_ini_string er deaktiverede på din server." INSTL_NOTICE_XML_SUPPORT="XML understøttelse er ikke tilgængelig. Dette burde være aktiveret som standard i php, men Ubuntu brugere skal måske installere det, ved at køre sudo apt-get install php-xml efterfulgt af en genstart af webserveren." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib komprimering er ikke sat. Dette kan aktiveres lokalt ved at indsætte zlib.output_compression = On i din php.ini fil." diff --git a/installation/language/da-DK/langmetadata.xml b/installation/language/da-DK/langmetadata.xml index 46bbe14af2c5a..988c634001991 100644 --- a/installation/language/da-DK/langmetadata.xml +++ b/installation/language/da-DK/langmetadata.xml @@ -1,7 +1,7 @@ Danish (Danmark) - 5.4.8 + 6.1.3 2026-07 Danish Translation Team (Transl.: Ronny Buelund) (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/de-AT/joomla.ini b/installation/language/de-AT/joomla.ini index 5744da08c7e7d..3cf125503c3e9 100644 --- a/installation/language/de-AT/joomla.ini +++ b/installation/language/de-AT/joomla.ini @@ -33,6 +33,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Der Webserver muss die PHP-Version {{phpversion}} oder BUILD_MIN_PHP_ERROR_URL_TEXT="Weitere Informationen sind in der Dokumentation zu finden." ; Main Config +INSTL_CHANGE_INSTALL_LANG="Installationssprache ändern" +INSTL_CHANGE_INSTALL_LANG_SHORT="Ändern" +INSTL_SELECTED_INSTALL_LANGUAGE="Aktuelle Sprache: %s" INSTL_SELECT_INSTALL_LANG="Installationssprache auswählen" INSTL_SELECT_LANGUAGE_TITLE="Sprachauswahl" INSTL_SETUP_LOGIN_DATA="Zugangsdaten einrichten" @@ -43,13 +46,9 @@ INSTL_WARNJSON="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla insta INSTL_DATABASE_SUPPORT="Datenbankunterstützung:" INSTL_JSON_SUPPORT_AVAILABLE="JSON-Support" INSTL_MB_LANGUAGE_IS_DEFAULT="PHPs mbstring Spracheinstellung ist neutral" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist deaktiviert" INSTL_NOTICE_DATABASE_SUPPORT="Es wurden keine unterstützten Datenbanken gefunden." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla installiert werden kann." INSTL_NOTICE_MBLANG_NOTDEFAULT="PHPs mbstring Spracheinstellung ist nicht auf „neutral“ gesetzt. Dies kann lokal aktiviert werden, indem eine neue Zeile mit php_value mbstring.language neutral in die .htaccess Datei eingefügt wird." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist aktiviert. Dies kann lokal deaktiviert werden, indem eine neue Zeile mit php_value mbstring.func_overload 0 in die .htaccess Datei eingefügt wird." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Die erforderlichen php-Funktionen parse_ini_file und parse_ini_string sind auf dem Webserver deaktiviert." INSTL_NOTICE_XML_SUPPORT="Die XML-Unterstützung ist nicht verfügbar. Dies sollte standardmäßig in php aktiviert sein, Ubuntu-Benutzer müssen möglicherweise durch Ausführen von sudo apt-get install php-xml die benötigten Pakete installieren, gefolgt von einem Neustart des Webservers." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Die Zlib-Kompression ist nicht aktiviert. Dies kann lokal aktiviert werden, indem eine neue Zeile mit zlib.output_compression = On in die php.ini Datei eingefügt wird." @@ -166,7 +165,7 @@ INSTL_DEFAULTLANGUAGE_DESC_FRONTEND="Joomla hat folgende Sprachen installiert. B INSTL_DEFAULTLANGUAGE_FRONTEND="Standard-Sprache: Website" INSTL_DEFAULTLANGUAGE_FRONTEND_COULDNT_SET_DEFAULT="Joomla war es nicht möglich die Sprache als Standard festzulegen. Englisch wird daher als Standard-Sprache für die WEBSITE (Frontend) verwendet." INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Die Sprache mit dem Sprach-Tag „%s“ wurde zur Standard-Sprache für die WEBSITE festgelegt." -INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache konfigurieren" +INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache festlegen" INSTL_DEFAULTLANGUAGE_TRY_LATER="Weitere Sprachen können auch noch später in der Administration von Joomla installiert werden." INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Deutsch (Österreich)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español diff --git a/installation/language/de-AT/langmetadata.xml b/installation/language/de-AT/langmetadata.xml index 938288898b513..5c77b315fe049 100644 --- a/installation/language/de-AT/langmetadata.xml +++ b/installation/language/de-AT/langmetadata.xml @@ -1,8 +1,8 @@ German (Austria) - 5.4.3 - 2026-02 + 6.1.0 + 2026-04 J!German (C) 2005 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt diff --git a/installation/language/de-CH/joomla.ini b/installation/language/de-CH/joomla.ini index 8681abcefd93c..01425cd2c87e1 100644 --- a/installation/language/de-CH/joomla.ini +++ b/installation/language/de-CH/joomla.ini @@ -33,6 +33,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Der Webserver muss die PHP-Version {{phpversion}} oder BUILD_MIN_PHP_ERROR_URL_TEXT="Weitere Informationen sind in der Dokumentation zu finden." ; Main Config +INSTL_CHANGE_INSTALL_LANG="Installationssprache ändern" +INSTL_CHANGE_INSTALL_LANG_SHORT="Ändern" +INSTL_SELECTED_INSTALL_LANGUAGE="Aktuelle Sprache: %s" INSTL_SELECT_INSTALL_LANG="Installationssprache auswählen" INSTL_SELECT_LANGUAGE_TITLE="Sprachauswahl" INSTL_SETUP_LOGIN_DATA="Zugangsdaten einrichten" @@ -43,13 +46,9 @@ INSTL_WARNJSON="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla insta INSTL_DATABASE_SUPPORT="Datenbankunterstützung:" INSTL_JSON_SUPPORT_AVAILABLE="JSON-Support" INSTL_MB_LANGUAGE_IS_DEFAULT="PHPs mbstring Spracheinstellung ist neutral" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist deaktiviert" INSTL_NOTICE_DATABASE_SUPPORT="Es wurden keine unterstützten Datenbanken gefunden." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla installiert werden kann." INSTL_NOTICE_MBLANG_NOTDEFAULT="PHPs mbstring Spracheinstellung ist nicht auf „neutral“ gesetzt. Dies kann lokal aktiviert werden, indem eine neue Zeile mit php_value mbstring.language neutral in die .htaccess Datei eingefügt wird." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist aktiviert. Dies kann lokal deaktiviert werden, indem eine neue Zeile mit php_value mbstring.func_overload 0 in die .htaccess Datei eingefügt wird." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Die erforderlichen php-Funktionen parse_ini_file und parse_ini_string sind auf dem Webserver deaktiviert." INSTL_NOTICE_XML_SUPPORT="Die XML-Unterstützung ist nicht verfügbar. Dies sollte standardmässig in php aktiviert sein, Ubuntu-Benutzer müssen möglicherweise durch Ausführen von sudo apt-get install php-xml die benötigten Pakete installieren, gefolgt von einem Neustart des Webservers." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Die Zlib-Kompression ist nicht aktiviert. Dies kann lokal aktiviert werden, indem eine neue Zeile mit zlib.output_compression = On in die php.ini Datei eingefügt wird." @@ -166,7 +165,7 @@ INSTL_DEFAULTLANGUAGE_DESC_FRONTEND="Joomla hat folgende Sprachen installiert. B INSTL_DEFAULTLANGUAGE_FRONTEND="Standard-Sprache: Website" INSTL_DEFAULTLANGUAGE_FRONTEND_COULDNT_SET_DEFAULT="Joomla war es nicht möglich die Sprache als Standard festzulegen. Englisch wird daher als Standard-Sprache für die WEBSITE (Frontend) verwendet." INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Die Sprache mit dem Sprach-Tag „%s“ wurde zur Standard-Sprache für die WEBSITE festgelegt." -INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache konfigurieren" +INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache festlegen" INSTL_DEFAULTLANGUAGE_TRY_LATER="Weitere Sprachen können auch noch später in der Administration von Joomla installiert werden." INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Deutsch (Schweiz)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español diff --git a/installation/language/de-CH/langmetadata.xml b/installation/language/de-CH/langmetadata.xml index 704724b5e1365..22078e82315f5 100644 --- a/installation/language/de-CH/langmetadata.xml +++ b/installation/language/de-CH/langmetadata.xml @@ -1,8 +1,8 @@ German (Switzerland) - 5.4.3 - 2026-02 + 6.1.0 + 2026-04 J!German (C) 2005 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt diff --git a/installation/language/de-DE/joomla.ini b/installation/language/de-DE/joomla.ini index db57e43c9fb47..8e4297eb6faa4 100644 --- a/installation/language/de-DE/joomla.ini +++ b/installation/language/de-DE/joomla.ini @@ -33,6 +33,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Der Webserver muss die PHP-Version {{phpversion}} oder BUILD_MIN_PHP_ERROR_URL_TEXT="Weitere Informationen sind in der Dokumentation zu finden." ; Main Config +INSTL_CHANGE_INSTALL_LANG="Installationssprache ändern" +INSTL_CHANGE_INSTALL_LANG_SHORT="Ändern" +INSTL_SELECTED_INSTALL_LANGUAGE="Aktuelle Sprache: %s" INSTL_SELECT_INSTALL_LANG="Installationssprache auswählen" INSTL_SELECT_LANGUAGE_TITLE="Sprachauswahl" INSTL_SETUP_LOGIN_DATA="Zugangsdaten einrichten" @@ -43,13 +46,9 @@ INSTL_WARNJSON="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla insta INSTL_DATABASE_SUPPORT="Datenbankunterstützung:" INSTL_JSON_SUPPORT_AVAILABLE="JSON-Support" INSTL_MB_LANGUAGE_IS_DEFAULT="PHPs mbstring Spracheinstellung ist neutral" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist deaktiviert" INSTL_NOTICE_DATABASE_SUPPORT="Es wurden keine unterstützten Datenbanken gefunden." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla installiert werden kann." INSTL_NOTICE_MBLANG_NOTDEFAULT="PHPs mbstring Spracheinstellung ist nicht auf „neutral“ gesetzt. Dies kann lokal aktiviert werden, indem eine neue Zeile mit php_value mbstring.language neutral in die .htaccess Datei eingefügt wird." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist aktiviert. Dies kann lokal deaktiviert werden, indem eine neue Zeile mit php_value mbstring.func_overload 0 in die .htaccess Datei eingefügt wird." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Die erforderlichen php-Funktionen parse_ini_file und parse_ini_string sind auf dem Webserver deaktiviert." INSTL_NOTICE_XML_SUPPORT="Die XML-Unterstützung ist nicht verfügbar. Dies sollte standardmäßig in php aktiviert sein, Ubuntu-Benutzer müssen möglicherweise durch Ausführen von sudo apt-get install php-xml die benötigten Pakete installieren, gefolgt von einem Neustart des Webservers." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Die Zlib-Kompression ist nicht aktiviert. Dies kann lokal aktiviert werden, indem eine neue Zeile mit zlib.output_compression = On in die php.ini Datei eingefügt wird." @@ -166,7 +165,7 @@ INSTL_DEFAULTLANGUAGE_DESC_FRONTEND="Joomla hat folgende Sprachen installiert. B INSTL_DEFAULTLANGUAGE_FRONTEND="Standard-Sprache: Website" INSTL_DEFAULTLANGUAGE_FRONTEND_COULDNT_SET_DEFAULT="Joomla war es nicht möglich die Sprache als Standard festzulegen. Englisch wird daher als Standard-Sprache für die WEBSITE (Frontend) verwendet." INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Die Sprache mit dem Sprach-Tag „%s“ wurde zur Standard-Sprache für die WEBSITE festgelegt." -INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache konfigurieren" +INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache festlegen" INSTL_DEFAULTLANGUAGE_TRY_LATER="Weitere Sprachen können auch noch später in der Administration von Joomla installiert werden." INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Deutsch (Deutschland)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español diff --git a/installation/language/de-DE/langmetadata.xml b/installation/language/de-DE/langmetadata.xml index 484356e498de9..40cf7bd342333 100644 --- a/installation/language/de-DE/langmetadata.xml +++ b/installation/language/de-DE/langmetadata.xml @@ -1,8 +1,8 @@ German (Germany) - 5.4.3 - 2026-02 + 6.1.0 + 2026-04 J!German (C) 2005 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt diff --git a/installation/language/de-LI/joomla.ini b/installation/language/de-LI/joomla.ini index 303eca95ea53f..d167e53f9d5b0 100644 --- a/installation/language/de-LI/joomla.ini +++ b/installation/language/de-LI/joomla.ini @@ -33,6 +33,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Der Webserver muss die PHP-Version {{phpversion}} oder BUILD_MIN_PHP_ERROR_URL_TEXT="Weitere Informationen sind in der Dokumentation zu finden." ; Main Config +INSTL_CHANGE_INSTALL_LANG="Installationssprache ändern" +INSTL_CHANGE_INSTALL_LANG_SHORT="Ändern" +INSTL_SELECTED_INSTALL_LANGUAGE="Aktuelle Sprache: %s" INSTL_SELECT_INSTALL_LANG="Installationssprache auswählen" INSTL_SELECT_LANGUAGE_TITLE="Sprachauswahl" INSTL_SETUP_LOGIN_DATA="Zugangsdaten einrichten" @@ -43,13 +46,9 @@ INSTL_WARNJSON="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla insta INSTL_DATABASE_SUPPORT="Datenbankunterstützung:" INSTL_JSON_SUPPORT_AVAILABLE="JSON-Support" INSTL_MB_LANGUAGE_IS_DEFAULT="PHPs mbstring Spracheinstellung ist neutral" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist deaktiviert" INSTL_NOTICE_DATABASE_SUPPORT="Es wurden keine unterstützten Datenbanken gefunden." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla installiert werden kann." INSTL_NOTICE_MBLANG_NOTDEFAULT="PHPs mbstring Spracheinstellung ist nicht auf „neutral“ gesetzt. Dies kann lokal aktiviert werden, indem eine neue Zeile mit php_value mbstring.language neutral in die .htaccess Datei eingefügt wird." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist aktiviert. Dies kann lokal deaktiviert werden, indem eine neue Zeile mit php_value mbstring.func_overload 0 in die .htaccess Datei eingefügt wird." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Die erforderlichen php-Funktionen parse_ini_file und parse_ini_string sind auf dem Webserver deaktiviert." INSTL_NOTICE_XML_SUPPORT="Die XML-Unterstützung ist nicht verfügbar. Dies sollte standardmässig in php aktiviert sein, Ubuntu-Benutzer müssen möglicherweise durch Ausführen von sudo apt-get install php-xml die benötigten Pakete installieren, gefolgt von einem Neustart des Webservers." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Die Zlib-Kompression ist nicht aktiviert. Dies kann lokal aktiviert werden, indem eine neue Zeile mit zlib.output_compression = On in die php.ini Datei eingefügt wird." @@ -166,7 +165,7 @@ INSTL_DEFAULTLANGUAGE_DESC_FRONTEND="Joomla hat folgende Sprachen installiert. B INSTL_DEFAULTLANGUAGE_FRONTEND="Standard-Sprache: Website" INSTL_DEFAULTLANGUAGE_FRONTEND_COULDNT_SET_DEFAULT="Joomla war es nicht möglich die Sprache als Standard festzulegen. Englisch wird daher als Standard-Sprache für die WEBSITE (Frontend) verwendet." INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Die Sprache mit dem Sprach-Tag „%s“ wurde zur Standard-Sprache für die WEBSITE festgelegt." -INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache konfigurieren" +INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache festlegen" INSTL_DEFAULTLANGUAGE_TRY_LATER="Weitere Sprachen können auch noch später in der Administration von Joomla installiert werden." INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Deutsch (Liechtenstein)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español diff --git a/installation/language/de-LI/langmetadata.xml b/installation/language/de-LI/langmetadata.xml index 4282b03d9cb4e..c5ec5d316999a 100644 --- a/installation/language/de-LI/langmetadata.xml +++ b/installation/language/de-LI/langmetadata.xml @@ -1,8 +1,8 @@ German (Liechtenstein) - 5.4.3 - 2026-02 + 6.1.0 + 2026-04 J!German (C) 2005 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt diff --git a/installation/language/de-LU/joomla.ini b/installation/language/de-LU/joomla.ini index adfe834dab380..0633b8bc928b8 100644 --- a/installation/language/de-LU/joomla.ini +++ b/installation/language/de-LU/joomla.ini @@ -33,6 +33,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Der Webserver muss die PHP-Version {{phpversion}} oder BUILD_MIN_PHP_ERROR_URL_TEXT="Weitere Informationen sind in der Dokumentation zu finden." ; Main Config +INSTL_CHANGE_INSTALL_LANG="Installationssprache ändern" +INSTL_CHANGE_INSTALL_LANG_SHORT="Ändern" +INSTL_SELECTED_INSTALL_LANGUAGE="Aktuelle Sprache: %s" INSTL_SELECT_INSTALL_LANG="Installationssprache auswählen" INSTL_SELECT_LANGUAGE_TITLE="Sprachauswahl" INSTL_SETUP_LOGIN_DATA="Zugangsdaten einrichten" @@ -43,13 +46,9 @@ INSTL_WARNJSON="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla insta INSTL_DATABASE_SUPPORT="Datenbankunterstützung:" INSTL_JSON_SUPPORT_AVAILABLE="JSON-Support" INSTL_MB_LANGUAGE_IS_DEFAULT="PHPs mbstring Spracheinstellung ist neutral" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist deaktiviert" INSTL_NOTICE_DATABASE_SUPPORT="Es wurden keine unterstützten Datenbanken gefunden." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="In der PHP-Umgebung muss JSON aktiviert sein, damit Joomla installiert werden kann." INSTL_NOTICE_MBLANG_NOTDEFAULT="PHPs mbstring Spracheinstellung ist nicht auf „neutral“ gesetzt. Dies kann lokal aktiviert werden, indem eine neue Zeile mit php_value mbstring.language neutral in die .htaccess Datei eingefügt wird." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHPs „mbstring function overload“ ist aktiviert. Dies kann lokal deaktiviert werden, indem eine neue Zeile mit php_value mbstring.func_overload 0 in die .htaccess Datei eingefügt wird." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Die erforderlichen php-Funktionen parse_ini_file und parse_ini_string sind auf dem Webserver deaktiviert." INSTL_NOTICE_XML_SUPPORT="Die XML-Unterstützung ist nicht verfügbar. Dies sollte standardmäßig in php aktiviert sein, Ubuntu-Benutzer müssen möglicherweise durch Ausführen von sudo apt-get install php-xml die benötigten Pakete installieren, gefolgt von einem Neustart des Webservers." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Die Zlib-Kompression ist nicht aktiviert. Dies kann lokal aktiviert werden, indem eine neue Zeile mit zlib.output_compression = On in die php.ini Datei eingefügt wird." @@ -166,7 +165,7 @@ INSTL_DEFAULTLANGUAGE_DESC_FRONTEND="Joomla hat folgende Sprachen installiert. B INSTL_DEFAULTLANGUAGE_FRONTEND="Standard-Sprache: Website" INSTL_DEFAULTLANGUAGE_FRONTEND_COULDNT_SET_DEFAULT="Joomla war es nicht möglich die Sprache als Standard festzulegen. Englisch wird daher als Standard-Sprache für die WEBSITE (Frontend) verwendet." INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Die Sprache mit dem Sprach-Tag „%s“ wurde zur Standard-Sprache für die WEBSITE festgelegt." -INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache konfigurieren" +INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standardsprache festlegen" INSTL_DEFAULTLANGUAGE_TRY_LATER="Weitere Sprachen können auch noch später in der Administration von Joomla installiert werden." INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Deutsch (Luxemburg)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español diff --git a/installation/language/de-LU/langmetadata.xml b/installation/language/de-LU/langmetadata.xml index 3712504e0c10b..726e786948dd8 100644 --- a/installation/language/de-LU/langmetadata.xml +++ b/installation/language/de-LU/langmetadata.xml @@ -1,8 +1,8 @@ German (Luxembourg) - 5.4.3 - 2026-02 + 6.1.0 + 2026-04 J!German (C) 2005 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt diff --git a/installation/language/el-GR/joomla.ini b/installation/language/el-GR/joomla.ini index 40bd7949bff33..1c422c8eb6882 100644 --- a/installation/language/el-GR/joomla.ini +++ b/installation/language/el-GR/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Ο διακομιστής πρέπει να διαθέ BUILD_MIN_PHP_ERROR_URL_TEXT="Βοήθεια για την επίλυση" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Αλλαγή Θέσης" INSTL_SELECT_INSTALL_LANG="Επιλέξτε Γλώσσα Εγκατάστασης" INSTL_SELECT_LANGUAGE_TITLE="Επιλογή γλώσσας" INSTL_SETUP_LOGIN_DATA="Ρύθμιση Δεδομένων Σύνδεσης" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Η εγκατάσταση PHP πρέπει να έχει ενε INSTL_DATABASE_SUPPORT="Υποστήριξη Βάσης Δεδομένων:" INSTL_JSON_SUPPORT_AVAILABLE="Υποστήριξη JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="Η γλώσσα MB είναι προεπιλεγμένη" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload απενεργοποιημένο" INSTL_NOTICE_DATABASE_SUPPORT="Δεν βρέθηκαν βάσεις δεδομένων που υποστηρίζονται." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Η εγκατάσταση PHP πρέπει να έχει ενεργοποιημένη την JSON για να εγκατασταθεί το Joomla!" INSTL_NOTICE_MBLANG_NOTDEFAULT="Η γλώσσα PHP mbstring δεν ορίστηκε σαν ουδέτερη. Αυτό μπορεί να οριστεί τοπικά γράφοντας php_value mbstring.language neutral στο αρχείο .htaccess ." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Η λειτουργία υπερφόρτωσης για την PHP mbstring έχει οριστεί. Αυτή μπορεί να απενεργοποιηθεί γράφοντας php_value mbstring.func_overload 0 στο αρχείο .htaccess ." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Οι απαιτούμενες php συναρτήσεις parse_ini_file και parse_ini_string είναι απενεργοποιημένες στον διακομιστή σας." INSTL_NOTICE_XML_SUPPORT="XML υποστήριξη δεν είναι διαθέσιμη. Αυτό πρέπει να είναι ενεργοποιημένο από προεπιλογή στην php, αλλά οι χρήστες Ubuntu μπορεί να χρειαστεί να το εγκαταστήσουν κάνοντας sudo apt-get εγκατάσταση php-xml και στη συνέχεια επανεκκίνηση του διακομιστή ιστού." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Η συμπίεση Zlib δεν έχει οριστεί. Αυτό μπορεί να ενεργοποιηθεί τοπικά εισάγοντας zlib.output_compression = On στο αρχείο php.ini." @@ -222,7 +219,7 @@ INSTL_WRITABLE="Ανεπαρκή δικαιώματα για τη δημιουρ INSTL_ZIP_SUPPORT_AVAILABLE="Ενσωματωμένη υποστήριξη ZIP" ; Global strings -JADMINISTRATOR="Περιοχή Διαχείρισης" +JADMINISTRATOR="Διαχειριστής" JCLOSE="Κλείσιμο" JEMAIL="Email" JERROR="Σφάλμα" @@ -236,7 +233,7 @@ JHIDEPASSWORD="Απόκρυψη κωδικού" JINVALID_TOKEN="Το πιο πρόσφατο αίτημα απορρίφθηκε επειδή περιείχε μη έγκυρο διακριτικό ασφαλείας. Ανανεώστε τη σελίδα και ξαναπροσπαθήστε." JINVALID_TOKEN_NOTICE="Το διακριτικό ασφαλείας δεν ταιριάζει. Το αίτημα ματαιώθηκε για την αποφυγή οποιασδήποτε παραβίασης ασφαλείας. Παρακαλώ δοκιμάστε ξανά." JNEXT="Επόμενο" -JNO="Όχι" +JNO="Ποτέ" JNOTICE="Ειδοποίηση" JOFF="Απενεργοποιημένο" JON="Ενεργοποιημένο" @@ -257,7 +254,7 @@ JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: Η διαδρομή δεν ε JLIB_FORM_FIELD_INVALID="Μη έγκυρο πεδίο: " JLIB_FORM_VALIDATE_FIELD_INVALID="Άκυρο πεδίο: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="Υποχρεωτικό πεδίο: %s" -JLIB_INSTALLER_ABORT="Η εγκατάσταση τη γλώσσας διακόπηκε: %s" +JLIB_INSTALLER_ABORT="Η εγκατάσταση τη γλωσσας ματαιώθηκε: %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Επέκταση %1$s: Αποτυχία δημιουργίας καταλόγου: %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="Η διαδρομή εγκατάστασης δεν υπάρχει" JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Πακέτο %1$s: Προέκυψε σφάλμα κατά την εγκατάσταση μιας επέκτασης: %2$s." diff --git a/installation/language/el-GR/langmetadata.xml b/installation/language/el-GR/langmetadata.xml index 033501ca44f22..c59cd69b3e020 100644 --- a/installation/language/el-GR/langmetadata.xml +++ b/installation/language/el-GR/langmetadata.xml @@ -1,7 +1,7 @@ Greek (el-GR) - 5.4.8 + 6.1.3 2026-07 Ομάδα Μετάφρασης: joomla. gr (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/en-AU/joomla.ini b/installation/language/en-AU/joomla.ini index be52437d6c519..d66e6bc6942d0 100644 --- a/installation/language/en-AU/joomla.ini +++ b/installation/language/en-AU/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Your host needs to use PHP version {{phpversion}} or n BUILD_MIN_PHP_ERROR_URL_TEXT="Help me resolve this" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Change" INSTL_SELECT_INSTALL_LANG="Select Installation Language" INSTL_SELECT_LANGUAGE_TITLE="Select Language" INSTL_SETUP_LOGIN_DATA="Setup Login Data" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Your PHP installation needs to have JSON enabled for Joomla to b INSTL_DATABASE_SUPPORT="Database Support:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Support" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is Default" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="No supported databases were found." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Your PHP installation needs to have JSON enabled for Joomla to be installed!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language is not set to neutral. This can be set locally by entering php_value mbstring.language neutral in your .htaccess file." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload is set. This can be turned off locally by entering php_value mbstring.func_overload 0 in your .htaccess file." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="The required php functions parse_ini_file and parse_ini_string are disabled on your server." INSTL_NOTICE_XML_SUPPORT="XML Support is not available. This should be enabled by default in php but Ubuntu users may need to install this by doing sudo apt-get install php-xml followed by web server restart." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib compression is not set. This can be turned on locally by entering zlib.output_compression = On in your php.ini file." diff --git a/installation/language/en-AU/langmetadata.xml b/installation/language/en-AU/langmetadata.xml index 7e9919aaaff6b..65d398297cc83 100644 --- a/installation/language/en-AU/langmetadata.xml +++ b/installation/language/en-AU/langmetadata.xml @@ -1,7 +1,7 @@ English (Australia) - 5.4.8 + 6.1.3 2026-07 Joomla! Project (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/en-CA/joomla.ini b/installation/language/en-CA/joomla.ini index dea34bbe498ca..3b6f824d0e94f 100644 --- a/installation/language/en-CA/joomla.ini +++ b/installation/language/en-CA/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Your host needs to use PHP version {{phpversion}} or n BUILD_MIN_PHP_ERROR_URL_TEXT="Help me resolve this" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Change" INSTL_SELECT_INSTALL_LANG="Select Installation Language" INSTL_SELECT_LANGUAGE_TITLE="Select Language" INSTL_SETUP_LOGIN_DATA="Setup Login Data" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Your PHP installation needs to have JSON enabled for Joomla to b INSTL_DATABASE_SUPPORT="Database Support:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Support" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is Default" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="No supported databases were found." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Your PHP installation needs to have JSON enabled for Joomla to be installed!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language is not set to neutral. This can be set locally by entering php_value mbstring.language neutral in your .htaccess file." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload is set. This can be turned off locally by entering php_value mbstring.func_overload 0 in your .htaccess file." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="The required php functions parse_ini_file and parse_ini_string are disabled on your server." INSTL_NOTICE_XML_SUPPORT="XML Support is not available. This should be enabled by default in php but Ubuntu users may need to install this by doing sudo apt-get install php-xml followed by web server restart." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib compression is not set. This can be turned on locally by entering zlib.output_compression = On in your php.ini file." diff --git a/installation/language/en-CA/langmetadata.xml b/installation/language/en-CA/langmetadata.xml index a995a8d7ed8a5..24345eb98f59e 100644 --- a/installation/language/en-CA/langmetadata.xml +++ b/installation/language/en-CA/langmetadata.xml @@ -1,7 +1,7 @@ English (Canada) - 5.4.8 + 6.1.3 2026-07 Joomla! Project (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/en-GB/joomla.ini b/installation/language/en-GB/joomla.ini index d11f18d0ea0d2..1dab713f8d58c 100644 --- a/installation/language/en-GB/joomla.ini +++ b/installation/language/en-GB/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Your host needs to use PHP version {{phpversion}} or n BUILD_MIN_PHP_ERROR_URL_TEXT="Help me resolve this" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Change Installation Language" +INSTL_CHANGE_INSTALL_LANG_SHORT="Change" +INSTL_SELECTED_INSTALL_LANGUAGE="Current language: %s" INSTL_SELECT_INSTALL_LANG="Select Installation Language" INSTL_SELECT_LANGUAGE_TITLE="Select Language" INSTL_SETUP_LOGIN_DATA="Setup Login Data" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Your PHP installation needs to have JSON enabled for Joomla to b INSTL_DATABASE_SUPPORT="Database Support:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Support" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is Default" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="No supported databases were found." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Your PHP installation needs to have JSON enabled for Joomla to be installed!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language is not set to neutral. This can be set locally by entering php_value mbstring.language neutral in your .htaccess file." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload is set. This can be turned off locally by entering php_value mbstring.func_overload 0 in your .htaccess file." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="The required php functions parse_ini_file and parse_ini_string are disabled on your server." INSTL_NOTICE_XML_SUPPORT="XML Support is not available. This should be enabled by default in php but Ubuntu users may need to install this by doing sudo apt-get install php-xml followed by web server restart." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib compression is not set. This can be turned on locally by entering zlib.output_compression = On in your php.ini file." diff --git a/installation/language/en-GB/langmetadata.xml b/installation/language/en-GB/langmetadata.xml index 9fad925d682ae..51ddea2a6deab 100644 --- a/installation/language/en-GB/langmetadata.xml +++ b/installation/language/en-GB/langmetadata.xml @@ -1,7 +1,7 @@ English (United Kingdom) - 5.4.8 + 6.2.0 2026-08 Joomla! Project (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/en-NZ/joomla.ini b/installation/language/en-NZ/joomla.ini index 381447fc911f4..5073ec443417c 100644 --- a/installation/language/en-NZ/joomla.ini +++ b/installation/language/en-NZ/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Your host needs to use PHP version {{phpversion}} or n BUILD_MIN_PHP_ERROR_URL_TEXT="Help me resolve this" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Change" INSTL_SELECT_INSTALL_LANG="Select Installation Language" INSTL_SELECT_LANGUAGE_TITLE="Select Language" INSTL_SETUP_LOGIN_DATA="Setup Login Data" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Your PHP installation needs to have JSON enabled for Joomla to b INSTL_DATABASE_SUPPORT="Database Support:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Support" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is Default" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="No supported databases were found." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Your PHP installation needs to have JSON enabled for Joomla to be installed!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language is not set to neutral. This can be set locally by entering php_value mbstring.language neutral in your .htaccess file." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload is set. This can be turned off locally by entering php_value mbstring.func_overload 0 in your .htaccess file." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="The required php functions parse_ini_file and parse_ini_string are disabled on your server." INSTL_NOTICE_XML_SUPPORT="XML Support is not available. This should be enabled by default in php but Ubuntu users may need to install this by doing sudo apt-get install php-xml followed by web server restart." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib compression is not set. This can be turned on locally by entering zlib.output_compression = On in your php.ini file." diff --git a/installation/language/en-NZ/langmetadata.xml b/installation/language/en-NZ/langmetadata.xml index bcfc6fff69de1..0b3205462e423 100644 --- a/installation/language/en-NZ/langmetadata.xml +++ b/installation/language/en-NZ/langmetadata.xml @@ -1,7 +1,7 @@ English (New Zealand) - 5.4.8 + 6.1.3 2026-07 Joomla! Project (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/en-US/joomla.ini b/installation/language/en-US/joomla.ini index bdca6ea745c12..46904ba170ea4 100644 --- a/installation/language/en-US/joomla.ini +++ b/installation/language/en-US/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Your host needs to use PHP version {{phpversion}} or n BUILD_MIN_PHP_ERROR_URL_TEXT="Help me resolve this" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Change" INSTL_SELECT_INSTALL_LANG="Select Installation Language" INSTL_SELECT_LANGUAGE_TITLE="Select Language" INSTL_SETUP_LOGIN_DATA="Setup Login Data" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Your PHP installation needs to have JSON enabled for Joomla to b INSTL_DATABASE_SUPPORT="Database Support:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Support" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is Default" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="No supported databases were found." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Your PHP installation needs to have JSON enabled for Joomla to be installed!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language is not set to neutral. This can be set locally by entering php_value mbstring.language neutral in your .htaccess file." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload is set. This can be turned off locally by entering php_value mbstring.func_overload 0 in your .htaccess file." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="The required php functions parse_ini_file and parse_ini_string are disabled on your server." INSTL_NOTICE_XML_SUPPORT="XML Support is not available. This should be enabled by default in php but Ubuntu users, may need to install by doing sudo apt-get install php-xml followed by web server restart." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib compression is not set. This can be turned on locally by entering zlib.output_compression = On in your php.ini file." @@ -240,9 +237,9 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="Select some options" JGLOBAL_SELECT_SOME_OPTIONS="Select some options" JHIDEPASSWORD="Hide Password" JINVALID_TOKEN="The most recent request was denied because it contained an invalid security token. Please refresh the page and try again." -JINVALID_TOKEN_NOTICE="The security token did not match. The request was cancelled to prevent any security breach. Please try again." +JINVALID_TOKEN_NOTICE="The security token did not match. The request was aborted to prevent any security breach. Please try again." JNEXT="Next" -JNO="No" +JNO="Never" JNOTICE="Notice" JOFF="Off" JON="On" @@ -263,7 +260,7 @@ JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: Path is not a folder. Path: %2 JLIB_FORM_FIELD_INVALID="Invalid field: " JLIB_FORM_VALIDATE_FIELD_INVALID="Invalid field: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="Field required: %s" -JLIB_INSTALLER_ABORT="Stopping language installation: %s" +JLIB_INSTALLER_ABORT="Aborting language installation: %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Extension %1$s: Failed to create folder: %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="Install path does not exist." JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Package %1$s: There was an error installing an extension: %2$s" @@ -304,7 +301,7 @@ NOTICE="Notice" WARNING="Warning" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="A connection error has occurred while fetching the JSON data." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="A connection abort has occured while fetching the JSON data." JLIB_JS_AJAX_ERROR_NO_CONTENT="No content was returned." JLIB_JS_AJAX_ERROR_OTHER="An error has occurred while fetching the JSON data: HTTP %d status code." JLIB_JS_AJAX_ERROR_PARSE="A parse error has occurred while processing the following JSON data:
%s" diff --git a/installation/language/en-US/langmetadata.xml b/installation/language/en-US/langmetadata.xml index a9db4e0137c1c..6d93257a79f93 100644 --- a/installation/language/en-US/langmetadata.xml +++ b/installation/language/en-US/langmetadata.xml @@ -1,7 +1,7 @@ English (United States) - 5.4.8 + 6.1.3 2026-07 Joomla! Project (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/es-ES/joomla.cli.ini b/installation/language/es-ES/joomla.cli.ini index c93e3f8039a57..898e59bccd2ee 100644 --- a/installation/language/es-ES/joomla.cli.ini +++ b/installation/language/es-ES/joomla.cli.ini @@ -1,19 +1,19 @@ INSTL_ADMIN_EMAIL_DESC="Introduzca una dirección de correo electrónico. Debe ser la dirección de correo electrónico del súper administrador del sitio" -INSTL_ADMIN_EMAIL_DESC_SHORT="Dirección de correo electrónico de la cuenta de Superusuario del sitio web" +INSTL_ADMIN_EMAIL_DESC_SHORT="Dirección de correo electrónico de la cuenta Super Usuario del sitio web" INSTL_ADMIN_PASSWORD_DESC="Asigne la contraseña de la cuenta del súper administrador y confírmela en el campo de más abajo" -INSTL_ADMIN_PASSWORD_DESC_SHORT="Contraseña de la cuenta de superusuario" +INSTL_ADMIN_PASSWORD_DESC_SHORT="Contraseña de su cuenta de Super Usuario" INSTL_ADMIN_USERNAME_DESC="Establezca el nombre de usuario para su cuenta de superusuario" -INSTL_ADMIN_USERNAME_DESC_SHORT="Nombre de usuario de su cuenta de superusuario" +INSTL_ADMIN_USERNAME_DESC_SHORT="Nombre de usuario de su cuenta de Super Usuario" INSTL_ADMIN_USER_DESC="Asigna el nombre de usuario para su cuenta de súper administrador" -INSTL_ADMIN_USER_DESC_SHORT="Nombre real de la cuenta de superusuario" +INSTL_ADMIN_USER_DESC_SHORT="Nombre real de la cuenta de Super Usuario" INSTL_DATABASE_COULD_NOT_CONNECT="%s" -INSTL_DATABASE_ENCRYPTION_CA_LABEL="Ruta al archivo CA para verificar el cifrado" +INSTL_DATABASE_ENCRYPTION_CA_LABEL="Ruta al archivo CA contra el que verificar el cifrado" INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Ruta al archivo CA contra el que verificar el cifrado" -INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Ruta al certificado SSL para la conexión con la base de datos. Requiere que el cifrado esté establecido en 2" +INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Ruta al certificado SSL para la conexión a la base de datos. Requiere que el cifrado se establezca en 2" INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Ruta al certificado SSL para la conexión a la base de datos. Requiere que el cifrado se establezca en 2" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Paquete de cifrado soportado (opcional)" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Paquete de cifrado soportado (opcional)" -INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Clave SSL para la conexión con la base de datos. Requiere que el cifrado esté establecido en 2" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Clave SSL para la conexión a la base de datos. Requiere que el cifrado se establezca en 2" INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="Clave SSL para la conexión a la base de datos. Requiere que el cifrado se establezca en 2" INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Cifrado para la conexión a la base de datos. Valores: 0=Ninguno, 1=Unidireccional, 2=Bidireccional" INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="Cifrado para la conexión a la base de datos. Valores: 0=Ninguno, 1=Unidireccional, 2=Bidireccional" diff --git a/installation/language/es-ES/joomla.ini b/installation/language/es-ES/joomla.ini index 650f222970ec4..b9805c22ba487 100644 --- a/installation/language/es-ES/joomla.ini +++ b/installation/language/es-ES/joomla.ini @@ -6,49 +6,46 @@ ; Fatal error page ; These will be processed by the JavaScript Build BUILD_FATAL_HEADER="Lo sentimos, hubo un problema del que no pudimos recuperarnos." -BUILD_FATAL_LANGUAGE="Español ES" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_FATAL_LANGUAGE="English GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_FATAL_TEXT="El servidor devuelve un \"{{statusCode_statusText}}\"" BUILD_FATAL_URL_TEXT="Ayúdeme a resolver esto" ; Build incomplete error page ; These will be processed by the JavaScript Build BUILD_INCOMPLETE_HEADER="Configuración del entorno de trabajo incompleta" -BUILD_INCOMPLETE_LANGUAGE="Español ES" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_INCOMPLETE_LANGUAGE="English GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_INCOMPLETE_TEXT="Parece que está intentando ejecutar Joomla! desde nuestro repositorio en Git. Para hacerlo, primero debe completar un par de pasos adicionales." BUILD_INCOMPLETE_URL_TEXT="Más detalles" ; No XML PHP error page ; These will be processed by the JavaScript Build BUILD_NOXML_HEADER="Lo sentimos, a su PHP le falta una biblioteca esencial" -BUILD_NOXML_LANGUAGE="Español ES" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_NOXML_LANGUAGE="English GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_NOXML_TEXT="Su hospedaje necesita usar PHP con soporte para la biblioteca XML y así poder ejecutar esta versión de Joomla!" BUILD_NOXML_URL_TEXT="Ayúdeme a resolver esto" ; Minimum PHP error page ; These will be processed by the JavaScript Build BUILD_MIN_PHP_ERROR_HEADER="Lo sentimos, su versión de PHP no es compatible." -BUILD_MIN_PHP_ERROR_LANGUAGE="Español ES" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_MIN_PHP_ERROR_LANGUAGE="English GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_MIN_PHP_ERROR_TEXT="Para poder usar esta versión de Joomla su hospedaje necesita usar la versión {{phpversion}} de PHP o superior." BUILD_MIN_PHP_ERROR_URL_TEXT="Ayúdeme a resolver esto" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Cambiar" INSTL_SELECT_INSTALL_LANG="Seleccione el idioma de instalación" INSTL_SELECT_LANGUAGE_TITLE="Seleccione el idioma" INSTL_SETUP_LOGIN_DATA="Configurar los datos de inicio de sesión" INSTL_WARNJAVASCRIPT="¡Advertencia! JavaScript debe estar habilitado para una correcta instalación de Joomla." -INSTL_WARNJSON="¡Para que se pueda instalar Joomla su instalación de PHP necesita tener habilitado JSON!" +INSTL_WARNJSON="Para que se pueda instalar Joomla su instalacción de PHP necesita tener habilitado JSON." ; Precheck view INSTL_DATABASE_SUPPORT="Soporte de la base de datos:" INSTL_JSON_SUPPORT_AVAILABLE="Soporte JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="El idioma de MB es el predeterminado" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="'MB String Overload' desactivado" INSTL_NOTICE_DATABASE_SUPPORT="No se encontraron bases de datos compatibles." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Para que se pueda instalar Joomla su instalacción de PHP necesita tener habilitado JSON." INSTL_NOTICE_MBLANG_NOTDEFAULT="El lenguaje de PHP mbstring no está configurado como neutral. Esto se puede configurar localmente introduciendo php_value mbstring.language neutral en su archivo .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="La sobrecarga de la función PHP mbstring está configurada. Esto se puede desactivar localmente introduciendo php_value mbstring.func_overload 0 en su archivo .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Las funciones requeridas parse_ini_file y parse_ini_string están deshabilitadas en su servidor." INSTL_NOTICE_XML_SUPPORT="El soporte XML no está disponible. Esto debería estar habilitado de forma predeterminada en php, pero los usuarios de Ubuntu pueden necesitar instalar esto desde la consola con sudo apt-get install php-xml seguido del reinicio del servidor web." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="La compresión Zlib no está activada. Esto se puede activar localmente añadiendo zlib.output_compression = On en su archivo .htaccess." @@ -242,7 +239,7 @@ JHIDEPASSWORD="Ocultar contraseña" JINVALID_TOKEN="Las solicitudes recientes han sido denegadas porque tenían un 'token' de seguridad inválido. Por favor, actualice la página e inténtelo de nuevo." JINVALID_TOKEN_NOTICE="El token de seguridad no coincidía. La solicitud se abortó para evitar cualquier violación de seguridad. Vuelve a intentarlo." JNEXT="Siguiente" -JNO="No" +JNO="Nunca" JNOTICE="Notificación" JOFF="Desactivado" JON="Activado" diff --git a/installation/language/es-ES/langmetadata.xml b/installation/language/es-ES/langmetadata.xml index 8878081d4cce9..db570206e0696 100644 --- a/installation/language/es-ES/langmetadata.xml +++ b/installation/language/es-ES/langmetadata.xml @@ -1,7 +1,7 @@ Spanish (es-ES) - 5.4.8 + 6.1.3 2026-07 Spanish [es-ES] Translation Team (C) 2005 Open Source Matters, Inc. @@ -11,7 +11,7 @@ Spanish (es-ES) - Español (España) + Spanish (es-ES) es-ES 0 diff --git a/installation/language/et-EE/joomla.ini b/installation/language/et-EE/joomla.ini index 3ad5ece347458..8958d120484a5 100644 --- a/installation/language/et-EE/joomla.ini +++ b/installation/language/et-EE/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Sinu veebimajutuse pakkuja peab kasutama PHP versiooni BUILD_MIN_PHP_ERROR_URL_TEXT="Aita mul seda lahendada" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Muuda" INSTL_SELECT_INSTALL_LANG="Vali paigalduse keel" INSTL_SELECT_LANGUAGE_TITLE="Vali keel" INSTL_SETUP_LOGIN_DATA="Sisesta sisselogimise info" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Et Joomlat saaks installida, peab sinu PHP-s olema JSON sisse l INSTL_DATABASE_SUPPORT="Andmebaasi tugi:" INSTL_JSON_SUPPORT_AVAILABLE="JSON tugi" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language on vaikeväärtus" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload on välja lülitatud" INSTL_NOTICE_DATABASE_SUPPORT="Ühtegi toetatud andmebaasi ei leitud." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Et Joomlat saaks installida, peab sinu PHP-s olema JSON sisse lülitatud!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language funktsioon pole pandud neutraalseks. Seda saab teha sisestades faili .htaccess rea php_value mbstring.language neutral." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring overload funktsioon on sisse lülitatud. Selle saab välja sisestades faili .htaccess rida php_value mbstring.func_overload 0." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Nõutud PHP funktsioonid parse_ini_file ja parse_ini_string on sinu serveris keelatud." INSTL_NOTICE_XML_SUPPORT="XML tugi pole saadaval. See peaks olema vaikimisi lubatud, aga Ubuntu serveris tuleb seda paigaldada käsuga sudo apt-get install php-xml ja siis server taaskäivitada." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib pakkimismeetod on määramata. Selle saab sisse lülitada sisestades zlib.output_compression = On sinu php.ini faili." @@ -145,7 +142,6 @@ INSTL_LANGUAGES_WARNING_NO_INTERNET="Joomla! ei suutnud keelte serveriga ühendu INSTL_LANGUAGES_WARNING_NO_INTERNET2="Märkus: Sa saad keeled hiljem Joomla! adminiliidesest paigaldada." ; Automated Updates Opt Out -INSTL_AUTOMATED_UPDATES="Automaatsed uuendused" INSTL_AUTOMATED_UPDATES_DESC="Joomla uuendab end automaatselt väikeste väljalasete ja parandusväljalasete korral.

Palun pane tähele: automaatsed uuendused registreerivad sinu lehe Joomla! projekti hallatavas teenuses. See registreerimine võimaldab Joomla projektil saada teavet sinu lehe ja serveri keskkonna kohta, sealhulgas lehe URL, PHP versioon, andmebaasi tüüp ja versioon, CMS-i versioon ning serveri operatsioonisüsteemi tüüp ja versioon. Seda teavet kasutatakse ainult teenuse parandamiseks.

Soovi korral saad automaatsed uuendused alloleva nupu abil keelata." INSTL_AUTOMATED_UPDATES_DISABLE="Keela automaatsed uuendused" INSTL_COMPLETE_ERROR_AUTOMATED_UPDATES_DISABLE="Ei suutnud keelata automaatset uuendamist." diff --git a/installation/language/et-EE/langmetadata.xml b/installation/language/et-EE/langmetadata.xml index 0e186f0276e53..dbb787217aeee 100644 --- a/installation/language/et-EE/langmetadata.xml +++ b/installation/language/et-EE/langmetadata.xml @@ -1,7 +1,7 @@ Estonian - 5.4.8 + 6.1.3 2026-07 Joomla! Project (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/eu-ES/joomla.ini b/installation/language/eu-ES/joomla.ini index 4302a87c0e689..be839c0f2d583 100644 --- a/installation/language/eu-ES/joomla.ini +++ b/installation/language/eu-ES/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Zure ostalariak PHP bertsio hau {{phpversion}} edo be BUILD_MIN_PHP_ERROR_URL_TEXT="Lagundu niri hau konpontzen" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Aldatu" INSTL_SELECT_INSTALL_LANG="Hautatu Instalazio Hizkuntza" INSTL_SELECT_LANGUAGE_TITLE="Hautatu Hizkuntza" INSTL_SETUP_LOGIN_DATA="Konfiguratu Saio-hasierako Datuak" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Zure PHP instalazioak JSON gaituta eduki behar du Joomla! instal INSTL_DATABASE_SUPPORT="Datu-base Laguntza:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Laguntza" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Hizkuntza da Lehenetsia" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload desgaituta" INSTL_NOTICE_DATABASE_SUPPORT="Ez da aurkitu datu-base bateragarririk." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Zure PHP instalazioak JSON gaituta eduki behar du Joomla! instalatu ahal izateko!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language ez dago jarrita neutral gisa jarrita. Hau ezar daiteke gunean bertan idatziz php_value mbstring.language neutral zure .htaccess fitxategian." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP 'mbstring function overload' gaituta dago. Hau desgaitu daiteke gunean bertan idatziz php_value mbstring.func_overload 0 zure .htaccess fitxategian." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Beharrezko php funtzioak parse_ini_file eta parse_ini_string desgaituta daude zure zerbitzarian." INSTL_NOTICE_XML_SUPPORT="XML laguntza ez dago erabilgarri. Hau lehenetsita gaitu beharko litzateke php-n, baina Ubuntu erabiltzaileek instalatu beharko dute sudo apt-get install php-xml eginez eta ondoren web zerbitzaria berrabiarazteko." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib konpresioa ez dago ezarrita. Hau lokalki aktiba daiteke zlib.output_compression = On ezarrita zure php.ini fitxategian." diff --git a/installation/language/eu-ES/langmetadata.xml b/installation/language/eu-ES/langmetadata.xml index eef0198a374da..2ac11f84df959 100644 --- a/installation/language/eu-ES/langmetadata.xml +++ b/installation/language/eu-ES/langmetadata.xml @@ -1,7 +1,7 @@ Basque - 5.4.8 + 6.1.3 2026-07 Joomla! Basque Translation Team (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/fa-AF/joomla.ini b/installation/language/fa-AF/joomla.ini index 4a3318f6b882c..5d53f8d29b55d 100644 --- a/installation/language/fa-AF/joomla.ini +++ b/installation/language/fa-AF/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="شما برای اجرای این نسخه از جوم BUILD_MIN_PHP_ERROR_URL_TEXT="برای حل این مشکل کمک کن" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="تغییر" INSTL_SELECT_INSTALL_LANG="زبان نصب را انتخاب کنید" INSTL_SELECT_LANGUAGE_TITLE="انتخاب لسان" INSTL_SETUP_LOGIN_DATA="تنظیمات اطلاعات ورود" @@ -42,13 +43,9 @@ INSTL_WARNJSON="برای نصب جوملا ، تابع JSON باید در PHP س INSTL_DATABASE_SUPPORT="پشتیبانی از دیتابیس:" INSTL_JSON_SUPPORT_AVAILABLE="پشتیبانی از JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language پیش‌فرض است" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload خاموش است" INSTL_NOTICE_DATABASE_SUPPORT="هیچ دیتابیسی که توسط جوملا پشتیبانی شود پیدا نشد." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="برای نصب جوملا ، تابع JSON باید در PHP سرور شما فعال باشد!" INSTL_NOTICE_MBLANG_NOTDEFAULT="متغیر MB String در پی اچ پی تنظیم نشده است.می‌توانید این مورد را با وارد کردن php_value mbstring.language neutral در فایل .htaccess>/code> خود تنظیم کنید." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="متغییر mbstring overload در پی اچ پی تنظیم شده است. و می‌توانید با وارد کردن php_value mbstring.func_overload 0 در فایل .htaccess آنرا غیر فعال کنید." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="توابع الزامی parse_ini_file و parse_ini_string باید روی سرور غیرفعال باشند." INSTL_NOTICE_XML_SUPPORT="پشتیبانی از XML در دسترس نیست. این مورد باید بصورت پیش‌فرض فعال باشد اما برای کاربران اوبونتو می‌توانید با دستور sudo apt-get install php-xml و ری‌استارت سرور این مورد را در php خود نصب کنید." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="قابلیت Zlib compression تعیین نشده است. شما می‌توانید بصورت محلی با وارد کردن zlib.output_compression = Onدر php.ini این قابلیت را فعال کنید." @@ -74,10 +71,6 @@ INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="پیش‌فرض (کنترل شده‌ INSTL_DATABASE_ENCRYPTION_MODE_VALUE_ONE_WAY="احراز هویت تک مرحله‌ای" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_TWO_WAY="احراز هویت دو مرحله‌ای" INSTL_DATABASE_ENCRYPTION_MSG_CONN_NOT_ENCRYPT="شما رمزنگاری اتصال به دیتابیس را انتخاب کرده‌اید، و می‌توان این اتصال را برقرار کرد، اما این اتصال رمزنگاری نشده است. دلیل این اتفاق ممکن است از پیکربندی نادرست برای بازگشت یک اتصال رمزنگاری نشده از طرف سرور بابت پارامترهای رمزنگاری باشد. به همین منظور پارامترهای رمزنگاری دیتابیس را چک کنید یا فیلد مربوط به «رمزنگاری اتصال» را به حالت «پیش‌فرض (کنترل شده توسط سرور)» تغییر دهید." -INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="فایل وارد شده در فیلد «%s» وجود ندارد یا در دسترس نیست." -INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_EMPTY="فیلد \"%s\" خالی است یا شامل مسیر معتبر نیست." -INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="شما نام هاست را «localhost» وارد کرده‌اید. اتصال به پایگاه داده با رمزگذاری اتصال ممکن است ناموفق باشد. برای این کار می‌توانید به جای عبارت «localhost» از «127.0.0.1» یا «::1» یا سایر نام هاست‌ها استفاده کنید یا اینکه «رمرزنگاری اتصال» را به حالت «پیش‌فرض (کنترل شده توسط سرور)» برگردانید." -INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="سرور دیتابیس، از رمزنگاری اتصال پشتیبانی نمی‌کند. با فعالسازی TLS (که در مستندات به SSL از آن یاد شده) ممکن است مشکل حل شود، یا اینکه فیلد «رمزنگاری اتصال» را به «پیش‌فرض (کنترل توسط سرور)» تغییر دهید." INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="نمایش گواهینامه‌های سرور" INSTL_DATABASE_ERROR_POSTGRESQL_QUERY="کوئری پایگاه داده PostgreSQ ناموفق بود." INSTL_DATABASE_HOST_DESC="نام هاست را وارد کنید، معمولا «localhost» یا نامی که توسط هاست معرفی می‌شود است." @@ -249,7 +242,6 @@ JYES="بلی" JLIB_DATABASE_ERROR_CONNECT_MYSQL="اتصال به MYSQL ناموفق بود." JLIB_DATABASE_ERROR_DATABASE="خطایی در دیتابیس رخ داده است." JLIB_DATABASE_ERROR_LOAD_DATABASE_DRIVER="بارگذاری درایور دیتابیس امکان پذیر نیست: %s" -JLIB_DATABASE_ERROR_VALID_MAIL="آدرس ایمیل وارد شده نامعتبر است. لطفاً از یک ایمیل دیگر استفاده کنید." JLIB_ENVIRONMENT_SESSION_EXPIRED="نشست شما منقضی شده است، لطفا صفحه را (Reload) مجدداً بارگزاری کنید." JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: مسیر شامل پوشه نیست. مسیر: %2$s" JLIB_FORM_FIELD_INVALID="فیلد نامعتبر:  " @@ -310,7 +302,6 @@ JFIELD_PASSWORD_TOO_LONG="رمزعبور خیلی طولانیست. رمزعبو JFIELD_PASSWORD_TOO_SHORT_N="رمزعبور خیلی کوتاه است. رمزعبور حداقل باید %d حرف داشته باشد." ; Javascript Form Validation Messages -JLIB_FORM_CONTAINS_INVALID_FIELDS="فرم را نمی‌توان ارسال کرد زیرا فاقد اطلاعات مورد نیاز است.
لطفاً فیلدهایی که ستاره‌دار هستند را با دقت پر کنید و مجدداً تلاش کنید." JLIB_FORM_FIELD_INVALID_VALUE="این مقدار معتبر نیست." JLIB_FORM_FIELD_REQUIRED_CHECK="یک گزینه باید انتخاب شود." JLIB_FORM_FIELD_REQUIRED_VALUE="این فیلد را پر کنید." diff --git a/installation/language/fa-AF/langmetadata.xml b/installation/language/fa-AF/langmetadata.xml index 997eae287668c..5212e0e0338c9 100644 --- a/installation/language/fa-AF/langmetadata.xml +++ b/installation/language/fa-AF/langmetadata.xml @@ -1,7 +1,7 @@ فارسی (دری) - 5.4.8 + 6.1.3 2026-07 JoomlaPersian Translation Team (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/fa-IR/joomla.ini b/installation/language/fa-IR/joomla.ini index fc597004f0d43..6c766ca9c278a 100644 --- a/installation/language/fa-IR/joomla.ini +++ b/installation/language/fa-IR/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="میزبان شما برای اجرای این نسخ BUILD_MIN_PHP_ERROR_URL_TEXT="به من کمک کنید تا این مسئله را حل کنم" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="تغییر" INSTL_SELECT_INSTALL_LANG="زبان نصب را انتخاب کنید" INSTL_SELECT_LANGUAGE_TITLE="انتخاب زبان" INSTL_SETUP_LOGIN_DATA="داده ورود به سیستم را تنظیم کنید" @@ -42,13 +43,9 @@ INSTL_WARNJSON="برای نصب PHP شما باید JSON فعال باشد تا INSTL_DATABASE_SUPPORT="پشتیبانی پایگاه داده:" INSTL_JSON_SUPPORT_AVAILABLE="پشتیبانی از JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB زبان پیش فرض است" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB اضافه بار رشته خاموش است" INSTL_NOTICE_DATABASE_SUPPORT="هیچ پایگاه داده پشتیبانی شده یافت نشد." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="برای نصب PHP شما باید JSON فعال باشد تا جوملا نصب شود!" INSTL_NOTICE_MBLANG_NOTDEFAULT="زبان PHP mbstring روی حالت خنثی تنظیم نشده است. می توانید بصورت دستی با وارد کردن php_value mbstring.language neutral در فایل .htaccess خود تنظیم کنید." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="اضافه بار تابع PHP mbstring تنظیم شده است. می توانید با وارد کردن به صورت محلی php_value mbstring.func_overload 0 در فایل .htaccess خاموش کرد." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="توابع مورد نیاز parse_ini_file و parse_ini_string در سرور شما غیر فعال هستند." INSTL_NOTICE_XML_SUPPORT="پشتیبانی XML در دسترس نیست. این مورد باید به صورت پیش فرض در php فعال باشد اما ممکن است کاربران اوبونتو با انجام sudo apt-get install php-xml و سپس اه اندازی مجدد وب سرور، این مورد را نصب کنند." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="فشرده سازی Zlib تنظیم نشده است. با وارد کردن zlib.output_compression = روشن در پرونده php.ini خود، می توانید این مورد را به صورت محلی فعال کنید." diff --git a/installation/language/fa-IR/langmetadata.xml b/installation/language/fa-IR/langmetadata.xml index bec6d31b25a93..8b0fcef2f2295 100644 --- a/installation/language/fa-IR/langmetadata.xml +++ b/installation/language/fa-IR/langmetadata.xml @@ -1,7 +1,7 @@ Persian (fa-IR) - 5.4.8 + 6.1.3 2026-07 Persian Translation Team: joomlafarsi.com (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/fi-FI/joomla.ini b/installation/language/fi-FI/joomla.ini index fef53acd61a1c..23b280bb963e9 100644 --- a/installation/language/fi-FI/joomla.ini +++ b/installation/language/fi-FI/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Palvelimen täytyy käyttää PHP-versiota {{phpversio BUILD_MIN_PHP_ERROR_URL_TEXT="Auta minua ratkaisemaan tämä" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Muuta asennuskieltä" +INSTL_CHANGE_INSTALL_LANG_SHORT="Vaihda" +INSTL_SELECTED_INSTALL_LANGUAGE="Käytössä oleva kieli: %s" INSTL_SELECT_INSTALL_LANG="Valitse asennuskieli" INSTL_SELECT_LANGUAGE_TITLE="Valitse kieli" INSTL_SETUP_LOGIN_DATA="Aseta kirjautumistiedot" @@ -42,13 +45,9 @@ INSTL_WARNJSON="PHP-asennuksessasi tulee olla JSON käytössä, jotta Joomla ase INSTL_DATABASE_SUPPORT="Database Support:" INSTL_JSON_SUPPORT_AVAILABLE="JSON-tuki" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language on oletus" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="Tuettuja tietokantoja ei löytynyt." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="PHP-asennuksessasi tulee olla JSON käytössä, jotta Joomla asentuu!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring kieli ei ole asetettu arvoon neutral. Tämä voidaan tehdä paikallisesti kirjoittamalla php_value mbstring.language neutral tiedostoon .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload -asetus on käytössä. Tämä voidaan estää paikallisesti kirjoittamalla php_value mbstring.func_overload 0 tiedostoon .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Vaaditut php-funktiot parse_ini_file ja parse_ini_string eivät ole käytettävissä palvelimellasi." INSTL_NOTICE_XML_SUPPORT="XML-tuki ei ole käytettävissä. Tämän pitäisi olla oletusarvoisesti käytössä php:ssä, mutta Ubuntu käyttäjät saattavat joutua asentamaan tämän komennolla sudo apt-get install php-xml sekä tehdä web-palvelimen uudelleenkäynnistys." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib-pakkaus ei ole käytettävissä. Tämän voi ottaa käyttöön paikallisesti lisäämällä teksti zlib.output_compression = Onphp.ini-tiedostoon." diff --git a/installation/language/fi-FI/langmetadata.xml b/installation/language/fi-FI/langmetadata.xml index 28a506981fe9e..0f200a70b513d 100644 --- a/installation/language/fi-FI/langmetadata.xml +++ b/installation/language/fi-FI/langmetadata.xml @@ -1,7 +1,7 @@ Finnish (Finland) - 5.4.8 + 6.1.3 2026-07 Finnish translation team: Joomla.fi (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/fr-CA/joomla.ini b/installation/language/fr-CA/joomla.ini index c3a7086440124..9754358fd80ad 100644 --- a/installation/language/fr-CA/joomla.ini +++ b/installation/language/fr-CA/joomla.ini @@ -14,7 +14,7 @@ BUILD_FATAL_URL_TEXT="Aidez-moi à résoudre ceci" ; These will be processed by the JavaScript Build BUILD_INCOMPLETE_HEADER="Configuration de l'environnement incomplète" BUILD_INCOMPLETE_LANGUAGE="Français FR" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_INCOMPLETE_TEXT="Il semble que vous essayez d'exécuter Joomla! depuis notre dépôt git. Pour cela vous devez d'abord compléter quelques étapes supplémentaires." +BUILD_INCOMPLETE_TEXT="Il semble que vous essayez d'exécuter Joomla! depuis notre dépôt git. Pour ce faire, vous devez d'abord compléter quelques étapes supplémentaires." BUILD_INCOMPLETE_URL_TEXT="Plus de détails" ; No XML PHP error page @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Votre serveur a besoin d'utiliser la version {{phpvers BUILD_MIN_PHP_ERROR_URL_TEXT="Aidez-moi à résoudre ceci" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Changer la langue d'installation" +INSTL_CHANGE_INSTALL_LANG_SHORT="Sélectionnez la position" +INSTL_SELECTED_INSTALL_LANGUAGE="Langue actuelle : %s" INSTL_SELECT_INSTALL_LANG="Choix de la langue d’installation" INSTL_SELECT_LANGUAGE_TITLE="Choix de la langue" INSTL_SETUP_LOGIN_DATA="Configuration des données de connexion" @@ -42,13 +45,9 @@ INSTL_WARNJSON="JSON doit être activé sur le serveur PHP pour pouvoir installe INSTL_DATABASE_SUPPORT="Bases de données supportées :" INSTL_JSON_SUPPORT_AVAILABLE="Support JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="Directive Mbstring langage par défaut" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="Directive Mbstring overload désactivée" INSTL_NOTICE_DATABASE_SUPPORT="Aucune base de données prise en charge n’a été trouvée." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="JSON doit être activé sur le serveur PHP pour pouvoir installer Joomla." INSTL_NOTICE_MBLANG_NOTDEFAULT="La directive PHP mbstring language n'est pas paramétrée à 'neutral'. Cela peut être fait en rajoutant php_value mbstring.language neutral dans le fichier .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="La directive PHP mbstring overload est activée. Vous pouvez la désactiver en ajoutant php_value mbstring.func_overload 0 dans le fichier ..htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Les fonctions parse_ini_file et parse_ini_string sont requises mais elles sont déactivées sur votre serveur PHP." INSTL_NOTICE_XML_SUPPORT="Le support XML n'est pas activé dans PHP. Les utilisateurs d'Ubuntu peuvent l'installer avec la commande sudo apt-get install php-xml suivi d'un redémarrage du serveur web." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="La compression Zlib n'est pas définie. Elle peut être activée localement en saisissant la ligne zlib.output_compression = On dans le fichier php.ini." @@ -240,9 +239,9 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="Aucun résultat correspondant" JGLOBAL_SELECT_SOME_OPTIONS="Sélectionnez certaines options" JHIDEPASSWORD="Masquer le mot de passe" JINVALID_TOKEN="La dernière requête a été refusée car elle contenait un marqueur de sécurité invalide. Rafraîchissez la page et réessayez." -JINVALID_TOKEN_NOTICE="L'identifiant de sécurité ne correspond pas. La requête a été annulée pour éviter toute violation de sécurité. Veuillez réessayer." +JINVALID_TOKEN_NOTICE="L'identifiant de sécurité ne correspondait pas. La demande a été interrompue pour empêcher toute violation de la sécurité. Veuillez réessayer." JNEXT="Suivant" -JNO="Non" +JNO="Jamais" JNOTICE="Annonce" JOFF="Désactivé" JON="Activé" @@ -263,7 +262,7 @@ JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s : Le chemin n'est pas un dossie JLIB_FORM_FIELD_INVALID="Champ invalide : " JLIB_FORM_VALIDATE_FIELD_INVALID="Champ invalide: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="Champ requis: %s" -JLIB_INSTALLER_ABORT="Arrêt de l'installation de la langue : %s" +JLIB_INSTALLER_ABORT="Interruption de l'installation de la langue : %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Extension %1$s : Impossible de créer le répertoire %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="Le chemin d'installation n'existe pas" JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Pack %1$s : erreur lors de l'installation de l'extension %2$s." @@ -304,7 +303,7 @@ NOTICE="Annonce" WARNING="Alerte" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Une erreur de connexion a eu lieu lors de la récupération des données JSON." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Une interruption de connexion est survenue lors de la récupération des données JSON." JLIB_JS_AJAX_ERROR_NO_CONTENT="Aucun contenu n'a été retourné." JLIB_JS_AJAX_ERROR_OTHER="Une erreur s'est produite lors de la récupération des données JSON : HTTP %d status code." JLIB_JS_AJAX_ERROR_PARSE="Une erreur d'analyse s'est produite lors du traitement des données JSON suivantes :
%s" diff --git a/installation/language/fr-CA/langmetadata.xml b/installation/language/fr-CA/langmetadata.xml index d8d4e09290a16..9d9a0fb45340f 100644 --- a/installation/language/fr-CA/langmetadata.xml +++ b/installation/language/fr-CA/langmetadata.xml @@ -1,9 +1,9 @@ French (Canada) - 5.4.8 + 6.1.3 2026-07 - Joomla! Project - French translation team + Joomla! Project - Canadian translation team (C) 2005 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt diff --git a/installation/language/fr-FR/joomla.ini b/installation/language/fr-FR/joomla.ini index 2a96496f5e2a6..edc89f17177c7 100644 --- a/installation/language/fr-FR/joomla.ini +++ b/installation/language/fr-FR/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Votre serveur a besoin d'utiliser la version {{phpvers BUILD_MIN_PHP_ERROR_URL_TEXT="Aidez-moi à résoudre ceci" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Changer la langue d'installation" +INSTL_CHANGE_INSTALL_LANG_SHORT="Sélectionnez la position" +INSTL_SELECTED_INSTALL_LANGUAGE="Langue actuelle : %s" INSTL_SELECT_INSTALL_LANG="Choix de la langue d’installation" INSTL_SELECT_LANGUAGE_TITLE="Choix de la langue" INSTL_SETUP_LOGIN_DATA="Configuration des données de connexion" @@ -42,13 +45,9 @@ INSTL_WARNJSON="JSON doit être activé sur le serveur PHP pour pouvoir installe INSTL_DATABASE_SUPPORT="Bases de données supportées :" INSTL_JSON_SUPPORT_AVAILABLE="Support JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="Directive Mbstring langage par défaut" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="Directive Mbstring overload désactivée" INSTL_NOTICE_DATABASE_SUPPORT="Aucune base de données prise en charge n’a été trouvée." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="JSON doit être activé sur le serveur PHP pour pouvoir installer Joomla." INSTL_NOTICE_MBLANG_NOTDEFAULT="La directive PHP mbstring language n'est pas paramétrée à 'neutral'. Cela peut être fait en rajoutant php_value mbstring.language neutral dans le fichier .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="La directive PHP mbstring overload est activée. Vous pouvez la désactiver en ajoutant php_value mbstring.func_overload 0 dans le fichier ..htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Les fonctions parse_ini_file et parse_ini_string sont requises mais elles sont déactivées sur votre serveur PHP." INSTL_NOTICE_XML_SUPPORT="Le support XML n'est pas activé dans PHP. Les utilisateurs d'Ubuntu peuvent l'installer avec la commande sudo apt-get install php-xml suivi d'un redémarrage du serveur web." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="La compression Zlib n'est pas définie. Elle peut être activée localement en saisissant la ligne zlib.output_compression = On dans le fichier php.ini." @@ -145,7 +144,7 @@ INSTL_LANGUAGES_WARNING_NO_INTERNET="Le système d'installation ne peut pas se c INSTL_LANGUAGES_WARNING_NO_INTERNET2="Note : vous pourrez installer d’autres langues plus tard depuis l’administration de Joomla." ; Automated Updates Opt Out -INSTL_AUTOMATED_UPDATES="Mises à jour automatiques" +INSTL_AUTOMATED_UPDATES="Mises à jour automatisées" INSTL_AUTOMATED_UPDATES_DESC="Joomla se met à jour automatiquement pour les versions mineures et les correctifs.

Veuillez noter que : les mises à jour automatisées enregistrent votre site auprès du service fourni par le projet Joomla, ce qui lui permet d'accéder aux informations suivantes sur votre site web et votre environnement serveur : Url du site, version PHP, version et type de base de données, version du CMS et version du système d'exploitation du serveur. Ces informations ne sont utilisées que pour améliorer le service.

Si vous ne souhaitez pas communiquer ces informations, vous pouvez désactiver les mises à jour automatisées en cliquant sur le bouton ci-dessous." INSTL_AUTOMATED_UPDATES_DISABLE="Désactiver les mises à jour automatisées" INSTL_COMPLETE_ERROR_AUTOMATED_UPDATES_DISABLE="Impossible de désactiver les mises à jour automatisées." @@ -240,7 +239,7 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="Aucun résultat correspondant" JGLOBAL_SELECT_SOME_OPTIONS="Sélectionnez certaines options" JHIDEPASSWORD="Masquer le mot de passe" JINVALID_TOKEN="La dernière requête a été refusée car elle contenait un marqueur de sécurité invalide. Rafraîchissez la page et réessayez." -JINVALID_TOKEN_NOTICE="L'identifiant de sécurité ne correspond pas. La requête a été annulée pour éviter toute violation de sécurité. Veuillez réessayer." +JINVALID_TOKEN_NOTICE="L'identifiant de sécurité ne correspondait pas. La demande a été interrompue pour empêcher toute violation de la sécurité. Veuillez réessayer." JNEXT="Suivant" JNO="Non" JNOTICE="Annonce" @@ -263,7 +262,7 @@ JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s : Le chemin n'est pas un dossie JLIB_FORM_FIELD_INVALID="Champ invalide : " JLIB_FORM_VALIDATE_FIELD_INVALID="Champ invalide: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="Champ requis: %s" -JLIB_INSTALLER_ABORT="Arrêt de l'installation de la langue : %s" +JLIB_INSTALLER_ABORT="Interruption de l'installation de la langue : %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Extension %1$s : Impossible de créer le répertoire %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="Le chemin d'installation n'existe pas" JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Pack %1$s : erreur lors de l'installation de l'extension %2$s." @@ -304,7 +303,7 @@ NOTICE="Annonce" WARNING="Alerte" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Une erreur de connexion a eu lieu lors de la récupération des données JSON." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Une interruption de connexion est survenue lors de la récupération des données JSON." JLIB_JS_AJAX_ERROR_NO_CONTENT="Aucun contenu n'a été retourné." JLIB_JS_AJAX_ERROR_OTHER="Une erreur s'est produite lors de la récupération des données JSON : HTTP %d status code." JLIB_JS_AJAX_ERROR_PARSE="Une erreur d'analyse s'est produite lors du traitement des données JSON suivantes :
%s" diff --git a/installation/language/fr-FR/langmetadata.xml b/installation/language/fr-FR/langmetadata.xml index de6578feb1d9b..7bf8bdbeed298 100644 --- a/installation/language/fr-FR/langmetadata.xml +++ b/installation/language/fr-FR/langmetadata.xml @@ -1,7 +1,7 @@ French (fr-FR) - 5.4.8 + 6.1.3 2026-07 Joomla! Project - French translation team (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/he-IL/joomla.ini b/installation/language/he-IL/joomla.ini index 5d0f76362c9dc..2da54ba162a8e 100644 --- a/installation/language/he-IL/joomla.ini +++ b/installation/language/he-IL/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="השרת מארח שלך צריך להשתמש בגר BUILD_MIN_PHP_ERROR_URL_TEXT="עזור לי לפתור זאת" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="שינוי מיקום" INSTL_SELECT_INSTALL_LANG="בחר שפת התקנה" INSTL_SELECT_LANGUAGE_TITLE="בחירת שפה" INSTL_SETUP_LOGIN_DATA="הגדרת נתוני התחברות" @@ -42,13 +43,9 @@ INSTL_WARNJSON="גרסת ה-PHP המותקנת, מחייבת JSON במצב מא INSTL_DATABASE_SUPPORT="תמיכה בבסיסי נתונים:" INSTL_JSON_SUPPORT_AVAILABLE="תמיכת JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="שפת (קידוד) מרובת בתים היא ברירת המחדל" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="העמסת מחרוזת בשפת (קידוד) מרובת בתים כבויה" INSTL_NOTICE_DATABASE_SUPPORT="לא נמצאו בסיסי נתונים נתמכים." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="גרסת ה-PHP המותקנת, מחייבת JSON במצב מאופשר, כדי להתקין את ג'ומלה!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP שפת (קידוד) מרובת בתים אינה מוגדרת למצב טבעי.ניתן להגדיר זאת על ידי הכנסת php_value mbstring.language neutral בקובץ .htaccess שלכם." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP שפת (קידוד) מרובת בתים - פונקציית טעינת יתר מוגדרת. ניתן לבטל את ההגדרה בעזרת הכנסת php_value mbstring.func_overload 0 בקובץ .htaccess שלכם." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="The required php functions parse_ini_file and parse_ini_string are disabled on your server." INSTL_NOTICE_XML_SUPPORT="XML Support is not available. This should be enabled by default in php but Ubuntu users may need to install this by doing sudo apt-get install php-xml followed by web server restart." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib compression is not set. This can be turned on locally by entering zlib.output_compression = On in your php.ini file." diff --git a/installation/language/he-IL/langmetadata.xml b/installation/language/he-IL/langmetadata.xml index 1124444bfb345..a9bc1ce45039b 100644 --- a/installation/language/he-IL/langmetadata.xml +++ b/installation/language/he-IL/langmetadata.xml @@ -1,7 +1,7 @@ Hebrew (Israel) - 5.4.8 + 6.1.3 2026-07 פרוייקט ג'ומלה (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/hr-HR/joomla.ini b/installation/language/hr-HR/joomla.ini index a58ef269d9dd2..9643cd3a0d721 100644 --- a/installation/language/hr-HR/joomla.ini +++ b/installation/language/hr-HR/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Za pokretanje ove Joomla verzije, vaš host treba kori BUILD_MIN_PHP_ERROR_URL_TEXT="Pomozite mi riješiti ovo" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Promjena pozicije" INSTL_SELECT_INSTALL_LANG="Odaberite jezik instalacije" INSTL_SELECT_LANGUAGE_TITLE="Odaberite jezik" INSTL_SETUP_LOGIN_DATA="Postavke podataka za pristup" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Vaša PHP instalacija mora imati podršku za JSON da bi se Jooml INSTL_DATABASE_SUPPORT="Podrška baze podataka:" INSTL_JSON_SUPPORT_AVAILABLE="JSON podrška" INSTL_MB_LANGUAGE_IS_DEFAULT="MB jezik je osnovni" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload isključen" INSTL_NOTICE_DATABASE_SUPPORT="Nije pronađena podržana baza podataka." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Vaša PHP instalacija mora imati podršku za JSON da bi se Joomla! mogla instalirati!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring jezik nije neutralan. Ovo možete namjestiti lokalno unošenjem php_value mbstring.language neutral u .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload je uključen. Ovo može biti isključeno lokalno unošenjem php_value mbstring.func_overload 0 u .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Potrebne php funkcije parse_ini_file i parse_ini_string onemogućene su na vašem serveru." INSTL_NOTICE_XML_SUPPORT="XML podrška nije dostupna. Ovo bi trebalo biti omogućeno prema zadanim postavkama u php-u, ali korisnici Ubuntu-a možda će to trebati instalirati izvedbom sudo apt-get install php-xml nakon čega je potrebno resetirati web server." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib kompresija nije postavljena. To se može lokalno uključiti unosom zlib.output_compression = On u datoteku php.ini." @@ -67,7 +64,6 @@ INSTL_ZLIB_COMPRESSION_SUPPORT="Podrška za Zlib kompresiju" INSTL_DATABASE="Konfiguracija baze podataka" INSTL_DATABASE_ENCRYPTION_CA_LABEL="Putanja do CA datoteke" INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Putanja do datoteke certifikata" -INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Podržani Cipher Suite - paket šifriranja (opcionalno)" INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Putanja do datoteke privatnog ključa" INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Enkripcija konekcije" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="Standardno (kontrolira poslužitelj)" @@ -76,7 +72,6 @@ INSTL_DATABASE_ENCRYPTION_MODE_VALUE_TWO_WAY="Dvosmjerna autentifikacija" INSTL_DATABASE_ENCRYPTION_MSG_CONN_NOT_ENCRYPT="Odabrano je korištenje šifrirane veze s bazom podataka i veza bi se mogla uspostaviti, ali nije šifrirana. Razlog bi mogao biti taj što je poslužitelj baze podataka konfiguriran da se vrati na nešifriranu vezu u slučaju loših parametara šifriranja. Provjeri i ispravi parametre šifriranja baze podataka ili promijeni polje \"Šifriranje veze\" natrag na \"Zadano (kontrolira poslužitelj)\"." INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="Datoteka unesena u polje \"%s\" ne postoji ili joj nije moguće pristupiti." INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_EMPTY="Polje \"%s\" je prazno ili ne sadrži važeću putanju." -INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="Upisali ste \"localhost\" kao naziv hosta. Povezivanje s bazom podataka pomoću šifrirane veze moglo bi dovesti do neuspjeha. Ili promijenite \"localhost\" u \"127.0.0.1\" ili \":: 1\" ili drugi naziv hosta ili promijenite polje \"Šifriranje veze\" natrag na \"Zadano (kontrolira poslužitelj) \"." INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="Poslužitelj baze podataka ne podržava šifriranje veze. Ili omogući podršku za TLS (često se naziva SSL u dokumentima) na svom poslužitelju baze podataka ili promijeni polje \"Šifriranje veze\" natrag na \"Zadano (kontrolira poslužitelj)\"." INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Provjeri certifikat servera" INSTL_DATABASE_ERROR_POSTGRESQL_QUERY="PostgreSQL upit na bazu nije uspio." @@ -114,7 +109,7 @@ INSTL_SITE_DEVMODE_LABEL="Detektiran je razvojni način rada" INSTL_SITE_NAME_DESC="Upišite ime vašeg Joomla sitea." ; Expert View -INSTL_PUBLIC_FOLDER_DESC="Relativna ili absolutna putanja do javnog direktorija" +INSTL_PUBLIC_FOLDER_DESC="Relativna ili apsolutna putanja do javnog direktorja" INSTL_PUBLIC_FOLDER_DESC_SHORT="Relativna ili apsolutna putanja do javnog direktorja" ; Complete view @@ -234,9 +229,7 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="Nijedan rezultat se ne poklapa" JGLOBAL_SELECT_SOME_OPTIONS="Odaberi neke opcije" JHIDEPASSWORD="Sakrij lozinku" JINVALID_TOKEN="Posljednji zahtjev je odbijen jer je sadržavao neispravan sigurnosni token. Molimo osvježite stranicu i pokušajte ponovo." -JINVALID_TOKEN_NOTICE="Sigurnosni "_QQ_"token"_QQ_" ne odgovara. Zahtjev je prekinut kako bi se spriječila bilo kakva povreda sigurnosti. Molimo pokušajte ponovno." JNEXT="Sljedeće" -JNO="Ne" JNOTICE="Napomena" JOFF="Isključeno" JON="Uključeno" diff --git a/installation/language/hr-HR/langmetadata.xml b/installation/language/hr-HR/langmetadata.xml index 178fd87de4f86..61183bda0c70e 100644 --- a/installation/language/hr-HR/langmetadata.xml +++ b/installation/language/hr-HR/langmetadata.xml @@ -1,7 +1,7 @@ Hrvatski (Hrvatska) - 5.4.8 + 6.1.3 2026-07 Joomla! Hrvatska team (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/hu-HU/joomla.ini b/installation/language/hu-HU/joomla.ini index 30d7cf5a3e709..b769c7814c56a 100644 --- a/installation/language/hu-HU/joomla.ini +++ b/installation/language/hu-HU/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Ennek a Joomla! verziónak a futtatásához a kiszolg BUILD_MIN_PHP_ERROR_URL_TEXT="Segíts ezt megoldani" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Módosítás" INSTL_SELECT_INSTALL_LANG="Telepítési nyelv kiválasztása" INSTL_SELECT_LANGUAGE_TITLE="Válasszon nyelvet" INSTL_SETUP_LOGIN_DATA="Bejelentkezési adatok beállítása" @@ -42,13 +43,9 @@ INSTL_WARNJSON="A PHP-telepítés a JSON engedélyezését igényli a Joomla tel INSTL_DATABASE_SUPPORT="Adatbázis-támogatás:" INSTL_JSON_SUPPORT_AVAILABLE="JSON-támogatás" INSTL_MB_LANGUAGE_IS_DEFAULT="MB nyelv az alapértelmezett" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String túlterhelés ki" INSTL_NOTICE_DATABASE_SUPPORT="Nem találtunk támogatott adatbázisokat." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="A PHP-telepítés a JSON engedélyezését igényli a Joomla telepítéséhez!" INSTL_NOTICE_MBLANG_NOTDEFAULT="A PHP mbstring nyelvet nem semlegesre állították. Ezt a .htaccess fájlba a php_value mbstring.language neutral beírásával helyben is ki tudja kapcsolni." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="A PHP mbstring függvény túlterhelését állították be. Ezt a .htaccess fájlba a php_value mbstring.func_overload 0 beírásával helyben is ki tudja kapcsolni." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="A szükséges parse_ini_file és parse_ini_string php függvények le vannak tiltva a kiszolgálóján." INSTL_NOTICE_XML_SUPPORT="Az XML támogatás nem érhető el. Ezt alapértelmezés szerint engedélyezni kell a php-ban, de előfordulhat, hogy az Ubuntu felhasználóknak ezt telepíteniük kell a sudo apt-get install php-xml paranccsal és a kiszolgáló újraindításával." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="A Zlib tömörítés nincs beállítva. Ezt helyileg kapcsolhatja be, ha beírja a zlib.output_compression = On parancsot a php.ini fájlba." @@ -240,7 +237,7 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="Nincs találat" JGLOBAL_SELECT_SOME_OPTIONS="Válasszon néhány lehetőséget" JHIDEPASSWORD="Jelszó elrejtése" JINVALID_TOKEN="A legutolsó kérés visszautasításra került, mert érvénytelen biztonsági vezérjelet tartalmazott. Frissítse az oldalt, és próbálja meg újra." -JINVALID_TOKEN_NOTICE="Nem egyezik a biztonsági vezérjel. A kérést eldobtuk a lehetséges biztonsági problémák megelőzése érdekében. Kérjük, próbálja meg újra." +JINVALID_TOKEN_NOTICE="Nem egyezik a biztonsági vezérjel. A kérést eldobtuk a lehetséges biztonsági problémák megelőzése érdekében. Kérjük, hogy próbálja meg újra." JNEXT="Következő" JNO="Nem" JNOTICE="Megjegyzés" @@ -263,7 +260,7 @@ JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: az elérési út nem könyvtá JLIB_FORM_FIELD_INVALID="Érvénytelen mező: " JLIB_FORM_VALIDATE_FIELD_INVALID="Érvénytelen mező: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="Kötelező mező: %s" -JLIB_INSTALLER_ABORT="A(z) %s nyelv telepítésének leállítása." +JLIB_INSTALLER_ABORT="A nyelv telepítésének leállítása: %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Bővítmény %1$s: Hiba a következő mappa létrehozásánál: %2$s." JLIB_INSTALLER_ABORT_NOINSTALLPATH="A telepítés elérési útja nem létezik" JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Csomag %1$s: Hiba volt egy bővítmény telepítésekor: %2$s" diff --git a/installation/language/hu-HU/langmetadata.xml b/installation/language/hu-HU/langmetadata.xml index 0d25349e907f7..41ebb231f2b64 100644 --- a/installation/language/hu-HU/langmetadata.xml +++ b/installation/language/hu-HU/langmetadata.xml @@ -1,7 +1,7 @@ Hungarian (Magyar) - 5.4.8 + 6.1.3 2026-07 Joomla! Magyarország (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/id-ID/joomla.ini b/installation/language/id-ID/joomla.ini index 398127804c02c..d2627a9526c3b 100644 --- a/installation/language/id-ID/joomla.ini +++ b/installation/language/id-ID/joomla.ini @@ -27,6 +27,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Host anda memerlukan PHP versi {{phpversion}} atau yan BUILD_MIN_PHP_ERROR_URL_TEXT="Bantu saya menyelesaikan masalah ini" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Ganti Posisi" INSTL_SELECT_INSTALL_LANG="Pilih Bahasa Instalasi" INSTL_SELECT_LANGUAGE_TITLE="Pilih Bahasa" INSTL_SETUP_LOGIN_DATA="Setelan Data Login" @@ -37,12 +38,8 @@ INSTL_WARNJSON="Konfigurasi JSON harus diaktifkan pada pemasangan PHP Anda untuk INSTL_DATABASE_SUPPORT="Dukungan Database:" INSTL_JSON_SUPPORT_AVAILABLE="Dukungan JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="Bahasa MB adalah Bawaan" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Padam" INSTL_NOTICE_DATABASE_SUPPORT="Tidak ada database mendukung yang ditemukan." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Konfigurasi JSON harus diaktifkan pada pemasangan PHP Anda untuk melanjutkan proses pemasangan Joomla!" -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Fungsi PHP mbstring overload telah diaktifkan. Hal ini dapat dimatikan secara lokal dengan memasukkan php_value mbstring.func_overload 0 di berkas .htaccess Anda." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Fungsi php yang diperlukan parse_ini_file dan parse_ini_string dinonaktifkan di server Anda." INSTL_NOTICE_XML_SUPPORT="Dukungan XML tidak tersedia. Ini harus diaktifkan secara default di php tetapi pengguna Ubuntu mungkin perlu menginstal ini dengan melakukan Sudo apt-get install php-xml diikuti dengan restart server web." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Kompresi Zlib tidak disetel. Ini dapat diaktifkan secara lokal dengan memasukkan zlib.output_compression = On di file php.ini Anda." diff --git a/installation/language/id-ID/langmetadata.xml b/installation/language/id-ID/langmetadata.xml index 62625875d2047..53c4853863e1e 100644 --- a/installation/language/id-ID/langmetadata.xml +++ b/installation/language/id-ID/langmetadata.xml @@ -1,7 +1,7 @@ Bahasa Indonesia (id-ID) - 5.4.8 + 6.1.3 2026-07 Joomla! Indonesia (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/it-IT/joomla.ini b/installation/language/it-IT/joomla.ini index ab781c55d5a2c..00c6993bbd9f8 100644 --- a/installation/language/it-IT/joomla.ini +++ b/installation/language/it-IT/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Il tuo host ha bisogno della versione di PHP {{phpvers BUILD_MIN_PHP_ERROR_URL_TEXT="Aiutami a risolvere questo" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Cambia lingua di installazione" +INSTL_CHANGE_INSTALL_LANG_SHORT="Cambia" +INSTL_SELECTED_INSTALL_LANGUAGE="Lingua corrente: %s" INSTL_SELECT_INSTALL_LANG="Seleziona la Lingua di Installazione" INSTL_SELECT_LANGUAGE_TITLE="Seleziona la lingua" INSTL_SETUP_LOGIN_DATA="Configura dati di accesso" @@ -41,14 +44,10 @@ INSTL_WARNJSON="La tua installazione di PHP deve avere JSON abilitato perchè Jo ; Precheck view INSTL_DATABASE_SUPPORT="Supporto Database:" INSTL_JSON_SUPPORT_AVAILABLE="Supporto JSON" -INSTL_MB_LANGUAGE_IS_DEFAULT="MB Lingua Predefinita" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" +INSTL_MB_LANGUAGE_IS_DEFAULT="MB language è predefinito" INSTL_NOTICE_DATABASE_SUPPORT="Nessun database supportato trovato." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="La tua installazione di PHP deve avere JSON abilitato perchè Joomla!® venga installato!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language non è configurato su 'neutral'. Questo può essere configurato in locale inserendo php_value mbstring.language neutral nel file .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="E' attiva la funzione PHP mbstring overload. Questa può essere disattivata in locale inserendo php_value mbstring.func_overload 0 nel file .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Le funzioni php parse_ini_file e parse_ini_string richieste sono disabilitate sul tuo server." INSTL_NOTICE_XML_SUPPORT="Il supporto XML non è disponibile. Dovrebbe venire abilitato di default in php ma gli utenti Ubuntu potrebbero aver bisogno di installarlo eseguendo sudo apt-get install php-xml seguito dal riavvio del server web." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="La compressione Zlib non è impostata. Può essere attivata localmente inserendo zlib.output_compression = On nel tuo file php.ini." @@ -56,12 +55,12 @@ INSTL_PARSE_INI_FILE_AVAILABLE="Supporto INI Parser" INSTL_PRECHECK_ACTUAL="Attuali" INSTL_PRECHECK_DESC="Se qualcuno di questi elementi non è supportato si prega di intervenire per correggerlo.
Non è possibile installare Joomla fino a che la configurazione non soddisfi questi requisiti." INSTL_PRECHECK_DIRECTIVE="Direttiva" -INSTL_PRECHECK_RECOMMENDED="Raccomandato" +INSTL_PRECHECK_RECOMMENDED="Raccomandati" INSTL_PRECHECK_RECOMMENDED_SETTINGS_DESC="Queste impostazioni sono raccomandate per assicurare l'assoluta compatibilità di PHP con Joomla." INSTL_PRECHECK_RECOMMENDED_SETTINGS_TITLE="Impostazioni raccomandate" INSTL_PRECHECK_TITLE="Controlli pre-installazione" INSTL_XML_SUPPORT="Supporto XML" -INSTL_ZLIB_COMPRESSION_SUPPORT="Supporto Zlib Compression" +INSTL_ZLIB_COMPRESSION_SUPPORT="Zlib Compression Support" ; Database view INSTL_DATABASE="Configurazione database" @@ -76,8 +75,8 @@ INSTL_DATABASE_ENCRYPTION_MODE_VALUE_TWO_WAY="Autenticazione a due fattori" INSTL_DATABASE_ENCRYPTION_MSG_CONN_NOT_ENCRYPT="Hai selezionato una connessione al database cifrata ma è stata stabilita una connessione non cifrata. Il motivo potrebbe essere dovuto da una settaggio del database impostato per restituire una connessione non cifrata in caso di errata configurazione dei parametri. Controlla e correggi i parametri di crittografia del database, o cambia l'impostazione da \"Connessione cifrata\" a \"Predefinita\"." INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="Il file inserito nel campo \"%s\" non esiste o non è accessibile." INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_EMPTY="Il campo \"%s\" è vuoto o non contiene un percorso valido." -INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="Hai inserito \"localhost\" come nome host. Una connessione cifrata verso il database potrebbe non andare a buon fine. Cambia \"localhost\" in \"127.0.0.1\" o \"::1\" o usa un nome host differente. Altrimenti, cambia il parametro \"Connessione cifrata\" in \"Predefinita (controllata dal server)\"." -INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="Il server del database non supporta la connessione cifrata. Abilita il supporto TLS (altrimenti chiamato SSL nelle documentazioni) sul server del tuo database, oppure cambia il parametro \"Connessione cifrata\" a \"Predefinita (controllata dal server)\"." +INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="Hai inserito \"localhost\" come nome host. Una connessione cifrata verso il database potrebbe non andare a buon fine. Cambia \"localhost\" in \"127.0.0.1\" o \"::1\" o usa un nome host differente. Altrimenti, cambia il parametro \"Connessione cifrata\" in \"Predefinito (controllato dal server)\"." +INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="Il server del database non supporta la connessione cifrata. Abilita il supporto TLS (altrimenti chiamato SSL nelle documentazioni) sul server del tuo database, oppure cambia il parametro \"Connessione cifrata\" a \"Predefinito (controllato dal server)\"." INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Verifica certificato server " INSTL_DATABASE_ERROR_POSTGRESQL_QUERY="Query del database PostgreSQL fallita." INSTL_DATABASE_HOST_DESC="Immetti il nome dell'host, solitamente \"localhost\" o un nome fornito dal tuo host." @@ -86,7 +85,7 @@ INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE="Per confermare che sei il prop INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE="Stai cercando di utilizzare un host di database che non si trova sul tuo server locale. Per motivi di sicurezza, devi verificare la proprietà del tuo account di web hosting. Leggi la documentazione per ulteriori informazioni." INSTL_DATABASE_HOST_LABEL="Nome Host" INSTL_DATABASE_NAME_DESC="Immetti il nome del database." -INSTL_DATABASE_NAME_LABEL="Nome del database" +INSTL_DATABASE_NAME_LABEL="Nome database" INSTL_DATABASE_NAME_MSG_MYSQL="Il nome del database non è valido. Non deve continuare i seguenti caratteri: \ / ." INSTL_DATABASE_NAME_MSG_POSTGRES="Il nome del database non è valido. Deve iniziare con una lettera, seguita da caratteri alfanumerici." INSTL_DATABASE_NO_SCHEMA="Non esiste nessun schema di database per questo tipo di database." @@ -203,14 +202,14 @@ INSTL_PAGE_TITLE="Installazione di Joomla" ; Configuration model INSTL_ERROR_CONNECT_DB="Impossibile connettersi al database. Il connettore ha restituito il messaggio di errore numero: %d." -INSTL_STD_OFFLINE_MSG="Sito fuori servizio per manutenzione.
Riprovare più tardi." +INSTL_STD_OFFLINE_MSG="Sito fuori servizio per manutenzione.
Riprovare più tardi." ; Languages model INSTL_ERROR_INVALID_URL="URL invalido" ; Others INSTL_CONFPROBLEM="Il file di configurazione o la cartella non è scrivibile, oppure si sono verificati problemi durante la creazione del file configuration.php. Clicca nell'area di testo sottostante per evidenziare tutto il codice e copialo in un nuovo file di testo. Nomina questo file configuration.php e caricalo nella root del tuo sito." -INSTL_DISPLAY_ERRORS="Mostra Errori" +INSTL_DISPLAY_ERRORS="Display Errors" INSTL_ERROR="Errore" INSTL_ERROR_DB="Si sono verificati alcuni errori durante il popolamento del database: %s" INSTL_ERROR_INITIALISE_SCHEMA="Impossibile inizializzare lo schema del database" @@ -225,12 +224,12 @@ INSTL_PHP_VERSION_NEWER="Versione di PHP >= %s" INSTL_PROCESS_BUSY="Processo in esecuzione. Attendere …" INSTL_SESSION_AUTO_START="Auto start sessione" INSTL_WRITABLE="Permessi non sufficienti per creare %s" -INSTL_ZIP_SUPPORT_AVAILABLE="Supporto nativo per ZIP" +INSTL_ZIP_SUPPORT_AVAILABLE="Native ZIP support" ; Global strings JADMINISTRATOR="Amministratore" JCLOSE="Chiudi" -JEMAIL="E-mail" +JEMAIL="Email" JERROR="Errore" JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="si è verificato un errore durante l'esecuzione della richiesta." JGLOBAL_ISFREESOFTWARE="%s è un software libero rilasciato sotto licenza %s." @@ -280,9 +279,9 @@ JLIB_UPDATER_ERROR_OPEN_UPDATE_SITE="Aggiornamento: Non è possibile accedere al JLIB_UTIL_ERROR_CONNECT_DATABASE="JDatabase: :getInstance: Non è stato possibile connettersi al database
joomla.library:%1$s - %2$s." ; Strings for the language debugger -JDEBUG_LANGUAGE_FILES_IN_ERROR="Errori nell'analisi nei file di lingua" +JDEBUG_LANGUAGE_FILES_IN_ERROR="Errori nei file di lingua da analizzare" JDEBUG_LANGUAGE_UNTRANSLATED_STRING="Stringhe non tradotte" -JNONE="Nessuno" +JNONE="Nessuna" ; Necessary for errors ADMIN_EMAIL="Email amministratore" diff --git a/installation/language/it-IT/langmetadata.xml b/installation/language/it-IT/langmetadata.xml index c1a2dafd60e4d..d856ca3dc551c 100644 --- a/installation/language/it-IT/langmetadata.xml +++ b/installation/language/it-IT/langmetadata.xml @@ -1,7 +1,7 @@ Italiano (it-IT) - 5.4.8 + 6.1.3 2026-07 Joomla! Project (Italian Translation Team) (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ja-JP/joomla.ini b/installation/language/ja-JP/joomla.ini index 79a5c92fecbae..22443df9fce33 100644 --- a/installation/language/ja-JP/joomla.ini +++ b/installation/language/ja-JP/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="このバージョンのJoomlaを実行するには、 BUILD_MIN_PHP_ERROR_URL_TEXT="この問題を解決するには" ; Main Config +INSTL_CHANGE_INSTALL_LANG="インストール言語の変更" +INSTL_CHANGE_INSTALL_LANG_SHORT="変更" +INSTL_SELECTED_INSTALL_LANGUAGE="現在の言語: %s" INSTL_SELECT_INSTALL_LANG="インストール言語の選択" INSTL_SELECT_LANGUAGE_TITLE="言語を選択" INSTL_SETUP_LOGIN_DATA="ログインデータの設定" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Joomlaをインストールするには、PHPインストール INSTL_DATABASE_SUPPORT="データベースのサポート:" INSTL_JSON_SUPPORT_AVAILABLE="JSON サポート" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language デフォルト" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String オーバーロード オフ" INSTL_NOTICE_DATABASE_SUPPORT="サポートされているデータベースが見つかりませんでした。" INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Joomlaをインストールするには、PHPインストールでJSONを有効にする必要があります。" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring 言語がニュートラルに設定されていません。.htaccess ファイルに php_value mbstring.language neutralを入力することでローカルで設定できます。" -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring 関数のオーバーロード機能が設定されています。.htaccess ファイルに php_value mbstring.func_overload 0を入力することでローカルでオフにすることができます。" INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="必要なphp関数 parse_ini_file と parse_ini_string サーバーで無効になっています。" INSTL_NOTICE_XML_SUPPORT="XMLサポートは利用できません。これはphpでデフォルトで有効になっているはずですが、Ubuntuユーザーは sudo apt-get install php-xml を実行してからWebサーバーを再起動することでこれをインストールする必要がある場合があります。" INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib圧縮が設定されていません。これはphp.ini ファイルに zlib.output_compression = On と入力することでローカルでオンにできます。" @@ -92,7 +91,7 @@ INSTL_DATABASE_NAME_MSG_POSTGRES="データベース名が無効です。文字 INSTL_DATABASE_NO_SCHEMA="このデータベースタイプのデータベーススキーマは存在しません。" INSTL_DATABASE_PASSWORD_DESC="作成したデータベースパスワード、またはホストから提供されたパスワードを入力します。" INSTL_DATABASE_PREFIX_DESC="テーブルプレフィックスを入力するか、ランダムに生成されたプレフィックスを使用" -INSTL_DATABASE_PREFIX_DUPLICATE_DESC="同じプレフィックスを持つテーブルを持つ既存のデータベースを使用している場合、Joomlaはこれらの既存プレフィックスに\"bak_\"を加えて別名に変更します。" +INSTL_DATABASE_PREFIX_DUPLICATE_DESC="同じプレフィックスを持つテーブルを持つ既存のデータベースを使用している場合、Joomlaは接頭辞 「bak_」を追加することで、既存のテーブルの名前を変更します。" INSTL_DATABASE_PREFIX_MSG="テーブル接頭辞は文字で始まり、任意で英数字も使えますが、最後はアンダースコアで終わらなければなりません。" INSTL_DATABASE_RESPONSE_ERROR="インストールプロセスが失敗しました。" INSTL_DATABASE_TYPE_DESC="データベースタイプを選択" diff --git a/installation/language/ja-JP/langmetadata.xml b/installation/language/ja-JP/langmetadata.xml index c6c0e82b6d75d..076e33bca8370 100644 --- a/installation/language/ja-JP/langmetadata.xml +++ b/installation/language/ja-JP/langmetadata.xml @@ -1,7 +1,7 @@ Japanese (Japan) - 5.4.8 + 6.1.3 2026-07 Joomla!じゃぱん (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ka-GE/joomla.ini b/installation/language/ka-GE/joomla.ini index 7698e572b2d23..083a29c636754 100644 --- a/installation/language/ka-GE/joomla.ini +++ b/installation/language/ka-GE/joomla.ini @@ -15,7 +15,7 @@ BUILD_FATAL_URL_TEXT="დამეხმარეთ პრობლემის BUILD_INCOMPLETE_HEADER="გარემოს კონფიგურირება არ არის დასულებული" BUILD_INCOMPLETE_LANGUAGE="ქართული GE" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_INCOMPLETE_TEXT="როგორც ჩანს, თქვენ ცდილობთ Joomla! დაყენებას ჩვენი Git-რეპოზიტორიდან. ამისათვის საჭიროა ჯერ შეასრულოთ რამოდენიმე დამატებითი ნაბიჯი." -BUILD_INCOMPLETE_URL_TEXT="ვრცლად" +BUILD_INCOMPLETE_URL_TEXT="დეტალურად" ; No XML PHP error page ; These will be processed by the JavaScript Build @@ -32,8 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Joomla! ამ ვერსიის დასაყ BUILD_MIN_PHP_ERROR_URL_TEXT="დამეხმარეთ პრობლემის მოგვარებაში" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="პოზიციის შეცვლა" INSTL_SELECT_INSTALL_LANG="აირჩიეთ დაყენების ენა" -INSTL_SELECT_LANGUAGE_TITLE="აირჩიეთ ენა" +INSTL_SELECT_LANGUAGE_TITLE="ენის არჩევა" INSTL_SETUP_LOGIN_DATA="შესვლის პარამეტრები" INSTL_WARNJAVASCRIPT="ყურადღება! Joomla! სწორად ინსტალაციისთვის ბრაუზერში ჩართული უნდა იყოს JavaScript!" INSTL_WARNJSON="Joomla! ინსტალაციისთვის PHP-ში ჩართული უნდა იყოს JSON!" @@ -41,14 +42,10 @@ INSTL_WARNJSON="Joomla! ინსტალაციისთვის PHP-ში ; Precheck view INSTL_DATABASE_SUPPORT="მონაცემთა ბაზის მხარდაჭერა:" INSTL_JSON_SUPPORT_AVAILABLE="JSON მხარდაჭერა" -INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language არის ავტომატური" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload გამორთულია" +INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language ავტომატური" INSTL_NOTICE_DATABASE_SUPPORT="მხარდაჭერილი მონაცემთა ბაზები ვერ მოიძებნა." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Joomla! ინსტალაციისთვის PHP-ში ჩართული უნდა იყოს JSON!" -INSTL_NOTICE_MBLANG_NOTDEFAULT="ენა PHP mbstring არ არის დაყენებული neutral. ეს შეგიძლიათ შეცვალოთ ლოკალურად, php_value mbstring.language neutral სტრიქონის დამატებით თქვენს .htaccess ფაილში." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring ფუნქციის გადატვირთვა ჩართულია. ეს შეგიძლიათ გამორთოთ ლოკალურად, php_value mbstring.func_overload 0 სტრიქონის დამატებით თქვენს .htaccess ფაილში." +INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring ენა არ არის neutral. თქვენ შეგიძლიათ შეცვალოთ მნიშვნელობა ლოკალურად, თუ დაამატებთ სტრიქონს php_value mbstring.language neutral თქვენს .htaccess ფაილში." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="საჭირო php ფუნქციები parse_ini_file და parse_ini_string გამორთულია თქვენს სერვერზე." INSTL_NOTICE_XML_SUPPORT="XML მხარდაჭერა არ არის ხელმისაწვდომი. ეს ავტომატურად უნდა იყოს ჩართული php-ში, თუმცა Ubuntu მომხმარებლებს შეიძლება დასჭირდეთ მისი დაყენება sudo apt-get install php-xml ბრძანების შესრულებით, რის შემდეგაც უნდა გადაიტვირთოს ვებ-სერვერი." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib შეკუმშვა არ არის დაყენებული. ეს შეგიძლიათ ჩართოთ ლოკალურად, zlib.output_compression = On სტრიქონის დამატებით თქვენს php.ini ფაილში." @@ -61,23 +58,23 @@ INSTL_PRECHECK_RECOMMENDED_SETTINGS_DESC="ეს პარამეტრებ INSTL_PRECHECK_RECOMMENDED_SETTINGS_TITLE="რეკომენდებული პარამეტრები:" INSTL_PRECHECK_TITLE="წინა-საინსტალაციო შემოწმება" INSTL_XML_SUPPORT="XML მხარდაჭერა" -INSTL_ZLIB_COMPRESSION_SUPPORT="Zlib შეკუმშვის მხარდაჭერა" +INSTL_ZLIB_COMPRESSION_SUPPORT="Zlib Compression მხადაჭერა" ; Database view INSTL_DATABASE="მონაცემთა ბაზის კონფიგურაცია" INSTL_DATABASE_ENCRYPTION_CA_LABEL="CA ფაილის გზა" INSTL_DATABASE_ENCRYPTION_CERT_LABEL="სერთიფიკატის ფაილის გზა" -INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="მხარდაჭერილი შიფრების კრებული (არასავალდებულო)" +INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="მხარდაჭერილი შიფრების ნაკრები (ნებაყოფლობითი)" INSTL_DATABASE_ENCRYPTION_KEY_LABEL="პრივატული გასაღების ფაილის გზა" -INSTL_DATABASE_ENCRYPTION_MODE_LABEL="შეერთების დაშიფრვა" -INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="ავტომატური (კონტროლდება სერვერით)" +INSTL_DATABASE_ENCRYPTION_MODE_LABEL="მიერთების დაშიფრვა" +INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="ავტორი (კონტროლდება სერვერით)" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_ONE_WAY="ერთმხრივი ავთენტიფიკაცია" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_TWO_WAY="ორმხრივი ავთენტიფიკაცია" INSTL_DATABASE_ENCRYPTION_MSG_CONN_NOT_ENCRYPT="თქვენ აირჩიეთ მონაცემთა ბაზასთან მიერთება დაშიფრვით, რომელიც შეიძლება დამყარდეს, მაგრამ არ იქნება დაშიფრული. მიზეზი შეიძლება იყოს იმაში, რომ სერვერი კონფიგურირებულია არადაშიფრულ შეერთებასთან დაბრუნებაზე, არასწორი დაშიფრვის პარამეტრების შემთხვევაში. საჭიროა შემოწნდეს და გასწორდეს შეერთების დაშიფრვის პარამეტრები, ან შეიცვალოს ველის მნიშვნელობა \"შეერთების დაშიფრვა\" მნიშვნელობით \"ავტომატური (კონტროლდება სერვერით)\"." -INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="ფაილი, რომელიც შეყვანილი ველში \"%s\" არ არსებობს ან არ არის წვდომადი." -INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_EMPTY="ველი \"%s\" არ არის შევსებული ან არ შეიცავს სწორ გზას." -INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="თქვენ შეიყვანეთ \"localhost\" როგორც ჰოსტის სახელი. ასეთ შემთხვევაში მიერთება მონაცემთა ბაზასთან შეერთების დაშიფრვით შეიძლება დასრულდეს შეცდომით. საჭირო შეიცვალოს ჰოსტის სახელი \"localhost\" მნიშვნელობით \"127.0.0.1\" ან \"::1\" ან სხვა სახელით, ან შეიცვალოს ველს მნიშვნელობა \"შეერთების დაშიფრვა\" მნიშვნელობით \"ავტომატური (კონტროლდება სერვერით)\"." -INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="მონაცემთა ბაზის სერვერს არა აქვს შეერთების დაშიფრვის მხარდაჭერა. საჭიროა ჩაირთოს TLS (ხშირად ეძახიან SSL დოკუმენტაციაში) მხარდაჭერა თქვენს მონაცემთა ბაზის სერვერზე, ან ან შეიცვალოს ველს მნიშვნელობა \"შეერთების დაშიფრვა\" მნიშვნელობით \"ავტომატური (კონტროლდება სერვერით)\"." +INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="ფაილი, რომელიც შეყვანილია ველში \"%s\" არ არსებობს ან არ არის წვდომადი." +INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_EMPTY="ველი \"%s\" არ არის შევსებული ან ფაილის გზა არასწორია." +INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="თქვენ შეიყვანეთ \"localhost\" როგორც ჰოსტის სახელი. ასეთ შემთხვევაში მონაცემთა ბაზასთან შეერთება მიერთების დაშიფრვით შეიძლება დასრულდეს შეცდომით. საჭიროა შეიცვალოს ჰოსტის სახელი \"localhost\" მნიშვნელობით \"127.0.0.1\" ან \"::1\" ან სხვა ჰოსტის სახელით, ან შეიცვალოს ველის მნიშვნელობა \"შეერთების დაშიფრვა\" მნიშვნელობით \"ავტომატური (კონტროლდება სერვერით)\"." +INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="მონაცემთა ბაზის სერვერს არა აქვს შეერთების დაშიფრვის მხარდაჭერა. საჭიროა სერვერზე ჩაირთოს TLS (ხშირად უწოდებენ SSL დოკუმენტაციაში) მხარდაჭერა, ან შეიცვალოს ველის მნიშვნელობა \"შეერთების დაშიფრვა\" მნიშვნელობით \"ავტომატური (კონტროლდება სერვერით)\"." INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="სერვერის სერთიფიკატის შემოწმება" INSTL_DATABASE_ERROR_POSTGRESQL_QUERY="PostgreSQL მონაცემთა ბაზაზე მოთხოვნა ვერ მოხერხდა." INSTL_DATABASE_HOST_DESC="შეიყვანეთ ჰოსტის სახელი, როგორც წესი \"localhost\" ან ჰოსტის მიერ მოწოდებული სახელი." @@ -145,7 +142,6 @@ INSTL_LANGUAGES_WARNING_NO_INTERNET="Joomla! ენის პაკეტებ INSTL_LANGUAGES_WARNING_NO_INTERNET2="შენიშვნა: თქვენ შეძლებთ დააყენოთ სასურველი ენების პაკეტები მოგვიანებით, Joomla! მართვის პანელიდან." ; Automated Updates Opt Out -INSTL_AUTOMATED_UPDATES="ავტომატური განახლებები" INSTL_AUTOMATED_UPDATES_DESC="Joomla! ავტომატურად განაახლებს თავის მცირე და პატჩის გამოცემებს.

გთხოვთ მიაქციოთ ყურადღება: ავტომატური განახლებები დაარეგისტრირებს თქვენს საიტს Joomla! მიერ მოწოდებულ შესაბამის სერვისზე. რეგისტრაცია საშუალებას აძლევს Joomla! პროექტს თქვენი საიტისა და სერვერის გარემოს შესახებ ინფორმაცაზე წვდომის, კონკრეტულად საიტის Url, PHP ვერსია, მონაცემთა ბაზის ტიპი და ვერსია, CMS ვერსია და სერვერის OS ტიპი და ვერსია. ეს ინფორმაცია გამოიყენება მხოლოდ მომსახურების გასაუმჯობესებლად.

გარდა ამისა, თქვენ შეგიძლიათ გამორთოთ ავტომატური განახლებები ქვემოთ მოცემული ღილაკის გამოყენებით." INSTL_AUTOMATED_UPDATES_DISABLE="გამორთეთ ავტომატური განახლებები" INSTL_COMPLETE_ERROR_AUTOMATED_UPDATES_DISABLE="ავტომატური განახლებების გამორთვა შეუძლებელია." @@ -157,7 +153,7 @@ INSTL_DEFAULTLANGUAGE_ADMIN_COULDNT_SET_DEFAULT="ავტომატური INSTL_DEFAULTLANGUAGE_ADMIN_SET_DEFAULT="ენა %s მოინიშნა Joomla!-ს მართვის პანელის ავტომატურ ენად." INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_LANGUAGE="ენა" INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_SELECT="არჩევა" -INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_TAG="ტეგი" +INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_TAG="თაგი" INSTL_DEFAULTLANGUAGE_COULD_NOT_DOWNLOAD_PACKAGE="Joomla! ენის პაკეტის ჩამოტვირთვა ან გაშლა ვერ მოხერხდა მისამართიდან: %s" INSTL_DEFAULTLANGUAGE_COULD_NOT_INSTALL_LANGUAGE="Joomla! ენის პაკეტის %s დაყენება ვერ მოხერხდა." INSTL_DEFAULTLANGUAGE_DESC="Joomla! ენის პაკეტები დაყენებულია. გთხოვთ აირჩიოთ ავტომატური ენის პაკეტი მართვის პანელისთვის და დააჭირეთ ღილაკს \"დააყენე ავტომატურად\"." @@ -203,10 +199,10 @@ INSTL_PAGE_TITLE="Joomla! ვებ ინსტალატორი" ; Configuration model INSTL_ERROR_CONNECT_DB="მონაცემთა ბაზასთან დაკავშირება ვერ მოხერხდა. დამაკავშირებელმა დააბრუნა ნომერი: %d." -INSTL_STD_OFFLINE_MSG="საიტი დროებით დახურულია ტექნიკური მიზეზების გამო.
გთხოვთ შემოხვიდეთ მოგვიანებით." +INSTL_STD_OFFLINE_MSG="საიტი გამორთულია ტექნიკური სამუშაოების გამო.
გთხოვთ სცადოთ მოგვიანებით." ; Languages model -INSTL_ERROR_INVALID_URL="Invalid URL" +INSTL_ERROR_INVALID_URL="არასწორი URL" ; Others INSTL_CONFPROBLEM="თქვენი კონფიგურაციის ფაილი ან საქაღალდე არ არის ჩაწერადი ან კონფიგურაციის ფაილის შექმნისას წარმოიშვა შეცდომა. საჭიროა ხელით შექმნათ ტექსტური ფაილი, დაარქვათ სახელი 'configuration.php', გამოყოთ/დააკოპიროთ გამოსახული კოდი და ჩასვათ მასში, და ამმის შემდეგ მოათავსოთ კონფიგურაციის ფაილი საიტის ძირეულ საქაღალდეში." @@ -219,31 +215,31 @@ INSTL_FILE_UPLOADS="ფაილების ატვირთვა" INSTL_GNU_GPL_LICENSE="GNU საერთო სახალხო ლიცენზია" INSTL_HELP_LINK="Joomla! დაყენებაზე დახმარება" INSTL_NOTICE_NEEDSTOBEWRITABLE="თქვენ მაინც შეგიძლიათ გააგრძელოთ Joomla! დაყენება, თუ აღადგენთ ნებართვას." -INSTL_OUTPUT_BUFFERING="გამოყვანის ბუფერიზაცია" +INSTL_OUTPUT_BUFFERING="შედეგების ბუფერიზაცია" INSTL_PHP_VERSION="PHP ვერსია" INSTL_PHP_VERSION_NEWER="PHP ვერსია >= %s" INSTL_PROCESS_BUSY="მიმდინარეობს დაყენების პროცესი. გთხოვთ მოიცადოთ …" -INSTL_SESSION_AUTO_START="Session Auto Start" +INSTL_SESSION_AUTO_START="სესიის ავტომატური გაშვება" INSTL_WRITABLE="%s ფაილის შესაქმნელად არ გვაქვს საკმარისი უფლება." INSTL_ZIP_SUPPORT_AVAILABLE="Native ZIP მხარდაჭერა" ; Global strings -JADMINISTRATOR="მართვის პანელი" +JADMINISTRATOR="ადმინისტრატორი" JCLOSE="დახურვა" JEMAIL="ელ-ფოსტა" JERROR="შეცდომა" JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="თქვენი მოთხოვნის დამუშავებისას მოხდა შეცდომა." JGLOBAL_ISFREESOFTWARE="%s არის თავისუფალი პროგრამული უზრუნველყოფა, რომელიც ვრცელდება ლიცენზიით %s." JGLOBAL_LANGUAGE_VERSION_NOT_PLATFORM="ენის პაკეტი არ შეესაბამება Joomla! ამ ვერსიას. ზოგიერთი ენის კონსტანტა შეიძლება იყოს გამოტოვებული და ნაჩვენები იქნება ინგლისურად." -JGLOBAL_SELECT_AN_OPTION="აირჩიეთ მნიშვნელობა" -JGLOBAL_SELECT_NO_RESULTS_MATCH="შედეგები არ დაემთხვა" -JGLOBAL_SELECT_SOME_OPTIONS="აირჩიეთ რამოდენიმე მნიშვნელობა" -JHIDEPASSWORD="პარილის დამალვა" +JGLOBAL_SELECT_AN_OPTION="აირჩიეთ პარამეტრი" +JGLOBAL_SELECT_NO_RESULTS_MATCH="შედეგები არ ემთხვევა" +JGLOBAL_SELECT_SOME_OPTIONS="აირჩიეთ რამოდენიმე პარამეტრი" +JHIDEPASSWORD="პაროლის დამალვა" JINVALID_TOKEN="უკანასკნელი მოთხოვნა უარყოფილი იქნა, რადგან შეიცავდა არასწორ უსაფრთხოების ტოკენს. გთხოვთ განაახლოთ გვერდი და სცადოთ კიდევ ერთხელ." -JINVALID_TOKEN_NOTICE="უსაფრთხოების ტოკენმა ვერ გაიარა შემოწმება. მოთხოვნა გაუქმდა უსაფრთხოების დარღვევის თავიდან ასაცილებლად. გთხოვთ სცადოთ ხელახლა." +JINVALID_TOKEN_NOTICE="უსაფრთხოების ტოკენი არ ემთხვევა. მოთხოვნა გაუქმდა უსაფრთხოების დარღვევის თავიდან ასაცილებლად. გთხოვთ, სცადოთ თავიდან." JNEXT="შემდეგი" JNO="არა" -JNOTICE="ყურადღება" +JNOTICE="შეტყობინება" JOFF="გამორთული" JON="ჩართული" JPREVIOUS="წინა" @@ -254,40 +250,40 @@ JUSERNAME="მომხმარებლის სახელი" JYES="კი" ; Framework strings necessary when no lang pack is available -JLIB_DATABASE_ERROR_CONNECT_MYSQL="MySQL-თან დაკავშირება ვერ მოხერხდა." +JLIB_DATABASE_ERROR_CONNECT_MYSQL="ვერ ვუკავშირდები MySQL-ს." JLIB_DATABASE_ERROR_DATABASE="მოხდა მონაცემთა ბაზის შეცდომა" -JLIB_DATABASE_ERROR_LOAD_DATABASE_DRIVER="ვერ მოხერხდა მონაცემთა ბაზის დრაივერის ჩატვირთვა: %s" +JLIB_DATABASE_ERROR_LOAD_DATABASE_DRIVER="მონაცემთა ბაზის დრაივერის ჩატვირთვა ვერ მოხერხდა: %s." JLIB_DATABASE_ERROR_VALID_MAIL="თქვენს მიერ შეყვანილი ელ-ფოსტის მისამართი არასწორია. გთხოვთ შეიყვანოთ სხვა ელ-ფოსტის მისამართი." JLIB_ENVIRONMENT_SESSION_EXPIRED="თქვენი სესიისთვის განკუთვნილი დრო ამოიწურა, გთხოვთ განაახლოთ გვერდი." -JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: გზა არ წარმოადგენს საქაღალდეს. გზა: %2$s" +JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: გზა არ არის საქაღალდე. გზა: %2$s" JLIB_FORM_FIELD_INVALID="ველი არასწორად არის შევსებული: " -JLIB_FORM_VALIDATE_FIELD_INVALID="ველი არასწორად არის შევსებული: %s" -JLIB_FORM_VALIDATE_FIELD_REQUIRED="აუცილებელია შეივსოს ველი: %s" +JLIB_FORM_VALIDATE_FIELD_INVALID="არასწორად შევსებული ველი: %s" +JLIB_FORM_VALIDATE_FIELD_REQUIRED="აუცილებელი ველი: %s" JLIB_INSTALLER_ABORT="ენის ინსტალაციის შეჩერება: %s" -JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="გაფართოება %1$s: ვერ მოხერხდა საქაღალეს შექმნა: %2$s" -JLIB_INSTALLER_ABORT_NOINSTALLPATH="ინსტალაციის მისამართი არ არსებობს." +JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="გაფართოება %1$s: შცდომა საქაღალდის შექმნისას: %2$s" +JLIB_INSTALLER_ABORT_NOINSTALLPATH="ინსტალაციის გზა არ არსებობს." JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="პაკეტი %1$s: გაფართოების ინსტალაციისას მოხდა შეცდომა: %2$s." -JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="პაკეტი %s: ინსტალაციისთვის არ გვაქვს ფაილები!" +JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="პაკეტი %s: არ იყო დასაინსტალირებელი ფაილები!" JLIB_INSTALLER_ERROR_DOWNLOAD_SERVER_CONNECT="სერვერთან დაკავშირების შეცდომა: %s" JLIB_INSTALLER_ERROR_FAIL_COPY_FILE="JInstaller: :Install: ფაილის %1$s ასლის შექმნის დროს წარმოიშვა შეცდომა %2$s-ში." JLIB_INSTALLER_INSTALL="ინსტალაცია" JLIB_INSTALLER_NOT_ERROR="ენის ფაილების TinyMCE დაყენების დროს მომხდარი შეცდომები არანაირად არ აისახება ენის პაკეტის ინსტალაციაზე. ენის ზოგიერთი პაკეტი, რომელიც შექმნილია Joomla! 3.2.0-ზე ქვედა ვერსიებისთვის, შესაძლოა შეეცადოს დააყენოს TinyMCE ენის ფაილები. თუმცა, TinyMCE ენის ფაილები უკვე გათვალისწინებულია და შედის ძირითად ბირთვში, ამიტომ მისი დამატებით დაყენება საჭირო არ არის." JLIB_INSTALLER_WARNING_UNABLE_TO_INSTALL_CONTENT_LANGUAGE="ვერ მოხერხდა კონტენტის ენის შექმნა ენისთვის %s: %s." -JLIB_UPDATER_ERROR_COLLECTION_FOPEN="PHP allow_url_fopen პარამეტრი გამორთულია. განახლების მუშაობისთვის ეს პარამეტრი უნდა იყოს ჩართული." -JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL="Update: :Collection: ვერ მოხერხდა გახსნა %s" +JLIB_UPDATER_ERROR_COLLECTION_FOPEN="PHP კოფიგურაციაში პარამეტრი allow_url_fopen გამორთულია. განახლების ფუნქციის გამოსაყენებლად ეს პარამეტრი უნდა იყოს ჩართული." +JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL="Update: :Collection: ვერ ვხსნი %s-ს" JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL="Update: :Collection: ვერ მოხერხდა დამუშავება %s" JLIB_UPDATER_ERROR_OPEN_UPDATE_SITE="Update: ვერ მოხერხდა განახლების სერვერის გახსნა #%d "%s", URL: %s." JLIB_UTIL_ERROR_CONNECT_DATABASE="JDatabase: :getInstance: ვერ მოხერხდა მონაცემთა ბაზასთან მიერთება
joomla.library: %1$s - %2$s." ; Strings for the language debugger -JDEBUG_LANGUAGE_FILES_IN_ERROR="შეცდომები ენის ფაილებში" +JDEBUG_LANGUAGE_FILES_IN_ERROR="გარჩევის შეცდომები ენის ფაილებში" JDEBUG_LANGUAGE_UNTRANSLATED_STRING="სათარგმნი სტრიქონები" JNONE="არცერთი" ; Necessary for errors ADMIN_EMAIL="ადმინისტრატორის ელ-ფოსტა" ADMIN_PASSWORD="ადმინისტრატორის პაროლი" -SITE_NAME="საიტის დასახელება" +SITE_NAME="საიტის სახელი" ; Database types (allows for a more descriptive label than the internal name) MYSQL="MySQL (PDO)" @@ -300,25 +296,25 @@ SQLITE="SQLite" ; Javascript message titles ERROR="შეცდომა" MESSAGE="შეტყობინება" -NOTICE="ყურადღება" +NOTICE="შეტყობინება" WARNING="გაფრთხილება" ; Javascript ajax error messages JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="JSON მონაცემების მიღებისას მოხდა კავშირის შეცდომა." -JLIB_JS_AJAX_ERROR_NO_CONTENT="კონტენტი არ დაბრუნებულა." +JLIB_JS_AJAX_ERROR_NO_CONTENT="კონტენტი ვერ დაბრუნდა." JLIB_JS_AJAX_ERROR_OTHER="შეხდომა მოხდა JSON მონაცემების მიღებისას: HTTP %d სტატუსის კოდი." -JLIB_JS_AJAX_ERROR_PARSE="შეცდომა მოხდა სინტაქსური ანალიზისას შემდეგი JSON მონაცემების დამუშავების დროს:
%s" -JLIB_JS_AJAX_ERROR_TIMEOUT="JSON მონაცემების მიღებისას მოხდა ლოდინის დროის გადაჭარბება (timeout)." +JLIB_JS_AJAX_ERROR_PARSE="სინტაქსური ანალიზისას (parse) მოხდა შეცდომა, შემდეგი JSON მონაცემების დამუშავების დროს:
%s" +JLIB_JS_AJAX_ERROR_TIMEOUT="JSON მონაცემების მიღებისას მოხდა შეყოვნება (timeout)." ; Field password messages JFIELD_PASSWORD_INDICATE_COMPLETE="პაროლი მიღებულია" JFIELD_PASSWORD_INDICATE_INCOMPLETE="პაროლი არ შეესაბამება საიტის მოთხოვნებს." -JFIELD_PASSWORD_SPACES_IN_PASSWORD="პაროლი არ უნდა შეიცავდეს პრობელებს სტრიქონის დასაწყისში ან ბოლოში." -JFIELD_PASSWORD_TOO_LONG="პაროლი საკმაოდ გრძელია. პაროლის სიგრძე უნდა იყოს 100 სიმბოლოზე ნაკლები." +JFIELD_PASSWORD_SPACES_IN_PASSWORD="პაროლი არ უნდა შეიცავდეს პრობელს სტრიქონის დასაწყისში ან ბოლოში." +JFIELD_PASSWORD_TOO_LONG="პაროლი ძალინ გრძელია. ის უნდა შეიცავდეს არაუმეტეს 100 სიმბოლოსა." JFIELD_PASSWORD_TOO_SHORT_N="პაროლი საკმაოდ მოკლეა. პაროლის სიგრძე უნდა იყოს არანაკლები %d სიმბოლოსი." ; Javascript Form Validation Messages -JLIB_FORM_CONTAINS_INVALID_FIELDS="ფორმა ვერ გაიგზავნება, რადგან ერთი ან რამოდენიმე ველი არ არის შევსებული სწორად.
გთხოვთ გაასწოროთ მონიშნული ველები და სცადეთ ხელახლა." +JLIB_FORM_CONTAINS_INVALID_FIELDS="ფორმის გაგზავნა ვერ ხერხდება, ერთი ან რამოდენიმე ველი არ არის სწორად შევსებული.
გთხოვთ გაასწოროთ მონიშნული ველები და სცადეთ ხელახლა." JLIB_FORM_FIELD_INVALID_VALUE="გთხოვთ შეიყვანოთ სწორი მნიშვნელობა." JLIB_FORM_FIELD_REQUIRED_CHECK="გთხოვთ აირჩიოთ მნიშვნელობა." JLIB_FORM_FIELD_REQUIRED_VALUE="გთხოვთ შეავსოთ ველი." diff --git a/installation/language/ka-GE/langmetadata.xml b/installation/language/ka-GE/langmetadata.xml index d8a5116ee6728..2699e37e0ec48 100644 --- a/installation/language/ka-GE/langmetadata.xml +++ b/installation/language/ka-GE/langmetadata.xml @@ -1,7 +1,7 @@ Georgian (Georgia) - 5.4.8 + 6.1.3 2026-07 Georgian Translation Team (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/kk-KZ/joomla.ini b/installation/language/kk-KZ/joomla.ini index 58a19859f6867..72fba50b42464 100644 --- a/installation/language/kk-KZ/joomla.ini +++ b/installation/language/kk-KZ/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Хостыңыз PHP {{phpversion}} немесе од BUILD_MIN_PHP_ERROR_URL_TEXT="Бұл мәселені шешуге көмектес" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Өзгерту" INSTL_SELECT_INSTALL_LANG="Орнату тілін таңдау" INSTL_SELECT_LANGUAGE_TITLE="Тілді таңдаңыз" INSTL_SETUP_LOGIN_DATA="Логин туралы мәліметтер орнату" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Joomla-ді орнату үшін сіздің PHP орнаты INSTL_DATABASE_SUPPORT="Деректер базасын қолдау:" INSTL_JSON_SUPPORT_AVAILABLE="JSON қолдауы" INSTL_MB_LANGUAGE_IS_DEFAULT="МБ тілі әдепкі" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="МБ жолды шамадан тыс жүктеу өшірулі" INSTL_NOTICE_DATABASE_SUPPORT="Дерекқор табылмады." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Joomla-ді орнату үшін сіздің PHP орнатылымыңыз JSON функциясын қажет етеді!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring тілі бейтарап күйге орнатылмаған. Мұны .htaccess файлыңызға php_value mbstring.language бейтарап енгізу арқылы жергілікті түрде орнатуға болады." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring функциясының шамадан тыс жүктелуі орнатылды. Мұны .htaccess файлыңызға php_value mbstring.func_overload 0 енгізу арқылы жергілікті түрде өшіруге болады." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Қажетті PHP функциялары parse_ini_file және parse_ini_string серверде өшірілген." INSTL_NOTICE_XML_SUPPORT="XML қолдауы қол жетімді емес. Мұны php-де әдепкі бойынша қосу керек, бірақ Ubuntu пайдаланушыларына оны орнату қажет болуы мүмкін sudo apt-get install php-xml, содан кейін веб-сервер қайта іске қосылады." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib қысу орнатылмаған. Мұны php.ini файлыңызға zlib.output_compression = On енгізу арқылы жергілікті түрде қосуға болады." @@ -263,7 +260,7 @@ JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION=" %1$s пакеті: кеңе JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="%s бумасы: Орнатылатын файлдар жоқ!" JLIB_INSTALLER_ERROR_DOWNLOAD_SERVER_CONNECT="Серверге қосылу қатесі: %s" JLIB_INSTALLER_ERROR_FAIL_COPY_FILE=" JInstaller:: Install: %1$s файлын %2$s ішіне көшіру мүмкін емес." -JLIB_INSTALLER_INSTALL="Орнату" +JLIB_INSTALLER_INSTALL="Орнатуы" JLIB_INSTALLER_NOT_ERROR="Егер қате TinyMCE тіл файлдарын орнатумен байланысты болса, ол тілді(тілдерді) орнатуға әсер етпейді. Кейбір тіл бумалары дейін құрылған Joomla! 3.2.0 жеке TinyMCE тіл файлдарын орнатуға тырысуы мүмкін. Олар енді ядроға енгізілгендіктен, оларды орнату қажет емес." JLIB_INSTALLER_WARNING_UNABLE_TO_INSTALL_CONTENT_LANGUAGE="%s тілі үшін мазмұн тілін жасау мүмкін емес: %s." JLIB_UPDATER_ERROR_COLLECTION_FOPEN="PHP allow_url_fopen параметрі өшірілген. Жаңартқыш жұмыс істеуі үшін бұл параметрді қосу керек." diff --git a/installation/language/kk-KZ/langmetadata.xml b/installation/language/kk-KZ/langmetadata.xml index 36c1cd87025a5..a1e454c59cb9c 100644 --- a/installation/language/kk-KZ/langmetadata.xml +++ b/installation/language/kk-KZ/langmetadata.xml @@ -1,7 +1,7 @@ Kazakh (Kazakhstan) - 5.4.8 + 6.1.3 2026-07 Sarvarov Akylkerey (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ko-KR/joomla.cli.ini b/installation/language/ko-KR/joomla.cli.ini index 0bcc1164ee31a..b2c66ab8355a7 100644 --- a/installation/language/ko-KR/joomla.cli.ini +++ b/installation/language/ko-KR/joomla.cli.ini @@ -1,4 +1,5 @@ INSTL_ADMIN_EMAIL_DESC="웹사이트 최고 관리자의 이메일 주소를 입력합니다" +INSTL_ADMIN_EMAIL_DESC_SHORT="웹사이트의 최고 관리자 계정 이메일 주소" INSTL_ADMIN_PASSWORD_DESC="최고 관리자 계정의 비밀번호를 설정합니다" INSTL_ADMIN_PASSWORD_DESC_SHORT="최고 관리자 계정의 비밀번호" INSTL_ADMIN_USERNAME_DESC="슈퍼 유저 계정의 사용자 아이디를 설정하세요" @@ -8,9 +9,16 @@ INSTL_ADMIN_USER_DESC_SHORT="최고 관리자 계정의 실명" INSTL_DATABASE_COULD_NOT_CONNECT="%s" INSTL_DATABASE_ENCRYPTION_CA_LABEL="암호화 검증용 CA 파일 경로" INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="암호화 검증용 CA 파일 경로" -INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="데이터베이스 연결을 위한 SSL 인증서 경로. 암호화를 2로 설정해야 함" +INSTL_DATABASE_ENCRYPTION_CERT_LABEL="데이터베이스 연결용 SSL 인증서 경로. 암호화를 2로 설정해야 함" +INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="데이터베이스 연결용 SSL 인증서 경로. 암호화를 2로 설정해야 함" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="지원되는 암호 스위트(선택 사항)" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="지원되는 암호 스위트(선택 사항)" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL="데이터베이스 연결용 SSL 키. 암호화를 2으로 설정해야 함" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="데이터베이스 연결용 SSL 키. 암호화를 2으로 설정해야 함" +INSTL_DATABASE_ENCRYPTION_MODE_LABEL="데이터베이스 연결 암호화. 값: 0=없음, 1=단방향, 2=양방향" +INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="데이터베이스 연결 암호화. 값: 0=없음, 1=단방향, 2=양방향" +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="데이터베이스 연결 시 SSL 인증서 확인. 값: 0=아니오, 1=예. 암호화가 1 또는 2로 설정되어야 함" +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="데이터베이스 연결 시 SSL 인증서 확인. 값: 0=아니오, 1=예. 암호화가 1 또는 2로 설정되어야 함" INSTL_DATABASE_HOST_DESC="데이터베이스 호스트" INSTL_DATABASE_HOST_DESC_SHORT="데이터베이스 호스트" INSTL_DATABASE_NAME_DESC="데이터베이스 이름" @@ -19,6 +27,8 @@ INSTL_DATABASE_PASSWORD_DESC="데이터베이스 비밀번호" INSTL_DATABASE_PASSWORD_DESC_SHORT="데이터베이스 비밀번호" INSTL_DATABASE_PREFIX_DESC="데이터베이스 테이블 접두사" INSTL_DATABASE_PREFIX_DESC_SHORT="데이터베이스 테이블 접두사" +INSTL_DATABASE_TYPE_DESC="데이터베이스 유형. 지원됨: mysql, mysqli, pgsql" +INSTL_DATABASE_TYPE_DESC_SHORT="데이터베이스 유형. Joomla에서 지원되는 데이터베이스: mysql (=MySQL (PDO)), mysqli (=MySQLi), pgsql (=PostgreSQL (PDO))" INSTL_DATABASE_USER_DESC="데이터베이스 사용자이름" INSTL_DATABASE_USER_DESC_SHORT="데이터베이스 사용자이름" INSTL_PUBLIC_FOLDER_DESC="공용 폴더의 상대 또는 절대 경로" diff --git a/installation/language/ko-KR/joomla.ini b/installation/language/ko-KR/joomla.ini index fadfe59d13502..7ecba579a3461 100644 --- a/installation/language/ko-KR/joomla.ini +++ b/installation/language/ko-KR/joomla.ini @@ -7,14 +7,14 @@ ; These will be processed by the JavaScript Build BUILD_FATAL_HEADER="자동 복구될 수 없는 문제가 발생했습니다." BUILD_FATAL_LANGUAGE="Korean KO" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_FATAL_TEXT="서버가 \"{{statusCode_statusText}}\" 를 리턴했습니다." -BUILD_FATAL_URL_TEXT="이 문제를 해결하도록 도와주세요." +BUILD_FATAL_TEXT="서버 리턴 값은 \"{{statusCode_statusText}}\" 입니다." +BUILD_FATAL_URL_TEXT="처리해야 하는 문제가 발생했습니다." ; Build incomplete error page ; These will be processed by the JavaScript Build -BUILD_INCOMPLETE_HEADER="환경 설정 불완전" +BUILD_INCOMPLETE_HEADER="환경 설정이 완료되지 않았습니다." BUILD_INCOMPLETE_LANGUAGE="Korean KO" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR -BUILD_INCOMPLETE_TEXT="Joomla가 git repository에서 작동되기 위해서는 추가 설정이 필요합니다." +BUILD_INCOMPLETE_TEXT="Git 저장소에서 Joomla!를 설치하려는 것 같습니다. 이렇게 하려면 먼저 몇 가지 추가 단계를 완료해야 합니다." BUILD_INCOMPLETE_URL_TEXT="자세히 보기" ; No XML PHP error page @@ -22,17 +22,18 @@ BUILD_INCOMPLETE_URL_TEXT="자세히 보기" BUILD_NOXML_HEADER="PHP에 필수 라이브러리를 찾을 수 없습니다." BUILD_NOXML_LANGUAGE="Korean KO" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_NOXML_TEXT="해당 Joomla 버전을 사용하기 위해서는 호스트가 XML 라이브러리가 지원되는 PHP를 사용해야 합니다." -BUILD_NOXML_URL_TEXT="이 문제를 해결하도록 도와주세요." +BUILD_NOXML_URL_TEXT="처리해야 하는 문제가 발생했습니다." ; Minimum PHP error page ; These will be processed by the JavaScript Build -BUILD_MIN_PHP_ERROR_HEADER="죄송합니다. 사용 중인 PHP 버전이 지원되지 않습니다." +BUILD_MIN_PHP_ERROR_HEADER="죄송합니다. 사용 중인 PHP 버전은 지원되지 않습니다." BUILD_MIN_PHP_ERROR_LANGUAGE="Korean KO" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_MIN_PHP_ERROR_TEXT="해당 버전의 Joomla를 사용하기 위해서는 PHP 버전 {{phpversion}} 또는 그 상위 버전이 필요합니다." -BUILD_MIN_PHP_ERROR_URL_TEXT="이 문제를 해결하도록 도와주세요." +BUILD_MIN_PHP_ERROR_URL_TEXT="처리해야 하는 문제가 발생했습니다." ; Main Config -INSTL_SELECT_INSTALL_LANG="설치될 언어를 선택해 주세요." +INSTL_CHANGE_INSTALL_LANG_SHORT="위치 변경" +INSTL_SELECT_INSTALL_LANG="설치할 언어를 선택해 주세요." INSTL_SELECT_LANGUAGE_TITLE="언어 선택" INSTL_SETUP_LOGIN_DATA="로그인 정보 설정" INSTL_WARNJAVASCRIPT="경고! Joomla를 정상적으로 설치하기 위해서는 JavaScript가 반드시 필요합니다." @@ -42,19 +43,15 @@ INSTL_WARNJSON="Joomla가 설치되기 위해서는 PHP 설치에서 JSON 사용 INSTL_DATABASE_SUPPORT="데이터베이스 지원:" INSTL_JSON_SUPPORT_AVAILABLE="JSON 지원" INSTL_MB_LANGUAGE_IS_DEFAULT="MB 언어가 기본값 입니다." -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB 문자열(스트링) 오버로드 끄기" -INSTL_NOTICE_DATABASE_SUPPORT="지원되는 데이터베이스가 발견되지 않았습니다." +INSTL_NOTICE_DATABASE_SUPPORT="지원되는 데이터베이스를 찾을 수 없습니다." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Joomla가 설치되기 위해서는 PHP 설치에서 JSON 사용이 활성화되어야 합니다." -INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring 언어가 중립(neutral)으로 설정되어있지 않습니다. 이는 로컬에서 .htaccess 파일에 php_value mbstring.language neutral를 입력하여 설정할 수 있습니다." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring 함수 오버로드가 설정되어 있습니다. 이는 로컬에서 .htaccess 파일에 php_value mbstring.func_overload 0을 입력하여 설정을 해제할수있습니다." -INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="필수 PHP 함수인 parse_ini_file과 parse_ini_string이(가) 서버에 비활성화되어 있습니다." +INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring 언어가 중립으로 설정되지 않았습니다. 이 값은 .htaccess 파일에 php_value mbstring.language neutral 을 입력하여 로컬에서 설정할 수 있습니다." +INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="필수 PHP 함수인 parse_ini_file과 parse_ini_string이(가) 서버에서 비활성화되어 있습니다." INSTL_NOTICE_XML_SUPPORT="XML 지원이 사용 불가능합니다. 이는 PHP에서 기본적으로 활성화되어야 하지만, Ubuntu 사용자는 sudo apt-get install php-xml 명령어를 실행한 후 웹 서버를 재시작해야 합니다." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib 압축이 설정되어 있지 않습니다. 이를 로컬에서 활성화하려면 php.ini 파일에 zlib.output_compression = On을 입력하면 됩니다." INSTL_PARSE_INI_FILE_AVAILABLE="INI Parser 지원" INSTL_PRECHECK_ACTUAL="최신" -INSTL_PRECHECK_DESC="지원되지 않는 아이템이 있다면 서버의 설정을 고치기 위한 조치를 취해야합니다.
아래의 요구 사항이 충족되지 않으면 Joomla를 설치할 수 없습니다." +INSTL_PRECHECK_DESC="지원되지 않는 항목에 대한 조치가 필요합니다.
요구 사항이 충족되지 않으면 Joomla를 설치할 수 없습니다." INSTL_PRECHECK_DIRECTIVE="지시문" INSTL_PRECHECK_RECOMMENDED="추천" INSTL_PRECHECK_RECOMMENDED_SETTINGS_DESC="PHP에서 Joomla와의 완전한 호환성을 보장하려면 이러한 설정을 권장합니다." @@ -64,13 +61,13 @@ INSTL_XML_SUPPORT="XML 지원" INSTL_ZLIB_COMPRESSION_SUPPORT="Zlib 압축 지원" ; Database view -INSTL_DATABASE="데이터베이스 구성" +INSTL_DATABASE="데이터베이스 설정" INSTL_DATABASE_ENCRYPTION_CA_LABEL="CA 파일 경로" INSTL_DATABASE_ENCRYPTION_CERT_LABEL="인증서 파일 경로" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="지원되는 암호 스위트(선택 사항)" -INSTL_DATABASE_ENCRYPTION_KEY_LABEL="개인키 파일 경로" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL="개인 키 파일 경로" INSTL_DATABASE_ENCRYPTION_MODE_LABEL="연결 암호화" -INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="디폴트 (서버 조작)" +INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="표준(서버 제어)" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_ONE_WAY="사용자 인증(single factor)" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_TWO_WAY="2단계 보안 인증(2FA)" INSTL_DATABASE_ENCRYPTION_MSG_CONN_NOT_ENCRYPT="데이터베이스 연결 암호화를 사용하도록 선택했으며 연결이 설정될 수 있지만 암호화되지 않았습니다. 그 이유는 데이터베이스 서버가 암호화 매개변수가 잘못된 경우 암호화되지 않은 연결로 되돌아가도록 구성되어 있기 때문일 수 있습니다. 데이터베이스 암호화 매개변수를 확인하여 수정하거나 \"연결 암호화\" 필드를 \"기본값(서버 제어)\"으로 다시 변경합니다." @@ -83,12 +80,12 @@ INSTL_DATABASE_ERROR_POSTGRESQL_QUERY="PostgreSQL 데이터베이스 쿼리에 INSTL_DATABASE_HOST_DESC="호스트 이름(일반적으로 \"localhost\" 또는 호스트가 제공한 이름)을 입력하세요." INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_CREATE_FILE="파일을 만들 수 없습니다. "_QQ_"\"%1$s\"라는 파일을 수동으로 생성하여 Joomla 사이트의 \"%2$s\"폴더에 업로드하세요. 그런 다음 \"%3$s\"를 선택하여 계속하세요." INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_DELETE_FILE="이 웹 사이트의 소유자임을 확인하려면 Joomla 사이트의 \"%2$s\"폴더에 생성된 \"%1$s\"라는 파일을 삭제하십시오. 그런 다음 \"%3$s\"를 선택하여 계속하세요." -INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE="로컬 서버에 없는 데이터베이스 호스트를 사용하려고 합니다. 보안 상의 이유로 웹 호스팅 계정의 소유권을 확인해야 합니다. 자세한 내용은 이 문서에서 참조하세요. " +INSTL_DATABASE_HOST_IS_NOT_LOCALHOST_GENERAL_MESSAGE="로컬 서버에 없는 데이터베이스 호스트를 사용하려고 합니다. 보안상의 이유로 웹 호스팅 계정의 소유권을 확인해야 합니다. 자세한 내용은 이 문서에서 참조하세요. " INSTL_DATABASE_HOST_LABEL="호스트 이름" INSTL_DATABASE_NAME_DESC="데이터베이스 이름을 입력하세요." INSTL_DATABASE_NAME_LABEL="데이타베이스 이름" INSTL_DATABASE_NAME_MSG_MYSQL="데이터베이스 이름이 잘못되었습니다. 다음 문자를 포함해서는 안 됩니다: \ /" -INSTL_DATABASE_NAME_MSG_POSTGRES="데이터베이스 이름이 잘못되었습니다. 데이터베이스 이름은 반드시 문자로 시작하고 그 뒤에 영문자와 숫자가 와야 합니다." +INSTL_DATABASE_NAME_MSG_POSTGRES="데이터베이스 이름이 잘못되었습니다. 문자로 시작하고 그 뒤에 영문자와 숫자가 와야 합니다." INSTL_DATABASE_NO_SCHEMA="이 데이터베이스 유형에 대한 데이터베이스 스키마가 존재하지 않습니다." INSTL_DATABASE_PREFIX_DESC="테이블 접두사를 입력하거나 무작위로 생성된 접두사를 사용합니다." INSTL_DATABASE_PREFIX_DUPLICATE_DESC="접두사가 같은 테이블이 있는 기존 데이터베이스를 사용하는 경우 Joomla는 접두사 \"bak_\"를 추가하여 기존 테이블의 이름을 바꿉니다." @@ -119,13 +116,13 @@ INSTL_PUBLIC_FOLDER_DESC_SHORT="공용 폴더의 상대 또는 절대 경로" INSTL_COMPLETE_ADD_EXTRA_LANGUAGE="추가 언어 설치" INSTL_COMPLETE_ADMIN_BTN="관리자 열기" INSTL_COMPLETE_CONGRAT="축하드립니다!" -INSTL_COMPLETE_ERROR_FOLDER_DELETE="\"%s\" 폴더는 삭제될 수 없습니다. 폴더를 수동으로 삭제해 주세요." +INSTL_COMPLETE_ERROR_FOLDER_DELETE="\"%s\" 폴더는 삭제될 수 없습니다. 직접 삭제해 주세요." INSTL_COMPLETE_FINAL="설치 완료되었습니다." INSTL_COMPLETE_FINAL_DESC="Joomla 설치가 완료되었고, 지금 바로 사용 가능합니다." INSTL_COMPLETE_REMOVE_FOLDER="\"%s\" 폴더 삭제" INSTL_COMPLETE_SITE_BTN="사이트 열기" INSTL_COMPLETE_TITLE="축하드립니다! Joomla 사이트가 준비되었습니다." -INSTL_REMOVE_INST_FOLDER="정말로 지우겠습니까? 삭제 시 \"%s\" 는 복구 불가합니다." +INSTL_REMOVE_INST_FOLDER="정말로 지우겠습니까? 삭제시 \"%s\" 는 복구 불가합니다." ; Languages view INSTL_LANGUAGES="추가 언어 설치" @@ -133,11 +130,11 @@ INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE="언어" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_SELECT="언어 선택" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_TAG="언어 태그" INSTL_LANGUAGES_COLUMN_HEADER_VERSION="버전" -INSTL_LANGUAGES_DESC="Joomla 인터페이스는 여러 언어로 이용 가능합니다. 원하는 언어의 체크박스를 선택 후, 버튼 \"I선택한 언어 설치\" 을 클릭해 주세요.
참고로, 각 언어당 약 10 초 정도의 설치 시간이 소요됩니다. 오류 가능성을 줄이기 위해, 4개 이상의 언어팩을 동시에 설치하지 말아 주세요." +INSTL_LANGUAGES_DESC="Joomla 인터페이스는 여러 언어로 이용 가능합니다. 원하는 언어의 체크박스를 선택 후, \"선택한 언어 설치\" 버튼을 클릭해 주세요.
참고로, 각 언어당 약 10 초 정도의 설치 시간이 소요됩니다. 오류 가능성을 줄이기 위해, 4개 이상의 언어팩을 동시에 설치하지 말아 주세요." INSTL_LANGUAGES_MESSAGE_PLEASE_WAIT="이 작업을 완료하는 데 언어당 최대 10초가 소요됩니다
언어를 다운로드하고 설치하는 동안 잠시 기다려 주세요 …" INSTL_LANGUAGES_NO_LANGUAGE_SELECTED="설치할 언어가 선택되지 않았습니다." INSTL_LANGUAGES_SELECTED="선택된 언어 설치하기" -INSTL_LANGUAGES_WARNING_BACK_BUTTON="이전 설치 단계로 돌아가기" +INSTL_LANGUAGES_WARNING_BACK_BUTTON="마지막 설치 단계로 돌아가기" INSTL_LANGUAGES_WARNING_NO_INTERNET="Joomla가 언어 서버에 연결하지 못했습니다. 설치 프로세스를 완료해 주십시오." INSTL_LANGUAGES_WARNING_NO_INTERNET2="참고: 나중에 Joomla 관리자에서 언어를 설치할 수 있습니다." @@ -163,7 +160,7 @@ INSTL_DEFAULTLANGUAGE_TRY_LATER="나중에 Joomla 관리자에서 설치할 수 INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="한국어 (Korean)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español ; Database Model -INSTL_DATABASE_COULD_NOT_CONNECT="데이터베이스에 연결할 수 없습니다. 커넥터로부터 반환받은 번호: %s" +INSTL_DATABASE_COULD_NOT_CONNECT="데이터베이스에 연결할 수 없습니다. 커넥터 에러 메시지: %s" INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="설치 프로그램이 지정한 데이터베이스에 연결할 수 없어 데이터베이스를 만들 수 없습니다. 설정을 다시 확인하고 필요한 경우 데이터베이스를 수동으로 생성하세요." INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="확장 프로그램을 위한 manifest 캐시를 새로 고치지 못했습니다: %s" INSTL_DATABASE_ERROR_BACKINGUP="데이터베이스 백업 중 오류가 발생했습니다." @@ -173,9 +170,9 @@ INSTL_DATABASE_ERROR_READING_SQL_FILE="SQL 파일을 읽을 수 없습니다." INSTL_DATABASE_FIELD_VALUE_BACKUP="백업" INSTL_DATABASE_FIELD_VALUE_REMOVE="삭제" INSTL_DATABASE_FILE_DOES_NOT_EXIST="파일 %s이(가) 존재하지 않습니다." -INSTL_DATABASE_FIX_LOWERCASE="PostgreSQL의 테이블 접두사는 반드시 소문자여야 합니다." +INSTL_DATABASE_FIX_LOWERCASE="PostgreSQL의 테이블 접두사는 소문자여야 합니다." INSTL_DATABASE_FIX_TOO_LONG="MySQL 테이블 접두사는 최대 15자까지만 입력할 수 있습니다." -INSTL_DATABASE_INVALID_DB_DETAILS="입력한 데이터베이스 세부 정보가 잘못되었거나 비어 있습니다." +INSTL_DATABASE_INVALID_DB_DETAILS="데이터베이스 세부 정보가 잘못되었거나 비어 있습니다." INSTL_DATABASE_INVALID_MARIADB_VERSION="설치를 계속하려면 MariaDB %1$s 혹은 그 이상이 필요합니다. 사용 중인 버전: %2$s" INSTL_DATABASE_INVALID_MYSQLI_VERSION="설치를 계속하려면 MySQL %1$s 혹은 그 이상이 필요합니다. 사용 중인 버전: %2$s" INSTL_DATABASE_INVALID_MYSQL_VERSION="설치를 계속하려면 MySQL %1$s 혹은 그 이상이 필요합니다. 사용 중인 버전: %2$s" @@ -195,15 +192,15 @@ INSTL_PAGE_TITLE="Joomla 설치 프로그램" ; Configuration model INSTL_ERROR_CONNECT_DB="데이터베이스에 연결할 수 없습니다. 커넥터로부터 반환받은 번호: %d." -INSTL_STD_OFFLINE_MSG="이 사이트는 유지보수를 위해 닫혀 있습니다.
잠시 후 다시 확인해 주세요." +INSTL_STD_OFFLINE_MSG="이 사이트는 유지보수를 위해 닫혀 있습니다.
잠시 후 다시 확인해 주세요." ; Languages model -INSTL_ERROR_INVALID_URL="유효하지 않은 URL" +INSTL_ERROR_INVALID_URL="잘못된 URL" ; Others -INSTL_CONFPROBLEM="구성 파일 또는 폴더를 작성 수 없거나 구성 파일을 만드는 데 문제가 있습니다. 다음 코드를 수동으로 업로드해야 합니다. 텍스트 영역에서 선택하여 모든 코드를 강조 표시한 다음 새 텍스트 파일에 붙여넣습니다. 이 파일의 이름을 'configuration.php'로 지정하고 사이트 루트 폴더에 업로드합니다." +INSTL_CONFPROBLEM="구성 파일 또는 폴더를 쓸 수 없거나 구성 파일을 만드는 데 문제가 있습니다. 다음 코드를 직접 업로드해야 합니다. 텍스트 영역에서 선택하여 모든 코드를 강조 표시한 다음 새 텍스트 파일에 붙여넣습니다. 이 파일의 이름을 'configuration.php'로 지정하고 사이트 루트 폴더에 업로드합니다." INSTL_DISPLAY_ERRORS="디스플레이 오류" -INSTL_ERROR="오류" +INSTL_ERROR="에러" INSTL_ERROR_DB="데이터베이스를 채우는 동안 오류가 발생했습니다: %s." INSTL_ERROR_INITIALISE_SCHEMA="데이터베이스 스키마를 초기화할 수 없습니다." INSTL_EXTENSION_AVAILABLE="%s 사용 가능" @@ -223,23 +220,23 @@ INSTL_ZIP_SUPPORT_AVAILABLE="기본 ZIP 지원" JADMINISTRATOR="관리자" JCLOSE="닫기" JEMAIL="이메일" -JERROR="오류" +JERROR="에러" JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="요청 처리 도중 오류가 발생했습니다." JGLOBAL_ISFREESOFTWARE="%s은(는) GNU 일반 공중 사용 허가서로 릴리즈된 자유 소프트웨어 입니다." -JGLOBAL_LANGUAGE_VERSION_NOT_PLATFORM="언어팩이 이 Joomla!버전과 일치하지 않습니다. 몇몇 문자열이 누락되어 영어로 표시될 것입니다." +JGLOBAL_LANGUAGE_VERSION_NOT_PLATFORM="언어 팩이 설치된 Joomla! 버전과 일치하지 않습니다. 따라서 일부 번역이 누락되어 영어로 표시될 수 있습니다." JGLOBAL_SELECT_AN_OPTION="옵션을 선택하세요." JGLOBAL_SELECT_NO_RESULTS_MATCH="일치하는 결과가 없습니다." JGLOBAL_SELECT_SOME_OPTIONS="몇개의 옵션을 선택하세요." JHIDEPASSWORD="비밀번호 숨기기" -JINVALID_TOKEN="가장 최근의 요청이 잘못된 보안 토큰을 가지고 있어서 거부되었습니다. 페이지를 새로 고침하여 다시 시도하세요." -JINVALID_TOKEN_NOTICE="보안 토큰이 일치하지 않습니다. 보안 침해를 방지하기 위해 요청이 취소되었습니다. 다시 시도해 주세요." +JINVALID_TOKEN="요청이 잘못된 토큰을 가지고 있어서 거부되었습니다. 페이지를 새로 고침하여 다시 시도하세요." +JINVALID_TOKEN_NOTICE="토큰이 일치하지 않습니다. 보안 위반을 막기 위해 요청이 중단되었습니다. 다시 시도해 주세요." JNEXT="다음" JNO="Never" -JNOTICE="공지" +JNOTICE="공지사항" JOFF="비활성" JON="활성" JPREVIOUS="이전" -JSHOWPASSWORD="비밀번호 보기" +JSHOWPASSWORD="비밀번호 보이기" JSITE="사이트" JSKIP="건너뛰기" JUSERNAME="사용자 이름" @@ -251,29 +248,29 @@ JLIB_DATABASE_ERROR_DATABASE="데이터베이스 오류가 발생했습니다." JLIB_DATABASE_ERROR_LOAD_DATABASE_DRIVER="%s 데이터베이스 드라이버를 불러올 수 없습니다." JLIB_DATABASE_ERROR_VALID_MAIL="유효한 이메일 주소를 입력하세요." JLIB_ENVIRONMENT_SESSION_EXPIRED="세션이 만료되었습니다. 페이지를 새로 고침하세요." -JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: 경로는 폴더가 아닙니다. 경로: %2$s" +JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="JFolder: :삭제: 경로는 폴더가 아닙니다. 경로: %s" JLIB_FORM_FIELD_INVALID="유효하지 않은 필드: " JLIB_FORM_VALIDATE_FIELD_INVALID="유효하지 않은 필드: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="필드 요구사항: %s" JLIB_INSTALLER_ABORT="언어 설치 중단: %s" -JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="확장기능 %1$s: 폴더 생성 실패: %2$s" +JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="확장 프로그램 %1$s: 폴더 생성 실패: %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="설치 경로가 존재하지 않습니다." -JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="패키지 %1$s: 확장기능 설치중에 에러가 발생했습니다.: %2$s." +JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="패키지 %1$s: 확장 프로그램 설치중에 에러가 발생했습니다.: %2$s." JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="패키지 %s: 설치할 파일이 없습니다!" JLIB_INSTALLER_ERROR_DOWNLOAD_SERVER_CONNECT="서버 접속 오류: %s" JLIB_INSTALLER_ERROR_FAIL_COPY_FILE="JInstaller: :Install: %1$s 파일을 %2$s로 복사하는데 실패했습니다." JLIB_INSTALLER_INSTALL="설치" JLIB_INSTALLER_NOT_ERROR="오류가 TinyMCE 언어 파일의 설치와 연관되어 있다면 그것은 언어의 설치에 아무런 영향을 미치지 않습니다. 몇몇 언어 팩은 Joomla 3.2.0 이전 버전에 만들어져서, 별도로 TimyMCE 언어파일을 설치하려고 할 수도 있습니다. 이러한 경우, 줌라의 핵심 파일로 포함되어 있기 때문에, 더이상 설치할 필요가 없습니다." -JLIB_INSTALLER_WARNING_UNABLE_TO_INSTALL_CONTENT_LANGUAGE="%s 언어를 위한 콘텐츠 언어를 만들 수 없음: %s." -JLIB_UPDATER_ERROR_COLLECTION_FOPEN="PHP의 allow_url_fopen 설정이 비활성화되어 있습니다. 이 설정은 작동 업데이트를 위해 활성화되어 있어야합니다." -JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL="업데이트: :Collection: %s을(를) 열수 없습니다." -JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL="업데이트: :Collection: %s를(을) parse할 수 없습니다." +JLIB_INSTALLER_WARNING_UNABLE_TO_INSTALL_CONTENT_LANGUAGE="%s 언어를 위한 컨텐츠 언어를 생성할 수 없음: %s." +JLIB_UPDATER_ERROR_COLLECTION_FOPEN="PHP의 allow_url_fopen 설정이 비활성화되어 있습니다. 이 설정은 작동 업데이를 활성화해야합니다." +JLIB_UPDATER_ERROR_COLLECTION_OPEN_URL="업데이트: :수집: %s을 열수 없습니다." +JLIB_UPDATER_ERROR_COLLECTION_PARSE_URL="업데이트: :수집: %s를 parse 할수 없습니다." JLIB_UPDATER_ERROR_OPEN_UPDATE_SITE="업데이트: 업데이트 사이트 #%d "%s"를(을) 열 수 없음, URL: %s." -JLIB_UTIL_ERROR_CONNECT_DATABASE="JDatabase: :getInstance: 데이터베이스에 접속할 수 없습니다.
joomla.library: %1$s - %2$s." +JLIB_UTIL_ERROR_CONNECT_DATABASE="JDatabase: ::getInstance: 데이터베이스에 접속할 수 없습니다.
joomla.library: %1$s - %2$s." ; Strings for the language debugger -JDEBUG_LANGUAGE_FILES_IN_ERROR="언어 파일에서 Parsing 오류" -JDEBUG_LANGUAGE_UNTRANSLATED_STRING="번역되지 않은 문자열" +JDEBUG_LANGUAGE_FILES_IN_ERROR="언어 파일에서 파실(Parsing)오류" +JDEBUG_LANGUAGE_UNTRANSLATED_STRING="번역되지 않은 스트링" JNONE="없음" ; Necessary for errors @@ -282,7 +279,7 @@ ADMIN_PASSWORD="관리자 비밀번호" SITE_NAME="사이트 이름" ; Database types (allows for a more descriptive label than the internal name) -MYSQL="MySQL (PDO)" +MYSQL="MySQL" MYSQLI="MySQLi" ORACLE="Oracle" PGSQL="PostgreSQL (PDO)" @@ -290,20 +287,20 @@ POSTGRESQL="PostgreSQL" SQLITE="SQLite" ; Javascript message titles -ERROR="오류" +ERROR="에러" MESSAGE="메시지" -NOTICE="공지" +NOTICE="공지사항" WARNING="경고" ; Javascript ajax error messages JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="JSON 데이터 수신 중 연결 중단이 발생했습니다." JLIB_JS_AJAX_ERROR_NO_CONTENT="콘텐츠가 없습니다." -JLIB_JS_AJAX_ERROR_OTHER="JSON 데이터를 가져오는 중 오류 발생: HTTP %d 상태 코드." -JLIB_JS_AJAX_ERROR_PARSE="JSON 데이터 처리 파싱 에러 발생:
%s" +JLIB_JS_AJAX_ERROR_OTHER="JSON 데이터를 가져오는 동안 오류가 발생했습니다: HTTP %d 상태 코드입니다." +JLIB_JS_AJAX_ERROR_PARSE="JSON 데이터 처리 파싱 에러 발생:
%s" JLIB_JS_AJAX_ERROR_TIMEOUT="JSON 데이터 수신에 타임아웃 오류가 발생했습니다." ; Field password messages -JFIELD_PASSWORD_INDICATE_COMPLETE="비밀번호가 허용됨" +JFIELD_PASSWORD_INDICATE_COMPLETE="비밀번호가 수락됨" JFIELD_PASSWORD_INDICATE_INCOMPLETE="비밀번호가 사이트 요구 사항을 충족하지 않습니다." JFIELD_PASSWORD_SPACES_IN_PASSWORD="비밀번호는 앞이나 뒤에 공백이 없어야 합니다." JFIELD_PASSWORD_TOO_LONG="비밀번호가 너무 깁니다. 비밀번호는 100자 미만이어야 합니다." @@ -313,7 +310,7 @@ JFIELD_PASSWORD_TOO_SHORT_N="비밀번호가 너무 짧습니다. 비밀번호 JLIB_FORM_CONTAINS_INVALID_FIELDS="필수 데이터가 누락되어 양식을 제출할 수 없습니다.
표시된 필드를 수정하고 다시 시도하십시오." JLIB_FORM_FIELD_INVALID_VALUE="이 값은 유효하지 않습니다." JLIB_FORM_FIELD_REQUIRED_CHECK="옵션 중 하나를 반드시 선택해야 합니다." -JLIB_FORM_FIELD_REQUIRED_VALUE="이 필드를 작성하십시오." +JLIB_FORM_FIELD_REQUIRED_VALUE="이 필드를 작성하세요." ; Installation progress screen INSTL="설치" diff --git a/installation/language/ko-KR/langmetadata.xml b/installation/language/ko-KR/langmetadata.xml index 9d314767c13f0..54141d821a8b9 100644 --- a/installation/language/ko-KR/langmetadata.xml +++ b/installation/language/ko-KR/langmetadata.xml @@ -1,7 +1,7 @@ - Korean (Republic of Korea) - 5.4.8 + Korean (ko-KR) + 6.1.3 2026-07 Joomla! 프로젝트 (C) 2005 Open Source Matters, Inc. @@ -11,7 +11,7 @@
Korean (ko-KR) - Korean (Republic of Korea) + Korean (ko-KR) ko-KR 0 diff --git a/installation/language/lt-LT/joomla.cli.ini b/installation/language/lt-LT/joomla.cli.ini index b38426e26ad39..a25cf90c33182 100644 --- a/installation/language/lt-LT/joomla.cli.ini +++ b/installation/language/lt-LT/joomla.cli.ini @@ -1,11 +1,38 @@ INSTL_ADMIN_EMAIL_DESC="Įveskite svetainės Super User el. pašto adresą" +INSTL_ADMIN_EMAIL_DESC_SHORT="Svetainės SuperVartotojo paskyros el. pašto adresas" INSTL_ADMIN_PASSWORD_DESC="Nustatykite Super User paskyros slaptažodį" +INSTL_ADMIN_PASSWORD_DESC_SHORT="Jūsų supervartotojo paskyros slaptažodis" INSTL_ADMIN_USERNAME_DESC="Įveskite jūsų Super Administratoriaus paskyros prisijungimo vardą" +INSTL_ADMIN_USERNAME_DESC_SHORT="Jūsų supervartotojo paskyros vartotojo vardas" INSTL_ADMIN_USER_DESC="Įveskite tikrąjį Super User vardą" +INSTL_ADMIN_USER_DESC_SHORT="Tikrasis supervartotojo paskyros vardas" INSTL_DATABASE_COULD_NOT_CONNECT="%s" +INSTL_DATABASE_ENCRYPTION_CA_LABEL="Kelias į CA failą, pagal kurį reikia patikrinti šifravimą" +INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Kelias į CA failą, pagal kurį reikia patikrinti šifravimą" +INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Kelias į SSL sertifikatą duomenų bazės ryšiui. Reikalingas šifravimo nustatymas į 2" +INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Kelias į SSL sertifikatą duomenų bazės ryšiui. Reikalingas šifravimo nustatymas į 2" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Palaikomas „Cipher Suite“ (neprivaloma)" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Palaikomas „Cipher Suite“ (neprivaloma)" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL="SSL raktas duomenų bazės ryšiui. Reikalingas šifravimo nustatymas į 2" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="SSL raktas duomenų bazės ryšiui. Reikalingas šifravimo nustatymas į 2" +INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Duomenų bazės ryšio šifravimas. Reikšmės: 0 = nėra, 1 = vienpusis, 2 = dvipusis" +INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="Duomenų bazės ryšio šifravimas. Reikšmės: 0 = nėra, 1 = vienpusis, 2 = dvipusis" +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Patikrinkite SSL sertifikatą duomenų bazės ryšiui. Reikšmės: 0 = Ne, 1 = Taip. Reikalingas šifravimo nustatymas į 1 arba 2" +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="Patikrinkite SSL sertifikatą duomenų bazės ryšiui. Reikšmės: 0 = Ne, 1 = Taip. Reikalingas šifravimo nustatymas į 1 arba 2" +INSTL_DATABASE_HOST_DESC="Duomenų bazės priegloba" +INSTL_DATABASE_HOST_DESC_SHORT="Duomenų bazės priegloba" +INSTL_DATABASE_NAME_DESC="Duomenų bazės pavadinimas" +INSTL_DATABASE_NAME_DESC_SHORT="Duomenų bazės pavadinimas" +INSTL_DATABASE_PASSWORD_DESC="Duomenų bazės slaptažodis" +INSTL_DATABASE_PASSWORD_DESC_SHORT="Duomenų bazės slaptažodis" +INSTL_DATABASE_PREFIX_DESC="Duomenų bazės lentelių prefiksas" +INSTL_DATABASE_PREFIX_DESC_SHORT="Duomenų bazės lentelių prefiksas" +INSTL_DATABASE_TYPE_DESC="Duomenų bazės tipas. Palaikomi: mysql, mysqli, pgsql" +INSTL_DATABASE_TYPE_DESC_SHORT="Duomenų bazės tipas. Palaikoma „Joomla“: mysql (=MySQL (PDO)), mysqli (=MySQLi), pgsql (=PostgreSQL (PDO))" +INSTL_DATABASE_USER_DESC="Duomenų bazės vartotojo vardas" +INSTL_DATABASE_USER_DESC_SHORT="Duomenų bazės vartotojo vardas" INSTL_PUBLIC_FOLDER_DESC="Santykinis arba absoliutus kelias į viešąjį aplanką" INSTL_PUBLIC_FOLDER_DESC_SHORT="Santykinis arba absoliutus kelias į viešąjį aplanką" INSTL_SITE_NAME_DESC="Įveskite savo Joomla svetainės pavadinimą" +INSTL_SITE_NAME_DESC_SHORT="Svetainės pavadinimas" diff --git a/installation/language/lt-LT/joomla.ini b/installation/language/lt-LT/joomla.ini index 1574f81a53e26..c86fd13e545ad 100644 --- a/installation/language/lt-LT/joomla.ini +++ b/installation/language/lt-LT/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Kad paleisti šios versijos Joomla, Jūsų talpinimo s BUILD_MIN_PHP_ERROR_URL_TEXT="Padėkite man tai išspręsti" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Pakeisti" INSTL_SELECT_INSTALL_LANG="Pasirinkite diegimo kalbą" INSTL_SELECT_LANGUAGE_TITLE="Pasirinkite kalbą" INSTL_SETUP_LOGIN_DATA="Nustatykite prisijungimo duomenis" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Jūsų PHP diegimui turi būti įgalintas JSON, kad Joomla! būt INSTL_DATABASE_SUPPORT="Duomenų bazės palaikymas:" INSTL_JSON_SUPPORT_AVAILABLE="JSON palaikymas" INSTL_MB_LANGUAGE_IS_DEFAULT="MB kalba yra numatytoji" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Išjungta" INSTL_NOTICE_DATABASE_SUPPORT="Nerasta jokių palaikomų duomenų bazių." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Jūsų PHP diegimui turi būti įgalintas JSON, kad Joomla! būtų tinkamai įdiegta!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring kalba nėra nustatyta į neutralią. Tai galima nustatyti lokaliai, įrašant php_value mbstring.language neutral vertę .htaccess faile." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring funkcijos perkrovą yra įjungta. Tai galima išjungti lokaliai, įrašant php_value mbstring.func_overload 0 vertę .htaccess faile." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Reikalingos php funkcijos parse_ini_file ir parse_ini_string jūsų serveryje yra išjungtos." INSTL_NOTICE_XML_SUPPORT="XML palaikymas negalimas. Tai turėtų būti įjungta pagal numatytuosius nustatymus „php“, tačiau „Ubuntu“ vartotojams gali tekti tai įdiegti įvykdžius sudo apt-get install php-xml , ir po to iš naujo paleidus žiniatinklio serverį." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="„Zlib“ suspaudimas nenustatytas. Tai galima įjungti byloje, php.ini faile įvedus zlib.output_compression = On ." @@ -298,7 +295,7 @@ NOTICE="Pranešimas" WARNING="Įspėjimas" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Gaunant JSON duomenis įvyko ryšio klaida." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Ryšys nutrauktas išrenkant JSON duomenis." JLIB_JS_AJAX_ERROR_NO_CONTENT="Rezultatų negrąžinta." JLIB_JS_AJAX_ERROR_OTHER="Klaida išrenkant JSON duomenis: HTTP %s būsenos kodas." JLIB_JS_AJAX_ERROR_PARSE="Apdorojant šiuos JSON duomenis įvyko analizavimo klaida:
%s" diff --git a/installation/language/lt-LT/langmetadata.xml b/installation/language/lt-LT/langmetadata.xml index 7d840c7decbf0..1676a65c27dad 100644 --- a/installation/language/lt-LT/langmetadata.xml +++ b/installation/language/lt-LT/langmetadata.xml @@ -1,7 +1,7 @@ Lietuvių (lt-LT) - 5.4.8 + 6.1.3 2026-07 Oskaras Jankauskas (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/lv-LV/joomla.cli.ini b/installation/language/lv-LV/joomla.cli.ini index 9391a1ace70c4..7092dd9ee3c5f 100644 --- a/installation/language/lv-LV/joomla.cli.ini +++ b/installation/language/lv-LV/joomla.cli.ini @@ -21,8 +21,8 @@ INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Verificēt SSL sertifikātu INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="Verificēt SSL sertifikātu datubāzes savienojumam. Vērtības: 0=Nē, 1=Jā. Nepieciešams, lai šifrēšana būtu iestatīta uz 1 vai 2" INSTL_DATABASE_HOST_DESC="Datubāzes serveris" INSTL_DATABASE_HOST_DESC_SHORT="Datubāzes serveris" -INSTL_DATABASE_NAME_DESC="Datubāzes nosaukums" -INSTL_DATABASE_NAME_DESC_SHORT="Datubāzes nosaukums" +INSTL_DATABASE_NAME_DESC="Datu bāzes nosaukums" +INSTL_DATABASE_NAME_DESC_SHORT="Datu bāzes nosaukums" INSTL_DATABASE_PASSWORD_DESC="Datubāzes parole" INSTL_DATABASE_PASSWORD_DESC_SHORT="Datubāzes parole" INSTL_DATABASE_PREFIX_DESC="Datubāzes tabulas prefikss tabulām" diff --git a/installation/language/lv-LV/joomla.ini b/installation/language/lv-LV/joomla.ini index 09dd7abd782be..28cb0d13f4966 100644 --- a/installation/language/lv-LV/joomla.ini +++ b/installation/language/lv-LV/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Lai palaistu šo Joomla versiju, serverim ir jāizmant BUILD_MIN_PHP_ERROR_URL_TEXT="Palīdziet man to atrisināt" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Mainīt pozīciju" INSTL_SELECT_INSTALL_LANG="Izvēlieties instalācijas valodu" INSTL_SELECT_LANGUAGE_TITLE="Izvēlieties valodu" INSTL_SETUP_LOGIN_DATA="Iestatīt pievienošanās datus" @@ -42,13 +43,9 @@ INSTL_WARNJSON="PHP dzinējā jābūt ieslēgtam JSON funkciju atbalstam, lai va INSTL_DATABASE_SUPPORT="Datu bāzu atbalsts:" INSTL_JSON_SUPPORT_AVAILABLE="JSON atbalsts" INSTL_MB_LANGUAGE_IS_DEFAULT="Daudz bitu kodējums ir noklusētais" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="Daudz bitu virkņu pārlādēšana atslēgta" INSTL_NOTICE_DATABASE_SUPPORT="Netika atrasta neviena atbalstīta datu bāze." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="PHP dzinējā jābūt ieslēgtam JSON funkciju atbalstam, lai varētu instalēt Joomla!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring valoda nav iestatīta kā 'neutral'. To var iestatīt ierakstot php_value mbstring.language neutral .htaccess failā, kas atrodas vietnes saknes direktorijā.<0>." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring valoda ir ieslēgta. To var atslēgt ierakstot 'php_value mbstring.func_overload 0' .htaccess failā, kas atrodas vietnes saknes direktorijā." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Nepieciešamās php funkcijas parse_ini_file un parse_ini_string uz servera ir izslēgtas." INSTL_NOTICE_XML_SUPPORT="XML atbalsts nav pieejams. Tas ir jāiespējo pēc noklusējuma programmā php, bet Ubuntu lietotājiem tas, iespējams, būs jāinstalē, veicot sudo apt-get install php-xml , pēc tam jāveic web servisa pārstarēšana." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib kompresija nav ieslēgta. To var ieslēgt ievadot zlib.output_compression = On servera php.ini failā." @@ -236,7 +233,7 @@ JHIDEPASSWORD="Slēpt paroli" JINVALID_TOKEN="Pēdējais pieprasījums netika apstrādāts, jo nebija pareizs drošības kods. Lūdzu atjaunojiet lapu un mēģiniet vēlreiz." JINVALID_TOKEN_NOTICE="Neatbilstoša drošības atpazīšana. Pieprasījums ir pārtraukts lai novērstu drošības apdraudējumu. Mēģiniet vēlreiz." JNEXT="Nākamā" -JNO="Nē" +JNO="Nekad" JNOTICE="Paziņojums" JOFF="Izslēgts" JON="Ieslēgts" diff --git a/installation/language/lv-LV/langmetadata.xml b/installation/language/lv-LV/langmetadata.xml index a99096f60aa32..abe63d34ae097 100644 --- a/installation/language/lv-LV/langmetadata.xml +++ b/installation/language/lv-LV/langmetadata.xml @@ -1,7 +1,7 @@ Latvian (Latvia) - 5.4.8 + 6.1.3 2026-07 Joomla! Projekts (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/mk-MK/joomla.ini b/installation/language/mk-MK/joomla.ini index dfa37b08bd3b3..dc56348b77f48 100644 --- a/installation/language/mk-MK/joomla.ini +++ b/installation/language/mk-MK/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Вашиот хост треба да користи P BUILD_MIN_PHP_ERROR_URL_TEXT="Помогни ми да го решам ова" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Смени" INSTL_SELECT_INSTALL_LANG="Изберете јазик за инсталација" INSTL_SELECT_LANGUAGE_TITLE="Одбери јазик" INSTL_SETUP_LOGIN_DATA="Поставете податоци за најавување" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Вашата PHP -инсталација треба да има INSTL_DATABASE_SUPPORT="Поддршка за база на податоци:" INSTL_JSON_SUPPORT_AVAILABLE="JSON поддршка" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language е поставено" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload исклучено" INSTL_NOTICE_DATABASE_SUPPORT="Не беа пронајдени поддржани бази на податоци." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Вашата PHP -инсталација треба да има овозможено JSON за да се инсталира Joomla!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring јазикот не е поставен на neutral. Ова може да биде поставено и локално со внесување на php_value mbstring.language neutral во вашиот .htaccess документ." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring функцијата overload е поставена. Ова може да биде исклучено и локално со внесување на php_value mbstring.func_overload 0 во вашиот .htaccess документ." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Потребните php функции parse_ini_file и parse_ini_string се оневозможени на вашиот сервер." INSTL_NOTICE_XML_SUPPORT="Поддршката за XML не е достапна. Ова треба да биде стандардно овозможено во php, но корисниците на Ubuntu можеби ќе треба да го инсталираат ова со правење sudo apt-get install php-xml проследено со рестартирање на веб-серверот." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Компресијата на Zlib не е поставена. Ова може да се вклучи локално со внесување zlib.output_compression = On во вашата датотека php.ini." diff --git a/installation/language/mk-MK/langmetadata.xml b/installation/language/mk-MK/langmetadata.xml index 575a239939bd3..2e2960d0f1310 100644 --- a/installation/language/mk-MK/langmetadata.xml +++ b/installation/language/mk-MK/langmetadata.xml @@ -1,7 +1,7 @@ Macedonian (mk-MK) - 5.4.8 + 6.1.3 2026-07 Joomla! Project (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ms-MY/joomla.ini b/installation/language/ms-MY/joomla.ini index cd9f7f1f11283..76c922dcdd70b 100644 --- a/installation/language/ms-MY/joomla.ini +++ b/installation/language/ms-MY/joomla.ini @@ -90,7 +90,7 @@ JLOGIN="Log Masuk" JLOGOUT="Log Keluar" JMONTH="Bulan" JNEVER="Tidak Pernah" -JNEW="Baharu" +JNEW="Baru" JNEXT="Seterusnya" JNEXT_TITLE="Artikel seterusnya: %s" JNO="Tidak" @@ -138,10 +138,10 @@ JVISIT_WEBSITE="Lawati Laman Web" JYEAR="Tahun" JYES="Ya" -JBROWSERTARGET_DOWNLOAD="Muat turun %s dalam tetingkap baharu" +JBROWSERTARGET_DOWNLOAD="Muat turun %s dalam tetingkap baru" JBROWSERTARGET_MODAL="Modal" -JBROWSERTARGET_NEW="Buka dalam tetingkap baharu" -JBROWSERTARGET_NEW_TITLE="Buka %s dalam tetingkap baharu" +JBROWSERTARGET_NEW="Buka dalam tetingkap baru" +JBROWSERTARGET_NEW_TITLE="Buka %s dalam tetingkap baru" JBROWSERTARGET_PARENT="Buka dalam tetingkap induk" JBROWSERTARGET_POPUP="Buka dalam popup" @@ -156,7 +156,7 @@ JERROR_LAYOUT_AN_OUT_OF_DATE_BOOKMARK_FAVOURITE="penanda buku/kegemaran JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="Satu ralat telah berlaku semasa memproses permintaan anda." JERROR_LAYOUT_GO_TO_THE_HOME_PAGE="Pergi ke Halaman Utama" JERROR_LAYOUT_HOME_PAGE="Halaman Utama" -; deprecated will be removed in 6.0 +; deprecated will be removed in 7.0 JERROR_LAYOUT_MIS_TYPED_ADDRESS="alamat yang salah taip" JERROR_LAYOUT_MISTYPED_ADDRESS="alamat yang salah taip" JERROR_LAYOUT_NOT_ABLE_TO_VISIT="Anda mungkin tidak dapat melawat halaman ini kerana:" @@ -203,7 +203,7 @@ JFIELD_MEDIA_CLASS_LABEL="Kelas Imej" JFIELD_MEDIA_FIGURE_CAPTION_LABEL="Kapsyen Rajah" JFIELD_MEDIA_FIGURE_CLASS_LABEL="Kelas Rajah" JFIELD_MEDIA_HEIGHT_LABEL="Tinggi" -JFIELD_MEDIA_LAZY_LABEL="Imej akan dimuatkan secara malas" +JFIELD_MEDIA_LAZY_LABEL="Imej akan dimuatkan secara leka" JFIELD_MEDIA_SUMMARY_LABEL="Data Tambahan" JFIELD_MEDIA_WIDTH_LABEL="Lebar" JFIELD_MEDIA_TITLE_LABEL="Tajuk" @@ -239,7 +239,7 @@ JFIELD_PASSWORD_TOO_SHORT_N="Kata laluan terlalu pendek. Kata laluan mestilah se JFIELD_PUBLISHED_DESC="Tetapkan status penerbitan." JFIELD_TITLE_DESC="Tajuk untuk artikel." -JGLOBAL_ADD_CUSTOM_CATEGORY="Tambah Kategori baharu" +JGLOBAL_ADD_CUSTOM_CATEGORY="Tambah Kategori baru" JGLOBAL_ARTICLES="Artikel" JGLOBAL_AUTH_ACCESS_DENIED="Akses Ditolak" JGLOBAL_AUTH_ACCESS_GRANTED="Akses Diberikan" @@ -267,7 +267,7 @@ JGLOBAL_CLICK_TO_SORT_THIS_COLUMN="Pilih untuk menyusun mengikut lajur ini" JGLOBAL_COLLAPSE_CATEGORIES="Tunjukkan kurang kategori" JGLOBAL_CONFIRM_DELETE="Adakah anda pasti mahu memadam? Mengesahkan akan memadam item yang dipilih secara kekal!" JGLOBAL_CREATED_DATE_ON="Dicipta pada %s" -JGLOBAL_CUSTOM_CATEGORY="Kategori Baharu" +JGLOBAL_CUSTOM_CATEGORY="Kategori Baru" JGLOBAL_DESCRIPTION="Penerangan" JGLOBAL_DISPLAY_NUM="Papar #" JGLOBAL_EDIT="Sunting" @@ -337,7 +337,7 @@ JGLOBAL_MAXIMUM_UPLOAD_SIZE_LIMIT="Saiz muat naik maksimum: %s" JGLOBAL_MAXLEVEL_LABEL="Tahap Subkategori" JGLOBAL_NAME_ASC="Nama menaik" JGLOBAL_NAME_DESC="Nama menurun" -JGLOBAL_NEWITEMSLAST_DESC="Item baharu akan diletakkan di kedudukan terakhir secara lalai. Susunan boleh diubah selepas item ini disimpan." +JGLOBAL_NEWITEMSLAST_DESC="Item baru akan diletakkan di kedudukan terakhir secara lalai. Susunan boleh diubah selepas item ini disimpan." JGLOBAL_NO_MATCHING_RESULTS="Tiada Keputusan Sepadan" JGLOBAL_NUM="#" JGLOBAL_OTPMETHOD_NONE="Lumpuhkan Pengesahan Pelbagai Faktor" diff --git a/installation/language/ms-MY/langmetadata.xml b/installation/language/ms-MY/langmetadata.xml index 9799a799f2eb8..e41d3d053d249 100644 --- a/installation/language/ms-MY/langmetadata.xml +++ b/installation/language/ms-MY/langmetadata.xml @@ -1,7 +1,7 @@ Malay (Malaysia) - 5.4.7 + 6.1.2 2026-07 Joomla! Project (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/nl-BE/joomla.cli.ini b/installation/language/nl-BE/joomla.cli.ini index e4a4b84890d4e..f253e78176a06 100644 --- a/installation/language/nl-BE/joomla.cli.ini +++ b/installation/language/nl-BE/joomla.cli.ini @@ -1,7 +1,7 @@ INSTL_ADMIN_EMAIL_DESC="Voer het e-mailadres in van de website Super gebruiker" INSTL_ADMIN_EMAIL_DESC_SHORT="E-mailadres van de supergebruiker van de website" INSTL_ADMIN_PASSWORD_DESC="Stel het wachtwoord in voor uw Super Gebruiker account" -INSTL_ADMIN_PASSWORD_DESC_SHORT="Wachtwoord van uw Super User account" +INSTL_ADMIN_PASSWORD_DESC_SHORT="Stel het wachtwoord in voor uw Super Gebruiker account" INSTL_ADMIN_USERNAME_DESC="Stel de gebruikersnaam in voor uw Supergebruiker account" INSTL_ADMIN_USERNAME_DESC_SHORT="Gebruikersnaam van uw supergebruiker account" INSTL_ADMIN_USER_DESC="Voer de echte naam in van uw supergebruiker" diff --git a/installation/language/nl-BE/joomla.ini b/installation/language/nl-BE/joomla.ini index 07665adc73df8..7e9be9cfb76f0 100644 --- a/installation/language/nl-BE/joomla.ini +++ b/installation/language/nl-BE/joomla.ini @@ -6,32 +6,35 @@ ; Fatal error page ; These will be processed by the JavaScript Build BUILD_FATAL_HEADER="Sorry, er deed zich een probleem voor dat we niet konden herstellen." -BUILD_FATAL_LANGUAGE="Vlaams BE" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_FATAL_LANGUAGE="Engels GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_FATAL_TEXT="De server heeft een \"{{statusCode_statusText}} \" teruggestuurd" BUILD_FATAL_URL_TEXT="Help dit probleem op te lossen" ; Build incomplete error page ; These will be processed by the JavaScript Build BUILD_INCOMPLETE_HEADER="Omgeving instellen onvolledig" -BUILD_INCOMPLETE_LANGUAGE="Vlaams BE" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_INCOMPLETE_LANGUAGE="Engels GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_INCOMPLETE_TEXT="Het lijkt erop dat u probeert Joomla! uit te voeren vanuit onze git repository. Hiervoor is vereist dat u eerst een aantal extra stappen heeft voltooid." BUILD_INCOMPLETE_URL_TEXT="Meer details" ; No XML PHP error page ; These will be processed by the JavaScript Build BUILD_NOXML_HEADER="Sorry, uw PHP mist een noodzakelijke library" -BUILD_NOXML_LANGUAGE="Vlaams BE" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_NOXML_LANGUAGE="Engels GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_NOXML_TEXT="Om deze versie van Joomla! uit te kunnen voeren moet uw host PHP gebruiken met ondersteuning voor de XML-library" BUILD_NOXML_URL_TEXT="Help dit probleem op te lossen" ; Minimum PHP error page ; These will be processed by the JavaScript Build BUILD_MIN_PHP_ERROR_HEADER="Sorry, uw PHP-versie wordt niet ondersteund." -BUILD_MIN_PHP_ERROR_LANGUAGE="Vlaams BE" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR +BUILD_MIN_PHP_ERROR_LANGUAGE="Engels GB" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_MIN_PHP_ERROR_TEXT="Uw host moet PHP versie {{phpversion}} of nieuwer gebruiken om deze versie van Joomla uit te voeren." BUILD_MIN_PHP_ERROR_URL_TEXT="Help dit probleem op te lossen" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Verander de installatietaal" +INSTL_CHANGE_INSTALL_LANG_SHORT="Verander" +INSTL_SELECTED_INSTALL_LANGUAGE="Huidige taal: %s" INSTL_SELECT_INSTALL_LANG="Installatietaal selecteren" INSTL_SELECT_LANGUAGE_TITLE="Selecteer taal" INSTL_SETUP_LOGIN_DATA="Inloggegevens instellen" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Uw PHP installatie moet JSON geactiveerd hebben om Joomla! te ku INSTL_DATABASE_SUPPORT="Database ondersteuning:" INSTL_JSON_SUPPORT_AVAILABLE="JSON ondersteuning" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is standaard" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String overload uit" INSTL_NOTICE_DATABASE_SUPPORT="Er zijn geen ondersteunde databases gevonden." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Uw PHP installatie moet JSON geactiveerd hebben om Joomla! te kunnen installeren!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language is niet ingesteld op neutraal. Dit kan lokaal ingesteld worden door het ingeven van php_value mbstring.language neutral in uw .htaccess bestand." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload is ingesteld. Dit kan lokaal uitgeschakeld worden door het ingeven van php_value mbstring.func_overload 0 in uw .htaccess bestand." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="De vereiste php-functies parse_ini_file en parse_ini_string zijn uitgeschakeld op uw server." INSTL_NOTICE_XML_SUPPORT="XML-ondersteuning is niet beschikbaar. Dit moet standaard worden ingeschakeld in php, maar Ubuntu-gebruikers moeten sudo apt-get install php-xml installeren gevolgd door opnieuw opstarten van de webserver." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib-compressie is niet ingesteld. Dit kan lokaal worden ingeschakeld door zlib.output_compression = On in uw php.ini -bestand in te voeren." @@ -168,7 +167,7 @@ INSTL_DEFAULTLANGUAGE_FRONTEND_SET_DEFAULT="Joomla heeft %s ingesteld als uw sta INSTL_DEFAULTLANGUAGE_SET_DEFAULT_LANGUAGE="Standaardtaal instellen" INSTL_DEFAULTLANGUAGE_TRY_LATER="U kunt het later installeren met behulp van Joomla beheer." -INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Flemish (BE)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español +INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Vlaams (BE)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español ; Database Model INSTL_DATABASE_COULD_NOT_CONNECT="Kan geen verbinding maken met de database. Foutmelding: %s" @@ -222,7 +221,7 @@ INSTL_NOTICE_NEEDSTOBEWRITABLE="U kunt de installatie laten doorgaan als u de re INSTL_OUTPUT_BUFFERING="Uitvoer buffering" INSTL_PHP_VERSION="PHP versie" INSTL_PHP_VERSION_NEWER="PHP versie >= %s" -INSTL_PROCESS_BUSY="Verwerking is bezig. Even geduld …" +INSTL_PROCESS_BUSY="Proces in verwerking. Even wachten …" INSTL_SESSION_AUTO_START="Sessie auto start" INSTL_WRITABLE="Niet voldoende rechten voor het aanmaken van %s." INSTL_ZIP_SUPPORT_AVAILABLE="Ingebakken ZIP ondersteuning" diff --git a/installation/language/nl-BE/langmetadata.xml b/installation/language/nl-BE/langmetadata.xml index 99fefc95aa986..42d6481159e9c 100644 --- a/installation/language/nl-BE/langmetadata.xml +++ b/installation/language/nl-BE/langmetadata.xml @@ -1,17 +1,17 @@ - Vlaams (België) - 5.4.8 + Dutch (Belgium) + 6.1.3 2026-07 - Vlaams (BE) translation team + Dutch (BE) translation team (C) 2005 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt joomla.ini - Vlaams (nl-BE) - Vlaams (België) + Dutch (nl-BE) + Dutch (Belgium) nl-BE 0 diff --git a/installation/language/nl-NL/joomla.ini b/installation/language/nl-NL/joomla.ini index a8b25b9e3bd2b..d0b8b93af3e39 100644 --- a/installation/language/nl-NL/joomla.ini +++ b/installation/language/nl-NL/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Uw host moet PHP versie {{phpversion}} of nieuwer gebr BUILD_MIN_PHP_ERROR_URL_TEXT="Help dit probleem op te lossen" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Verander installatietaal" +INSTL_CHANGE_INSTALL_LANG_SHORT="Wijzigen" +INSTL_SELECTED_INSTALL_LANGUAGE="Huidige taal: %s" INSTL_SELECT_INSTALL_LANG="Installatietaal selecteren" INSTL_SELECT_LANGUAGE_TITLE="Selecteer taal" INSTL_SETUP_LOGIN_DATA="Inloggegevens instellen" @@ -42,13 +45,9 @@ INSTL_WARNJSON="In de PHP installatie dient JSON ingeschakeld te zijn om Joomla INSTL_DATABASE_SUPPORT="Database ondersteuning:" INSTL_JSON_SUPPORT_AVAILABLE="JSON ondersteuning" INSTL_MB_LANGUAGE_IS_DEFAULT="MB taal is standaard" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB string overload uitgeschakeld" INSTL_NOTICE_DATABASE_SUPPORT="Er zijn geen ondersteunde databases gevonden." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="In de PHP installatie dient JSON ingeschakeld te zijn om Joomla te kunnen installeren!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring taal is niet ingesteld op neutral. Voeg de regel php_value mbstring.language neutral toe aan het .htaccess bestand." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload is ingesteld. Dit kan lokaal uitgeschakeld worden door de regel php_value mbstring.func_overload 0 in het .htaccess bestand op te nemen." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="De vereiste php-functies parse_ini_file en parse_ini_string zijn uitgeschakeld op uw server." INSTL_NOTICE_XML_SUPPORT="XML-ondersteuning is niet beschikbaar. Dit moet standaard worden ingeschakeld in php, maar Ubuntu-gebruikers moeten sudo apt-get install php-xml installeren gevolgd door opnieuw opstarten van de webserver." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib-compressie is niet ingesteld. Dit kan lokaal worden ingeschakeld door zlib.output_compression = On in uw php.ini -bestand in te voeren." @@ -240,7 +239,7 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="Geen overeenkomende resultaten" JGLOBAL_SELECT_SOME_OPTIONS="Selecteer enkele opties" JHIDEPASSWORD="Wachtwoord verbergen" JINVALID_TOKEN="Het laatste verzoek is geweigerd omdat het een ongeldig veiligheidsteken bevat. Vernieuw de pagina en probeer het opnieuw." -JINVALID_TOKEN_NOTICE="Het beveiligingstoken komt niet overeen. Het verzoek is geannuleerd om een inbreuk op de beveiliging te voorkomen. Probeer het opnieuw." +JINVALID_TOKEN_NOTICE="Het beveiligingstoken komt niet overeen. Het verzoek is afgebroken om een inbreuk op de beveiliging te voorkomen. Probeer het opnieuw." JNEXT="Volgende" JNO="Nee" JNOTICE="Attentie" diff --git a/installation/language/nl-NL/langmetadata.xml b/installation/language/nl-NL/langmetadata.xml index 20ff3ceb4e76a..0767980352266 100644 --- a/installation/language/nl-NL/langmetadata.xml +++ b/installation/language/nl-NL/langmetadata.xml @@ -1,7 +1,7 @@ - Dutch (Netherlands) - 5.4.8 + Dutch (nl-NL) + 6.1.3 2026-07 Dutch Translation Team (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/pl-PL/joomla.ini b/installation/language/pl-PL/joomla.ini index 2077e539abb09..c327b76700fe8 100644 --- a/installation/language/pl-PL/joomla.ini +++ b/installation/language/pl-PL/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Twój serwer musi używać PHP w wersji {{phpversion}} BUILD_MIN_PHP_ERROR_URL_TEXT="Pomoc w rozwiązaniu tego problemu" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Zmień język instalacji" +INSTL_CHANGE_INSTALL_LANG_SHORT="Zmień" +INSTL_SELECTED_INSTALL_LANGUAGE="Obecny język: %s" INSTL_SELECT_INSTALL_LANG="Wybierz język instalacji" INSTL_SELECT_LANGUAGE_TITLE="Wybierz język" INSTL_SETUP_LOGIN_DATA="Ustawienia danych logowania" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Aby zainstalować Joomla, w ustawieniach PHP na serwerze musi by INSTL_DATABASE_SUPPORT="Obsługiwane bazy danych:" INSTL_JSON_SUPPORT_AVAILABLE="Obsługa JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="Język wielobajtowy - neutralny" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="Nadpisywanie funkcji MB - wyłączone" INSTL_NOTICE_DATABASE_SUPPORT="Nie znaleziono obsługiwanych baz danych." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Aby zainstalować Joomla, w ustawieniach PHP na serwerze musi być włączona obsługa JSON." INSTL_NOTICE_MBLANG_NOTDEFAULT="Wartość dyrektywy PHP mb_language nie została ustawiona na \"neutral\". Można zmienić to ustawienie poprzez dopisanie php_value mbstring.language neutral w pliku .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Funkcja PHP przeciążania mbstring jest włączona. Można ją lokalnie wyłączyć poprzez dopisanie php_value mbstring.func_overload 0 w pliku .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Wymagane funkcje php parse_ini_file i parse_ini_string są wyłączone na twoim serwerze." INSTL_NOTICE_XML_SUPPORT="Obsługa plików XML jest niedostępna. Powinna być domyślnie włączona w php. W przypadku korzystania z Ubuntu wymagana może być dodatkowa instalacja mechanizmu obsługi z wykorzystaniem sudo apt-get install php-xml. Po zakończeniu instalacji należy wykonać restart serwera www." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Kompresja Zlib nie jest uruchomiona. Można ją włączyć lokalnie, wpisując zlib.output_compression = On w pliku php.ini." diff --git a/installation/language/pl-PL/langmetadata.xml b/installation/language/pl-PL/langmetadata.xml index c5405a90cae20..c9eb25a820e23 100644 --- a/installation/language/pl-PL/langmetadata.xml +++ b/installation/language/pl-PL/langmetadata.xml @@ -1,7 +1,7 @@ Polski (PL) - 5.4.0 + 6.0.0 2025-10-13 Projekt Joomla! (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/pt-BR/joomla.cli.ini b/installation/language/pt-BR/joomla.cli.ini index 966cebb5bac61..18b15570f2d25 100644 --- a/installation/language/pt-BR/joomla.cli.ini +++ b/installation/language/pt-BR/joomla.cli.ini @@ -1,38 +1,38 @@ INSTL_ADMIN_EMAIL_DESC="Informe o endereço de e-mail do Super Usuário do site" -INSTL_ADMIN_EMAIL_DESC_SHORT="Endereço de e-mail da conta de Superusuário do site" +INSTL_ADMIN_EMAIL_DESC_SHORT="Endereço de email da conta Super Usuário do site" INSTL_ADMIN_PASSWORD_DESC="Defina a senha para sua conta do Super Usuário" -INSTL_ADMIN_PASSWORD_DESC_SHORT="Senha da sua conta de Superusuário" +INSTL_ADMIN_PASSWORD_DESC_SHORT="Senha da sua conta de Super Usuário" INSTL_ADMIN_USERNAME_DESC="Defina o nome de usuário para a conta do Super Usuário" -INSTL_ADMIN_USERNAME_DESC_SHORT="Nome de usuário da sua conta de Superusuário" +INSTL_ADMIN_USERNAME_DESC_SHORT="Nome de usuário da sua conta de Super Usuário" INSTL_ADMIN_USER_DESC="Digite o nome real do seu Super Usuário" -INSTL_ADMIN_USER_DESC_SHORT="Nome real da conta de Superusuário" +INSTL_ADMIN_USER_DESC_SHORT="Nome real da conta do Super Usuário" INSTL_DATABASE_COULD_NOT_CONNECT="%s" -INSTL_DATABASE_ENCRYPTION_CA_LABEL="Caminho para o arquivo CA a ser usado para verificar a criptografia." -INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Caminho para o arquivo CA a ser usado para verificar a criptografia." -INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Caminho para o certificado SSL da conexão com o banco de dados. Requer que a criptografia esteja definida como 2." -INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Caminho para o certificado SSL da conexão com o banco de dados. Requer que a criptografia esteja definida como 2." +INSTL_DATABASE_ENCRYPTION_CA_LABEL="Caminho para o arquivo CA para verificar a criptografia" +INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Caminho para o arquivo CA para verificar a criptografia" +INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Caminho para o certificado SSL para a conexão de banco de dados. Requer criptografia para ser definida como 2" +INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Caminho para o certificado SSL para a conexão de banco de dados. Requer criptografia para ser definida como 2" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Suporte a Cipher Suite (opcional)" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Suporte a Cipher Suite (opcional)" -INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Chave SSL para a conexão com o banco de dados. Requer que a criptografia esteja definida como 2." -INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="Chave SSL para a conexão com o banco de dados. Requer que a criptografia esteja definida como 2." -INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Criptografia para a conexão com o banco de dados. Valores: 0 = Nenhuma, 1 = Unidirecional, 2 = Bidirecional" -INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="Criptografia para a conexão com o banco de dados. Valores: 0 = Nenhuma, 1 = Unidirecional, 2 = Bidirecional" -INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Verificar certificado SSL para conexão com o banco de dados. Valores: 0 = Não, 1 = Sim. Requer que a criptografia esteja definida como 1 ou 2." -INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="Verificar certificado SSL para conexão com o banco de dados. Valores: 0 = Não, 1 = Sim. Requer que a criptografia esteja definida como 1 ou 2." -INSTL_DATABASE_HOST_DESC="Hospedagem do banco de dados" -INSTL_DATABASE_HOST_DESC_SHORT="Hospedagem do banco de dados" -INSTL_DATABASE_NAME_DESC="Nome do banco de dados" -INSTL_DATABASE_NAME_DESC_SHORT="Nome do banco de dados" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Caminho para o certificado SSL para a conexão de banco de dados. Requer criptografia para ser definida como 2" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="Caminho para o certificado SSL para a conexão de banco de dados. Requer criptografia para ser definida como 2" +INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Criptografia para a conexão do banco de dados. Valores: 0=Nenhum, 1=Uma via, 2=Duas vias" +INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="Criptografia para a conexão do banco de dados. Valores: 0=Nenhum, 1=Uma via, 2=Duas vias" +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Verifique o certificado SSL para conexão com o banco de dados. Valores: 0=Não, 1=Sim. Requer criptografia para ser definida como 1 ou 2" +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="Verifique o certificado SSL para conexão com o banco de dados. Valores: 0=Não, 1=Sim. Requer criptografia para ser definida como 1 ou 2" +INSTL_DATABASE_HOST_DESC="Host do banco de dados" +INSTL_DATABASE_HOST_DESC_SHORT="Host do banco de dados" +INSTL_DATABASE_NAME_DESC="Nome do Banco de Dados" +INSTL_DATABASE_NAME_DESC_SHORT="Nome do Banco de Dados" INSTL_DATABASE_PASSWORD_DESC="Senha do banco de dados" INSTL_DATABASE_PASSWORD_DESC_SHORT="Senha do banco de dados" -INSTL_DATABASE_PREFIX_DESC="Prefixo para as tabelas do banco de dados" -INSTL_DATABASE_PREFIX_DESC_SHORT="Prefixo para as tabelas do banco de dados" +INSTL_DATABASE_PREFIX_DESC="Prefixo para as tabelas da base de dados" +INSTL_DATABASE_PREFIX_DESC_SHORT="Prefixo para as tabelas da base de dados" INSTL_DATABASE_TYPE_DESC="Tipo de banco de dados. Suportado: mysql, mysqli, pgsql" -INSTL_DATABASE_TYPE_DESC_SHORT="Tipo de banco de dados. Compatível com Joomla: mysql (=MySQL (PDO)), mysqli (=MySQLi), pgsql (=PostgreSQL (PDO))" -INSTL_DATABASE_USER_DESC="Nome de usuário do banco de dados" -INSTL_DATABASE_USER_DESC_SHORT="Nome de usuário do banco de dados" +INSTL_DATABASE_TYPE_DESC_SHORT="Tipo de banco de dados. Suportado pelo Joomla: mysql (=MySQL (PDO)), mysqli (=MySQLi), pgsql (=PostgreSQL (PDO))" +INSTL_DATABASE_USER_DESC="Nome de Usuário do Banco de Dados" +INSTL_DATABASE_USER_DESC_SHORT="Nome de Usuário do Banco de Dados" INSTL_PUBLIC_FOLDER_DESC="Caminho relativo ou absoluto para a pasta pública" INSTL_PUBLIC_FOLDER_DESC_SHORT="Caminho relativo ou absoluto para a pasta pública" INSTL_SITE_NAME_DESC="Insira o nome do seu site Joomla" -INSTL_SITE_NAME_DESC_SHORT="Nome do site" +INSTL_SITE_NAME_DESC_SHORT="Nome do website" diff --git a/installation/language/pt-BR/joomla.ini b/installation/language/pt-BR/joomla.ini index 53158b8b1b7f7..75ea834211268 100644 --- a/installation/language/pt-BR/joomla.ini +++ b/installation/language/pt-BR/joomla.ini @@ -5,7 +5,7 @@ ; Fatal error page ; These will be processed by the JavaScript Build -BUILD_FATAL_HEADER="Desculpe, houve um problema que não pôde ser recuperado." +BUILD_FATAL_HEADER="Desculpe, houve um problema do qual não pudemos nos recuperar." BUILD_FATAL_LANGUAGE="Português do Brasil (pt-BR)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_FATAL_TEXT="O servidor retornou um \"{{statusCode_statusText}}\"" BUILD_FATAL_URL_TEXT="Ajude-me a resolver isto" @@ -15,7 +15,7 @@ BUILD_FATAL_URL_TEXT="Ajude-me a resolver isto" BUILD_INCOMPLETE_HEADER="Configuração do Ambiente Incompleta" BUILD_INCOMPLETE_LANGUAGE="Português do Brasil (pt-BR)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_INCOMPLETE_TEXT="Parece que você está tentando executar o Joomla! do nosso repositório git. Para fazer isso, primeiro é necessário que você conclua alguns passos adicionais." -BUILD_INCOMPLETE_URL_TEXT="Mais detalhes" +BUILD_INCOMPLETE_URL_TEXT="[ Mais Detalhe %s ]" ; No XML PHP error page ; These will be processed by the JavaScript Build @@ -32,8 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Seu servidor precisa usar a versão {{phpversion}} do BUILD_MIN_PHP_ERROR_URL_TEXT="Ajude-me a resolver isto" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Alterar Posição" INSTL_SELECT_INSTALL_LANG="Selecione o Idioma de Instalação" -INSTL_SELECT_LANGUAGE_TITLE="Selecionar idioma" +INSTL_SELECT_LANGUAGE_TITLE="Selecionar a linguagem" INSTL_SETUP_LOGIN_DATA="Configuração dos Dados de Autenticação" INSTL_WARNJAVASCRIPT="Atenção! O JavaScript deve estar ativado para a instalação correta do Joomla." INSTL_WARNJSON="A sua instalação do PHP no servidor precisa ter o JSON ativado para instalar o Joomla!" @@ -42,13 +43,9 @@ INSTL_WARNJSON="A sua instalação do PHP no servidor precisa ter o JSON ativado INSTL_DATABASE_SUPPORT="Suporte a Banco de dados:" INSTL_JSON_SUPPORT_AVAILABLE="Suporte a JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language é padrão" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="Não foram encontrados bancos de dados suportados." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="A sua instalação do PHP no servidor precisa ter o JSON ativado para instalar o Joomla!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring não está configurado como neutro. Isto pode ser configurado localmente mediante a inserção de php_value mbstring.language neutral no seu arquivo . htaccess ." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Sobrecarga de função PHP mbstring está ativada. Isto pode ser desativado localmente mediante a inserção de php_value mbstring.func_overload 0 no seu arquivo .htaccess ." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="As funções do php necessárias parse_ini_file e parse_ini_string estão desativadas no seu servidor." INSTL_NOTICE_XML_SUPPORT="O suporte a XML não está disponível. Isto deve ser habilitado por padrão no php, mas usuários do Ubuntu podem precisar instalar isso através do comando sudo apt-get install php-xml seguido de reinicialização do servidor web." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="A compressão Zlib não está configurada. Isso pode ser ativado localmente digitando zlib.output_compression = On no seu arquivo php.ini." @@ -136,7 +133,7 @@ INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_SELECT="Selecionar a linguagem" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_TAG="Código do idioma" INSTL_LANGUAGES_COLUMN_HEADER_VERSION="Versão" INSTL_LANGUAGES_DESC="A interface do Joomla está disponível em vários idiomas. Escolha o seu idioma através das caixas de seleção e, em seguida instale-os, selecionando o botão \"Instalar Idiomas Selecionados\".
Nota: Esta operação levará cerca de 10 segundos para baixar e instalar cada idioma. Para evitar timeouts por favor, selecione não mais do que 3 idiomas para instalar." -INSTL_LANGUAGES_MESSAGE_PLEASE_WAIT="Esta operação levará até 10 segundos por idioma para completar
Por favor espere enquanto baixamos e instalamos os idiomas" +INSTL_LANGUAGES_MESSAGE_PLEASE_WAIT="Esta operação levará até 10 segundos por idioma para completar
Por favor espere enquanto baixamos e instalamos os idiomas..." INSTL_LANGUAGES_NO_LANGUAGE_SELECTED="Nenhum idioma foi selecionado para instalação." INSTL_LANGUAGES_SELECTED="Instalar Idiomas Selecionados" INSTL_LANGUAGES_WARNING_BACK_BUTTON="Retornar à última etapa da instalação" @@ -234,9 +231,9 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="Sem resultados correspondentes" JGLOBAL_SELECT_SOME_OPTIONS="Selecione algumas opções" JHIDEPASSWORD="Ocultar senha" JINVALID_TOKEN="A requisição mais recente foi negada por conter um token de segurança inválido. Recarregue a página e tente novamente." -JINVALID_TOKEN_NOTICE="O token de segurança não corresponde. A solicitação foi cancelada para evitar qualquer violação de segurança. Tente novamente." +JINVALID_TOKEN_NOTICE="O token de segurança não corresponde. A solicitação foi abortada para prevenir qualquer violação de segurança. Tente novamente." JNEXT="Próximo" -JNO="Não" +JNO="Nunca" JNOTICE="Aviso" JOFF="Desativado" JON="Ativado" diff --git a/installation/language/pt-BR/langmetadata.xml b/installation/language/pt-BR/langmetadata.xml index 2282b5ce1db76..f3e09f2bdfe0c 100644 --- a/installation/language/pt-BR/langmetadata.xml +++ b/installation/language/pt-BR/langmetadata.xml @@ -1,7 +1,7 @@ Português do Brasil (pt-BR) - 5.4.8 + 6.1.3 2026-07 Projeto Joomla! (C) 2005 Open Source Matters, Inc. @@ -10,8 +10,8 @@ joomla.ini - Português do Brasil (pt-BR) - Portuguese (Brazil) + Brazilian Portuguese (pt-BR) + Português do Brasil (pt-BR) pt-BR 0 diff --git a/installation/language/pt-PT/joomla.cli.ini b/installation/language/pt-PT/joomla.cli.ini index d78916111ed0e..2b1ab55e04139 100644 --- a/installation/language/pt-PT/joomla.cli.ini +++ b/installation/language/pt-PT/joomla.cli.ini @@ -3,7 +3,7 @@ INSTL_ADMIN_EMAIL_DESC_SHORT="Endereço de email da conta de superutilizador do INSTL_ADMIN_PASSWORD_DESC="Defina a senha para a sua conta de superutilizador" INSTL_ADMIN_PASSWORD_DESC_SHORT="Senha da sua conta de superutilizador" INSTL_ADMIN_USERNAME_DESC="Defina o nome de utilizador para a sua conta de superutilizador" -INSTL_ADMIN_USERNAME_DESC_SHORT="Nome de utilizador da sua conta de superutilizador" +INSTL_ADMIN_USERNAME_DESC_SHORT="Endereço de email da sua conta de superutilizador" INSTL_ADMIN_USER_DESC="Digite o nome real para o seu superutilizador" INSTL_ADMIN_USER_DESC_SHORT="Nome real da conta de superutilizador" INSTL_DATABASE_COULD_NOT_CONNECT="%s" diff --git a/installation/language/pt-PT/joomla.ini b/installation/language/pt-PT/joomla.ini index ddf8d007d84e1..71dd6f303468e 100644 --- a/installation/language/pt-PT/joomla.ini +++ b/installation/language/pt-PT/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="O seu alojamento terá de usar PHP na versão {{phpver BUILD_MIN_PHP_ERROR_URL_TEXT="Ajude-me a resolver isto" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Alterar posição" INSTL_SELECT_INSTALL_LANG="Selecionar idioma de instalação" INSTL_SELECT_LANGUAGE_TITLE="Selecionar idioma" INSTL_SETUP_LOGIN_DATA="Configuração de dados de autenticação" @@ -42,13 +43,9 @@ INSTL_WARNJSON="É necessário ter o JSON autorizado na sua instalação PHP de INSTL_DATABASE_SUPPORT="Suporte a bases de dados:" INSTL_JSON_SUPPORT_AVAILABLE="Suporte a JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="Idioma predefinido de MB" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="Definição OVERLOAD de MB desligada" INSTL_NOTICE_DATABASE_SUPPORT="Não foram encontradas bases de dados suportadas." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="É necessário ter o JSON autorizado na sua instalação PHP de forma a poder instalar o Joomla. Contacte o gestor do seu alojamento!" INSTL_NOTICE_MBLANG_NOTDEFAULT="A 'mbstring' do PHP não está definida como neutra para idioma. Pode efetuar essa definição localmente colocando php_value mbstring.language neutral no ficheiro .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="A 'mbstring' do PHP de função 'overload' está ligada. Pode ser desligada localmente inserindo php_value mbstring.func_overload 0 no ficheiro .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="As funções de Php parse_ini_file e parse_ini_string são obrigatórias, mas estão desativadas no seu servidor." INSTL_NOTICE_XML_SUPPORT="O suporte a XML não está disponível. Isto deve estar autorizado, por predefinição, no PHP, mas os utilizadores do Ubuntu podem precisar de o instalar fazendo sudo apt-get install php-xml seguido de um reinício do servidor web." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Compressão Zlib não definida. Pode ser ativada adicionando a linha zlib.output_compression = On no seu ficheiro php.ini." @@ -151,7 +148,7 @@ INSTL_AUTOMATED_UPDATES_DISABLE="Desativar atualizações automatizadas" ; Default language view INSTL_DEFAULTLANGUAGE_ADMINISTRATOR="Idioma predefinido da área administrativa" INSTL_DEFAULTLANGUAGE_ADMIN_COULDNT_SET_DEFAULT="Não foi possível definir este idioma como predefinido. Será utilizado o inglês como idioma predefinido para a interface da área administrativa do sítio." -INSTL_DEFAULTLANGUAGE_ADMIN_SET_DEFAULT="O idioma %s foi definido como predefinido para a área administrativa." +INSTL_DEFAULTLANGUAGE_ADMIN_SET_DEFAULT="O idioma %s foi definido como predefinido para a administração." INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_LANGUAGE="Idioma" INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_SELECT="Selecionar" INSTL_DEFAULTLANGUAGE_COLUMN_HEADER_TAG="Etiqueta" diff --git a/installation/language/pt-PT/langmetadata.xml b/installation/language/pt-PT/langmetadata.xml index 80a2fa576419e..bbef891907435 100644 --- a/installation/language/pt-PT/langmetadata.xml +++ b/installation/language/pt-PT/langmetadata.xml @@ -1,7 +1,7 @@ Português (Portugal) - 5.4.8 + 6.1.3 2026-07 Comunidade JoomlaPortugal (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ro-RO/joomla.ini b/installation/language/ro-RO/joomla.ini index 9ac1a5aa13989..99f686015b987 100644 --- a/installation/language/ro-RO/joomla.ini +++ b/installation/language/ro-RO/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Gazda dvs. trebuie să folosească versiunea PHP {{php BUILD_MIN_PHP_ERROR_URL_TEXT="Ajută-mă să rezolv această problemă" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Schimbare" INSTL_SELECT_INSTALL_LANG="Selectaţi limba de instalare" INSTL_SELECT_LANGUAGE_TITLE="Selectare limbă" INSTL_SETUP_LOGIN_DATA="Configurare date de autentificare" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Pentru a instala Joomla, instalarea dvs PHP trebuie să aibă JS INSTL_DATABASE_SUPPORT="Suport bază de date:" INSTL_JSON_SUPPORT_AVAILABLE="Suport JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language este implicit" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="Nu au fost găsite baze de date acceptate." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Pentru a instala Joomla, instalarea dvs PHP trebuie să aibă JSON activat!" INSTL_NOTICE_MBLANG_NOTDEFAULT="Funcţia PHP mbstring nu este setată cu valoare neutră. Acest parametru poate fi setat local prin introducerea php_value mbstring.language neutral în fişierul .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Setarea privind supraîncărcarea funcţiei PHP mbstring a fost activată. Aceasta poate fi dezactivată local prin introducerea php_value mbstring.func_overload 0 în .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Funcțiile php necesare parse_ini_file și parse_ini_string sunt dezactivate pe serverul dvs." INSTL_NOTICE_XML_SUPPORT="Suportul XML nu este disponibil. Ar trebui activat în mod implicit în php, dar utilizatorii Ubuntu ar putea avea nevoie să instaleze acest pachet prin sudo apt-get install php-xml urmat de repornirea serverului web." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Compresia Zlib nu este setată. Aceasta poate fi activată local prin introducerea zlib.output_compression = On în fișierul dvs. php.ini." @@ -234,7 +231,7 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="Nici un rezultat nu se potriveste" JGLOBAL_SELECT_SOME_OPTIONS="Selectați niște opțiuni" JHIDEPASSWORD="Ascunde parola" JINVALID_TOKEN="Ultima solicitare a fost refuzată pentru că aceasta conținea un token invalid. Vă rugăm să reîmprospătați pagina și să încercați din nou." -JINVALID_TOKEN_NOTICE="Token-ul de securitate nu s-a potrivit. Solicitarea a fost anulată pentru a preveni orice încălcare a securității. Vă rugăm să încercați din nou." +JINVALID_TOKEN_NOTICE="Token-ul de securitate nu se potrivește. Solicitarea a fost anulată pentru a preveni orice problemă de securitate. Vă rugăm să încercați din nou." JNEXT="Următor" JNO="Nu" JNOTICE="Observație" @@ -257,7 +254,7 @@ JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: Calea nu este un director. Cal JLIB_FORM_FIELD_INVALID="Câmpul:  este invalid" JLIB_FORM_VALIDATE_FIELD_INVALID="Câmp invalid: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="Câmp necesar: %s" -JLIB_INSTALLER_ABORT="Oprire instalare limbă: %s" +JLIB_INSTALLER_ABORT="Renunțare la instalarea limbii: %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Extensia %1$s: Nu s-a putut crea directorul: %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="Calea de instalare nu există." JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Pachetul %1$s: A apărut o eroare la instalarea unei extensii: %2$s." @@ -298,7 +295,7 @@ NOTICE="Observație" WARNING="Avertizare" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="A apărut o eroare de conectare în timpul preluării datelor JSON." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="A apărut o eroare de conectare în timpul obținerii datelor JSON." JLIB_JS_AJAX_ERROR_NO_CONTENT="Nici un conținut nu a fost returnat" JLIB_JS_AJAX_ERROR_OTHER="A apărut o eroare în timpul obținerii datelor JSON: cod de status HTTP %d." JLIB_JS_AJAX_ERROR_PARSE="A apărut o eroare la procesarea următoarelor date JSON:
%s" diff --git a/installation/language/ro-RO/langmetadata.xml b/installation/language/ro-RO/langmetadata.xml index f850987c279f7..1a8618e317e2d 100644 --- a/installation/language/ro-RO/langmetadata.xml +++ b/installation/language/ro-RO/langmetadata.xml @@ -1,7 +1,7 @@ Română (România) - 5.4.8 + 6.1.3 2026-07 Horia Negura - Quanta (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ru-RU/joomla.ini b/installation/language/ru-RU/joomla.ini index c73cfab99e292..cb1979cd0090d 100644 --- a/installation/language/ru-RU/joomla.ini +++ b/installation/language/ru-RU/joomla.ini @@ -31,7 +31,10 @@ BUILD_MIN_PHP_ERROR_LANGUAGE="Русский RU" ; IMPORTANT NOTE FOR TRANSLATOR BUILD_MIN_PHP_ERROR_TEXT="Для установки Joomla необходимо наличие PHP {{phpversion}} или более новой версии." BUILD_MIN_PHP_ERROR_URL_TEXT="Подробнее о решении проблемы" -; Main Config +; Main config +INSTL_CHANGE_INSTALL_LANG="Изменить язык" +INSTL_CHANGE_INSTALL_LANG_SHORT="Изменить" +INSTL_SELECTED_INSTALL_LANGUAGE="Язык: %s" INSTL_SELECT_INSTALL_LANG="Параметры языка" INSTL_SELECT_LANGUAGE_TITLE="Язык установки" INSTL_SETUP_LOGIN_DATA="Параметры учетной записи" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Для установки Joomla в PHP должен быть в INSTL_DATABASE_SUPPORT="Поддержка баз данных" INSTL_JSON_SUPPORT_AVAILABLE="Поддержка JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language по умолчанию" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Выкл" INSTL_NOTICE_DATABASE_SUPPORT="Поддерживаемые базы данных не найдены." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Для установки Joomla в PHP должен быть включен JSON." INSTL_NOTICE_MBLANG_NOTDEFAULT="Для директивы mbstring.language установлено значение не neutral. Измените значение, добавив в файл .htaccess строку php_value mbstring.language neutral." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Для директивы mbstring.func_overload установлено значение 1 (включено). Измените значение, добавив в файл .htaccess строку php_value mbstring.func_overload 0." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Функции PHP parse_ini_file и parse_ini_string отключены на сервере." INSTL_NOTICE_XML_SUPPORT="Поддержка XML недоступна на сервере. Модуль должен быть включен в PHP по умолчанию, но пользователям Ubuntu может потребоваться его установка. Пожалуйста, выполните команду sudo apt-get install php-xml и перезапустите сервер." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Поддержка Zlib недоступна на сервере. Измените значение, добавив в файл php.ini строку zlib.output_compression = On." @@ -115,8 +114,8 @@ INSTL_SITE_DEVMODE_LABEL="Обнаружен режим разработки" INSTL_SITE_NAME_DESC="Название сайта" ; Expert view -INSTL_PUBLIC_FOLDER_DESC="Путь к общему каталогу" INSTL_PUBLIC_FOLDER_DESC_SHORT="Путь к общему каталогу" +INSTL_PUBLIC_FOLDER_LABEL="Путь к общему каталогу" ; Complete view INSTL_COMPLETE_ADD_EXTRA_LANGUAGE="Установить языки" @@ -170,7 +169,7 @@ INSTL_DEFAULTLANGUAGE_TRY_LATER="Вы можете установить его INSTL_DEFAULTLANGUAGE_NATIVE_LANGUAGE_NAME="Русский (RU)" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example Spanish will be Español -; Database Model +; Database model INSTL_DATABASE_COULD_NOT_CONNECT="Не удалось подключиться к базе данных: %s." INSTL_DATABASE_COULD_NOT_CREATE_DATABASE="Не удалось подключиться к базе данных. Пожалуйста, проверьте параметры и при необходимости создайте базу данных вручную." INSTL_DATABASE_COULD_NOT_REFRESH_MANIFEST_CACHE="Не удалось обновить кэш манифеста: %s." @@ -299,8 +298,9 @@ SQLITE="SQLite" ; Javascript message titles ERROR="Ошибка" -MESSAGE="Сообщение" +MESSAGE="Уведомление" NOTICE="Внимание" +SUCCESS="Успех" WARNING="Предупреждение" ; Javascript ajax error messages diff --git a/installation/language/ru-RU/langmetadata.xml b/installation/language/ru-RU/langmetadata.xml index 9c14284dba500..b8a1e93f98fa1 100644 --- a/installation/language/ru-RU/langmetadata.xml +++ b/installation/language/ru-RU/langmetadata.xml @@ -1,19 +1,19 @@ - - - Russian (Russia) - 5.4.6 - 2026-05 - Russian Translation Team - (C) 2005 Open Source Matters, Inc. - GNU General Public License version 2 or later; see LICENSE.txt - - joomla.ini - - - Russian (ru-RU) - Русский (Россия) - ru-RU - 0 - - - + + + Russian (Russia) + 6.1.2 + 2026-07 + Russian Translation Team + (C) 2005 Open Source Matters, Inc. + GNU General Public License version 2 or later; see LICENSE.txt + + joomla.ini + + + Russian (ru-RU) + Русский (Россия) + ru-RU + 0 + + + diff --git a/installation/language/sk-SK/joomla.ini b/installation/language/sk-SK/joomla.ini index b05c77ed65a45..08e84443de28e 100644 --- a/installation/language/sk-SK/joomla.ini +++ b/installation/language/sk-SK/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Aby táto verzia Joomla fungovala, váš hosting musí BUILD_MIN_PHP_ERROR_URL_TEXT="Pomôžte mi vyriešiť to" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Zmeniť jazyk inštalácie" +INSTL_CHANGE_INSTALL_LANG_SHORT="Zmeniť" +INSTL_SELECTED_INSTALL_LANGUAGE="Aktuálny jazyk: %s" INSTL_SELECT_INSTALL_LANG="Vyberte jazyk inštalácie" INSTL_SELECT_LANGUAGE_TITLE="Vyberte jazyk" INSTL_SETUP_LOGIN_DATA="Nastavenie prihlasovacích údajov" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Vaša inštalácia PHP musí mať zapnuté JSON, aby Joomla! moh INSTL_DATABASE_SUPPORT="Podpora databázy:" INSTL_JSON_SUPPORT_AVAILABLE="Podpora JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="Predvolené MB Language" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="Neboli nájdené žiadne podporované databázy." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Vaša inštalácia PHP musí mať zapnuté JSON, aby Joomla! mohla byť nainštalovaná!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language nie je nastavený na neutrálny. Môžete tak urobiť lokálne pridaním riadku php_value mbstring.language neutral do vášho súboru .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Je nastavené preťaženie funkcie PHP mbstring. Nastavenie môžete vypnúť lokálne pridaním riadku php_value mbstring.func_overload 0 do vášho súboru .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Požadované funkcie php parse_ini_file a parse_ini_string sú na serveri vypnuté." INSTL_NOTICE_XML_SUPPORT="Podpora XML nie je k dispozícii. Štandardne sa zapína v php, ale používatelia Ubuntu ju musia nainštalovať pomocou príkazu sudo apt-get install php-xml s následným reštartom webového servera." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib kompresia nie je nastavená. Lokálne môže byť zapnutá zadaním zlib.output_compression = On do vášho súboru php.ini." diff --git a/installation/language/sk-SK/langmetadata.xml b/installation/language/sk-SK/langmetadata.xml index d55cef04e2344..568b5d540aa95 100644 --- a/installation/language/sk-SK/langmetadata.xml +++ b/installation/language/sk-SK/langmetadata.xml @@ -1,7 +1,7 @@ Slovak (Slovakia) - 5.4.8 + 6.1.3 2026-07 Slovak translation team : Peter Michnica (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/sl-SI/joomla.ini b/installation/language/sl-SI/joomla.ini index f882b1c15bb40..3f4da74f3f610 100644 --- a/installation/language/sl-SI/joomla.ini +++ b/installation/language/sl-SI/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Vaš gostitelj mora uporabljati PHP različico {{phpv BUILD_MIN_PHP_ERROR_URL_TEXT="Pomagajte mi rešiti to težavo" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Spremenite jezik namestitve" +INSTL_CHANGE_INSTALL_LANG_SHORT="Spremenite pozicijo" +INSTL_SELECTED_INSTALL_LANGUAGE="Trenutni jezik: %s" INSTL_SELECT_INSTALL_LANG="Izberite jezik namestitve" INSTL_SELECT_LANGUAGE_TITLE="Izberite jezik" INSTL_SETUP_LOGIN_DATA="Nastavitev prijavnih podatkov" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Vaša PHP namestitev mora imeti JSON omogočeno, za namestitev INSTL_DATABASE_SUPPORT="Baza podatkov Podpora:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Podpora" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Jezik je privzeti" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB Niz preobremenitve izklopljen" INSTL_NOTICE_DATABASE_SUPPORT="Nobena podprta zbirka podatkov ni najdena." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Vaša PHP namestitev mora imeti JSON omogočeno, za namestitev Joomla!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring jezik ni nastavljen v nevtralni položaj. To je mogoče nastaviti na lokalni ravni z vnosom php_value mbstring.language neutral v vaši .htaccess datoteki." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring preobremenitev funkcija je nastavljena. To je mogoče izklopiti lokalno z vnosom php_value mbstring.func_overload 0 v vaši .htaccess datoteki." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Zahtevane php funkcije parse_ini_file in parse_ini_string so onemogočene na vašem strežniku." INSTL_NOTICE_XML_SUPPORT="Podpora za XML ni na voljo. To bi moralo biti privzeto omogočeno v php, vendar ga bodo uporabniki Ubuntuja morda morali namestiti tako, da izvedejo sudo apt-get install php-xml čemur sledi ponovni zagon spletnega strežnika." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib stiskanje ni nastavljeno. To je mogoče vklopiti lokalno, tako da v datoteko zlib.output_compression = On v vaši php.ini datoteki." @@ -240,7 +239,7 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="Noben rezultat se ne ujema" JGLOBAL_SELECT_SOME_OPTIONS="Izberite nekaj možnosti" JHIDEPASSWORD="Skrijte geslo" JINVALID_TOKEN="Najnovejša zahteva zavrnjena, ker je imela neveljaven varnostni žeton. Prosimo, osvežite stran in poskusite znova." -JINVALID_TOKEN_NOTICE="Varnostni žeton se ne ujema. Zahteva je bila preklicana, da se prepreči kakršno koli kršitev varnosti. Prosim poskusite ponovno." +JINVALID_TOKEN_NOTICE="Varnostni žeton se ni ujemal. Zahteva je bila preklicana, da se prepreči morebitna kršitev varnosti. Prosim poskusite ponovno." JNEXT="Naprej" JNO="Ne" JNOTICE="Obvestilo" @@ -304,7 +303,7 @@ NOTICE="Obvestilo" WARNING="Opozorilo" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Pri pridobivanju JSON podatkov je prišlo do napake pri povezavi." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Pri pridobivanju podatkov JSON je prišlo do napake pri povezavi." JLIB_JS_AJAX_ERROR_NO_CONTENT="Vsebina ni vrnjena." JLIB_JS_AJAX_ERROR_OTHER="Prišlo je do napake pri pridobivanju JSON podatkov: HTTP %d status code." JLIB_JS_AJAX_ERROR_PARSE="Prišlo je do napake pri razčlenjevanju med obdelavo naslednjih JSON podatkov:
%s" diff --git a/installation/language/sl-SI/langmetadata.xml b/installation/language/sl-SI/langmetadata.xml index 2cee2f9f2918e..655a6bfbb3781 100644 --- a/installation/language/sl-SI/langmetadata.xml +++ b/installation/language/sl-SI/langmetadata.xml @@ -1,7 +1,7 @@ Slovenščina (Slovenija) - 5.4.8 + 6.1.3 2026-07 Slovenska prevajalska ekipa (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/sr-YU/joomla.cli.ini b/installation/language/sr-YU/joomla.cli.ini index 532b3c2f7d26c..e964a17bc46fc 100644 --- a/installation/language/sr-YU/joomla.cli.ini +++ b/installation/language/sr-YU/joomla.cli.ini @@ -8,17 +8,17 @@ INSTL_ADMIN_USER_DESC="Unesite pravo ime super korisnika" INSTL_ADMIN_USER_DESC_SHORT="Pravo ime Super User naloga" INSTL_DATABASE_COULD_NOT_CONNECT="%s" INSTL_DATABASE_ENCRYPTION_CA_LABEL="Putanja do CA datoteke za proveru enkripcije" -INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Putanja do CA datoteke za proveru enkripcije" +INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Putanja do CA fajla za proveru enkripcije" INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Putanja do SSL sertifikata za konekciju sa bazom podataka. Zahteva da enkripcija bude podešena na 2" -INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Putanja do SSL sertifikata za konekciju sa bazom podataka. Zahteva da enkripcija bude podešena na 2" +INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Putanja do SSL sertifikata za vezu sa bazom podataka. Zahteva da enkripcija bude podešena na 2" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Podržani Cipher Suite (opcionalno)" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Podržani Cipher Suite (opcionalno)" INSTL_DATABASE_ENCRYPTION_KEY_LABEL="SSL ključ za vezu sa bazom podataka. Zahteva da enkripcija bude podešena na 2" -INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="SSL ključ za vezu sa bazom podataka. Zahteva da enkripcija bude podešena na 2" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="SSL ključ za konekciju sa bazom podataka. Zahteva da enkripcija bude podešena na 2" INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Enkripcija za konekciju sa bazom podataka. Vrednosti: 0=Bez enkripcije, 1=Jednosmerna, 2=Dvosmerna" INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="Enkripcija za konekciju sa bazom podataka. Vrednosti: 0=Bez enkripcije, 1=Jednosmerna, 2=Dvosmerna" INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Proveri SSL sertifikat za konekciju sa bazom podataka. Vrednosti: 0=Ne, 1=Da. Zahteva da enkripcija bude podešena na 1 ili 2" -INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="Proveri SSL sertifikat za konekciju sa bazom podataka. Vrednosti: 0=Ne, 1=Da. Zahteva da enkripcija bude podešena na 1 ili 2" +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="Proveri SSL sertifikat za vezu sa bazom podataka. Vrednosti: 0=Ne, 1=Da. Zahteva da enkripcija bude podešena na 1 ili 2" INSTL_DATABASE_HOST_DESC="Host baze podataka" INSTL_DATABASE_HOST_DESC_SHORT="Host baze podataka" INSTL_DATABASE_NAME_DESC="Ime baze podataka" diff --git a/installation/language/sr-YU/joomla.ini b/installation/language/sr-YU/joomla.ini index 6863a2d95131e..950b75cec8b9e 100644 --- a/installation/language/sr-YU/joomla.ini +++ b/installation/language/sr-YU/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Vaš host mora da koristi PHP verziju {{phpversion}} i BUILD_MIN_PHP_ERROR_URL_TEXT="Kako da rešim ovo" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Promeni poziciju" INSTL_SELECT_INSTALL_LANG="Izaberite jezik instalacije" INSTL_SELECT_LANGUAGE_TITLE="Odaberite jezik" INSTL_SETUP_LOGIN_DATA="Podesite podatke za prijavu" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Za Joomla! instalaciju PHP mora imati omogućenu JSON ekstenziju INSTL_DATABASE_SUPPORT="Podrška baze:" INSTL_JSON_SUPPORT_AVAILABLE="JSON podrška" INSTL_MB_LANGUAGE_IS_DEFAULT="MB jezik je podrazumevan" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload isključen" INSTL_NOTICE_DATABASE_SUPPORT="Nepodržana baza je detektovana." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Za Joomla! instalaciju PHP mora imati omogućenu JSON ekstenziju" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring jezik nije neutralan. Ovo možete namestiti lokalno unošenjem php_value mbstring.language neutral u .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload je podešen. Ovo može biti isključeno lokalno unošenjem php_value mbstring.func_overload 0 u .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Potrebne php funkcije parse_ini_file i parse_ini_string su isključene na serveru." INSTL_NOTICE_XML_SUPPORT="XML podrška nije dostupna. Treba je omogućiti u php-u, Ubuntu korisnici treba da instaliraju pokretanjem komande sudo apt-get install php-xml prateći restartovanje servera." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib kompresija nije podešena. Može se uključiti setovanjem zlib.output_compression = On u php.ini datoteci." @@ -298,7 +295,7 @@ NOTICE="Obaveštenje" WARNING="Upozorenje" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Prekid konekcije u toku preuzimanja JSON podataka." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Došlo je do prekida veze tokom dohvaćanja JSON podataka." JLIB_JS_AJAX_ERROR_NO_CONTENT="Sadržaj nije vraćen." JLIB_JS_AJAX_ERROR_OTHER="Greška pri preuzimanju JSON podataka: HTTP %d status kod." JLIB_JS_AJAX_ERROR_PARSE="Greška pri parsiranju JSON podataka:
%s" diff --git a/installation/language/sr-YU/langmetadata.xml b/installation/language/sr-YU/langmetadata.xml index 63a687d46b8ed..b211217b23c06 100644 --- a/installation/language/sr-YU/langmetadata.xml +++ b/installation/language/sr-YU/langmetadata.xml @@ -1,7 +1,7 @@ Srpski (Republika Srbija) - 5.4.8 + 6.1.3 2026-07 Goran Nešić & Saša Matić (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/sv-SE/joomla.cli.ini b/installation/language/sv-SE/joomla.cli.ini index a544e57a119f9..3bb2a0265429d 100644 --- a/installation/language/sv-SE/joomla.cli.ini +++ b/installation/language/sv-SE/joomla.cli.ini @@ -14,7 +14,7 @@ INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Sökväg till SSL-certifikatet för INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Shiffersviter som stöds (frivillig)" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Shiffersviter som stöds (frivillig)" INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Sökväg till SSL-certifikatet för databasanslutningen. Kräver kryptering för att sättas till 2" -INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="Sökväg till SSL-certifikat för databasanslutning. Kräver kryptering för att sättas till 2" +INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="Sökväg till SSL-certifikatet för databasanslutningen. Kräver kryptering för att sättas till 2" INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Kryptering för databasanslutningen. Värden: 0=Ingen, 1=Ett sätt, 2=Tvåvägs" INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="Kryptering för databasanslutningen. Värden: 0=Ingen, 1=Ett sätt, 2=Tvåvägs" INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="Verifiera SSL-certifikat för databasanslutning. Värden: 0=Nej, 1=Ja. Kräver kryptering för att sättas till 1 eller 2" diff --git a/installation/language/sv-SE/joomla.ini b/installation/language/sv-SE/joomla.ini index 3d4227cf973c7..eccfceab550ac 100644 --- a/installation/language/sv-SE/joomla.ini +++ b/installation/language/sv-SE/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Ditt webbhotell måste använda PHP-version {{phpversi BUILD_MIN_PHP_ERROR_URL_TEXT="Hjälp mig att lösa detta" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Ändra installationsspråk" +INSTL_CHANGE_INSTALL_LANG_SHORT="Ändra position" +INSTL_SELECTED_INSTALL_LANGUAGE="Nuvarande språk: %s" INSTL_SELECT_INSTALL_LANG="Välj installationsspråk" INSTL_SELECT_LANGUAGE_TITLE="Välj språk" INSTL_SETUP_LOGIN_DATA="Ställ in inloggningsdata" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Din PHP-installation måste ha JSON aktiverat för att Joomla sk INSTL_DATABASE_SUPPORT="Databas som stöds:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Support" INSTL_MB_LANGUAGE_IS_DEFAULT="MB language är standard" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload är avstängd" INSTL_NOTICE_DATABASE_SUPPORT="Hittade databaser som inte stöds." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Din PHP-installation måste ha JSON aktiverat för att Joomla ska kunna installeras!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language är inte satt till neutral. Detta kan ställas in lokalt genom att skriva in php_value mbstring.language neutral i .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload är aktiverat. Detta kan stängas av lokalt genom att skriva in php_value mbstring.func_overload 0 i .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="De php funktioner som krävs parse_ini_file och parse_ini_string är inaktiverade på din server." INSTL_NOTICE_XML_SUPPORT="XML-stöd är inte tillgänglig. Detta bör vara aktiverat som standard i php men Ubuntu-användare, kan behöva installera det genom att göra sudo apt-get install php-xml följt av web server omstart." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib komprimering är inte inställd. Detta kan slås på lokalt genom att ange zlib.output_compression = On i din php.ini fil." @@ -242,7 +241,7 @@ JHIDEPASSWORD="Dölj lösenord" JINVALID_TOKEN="Det senaste anropet nekades för att det innehåller ett ogiltigt igenkänningstecken för säkerhet. Uppdatera sidan och försök igen. Tips: ta bort 'index.php' i URL:en." JINVALID_TOKEN_NOTICE="Säkerhetstecknen matchar inte. Begäran har avbrutits för att förhindra säkerhetsöverträdelser. Försök igen." JNEXT="Nästa" -JNO="Nej" +JNO="Aldrig" JNOTICE="Observera" JOFF="Av" JON="På" @@ -263,7 +262,7 @@ JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER="%1$s: Sökvägen är inte en mapp. S JLIB_FORM_FIELD_INVALID="Ogiltigt fält: " JLIB_FORM_VALIDATE_FIELD_INVALID="Ogiltigt fält: %s" JLIB_FORM_VALIDATE_FIELD_REQUIRED="Fältet krävs: %s" -JLIB_INSTALLER_ABORT="Stoppar språkinstallationen: %s" +JLIB_INSTALLER_ABORT="Avbryter språkinstallation: %s" JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="Tillägg %1$s: Kan inte skapa mapp: %2$s" JLIB_INSTALLER_ABORT_NOINSTALLPATH="Installationssökvägen finns inte" JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="Paket %1$s: Det uppstod ett fel när tillägget %2$s installerades." @@ -304,7 +303,7 @@ NOTICE="Observera" WARNING="Varning" ; Javascript ajax error messages -JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="Ett anslutningsfel uppstod vid hämtningen av JSON-data." +JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="En anslutning avbröts när JSON-data hämtades." JLIB_JS_AJAX_ERROR_NO_CONTENT="Inget innehåll har returnerats." JLIB_JS_AJAX_ERROR_OTHER="Ett fel uppstod när JSON-data hämtades: HTTP %d statuskod." JLIB_JS_AJAX_ERROR_PARSE="Ett parsningsfel har uppstått medan följande JSON-data behandlades:
%s" diff --git a/installation/language/sv-SE/langmetadata.xml b/installation/language/sv-SE/langmetadata.xml index 505b0d9ee0c26..61c6cc239203b 100644 --- a/installation/language/sv-SE/langmetadata.xml +++ b/installation/language/sv-SE/langmetadata.xml @@ -1,7 +1,7 @@ Swedish (Sweden) - 5.4.8 + 6.1.3 2026-07 Swedish Translation Team - SvenskJoomla (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ta-IN/joomla.ini b/installation/language/ta-IN/joomla.ini index 2f40c76297964..973ea3dc562af 100644 --- a/installation/language/ta-IN/joomla.ini +++ b/installation/language/ta-IN/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Joomla-வின் இந்தப் பதிப் BUILD_MIN_PHP_ERROR_URL_TEXT="இதனைத் தீர்க்க எனக்கு உதவுக" ; Main Config +INSTL_CHANGE_INSTALL_LANG="நிறுவல் மொழி மாற்றுக" +INSTL_CHANGE_INSTALL_LANG_SHORT="மாற்றுக" +INSTL_SELECTED_INSTALL_LANGUAGE="தற்போதைய மொழி: %s" INSTL_SELECT_INSTALL_LANG="நிறுவல் மொழித் தேர்வு" INSTL_SELECT_LANGUAGE_TITLE="மொழி தேர்வுசெய்யவும்" INSTL_SETUP_LOGIN_DATA="உள்நுழைவு தரவு அமைத்தல்" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Joomla-வை நிறுவுவதற்கு, தங்க INSTL_DATABASE_SUPPORT="தரவுத்தள ஆதரவு:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Support" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is Default" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="ஆதரிக்கப்படும் தரவுத்தளங்கள் (databases) எதுவும் காணப்படவில்லை." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Joomla-வை நிறுவுவதற்கு, தங்கள் PHP நிறுவலில் JSON ஆனது இயலுமைப்படுத்தப்பட்டிருக்க வேண்டும்!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language நடு நிலையாக (neutral) அமைக்கப்படவில்லை. இதனைத் தங்கள் தளத்தில் php_value mbstring.language neutral என்ற சொற்றொடரைத் தங்கள் .htaccess கோப்பில் எழுதுவதின் மூலம் உள்ளகத்தில் அமைக்க (locally set) முடியும்." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload அமைக்கப்பட்டுள்ளது. இதனைத் தங்கள் தளத்தில் php_value mbstring.func_overload 0 என்ற சொற்றொடரைத் தங்கள் .htaccess கோப்பில் எழுதுவதின் மூலம் உள்ளகத்தில் நிறுத்த முடியும் (turned off locally)." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="தங்கள் சேவையகத்தில், தேவையான php செயற்பாடுகள் parse_ini_file மற்றும் parse_ini_string ஆகியவை முடக்கப்பட்டுள்ளன." INSTL_NOTICE_XML_SUPPORT="XML Support இல்லை. இதனை இயல்புநிலையாக php-இல் இயலுமைப்படுத்தப்பட வேண்டும். ஆனால், Ubuntu பயனாளர்கள் இதனை sudo apt-get install php-xml என்ற குறியீட்டைச் செயற்படுத்தி, அதன் பின் சேவையகத்தை மறுதொடக்கம் செய்து நிறுவ வேண்டியிருக்கலாம்." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib compression அமைக்கப்படவில்லை. இதனைத் தங்கள் தளத்தில் zlib.output_compression = On என்ற சொற்றொடரைத் தங்கள் php.ini கோப்பில் எழுதுவதின் மூலம் அமைக்க (locally set) முடியும்." diff --git a/installation/language/ta-IN/langmetadata.xml b/installation/language/ta-IN/langmetadata.xml index daaf5e6a3d4c0..00b644c75072e 100644 --- a/installation/language/ta-IN/langmetadata.xml +++ b/installation/language/ta-IN/langmetadata.xml @@ -1,7 +1,7 @@ Tamil (India) - 5.4.8 + 6.1.3 2026-07 Ilagnayeru 'MIG' Manickam, Elango Samy Manim (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/th-TH/joomla.ini b/installation/language/th-TH/joomla.ini index 52c55d633a5ca..ce963f7eee8d1 100644 --- a/installation/language/th-TH/joomla.ini +++ b/installation/language/th-TH/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="โฮสต์ของคุณต้องใช้ BUILD_MIN_PHP_ERROR_URL_TEXT="ช่วยฉันแก้ปัญหานี้" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="เปลี่ยนตำแหน่ง" INSTL_SELECT_INSTALL_LANG="เลือกภาษาที่ใช้ในการติดตั้ง" INSTL_SELECT_LANGUAGE_TITLE="เลือกภาษา" INSTL_SETUP_LOGIN_DATA="ตั้งค่าข้อมูลเข้าสู่ระบบ" @@ -42,13 +43,9 @@ INSTL_WARNJSON="คุณต้องเปิดการใช้งาน JSO INSTL_DATABASE_SUPPORT="รองรับฐานข้อมูล:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Support" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is Default" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="ไม่พบฐานข้อมูลที่รองรับ" INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="คุณต้องเปิดการใช้งาน JSON สำหรับการติดตั้งจูมล่า" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring ไม่ได้ถูกตั้งให้เป็นกลาง คุณสามารถตั้งในประเทศโดยการใส่ค่า php_value mbstring.language ให้เป็นกลาง ในไฟล์ .htaccess" -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring ฟังก์ชัน นี้สามารถปิดได้โดยการใส่ค่า php_value mbstring.func_overload 0 ในไฟล์ .htaccess" INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="จำเป็นที่จะต้องใช้ php ฟังก์ชัน parse_ini_file และ parse_ini_string แต่ถูกปิดการใช้งานบนเซิร์ฟเวอร์ของคุณ" INSTL_NOTICE_XML_SUPPORT="ไม่มีการสนับสนุน XML ควรเปิดใช้งานโดยค่าเริ่มต้นใน php แต่ผู้ใช้ Ubuntu อาจจำเป็นต้องติดตั้งสิ่งนี้โดยทำด้วยคำสั่ง sudo apt-get install php-xml แล้วรีสตาร์ทเว็บเซิร์ฟเวอร์" INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib compression ไม่ได้ตั้งค่า สามารถเปิดในเครื่องได้โดยกำหนดให้ zlib.output_compression = On ในไฟล์ php.ini ของคุณ" @@ -235,7 +232,7 @@ JGLOBAL_SELECT_NO_RESULTS_MATCH="ไม่มีผลลัพธ์" JGLOBAL_SELECT_SOME_OPTIONS="เลือกตัวเลือกบางตัว" JHIDEPASSWORD="ซ่อนรหัสผ่าน" JINVALID_TOKEN="คำขอล่าสุดถูกปฏิเสธเนื่องจากมีความปลอดภัยของโทเค็นที่ไม่ถูกต้อง โปรดรีเฟรชหน้าเว็บและลองอีกครั้ง" -JINVALID_TOKEN_NOTICE="โทเค็นความปลอดภัยไม่ตรงกัน คำขอถูกยกเลิกเพื่อป้องกันการละเมิดความปลอดภัย กรุณาลองอีกครั้ง" +JINVALID_TOKEN_NOTICE="โทเค็นการรักษาความปลอดภัยไม่ตรงกัน การร้องขอถูกยกเลิกเพื่อป้องกันการละเมิดความปลอดภัย โปรดลองอีกครั้ง" JNEXT="ต่อไป" JNO="ไม่" JNOTICE="แจ้งให้ทราบ" @@ -263,7 +260,7 @@ JLIB_INSTALLER_ABORT_CREATE_DIRECTORY="ส่วนเสริม %1$s: ไม JLIB_INSTALLER_ABORT_NOINSTALLPATH="ไม่มีพาทของการติดตั้ง" JLIB_INSTALLER_ABORT_PACK_INSTALL_ERROR_EXTENSION="แพ็กเกจ %1$s: เกิดข้อผิดพลาดในการติดตั้งส่วนเสริม: %2$s" JLIB_INSTALLER_ABORT_PACK_INSTALL_NO_FILES="แพ็กเกจ %s: ไม่มีไฟล์ให้ติดตั้ง!" -JLIB_INSTALLER_ERROR_DOWNLOAD_SERVER_CONNECT="เกิดข้อผิดพลาดในการเชื่อมต่อกับเซิร์ฟเวอร์: %s" +JLIB_INSTALLER_ERROR_DOWNLOAD_SERVER_CONNECT="Error connecting to the server: %s" JLIB_INSTALLER_ERROR_FAIL_COPY_FILE="JInstaller: :Install: การคัดลอกไฟล์ล้มเหลวจาก %1$s ไปยัง %2$s" JLIB_INSTALLER_INSTALL="ติดตั้ง" JLIB_INSTALLER_NOT_ERROR="หากมีข้อผิดที่เกี่ยวข้องกับการติดตั้งไฟล์ภาษาของ TinyMCE ซึ่งจะไม่มีผลกระทบต่อการติดตั้งของไฟล์ภาษา เพราะบางแพ็คเกจภาษาถูกสร้างขึ้นก่อนที่จะมี Joomla 3.2.0 อาจเป็นเพราะพยายามที่จะติดตั้งไฟล์ภาษาของ TinyMCE แยกต่างหาก ซึ่งตอนนี้ได้ถูกรวมอยู่ในคอร์หลักนี้แล้ว โดยที่ไม่จำเป็นต้องมีการติดตั้งตามลงไป" @@ -300,10 +297,10 @@ WARNING="คำเตือน" ; Javascript ajax error messages JLIB_JS_AJAX_ERROR_CONNECTION_ABORT="เกิดข้อผิดพลาดในการเชื่อมต่อขณะดึงข้อมูล JSON" -JLIB_JS_AJAX_ERROR_NO_CONTENT="ไม่มีการส่งคืนเนื้อหา" +JLIB_JS_AJAX_ERROR_NO_CONTENT="No content was returned." JLIB_JS_AJAX_ERROR_OTHER="เกิดข้อผิดพลาดขณะดึงข้อมูล JSON: รหัสสถานะ HTTP %d" JLIB_JS_AJAX_ERROR_PARSE="เกิดข้อผิดพลาดในการแยกวิเคราะห์ขณะประมวลผลข้อมูล JSON ต่อไปนี้:
%s" -JLIB_JS_AJAX_ERROR_TIMEOUT="เกิดหมดเวลาขึ้นขณะดึงข้อมูล JSON" +JLIB_JS_AJAX_ERROR_TIMEOUT="A timeout has occurred while fetching the JSON data." ; Field password messages JFIELD_PASSWORD_INDICATE_COMPLETE="รหัสผ่านได้รับการยอมรับ" diff --git a/installation/language/th-TH/langmetadata.xml b/installation/language/th-TH/langmetadata.xml index e4540002a93cc..4d71a0e8bb1d8 100644 --- a/installation/language/th-TH/langmetadata.xml +++ b/installation/language/th-TH/langmetadata.xml @@ -1,7 +1,7 @@ Thai (ภาษาไทย) - 5.4.8 + 6.1.3 2026-07 Thai Translation Team (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/tr-TR/joomla.cli.ini b/installation/language/tr-TR/joomla.cli.ini index f8653b506a504..1472db9f4828d 100644 --- a/installation/language/tr-TR/joomla.cli.ini +++ b/installation/language/tr-TR/joomla.cli.ini @@ -3,7 +3,7 @@ INSTL_ADMIN_EMAIL_DESC_SHORT="Web sitesinin Süper Kullanıcı hesabının e-pos INSTL_ADMIN_PASSWORD_DESC="Süper Kullanıcı hesabınız için şifre belirleyin" INSTL_ADMIN_PASSWORD_DESC_SHORT="Süper Kullanıcı hesabınızın şifresi" INSTL_ADMIN_USERNAME_DESC="Süper Kullanıcı hesabınız için kullanıcı adını belirleyin" -INSTL_ADMIN_USERNAME_DESC_SHORT="Süper Kullanıcı hesabınızın şifresi" +INSTL_ADMIN_USERNAME_DESC_SHORT="Süper Kullanıcı hesabınızın kullanıcı adı" INSTL_ADMIN_USER_DESC="Süper Kullanıcınızın gerçek adını girin" INSTL_ADMIN_USER_DESC_SHORT="Süper Kullanıcı hesabının gerçek adı" INSTL_DATABASE_COULD_NOT_CONNECT="%s" @@ -12,7 +12,7 @@ INSTL_DATABASE_ENCRYPTION_CA_LABEL_SHORT="Şifrelemeyi doğrulamak için kullan INSTL_DATABASE_ENCRYPTION_CERT_LABEL="Veritabanı bağlantısı için SSL sertifikası dosyasının yolu. Şifreleme değerinin 2 olması gerekir" INSTL_DATABASE_ENCRYPTION_CERT_LABEL_SHORT="Veritabanı bağlantısı için SSL sertifikasının yolu. Şifrelemenin 2 olarak ayarlanması gerekir" INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL="Desteklenen Şifreleme Yöntemleri (isteğe baglı)" -INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Desteklenen Şifreleme Yöntemi (isteğe bağlı)" +INSTL_DATABASE_ENCRYPTION_CIPHER_LABEL_SHORT="Desteklenen Şifreleme Yöntemleri (isteğe baglı)" INSTL_DATABASE_ENCRYPTION_KEY_LABEL="Veritabanı bağlantısı için SSL anahtarı. Şifrelemenin 2 olarak ayarlanması gerekir" INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="Veritabanı bağlantısı için SSL anahtarı. Şifrelemenin 2 olarak ayarlanması gerekir" INSTL_DATABASE_ENCRYPTION_MODE_LABEL="Veritabanı bağlantısında kullanılacak şifreleme türü. Değerler: 0=Şifreleme yok, 1=Tek yönlü şifreleme, 2=Çift yönlü şifreleme" diff --git a/installation/language/tr-TR/joomla.ini b/installation/language/tr-TR/joomla.ini index 6f275648253df..d95a9134748ec 100644 --- a/installation/language/tr-TR/joomla.ini +++ b/installation/language/tr-TR/joomla.ini @@ -32,6 +32,9 @@ BUILD_MIN_PHP_ERROR_TEXT="Joomla'nın bu sürümünü çalıştırmak için sunu BUILD_MIN_PHP_ERROR_URL_TEXT="Bunu çözmeme yardım et" ; Main Config +INSTL_CHANGE_INSTALL_LANG="Kurulum Dilini Değiştir" +INSTL_CHANGE_INSTALL_LANG_SHORT="Değişiklikler" +INSTL_SELECTED_INSTALL_LANGUAGE="Mevcut dil: %s" INSTL_SELECT_INSTALL_LANG="Kurulum Dilini Seçin" INSTL_SELECT_LANGUAGE_TITLE="Dil Seçin" INSTL_SETUP_LOGIN_DATA="Oturum Açma Verilerini Ayarla" @@ -42,13 +45,9 @@ INSTL_WARNJSON="Joomla kurulabilmesi için PHP kurulumunuzda JSON'un etkinleşti INSTL_DATABASE_SUPPORT="Veritabanı Desteği:" INSTL_JSON_SUPPORT_AVAILABLE="JSON Desteği" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Dili Varsayılandır" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MBString Aşırı Yük Kapalı" INSTL_NOTICE_DATABASE_SUPPORT="Desteklenen veritabanları bulunamadı." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Joomla kurulabilmesi için PHP kurulumunuzda JSON'un etkinleştirilmesi gerekir!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring dili nötr olarak ayarlanmadı. Bu, .htaccess dosyanıza php_value mbstring.language nötr girilerek yerel olarak ayarlanabilir." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring işlevi aşırı yüklemesi ayarlandı. Bu, .htaccess dosyanıza php_value mbstring.func_overload 0 girilerek yerel olarak kapatılabilir." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Gerekli php işlevleri parse_ini_file ve parse_ini_string sunucunuzda devre dışı bırakıldı." INSTL_NOTICE_XML_SUPPORT="XML Desteği mevcut değil. Bu, php'de varsayılan olarak etkinleştirilmelidir, ancak Ubuntu kullanıcılarının bunu sudo apt-get install php-xml yaparak ve ardından web sunucusunu yeniden başlatarak yüklemeleri gerekebilir." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib sıkıştırması ayarlanmadı. Bu, php.ini dosyanıza zlib.output_compression = On yazılarak yerel olarak açılabilir." @@ -229,7 +228,7 @@ INSTL_ZIP_SUPPORT_AVAILABLE="Yerel ZIP desteği" ; Global strings JADMINISTRATOR="Yönetici" -JCLOSE="Kapalı" +JCLOSE="Kapat" JEMAIL="E-posta" JERROR="Hata" JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="İsteğiniz işlenirken bir hata oluştu." diff --git a/installation/language/tr-TR/langmetadata.xml b/installation/language/tr-TR/langmetadata.xml index 3de022c75e1dc..f35028c57f82a 100644 --- a/installation/language/tr-TR/langmetadata.xml +++ b/installation/language/tr-TR/langmetadata.xml @@ -1,7 +1,7 @@ Turkish (Turkey) - 5.4.8 + 6.1.3 2026-07 Joomla! Türkiye (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/uk-UA/joomla.ini b/installation/language/uk-UA/joomla.ini index 926fef283080b..b3d86622c2280 100644 --- a/installation/language/uk-UA/joomla.ini +++ b/installation/language/uk-UA/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Ваш хост повинен використову BUILD_MIN_PHP_ERROR_URL_TEXT="Допоможіть мені це вирішити" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Змінити" INSTL_SELECT_INSTALL_LANG="Оберіть мову встановлення" INSTL_SELECT_LANGUAGE_TITLE="Обрати мову" INSTL_SETUP_LOGIN_DATA="Налаштування даних для входу" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Налаштування PHP повинні підтримува INSTL_DATABASE_SUPPORT="Підтримка база даних:" INSTL_JSON_SUPPORT_AVAILABLE="Підтримка JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language за налаштуванням" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload вимкнено" INSTL_NOTICE_DATABASE_SUPPORT="Не знайдено підтримуваних баз даних." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Налаштування PHP повинні підтримувати бібліотеку JSON для подальшого встановлення Joomla!" INSTL_NOTICE_MBLANG_NOTDEFAULT="Функція мови PHP mbstring (mbstring.language) не встановлено у нейтральне положення. Ви можете задати цей параметр локально, прописавши php_value mbstring.language neutral у вашому файлі .htaccess." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Функція перезавантаження PHP mbstring (mbstring.func_overload) встановлена. Ви можете вимкнути цей параметр локально, прописавши php_value mbstring.func_overload 0 у вашому файлі .htaccess." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Необхідні PHP-функції parse_ini_file та parse_ini_string вимкнені на вашому сервері." INSTL_NOTICE_XML_SUPPORT="Підтримка XML недоступна. Вона повинна бути ввімкненою за налаштуванням, але користувачам Ubuntu необхідно встановити її через термінал на сервері за допомогою команди sudo apt-get install php-xml. Це призведе до повторного старту сервера." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Компресія Zlib не встановлена. Для ввімкнення цього параметри необхідно у файлі php.ini розкоментувати або додати значення zlib.output_compression = On." diff --git a/installation/language/uk-UA/langmetadata.xml b/installation/language/uk-UA/langmetadata.xml index a9caa02a6195c..b194b75cce4c3 100644 --- a/installation/language/uk-UA/langmetadata.xml +++ b/installation/language/uk-UA/langmetadata.xml @@ -1,7 +1,7 @@ Ukrainian (uk-UA) - 5.4.8 + 6.1.3 2026-07 Denys Nosov (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/ur-PK/joomla.ini b/installation/language/ur-PK/joomla.ini index 42dd036406102..b2458d4356788 100644 --- a/installation/language/ur-PK/joomla.ini +++ b/installation/language/ur-PK/joomla.ini @@ -5,10 +5,10 @@ ; Fatal error page ; These will be processed by the JavaScript Build -BUILD_FATAL_HEADER="معاف کیجیے گا، ایک مسئلہ تھا جس سے ہم بازیاب نہ ہو سکے." +BUILD_FATAL_HEADER="معاف کیجیے گا، ایک مسئلہ تھا جس سے ہم بازیاب نہ ہو سکے۔" BUILD_FATAL_LANGUAGE="انگریزی جی-بی" ; IMPORTANT NOTE FOR TRANSLATORS: Do not literally translate this line, instead add the localised name of the language. For example French will be Français FR BUILD_FATAL_TEXT="سرور نے \"{{statusCode_statusText}}\" لوٹایا" -BUILD_FATAL_URL_TEXT="اس کو حل کرنے میں میری مدد کریں." +BUILD_FATAL_URL_TEXT="اس کو حل کرنے میں میری مدد کریں۔" ; Build incomplete error page ; These will be processed by the JavaScript Build @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="جملہ کے اس ورژن کو چلانے کے لی BUILD_MIN_PHP_ERROR_URL_TEXT="اس کو حل کرنے میں میری مدد کریں۔" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="تبدیلیاں" INSTL_SELECT_INSTALL_LANG="انسٹالیشن کی زبان منتخب کریں۔" INSTL_SELECT_LANGUAGE_TITLE="زبان منتخب کریں۔" INSTL_SETUP_LOGIN_DATA="لاگ ان ڈیٹا سیٹ کریں۔" @@ -42,13 +43,9 @@ INSTL_WARNJSON="جملہ کو انسٹال کرنے کے لیے آپ کی پی INSTL_DATABASE_SUPPORT="ڈیٹا بیس سپورٹ:" INSTL_JSON_SUPPORT_AVAILABLE="JSON سپورٹ" INSTL_MB_LANGUAGE_IS_DEFAULT="MB زبان پہلے سے طے شدہ ہے۔" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="ایم بی سٹرنگ اوورلوڈ آف" INSTL_NOTICE_DATABASE_SUPPORT="کوئی معاون ڈیٹا بیس نہیں ملا۔" INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="جملہ کو انسٹال کرنے کے لیے آپ کی پی ایچ پی کی انسٹالیشن میں JSON کا فعال ہونا ضروری ہے!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring زبان غیر جانبدار پر سیٹ نہیں ہے۔ اسے اپنی .htaccess فائل میں php_value mbstring.language neutral درج کرکے مقامی طور پر سیٹ کیا جاسکتا ہے۔." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring فنکشن اوورلوڈ سیٹ ہے۔ اسے اپنی .htaccess فائل میں php_value mbstring.func_overload 0 درج کرکے مقامی طور پر بند کیا جاسکتا ہے۔." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="مطلوبہ php فنکشنز parse_ini_file اور parse_ini_string آپ کے سرور پر غیر فعال ہیں۔" INSTL_NOTICE_XML_SUPPORT="XML سپورٹ دستیاب نہیں ہے۔ اسے php میں بطور ڈیفالٹ فعال ہونا چاہیے لیکن Ubuntu کے صارفین کو اسے sudo apt-get install php-xml کرکے انسٹال کرنے کی ضرورت پڑسکتی ہے جس کے بعد ویب سرور دوبارہ شروع ہوتا ہے۔" INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib کمپریشن سیٹ نہیں ہے۔ اسے اپنی php.ini فائل میں zlib.output_compression = On درج کرکے مقامی طور پر آن کیا جاسکتا ہے۔" diff --git a/installation/language/ur-PK/langmetadata.xml b/installation/language/ur-PK/langmetadata.xml index 4d23f9a3ee89b..efd049d158560 100644 --- a/installation/language/ur-PK/langmetadata.xml +++ b/installation/language/ur-PK/langmetadata.xml @@ -1,7 +1,7 @@ Urdu (ur-PK) - 5.4.8 + 6.1.3 2026-07 Urdu Translation Team (C) 2005 Open Source Matters, Inc. @@ -10,7 +10,7 @@ joomla.ini - Urdu (ur-PK) + انگریزی (برطانیہ) ur-PK 1 diff --git a/installation/language/vi-VN/joomla.ini b/installation/language/vi-VN/joomla.ini index 6cb4ea95eaa1f..de15e58c49295 100644 --- a/installation/language/vi-VN/joomla.ini +++ b/installation/language/vi-VN/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="Máy chủ của bạn cần sử dụng PHP phiên b BUILD_MIN_PHP_ERROR_URL_TEXT="Giúp tôi giải quyết vấn đề này" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="Thay đổi vị trí" INSTL_SELECT_INSTALL_LANG="Chọn ngôn ngữ cài đặt" INSTL_SELECT_LANGUAGE_TITLE="Chọn ngôn ngữ" INSTL_SETUP_LOGIN_DATA="Thiết lập dữ liệu đăng nhập" @@ -42,13 +43,9 @@ INSTL_WARNJSON="Hệ thống PHP của bạn cần có JSON được kích hoạ INSTL_DATABASE_SUPPORT="Hỗ trợ cơ sở dữ liệu:" INSTL_JSON_SUPPORT_AVAILABLE="Hỗ trợ JSON" INSTL_MB_LANGUAGE_IS_DEFAULT="MB language là mặc định" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String overload tắt" INSTL_NOTICE_DATABASE_SUPPORT="Không có cơ sở dữ liệu được hỗ trợ nào được tìm thấy." INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="Hệ thống PHP của bạn cần có JSON được kích hoạt để cài đặt Joomla!" INSTL_NOTICE_MBLANG_NOTDEFAULT="Ngôn ngữ PHP mbstring không được để thành neutral. Có thể thiết lập cục bộ bằng cách điềnphp_value mbstring.language neutral vào tập tin .htaccess của bạn." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="Chức năng PHP mbstring overload đang được thiết lập. Có thể tắt cục bộ bằng cách điền php_value mbstring.func_overload 0 vào tập tin .htaccess của bạn." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="Các hàm php bắt buộc parse_ini_file và parse_ini_string đã bị tắt trên máy chủ của bạn." INSTL_NOTICE_XML_SUPPORT="Hỗ trợ XML không khả dụng. Điều này sẽ được bật theo mặc định trong php nhưng người dùng Ubuntu có thể cần phải cài đặt điều này bằng cách thực hiện sudo apt-get install php-xml sau đó khởi động lại máy chủ web." INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib compression không được thiết lập. Điều này có thể được bật cục bộ bằng cách nhập zlib.output_compression = On trong tệp php.ini của bạn." diff --git a/installation/language/vi-VN/langmetadata.xml b/installation/language/vi-VN/langmetadata.xml index c6a5be31cd175..c58c4272bbac1 100644 --- a/installation/language/vi-VN/langmetadata.xml +++ b/installation/language/vi-VN/langmetadata.xml @@ -1,7 +1,7 @@ Vietnamese (Vietnam) - 5.4.8 + 6.1.3 2026-07 Joomla! Project (C) 2005 Open Source Matters, Inc. diff --git a/installation/language/zh-CN/joomla.ini b/installation/language/zh-CN/joomla.ini index a5df6dd0a2e34..8728115ec6b7c 100644 --- a/installation/language/zh-CN/joomla.ini +++ b/installation/language/zh-CN/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="需要 PHP {{phpversion}} 或更新的版本运行" BUILD_MIN_PHP_ERROR_URL_TEXT="帮助我解决这个问题" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="更换" INSTL_SELECT_INSTALL_LANG="选择安装语言" INSTL_SELECT_LANGUAGE_TITLE="选择安装语言" INSTL_SETUP_LOGIN_DATA="设置登录信息" @@ -42,13 +43,9 @@ INSTL_WARNJSON="PHP 需要启用 JSON 才能安装!" INSTL_DATABASE_SUPPORT="数据库支持:" INSTL_JSON_SUPPORT_AVAILABLE="JSON 支持并启用" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language 设置为默认" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload 关闭" INSTL_NOTICE_DATABASE_SUPPORT="没有找到支持的数据库" INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="PHP 需要启用 JSON 才能安装!" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring 的当前设置不是 neutral 可以通过在网站根目录下的 .htaccess 文件中加入 php_value mbstring.language neutral 修改此设置" -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring Overload 设置为启用。可以童哥在网站根目录下的 .htaccess 文件中加入 php_value mbstring.func_overload 0 修改此设置" INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="所需的 PHP 函数parse_ini_file和 parse_ini_string 在服务器上已关闭。" INSTL_NOTICE_XML_SUPPORT="XML 支持不可用。这个功能在 PHP 中应该是默认启用,但 Ubuntu 用户可能需要通过sudo apt-get install php-xml安装这个功能,然后重新启动 WEB 服务器。" INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="没有设置 Zlib 压缩。可以在你的 php.ini 文件中输入 zlib.output_compression = On 打开。" @@ -92,7 +89,7 @@ INSTL_DATABASE_NAME_MSG_POSTGRES="数据库名无效。它必须以字母开头 INSTL_DATABASE_NO_SCHEMA="该数据库类型不存在数据库模式" INSTL_DATABASE_PASSWORD_DESC="请输入数据库密码" INSTL_DATABASE_PREFIX_DESC="输入表前缀或使用随机生成的表前缀" -INSTL_DATABASE_PREFIX_DUPLICATE_DESC="如果您正在使用一个带有相同前缀的表格的现有数据库,Joomla将通过添加前缀\"bak_\"重命名这些现有表格。" +INSTL_DATABASE_PREFIX_DUPLICATE_DESC="如果您正在使用的数据库中已经存在带有相同前缀的数据表,Joomla将通过添加前缀\"bak_\"重命名这些重名的数据表。" INSTL_DATABASE_RESPONSE_ERROR="安装过程失败" INSTL_DATABASE_TYPE_DESC="选择数据库类型" INSTL_DATABASE_USER_DESC="请输入数据库用户名" @@ -118,7 +115,7 @@ INSTL_PUBLIC_FOLDER_DESC="公共文件夹的相对路径或绝对路径" INSTL_PUBLIC_FOLDER_DESC_SHORT="公共文件夹的相对路径或绝对路径" ; Complete view -INSTL_COMPLETE_ADD_EXTRA_LANGUAGE="安装本地化语言包(zh-CN为简体中文)" +INSTL_COMPLETE_ADD_EXTRA_LANGUAGE="安装其它语言" INSTL_COMPLETE_ADMIN_BTN="完成并打开后台" INSTL_COMPLETE_CONGRAT="恭喜!" INSTL_COMPLETE_ERROR_FOLDER_DELETE="无法删除 \"%s\" 目录。请手动删除该文件夹。" @@ -130,7 +127,7 @@ INSTL_COMPLETE_TITLE="网站安装成功。" INSTL_REMOVE_INST_FOLDER="你确定要删除吗? 确认 将永久删除 \"%s\"文件夹。" ; Languages view -INSTL_LANGUAGES="安装本地化语言包" +INSTL_LANGUAGES="安装其它语言" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE="语言" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_SELECT="选择安装语言" INSTL_LANGUAGES_COLUMN_HEADER_LANGUAGE_TAG="语言标签" @@ -216,13 +213,13 @@ INSTL_NOTICE_NEEDSTOBEWRITABLE="如果你修复了权限或者提供了 FTP 连 INSTL_OUTPUT_BUFFERING="输出缓冲(Output Buffering)" INSTL_PHP_VERSION="PHP 版本" INSTL_PHP_VERSION_NEWER="PHP 版本 >= %s" -INSTL_PROCESS_BUSY="安装正在进行,请稍候……" +INSTL_PROCESS_BUSY="进程中。请等待 ..." INSTL_SESSION_AUTO_START="会话自启动(Session Auto Start)" INSTL_WRITABLE="没有足够的权限创建 %s" INSTL_ZIP_SUPPORT_AVAILABLE="Native ZIP 支持并启用" ; Global strings -JADMINISTRATOR="管理员" +JADMINISTRATOR="管理员激活" JCLOSE="关闭" JEMAIL="邮件" JERROR="错误" diff --git a/installation/language/zh-CN/langmetadata.xml b/installation/language/zh-CN/langmetadata.xml index 810c048df9c02..29d7ca0b1994f 100644 --- a/installation/language/zh-CN/langmetadata.xml +++ b/installation/language/zh-CN/langmetadata.xml @@ -1,17 +1,17 @@ Chinese Simplified (China) - 5.4.8 + 6.1.3 2026-07 - Joomla中文网 + Joomla中文网 (C) 2005 Open Source Matters, Inc. GNU General Public License version 2 or later; see LICENSE.txt joomla.ini - 简体中文(zh-CN) - 简体中文 (中国) + Chinese Simplified (zh-CN) + Chinese Simplified (China) zh-CN 0 diff --git a/installation/language/zh-TW/joomla.cli.ini b/installation/language/zh-TW/joomla.cli.ini index 912fc56724137..a7d7ee12bc1e8 100644 --- a/installation/language/zh-TW/joomla.cli.ini +++ b/installation/language/zh-TW/joomla.cli.ini @@ -2,7 +2,7 @@ INSTL_ADMIN_EMAIL_DESC="輸入網站超級管理者的電子信箱" INSTL_ADMIN_EMAIL_DESC_SHORT="網站超級管理者帳號的電子信箱" INSTL_ADMIN_PASSWORD_DESC="設定超級管理員的密碼" INSTL_ADMIN_PASSWORD_DESC_SHORT="超級使用者帳號的密碼" -INSTL_ADMIN_USERNAME_DESC="設定超級管理員的帳號名稱" +INSTL_ADMIN_USERNAME_DESC="設定超級管理員的帳號" INSTL_ADMIN_USERNAME_DESC_SHORT="超級使用者的帳號名稱" INSTL_ADMIN_USER_DESC="請填寫超級管理者的真實姓名" INSTL_ADMIN_USER_DESC_SHORT="超級使用者的真實姓名" @@ -18,7 +18,7 @@ INSTL_DATABASE_ENCRYPTION_KEY_LABEL_SHORT="資料庫連線的SSL金鑰,加密 INSTL_DATABASE_ENCRYPTION_MODE_LABEL="資料庫連線的加密設定。 數值:0 = 無加密,1 = 單向加密,2 = 雙向加密" INSTL_DATABASE_ENCRYPTION_MODE_LABEL_SHORT="資料庫連線的加密設定。 數值:0 = 無加密,1 = 單向加密,2 = 雙向加密" INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL="驗證資料庫連線的 SSL 憑證。數值:0 = 否,1 = 是。此設定需要將 加密(Encryption) 設為 1 或 2 才會生效" -INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="驗證資料庫連線的 SSL 憑證。數值:0 = 否,1 = 是。此設定需要將 加密(Encryption) 設為 1 或 2 才會生效" +INSTL_DATABASE_ENCRYPTION_VERIFY_SERVER_CERT_LABEL_SHORT="驗證資料庫連線的 SSL 憑證。數值:0 = 否,1 = 是。此設定需要將 加密(Encryption) 設為 1 或 2 才會生效。" INSTL_DATABASE_HOST_DESC="資料庫主機" INSTL_DATABASE_HOST_DESC_SHORT="資料庫主機" INSTL_DATABASE_NAME_DESC="資料庫名稱" diff --git a/installation/language/zh-TW/joomla.ini b/installation/language/zh-TW/joomla.ini index 3641d850aa16c..8726314c123b0 100644 --- a/installation/language/zh-TW/joomla.ini +++ b/installation/language/zh-TW/joomla.ini @@ -32,6 +32,7 @@ BUILD_MIN_PHP_ERROR_TEXT="您的主機需要PHP版本{{phpversion}}或以上來 BUILD_MIN_PHP_ERROR_URL_TEXT="協助我解決這個問題" ; Main Config +INSTL_CHANGE_INSTALL_LANG_SHORT="變更" INSTL_SELECT_INSTALL_LANG="選擇安裝語言" INSTL_SELECT_LANGUAGE_TITLE="選擇語言" INSTL_SETUP_LOGIN_DATA="設定登入資訊" @@ -42,13 +43,9 @@ INSTL_WARNJSON="你的PHP環境需要啟用JSON支援才能進行Joomla!安裝" INSTL_DATABASE_SUPPORT="支援的資料庫:" INSTL_JSON_SUPPORT_AVAILABLE="JSON 支援" INSTL_MB_LANGUAGE_IS_DEFAULT="MB Language is Default" -; Deprecated, will be removed with 6.0 -INSTL_MB_STRING_OVERLOAD_OFF="MB String Overload Off" INSTL_NOTICE_DATABASE_SUPPORT="找不到被支援的資料庫" INSTL_NOTICE_JSON_SUPPORT_AVAILABLE="你的PHP環境需要啟用JSON支援才能進行Joomla!安裝" INSTL_NOTICE_MBLANG_NOTDEFAULT="PHP mbstring language is not set to neutral. This can be set locally by entering php_value mbstring.language neutral in your .htaccess file." -; Deprecated, will be removed with 6.0 -INSTL_NOTICE_MBSTRING_OVERLOAD_OFF="PHP mbstring function overload is set. This can be turned off locally by entering php_value mbstring.func_overload 0 in your .htaccess file." INSTL_NOTICE_PARSE_INI_FILE_AVAILABLE="所需的 php 函式 parse_ini_file 及 parse_ini_string 在你的伺服器是停用的。" INSTL_NOTICE_XML_SUPPORT="XML 支援不可用,PHP 的預設應為啟動但 Ubuntu 系統使用者也許需透過 sudo apt-get install php-xml 並重新啟動 Web 伺服器。" INSTL_NOTICE_ZLIB_COMPRESSION_SUPPORT="Zlib 壓縮功能未設置,在你的 php.ini 檔案中透過輸入 zlib.output_compression = On 啟動。" @@ -74,7 +71,7 @@ INSTL_DATABASE_ENCRYPTION_MODE_VALUE_NONE="預設(伺服器控制)" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_ONE_WAY="One-way authentication" INSTL_DATABASE_ENCRYPTION_MODE_VALUE_TWO_WAY="Two-way authentication" INSTL_DATABASE_ENCRYPTION_MSG_CONN_NOT_ENCRYPT="你已選擇使用資料庫連線加密,連線已確立但未加密。這可能是因為資料庫因錯誤加密參數而倒回未加密連線配置,逐個檢查並修正資料庫加密參數,或變更欄位 \"連線加密\" 退回 \"預設 (伺服器控制)\"." -INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="欄位 \"%s\" 中輸入的檔案不存在或無法存取" +INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_BAD="The file entered in field \"%s\" does not exist or is not accessible." INSTL_DATABASE_ENCRYPTION_MSG_FILE_FIELD_EMPTY="欄位 \"%s\" is empty or doesn't contain a valid path." INSTL_DATABASE_ENCRYPTION_MSG_LOCALHOST="You have entered \"localhost\" as host name. Connecting to the database with connection encryption might fail with this. Either change \"localhost\" to \"127.0.0.1\" or \"::1\" or a different host name, or change field \"Connection Encryption\" back to \"預設(server controlled)\"." INSTL_DATABASE_ENCRYPTION_MSG_SRV_NOT_SUPPORTS="The database server doesn't support connection encryption. Either enable TLS (often called SSL in docs) support on your database server, or change field \"Connection Encryption\" back to \"預設(server controlled)\"." diff --git a/installation/language/zh-TW/langmetadata.xml b/installation/language/zh-TW/langmetadata.xml index 1e7b4d5293f91..a7a97fb788f57 100644 --- a/installation/language/zh-TW/langmetadata.xml +++ b/installation/language/zh-TW/langmetadata.xml @@ -1,7 +1,7 @@ 正體中文 - 5.4.8 + 6.1.3 2026-07 正體中文 Translation Team (C) 2005 Open Source Matters, Inc. diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index 5a3b514606ed1..61180d9da653b 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -175,7 +175,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'com_newsfeeds', 'component', 'com_newsfeeds', '', 1, 1, 1, 0, 1, '', '{"newsfeed_layout":"_:default","save_history":"1","history_limit":5,"show_feed_image":"1","show_feed_description":"1","show_item_description":"1","feed_character_count":"0","feed_display_order":"des","float_first":"right","float_second":"right","show_tags":"1","category_layout":"_:default","show_category_title":"1","show_description":"1","show_description_image":"1","maxLevel":"-1","show_empty_categories":"0","show_subcat_desc":"1","show_cat_items":"1","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_items_cat":"1","filter_field":"1","show_pagination_limit":"1","show_headings":"1","show_articles":"0","show_link":"1","show_pagination":"1","show_pagination_results":"1","sef_ids":1}', ''), (0, 'com_plugins', 'component', 'com_plugins', '', 1, 1, 1, 1, 1, '', '', ''), (0, 'com_templates', 'component', 'com_templates', '', 1, 1, 1, 1, 1, '', '{"template_positions_display":"0","upload_limit":"10","image_formats":"gif,bmp,jpg,jpeg,png,webp","source_formats":"txt,less,ini,xml,js,php,css,scss,sass,json","font_formats":"woff,woff2,ttf,otf","compressed_formats":"zip","difference":"SideBySide"}', ''), -(0, 'com_content', 'component', 'com_content', '', 1, 1, 0, 1, 1, '', '{"article_layout":"_:default","show_title":"1","link_titles":"1","show_intro":"1","info_block_position":"0","info_block_show_title":"1","show_category":"1","link_category":"1","show_parent_category":"0","link_parent_category":"0","show_associations":"0","flags":"1","show_author":"1","link_author":"0","show_create_date":"0","show_modify_date":"0","show_publish_date":"1","show_item_navigation":"1","show_readmore":"1","show_readmore_title":"1","readmore_limit":100,"show_tags":"1","record_hits":"1","show_hits":"1","show_noauth":"0","urls_position":0,"captcha":"","show_publishing_options":"1","show_article_options":"1","show_configure_edit_options":"1","show_permissions":"1","show_associations_edit":"1","save_history":"1","history_limit":10,"show_urls_images_frontend":"0","show_urls_images_backend":"1","targeta":0,"targetb":0,"targetc":0,"float_intro":"left","float_fulltext":"left","category_layout":"_:blog","show_category_title":"0","show_description":"0","show_description_image":"0","maxLevel":"1","show_empty_categories":"0","show_no_articles":"1","show_category_heading_title_text":"1","show_subcat_desc":"1","show_cat_num_articles":"0","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_num_articles_cat":"1","num_leading_articles":1,"blog_class_leading":"","num_intro_articles":4,"blog_class":"","num_columns":1,"multi_column_order":"0","num_links":4,"show_subcategory_content":"0","link_intro_image":"0","show_pagination_limit":"1","filter_field":"hide","show_headings":"1","list_show_date":"0","date_format":"","list_show_hits":"1","list_show_author":"1","display_num":"10","orderby_pri":"order","orderby_sec":"rdate","order_date":"published","show_pagination":"2","show_pagination_results":"1","show_featured":"show","show_feed_link":"1","feed_summary":"0","feed_show_readmore":"0","sef_ids":1,"custom_fields_enable":"1","workflow_enabled":"0"}', ''), +(0, 'com_content', 'component', 'com_content', '', 1, 1, 0, 1, 1, '', '{"article_layout":"_:default","show_title":"1","link_titles":"1","show_intro":"1","info_block_position":"0","info_block_show_title":"1","show_category":"1","link_category":"1","show_parent_category":"0","link_parent_category":"0","show_associations":"0","flags":"1","show_author":"1","link_author":"0","show_create_date":"0","show_modify_date":"0","show_publish_date":"1","show_item_navigation":"1","show_readmore":"1","show_readmore_title":"1","readmore_limit":100,"show_tags":"1","record_hits":"1","show_hits":"1","show_noauth":"0","urls_position":0,"captcha":"","show_publishing_options":"1","show_article_options":"1","show_configure_edit_options":"1","show_permissions":"1","show_associations_edit":"1","save_history":"1","history_limit":10,"show_urls_images_frontend":"0","show_urls_images_backend":"1","targeta":0,"targetb":0,"targetc":0,"float_intro":"left","float_fulltext":"left","category_layout":"_:blog","show_category_title":"0","show_description":"0","show_description_image":"0","maxLevel":"1","show_empty_categories":"0","show_no_articles":"1","show_category_heading_title_text":"1","show_subcat_desc":"1","show_subcat_image":"0","show_cat_num_articles":"0","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_num_articles_cat":"1","num_leading_articles":1,"blog_class_leading":"","num_intro_articles":4,"blog_class":"","num_columns":1,"multi_column_order":"0","num_links":4,"show_subcategory_content":"0","link_intro_image":"0","show_pagination_limit":"1","filter_field":"hide","show_headings":"1","list_show_date":"0","date_format":"","list_show_hits":"1","list_show_author":"1","display_num":"10","orderby_pri":"order","orderby_sec":"rdate","order_date":"published","show_pagination":"2","show_pagination_results":"1","show_featured":"show","show_feed_link":"1","feed_summary":"0","feed_show_readmore":"0","sef_ids":1,"custom_fields_enable":"1","workflow_enabled":"0"}', ''), (0, 'com_config', 'component', 'com_config', '', 1, 1, 0, 1, 1, '', '{"filters":{"1":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"9":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"6":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"7":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"2":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"3":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"4":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"5":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"8":{"filter_type":"NONE","filter_tags":"","filter_attributes":""}}}', ''), (0, 'com_redirect', 'component', 'com_redirect', '', 1, 1, 0, 0, 1, '', '', ''), (0, 'com_users', 'component', 'com_users', '', 1, 1, 0, 1, 1, '', '{"allowUserRegistration":"0","new_usertype":"2","guest_usergroup":"9","sendpassword":"0","useractivation":"2","mail_to_admin":"1","captcha":"","frontend_userparams":"1","site_language":"0","change_login_name":"0","reset_count":"10","reset_time":"1","minimum_length":"12","minimum_integers":"0","minimum_symbols":"0","minimum_uppercase":"0","save_history":"1","history_limit":5,"mailSubjectPrefix":"","mailBodySuffix":""}', ''), @@ -262,10 +262,10 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'plg_authentication_cookie', 'plugin', 'cookie', 'authentication', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_authentication_joomla', 'plugin', 'joomla', 'authentication', 0, 1, 1, 1, 1, '', '', '', 2, 0), (0, 'plg_authentication_ldap', 'plugin', 'ldap', 'authentication', 0, 0, 1, 0, 1, '', '{"host":"","port":"389","use_ldapV3":"0","negotiate_tls":"0","no_referrals":"0","auth_method":"bind","base_dn":"","search_string":"","users_dn":"","username":"admin","password":"bobby7","ldap_fullname":"fullName","ldap_email":"mail","ldap_uid":"uid"}', '', 3, 0), -(0, 'plg_behaviour_compat', 'plugin', 'compat', 'behaviour', 0, 1, 1, 0, 1, '', '{"classes_aliases":"1","es5_assets":"1"}', '', 1, 0), -(0, 'plg_behaviour_compat6', 'plugin', 'compat6', 'behaviour', 0, 1, 1, 0, 1, '', '{"classes_aliases":"1","legacy_classes":"1"}', '', 2, 0), -(0, 'plg_behaviour_taggable', 'plugin', 'taggable', 'behaviour', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), -(0, 'plg_behaviour_versionable', 'plugin', 'versionable', 'behaviour', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), +(0, 'plg_behaviour_compat6', 'plugin', 'compat6', 'behaviour', 0, 0, 1, 0, 1, '', '{"classes_aliases":"0","legacy_classes":"1"}', '', 1, 0), +(0, 'plg_behaviour_taggable', 'plugin', 'taggable', 'behaviour', 0, 1, 1, 0, 1, '', '{}', '', 2, 0), +(0, 'plg_behaviour_versionable', 'plugin', 'versionable', 'behaviour', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), +(0, 'plg_captcha_powcaptcha', 'plugin', 'powcaptcha', 'captcha', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_content_confirmconsent', 'plugin', 'confirmconsent', 'content', 0, 0, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_content_contact', 'plugin', 'contact', 'content', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_content_emailcloak', 'plugin', 'emailcloak', 'content', 0, 1, 1, 0, 1, '', '{"mode":"1"}', '', 3, 0), @@ -286,7 +286,7 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'plg_editors-xtd_readmore', 'plugin', 'readmore', 'editors-xtd', 0, 1, 1, 0, 1, '', '', '', 8, 0), (0, 'plg_editors_codemirror', 'plugin', 'codemirror', 'editors', 0, 1, 1, 0, 1, '', '{"lineNumbers":"1","lineWrapping":"1","matchTags":"1","matchBrackets":"1","marker-gutter":"1","autoCloseTags":"1","autoCloseBrackets":"1","autoFocus":"1","theme":"default","tabmode":"indent"}', '', 1, 0), (0, 'plg_editors_none', 'plugin', 'none', 'editors', 0, 1, 1, 1, 1, '', '', '', 2, 0), -(0, 'plg_editors_tinymce', 'plugin', 'tinymce', 'editors', 0, 1, 1, 0, 1, '', '{"configuration":{"toolbars":{"2":{"toolbar1":["bold","underline","strikethrough","|","undo","redo","|","bullist","numlist","|","pastetext"]},"1":{"menu":["edit","insert","view","format","table","tools"],"toolbar1":["bold","italic","underline","strikethrough","|","alignleft","aligncenter","alignright","alignjustify","|","blocks","|","bullist","numlist","|","outdent","indent","|","undo","redo","|","link","unlink","anchor","code","|","hr","table","|","subscript","superscript","|","charmap","pastetext","preview"]},"0":{"menu":["edit","insert","view","format","table","tools"],"toolbar1":["bold","italic","underline","strikethrough","|","alignleft","aligncenter","alignright","alignjustify","|","styles","|","blocks","fontfamily","fontsize","|","searchreplace","|","bullist","numlist","|","outdent","indent","|","undo","redo","|","link","unlink","anchor","image","|","code","|","forecolor","backcolor","|","fullscreen","|","table","|","subscript","superscript","|","charmap","emoticons","media","hr","ltr","rtl","|","cut","copy","paste","pastetext","|","visualchars","visualblocks","nonbreaking","blockquote","jtemplate","|","print","preview","codesample","insertdatetime","removeformat"]}},"setoptions":{"2":{"access":["1"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"0","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"0","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""},"1":{"access":["6","2"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"0","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"0","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""},"0":{"access":["7","4","8"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"0","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"1","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""}}},"sets_amount":3,"html_height":"550","html_width":"750"}', '', 3, 0), +(0, 'plg_editors_tinymce', 'plugin', 'tinymce', 'editors', 0, 1, 1, 0, 1, '', '{"configuration":{"toolbars":{"2":{"toolbar1":["bold","underline","strikethrough","|","readmore","|","undo","redo","|","bullist","numlist","|","pastetext"]},"1":{"menu":["edit","insert","view","format","table","tools"],"toolbar1":["bold","italic","underline","strikethrough","|","alignleft","aligncenter","alignright","alignjustify","|","readmore","|","blocks","|","bullist","numlist","|","outdent","indent","|","undo","redo","|","link","unlink","anchor","code","|","hr","table","|","subscript","superscript","|","charmap","pastetext","preview"]},"0":{"menu":["edit","insert","view","format","table","tools"],"toolbar1":["bold","italic","underline","strikethrough","|","alignleft","aligncenter","alignright","alignjustify","|","readmore","|","lineheight","|","styles","|","blocks","fontfamily","fontsize","|","searchreplace","|","bullist","numlist","|","outdent","indent","|","undo","redo","|","link","unlink","anchor","image","|","code","|","forecolor","backcolor","|","fullscreen","|","table","|","subscript","superscript","|","charmap","emoticons","media","hr","ltr","rtl","|","cut","copy","paste","pastetext","|","visualchars","visualblocks","nonbreaking","blockquote","jtemplate","|","print","preview","codesample","insertdatetime","removeformat","language","abbr","abbr_remove"]}},"setoptions":{"2":{"access":["1"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"1","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"0","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""},"1":{"access":["6","2"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"1","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"0","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""},"0":{"access":["7","4","8"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"1","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"1","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""}}},"sets_amount":3,"html_height":"550px","html_width":"100%"}', '', 3, 0), (0, 'plg_extension_finder', 'plugin', 'finder', 'extension', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_extension_joomla', 'plugin', 'joomla', 'extension', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_extension_joomlaupdate', 'plugin', 'joomlaupdate', 'extension', 0, 1, 1, 0, 1, '', '', '', 3, 0), @@ -299,14 +299,16 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, (0, 'plg_fields_integer', 'plugin', 'integer', 'fields', 0, 1, 1, 0, 1, '', '{"multiple":"0","first":"1","last":"100","step":"1"}', '', 6, 0), (0, 'plg_fields_list', 'plugin', 'list', 'fields', 0, 1, 1, 0, 1, '', '', '', 7, 0), (0, 'plg_fields_media', 'plugin', 'media', 'fields', 0, 1, 1, 0, 1, '', '', '', 8, 0), -(0, 'plg_fields_radio', 'plugin', 'radio', 'fields', 0, 1, 1, 0, 1, '', '', '', 9, 0), -(0, 'plg_fields_sql', 'plugin', 'sql', 'fields', 0, 1, 1, 0, 1, '', '', '', 10, 0), -(0, 'plg_fields_subform', 'plugin', 'subform', 'fields', 0, 1, 1, 0, 1, '', '', '', 11, 0), -(0, 'plg_fields_text', 'plugin', 'text', 'fields', 0, 1, 1, 0, 1, '', '', '', 12, 0), -(0, 'plg_fields_textarea', 'plugin', 'textarea', 'fields', 0, 1, 1, 0, 1, '', '{"rows":10,"cols":10,"maxlength":"","filter":"\\\\Joomla\\\\CMS\\\\Component\\\\ComponentHelper::filterText"}', '', 13, 0), -(0, 'plg_fields_url', 'plugin', 'url', 'fields', 0, 1, 1, 0, 1, '', '', '', 14, 0), -(0, 'plg_fields_user', 'plugin', 'user', 'fields', 0, 1, 1, 0, 1, '', '', '', 15, 0), -(0, 'plg_fields_usergrouplist', 'plugin', 'usergrouplist', 'fields', 0, 1, 1, 0, 1, '', '', '', 16, 0), +(0, 'plg_fields_note', 'plugin', 'note', 'fields', 0, 1, 1, 0, 1, '', '{"class":"alert alert-info","heading":"h4"}', '', 9, 0), +(0, 'plg_fields_number', 'plugin', 'number', 'fields', 0, 1, 1, 0, 1, '', '{"min":"1.0","max":"100.0","step":"0.1","currency":"0","symbol":"","position":"0","decimals":"2"}', '', 10, 0), +(0, 'plg_fields_radio', 'plugin', 'radio', 'fields', 0, 1, 1, 0, 1, '', '', '', 11, 0), +(0, 'plg_fields_sql', 'plugin', 'sql', 'fields', 0, 1, 1, 0, 1, '', '', '', 12, 0), +(0, 'plg_fields_subform', 'plugin', 'subform', 'fields', 0, 1, 1, 0, 1, '', '', '', 13, 0), +(0, 'plg_fields_text', 'plugin', 'text', 'fields', 0, 1, 1, 0, 1, '', '', '', 14, 0), +(0, 'plg_fields_textarea', 'plugin', 'textarea', 'fields', 0, 1, 1, 0, 1, '', '{"rows":10,"cols":10,"maxlength":"","filter":"\\\\Joomla\\\\CMS\\\\Component\\\\ComponentHelper::filterText"}', '', 15, 0), +(0, 'plg_fields_url', 'plugin', 'url', 'fields', 0, 1, 1, 0, 1, '', '', '', 16, 0), +(0, 'plg_fields_user', 'plugin', 'user', 'fields', 0, 1, 1, 0, 1, '', '', '', 17, 0), +(0, 'plg_fields_usergrouplist', 'plugin', 'usergrouplist', 'fields', 0, 1, 1, 0, 1, '', '', '', 18, 0), (0, 'plg_filesystem_local', 'plugin', 'local', 'filesystem', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_finder_categories', 'plugin', 'categories', 'finder', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_finder_contacts', 'plugin', 'contacts', 'finder', 0, 1, 1, 0, 1, '', '', '', 2, 0), @@ -414,7 +416,8 @@ INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, -- Templates INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) VALUES (0, 'atum', 'template', 'atum', '', 1, 1, 1, 0, 1, '', '', '', 0, 0), -(0, 'cassiopeia', 'template', 'cassiopeia', '', 0, 1, 1, 0, 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0}', '', 0, 0); +(0, 'cassiopeia', 'template', 'cassiopeia', '', 0, 1, 1, 0, 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0}', '', 0, 0), +(0, 'cassiopeia_extended', 'template', 'cassiopeia_extended', '', 0, 1, 1, 0, 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","systemFontBody":"","systemFontHeading":"","colorName":"colors_standard","fluidContainer":"0","stickyHeader":"0","backTop":"0","colorSettings":"0","headerbg":"rgb(193, 205, 207)","headercolor":"rgb(23, 23, 23)","bodybg":"rgb(254, 254, 254)","bodycolor":"rgb(23, 23, 23)","linkcolor":"rgb(29, 121, 137)","linkcolorh":"rgb(14, 59, 67)","btnbg":"rgb(206, 60, 55)","btnbgh":"rgb(131, 35, 32)","btncolor":"rgb(254, 254, 254)","btncolorh":"rgb(254, 254, 254)","footerbg":"rgb(29, 121, 137)","footercolor":"rgb(254, 254, 254)","fontSettings":"0","bodysize":"1","h1size":"2","h2size":"1.7","h3size":"1.5"}', '', 0, 0); -- Files Extensions INSERT INTO `#__extensions` (`package_id`, `name`, `type`, `element`, `folder`, `client_id`, `enabled`, `access`, `protected`, `locked`, `manifest_cache`, `params`, `custom_data`, `ordering`, `state`) VALUES @@ -847,7 +850,8 @@ CREATE TABLE IF NOT EXISTS `#__template_styles` ( INSERT INTO `#__template_styles` (`id`, `template`, `client_id`, `home`, `title`, `inheritable`, `parent`, `params`) VALUES (10, 'atum', 1, '1', 'Atum - Default', 1, '', '{"hue":"hsl(214, 63%, 20%)","bg-light":"#f0f4fb","text-dark":"#495057","text-light":"#ffffff","link-color":"#2a69b8","special-color":"#001b4c","colorScheme":"os","monochrome":"0","loginLogo":"","loginLogoAlt":"","logoBrandLarge":"","logoBrandLargeAlt":"","logoBrandSmall":"","logoBrandSmallAlt":""}'), -(11, 'cassiopeia', 0, '1', 'Cassiopeia - Default', 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0}'); +(11, 'cassiopeia', 0, '1', 'Cassiopeia - Default', 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0}'), +(12, 'cassiopeia_extended', 0, '0', 'Cassiopeia Extended - Default', 0, 'cassiopeia', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","systemFontBody":"","systemFontHeading":"","colorName":"colors_standard","fluidContainer":"0","stickyHeader":"0","backTop":"0","colorSettings":"0","headerbg":"rgb(193, 205, 207)","headercolor":"rgb(23, 23, 23)","bodybg":"rgb(254, 254, 254)","bodycolor":"rgb(23, 23, 23)","linkcolor":"rgb(29, 121, 137)","linkcolorh":"rgb(14, 59, 67)","btnbg":"rgb(206, 60, 55)","btnbgh":"rgb(131, 35, 32)","btncolor":"rgb(254, 254, 254)","btncolorh":"rgb(254, 254, 254)","footerbg":"rgb(29, 121, 137)","footercolor":"rgb(254, 254, 254)","fontSettings":"0","bodysize":"1","h1size":"2","h2size":"1.7","h3size":"1.5"}'); -- -------------------------------------------------------- @@ -871,6 +875,7 @@ CREATE TABLE IF NOT EXISTS `#__updates` ( `infourl` text NOT NULL, `changelogurl` text, `extra_query` varchar(1000) DEFAULT '', + `security` tinyint DEFAULT NULL, PRIMARY KEY (`update_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci COMMENT='Available Updates'; @@ -922,7 +927,7 @@ CREATE TABLE IF NOT EXISTS `#__update_sites` ( INSERT INTO `#__update_sites` (`update_site_id`, `name`, `type`, `location`, `enabled`, `last_check_timestamp`) VALUES (1, 'Joomla! Core', 'tuf', 'https://update.joomla.org/cms/', 1, 0), -(2, 'Accredited Joomla! Translations', 'collection', 'https://update.joomla.org/language/translationlist_5.xml', 1, 0), +(2, 'Accredited Joomla! Translations', 'collection', 'https://update.joomla.org/language/translationlist_6.xml', 1, 0), (3, 'Joomla! Update Component', 'extension', 'https://update.joomla.org/core/extensions/com_joomlaupdate.xml', 1, 0); -- -------------------------------------------------------- @@ -1203,6 +1208,7 @@ CREATE TABLE IF NOT EXISTS `#__workflow_stages` ( `title` varchar(255) NOT NULL, `description` text NOT NULL, `default` tinyint NOT NULL DEFAULT 0, + `position` text, `checked_out_time` datetime, `checked_out` int unsigned, PRIMARY KEY (`id`), diff --git a/installation/sql/mysql/supports.sql b/installation/sql/mysql/supports.sql index f54ff9edea74f..f5f28b276cb1f 100644 --- a/installation/sql/mysql/supports.sql +++ b/installation/sql/mysql/supports.sql @@ -95,19 +95,20 @@ CREATE TABLE IF NOT EXISTS `#__content_types` ( -- INSERT INTO `#__content_types` (`type_id`, `type_title`, `type_alias`, `table`, `rules`, `field_mappings`, `router`, `content_history_options`) VALUES -(1, 'Article', 'com_content.article', '{"special":{"dbtable":"#__content","key":"id","type":"ArticleTable","prefix":"Joomla\\\\Component\\\\Content\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_user_id":"created_by","core_created_by_alias":"created_by_alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"asset_id", "note":"note"}, "special":{"fulltext":"fulltext"}}', 'ContentHelperRoute::getArticleRoute', '{"formFile":"administrator\\/components\\/com_content\\/forms\\/article.xml", "hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits", "ordering"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ]}'), -(2, 'Contact', 'com_contact.contact', '{"special":{"dbtable":"#__contact_details","key":"id","type":"ContactTable","prefix":"Joomla\\\\Component\\\\Contact\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}}', 'ContactHelperRoute::getContactRoute', '{"formFile":"administrator\\/components\\/com_contact\\/forms\\/contact.xml","hideFields":["default_con","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"], "displayLookup":[ {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ] }'), -(3, 'Newsfeed', 'com_newsfeeds.newsfeed', '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"NewsfeedTable","prefix":"Joomla\\\\Component\\\\Newsfeeds\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}}', 'NewsfeedsHelperRoute::getNewsfeedRoute', '{"formFile":"administrator\\/components\\/com_newsfeeds\\/forms\\/newsfeed.xml","hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ]}'), +(1, 'Article', 'com_content.article', '{"special":{"dbtable":"#__content","key":"id","type":"ArticleTable","prefix":"Joomla\\\\Component\\\\Content\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_user_id":"created_by","core_created_by_alias":"created_by_alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"asset_id", "note":"note"}, "special":{"fulltext":"fulltext"}}', 'ContentHelperRoute::getArticleRoute', '{"formFile":"administrator\\/components\\/com_content\\/forms\\/article.xml", "hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits", "ordering"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"} ]}'), +(2, 'Contact', 'com_contact.contact', '{"special":{"dbtable":"#__contact_details","key":"id","type":"ContactTable","prefix":"Joomla\\\\Component\\\\Contact\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}}', 'ContactHelperRoute::getContactRoute', '{"formFile":"administrator\\/components\\/com_contact\\/forms\\/contact.xml","hideFields":["default_con","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"], "displayLookup":[ {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"} ] }'), +(3, 'Newsfeed', 'com_newsfeeds.newsfeed', '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"NewsfeedTable","prefix":"Joomla\\\\Component\\\\Newsfeeds\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}}', 'NewsfeedsHelperRoute::getNewsfeedRoute', '{"formFile":"administrator\\/components\\/com_newsfeeds\\/forms\\/newsfeed.xml","hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"} ]}'), (4, 'User', 'com_users.user', '{"special":{"dbtable":"#__users","key":"id","type":"User","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"null","core_alias":"username","core_created_time":"registerDate","core_modified_time":"lastvisitDate","core_body":"null", "core_hits":"null","core_publish_up":"null","core_publish_down":"null","access":"null", "core_params":"params", "core_featured":"null", "core_metadata":"null", "core_language":"null", "core_images":"null", "core_urls":"null", "core_version":"null", "core_ordering":"null", "core_metakey":"null", "core_metadesc":"null", "core_catid":"null", "asset_id":"null"}, "special":{}}', '', ''), -(5, 'Article Category', 'com_content.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'ContentHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'), -(6, 'Contact Category', 'com_contact.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'ContactHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'), -(7, 'Newsfeeds Category', 'com_newsfeeds.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'NewsfeedsHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'), +(5, 'Article Category', 'com_content.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'ContentHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), +(6, 'Contact Category', 'com_contact.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'ContactHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), +(7, 'Newsfeeds Category', 'com_newsfeeds.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'NewsfeedsHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), (8, 'Tag', 'com_tags.tag', '{"special":{"dbtable":"#__tags","key":"tag_id","type":"TagTable","prefix":"Joomla\\\\Component\\\\Tags\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"null", "asset_id":"null"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path"}}', 'TagsHelperRoute::getTagRoute', '{"formFile":"administrator\\/components\\/com_tags\\/forms\\/tag.xml", "hideFields":["checked_out","checked_out_time","version", "lft", "rgt", "level", "path", "urls", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'), (9, 'Banner', 'com_banners.banner', '{"special":{"dbtable":"#__banners","key":"id","type":"BannerTable","prefix":"Joomla\\\\Component\\\\Banners\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"null","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"imptotal":"imptotal", "impmade":"impmade", "clicks":"clicks", "clickurl":"clickurl", "custombannercode":"custombannercode", "cid":"cid", "purchase_type":"purchase_type", "track_impressions":"track_impressions", "track_clicks":"track_clicks"}}', '','{"formFile":"administrator\\/components\\/com_banners\\/forms\\/banner.xml", "hideFields":["checked_out","checked_out_time","version", "reset"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "imptotal", "impmade", "reset"], "convertToInt":["publish_up", "publish_down", "ordering"], "displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"cid","targetTable":"#__banner_clients","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ]}'), -(10, 'Banners Category', 'com_banners.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}','','{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'), +(10, 'Banners Category', 'com_banners.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}','','{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), (11, 'Banner Client', 'com_banners.client', '{"special":{"dbtable":"#__banner_clients","key":"id","type":"ClientTable","prefix":"Joomla\\\\Component\\\\Banners\\\\Administrator\\\\Table\\\\"}}', '', '', '', '{"formFile":"administrator\\/components\\/com_banners\\/forms\\/client.xml", "hideFields":["checked_out","checked_out_time"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":[], "displayLookup":[]}'), (12, 'User Notes', 'com_users.note', '{"special":{"dbtable":"#__user_notes","key":"id","type":"NoteTable","prefix":"Joomla\\\\Component\\\\Users\\\\Administrator\\\\Table\\\\"}}', '', '', '', '{"formFile":"administrator\\/components\\/com_users\\/forms\\/note.xml", "hideFields":["checked_out","checked_out_time", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'), -(13, 'User Notes Category', 'com_users.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'); +(13, 'User Notes Category', 'com_users.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), +(14, 'Module', 'com_modules.module', '{"special":{"dbtable":"#__modules","key":"id","type":"Module","prefix":"Joomla\\\\CMS\\\\Table\\\\"}}', '', '{}', '', '{"formFile":"administrator\\/components\\/com_modules\\/forms\\/module.xml", "hideFields":["checked_out", "checked_out_time", "publish_up", "publish_down"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"checked_out", "targetTable":"#__users", "targetColumn":"id", "displayColumn":"name"}]}'); -- -------------------------------------------------------- @@ -367,6 +368,8 @@ CREATE TABLE IF NOT EXISTS `#__history` ( `sha1_hash` varchar(50) NOT NULL DEFAULT '' COMMENT 'SHA1 hash of the version_data column.', `version_data` mediumtext NOT NULL COMMENT 'json-encoded string of version data', `keep_forever` tinyint NOT NULL DEFAULT 0 COMMENT '0=auto delete; 1=keep', + `is_current` tinyint NOT NULL DEFAULT 0, + `is_legacy` tinyint NOT NULL DEFAULT 0, PRIMARY KEY (`version_id`), KEY `idx_ucm_item_id` (`item_id`), KEY `idx_save_date` (`save_date`) @@ -420,7 +423,7 @@ INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subjec ('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), ('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'), ('plg_user_joomla.mail', 'plg_user_joomla', '', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_SUBJECT', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_BODY', '', '', '{"tags":["name","sitename","url","username","password","email"]}'), -('com_actionlogs.notification', 'com_actionlogs', '', 'COM_ACTIONLOGS_EMAIL_SUBJECT', 'COM_ACTIONLOGS_EMAIL_BODY', 'COM_ACTIONLOGS_EMAIL_HTMLBODY', '', '{"tags":["messages","message","date","extension","username"]}'), +('com_actionlogs.notification', 'com_actionlogs', '', 'COM_ACTIONLOGS_EMAIL_SUBJECT', 'COM_ACTIONLOGS_EMAIL_BODY', 'COM_ACTIONLOGS_EMAIL_HTMLBODY', '', '{"tags":["messages","message","date","extension","username","ip_address"]}'), ('com_privacy.userdataexport', 'com_privacy', '', 'COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_SUBJECT', 'COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_BODY', '', '', '{"tags":["sitename","url"]}'), ('com_privacy.notification.export', 'com_privacy', '', 'COM_PRIVACY_EMAIL_REQUEST_SUBJECT_EXPORT_REQUEST', 'COM_PRIVACY_EMAIL_REQUEST_BODY_EXPORT_REQUEST', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), ('com_privacy.notification.remove', 'com_privacy', '', 'COM_PRIVACY_EMAIL_REQUEST_SUBJECT_REMOVE_REQUEST', 'COM_PRIVACY_EMAIL_REQUEST_BODY_REMOVE_REQUEST', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), @@ -441,4 +444,5 @@ INSERT INTO `#__mail_templates` (`template_id`, `extension`, `language`, `subjec ('plg_system_tasknotification.fatal_recovery_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_FATAL_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_FATAL_MAIL_BODY', '', '', '{"tags": ["task_id", "task_title"]}'), ('plg_system_tasknotification.orphan_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_ORPHAN_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_ORPHAN_MAIL_BODY', '', '', '{"tags": ["task_id", "task_title"]}'), ('plg_system_tasknotification.success_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_SUCCESS_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_SUCCESS_MAIL_BODY', '', '', '{"tags":["task_id", "task_title", "exec_data_time", "task_output"]}'), -('plg_multifactorauth_email.mail', 'plg_multifactorauth_email', '', 'PLG_MULTIFACTORAUTH_EMAIL_EMAIL_SUBJECT', 'PLG_MULTIFACTORAUTH_EMAIL_EMAIL_BODY', '', '', '{"tags":["code","sitename","siteurl","username","email","fullname"]}'); +('plg_multifactorauth_email.mail', 'plg_multifactorauth_email', '', 'PLG_MULTIFACTORAUTH_EMAIL_EMAIL_SUBJECT', 'PLG_MULTIFACTORAUTH_EMAIL_EMAIL_BODY', '', '', '{"tags":["code","sitename","siteurl","username","email","fullname"]}'), +('plg_content_joomla.newarticle', 'plg_content_joomla', '', 'PLG_CONTENT_JOOMLA_NEW_ARTICLE_SUBJECT', 'PLG_CONTENT_JOOMLA_NEW_ARTICLE_BODY', '', '', '{"tags":["sitename","name","email","title","url"]}'); diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index bbff277f4c5b3..2916c3f99c7a1 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -181,7 +181,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'com_newsfeeds', 'component', 'com_newsfeeds', '', 1, 1, 1, 0, 1, '', '{"newsfeed_layout":"_:default","save_history":"1","history_limit":5,"show_feed_image":"1","show_feed_description":"1","show_item_description":"1","feed_character_count":"0","feed_display_order":"des","float_first":"right","float_second":"right","show_tags":"1","category_layout":"_:default","show_category_title":"1","show_description":"1","show_description_image":"1","maxLevel":"-1","show_empty_categories":"0","show_subcat_desc":"1","show_cat_items":"1","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_items_cat":"1","filter_field":"1","show_pagination_limit":"1","show_headings":"1","show_articles":"0","show_link":"1","show_pagination":"1","show_pagination_results":"1","sef_ids":1}', '', 0, 0), (0, 'com_plugins', 'component', 'com_plugins', '', 1, 1, 1, 1, 1, '', '', '', 0, 0), (0, 'com_templates', 'component', 'com_templates', '', 1, 1, 1, 1, 1, '', '{"template_positions_display":"0","upload_limit":"10","image_formats":"gif,bmp,jpg,jpeg,png,webp","source_formats":"txt,less,ini,xml,js,php,css,scss,sass,json","font_formats":"woff,woff2,ttf,otf","compressed_formats":"zip","difference":"SideBySide"}', '', 0, 0), -(0, 'com_content', 'component', 'com_content', '', 1, 1, 0, 1, 1, '', '{"article_layout":"_:default","show_title":"1","link_titles":"1","show_intro":"1","info_block_position":"0","info_block_show_title":"1","show_category":"1","link_category":"1","show_parent_category":"0","link_parent_category":"0","show_associations":"0","flags":"1","show_author":"1","link_author":"0","show_create_date":"0","show_modify_date":"0","show_publish_date":"1","show_item_navigation":"1","show_readmore":"1","show_readmore_title":"1","readmore_limit":100,"show_tags":"1","record_hits":"1","show_hits":"1","show_noauth":"0","urls_position":0,"captcha":"","show_publishing_options":"1","show_article_options":"1","show_configure_edit_options":"1","show_permissions":"1","show_associations_edit":"1","save_history":"1","history_limit":10,"show_urls_images_frontend":"0","show_urls_images_backend":"1","targeta":0,"targetb":0,"targetc":0,"float_intro":"left","float_fulltext":"left","category_layout":"_:blog","show_category_title":"0","show_description":"0","show_description_image":"0","maxLevel":"1","show_empty_categories":"0","show_no_articles":"1","show_category_heading_title_text":"1","show_subcat_desc":"1","show_cat_num_articles":"0","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_num_articles_cat":"1","num_leading_articles":1,"blog_class_leading":"","num_intro_articles":4,"blog_class":"","num_columns":1,"multi_column_order":"0","num_links":4,"show_subcategory_content":"0","link_intro_image":"0","show_pagination_limit":"1","filter_field":"hide","show_headings":"1","list_show_date":"0","date_format":"","list_show_hits":"1","list_show_author":"1","display_num":"10","orderby_pri":"order","orderby_sec":"rdate","order_date":"published","show_pagination":"2","show_pagination_results":"1","show_featured":"show","show_feed_link":"1","feed_summary":"0","feed_show_readmore":"0","sef_ids":1,"custom_fields_enable":"1","workflow_enabled":"0"}', '', 0, 0), +(0, 'com_content', 'component', 'com_content', '', 1, 1, 0, 1, 1, '', '{"article_layout":"_:default","show_title":"1","link_titles":"1","show_intro":"1","info_block_position":"0","info_block_show_title":"1","show_category":"1","link_category":"1","show_parent_category":"0","link_parent_category":"0","show_associations":"0","flags":"1","show_author":"1","link_author":"0","show_create_date":"0","show_modify_date":"0","show_publish_date":"1","show_item_navigation":"1","show_readmore":"1","show_readmore_title":"1","readmore_limit":100,"show_tags":"1","record_hits":"1","show_hits":"1","show_noauth":"0","urls_position":0,"captcha":"","show_publishing_options":"1","show_article_options":"1","show_configure_edit_options":"1","show_permissions":"1","show_associations_edit":"1","save_history":"1","history_limit":10,"show_urls_images_frontend":"0","show_urls_images_backend":"1","targeta":0,"targetb":0,"targetc":0,"float_intro":"left","float_fulltext":"left","category_layout":"_:blog","show_category_title":"0","show_description":"0","show_description_image":"0","maxLevel":"1","show_empty_categories":"0","show_no_articles":"1","show_category_heading_title_text":"1","show_subcat_desc":"1","show_subcat_image":"0","show_cat_num_articles":"0","show_cat_tags":"1","show_base_description":"1","maxLevelcat":"-1","show_empty_categories_cat":"0","show_subcat_desc_cat":"1","show_cat_num_articles_cat":"1","num_leading_articles":1,"blog_class_leading":"","num_intro_articles":4,"blog_class":"","num_columns":1,"multi_column_order":"0","num_links":4,"show_subcategory_content":"0","link_intro_image":"0","show_pagination_limit":"1","filter_field":"hide","show_headings":"1","list_show_date":"0","date_format":"","list_show_hits":"1","list_show_author":"1","display_num":"10","orderby_pri":"order","orderby_sec":"rdate","order_date":"published","show_pagination":"2","show_pagination_results":"1","show_featured":"show","show_feed_link":"1","feed_summary":"0","feed_show_readmore":"0","sef_ids":1,"custom_fields_enable":"1","workflow_enabled":"0"}', '', 0, 0), (0, 'com_config', 'component', 'com_config', '', 1, 1, 0, 1, 1, '', '{"filters":{"1":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"9":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"6":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"7":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"2":{"filter_type":"NH","filter_tags":"","filter_attributes":""},"3":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"4":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"5":{"filter_type":"BL","filter_tags":"","filter_attributes":""},"8":{"filter_type":"NONE","filter_tags":"","filter_attributes":""}}}', '', 0, 0), (0, 'com_redirect', 'component', 'com_redirect', '', 1, 1, 0, 0, 1, '', '', '', 0, 0), (0, 'com_users', 'component', 'com_users', '', 1, 1, 0, 1, 1, '', '{"allowUserRegistration":"0","new_usertype":"2","guest_usergroup":"9","sendpassword":"0","useractivation":"2","mail_to_admin":"1","captcha":"","frontend_userparams":"1","site_language":"0","change_login_name":"0","reset_count":"10","reset_time":"1","minimum_length":"12","minimum_integers":"0","minimum_symbols":"0","minimum_uppercase":"0","save_history":"1","history_limit":5,"mailSubjectPrefix":"","mailBodySuffix":""}', '', 0, 0), @@ -268,10 +268,10 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'plg_authentication_cookie', 'plugin', 'cookie', 'authentication', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_authentication_joomla', 'plugin', 'joomla', 'authentication', 0, 1, 1, 1, 1, '', '', '', 2, 0), (0, 'plg_authentication_ldap', 'plugin', 'ldap', 'authentication', 0, 0, 1, 0, 1, '', '{"host":"","port":"389","use_ldapV3":"0","negotiate_tls":"0","no_referrals":"0","auth_method":"bind","base_dn":"","search_string":"","users_dn":"","username":"admin","password":"bobby7","ldap_fullname":"fullName","ldap_email":"mail","ldap_uid":"uid"}', '', 3, 0), -(0, 'plg_behaviour_compat', 'plugin', 'compat', 'behaviour', 0, 1, 1, 0, 1, '', '{"classes_aliases":"1","es5_assets":"1"}', '', 1, 0), -(0, 'plg_behaviour_compat6', 'plugin', 'compat6', 'behaviour', 0, 1, 1, 0, 1, '', '{"classes_aliases":"1","legacy_classes":"1"}', '', 2, 0), -(0, 'plg_behaviour_taggable', 'plugin', 'taggable', 'behaviour', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), -(0, 'plg_behaviour_versionable', 'plugin', 'versionable', 'behaviour', 0, 1, 1, 0, 1, '', '{}', '', 4, 0), +(0, 'plg_behaviour_compat6', 'plugin', 'compat6', 'behaviour', 0, 0, 1, 0, 1, '', '{"classes_aliases":"0","legacy_classes":"1"}', '', 1, 0), +(0, 'plg_behaviour_taggable', 'plugin', 'taggable', 'behaviour', 0, 1, 1, 0, 1, '', '{}', '', 2, 0), +(0, 'plg_behaviour_versionable', 'plugin', 'versionable', 'behaviour', 0, 1, 1, 0, 1, '', '{}', '', 3, 0), +(0, 'plg_captcha_powcaptcha', 'plugin', 'powcaptcha', 'captcha', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_content_confirmconsent', 'plugin', 'confirmconsent', 'content', 0, 0, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_content_contact', 'plugin', 'contact', 'content', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_content_emailcloak', 'plugin', 'emailcloak', 'content', 0, 1, 1, 0, 1, '', '{"mode":"1"}', '', 3, 0), @@ -292,7 +292,7 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'plg_editors-xtd_readmore', 'plugin', 'readmore', 'editors-xtd', 0, 1, 1, 0, 1, '', '', '', 8, 0), (0, 'plg_editors_codemirror', 'plugin', 'codemirror', 'editors', 0, 1, 1, 0, 1, '', '{"lineNumbers":"1","lineWrapping":"1","matchTags":"1","matchBrackets":"1","marker-gutter":"1","autoCloseTags":"1","autoCloseBrackets":"1","autoFocus":"1","theme":"default","tabmode":"indent"}', '', 1, 0), (0, 'plg_editors_none', 'plugin', 'none', 'editors', 0, 1, 1, 1, 1, '', '', '', 2, 0), -(0, 'plg_editors_tinymce', 'plugin', 'tinymce', 'editors', 0, 1, 1, 0, 1, '', '{"configuration":{"toolbars":{"2":{"toolbar1":["bold","underline","strikethrough","|","undo","redo","|","bullist","numlist","|","pastetext"]},"1":{"menu":["edit","insert","view","format","table","tools"],"toolbar1":["bold","italic","underline","strikethrough","|","alignleft","aligncenter","alignright","alignjustify","|","blocks","|","bullist","numlist","|","outdent","indent","|","undo","redo","|","link","unlink","anchor","code","|","hr","table","|","subscript","superscript","|","charmap","pastetext","preview"]},"0":{"menu":["edit","insert","view","format","table","tools"],"toolbar1":["bold","italic","underline","strikethrough","|","alignleft","aligncenter","alignright","alignjustify","|","styles","|","blocks","fontfamily","fontsize","|","searchreplace","|","bullist","numlist","|","outdent","indent","|","undo","redo","|","link","unlink","anchor","image","|","code","|","forecolor","backcolor","|","fullscreen","|","table","|","subscript","superscript","|","charmap","emoticons","media","hr","ltr","rtl","|","cut","copy","paste","pastetext","|","visualchars","visualblocks","nonbreaking","blockquote","jtemplate","|","print","preview","codesample","insertdatetime","removeformat"]}},"setoptions":{"2":{"access":["1"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"0","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"0","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""},"1":{"access":["6","2"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"0","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"0","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""},"0":{"access":["7","4","8"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"0","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"1","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""}}},"sets_amount":3,"html_height":"550","html_width":"750"}', '', 3, 0), +(0, 'plg_editors_tinymce', 'plugin', 'tinymce', 'editors', 0, 1, 1, 0, 1, '', '{"configuration":{"toolbars":{"2":{"toolbar1":["bold","underline","strikethrough","|","readmore","|","undo","redo","|","bullist","numlist","|","pastetext"]},"1":{"menu":["edit","insert","view","format","table","tools"],"toolbar1":["bold","italic","underline","strikethrough","|","alignleft","aligncenter","alignright","alignjustify","|","readmore","|","blocks","|","bullist","numlist","|","outdent","indent","|","undo","redo","|","link","unlink","anchor","code","|","hr","table","|","subscript","superscript","|","charmap","pastetext","preview"]},"0":{"menu":["edit","insert","view","format","table","tools"],"toolbar1":["bold","italic","underline","strikethrough","|","alignleft","aligncenter","alignright","alignjustify","|","readmore","|","lineheight","|","styles","|","blocks","fontfamily","fontsize","|","searchreplace","|","bullist","numlist","|","outdent","indent","|","undo","redo","|","link","unlink","anchor","image","|","code","|","forecolor","backcolor","|","fullscreen","|","table","|","subscript","superscript","|","charmap","emoticons","media","hr","ltr","rtl","|","cut","copy","paste","pastetext","|","visualchars","visualblocks","nonbreaking","blockquote","jtemplate","|","print","preview","codesample","insertdatetime","removeformat","language","abbr","abbr_remove"]}},"setoptions":{"2":{"access":["1"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"1","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"0","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""},"1":{"access":["6","2"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"1","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"0","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""},"0":{"access":["7","4","8"],"skin":"0","skin_admin":"0","mobile":"0","drag_drop":"1","path":"","entity_encoding":"raw","lang_mode":"1","text_direction":"ltr","content_css":"1","content_css_custom":"","relative_urls":"1","newlines":"0","use_config_textfilters":"1","invalid_elements":"script,applet,iframe","valid_elements":"","extended_elements":"","resizing":"1","resize_horizontal":"1","element_path":"1","wordcount":"1","image_advtab":"1","advlist":"1","autosave":"1","contextmenu":"1","custom_plugin":"","custom_button":""}}},"sets_amount":3,"html_height":"550px","html_width":"100%"}', '', 3, 0), (0, 'plg_extension_finder', 'plugin', 'finder', 'extension', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_extension_joomla', 'plugin', 'joomla', 'extension', 0, 1, 1, 0, 1, '', '', '', 2, 0), (0, 'plg_extension_joomlaupdate', 'plugin', 'joomlaupdate', 'extension', 0, 1, 1, 0, 1, '', '', '', 3, 0), @@ -305,14 +305,16 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", (0, 'plg_fields_integer', 'plugin', 'integer', 'fields', 0, 1, 1, 0, 1, '', '{"multiple":"0","first":"1","last":"100","step":"1"}', '', 6, 0), (0, 'plg_fields_list', 'plugin', 'list', 'fields', 0, 1, 1, 0, 1, '', '', '', 7, 0), (0, 'plg_fields_media', 'plugin', 'media', 'fields', 0, 1, 1, 0, 1, '', '', '', 8, 0), -(0, 'plg_fields_radio', 'plugin', 'radio', 'fields', 0, 1, 1, 0, 1, '', '', '', 9, 0), -(0, 'plg_fields_sql', 'plugin', 'sql', 'fields', 0, 1, 1, 0, 1, '', '', '', 10, 0), -(0, 'plg_fields_subform', 'plugin', 'subform', 'fields', 0, 1, 1, 0, 1, '', '', '', 11, 0), -(0, 'plg_fields_text', 'plugin', 'text', 'fields', 0, 1, 1, 0, 1, '', '', '', 12, 0), -(0, 'plg_fields_textarea', 'plugin', 'textarea', 'fields', 0, 1, 1, 0, 1, '', '{"rows":10,"cols":10,"maxlength":"","filter":"\\\\Joomla\\\\CMS\\\\Component\\\\ComponentHelper::filterText"}', '', 13, 0), -(0, 'plg_fields_url', 'plugin', 'url', 'fields', 0, 1, 1, 0, 1, '', '', '', 14, 0), -(0, 'plg_fields_user', 'plugin', 'user', 'fields', 0, 1, 1, 0, 1, '', '', '', 15, 0), -(0, 'plg_fields_usergrouplist', 'plugin', 'usergrouplist', 'fields', 0, 1, 1, 0, 1, '', '', '', 16, 0), +(0, 'plg_fields_note', 'plugin', 'note', 'fields', 0, 1, 1, 0, 1, '', '{"class":"alert alert-info","heading":"h4"}', '', 9, 0), +(0, 'plg_fields_number', 'plugin', 'number', 'fields', 0, 1, 1, 0, 1, '', '{"min":"1.0","max":"100.0","step":"0.1","currency":"0","symbol":"","position":"0","decimals":"2"}', '', 10, 0), +(0, 'plg_fields_radio', 'plugin', 'radio', 'fields', 0, 1, 1, 0, 1, '', '', '', 11, 0), +(0, 'plg_fields_sql', 'plugin', 'sql', 'fields', 0, 1, 1, 0, 1, '', '', '', 12, 0), +(0, 'plg_fields_subform', 'plugin', 'subform', 'fields', 0, 1, 1, 0, 1, '', '', '', 13, 0), +(0, 'plg_fields_text', 'plugin', 'text', 'fields', 0, 1, 1, 0, 1, '', '', '', 14, 0), +(0, 'plg_fields_textarea', 'plugin', 'textarea', 'fields', 0, 1, 1, 0, 1, '', '{"rows":10,"cols":10,"maxlength":"","filter":"\\\\Joomla\\\\CMS\\\\Component\\\\ComponentHelper::filterText"}', '', 15, 0), +(0, 'plg_fields_url', 'plugin', 'url', 'fields', 0, 1, 1, 0, 1, '', '', '', 16, 0), +(0, 'plg_fields_user', 'plugin', 'user', 'fields', 0, 1, 1, 0, 1, '', '', '', 17, 0), +(0, 'plg_fields_usergrouplist', 'plugin', 'usergrouplist', 'fields', 0, 1, 1, 0, 1, '', '', '', 18, 0), (0, 'plg_filesystem_local', 'plugin', 'local', 'filesystem', 0, 1, 1, 0, 1, '', '{}', '', 1, 0), (0, 'plg_finder_categories', 'plugin', 'categories', 'finder', 0, 1, 1, 0, 1, '', '', '', 1, 0), (0, 'plg_finder_contacts', 'plugin', 'contacts', 'finder', 0, 1, 1, 0, 1, '', '', '', 2, 0), @@ -420,7 +422,8 @@ INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", -- Templates INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") VALUES (0, 'atum', 'template', 'atum', '', 1, 1, 1, 0, 1, '', '', '', 0, 0), -(0, 'cassiopeia', 'template', 'cassiopeia', '', 0, 1, 1, 0, 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0}', '', 0, 0); +(0, 'cassiopeia', 'template', 'cassiopeia', '', 0, 1, 1, 0, 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0,"colorSettings":0,"fontSettings":0}', '', 0, 0), +(0, 'cassiopeia_extended', 'template', 'cassiopeia_extended', '', 0, 1, 1, 0, 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","systemFontBody":"","systemFontHeading":"","colorName":"colors_standard","fluidContainer":"0","stickyHeader":"0","backTop":"0","colorSettings":"0","headerbg":"rgb(193, 205, 207)","headercolor":"rgb(23, 23, 23)","bodybg":"rgb(254, 254, 254)","bodycolor":"rgb(23, 23, 23)","linkcolor":"rgb(29, 121, 137)","linkcolorh":"rgb(14, 59, 67)","btnbg":"rgb(206, 60, 55)","btnbgh":"rgb(131, 35, 32)","btncolor":"rgb(254, 254, 254)","btncolorh":"rgb(254, 254, 254)","footerbg":"rgb(29, 121, 137)","footercolor":"rgb(254, 254, 254)","fontSettings":"0","bodysize":"1","h1size":"2","h2size":"1.7","h3size":"1.5"}', '', 0, 0); -- Files Extensions INSERT INTO "#__extensions" ("package_id", "name", "type", "element", "folder", "client_id", "enabled", "access", "protected", "locked", "manifest_cache", "params", "custom_data", "ordering", "state") VALUES @@ -862,9 +865,10 @@ CREATE INDEX "#__template_styles_idx_client_id_home" ON "#__template_styles" ("c -- INSERT INTO "#__template_styles" ("id", "template", "client_id", "home", "title", "inheritable", "parent", "params") VALUES (10, 'atum', 1, '1', 'Atum - Default', 1, '', '{"hue":"hsl(214, 63%, 20%)","bg-light":"#f0f4fb","text-dark":"#495057","text-light":"#ffffff","link-color":"#2a69b8","special-color":"#001b4c","colorScheme":"os","monochrome":"0","loginLogo":"","loginLogoAlt":"","logoBrandLarge":"","logoBrandLargeAlt":"","logoBrandSmall":"","logoBrandSmallAlt":""}'), -(11, 'cassiopeia', 0, '1', 'Cassiopeia - Default', 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0}'); +(11, 'cassiopeia', 0, '1', 'Cassiopeia - Default', 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0}'), +(12, 'cassiopeia_extended', 0, '0', 'Cassiopeia Extended - Default', 0, 'cassiopeia', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","systemFontBody":"","systemFontHeading":"","colorName":"colors_standard","fluidContainer":"0","stickyHeader":"0","backTop":"0","colorSettings":"0","headerbg":"rgb(193, 205, 207)","headercolor":"rgb(23, 23, 23)","bodybg":"rgb(254, 254, 254)","bodycolor":"rgb(23, 23, 23)","linkcolor":"rgb(29, 121, 137)","linkcolorh":"rgb(14, 59, 67)","btnbg":"rgb(206, 60, 55)","btnbgh":"rgb(131, 35, 32)","btncolor":"rgb(254, 254, 254)","btncolorh":"rgb(254, 254, 254)","footerbg":"rgb(29, 121, 137)","footercolor":"rgb(254, 254, 254)","fontSettings":"0","bodysize":"1","h1size":"2","h2size":"1.7","h3size":"1.5"}'); -SELECT setval('#__template_styles_id_seq', 12, false); +SELECT setval('#__template_styles_id_seq', 13, false); -- -- Table structure for table `#__updates` @@ -886,6 +890,7 @@ CREATE TABLE IF NOT EXISTS "#__updates" ( "infourl" text NOT NULL, "changelogurl" text, "extra_query" varchar(1000) DEFAULT '', + "security" smallint DEFAULT NULL, PRIMARY KEY ("update_id") ); @@ -940,7 +945,7 @@ COMMENT ON TABLE "#__update_sites" IS 'Update Sites'; INSERT INTO "#__update_sites" ("update_site_id", "name", "type", "location", "enabled", "last_check_timestamp") VALUES (1, 'Joomla! Core', 'tuf', 'https://update.joomla.org/cms/', 1, 0), -(2, 'Accredited Joomla! Translations', 'collection', 'https://update.joomla.org/language/translationlist_5.xml', 1, 0), +(2, 'Accredited Joomla! Translations', 'collection', 'https://update.joomla.org/language/translationlist_6.xml', 1, 0), (3, 'Joomla! Update Component', 'extension', 'https://update.joomla.org/core/extensions/com_joomlaupdate.xml', 1, 0); SELECT setval('#__update_sites_update_site_id_seq', 4, false); @@ -1228,6 +1233,7 @@ CREATE TABLE IF NOT EXISTS "#__workflow_stages" ( "title" varchar(255) NOT NULL, "description" text NOT NULL, "default" smallint NOT NULL DEFAULT 0, + "position" text, "checked_out_time" timestamp without time zone, "checked_out" integer, PRIMARY KEY ("id") diff --git a/installation/sql/postgresql/supports.sql b/installation/sql/postgresql/supports.sql index 0a35f22d80db7..c0688fa70a7be 100644 --- a/installation/sql/postgresql/supports.sql +++ b/installation/sql/postgresql/supports.sql @@ -99,19 +99,20 @@ COMMENT ON COLUMN "#__content_types"."content_history_options" IS 'JSON string f -- INSERT INTO "#__content_types" ("type_id", "type_title", "type_alias", "table", "rules", "field_mappings", "router", "content_history_options") VALUES -(1, 'Article', 'com_content.article', '{"special":{"dbtable":"#__content","key":"id","type":"ArticleTable","prefix":"Joomla\\\\Component\\\\Content\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_user_id":"created_by","core_created_by_alias":"created_by_alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"asset_id", "note":"note"}, "special":{"fulltext":"fulltext"}}', 'ContentHelperRoute::getArticleRoute', '{"formFile":"administrator\\/components\\/com_content\\/forms\\/article.xml", "hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits", "ordering"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ]}'), -(2, 'Contact', 'com_contact.contact', '{"special":{"dbtable":"#__contact_details","key":"id","type":"ContactTable","prefix":"Joomla\\\\Component\\\\Contact\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}}', 'ContactHelperRoute::getContactRoute', '{"formFile":"administrator\\/components\\/com_contact\\/forms\\/contact.xml","hideFields":["default_con","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"], "displayLookup":[ {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ] }'), -(3, 'Newsfeed', 'com_newsfeeds.newsfeed', '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"NewsfeedTable","prefix":"Joomla\\\\Component\\\\Newsfeeds\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}}', 'NewsfeedsHelperRoute::getNewsfeedRoute', '{"formFile":"administrator\\/components\\/com_newsfeeds\\/forms\\/newsfeed.xml","hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ]}'), +(1, 'Article', 'com_content.article', '{"special":{"dbtable":"#__content","key":"id","type":"ArticleTable","prefix":"Joomla\\\\Component\\\\Content\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"state","core_alias":"alias","core_created_user_id":"created_by","core_created_by_alias":"created_by_alias","core_created_time":"created","core_modified_time":"modified","core_body":"introtext", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"attribs", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"asset_id", "note":"note"}, "special":{"fulltext":"fulltext"}}', 'ContentHelperRoute::getArticleRoute', '{"formFile":"administrator\\/components\\/com_content\\/forms\\/article.xml", "hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits", "ordering"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"} ]}'), +(2, 'Contact', 'com_contact.contact', '{"special":{"dbtable":"#__contact_details","key":"id","type":"ContactTable","prefix":"Joomla\\\\Component\\\\Contact\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"address", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"image", "core_urls":"webpage", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"con_position":"con_position","suburb":"suburb","state":"state","country":"country","postcode":"postcode","telephone":"telephone","fax":"fax","misc":"misc","email_to":"email_to","default_con":"default_con","user_id":"user_id","mobile":"mobile","sortname1":"sortname1","sortname2":"sortname2","sortname3":"sortname3"}}', 'ContactHelperRoute::getContactRoute', '{"formFile":"administrator\\/components\\/com_contact\\/forms\\/contact.xml","hideFields":["default_con","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"], "displayLookup":[ {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"} ] }'), +(3, 'Newsfeed', 'com_newsfeeds.newsfeed', '{"special":{"dbtable":"#__newsfeeds","key":"id","type":"NewsfeedTable","prefix":"Joomla\\\\Component\\\\Newsfeeds\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"hits","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"numarticles":"numarticles","cache_time":"cache_time","rtl":"rtl"}}', 'NewsfeedsHelperRoute::getNewsfeedRoute', '{"formFile":"administrator\\/components\\/com_newsfeeds\\/forms\\/newsfeed.xml","hideFields":["asset_id","checked_out","checked_out_time","version"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "hits"],"convertToInt":["publish_up", "publish_down", "featured", "ordering"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"} ]}'), (4, 'User', 'com_users.user', '{"special":{"dbtable":"#__users","key":"id","type":"User","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"null","core_alias":"username","core_created_time":"registerDate","core_modified_time":"lastvisitDate","core_body":"null", "core_hits":"null","core_publish_up":"null","core_publish_down":"null","access":"null", "core_params":"params", "core_featured":"null", "core_metadata":"null", "core_language":"null", "core_images":"null", "core_urls":"null", "core_version":"null", "core_ordering":"null", "core_metakey":"null", "core_metadesc":"null", "core_catid":"null", "asset_id":"null"}, "special":{}}', '', ''), -(5, 'Article Category', 'com_content.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'ContentHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'), -(6, 'Contact Category', 'com_contact.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'ContactHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'), -(7, 'Newsfeeds Category', 'com_newsfeeds.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'NewsfeedsHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'), +(5, 'Article Category', 'com_content.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'ContentHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), +(6, 'Contact Category', 'com_contact.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'ContactHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), +(7, 'Newsfeeds Category', 'com_newsfeeds.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', 'NewsfeedsHelperRoute::getCategoryRoute', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), (8, 'Tag', 'com_tags.tag', '{"special":{"dbtable":"#__tags","key":"tag_id","type":"TagTable","prefix":"Joomla\\\\Component\\\\Tags\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"featured", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"urls", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"null", "asset_id":"null"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path"}}', 'TagsHelperRoute::getTagRoute', '{"formFile":"administrator\\/components\\/com_tags\\/forms\\/tag.xml", "hideFields":["checked_out","checked_out_time","version", "lft", "rgt", "level", "path", "urls", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"],"convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'), (9, 'Banner', 'com_banners.banner', '{"special":{"dbtable":"#__banners","key":"id","type":"BannerTable","prefix":"Joomla\\\\Component\\\\Banners\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"name","core_state":"published","core_alias":"alias","core_created_time":"created","core_modified_time":"modified","core_body":"description", "core_hits":"null","core_publish_up":"publish_up","core_publish_down":"publish_down","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"images", "core_urls":"link", "core_version":"version", "core_ordering":"ordering", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"catid", "asset_id":"null"}, "special":{"imptotal":"imptotal", "impmade":"impmade", "clicks":"clicks", "clickurl":"clickurl", "custombannercode":"custombannercode", "cid":"cid", "purchase_type":"purchase_type", "track_impressions":"track_impressions", "track_clicks":"track_clicks"}}', '','{"formFile":"administrator\\/components\\/com_banners\\/forms\\/banner.xml", "hideFields":["checked_out","checked_out_time","version", "reset"],"ignoreChanges":["modified_by", "modified", "checked_out", "checked_out_time", "version", "imptotal", "impmade", "reset"], "convertToInt":["publish_up", "publish_down", "ordering"], "displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"cid","targetTable":"#__banner_clients","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"created_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"modified_by","targetTable":"#__users","targetColumn":"id","displayColumn":"name"} ]}'), -(10, 'Banners Category', 'com_banners.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}','','{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'), +(10, 'Banners Category', 'com_banners.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special": {"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}','','{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["asset_id","checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), (11, 'Banner Client', 'com_banners.client', '{"special":{"dbtable":"#__banner_clients","key":"id","type":"ClientTable","prefix":"Joomla\\\\Component\\\\Banners\\\\Administrator\\\\Table\\\\"}}', '', '', '', '{"formFile":"administrator\\/components\\/com_banners\\/forms\\/client.xml", "hideFields":["checked_out","checked_out_time"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":[], "displayLookup":[]}'), (12, 'User Notes', 'com_users.note', '{"special":{"dbtable":"#__user_notes","key":"id","type":"NoteTable","prefix":"Joomla\\\\Component\\\\Users\\\\Administrator\\\\Table\\\\"}}', '', '', '', '{"formFile":"administrator\\/components\\/com_users\\/forms\\/note.xml", "hideFields":["checked_out","checked_out_time", "publish_up", "publish_down"],"ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"],"displayLookup":[{"sourceColumn":"catid","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}, {"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}]}'), -(13, 'User Notes Category', 'com_users.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"}]}'); +(13, 'User Notes Category', 'com_users.category', '{"special":{"dbtable":"#__categories","key":"id","type":"CategoryTable","prefix":"Joomla\\\\Component\\\\Categories\\\\Administrator\\\\Table\\\\","config":"array()"},"common":{"dbtable":"#__ucm_content","key":"ucm_id","type":"Corecontent","prefix":"Joomla\\\\CMS\\\\Table\\\\","config":"array()"}}', '', '{"common":{"core_content_item_id":"id","core_title":"title","core_state":"published","core_alias":"alias","core_created_time":"created_time","core_modified_time":"modified_time","core_body":"description", "core_hits":"hits","core_publish_up":"null","core_publish_down":"null","core_access":"access", "core_params":"params", "core_featured":"null", "core_metadata":"metadata", "core_language":"language", "core_images":"null", "core_urls":"null", "core_version":"version", "core_ordering":"null", "core_metakey":"metakey", "core_metadesc":"metadesc", "core_catid":"parent_id", "asset_id":"asset_id"}, "special":{"parent_id":"parent_id","lft":"lft","rgt":"rgt","level":"level","path":"path","extension":"extension","note":"note"}}', '', '{"formFile":"administrator\\/components\\/com_categories\\/forms\\/category.xml", "hideFields":["checked_out","checked_out_time","version","lft","rgt","level","path","extension"], "ignoreChanges":["modified_user_id", "modified_time", "checked_out", "checked_out_time", "version", "hits", "path"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"created_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"}, {"sourceColumn":"access","targetTable":"#__viewlevels","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"modified_user_id","targetTable":"#__users","targetColumn":"id","displayColumn":"name"},{"sourceColumn":"parent_id","targetTable":"#__categories","targetColumn":"id","displayColumn":"title"},{"sourceColumn":"tags","targetTable":"#__tags","targetColumn":"id","displayColumn":"title"}]}'), +(14, 'Module', 'com_modules.module', '{"special":{"dbtable":"#__modules","key":"id","type":"Module","prefix":"Joomla\\\\CMS\\\\Table\\\\"}}', '', '{}', '', '{"formFile":"administrator\\/components\\/com_modules\\/forms\\/module.xml", "hideFields":["checked_out", "checked_out_time", "publish_up", "publish_down"], "ignoreChanges":["checked_out", "checked_out_time"], "convertToInt":["publish_up", "publish_down"], "displayLookup":[{"sourceColumn":"checked_out", "targetTable":"#__users", "targetColumn":"id", "displayColumn":"name"}]}'); SELECT setval('#__content_types_type_id_seq', 10000, false); @@ -372,6 +373,8 @@ CREATE TABLE IF NOT EXISTS "#__history" ( "sha1_hash" varchar(50) NOT NULL DEFAULT '', "version_data" text NOT NULL, "keep_forever" smallint NOT NULL DEFAULT 0, + "is_current" smallint NOT NULL DEFAULT 0, + "is_legacy" smallint NOT NULL DEFAULT 0, PRIMARY KEY ("version_id") ); CREATE INDEX "#__history_idx_ucm_item_id" ON "#__history" ("item_id"); @@ -430,7 +433,7 @@ INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subjec ('com_joomlaupdate.update.failed', 'com_joomlaupdate', '', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_SUBJECT', 'COM_JOOMLAUPDATE_UPDATE_FAILED_MAIL_BODY', '', '', '{"tags":["newversion","oldversion","sitename","url"]}'), ('plg_task_updatenotification.mail', 'plg_task_updatenotification', '', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_SUBJECT', 'PLG_TASK_UPDATENOTIFICATION_EMAIL_BODY', '', '', '{"tags":["newversion","curversion","sitename","url","link","releasenews"]}'), ('plg_user_joomla.mail', 'plg_user_joomla', '', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_SUBJECT', 'PLG_USER_JOOMLA_NEW_USER_EMAIL_BODY', '', '', '{"tags":["name","sitename","url","username","password","email"]}'), -('com_actionlogs.notification', 'com_actionlogs', '', 'COM_ACTIONLOGS_EMAIL_SUBJECT', 'COM_ACTIONLOGS_EMAIL_BODY', 'COM_ACTIONLOGS_EMAIL_HTMLBODY', '', '{"tags":["messages","message","date","extension","username"]}'), +('com_actionlogs.notification', 'com_actionlogs', '', 'COM_ACTIONLOGS_EMAIL_SUBJECT', 'COM_ACTIONLOGS_EMAIL_BODY', 'COM_ACTIONLOGS_EMAIL_HTMLBODY', '', '{"tags":["messages","message","date","extension","username","ip_address"]}'), ('com_privacy.userdataexport', 'com_privacy', '', 'COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_SUBJECT', 'COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_BODY', '', '', '{"tags":["sitename","url"]}'), ('com_privacy.notification.export', 'com_privacy', '', 'COM_PRIVACY_EMAIL_REQUEST_SUBJECT_EXPORT_REQUEST', 'COM_PRIVACY_EMAIL_REQUEST_BODY_EXPORT_REQUEST', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), ('com_privacy.notification.remove', 'com_privacy', '', 'COM_PRIVACY_EMAIL_REQUEST_SUBJECT_REMOVE_REQUEST', 'COM_PRIVACY_EMAIL_REQUEST_BODY_REMOVE_REQUEST', '', '', '{"tags":["sitename","url","tokenurl","formurl","token"]}'), @@ -451,4 +454,5 @@ INSERT INTO "#__mail_templates" ("template_id", "extension", "language", "subjec ('plg_system_tasknotification.fatal_recovery_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_FATAL_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_FATAL_MAIL_BODY', '', '', '{"tags": ["task_id", "task_title"]}'), ('plg_system_tasknotification.orphan_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_ORPHAN_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_ORPHAN_MAIL_BODY', '', '', '{"tags": ["task_id", "task_title"]}'), ('plg_system_tasknotification.success_mail', 'plg_system_tasknotification', '', 'PLG_SYSTEM_TASK_NOTIFICATION_SUCCESS_MAIL_SUBJECT', 'PLG_SYSTEM_TASK_NOTIFICATION_SUCCESS_MAIL_BODY', '', '', '{"tags":["task_id", "task_title", "exec_data_time", "task_output"]}'), -('plg_multifactorauth_email.mail', 'plg_multifactorauth_email', '', 'PLG_MULTIFACTORAUTH_EMAIL_EMAIL_SUBJECT', 'PLG_MULTIFACTORAUTH_EMAIL_EMAIL_BODY', '', '', '{"tags":["code","sitename","siteurl","username","email","fullname"]}'); +('plg_multifactorauth_email.mail', 'plg_multifactorauth_email', '', 'PLG_MULTIFACTORAUTH_EMAIL_EMAIL_SUBJECT', 'PLG_MULTIFACTORAUTH_EMAIL_EMAIL_BODY', '', '', '{"tags":["code","sitename","siteurl","username","email","fullname"]}'), +('plg_content_joomla.newarticle', 'plg_content_joomla', '', 'PLG_CONTENT_JOOMLA_NEW_ARTICLE_SUBJECT', 'PLG_CONTENT_JOOMLA_NEW_ARTICLE_BODY', '', '', '{"tags":["sitename","name","email","title","url"]}'); diff --git a/installation/src/Application/CliInstallationApplication.php b/installation/src/Application/CliInstallationApplication.php index 56f704874f473..627c688f2339d 100644 --- a/installation/src/Application/CliInstallationApplication.php +++ b/installation/src/Application/CliInstallationApplication.php @@ -121,10 +121,6 @@ public function __construct( // Store the debug value to config based on the JDEBUG flag. $this->config->set('debug', JDEBUG); - \define('JPATH_COMPONENT', JPATH_BASE); - \define('JPATH_COMPONENT_SITE', JPATH_SITE); - \define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR); - // Register the config to Factory. Factory::$config = $this->config; Factory::$language = $language; @@ -311,21 +307,4 @@ public function isClient($identifier) { return 'cli_installation' === $identifier; } - - /** - * Flag if the application instance is a CLI or web based application. - * - * Helper function, you should use the native PHP functions to detect if it is a CLI application. - * - * @return boolean - * - * @since 4.3.0 - * - * @deprecated 4.3 will be removed in 5.0 - * Use $app->isClient('cli_installation') instead - */ - public function isCli() - { - return $this->isClient('cli_installation'); - } } diff --git a/installation/src/Application/InstallationApplication.php b/installation/src/Application/InstallationApplication.php index 8f65c113e9bec..6121ccdcc5730 100644 --- a/installation/src/Application/InstallationApplication.php +++ b/installation/src/Application/InstallationApplication.php @@ -18,7 +18,6 @@ use Joomla\CMS\Document\HtmlDocument; use Joomla\CMS\Exception\ExceptionHandler; use Joomla\CMS\Factory; -use Joomla\CMS\Input\Input; use Joomla\CMS\Language\LanguageFactoryInterface; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; @@ -27,6 +26,7 @@ use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\Filesystem\Folder; +use Joomla\Input\Input; use Joomla\Registry\Registry; use Joomla\Session\SessionEvent; @@ -47,7 +47,7 @@ final class InstallationApplication extends CMSApplication * Class constructor. * * @param ?Input $input An optional argument to provide dependency injection for the application's input - * object. If the argument is a JInput object that object will become the + * object. If the argument is a Input object that object will become the * application's input object, otherwise a default input object is created. * @param ?Registry $config An optional argument to provide dependency injection for the application's * config object. If the argument is a Registry object that object will become @@ -187,11 +187,6 @@ public function dispatch() // Register the document object with Factory. Factory::$document = $document; - // Define component path. - \define('JPATH_COMPONENT', JPATH_BASE); - \define('JPATH_COMPONENT_SITE', JPATH_SITE); - \define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR); - // Execute the task. ob_start(); $this->executeController(); @@ -294,14 +289,14 @@ private function executeController() // Parse task in format controller.task if ($task !== '') { - list($controllerName, $task) = explode('.', $task, 2); + [$controllerName, $task] = explode('.', $task, 2); } $factory = new MVCFactory('Joomla\\CMS', $this->getLogger()); $factory->setDatabase($this->getContainer()->get(DatabaseInterface::class)); // Create the instance - $controller = $factory->createController($controllerName, 'Installation', [], $this, $this->input); + $controller = $factory->createController($controllerName, 'Installation', ['base_path' => JPATH_INSTALLATION], $this, $this->input); // Execute the task $controller->execute($task); @@ -368,30 +363,6 @@ public function getLocaliseAdmin(?DatabaseInterface $db = null) return $langfiles; } - /** - * Gets the name of the current template. - * - * @param boolean $params True to return the template parameters - * - * @return string|\stdClass The name of the template. - * - * @since 3.1 - */ - public function getTemplate($params = false) - { - if ($params) { - $template = new \stdClass(); - $template->template = 'template'; - $template->params = new Registry(); - $template->inheritable = 0; - $template->parent = ''; - - return $template; - } - - return 'template'; - } - /** * Initialise the application. * @@ -568,4 +539,21 @@ public function getMenu($name = null, $options = []) { return null; } + + /** + * Initialise the template. + * + * @return void + * + * @since 6.1.0 + */ + protected function initialiseTemplate(): void + { + $this->template = (object) [ + 'template' => 'template', + 'params' => new Registry(), + 'inheritable' => 0, + 'parent' => '', + ]; + } } diff --git a/installation/src/Controller/InstallationController.php b/installation/src/Controller/InstallationController.php index 5b93cdf619bd3..c3ff5ee31bed7 100644 --- a/installation/src/Controller/InstallationController.php +++ b/installation/src/Controller/InstallationController.php @@ -14,6 +14,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\Session\Session; +use Joomla\Input\Input; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -27,12 +28,12 @@ class InstallationController extends JSONController { /** - * @param array $config An optional associative array of configuration settings. - * Recognized key values include 'name', 'default_task', 'model_path', and - * 'view_path' (this list is not meant to be comprehensive). - * @param ?MVCFactoryInterface $factory The factory. - * @param ?CMSApplication $app The Application for the dispatcher - * @param ?\Joomla\CMS\Input\Input $input The Input object. + * @param array $config An optional associative array of configuration settings. + * Recognized key values include 'name', 'default_task', 'model_path', and + * 'view_path' (this list is not meant to be comprehensive). + * @param ?MVCFactoryInterface $factory The factory. + * @param ?CMSApplication $app The Application for the dispatcher + * @param ?Input $input The Input object. * * @since 3.0 */ @@ -70,6 +71,7 @@ public function dbcheck() if ($model->validate($data, 'setup') === false) { $this->app->enqueueMessage(Text::_('INSTL_DATABASE_VALIDATION_ERROR'), 'error'); $r->validated = false; + $r->error = true; $this->sendJsonResponse($r); return; diff --git a/installation/src/Form/Field/Installation/PrefixField.php b/installation/src/Form/Field/Installation/PrefixField.php index f29acdab035fb..9f839324fca42 100644 --- a/installation/src/Form/Field/Installation/PrefixField.php +++ b/installation/src/Form/Field/Installation/PrefixField.php @@ -53,7 +53,7 @@ protected function getInput() } // If a prefix is already set, use it instead. - $session = Factory::getSession()->get('setup.options', []); + $session = Factory::getApplication()->getSession()->get('setup.options', []); if (empty($session['db_prefix'])) { // Create the random prefix. diff --git a/installation/src/Helper/DatabaseHelper.php b/installation/src/Helper/DatabaseHelper.php index aa4f1351a7fb1..364c182555edd 100644 --- a/installation/src/Helper/DatabaseHelper.php +++ b/installation/src/Helper/DatabaseHelper.php @@ -12,7 +12,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\User\UserHelper; -use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseFactory; use Joomla\Database\DatabaseInterface; use Joomla\Filesystem\File; use Joomla\Filesystem\Path; @@ -113,7 +113,7 @@ public static function getDbo($driver, $host, $user, $password, $database, $pref } // Get a database object. - $db = DatabaseDriver::getInstance($options); + $db = (new DatabaseFactory())->getDriver($options['driver'], $options); } return $db; @@ -143,8 +143,8 @@ public static function getEncryptionSettings($options) /** * Get the minimum required database server version. * - * @param DatabaseDriver $db Database object - * @param \stdClass $options The session options + * @param DatabaseInterface $db Database object + * @param \stdClass $options The session options * * @return string The minimum required database server version. * @@ -318,7 +318,7 @@ public static function validateConnectionParameters($options) // Save options to session data if changed if ($optionsChanged) { $optsArr = ArrayHelper::fromObject($options); - Factory::getSession()->set('setup.options', $optsArr); + Factory::getApplication()->getSession()->set('setup.options', $optsArr); } return false; @@ -344,7 +344,7 @@ public static function checkRemoteDbHost($options) // Check the security file if the db_host is not localhost / 127.0.0.1 / ::1 if ($shouldCheckLocalhost && preg_match($localhost, $options->db_host) !== 1) { - $remoteDbFileTestsPassed = Factory::getSession()->get('remoteDbFileTestsPassed', false); + $remoteDbFileTestsPassed = Factory::getApplication()->getSession()->get('remoteDbFileTestsPassed', false); // When all checks have been passed we don't need to do this here again. if ($remoteDbFileTestsPassed === false) { @@ -353,7 +353,7 @@ public static function checkRemoteDbHost($options) 'https://docs.joomla.org/Special:MyLanguage/J3.x:Secured_procedure_for_installing_Joomla_with_a_remote_database' ); - $remoteDbFile = Factory::getSession()->get('remoteDbFile', false); + $remoteDbFile = Factory::getApplication()->getSession()->get('remoteDbFile', false); if ($remoteDbFile === false) { // Add the general message @@ -361,7 +361,7 @@ public static function checkRemoteDbHost($options) // This is the file you need to remove if you want to use a remote database $remoteDbFile = '_Joomla' . UserHelper::genRandomPassword(21) . '.txt'; - Factory::getSession()->set('remoteDbFile', $remoteDbFile); + Factory::getApplication()->getSession()->set('remoteDbFile', $remoteDbFile); // Get the path $remoteDbPath = JPATH_INSTALLATION . '/' . $remoteDbFile; @@ -380,13 +380,13 @@ public static function checkRemoteDbHost($options) 'notice' ); - Factory::getSession()->set('remoteDbFileUnwritable', true); + Factory::getApplication()->getSession()->set('remoteDbFileUnwritable', true); return false; } // Save the file name to the session - Factory::getSession()->set('remoteDbFileWrittenByJoomla', true); + Factory::getApplication()->getSession()->set('remoteDbFileWrittenByJoomla', true); // Request to delete that file Factory::getApplication()->enqueueMessage( @@ -403,7 +403,7 @@ public static function checkRemoteDbHost($options) } if ( - Factory::getSession()->get('remoteDbFileWrittenByJoomla', false) === true + Factory::getApplication()->getSession()->get('remoteDbFileWrittenByJoomla', false) === true && is_file(JPATH_INSTALLATION . '/' . $remoteDbFile) ) { // Add the general message @@ -423,7 +423,7 @@ public static function checkRemoteDbHost($options) return false; } - if (Factory::getSession()->get('remoteDbFileUnwritable', false) === true && !is_file(JPATH_INSTALLATION . '/' . $remoteDbFile)) { + if (Factory::getApplication()->getSession()->get('remoteDbFileUnwritable', false) === true && !is_file(JPATH_INSTALLATION . '/' . $remoteDbFile)) { // Add the general message Factory::getApplication()->enqueueMessage($generalRemoteDatabaseMessage, 'warning'); @@ -442,7 +442,7 @@ public static function checkRemoteDbHost($options) } // All tests for this session passed set it to the session - Factory::getSession()->set('remoteDbFileTestsPassed', true); + Factory::getApplication()->getSession()->set('remoteDbFileTestsPassed', true); } } @@ -452,8 +452,8 @@ public static function checkRemoteDbHost($options) /** * Check database server parameters after connection * - * @param DatabaseDriver $db Database object - * @param \stdClass $options The session options + * @param DatabaseInterface $db Database object + * @param \stdClass $options The session options * * @return string|boolean A string with the translated error message if * some server parameter is not ok, otherwise false. diff --git a/installation/src/Model/AutomatedUpdatesModel.php b/installation/src/Model/AutomatedUpdatesModel.php index bfbe4d9ba716b..29548d4ce2c53 100644 --- a/installation/src/Model/AutomatedUpdatesModel.php +++ b/installation/src/Model/AutomatedUpdatesModel.php @@ -51,7 +51,7 @@ public function disable() { // Get the params of com_joomlaupdate $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select('params') ->from($db->quoteName('#__extensions')) diff --git a/installation/src/Model/BaseInstallationModel.php b/installation/src/Model/BaseInstallationModel.php index e22c8b607f072..78a6d23d904d5 100644 --- a/installation/src/Model/BaseInstallationModel.php +++ b/installation/src/Model/BaseInstallationModel.php @@ -51,6 +51,6 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) */ public function getOptions() { - return Factory::getSession()->get('setup.options', []); + return Factory::getApplication()->getSession()->get('setup.options', []); } } diff --git a/installation/src/Model/ConfigurationModel.php b/installation/src/Model/ConfigurationModel.php index 915d7b469b42f..4a8f0aa845bf3 100644 --- a/installation/src/Model/ConfigurationModel.php +++ b/installation/src/Model/ConfigurationModel.php @@ -99,7 +99,7 @@ public function setup($options) } } - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('extension_id') ->from($db->quoteName('#__extensions')) ->where($db->quoteName('name') . ' = ' . $db->quote('files_joomla')); @@ -140,7 +140,7 @@ public function setup($options) $return = false; } - // This is needed because the installer loads the extension table in constructor, needs to be refactored in 5.0 + // This is needed because the installer loads the extension table in constructor, needs to be refactored in 7.0 // It doesn't honor the DatabaseAware interface Factory::getContainer()->set('\Joomla\CMS\Table\Extension', new \Joomla\CMS\Table\Extension($db)); @@ -235,7 +235,7 @@ public static function getUserId() */ protected static function generateRandUserId() { - $session = Factory::getSession(); + $session = Factory::getApplication()->getSession(); $randUserId = $session->get('randUserId'); if (empty($randUserId)) { @@ -258,7 +258,7 @@ public static function resetRandUserId() { self::$userId = 0; - Factory::getSession()->set('randUserId', self::$userId); + Factory::getApplication()->getSession()->set('randUserId', self::$userId); } /** @@ -287,7 +287,7 @@ protected function updateUserIds($db) foreach ($updatesArray as $table => $fields) { foreach ($fields as $field) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($table)) ->set($db->quoteName($field) . ' = ' . $db->quote($userId)) ->where($db->quoteName($field) . ' != 0') @@ -407,7 +407,7 @@ public function createConfiguration($options) $registry->set('cors', false); $registry->set('cors_allow_origin', '*'); $registry->set('cors_allow_methods', ''); - $registry->set('cors_allow_headers', 'Content-Type,X-Joomla-Token'); + $registry->set('cors_allow_headers', 'Content-Type,X-Joomla-Token,Authorization'); // Mail settings. $registry->set('mailonline', true); @@ -475,7 +475,7 @@ public function createConfiguration($options) } // Get the session - $session = Factory::getSession(); + $session = Factory::getApplication()->getSession(); if ($canWrite) { file_put_contents($path, $buffer); @@ -509,7 +509,7 @@ private function createRootUser($options, $db) date_default_timezone_set('UTC'); $installdate = date('Y-m-d H:i:s'); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where($db->quoteName('id') . ' = ' . $db->quote($userId)); @@ -570,7 +570,7 @@ private function createRootUser($options, $db) // Synch the sequence if pgsql if (($db->getServerType() === 'postgresql') && (!$result)) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('MAX(' . $db->quoteName('id') . ') + 1 AS ' . $db->quoteName('id')) ->from($db->quoteName('#__users')); $db->setQuery($query); diff --git a/installation/src/Model/DatabaseModel.php b/installation/src/Model/DatabaseModel.php index 7ab5bf80d808a..813d39f11531d 100644 --- a/installation/src/Model/DatabaseModel.php +++ b/installation/src/Model/DatabaseModel.php @@ -14,7 +14,7 @@ use Joomla\CMS\Installation\Helper\DatabaseHelper; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; -use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseFactory; use Joomla\Database\DatabaseInterface; use Joomla\Utilities\ArrayHelper; @@ -159,7 +159,7 @@ public function createDatabase(array $options) ]; } - $altDB = DatabaseDriver::getInstance($altDBoptions); + $altDB = (new DatabaseFactory())->getDriver($altDBoptions['driver'], $altDBoptions); // Check database server parameters $dbServerCheck = DatabaseHelper::checkDbServerParameters($altDB, $options); @@ -243,7 +243,7 @@ public function createDatabase(array $options) $options = array_merge(['db_created' => 1], $options); - Factory::getSession()->set('setup.options', $options); + Factory::getApplication()->getSession()->set('setup.options', $options); return true; } @@ -321,8 +321,8 @@ public function createTables(string $schema, array $options) /** * Method to backup all tables in a database with a given prefix. * - * @param DatabaseDriver $db DatabaseDriver object. - * @param string $prefix Database table prefix. + * @param DatabaseInterface $db Database object. + * @param string $prefix Database table prefix. * * @return boolean True on success. * diff --git a/installation/src/Model/LanguagesModel.php b/installation/src/Model/LanguagesModel.php index 62a4b25e0fe76..e52069ca40954 100644 --- a/installation/src/Model/LanguagesModel.php +++ b/installation/src/Model/LanguagesModel.php @@ -18,7 +18,8 @@ use Joomla\CMS\Installer\InstallerHelper; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; +use Joomla\CMS\Table\Update as UpdateTable; use Joomla\CMS\Updater\Update; use Joomla\CMS\Updater\Updater; use Joomla\Database\DatabaseAwareInterface; @@ -94,7 +95,7 @@ public function getItems() { // Get the extension_id of the en-GB package. $db = $this->getDatabase(); - $extQuery = $db->getQuery(true); + $extQuery = $db->createQuery(); $extQuery->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) @@ -116,7 +117,7 @@ public function getItems() */ $updater->findUpdates([$extId], 0); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the required fields from the updates table. $query->select($db->quoteName(['update_id', 'name', 'element', 'version'])) @@ -154,7 +155,7 @@ public function install($lids) $installer = clone $installerBase; // Loads the update database object that represents the language. - $language = Table::getInstance('update'); + $language = new UpdateTable($this->getDatabase()); $language->load($id); // Get the URL to the XML manifest file of the selected language. @@ -228,7 +229,7 @@ public function install($lids) */ protected function getLanguageManifest($uid) { - $instance = Table::getInstance('update'); + $instance = new UpdateTable($this->getDatabase()); $instance->load($uid); return trim($instance->detailsurl); @@ -379,7 +380,7 @@ protected function getLanguageList($clientId = 1) { // Create a new db object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select field element from the extensions table. $query->select($db->quoteName(['element', 'name'])) @@ -461,7 +462,7 @@ public function setDefault($language, $clientName = 'administrator') $params = ComponentHelper::getParams('com_languages'); $params->set($client->name, $language); - $table = Table::getInstance('extension'); + $table = new Extension($this->getDatabase()); $id = $table->find(['element' => 'com_languages']); // Load diff --git a/installation/src/Model/SetupModel.php b/installation/src/Model/SetupModel.php index 4809decf925c4..102e63c991252 100644 --- a/installation/src/Model/SetupModel.php +++ b/installation/src/Model/SetupModel.php @@ -59,7 +59,7 @@ public function storeOptions($options) } // Get the session - $session = Factory::getSession(); + $session = Factory::getApplication()->getSession(); $options['helpurl'] = $session->get('setup.helpurl', null); // Merge the new setup options into the current ones and store in the session. diff --git a/installation/src/Service/Provider/Application.php b/installation/src/Service/Provider/Application.php index b8da47fb3b480..dab5283f079c8 100644 --- a/installation/src/Service/Provider/Application.php +++ b/installation/src/Service/Provider/Application.php @@ -11,13 +11,13 @@ namespace Joomla\CMS\Installation\Service\Provider; use Joomla\CMS\Error\Renderer\JsonRenderer; -use Joomla\CMS\Input\Input as CMSInput; use Joomla\CMS\Installation\Application\CliInstallationApplication; use Joomla\CMS\Installation\Application\InstallationApplication; use Joomla\CMS\Language\LanguageFactoryInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\Priority; +use Joomla\Input\Input as CMSInput; use Joomla\Session\SessionEvents; use Joomla\Session\SessionInterface; use Psr\Log\LoggerInterface; diff --git a/installation/template/error.php b/installation/template/error.php index a06218f96fe4f..b3310731aadda 100644 --- a/installation/template/error.php +++ b/installation/template/error.php @@ -46,7 +46,7 @@
- + diff --git a/installation/template/index.php b/installation/template/index.php index b11dec7fee0fe..303a2152f1641 100644 --- a/installation/template/index.php +++ b/installation/template/index.php @@ -93,7 +93,7 @@
- + diff --git a/installation/template/js/remove.js b/installation/template/js/remove.js deleted file mode 100644 index 3e72ecec592e1..0000000000000 --- a/installation/template/js/remove.js +++ /dev/null @@ -1,224 +0,0 @@ -/** - * @package Joomla.Installation - * @copyright (C) 2017 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ -// Init on dom content loaded event -var url = Joomla.getOptions('system.installation').url ? Joomla.getOptions('system.installation').url.replace(/&/g, '&') : 'index.php'; - -if (document.getElementById('installAddFeatures')) { - document.getElementById('installAddFeatures').addEventListener('click', function(e) { - e.preventDefault(); - document.getElementById('installLanguages').classList.add('active'); - document.getElementById('automatedUpdates')?.classList?.remove('active'); - document.getElementById('installCongrat').classList.remove('active'); - document.getElementById('installFinal').classList.remove('active'); - document.getElementById('installRecommended').classList.remove('active'); - }) -} - -if (document.getElementById('skipLanguages')) { - document.getElementById('skipLanguages').addEventListener('click', function(e) { - e.preventDefault(); - document.getElementById('automatedUpdates')?.classList?.add('active'); - document.getElementById('installCongrat').classList.add('active'); - document.getElementById('installFinal').classList.add('active'); - document.getElementById('installRecommended').classList.add('active'); - document.getElementById('installLanguages').classList.remove('active'); - - if (document.getElementById('installFinal')) { - document.getElementById('installFinal').focus(); - } - }) -} - -if (document.getElementById('removeInstallationFolder')) { - document.getElementById('removeInstallationFolder') - .addEventListener('click', function (e) { - e.preventDefault(); - let confirm = window.confirm(Joomla.Text._('INSTL_REMOVE_INST_FOLDER').replace('%s', 'installation')); - if (confirm) { - Joomla.deleteJoomlaInstallationDirectory(); - } - }); -} - -if (document.getElementById('automatedUpdatesDisableButton')) { - document.getElementById('automatedUpdatesDisableButton') - .addEventListener('click', function (e) { - e.preventDefault(); - let confirm = window.confirm(Joomla.Text._('INSTL_DISABLE_AUTOUPDATE')); - if (confirm) { - Joomla.disableAutomatedUpdates(); - } - }); -} - -const completeInstallationOptions = document.querySelectorAll('.complete-installation'); - -completeInstallationOptions.forEach(function(item) { - item.addEventListener('click', function (e) { - // In development mode we show the user a pretty button to allow them to choose whether to delete the installation - // directory or not. In this case or when the installation folder has been deleted or might be partly deleted, - // the buttons just redirect to the admin or site. - // In stable release we always try to delete the folder at the first click. Maximum extermination! - if ('development' in item.dataset || 'installremoved' in item.dataset) { - window.location.href = item.dataset.href; - } else { - Joomla.deleteJoomlaInstallationDirectory(item.dataset.href); - } - - return false; - }); -}); - - -Joomla.disableAutomatedUpdates = function () { - Joomla.request({ - method: "POST", - url: Joomla.installationBaseUrl + '?task=installation.disableAutomatedUpdates&format=json', - perform: true, - token: true, - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - onSuccess: function (response) { - const successresponse = JSON.parse(response); - if (successresponse.error === true) { - if (successresponse.messages) { - Joomla.renderMessages(successresponse.messages); - Joomla.loadOptions({'csrf.token': successresponse.token}); - } else { - // Stuff went wrong. No error messages. Just panic bail! - Joomla.renderMessages({error:['Unknown error disabling the automated updates.']}); - } - } else { - const automatedUpdates = document.getElementById('automatedUpdates'); - automatedUpdates.parentNode.removeChild(automatedUpdates); - } - }, - onError: function (xhr) { - Joomla.renderMessages(Joomla.ajaxErrorsMessages(xhr)); - } - }); -} - -Joomla.deleteJoomlaInstallationDirectory = function (redirectUrl) { - Joomla.request({ - method: "POST", - url: Joomla.installationBaseUrl + '?task=installation.removeFolder&format=json', - perform: true, - token: true, - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - onSuccess: function (response) { - // If the installation folder has been deleted at least partly, i.e. also - // in case of a failure, we cannot use it anymore. - // Therefore set a marker in the admin and site buttons so they still work - // and disable buttons which will not work anymore. - completeInstallationOptions.forEach(function(item) { - item.dataset.installremoved = 'true'; - }); - if (document.getElementById('installAddFeatures')) { - document.getElementById('installAddFeatures').disabled = true; - } - if (document.getElementById('automatedUpdatesDisableButton')) { - document.getElementById('automatedUpdatesDisableButton').disabled = true; - } - if (document.getElementById('removeInstallationFolder')) { - document.getElementById('removeInstallationFolder').disabled = true; - } - const successresponse = JSON.parse(response); - if (successresponse.error === true) { - if (successresponse.messages) { - Joomla.renderMessages(successresponse.messages); - Joomla.loadOptions({'csrf.token': successresponse.token}); - } else { - // Stuff went wrong. No error messages. Just panic bail! - Joomla.renderMessages({error:['Unknown error deleting the installation folder.']}); - } - } else { - const customInstallation = document.getElementById('customInstallation'); - customInstallation.parentNode.removeChild(customInstallation); - - const automatedUpdates = document.getElementById('automatedUpdates'); - - // This will only exist if it has not been removed with a previous step - if (automatedUpdates) { - automatedUpdates.parentNode.removeChild(automatedUpdates); - } - - const removeInstallationTab = document.getElementById('removeInstallationTab'); - - // This will only exist in debug mode - if (removeInstallationTab) { - removeInstallationTab.parentNode.removeChild(removeInstallationTab); - } - - if (redirectUrl) { - window.location.href = redirectUrl; - } - } - }, - onError: function (xhr) { - Joomla.renderMessages(Joomla.ajaxErrorsMessages(xhr)); - } - }); -} - -if (document.getElementById('installLanguagesButton')) { - document.getElementById('installLanguagesButton').addEventListener('click', function(e) { - e.preventDefault(); - var form = document.getElementById('languagesForm'); - if (form) { - Joomla.removeMessages(); - document.body.appendChild(document.createElement('joomla-core-loader')); - - // Install the extra languages - try { - Joomla.install(['languages'], form, true); - } catch (err) { - const loader = document.querySelector('joomla-core-loader'); - if (loader) { - loader.remove(); - } - } - } - }) -} - -if (document.getElementById('defaultLanguagesButton')) { - document.getElementById('defaultLanguagesButton') - .addEventListener('click', (e) => { - let frontendlang = 'en-GB'; - if (document.querySelector('input[name="frontendlang"]:checked')) { - frontendlang = document.querySelector('input[name="frontendlang"]:checked').value; - } - - let administratorlang = 'en-GB'; - if (document.querySelector('input[name="administratorlang"]:checked')) { - administratorlang = document.querySelector('input[name="administratorlang"]:checked').value; - } - - e.preventDefault(); - - Joomla.request({ - method: 'POST', - url: `${Joomla.installationBaseUrl}?view=setup&frontendlang=${frontendlang}&administratorlang=${administratorlang}&task=language.setdefault&format=json`, - perform: true, - token: true, - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - onSuccess(response) { - const successresponse = JSON.parse(response); - if (successresponse.messages) { - Joomla.renderMessages(successresponse.messages, '#system-message-container'); - } - Joomla.loadOptions({'csrf.token': successresponse.token}); - }, - onError(xhr) { - Joomla.renderMessages(Joomla.ajaxErrorsMessages(xhr)); - }, - }); - - if (document.getElementById('header')) { - document.getElementById('header').scrollIntoView(); - } - }); -} diff --git a/installation/tmpl/preinstall/default.php b/installation/tmpl/preinstall/default.php index 6a19e70924fd6..d38a98f4f71b3 100644 --- a/installation/tmpl/preinstall/default.php +++ b/installation/tmpl/preinstall/default.php @@ -9,11 +9,8 @@ defined('_JEXEC') or die; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; -HTMLHelper::_('behavior.formvalidator'); - /** @var \Joomla\CMS\Installation\View\Preinstall\HtmlView $this */ ?>
diff --git a/installation/tmpl/remove/default.php b/installation/tmpl/remove/default.php index 99ff60cc1d3a3..7cf8182539ee5 100644 --- a/installation/tmpl/remove/default.php +++ b/installation/tmpl/remove/default.php @@ -14,8 +14,6 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Uri\Uri; -HTMLHelper::_('behavior.formvalidator'); - $direction = Factory::getLanguage()->isRtl() ? 'left' : 'right'; /** @var \Joomla\CMS\Installation\View\Remove\HtmlView $this */ diff --git a/installation/tmpl/setup/default.php b/installation/tmpl/setup/default.php index 85d1e94eef988..df441fc3ace2f 100644 --- a/installation/tmpl/setup/default.php +++ b/installation/tmpl/setup/default.php @@ -14,29 +14,16 @@ use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; -HTMLHelper::_('behavior.formvalidator'); - $direction = Factory::getLanguage()->isRtl() ? 'left' : 'right'; /** @var \Joomla\CMS\Installation\View\Setup\HtmlView $this */ + +$wa = $this->getDocument()->getWebAssetManager(); + +$wa->useScript('joomla.dialog-autocreate'); ?>
-
-
- - - -
-
- form->renderField('language'); ?> -
- - - -
-
-
@@ -137,5 +124,31 @@ +
+
+ + Text::_('INSTL_SELECT_INSTALL_LANG'), + 'iconHeader' => 'icon-language', + 'src' => '#languageSelect', + ]; + + $text = ''; + + $text .= ''; + + echo Text::sprintf('INSTL_SELECTED_INSTALL_LANGUAGE', $text); + ?> +
+ + + + +
diff --git a/language/en-GB/com_content.ini b/language/en-GB/com_content.ini index 7ffe305b55ffc..1f6f55726ff90 100644 --- a/language/en-GB/com_content.ini +++ b/language/en-GB/com_content.ini @@ -32,6 +32,7 @@ COM_CONTENT_FEED_READMORE="Read More …" COM_CONTENT_FIELD_ARTICLETEXT_LABEL="Article Text" COM_CONTENT_FIELD_FEATURED_DOWN_LABEL="Finish Featured" COM_CONTENT_FIELD_FEATURED_UP_LABEL="Start Featured" +COM_CONTENT_FIELD_FIGURE_CLASS_LABEL="Figure Class" COM_CONTENT_FIELD_FULL_LABEL="Full Article Image" COM_CONTENT_FIELD_IMAGE_ALT_EMPTY_DESC="Decorative Image - no description required" COM_CONTENT_FIELD_IMAGE_ALT_EMPTY_LABEL="No Description" @@ -68,6 +69,7 @@ COM_CONTENT_MORE_ARTICLES="More Articles …" COM_CONTENT_NEW_ARTICLE="New Article" COM_CONTENT_NO_ARTICLES="There are no articles in this category. If subcategories display on this page, they may have articles." COM_CONTENT_NUM_ITEMS="Article Count:" +;Deprecated, will be removed in 7.0 COM_CONTENT_ON_NEW_CONTENT="A new Article has been submitted by '%1$s' entitled '%2$s'." COM_CONTENT_ORDERING="Ordering:
New articles default to the first position in the Category. The ordering can be changed in Backend." COM_CONTENT_PAGEBREAK_DOC_TITLE="Page Break" diff --git a/language/en-GB/com_users.ini b/language/en-GB/com_users.ini index c49d8509f26e8..42479b546fb19 100644 --- a/language/en-GB/com_users.ini +++ b/language/en-GB/com_users.ini @@ -5,6 +5,7 @@ COM_USERS_ACTIVATION_TOKEN_NOT_FOUND="Verification code not found. Check if your account is already activated and try to log in." COM_USERS_CAPTCHA_LABEL="Captcha" +COM_USERS_COMPLETE="Complete Password Reset" COM_USERS_DATABASE_ERROR="Error getting the user from the database: %s" COM_USERS_EDIT_PROFILE="Edit Profile" COM_USERS_EMAIL_ACCOUNT_DETAILS="Account Details for {NAME} at {SITENAME}" @@ -108,6 +109,7 @@ COM_USERS_REGISTRATION_ACL_ADMIN_ACTIVATION="Please log in to confirm that you a COM_USERS_REGISTRATION_ACL_ADMIN_ACTIVATION_PERMISSIONS="You are not authorised to activate new accounts, please log in with a privileged account." COM_USERS_REGISTRATION_ACTIVATE_SUCCESS="Your Account has been activated. You can now log in using the username and password you chose during the registration." COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_FAILED="An error was encountered while sending activation notification email" +COM_USERS_REGISTRATION_ACTIVATION_NOTIFY_SEND_MAIL_SUCCESS="The user has been notified that their account has been activated." COM_USERS_REGISTRATION_ACTIVATION_SAVE_FAILED="Failed to save activation data: %s" COM_USERS_REGISTRATION_ADMINACTIVATE_SUCCESS="The user's account has been activated and the user has been notified about it." COM_USERS_REGISTRATION_COMPLETE_ACTIVATE="Your account has been created and an activation link has been sent to the email address you entered. Note that you must activate the account by selecting the activation link when you get the email before you can login." diff --git a/language/en-GB/files_joomla.sys.ini b/language/en-GB/files_joomla.sys.ini index 62031e108ca39..a569b4686c3ab 100644 --- a/language/en-GB/files_joomla.sys.ini +++ b/language/en-GB/files_joomla.sys.ini @@ -4,8 +4,4 @@ ; Note : All ini files need to be saved as UTF-8 FILES_JOOMLA="Joomla CMS" -FILES_JOOMLA_XML_DESCRIPTION="Joomla! 5 Content Management System." - -; All the following strings are deprecated and will be removed with 6.0 -FILES_JOOMLA_ERROR_FILE_FOLDER="Error on deleting file or folder %s" -FILES_JOOMLA_ERROR_MANIFEST="Error on updating manifest cache: (type, element, folder, client) = (%s, %s, %s, %s)" +FILES_JOOMLA_XML_DESCRIPTION="Joomla! 6 Content Management System." diff --git a/language/en-GB/install.xml b/language/en-GB/install.xml index 4c9f4379a15f9..36c28c489290e 100644 --- a/language/en-GB/install.xml +++ b/language/en-GB/install.xml @@ -2,7 +2,7 @@ English (en-GB) en-GB - 5.4.8 + 6.2.0 2026-08 Joomla! Project admin@joomla.org diff --git a/language/en-GB/joomla.ini b/language/en-GB/joomla.ini index 5c1f063cbf05a..4a1e16ff22001 100644 --- a/language/en-GB/joomla.ini +++ b/language/en-GB/joomla.ini @@ -156,8 +156,6 @@ JERROR_LAYOUT_AN_OUT_OF_DATE_BOOKMARK_FAVOURITE="an out-of-date bookmark JERROR_LAYOUT_ERROR_HAS_OCCURRED_WHILE_PROCESSING_YOUR_REQUEST="An error has occurred while processing your request." JERROR_LAYOUT_GO_TO_THE_HOME_PAGE="Go to the Home Page" JERROR_LAYOUT_HOME_PAGE="Home Page" -; deprecated will be removed in 6.0 -JERROR_LAYOUT_MIS_TYPED_ADDRESS="a mistyped address" JERROR_LAYOUT_MISTYPED_ADDRESS="a mistyped address" JERROR_LAYOUT_NOT_ABLE_TO_VISIT="You may not be able to visit this page because of:" JERROR_LAYOUT_PAGE_NOT_FOUND="The requested page can't be found." @@ -185,8 +183,11 @@ JFIELD_ALIAS_LABEL="Alias" JFIELD_ALIAS_PLACEHOLDER="Auto-generate from title" JFIELD_ALT_PAGE_TITLE_LABEL="Alternative Page Title" JFIELD_CATEGORY_DESC="Category" +; The following string is deprecated and will be removed with 7.0 JFIELD_COLOR_SELECT="Select a colour" +; The following string is deprecated and will be removed with 7.0 JFIELD_COLOR_TRANSPARENT="No colour, transparent" +; The following string is deprecated and will be removed with 7.0 JFIELD_COLOR_VALUE="Colour with hexadecimal value of" JFIELD_FIELDS_CATEGORY_DESC="Select the category that this field is assigned to." JFIELD_LANGUAGE_DESC="Assign a language to this article." @@ -495,6 +496,7 @@ PHPMAILER_RECIPIENTS_FAILED="SMTP Error! The following recipients failed: " PHPMAILER_SIGNING_ERROR="Signing error: " PHPMAILER_SMTP_CONNECT_FAILED="SMTP connect failed" PHPMAILER_SMTP_ERROR="SMTP server error: " +; Deprecated, will be removed with 7.0 PHPMAILER_TLS="Could not start TLS" PHPMAILER_VARIABLE_SET="Can't set or reset variable: " diff --git a/language/en-GB/langmetadata.xml b/language/en-GB/langmetadata.xml index 40936753234fd..b9a021f27e871 100644 --- a/language/en-GB/langmetadata.xml +++ b/language/en-GB/langmetadata.xml @@ -1,7 +1,7 @@ English (en-GB) - 5.4.8 + 6.2.0 2026-08 Joomla! Project admin@joomla.org diff --git a/language/en-GB/lib_joomla.ini b/language/en-GB/lib_joomla.ini index 9d68f025455cf..105557192ced8 100644 --- a/language/en-GB/lib_joomla.ini +++ b/language/en-GB/lib_joomla.ini @@ -255,6 +255,7 @@ JLIB_FILTER_PARAMS_TEXT="Text" JLIB_FORM_BUTTON_CLEAR="Clear" JLIB_FORM_BUTTON_SELECT="Select" +JLIB_FORM_CHANGE_FILE="Change File" JLIB_FORM_CHANGE_IMAGE="Change Image" JLIB_FORM_CHANGE_IMAGE_BUTTON="Change Image Button" JLIB_FORM_CHANGE_USER="Select User" @@ -271,11 +272,20 @@ JLIB_FORM_FIELD_INVALID_MIN_TIME="The time you entered is before the minimum tim JLIB_FORM_FIELD_INVALID_TIME_INPUT="Invalid time format. Please use hh:mm." JLIB_FORM_FIELD_INVALID_TIME_INPUT_SECONDS="Invalid time format. Please use hh:mm:ss." JLIB_FORM_FIELD_INVALID_VALUE="This value is not valid" -JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_LABEL="Media" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_LABEL="Media (%s)" JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_ALT_EMPTY_DESC="Decorative Image - no description required" JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_ALT_EMPTY_LABEL="No Description" JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_ALT_TEXT_LABEL="Image Description (Alt Text)" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_AUDIO_LABEL="Audio" JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_IMAGEFILE_LABEL="Image" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_LINKTEXT_DEFAULT_VALUE="Download {filename}" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_LINKTEXT_DESC="Specify the link text for non-image file." +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_LINKTEXT_LABEL="Link Text" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_AUDIOS="Audio" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_DOCUMENTS="Document" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_IMAGES="Image" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_VIDEOS="Video" +JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_VIDEO_POSTER_LABEL="Video Poster" JLIB_FORM_FIELD_PARAM_CALENDAR_FORMAT_DESC="The date format to be used. This is in the format used by PHP to specify date string formats (see below). If no format argument is given, '%Y-%m-%d' is assumed (giving dates like '2008-04-16')." JLIB_FORM_FIELD_PARAM_CALENDAR_FORMAT_LABEL="Format" JLIB_FORM_FIELD_PARAM_CHECKBOX_MULTIPLE_DESC="Allow multiple values to be selected." @@ -375,8 +385,11 @@ JLIB_HTML_BATCH_MOVE="Move" JLIB_HTML_BATCH_MOVE_QUESTION="Action to Perform" JLIB_HTML_BATCH_NO_CATEGORY="- Don't copy or move -" JLIB_HTML_BATCH_NOCHANGE="- Keep original Access Levels -" -JLIB_HTML_BATCH_TAG_LABEL="Add Tag" +JLIB_HTML_BATCH_TAG_ADD="Add" +JLIB_HTML_BATCH_TAG_ADDREMOVE_QUESTION="Action to Perform" +JLIB_HTML_BATCH_TAG_LABEL="Add or Remove Tag" JLIB_HTML_BATCH_TAG_NOCHANGE="- Keep original Tags -" +JLIB_HTML_BATCH_TAG_REMOVE="Remove" JLIB_HTML_BATCH_USER_LABEL="Set User." JLIB_HTML_BATCH_USER_NOCHANGE="- Keep original User -" JLIB_HTML_BATCH_USER_NOUSER="No User." @@ -619,8 +632,6 @@ JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MANIFEST_NOT_REMOVED="Package Uninstall: Err JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MISSING_EXTENSION="Package Uninstall: This extension is missing or has already been uninstalled: %s" JLIB_INSTALLER_ERROR_PACK_UNINSTALL_MISSINGMANIFEST="Package Uninstall: Missing manifest file." JLIB_INSTALLER_ERROR_PACK_UNINSTALL_NOT_PROPER="Package Uninstall: This extension may have already been uninstalled or might not have been uninstalled properly: %s" -; The following string is deprecated and will be removed with 6.0 -JLIB_INSTALLER_ERROR_PACK_UNINSTALL_UNKNOWN_EXTENSION="Trying to uninstall unknown extension from package. This extension may have already been removed earlier." JLIB_INSTALLER_ERROR_PACK_UNINSTALL_WARNCOREPACK="Package Uninstall: Trying to uninstall core package." JLIB_INSTALLER_ERROR_PLG_DISCOVER_STORE_DETAILS="Plugin Discover install: Failed to store plugin details." JLIB_INSTALLER_ERROR_PLG_REFRESH_MANIFEST_CACHE="Plugin Refresh manifest cache: Failed to store plugin details." @@ -674,6 +685,7 @@ JLIB_JS_AJAX_ERROR_TIMEOUT="A timeout has occurred while fetching the JSON data. JLIB_LANGUAGE_ERROR_CANNOT_LOAD_METADATA="Could not load %s metadata from %s." JLIB_LANGUAGE_ERROR_CANNOT_LOAD_METAFILE="Could not load %s language XML file from %s." +JLIB_LANGUAGE_ERROR_CANNOT_WRITE_CACHE="Unable to write cache file for %s." JLIB_LOGIN_AUTHORISATION="Your access has been authorised." JLIB_LOGIN_DENIED="Your access has been denied." @@ -683,6 +695,8 @@ JLIB_MAIL_FUNCTION_DISABLED="The mail() function has been disabled and the mail JLIB_MAIL_FUNCTION_OFFLINE="The mail function has been disabled by an administrator." JLIB_MAIL_INVALID_EMAIL_SENDER="Invalid email sender: %s" +JLIB_MEDIA_ERROR_SVG_ISSUE="SVG Issue: %s" +JLIB_MEDIA_ERROR_SVG_UNKNOWN="Unknown SVG error" JLIB_MEDIA_ERROR_UPLOAD_INPUT="Unable to upload file." JLIB_MEDIA_ERROR_WARNFILENAME="File name must only have alphanumeric characters and no spaces." JLIB_MEDIA_ERROR_WARNFILETOOLARGE="This file is too large to upload." diff --git a/language/en-GB/mod_articles.ini b/language/en-GB/mod_articles.ini index 1ae372de8848a..64a22c778421d 100644 --- a/language/en-GB/mod_articles.ini +++ b/language/en-GB/mod_articles.ini @@ -70,6 +70,7 @@ MOD_ARTICLES_FIELD_TITLE_HEADING_NONE="None" MOD_ARTICLES_FIELD_TITLE_LABEL="Article Title" MOD_ARTICLES_FIELD_TRIGGER_EVENTS_DESC="Enable this option to trigger four plugin events (onContentPrepare, afterDisplayTitle, beforeDisplayContent, afterDisplayContent) for each article in the results list." MOD_ARTICLES_FIELD_TRIGGER_EVENTS_LABEL="Trigger Plugin Events" +MOD_ARTICLES_FIELD_UNPUBLISHED_LABEL="Show Unpublished Articles" MOD_ARTICLES_INFO="Details" MOD_ARTICLES_OPTION_ASCENDING_VALUE="Ascending" MOD_ARTICLES_OPTION_CREATED_VALUE="Created Date" diff --git a/language/en-GB/mod_login.ini b/language/en-GB/mod_login.ini index f63a865d26f21..931e6d229561d 100644 --- a/language/en-GB/mod_login.ini +++ b/language/en-GB/mod_login.ini @@ -14,6 +14,10 @@ MOD_LOGIN_FIELD_POST_TEXT_LABEL="Post-text" MOD_LOGIN_FIELD_PRE_TEXT_LABEL="Pre-text" MOD_LOGIN_FIELD_PROFILE_LABEL="Profile Link" MOD_LOGIN_FIELD_REGISTRATION_MENU_LABEL="Registration Page" +MOD_LOGIN_FIELD_SHOW_PASSWORD_RESET_DESC="Show the link that lets users request a password reset." +MOD_LOGIN_FIELD_SHOW_PASSWORD_RESET_LABEL="Reset Password Link" +MOD_LOGIN_FIELD_SHOW_USERNAME_REMINDER_DESC="Show the link that lets users request a reminder of their username." +MOD_LOGIN_FIELD_SHOW_USERNAME_REMINDER_LABEL="Forgot Username Link" MOD_LOGIN_FIELD_USETEXT_LABEL="Display Labels" MOD_LOGIN_FORGOT_YOUR_PASSWORD="Forgot your password?" MOD_LOGIN_FORGOT_YOUR_USERNAME="Forgot your username?" diff --git a/language/en-GB/mod_menu.ini b/language/en-GB/mod_menu.ini index 01c0ddb9d2ef3..a3e5902b6f126 100644 --- a/language/en-GB/mod_menu.ini +++ b/language/en-GB/mod_menu.ini @@ -14,4 +14,6 @@ MOD_MENU_FIELD_TAG_ID_LABEL="Menu Tag ID" MOD_MENU_FIELD_TARGET_DESC="JavaScript values to position a popup window, eg top=50, left=50, width=200, height=300." MOD_MENU_FIELD_TARGET_LABEL="Target Position" MOD_MENU_TOGGLE="Toggle Navigation" +MOD_MENU_TOGGLE_SUBMENU_LABEL="More about: %s" MOD_MENU_XML_DESCRIPTION="This module displays a menu on the Frontend." + diff --git a/language/en-GB/tpl_cassiopeia.ini b/language/en-GB/tpl_cassiopeia.ini index ea9946904cb93..f8b0cd3cd8106 100644 --- a/language/en-GB/tpl_cassiopeia.ini +++ b/language/en-GB/tpl_cassiopeia.ini @@ -6,12 +6,23 @@ CASSIOPEIA="Cassiopeia Site template" TPL_CASSIOPEIA_BACKTOTOP="Back to Top" TPL_CASSIOPEIA_BACKTOTOP_LABEL="Back-to-top Link" +TPL_CASSIOPEIA_BODY_BACKGROUND_COLOR_LABEL="Body Background Colour" +TPL_CASSIOPEIA_BODY_SIZE="Body Font Size (rem)" +TPL_CASSIOPEIA_BODY_TEXT_COLOR_LABEL="Body Text Colour" TPL_CASSIOPEIA_BRAND_LABEL="Brand" +TPL_CASSIOPEIA_BUTTON_BACKGROUND_COLOR_LABEL="Button Primary Background Colour" +TPL_CASSIOPEIA_BUTTON_BACKGROUND_HOVER_COLOR_LABEL="Button Primary Hover Background Colour" +TPL_CASSIOPEIA_BUTTON_COLOR_LABEL="Button Primary Text Colour" +TPL_CASSIOPEIA_BUTTON_HOVER_COLOR_LABEL="Button Primary Hover Text Colour" +TPL_CASSIOPEIA_COLORS_FIELDSET_LABEL="Colour Settings" TPL_CASSIOPEIA_COLOR_NAME_ALTERNATIVE="Alternative" +TPL_CASSIOPEIA_COLOR_NAME_CUSTOM="Custom" TPL_CASSIOPEIA_COLOR_NAME_LABEL="Colour Theme" TPL_CASSIOPEIA_COLOR_NAME_STANDARD="Standard" +TPL_CASSIOPEIA_EXTENDED_XML_DESCRIPTION="Continuing the space theme (Solarflare from 1.0, Milkyway from 1.5 and Protostar from 3.0), Cassiopeia is the Joomla site template based on Bootstrap 5. This is an extended child version with a new colour set for the base Cassiopeia template." TPL_CASSIOPEIA_FLUID="Fluid" TPL_CASSIOPEIA_FLUID_LABEL="Layout" +TPL_CASSIOPEIA_FONTS_FIELDSET_LABEL="Font Settings" TPL_CASSIOPEIA_FONT_GROUP_LOCAL="Fonts from Folder" TPL_CASSIOPEIA_FONT_GROUP_WEB="Fonts from Web" TPL_CASSIOPEIA_FONT_LABEL="Fonts Scheme" @@ -34,10 +45,19 @@ TPL_CASSIOPEIA_FONT_SYSTEM_STACK_SYSTEM_OLDSTYLE="Old Style" TPL_CASSIOPEIA_FONT_SYSTEM_STACK_SYSTEM_ROUNDED="Rounded Sans" TPL_CASSIOPEIA_FONT_SYSTEM_STACK_SYSTEM_SLAB="Slab Serif" TPL_CASSIOPEIA_FONT_SYSTEM_STACK_SYSTEM_TRANSITIONAL="Transitional" +TPL_CASSIOPEIA_FOOTER_BACKGROUND_COLOR_LABEL="Footer Background Colour" +TPL_CASSIOPEIA_FOOTER_TEXT_COLOR_LABEL="Footer Text Colour" +TPL_CASSIOPEIA_H1_SIZE="H1 Font Size (rem)" +TPL_CASSIOPEIA_H2_SIZE="H2 Font Size (rem)" +TPL_CASSIOPEIA_H3_SIZE="H3 Font Size (rem)" +TPL_CASSIOPEIA_HEADER_BACKGROUND_COLOR_LABEL="Header Background Colour" +TPL_CASSIOPEIA_HEADER_TEXT_COLOR_LABEL="Header Text Colour" +TPL_CASSIOPEIA_LINK_COLOR_LABEL="Links Colour" +TPL_CASSIOPEIA_LINK_HOVER_COLOR_LABEL="Links Hover Colour" TPL_CASSIOPEIA_LOGO_LABEL="Logo" TPL_CASSIOPEIA_STATIC="Static" TPL_CASSIOPEIA_STICKY_LABEL="Sticky Header" TPL_CASSIOPEIA_TAGLINE_DESC="Optional text to show as a subheading" TPL_CASSIOPEIA_TAGLINE_LABEL="Tagline" TPL_CASSIOPEIA_TITLE="Title (alternative to logo)" -TPL_CASSIOPEIA_XML_DESCRIPTION="Continuing the space theme (Solarflare from 1.0, Milkyway from 1.5 and Protostar from 3.0), Cassiopeia is the Joomla 4 and Joomla 5 site template based on Bootstrap 5." +TPL_CASSIOPEIA_XML_DESCRIPTION="Continuing the space theme (Solarflare from 1.0, Milkyway from 1.5 and Protostar from 3.0), Cassiopeia is the Joomla site template based on Bootstrap 5." diff --git a/language/en-GB/tpl_cassiopeia.sys.ini b/language/en-GB/tpl_cassiopeia.sys.ini index 42e58e4a3bd90..88d27dac3095b 100644 --- a/language/en-GB/tpl_cassiopeia.sys.ini +++ b/language/en-GB/tpl_cassiopeia.sys.ini @@ -1,28 +1,31 @@ -; Joomla! Project -; (C) 2017 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 - -CASSIOPEIA="Cassiopeia Site template" -TPL_CASSIOPEIA_MOD_CUSTOM_LAYOUT_BANNER="Banner" -TPL_CASSIOPEIA_MOD_MENU_LAYOUT_COLLAPSE-METISMENU="Collapsible Dropdown" -TPL_CASSIOPEIA_MOD_MENU_LAYOUT_DROPDOWN-METISMENU="Dropdown" -TPL_CASSIOPEIA_POSITION_BANNER="Banner" -TPL_CASSIOPEIA_POSITION_BELOW-TOP="Below Top" -TPL_CASSIOPEIA_POSITION_BOTTOM-A="Bottom-a" -TPL_CASSIOPEIA_POSITION_BOTTOM-B="Bottom-b" -TPL_CASSIOPEIA_POSITION_BREADCRUMBS="Breadcrumbs" -TPL_CASSIOPEIA_POSITION_DEBUG="Debug" -TPL_CASSIOPEIA_POSITION_ERROR-403="Error 403" -TPL_CASSIOPEIA_POSITION_ERROR-404="Error 404" -TPL_CASSIOPEIA_POSITION_FOOTER="Footer" -TPL_CASSIOPEIA_POSITION_MAIN-BOTTOM="Main-bottom" -TPL_CASSIOPEIA_POSITION_MAIN-TOP="Main-top" -TPL_CASSIOPEIA_POSITION_MENU="Menu" -TPL_CASSIOPEIA_POSITION_SEARCH="Search" -TPL_CASSIOPEIA_POSITION_SIDEBAR-LEFT="Sidebar-left" -TPL_CASSIOPEIA_POSITION_SIDEBAR-RIGHT="Sidebar-right" -TPL_CASSIOPEIA_POSITION_TOP-A="Top-a" -TPL_CASSIOPEIA_POSITION_TOP-B="Top-b" -TPL_CASSIOPEIA_POSITION_TOPBAR="Top Bar" -TPL_CASSIOPEIA_XML_DESCRIPTION="Continuing the space theme (Solarflare from 1.0, Milkyway from 1.5 and Protostar from 3.0), Cassiopeia is the Joomla 4 and Joomla 5 site template based on Bootstrap 5." +; Joomla! Project +; (C) 2017 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 + +CASSIOPEIA="Cassiopeia Site template" +TPL_CASSIOPEIA_COLORS_FIELDSET_LABEL="Colour Settings" +TPL_CASSIOPEIA_EXTENDED_XML_DESCRIPTION="Continuing the space theme (Solarflare from 1.0, Milkyway from 1.5 and Protostar from 3.0), Cassiopeia is the Joomla site template based on Bootstrap 5. This is an extended child version with a new colour set for the base Cassiopeia template." +TPL_CASSIOPEIA_FONTS_FIELDSET_LABEL="Font Settings" +TPL_CASSIOPEIA_MOD_CUSTOM_LAYOUT_BANNER="Banner" +TPL_CASSIOPEIA_MOD_MENU_LAYOUT_COLLAPSE-METISMENU="Collapsible Dropdown" +TPL_CASSIOPEIA_MOD_MENU_LAYOUT_DROPDOWN-METISMENU="Dropdown" +TPL_CASSIOPEIA_POSITION_BANNER="Banner" +TPL_CASSIOPEIA_POSITION_BELOW-TOP="Below Top" +TPL_CASSIOPEIA_POSITION_BOTTOM-A="Bottom-a" +TPL_CASSIOPEIA_POSITION_BOTTOM-B="Bottom-b" +TPL_CASSIOPEIA_POSITION_BREADCRUMBS="Breadcrumbs" +TPL_CASSIOPEIA_POSITION_DEBUG="Debug" +TPL_CASSIOPEIA_POSITION_ERROR-403="Error 403" +TPL_CASSIOPEIA_POSITION_ERROR-404="Error 404" +TPL_CASSIOPEIA_POSITION_FOOTER="Footer" +TPL_CASSIOPEIA_POSITION_MAIN-BOTTOM="Main-bottom" +TPL_CASSIOPEIA_POSITION_MAIN-TOP="Main-top" +TPL_CASSIOPEIA_POSITION_MENU="Menu" +TPL_CASSIOPEIA_POSITION_SEARCH="Search" +TPL_CASSIOPEIA_POSITION_SIDEBAR-LEFT="Sidebar-left" +TPL_CASSIOPEIA_POSITION_SIDEBAR-RIGHT="Sidebar-right" +TPL_CASSIOPEIA_POSITION_TOP-A="Top-a" +TPL_CASSIOPEIA_POSITION_TOP-B="Top-b" +TPL_CASSIOPEIA_POSITION_TOPBAR="Top Bar" +TPL_CASSIOPEIA_XML_DESCRIPTION="Continuing the space theme (Solarflare from 1.0, Milkyway from 1.5 and Protostar from 3.0), Cassiopeia is the Joomla site template based on Bootstrap 5." diff --git a/layouts/joomla/content/category_default.php b/layouts/joomla/content/category_default.php index 8b7fc1f7dfb57..51dcb8a8644ba 100644 --- a/layouts/joomla/content/category_default.php +++ b/layouts/joomla/content/category_default.php @@ -10,10 +10,15 @@ defined('_JEXEC') or die; +use Joomla\CMS\Event\Content\AfterDisplayEvent; +use Joomla\CMS\Event\Content\AfterTitleEvent; +use Joomla\CMS\Event\Content\BeforeDisplayEvent; +use Joomla\CMS\Event\Content\ContentPrepareEvent; use Joomla\CMS\Factory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; +use Joomla\Event\DispatcherInterface; /** * Note that this layout opens a div with the page class suffix. If you do not use the category children @@ -26,19 +31,40 @@ $className = substr($extension, 4); $htag = $params->get('show_page_heading') ? 'h2' : 'h1'; -$app = Factory::getApplication(); +$dispatcher = Factory::getContainer()->get(DispatcherInterface::class); $category->text = $category->description; -$app->triggerEvent('onContentPrepare', [$extension . '.categories', &$category, &$params, 0]); + +$contentEventArguments = [ + 'context' => $extension . '.categories', + 'subject' => $category, + 'params' => $params, + 'page' => 0, +]; + +$dispatcher->dispatch('onContentPrepare', new ContentPrepareEvent('onContentPrepare', $contentEventArguments)); + $category->description = $category->text; -$results = $app->triggerEvent('onContentAfterTitle', [$extension . '.categories', &$category, &$params, 0]); +$results = $dispatcher->dispatch( + 'onContentAfterTitle', + new AfterTitleEvent('onContentAfterTitle', $contentEventArguments) +)->getArgument('result', []); + $afterDisplayTitle = trim(implode("\n", $results)); -$results = $app->triggerEvent('onContentBeforeDisplay', [$extension . '.categories', &$category, &$params, 0]); +$results = $dispatcher->dispatch( + 'onContentBeforeDisplay', + new BeforeDisplayEvent('onContentBeforeDisplay', $contentEventArguments) +)->getArgument('result', []); + $beforeDisplayContent = trim(implode("\n", $results)); -$results = $app->triggerEvent('onContentAfterDisplay', [$extension . '.categories', &$category, &$params, 0]); +$results = $dispatcher->dispatch( + 'onContentAfterDisplay', + new AfterDisplayEvent('onContentAfterDisplay', $contentEventArguments) +)->getArgument('result', []); + $afterDisplayContent = trim(implode("\n", $results)); /** diff --git a/layouts/joomla/content/emptystate.php b/layouts/joomla/content/emptystate.php index 2abe33d2ab641..dfe7a9f8bba62 100644 --- a/layouts/joomla/content/emptystate.php +++ b/layouts/joomla/content/emptystate.php @@ -29,6 +29,8 @@ $icon = $displayData['icon'] ?? 'icon-copy article'; $append = $displayData['formAppend'] ?? ''; $btnadd = $displayData['btnadd'] ?? Text::_($textPrefix . '_EMPTYSTATE_BUTTON_ADD'); + +$controlFields = $displayData['controlFields'] ?? ''; ?>
@@ -58,7 +60,11 @@ class="btn btn-outline-secondary btn-lg px-4"> - - - + + + + + + +
diff --git a/layouts/joomla/content/full_image.php b/layouts/joomla/content/full_image.php index 94e4ffd94e41f..1075ffabcb479 100644 --- a/layouts/joomla/content/full_image.php +++ b/layouts/joomla/content/full_image.php @@ -19,13 +19,15 @@ return; } -$imgclass = empty($images->float_fulltext) ? $params->get('float_fulltext') : $images->float_fulltext; +$figureClass = empty($images->float_fulltext) ? $params->get('float_fulltext') : $images->float_fulltext; +$imageClass = empty($images->imgclass_fulltext) ? $params->get('imgclass_fulltext') : $images->imgclass_fulltext; $layoutAttr = [ 'src' => $images->image_fulltext, 'alt' => empty($images->image_fulltext_alt) && empty($images->image_fulltext_alt_empty) ? false : $images->image_fulltext_alt, + 'class' => $imageClass, ]; ?> -
+
image_fulltext_caption) && $images->image_fulltext_caption !== '') : ?>
escape($images->image_fulltext_caption); ?>
diff --git a/layouts/joomla/content/icons/create.php b/layouts/joomla/content/icons/create.php index c4d77e67f54e1..da412d91b0a6c 100644 --- a/layouts/joomla/content/icons/create.php +++ b/layouts/joomla/content/icons/create.php @@ -6,7 +6,7 @@ * * @copyright (C) 2016 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 */ defined('_JEXEC') or die; diff --git a/layouts/joomla/content/intro_image.php b/layouts/joomla/content/intro_image.php index 8bd618bbc0e9d..505ebe9cac8e5 100644 --- a/layouts/joomla/content/intro_image.php +++ b/layouts/joomla/content/intro_image.php @@ -21,13 +21,18 @@ return; } -$imgclass = empty($images->float_intro) ? $params->get('float_intro') : $images->float_intro; -$layoutAttr = [ - 'src' => $images->image_intro, - 'alt' => empty($images->image_intro_alt) && empty($images->image_intro_alt_empty) ? false : $images->image_intro_alt, +$figureClass = empty($images->float_intro) ? $params->get('float_intro') : $images->float_intro; +$imageClass = empty($images->imgclass_intro) ? $params->get('imgclass_intro') : $images->imgclass_intro; +$layoutAttr = [ + 'src' => $images->image_intro, + 'alt' => empty($images->image_intro_alt) && empty($images->image_intro_alt_empty) ? false : $images->image_intro_alt, + 'class' => $imageClass, ]; ?> -
+image_intro_caption) && $images->image_intro_caption !== '') : ?> +
+ + get('link_intro_image') && ($params->get('access-view') || $params->get('show_noauth', '0') == '1')) : ?> @@ -35,7 +40,9 @@ - image_intro_caption) && $images->image_intro_caption !== '') : ?> + +image_intro_caption) && $images->image_intro_caption !== '') : ?>
escape($images->image_intro_caption); ?>
- -
+ +
+ diff --git a/layouts/joomla/edit/admin_modules.php b/layouts/joomla/edit/admin_modules.php index f06d5752f4f38..02fb858033e10 100644 --- a/layouts/joomla/edit/admin_modules.php +++ b/layouts/joomla/edit/admin_modules.php @@ -10,12 +10,16 @@ defined('_JEXEC') or die; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Helper\ModuleHelper; -$app = Factory::getApplication(); -$form = $displayData->getForm(); -$input = $app->getInput(); +$app = Factory::getApplication(); +$form = $displayData->getForm(); +$input = $app->getInput(); +$component = $input->getCmd('option', 'com_content'); + +$saveHistory = ComponentHelper::getParams($component)->get('save_history', 0); $fields = $displayData->get('fields') ?: [ ['parent', 'parent_id'], @@ -32,6 +36,10 @@ $hiddenFields = $displayData->get('hidden_fields') ?: []; +if (!$saveHistory) { + $hiddenFields[] = 'version_note'; +} + if (!ModuleHelper::isAdminMultilang()) { $hiddenFields[] = 'language'; $form->setFieldAttribute('language', 'default', '*'); diff --git a/layouts/joomla/form/field/color/simple.php b/layouts/joomla/form/field/color/simple.php index 2ed3e632ead10..73e443135eb3e 100644 --- a/layouts/joomla/form/field/color/simple.php +++ b/layouts/joomla/form/field/color/simple.php @@ -12,6 +12,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; +use Joomla\Utilities\ArrayHelper; extract($displayData); @@ -51,22 +52,34 @@ * @var string $dataAttribute Miscellaneous data attributes preprocessed for HTML output * @var array $dataAttributes Miscellaneous data attribute for eg, data-*. */ - -$class = ' class="form-select ' . trim($class) . '"'; -$disabled = $disabled ? ' disabled' : ''; -$readonly = $readonly ? ' readonly' : ''; - Factory::getDocument()->getWebAssetManager() ->useStyle('webcomponent.field-simple-color') ->useScript('webcomponent.field-simple-color'); +Text::script('JCLOSE'); +Text::script('JNONE'); + +$slots = []; +$attr = [ + 'name' => $name, + 'id' => $id, + 'class' => trim($class), + 'value' => trim($color), +]; + +if ($disabled) { + $attr['disabled'] = ''; +} + +if ($readonly) { + $attr['readonly'] = ''; +} + +foreach ($colors as $val) { + $slots[] = ''; +} ?> - - +> + + diff --git a/layouts/joomla/form/field/combo.php b/layouts/joomla/form/field/combo.php index 86f52cee67e07..b710201c388fb 100644 --- a/layouts/joomla/form/field/combo.php +++ b/layouts/joomla/form/field/combo.php @@ -12,7 +12,7 @@ extract($displayData); -use Joomla\CMS\HTML\HTMLHelper; +use Joomla\CMS\Factory; /** * Layout variables @@ -45,7 +45,7 @@ * @var array $dataAttributes Miscellaneous data attribute for eg, data-*. */ -HTMLHelper::_('behavior.combobox'); +Factory::getApplication()->getDocument()->getWebAssetManager()->usePreset('awesomplete'); $attr = ''; diff --git a/layouts/joomla/form/field/date.php b/layouts/joomla/form/field/date.php new file mode 100644 index 0000000000000..5771653dc9e58 --- /dev/null +++ b/layouts/joomla/form/field/date.php @@ -0,0 +1,56 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +/** + * Layout variables + * ----------------- + * @var string $autocomplete Autocomplete attribute for the field. + * @var boolean $autofocus Is autofocus enabled? + * @var string $class Classes for the input. + * @var string $description Description of the field. + * @var boolean $disabled Is this field disabled? + * @var string $group Group the field belongs to. section in form XML. + * @var boolean $hidden Is this field hidden in the form? + * @var string $hint Placeholder for the field. + * @var string $id DOM id of the field. + * @var string $label Label of the field. + * @var string $labelclass Classes to apply to the label. + * @var boolean $multiple Does this field support multiple values? + * @var string $name Name of the input field. + * @var string $onchange Onchange attribute for the field. + * @var string $onclick Onclick attribute for the field. + * @var string $pattern Pattern (Reg Ex) of value of the form field. + * @var boolean $readonly Is this field read only? + * @var boolean $required Is this field required? + * @var integer $size Size attribute of the input. + * @var string $value Value attribute of the field. + * @var string $min + * @var string $max + */ +extract($displayData); + +$class = !empty($class) ? 'class="form-control ' . $class . '"' : 'class="form-control"'; +$readonly = $readonly ? ' readonly' : ''; +$disabled = $disabled ? ' disabled' : ''; +$required = $required ? ' required' : ''; +$hint = strlen($hint) ? ' placeholder="' . $hint . '"' : ''; +$autocomplete = !$autocomplete ? ' autocomplete="off"' : ' autocomplete="' . $autocomplete . '"'; +$autocomplete = $autocomplete == ' autocomplete="on"' ? '' : $autocomplete; +$autofocus = $autofocus ? ' autofocus' : ''; +$pattern = !empty($pattern) ? ' pattern="' . $pattern . '"' : ''; +$onchange = !empty($onchange) ? ' onchange="' . $onchange . '"' : ''; +$minAttr = !empty($min) ? ' min="' . $this->escape($min) . '"' : ''; +$maxAttr = !empty($max) ? ' max="' . $this->escape($max) . '"' : ''; + +echo ''; diff --git a/layouts/joomla/form/field/datetime.php b/layouts/joomla/form/field/datetime.php new file mode 100644 index 0000000000000..cfe5e6ae9cab3 --- /dev/null +++ b/layouts/joomla/form/field/datetime.php @@ -0,0 +1,56 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +/** + * Layout variables + * ----------------- + * @var string $autocomplete Autocomplete attribute for the field. + * @var boolean $autofocus Is autofocus enabled? + * @var string $class Classes for the input. + * @var string $description Description of the field. + * @var boolean $disabled Is this field disabled? + * @var string $group Group the field belongs to. section in form XML. + * @var boolean $hidden Is this field hidden in the form? + * @var string $hint Placeholder for the field. + * @var string $id DOM id of the field. + * @var string $label Label of the field. + * @var string $labelclass Classes to apply to the label. + * @var boolean $multiple Does this field support multiple values? + * @var string $name Name of the input field. + * @var string $onchange Onchange attribute for the field. + * @var string $onclick Onclick attribute for the field. + * @var string $pattern Pattern (Reg Ex) of value of the form field. + * @var boolean $readonly Is this field read only? + * @var boolean $required Is this field required? + * @var integer $size Size attribute of the input. + * @var string $value Value attribute of the field. + * @var string $min + * @var string $max + */ +extract($displayData); + +$class = !empty($class) ? 'class="form-control ' . $class . '"' : 'class="form-control"'; +$readonly = $readonly ? ' readonly' : ''; +$disabled = $disabled ? ' disabled' : ''; +$required = $required ? ' required' : ''; +$hint = strlen($hint) ? ' placeholder="' . $hint . '"' : ''; +$autocomplete = !$autocomplete ? ' autocomplete="off"' : ' autocomplete="' . $autocomplete . '"'; +$autocomplete = $autocomplete == ' autocomplete="on"' ? '' : $autocomplete; +$autofocus = $autofocus ? ' autofocus' : ''; +$pattern = !empty($pattern) ? ' pattern="' . $pattern . '"' : ''; +$onchange = !empty($onchange) ? ' onchange="' . $onchange . '"' : ''; +$minAttr = !empty($min) ? ' min="' . $this->escape($min) . '"' : ''; +$maxAttr = !empty($max) ? ' max="' . $this->escape($max) . '"' : ''; + +echo ''; diff --git a/layouts/joomla/form/field/groupedlist-transition.php b/layouts/joomla/form/field/groupedlist-transition.php new file mode 100644 index 0000000000000..8fe9f2c1e35cd --- /dev/null +++ b/layouts/joomla/form/field/groupedlist-transition.php @@ -0,0 +1,207 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Factory; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Layout\LayoutHelper; + +extract($displayData); +$wa = Factory::getApplication()->getDocument()->getWebAssetManager(); +$wa->getRegistry()->addExtensionRegistryFile('com_workflow'); + +$wa->useScript('joomla.dialog-autocreate'); +$wa->useScript('com_workflow.workflowgraphclient') + ->useStyle('com_workflow.workflowgraphclient'); + + +// Populate the language +$translationStrings = [ + 'COM_WORKFLOW_GRAPH', + 'COM_WORKFLOW_GRAPH_ADD_STAGE', + 'COM_WORKFLOW_GRAPH_ADD_STAGE_DIALOG_OPENED', + 'COM_WORKFLOW_GRAPH_ADD_TRANSITION_DIALOG_OPENED', + 'COM_WORKFLOW_GRAPH_ADD_TRANSITION', + 'COM_WORKFLOW_GRAPH_API_NOT_SET', + 'COM_WORKFLOW_GRAPH_BACKGROUND', + 'COM_WORKFLOW_GRAPH_CANVAS_DESCRIPTION', + 'COM_WORKFLOW_GRAPH_CANVAS_LABEL', + 'COM_WORKFLOW_GRAPH_CANVAS_VIEW_CONTROLS', + 'COM_WORKFLOW_GRAPH_CLEAR_SELECTION', + 'COM_WORKFLOW_GRAPH_CLOSE_ACTIONS_MENU', + 'COM_WORKFLOW_GRAPH_CONTROLS', + 'COM_WORKFLOW_GRAPH_CREATING_TRANSITION', + 'COM_WORKFLOW_GRAPH_DEFAULT', + 'COM_WORKFLOW_GRAPH_DISABLED', + 'COM_WORKFLOW_GRAPH_EDIT_ITEM', + 'COM_WORKFLOW_GRAPH_EDIT_STAGE', + 'COM_WORKFLOW_GRAPH_EDIT_TRANSITION', + 'COM_WORKFLOW_GRAPH_ENABLED', + 'COM_WORKFLOW_GRAPH_ERROR_API_RETURNED_ERROR', + 'COM_WORKFLOW_GRAPH_ERROR_CSRF_TOKEN_NOT_SET', + 'COM_WORKFLOW_GRAPH_ERROR_EXTENSION_NOT_SET', + 'COM_WORKFLOW_GRAPH_ERROR_FAILED_TO_UPDATE_STAGE_POSITIONS', + 'COM_WORKFLOW_GRAPH_ERROR_FETCHING_MODEL', + 'COM_WORKFLOW_GRAPH_ERROR_INVALID_ID', + 'COM_WORKFLOW_GRAPH_ERROR_INVALID_POSITION_DATA', + 'COM_WORKFLOW_GRAPH_ERROR_INVALID_STAGE_POSITIONS', + 'COM_WORKFLOW_GRAPH_ERROR_NOT_AUTHENTICATED', + 'COM_WORKFLOW_GRAPH_ERROR_NO_PERMISSION', + 'COM_WORKFLOW_GRAPH_ERROR_REQUEST_FAILED', + 'COM_WORKFLOW_GRAPH_ERROR_STAGES_NOT_FOUND', + 'COM_WORKFLOW_GRAPH_ERROR_STAGE_DEFAULT_CANT_DELETED', + 'COM_WORKFLOW_GRAPH_ERROR_STAGE_HAS_TRANSITIONS', + 'COM_WORKFLOW_GRAPH_ERROR_UNKNOWN', + 'COM_WORKFLOW_GRAPH_ERROR_WORKFLOW_ID_NOT_SET', + 'COM_WORKFLOW_GRAPH_ERROR_WORKFLOW_NOT_FOUND', + 'COM_WORKFLOW_GRAPH_FIT_VIEW', + 'COM_WORKFLOW_GRAPH_FOCUS_TYPE_CHANGE', + 'COM_WORKFLOW_GRAPH_FROM_ANY', + 'COM_WORKFLOW_GRAPH_LOADING', + 'COM_WORKFLOW_GRAPH_MINIMAP_HIDE', + 'COM_WORKFLOW_GRAPH_MINIMAP_LABEL', + 'COM_WORKFLOW_GRAPH_MINIMAP_SHOW', + 'COM_WORKFLOW_GRAPH_MOVE_STAGE', + 'COM_WORKFLOW_GRAPH_MOVE_VIEW', + 'COM_WORKFLOW_GRAPH_NAVIGATE_NODES', + 'COM_WORKFLOW_GRAPH_OPEN_ACTIONS_MENU', + 'COM_WORKFLOW_GRAPH_SELECTION_CLEARED', + 'COM_WORKFLOW_GRAPH_SELECT_ITEM', + 'COM_WORKFLOW_GRAPH_SHORTCUTS', + 'COM_WORKFLOW_GRAPH_SHORTCUTS_TITLE', + 'COM_WORKFLOW_GRAPH_STAGE', + 'COM_WORKFLOW_GRAPH_STAGES', + 'COM_WORKFLOW_GRAPH_STAGE_ACTIONS', + 'COM_WORKFLOW_GRAPH_STAGE_COUNT', + 'COM_WORKFLOW_GRAPH_STAGE_DESCRIPTION', + 'COM_WORKFLOW_GRAPH_STAGE_POSITIONS_UPDATED', + 'COM_WORKFLOW_GRAPH_STAGE_REF', + 'COM_WORKFLOW_GRAPH_STAGE_SELECTED', + 'COM_WORKFLOW_GRAPH_STAGE_STATUS_ENABLED', + 'COM_WORKFLOW_GRAPH_STAGE_STATUS_DISABLED', + 'COM_WORKFLOW_GRAPH_STATUS', + 'COM_WORKFLOW_GRAPH_TRANSITION', + 'COM_WORKFLOW_GRAPH_TRANSITIONS', + 'COM_WORKFLOW_GRAPH_TRANSITION_ACTIONS', + 'COM_WORKFLOW_GRAPH_TRANSITION_COUNT', + 'COM_WORKFLOW_GRAPH_TRANSITION_DESCRIPTION', + 'COM_WORKFLOW_GRAPH_TRANSITION_PATH', + 'COM_WORKFLOW_GRAPH_TRANSITION_REF', + 'COM_WORKFLOW_GRAPH_TRANSITION_SELECTED', + 'COM_WORKFLOW_GRAPH_TRANSITION_STATUS_ENABLED', + 'COM_WORKFLOW_GRAPH_TRANSITION_STATUS_DISABLED', + 'COM_WORKFLOW_GRAPH_TRASH_ITEM', + 'COM_WORKFLOW_GRAPH_TRASH_STAGE', + 'COM_WORKFLOW_GRAPH_TRASH_STAGE_CONFIRM', + 'COM_WORKFLOW_GRAPH_TRASH_STAGE_FAILED', + 'COM_WORKFLOW_GRAPH_TRASH_TRANSITION', + 'COM_WORKFLOW_GRAPH_TRASH_TRANSITION_CONFIRM', + 'COM_WORKFLOW_GRAPH_TRASH_TRANSITION_FAILED', + 'COM_WORKFLOW_GRAPH_UNSAVED_CHANGES', + 'COM_WORKFLOW_GRAPH_UPDATE_STAGE_POSITION_FAILED', + 'COM_WORKFLOW_GRAPH_UP_TO_DATE', + 'COM_WORKFLOW_GRAPH_WORKFLOWS_EDIT', + 'COM_WORKFLOW_GRAPH_ZOOM_IN', + 'COM_WORKFLOW_GRAPH_ZOOM_OUT', +]; + +foreach ($translationStrings as $string) { + Text::script($string); +} + +$workflowId = $field ? $field->getAttribute('workflow_id') : null; +if (!$workflowId) { + return; +} +$popupId = 'workflow-graph-modal-content'; +$popupOptions = json_encode([ + 'src' => '#' . $popupId, + 'height' => 'fit-content', + 'textHeader' => Text::_('COM_WORKFLOW_GRAPH_FULL'), + 'preferredParent' => 'body', + 'modal' => true, +]); + +?> +
+
+ +
+
+
+ +
+
+
+ + diff --git a/layouts/joomla/form/field/media.php b/layouts/joomla/form/field/media.php index 340e1e248fa9b..99a4dd965415d 100644 --- a/layouts/joomla/form/field/media.php +++ b/layouts/joomla/form/field/media.php @@ -154,6 +154,8 @@ ]); } +$imagesOnly = count($mediaTypeNames) === 1 && in_array('images', $mediaTypeNames); + ?> * @license GNU General Public License version 2 or later; see LICENSE.txt * - * @deprecated 5.2 will be moved to the b/c plugin in 6.0 and removed in 7.0 + * @deprecated 5.2 will be moved to the b/c plugin in 7.0 and removed in 8.0 * */ diff --git a/layouts/joomla/form/field/subform/repeatable-grid.php b/layouts/joomla/form/field/subform/repeatable-grid.php new file mode 100644 index 0000000000000..73056dfad5d4c --- /dev/null +++ b/layouts/joomla/form/field/subform/repeatable-grid.php @@ -0,0 +1,74 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Factory; +use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\Text; + +extract($displayData); + +/** + * Layout variables + * ----------------- + * @var Form $tmpl The Empty form for template + * @var array $forms Array of JForm instances for render the rows + * @var bool $multiple The multiple state for the form field + * @var int $min Count of minimum repeating in multiple mode + * @var int $max Count of maximum repeating in multiple mode + * @var string $name Name of the input field. + * @var string $fieldname The field name + * @var string $fieldId The field ID + * @var string $control The forms control + * @var string $label The field label + * @var string $description The field description + * @var string $class Classes for the container + * @var array $buttons Array of the buttons that will be rendered + * @var bool $groupByFieldset Whether group the subform fields by it`s fieldset + */ +if ($multiple) { + // Add script + Factory::getApplication() + ->getDocument() + ->getWebAssetManager() + ->useScript('webcomponent.field-subform'); +} + +$class = $class ? ' ' . $class : ''; + +$sublayout = empty($groupByFieldset) ? 'section' : 'section-byfieldsets'; +?> + +
+ + +
+
+ +
+
+ + $form) : + echo $this->sublayout($sublayout, ['form' => $form, 'basegroup' => $fieldname, 'group' => $fieldname . $k, 'buttons' => $buttons]); + endforeach; + ?> + + + +
+
diff --git a/layouts/joomla/form/field/subform/repeatable-grid/section-byfieldsets.php b/layouts/joomla/form/field/subform/repeatable-grid/section-byfieldsets.php new file mode 100644 index 0000000000000..210b8c6a7bb30 --- /dev/null +++ b/layouts/joomla/form/field/subform/repeatable-grid/section-byfieldsets.php @@ -0,0 +1,56 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\Text; + +extract($displayData); + +/** + * Layout variables + * ----------------- + * @var Form $form The form instance for render the section + * @var string $basegroup The base group name + * @var string $group Current group name + * @var array $buttons Array of the buttons that will be rendered + */ +?> + +
+ +
+
+ + + +
+
+ +
+ getFieldsets() as $fieldset) : ?> +
+ label)) : ?> + label); ?> + + getFieldset($fieldset->name) as $field) : ?> + renderField(); ?> + +
+ +
+
diff --git a/layouts/joomla/form/field/subform/repeatable-grid/section.php b/layouts/joomla/form/field/subform/repeatable-grid/section.php new file mode 100644 index 0000000000000..fbd2c10b40192 --- /dev/null +++ b/layouts/joomla/form/field/subform/repeatable-grid/section.php @@ -0,0 +1,49 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +defined('_JEXEC') or die; + +use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\Text; + +extract($displayData); + +/** + * Layout variables + * ----------------- + * @var Form $form The form instance for render the section + * @var string $basegroup The base group name + * @var string $group Current group name + * @var array $buttons Array of the buttons that will be rendered + */ +?> + +
+ +
+
+ + + +
+
+ +
+ getGroup('') as $field) : ?> + renderField(); ?> + +
+
diff --git a/layouts/joomla/form/field/subform/repeatable-table.php b/layouts/joomla/form/field/subform/repeatable-table.php index e37d3ffb48975..1648032e8caea 100644 --- a/layouts/joomla/form/field/subform/repeatable-table.php +++ b/layouts/joomla/form/field/subform/repeatable-table.php @@ -82,12 +82,12 @@ ?>
-
- +
diff --git a/layouts/joomla/form/field/subform/repeatable/section-byfieldsets.php b/layouts/joomla/form/field/subform/repeatable/section-byfieldsets.php index 4713233ba9b60..70680361ee33b 100644 --- a/layouts/joomla/form/field/subform/repeatable/section-byfieldsets.php +++ b/layouts/joomla/form/field/subform/repeatable/section-byfieldsets.php @@ -8,11 +8,11 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -defined('_JEXEC') or die; - use Joomla\CMS\Form\Form; use Joomla\CMS\Language\Text; +\defined('_JEXEC') or die; + extract($displayData); /** @@ -45,16 +45,15 @@
getFieldsets() as $fieldset) : ?> -
- label)) : ?> - label); ?> - - getFieldset($fieldset->name) as $field) : ?> - renderField(); ?> - -
+ class) ? ' class="' . $this->escape($fieldset->class) . '"' : ''; ?> + > + label)) : ?> + label); ?> + + getFieldset($fieldset->name) as $field) : ?> + renderField(); ?> + +
diff --git a/layouts/joomla/form/field/url.php b/layouts/joomla/form/field/url.php index 377fa2fad77db..c9af1729c322b 100644 --- a/layouts/joomla/form/field/url.php +++ b/layouts/joomla/form/field/url.php @@ -65,7 +65,7 @@ ]; /** - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * The unicode conversion of the URL will be moved to \Joomla\CMS\Form\Field\UrlField::getLayoutData */ if ($value !== null) { diff --git a/layouts/joomla/html/audio.php b/layouts/joomla/html/audio.php new file mode 100644 index 0000000000000..225b20f4cb60c --- /dev/null +++ b/layouts/joomla/html/audio.php @@ -0,0 +1,26 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +/** + * Layout variables + * ----------------- + * @var array $displayData Array with all the given attributes for the audio element. + * Eg: src, class, controls, controlslist, autoplay, loop, style, data-* + * See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio + */ +defined('_JEXEC') or die; + +use Joomla\Utilities\ArrayHelper; + +if (array_key_exists('src', $displayData) && !empty($displayData['src'])) { + $displayData['src'] = $this->escape($displayData['src']); +} + +echo ''; diff --git a/layouts/joomla/html/batch/item.php b/layouts/joomla/html/batch/item.php index e83f6cad722cc..7ddbaeeff753c 100644 --- a/layouts/joomla/html/batch/item.php +++ b/layouts/joomla/html/batch/item.php @@ -32,6 +32,13 @@ $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); $wa->useScript('joomla.batch-copymove'); +// Get category options +if (isset($addRoot) && $addRoot) { + $categoryOptions = HTMLHelper::_('category.categories', $extension, ['filter.published' => [0, 1, 2]]); +} else { + $categoryOptions = HTMLHelper::_('category.options', $extension, ['filter.published' => [0, 1, 2]]); +} + ?> getAaguid() : ''; - $authMetadata = $knownAuthenticators[$aaguid->toString()] ?? $knownAuthenticators['']; + $aaguid = ($method['credential'] instanceof PublicKeyCredentialSource) ? (string) $method['credential']->getAaguid() : ''; + $authMetadata = $knownAuthenticators[$aaguid] ?? $knownAuthenticators['']; ?>
getShortVersion()); +\defined('JVERSION') or \define('JVERSION', (new \Joomla\CMS\Version())->getShortVersion()); // Set up the message queue logger for web requests -if (array_key_exists('REQUEST_METHOD', $_SERVER)) { +if (\array_key_exists('REQUEST_METHOD', $_SERVER)) { \Joomla\CMS\Log\Log::addLogger(['logger' => 'messagequeue'], \Joomla\CMS\Log\Log::ALL, ['jerror']); } diff --git a/libraries/cms.php b/libraries/cms.php index e8303fd34ca34..2f5ab9f2f154c 100644 --- a/libraries/cms.php +++ b/libraries/cms.php @@ -7,10 +7,10 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -defined('_JEXEC') or die; +\defined('_JEXEC') or die; trigger_error( - sprintf( + \sprintf( 'Bootstrapping Joomla using the %1$s file is deprecated. Use %2$s instead.', __FILE__, __DIR__ . '/bootstrap.php' @@ -18,16 +18,6 @@ E_USER_DEPRECATED ); -/** - * Set the platform root path as a constant if necessary. - * - * @deprecated 4.4.0 will be removed in 6.0 - * Use defined('_JEXEC') or die; to detect if the CMS is loaded correctly - **/ -if (!defined('JPATH_PLATFORM')) { - define('JPATH_PLATFORM', __DIR__); -} - // Import the library loader if necessary if (!class_exists('JLoader')) { require_once JPATH_LIBRARIES . '/loader.php'; @@ -50,15 +40,15 @@ class_exists('\\Joomla\\CMS\\Autoload\\ClassLoader'); spl_autoload_register([new \Joomla\CMS\Autoload\ClassLoader($loader), 'loadClass'], true, true); // Define the Joomla version if not already defined -if (!defined('JVERSION')) { - define('JVERSION', (new \Joomla\CMS\Version())->getShortVersion()); +if (!\defined('JVERSION')) { + \define('JVERSION', (new \Joomla\CMS\Version())->getShortVersion()); } // Register a handler for uncaught exceptions that shows a pretty error page when possible set_exception_handler(['Joomla\CMS\Exception\ExceptionHandler', 'handleException']); // Set up the message queue logger for web requests -if (array_key_exists('REQUEST_METHOD', $_SERVER)) { +if (\array_key_exists('REQUEST_METHOD', $_SERVER)) { \Joomla\CMS\Log\Log::addLogger(['logger' => 'messagequeue'], \Joomla\CMS\Log\Log::ALL, ['jerror']); } diff --git a/libraries/import.legacy.php b/libraries/import.legacy.php index 60ea147aaa017..0263d3099c28b 100644 --- a/libraries/import.legacy.php +++ b/libraries/import.legacy.php @@ -9,7 +9,7 @@ */ trigger_error( - sprintf( + \sprintf( 'Bootstrapping Joomla using the %1$s file is deprecated. Use %2$s instead.', __FILE__, __DIR__ . '/bootstrap.php' @@ -17,25 +17,15 @@ E_USER_DEPRECATED ); -/** - * Set the platform root path as a constant if necessary. - * - * @deprecated 4.4.0 will be removed in 6.0 - * Use defined('_JEXEC') or die; to detect if the CMS is loaded correctly - **/ -if (!defined('JPATH_PLATFORM')) { - define('JPATH_PLATFORM', __DIR__); -} - // Detect the native operating system type. $os = strtoupper(substr(PHP_OS, 0, 3)); -if (!defined('IS_WIN')) { - define('IS_WIN', $os === 'WIN'); +if (!\defined('IS_WIN')) { + \define('IS_WIN', $os === 'WIN'); } -if (!defined('IS_UNIX')) { - define('IS_UNIX', $os !== 'MAC' && $os !== 'WIN'); +if (!\defined('IS_UNIX')) { + \define('IS_UNIX', $os !== 'MAC' && $os !== 'WIN'); } // Import the library loader if necessary. diff --git a/libraries/import.php b/libraries/import.php index cc87ee797a32f..6a6a63d34093a 100644 --- a/libraries/import.php +++ b/libraries/import.php @@ -9,7 +9,7 @@ */ trigger_error( - sprintf( + \sprintf( 'Bootstrapping Joomla using the %1$s file is deprecated. Use %2$s instead.', __FILE__, __DIR__ . '/bootstrap.php' @@ -17,25 +17,15 @@ E_USER_DEPRECATED ); -/** - * Set the platform root path as a constant if necessary. - * - * @deprecated 4.4.0 will be removed in 6.0 - * Use defined('_JEXEC') or die; to detect if the CMS is loaded correctly - **/ -if (!defined('JPATH_PLATFORM')) { - define('JPATH_PLATFORM', __DIR__); -} - // Detect the native operating system type. $os = strtoupper(substr(PHP_OS, 0, 3)); -if (!defined('IS_WIN')) { - define('IS_WIN', $os === 'WIN'); +if (!\defined('IS_WIN')) { + \define('IS_WIN', $os === 'WIN'); } -if (!defined('IS_UNIX')) { - define('IS_UNIX', IS_WIN === false); +if (!\defined('IS_UNIX')) { + \define('IS_UNIX', IS_WIN === false); } // Import the library loader if necessary. diff --git a/libraries/loader.php b/libraries/loader.php index 5883847634300..70089172a830a 100644 --- a/libraries/loader.php +++ b/libraries/loader.php @@ -9,7 +9,7 @@ * @phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace */ -defined('_JEXEC') or die; +\defined('_JEXEC') or die; /** * Static class to handle loading of libraries. @@ -94,7 +94,7 @@ abstract class JLoader * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to * register an autoloader for your files. */ @@ -176,7 +176,7 @@ public static function getNamespaces() * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to * register an autoloader for your files. */ @@ -207,7 +207,7 @@ public static function import($key, $base = null) // Only register the class for autoloading if the file exists. if (is_file($base . '/' . $path . '.php')) { self::$classes[strtolower($class)] = $base . '/' . $path . '.php'; - $success = true; + $success = true; } } else { /** @@ -289,7 +289,7 @@ class_alias($original, $class); public static function register($class, $path, $force = true) { // When an alias exists, register it as well - if (array_key_exists(strtolower($class), self::$classAliases)) { + if (\array_key_exists(strtolower($class), self::$classAliases)) { self::register(self::stripFirstBackslash(self::$classAliases[strtolower($class)]), $path, $force); } @@ -466,7 +466,7 @@ public static function setup($enablePsr = true, $enablePrefixes = true, $enableC * * @since 3.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use JLoader::loadByPsr instead */ public static function loadByPsr4($class) @@ -509,7 +509,7 @@ public static function loadByPsr($class) // Loop through paths registered to this namespace until we find a match. foreach ($paths as $path) { - $classFilePath = realpath($path . DIRECTORY_SEPARATOR . substr_replace($classPath, '', 0, strlen($nsPath) + 1)); + $classFilePath = realpath($path . DIRECTORY_SEPARATOR . substr_replace($classPath, '', 0, \strlen($nsPath) + 1)); // We do not allow files outside the namespace root to be loaded if (strpos($classFilePath, realpath($path)) !== 0) { @@ -590,10 +590,10 @@ class_alias($class, $alias); public static function _autoload($class) { foreach (self::$prefixes as $prefix => $lookup) { - $chr = strlen($prefix) < strlen($class) ? $class[strlen($prefix)] : 0; + $chr = \strlen($prefix) < \strlen($class) ? $class[\strlen($prefix)] : 0; if (strpos($class, $prefix) === 0 && ($chr === strtoupper($chr))) { - return self::_load(substr($class, strlen($prefix)), $lookup); + return self::_load(substr($class, \strlen($prefix)), $lookup); } } @@ -613,8 +613,8 @@ public static function _autoload($class) private static function _load($class, $lookup) { // Split the class name into parts separated by camelCase. - $parts = preg_split('/(?<=[a-z0-9])(?=[A-Z])/x', $class); - $partsCount = count($parts); + $parts = preg_split('/(?<=[a-z0-9])(?=[A-Z])/x', $class); + $partsCount = \count($parts); foreach ($lookup as $base) { // Generate the path based on the class name parts. @@ -665,7 +665,7 @@ private static function _load($class, $lookup) */ private static function loadAliasFor($class) { - if (!array_key_exists($class, self::$classAliasesInverse)) { + if (!\array_key_exists($class, self::$classAliasesInverse)) { return; } @@ -691,7 +691,7 @@ private static function stripFirstBackslash($class) } // Check if jexit is defined first (our unit tests mock this) -if (!function_exists('jexit')) { +if (!\function_exists('jexit')) { /** * Global application exit. * @@ -720,7 +720,7 @@ function jexit($message = 0): never * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Classes should be autoloaded. Use JLoader::registerPrefix() or JLoader::registerNamespace() to * register an autoloader for your files. */ diff --git a/libraries/namespacemap.php b/libraries/namespacemap.php index 709988e87817d..00beb17d3584e 100644 --- a/libraries/namespacemap.php +++ b/libraries/namespacemap.php @@ -154,15 +154,15 @@ protected function writeNamespaceFile($elements) } catch (Exception $e) { Log::add('Could not save ' . $this->file, Log::WARNING); - $map = []; + $map = []; $constants = ['JPATH_ADMINISTRATOR', 'JPATH_API', 'JPATH_SITE', 'JPATH_PLUGINS', 'JPATH_LIBRARIES']; foreach ($elements as $namespace => $path) { foreach ($constants as $constant) { - $path = preg_replace(['/^(' . $constant . ")\s\.\s\'/", '/\'$/'], [constant($constant), ''], $path); + $path = preg_replace(['/^(' . $constant . ")\s\.\s\'/", '/\'$/'], [\constant($constant), ''], $path); } - $namespace = str_replace('\\\\', '\\', $namespace); + $namespace = str_replace('\\\\', '\\', $namespace); $map[$namespace] = [ $path ]; } @@ -212,7 +212,7 @@ private function getNamespaces(string $type): array if ($type === 'plugin' || $type === 'library') { $baseDir = $type === 'plugin' ? 'JPATH_PLUGINS . \'' : 'JPATH_LIBRARIES . \''; - $path = substr($namespacePath, strlen($type === 'plugin' ? JPATH_PLUGINS : JPATH_LIBRARIES)); + $path = substr($namespacePath, \strlen($type === 'plugin' ? JPATH_PLUGINS : JPATH_LIBRARIES)); // Set the namespace $extensions[$namespace] = $baseDir . $path . '\''; @@ -222,7 +222,7 @@ private function getNamespaces(string $type): array // Check if we need to use administrator path $isAdministrator = strpos($namespacePath, JPATH_ADMINISTRATOR) === 0; - $path = substr($namespacePath, strlen($isAdministrator ? JPATH_ADMINISTRATOR : JPATH_SITE)); + $path = substr($namespacePath, \strlen($isAdministrator ? JPATH_ADMINISTRATOR : JPATH_SITE)); // Add the site path when a component if ($type === 'component') { @@ -271,7 +271,7 @@ private function getExtensions(string $type): array // Scan library manifest directories for XML files foreach (Folder::files(JPATH_MANIFESTS . '/libraries', '\.xml$', true, true) as $file) { // Match manifest to extension directory - $manifests[JPATH_LIBRARIES . '/' . File::stripExt(substr($file, strlen(JPATH_MANIFESTS . '/libraries') + 1))] = $file; + $manifests[JPATH_LIBRARIES . '/' . File::stripExt(substr($file, \strlen(JPATH_MANIFESTS . '/libraries') + 1))] = $file; } } catch (UnexpectedValueException $e) { return []; diff --git a/libraries/src/Access/Access.php b/libraries/src/Access/Access.php index f8a8ae036624f..c090c91ba5fb3 100644 --- a/libraries/src/Access/Access.php +++ b/libraries/src/Access/Access.php @@ -178,7 +178,7 @@ public static function check($userId, $action, $assetKey = null, $preload = true * @return boolean True on success. * * @since 1.6 - * @note This method will return void in 4.0. + * @note This method will return void in 7.0. */ public static function preload($assetTypes = 'components', $reload = false) { @@ -283,7 +283,7 @@ protected static function preloadPermissions($assetType, $reload = false) $assetKey = $extensionName . '.%'; // Get a fresh query object. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['id', 'name', 'rules', 'parent_id'])) ->from($db->quoteName('#__assets')) ->where( @@ -348,7 +348,7 @@ protected static function preloadComponents() $db = Factory::getDbo(); // Get the asset info for all assets in asset names list. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['id', 'name', 'rules', 'parent_id'])) ->from($db->quoteName('#__assets')) ->whereIn($db->quoteName('name'), $components, ParameterType::STRING); @@ -444,7 +444,7 @@ protected static function getGroupPath($groupId) * @return Rules Rules object for the asset. * * @since 1.7.0 - * @note The non preloading code will be removed in 4.0. All asset rules should use asset preloading. + * @note The non preloading code will be removed in 7.0. All asset rules should use asset preloading. */ public static function getAssetRules($assetKey, $recursive = false, $recursiveParentAsset = true, $preload = true) { @@ -569,7 +569,7 @@ public static function getAssetRules($assetKey, $recursive = false, $recursivePa $db = Factory::getDbo(); // Build the database query to get the rules for the asset. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName($recursive ? 'b.rules' : 'a.rules', 'rules')) ->from($db->quoteName('#__assets', 'a')); @@ -798,7 +798,7 @@ public static function getGroupTitle($groupId) // Fetch the group title from the database $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('title')) ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('id') . ' = :groupId') @@ -840,7 +840,7 @@ public static function getGroupsByUser($userId, $recursive = true) $db = Factory::getDbo(); // Build the database query to get the rules for the asset. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName($recursive ? 'b.id' : 'a.id')); if (empty($userId)) { @@ -905,7 +905,7 @@ public static function getUsersByGroup($groupId, $recursive = false) $test = $recursive ? ' >= ' : ' = '; // First find the users contained in the group - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT(' . $db->quoteName('user_id') . ')') ->from($db->quoteName('#__usergroups', 'ug1')) ->join( @@ -944,7 +944,7 @@ public static function getAuthorisedViewLevels($userId) $db = Factory::getDbo(); // Build the base query. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['id', 'rules'])) ->from($db->quoteName('#__viewlevels')); diff --git a/libraries/src/Access/Rules.php b/libraries/src/Access/Rules.php index 5ee37eb47cc83..277f3cee31c97 100644 --- a/libraries/src/Access/Rules.php +++ b/libraries/src/Access/Rules.php @@ -9,8 +9,6 @@ namespace Joomla\CMS\Access; -use Joomla\CMS\Object\CMSObject; - // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects @@ -163,14 +161,14 @@ public function allow($action, $identity) * * @param mixed $identity An integer representing the identity or an array of identities * - * @return CMSObject Allowed actions for the identity or identities + * @return \stdClass Allowed actions for the identity or identities * * @since 1.7.0 */ public function getAllowed($identity) { // Sweep for the allowed actions. - $allowed = new CMSObject(); + $allowed = new \stdClass(); foreach ($this->data as $name => &$action) { if ($action->allow($identity)) { diff --git a/libraries/src/Adapter/Adapter.php b/libraries/src/Adapter/Adapter.php deleted file mode 100644 index e415206781180..0000000000000 --- a/libraries/src/Adapter/Adapter.php +++ /dev/null @@ -1,226 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -namespace Joomla\CMS\Adapter; - -use Joomla\CMS\Factory; -use Joomla\CMS\Object\LegacyErrorHandlingTrait; -use Joomla\CMS\Object\LegacyPropertyManagementTrait; -use Joomla\Database\DatabaseAwareInterface; - -// phpcs:disable PSR1.Files.SideEffects -\defined('_JEXEC') or die; -// phpcs:enable PSR1.Files.SideEffects - -/** - * Adapter Class - * Retains common adapter pattern functions - * Class harvested from joomla.installer.installer - * - * @since 1.6 - * @deprecated 4.3 will be removed in 6.0 - * Will be removed without replacement - */ -class Adapter -{ - use LegacyErrorHandlingTrait; - use LegacyPropertyManagementTrait; - - /** - * Associative array of adapters - * - * @var static[] - * @since 1.6 - */ - protected $_adapters = []; - - /** - * Adapter Folder - * - * @var string - * @since 1.6 - */ - protected $_adapterfolder = 'adapters'; - - /** - * Adapter Class Prefix - * - * @var string - * @since 1.6 - */ - protected $_classprefix = 'J'; - - /** - * Base Path for the adapter instance - * - * @var string - * @since 1.6 - */ - protected $_basepath = null; - - /** - * Database Connector Object - * - * @var \Joomla\Database\DatabaseDriver - * @since 1.6 - */ - protected $_db; - - /** - * Constructor - * - * @param string $basepath Base Path of the adapters - * @param string $classprefix Class prefix of adapters - * @param string $adapterfolder Name of folder to append to base path - * - * @since 1.6 - */ - public function __construct($basepath, $classprefix = null, $adapterfolder = null) - { - $this->_basepath = $basepath; - $this->_classprefix = $classprefix ?: 'J'; - $this->_adapterfolder = $adapterfolder ?: 'adapters'; - - $this->_db = Factory::getDbo(); - - // Ensure BC, when removed in 5, then the db must be set with setDatabase explicitly - if ($this instanceof DatabaseAwareInterface) { - $this->setDatabase($this->_db); - } - } - - /** - * Get the database connector object - * - * @return \Joomla\Database\DatabaseDriver Database connector object - * - * @since 1.6 - */ - public function getDbo() - { - return $this->_db; - } - - /** - * Return an adapter. - * - * @param string $name Name of adapter to return - * @param array $options Adapter options - * - * @return static|boolean Adapter of type 'name' or false - * - * @since 1.6 - */ - public function getAdapter($name, $options = []) - { - if (\array_key_exists($name, $this->_adapters)) { - return $this->_adapters[$name]; - } - - if ($this->setAdapter($name, $options)) { - return $this->_adapters[$name]; - } - - return false; - } - - /** - * Set an adapter by name - * - * @param string $name Adapter name - * @param object $adapter Adapter object - * @param array $options Adapter options - * - * @return boolean True if successful - * - * @since 1.6 - */ - public function setAdapter($name, &$adapter = null, $options = []) - { - if (\is_object($adapter)) { - $this->_adapters[$name] = &$adapter; - - return true; - } - - $class = rtrim($this->_classprefix, '\\') . '\\' . ucfirst($name); - - if (class_exists($class)) { - $this->_adapters[$name] = new $class($this, $this->_db, $options); - - return true; - } - - $class = rtrim($this->_classprefix, '\\') . '\\' . ucfirst($name) . 'Adapter'; - - if (class_exists($class)) { - $this->_adapters[$name] = new $class($this, $this->_db, $options); - - return true; - } - - $fullpath = $this->_basepath . '/' . $this->_adapterfolder . '/' . strtolower($name) . '.php'; - - if (!is_file($fullpath)) { - return false; - } - - // Try to load the adapter object - $class = $this->_classprefix . ucfirst($name); - - \JLoader::register($class, $fullpath); - - if (!class_exists($class)) { - return false; - } - - $this->_adapters[$name] = new $class($this, $this->_db, $options); - - return true; - } - - /** - * Loads all adapters. - * - * @param array $options Adapter options - * - * @return void - * - * @since 1.6 - */ - public function loadAllAdapters($options = []) - { - $files = new \DirectoryIterator($this->_basepath . '/' . $this->_adapterfolder); - - /** @type $file \DirectoryIterator */ - foreach ($files as $file) { - $fileName = $file->getFilename(); - - // Only load for php files. - if (!$file->isFile() || $file->getExtension() != 'php') { - continue; - } - - // Try to load the adapter object - require_once $this->_basepath . '/' . $this->_adapterfolder . '/' . $fileName; - - // Derive the class name from the filename. - $name = str_ireplace('.php', '', ucfirst(trim($fileName))); - $class = $this->_classprefix . ucfirst($name); - - if (!class_exists($class)) { - // Skip to next one - continue; - } - - $adapter = new $class($this, $this->_db, $options); - $this->_adapters[$name] = clone $adapter; - } - } -} diff --git a/libraries/src/Adapter/AdapterInstance.php b/libraries/src/Adapter/AdapterInstance.php deleted file mode 100644 index 49023952b8ed0..0000000000000 --- a/libraries/src/Adapter/AdapterInstance.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -namespace Joomla\CMS\Adapter; - -use Joomla\CMS\Factory; -use Joomla\CMS\Object\LegacyErrorHandlingTrait; -use Joomla\CMS\Object\LegacyPropertyManagementTrait; -use Joomla\Database\DatabaseDriver; - -// phpcs:disable PSR1.Files.SideEffects -\defined('_JEXEC') or die; -// phpcs:enable PSR1.Files.SideEffects - -/** - * Adapter Instance Class - * - * @since 1.6 - * @deprecated 4.3 will be removed in 6.0 - * Will be removed without replacement - */ -class AdapterInstance -{ - use LegacyErrorHandlingTrait; - use LegacyPropertyManagementTrait; - - /** - * Parent - * - * @var Adapter - * @since 1.6 - */ - protected $parent = null; - - /** - * Database - * - * @var DatabaseDriver - * @since 1.6 - */ - protected $db = null; - - /** - * Constructor - * - * @param Adapter $parent Parent object - * @param DatabaseDriver $db Database object - * @param array $options Configuration Options - * - * @since 1.6 - */ - public function __construct(Adapter $parent, DatabaseDriver $db, array $options = []) - { - // Set the properties from the options array that is passed in - $this->setProperties($options); - - // Set the parent and db in case $options for some reason overrides it. - $this->parent = $parent; - - // Pull in the global dbo in case something happened to it. - $this->db = $db ?: Factory::getDbo(); - } - - /** - * Retrieves the parent object - * - * @return Adapter - * - * @since 1.6 - */ - public function getParent() - { - return $this->parent; - } -} diff --git a/libraries/src/Application/AdministratorApplication.php b/libraries/src/Application/AdministratorApplication.php index 76e5625a120ad..1ffbf4b4275fc 100644 --- a/libraries/src/Application/AdministratorApplication.php +++ b/libraries/src/Application/AdministratorApplication.php @@ -16,7 +16,6 @@ use Joomla\CMS\Event\Application\AfterRouteEvent; use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; -use Joomla\CMS\Input\Input; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\PluginHelper; @@ -24,6 +23,7 @@ use Joomla\CMS\Session\Session; use Joomla\CMS\Uri\Uri; use Joomla\DI\Container; +use Joomla\Input\Input; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects @@ -59,7 +59,7 @@ class AdministratorApplication extends CMSApplication * Class constructor. * * @param ?Input $input An optional argument to provide dependency injection for the application's input - * object. If the argument is a JInput object that object will become the + * object. If the argument is a Input object that object will become the * application's input object, otherwise a default input object is created. * @param ?Registry $config An optional argument to provide dependency injection for the application's config * object. If the argument is a Registry object that object will become the @@ -219,7 +219,7 @@ protected function doExecute() * * @since 3.2 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Inject the router or load it from the dependency injection container * Example: * Factory::getContainer()->get(AdministratorRouter::class); @@ -229,61 +229,6 @@ public static function getRouter($name = 'administrator', array $options = []) return parent::getRouter($name, $options); } - /** - * Gets the name of the current template. - * - * @param boolean $params True to return the template parameters - * - * @return string|\stdClass The name of the template if the params argument is false. The template object if the params argument is true. - * - * @since 3.2 - * @throws \InvalidArgumentException - */ - public function getTemplate($params = false) - { - if (\is_object($this->template)) { - if ($params) { - return $this->template; - } - - return $this->template->template; - } - - $adminStyle = $this->getIdentity() ? (int) $this->getIdentity()->getParam('admin_style') : 0; - $template = $this->bootComponent('templates')->getMVCFactory() - ->createModel('Style', 'Administrator')->getAdminTemplate($adminStyle); - - $template->template = InputFilter::getInstance()->clean($template->template, 'cmd'); - $template->params = new Registry($template->params); - - // Fallback template - if ( - !is_file(JPATH_THEMES . '/' . $template->template . '/index.php') - && !is_file(JPATH_THEMES . '/' . $template->parent . '/index.php') - ) { - $this->getLogger()->error(Text::_('JERROR_ALERTNOTEMPLATE'), ['category' => 'system']); - $template->params = new Registry(); - $template->template = 'atum'; - - // Check, the data were found and if template really exists - if (!is_file(JPATH_THEMES . '/' . $template->template . '/index.php')) { - throw new \InvalidArgumentException(Text::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $template->template)); - } - } - - // Cache the result - $this->template = $template; - - // Pass the parent template to the state - $this->set('themeInherits', $template->parent); - - if ($params) { - return $template; - } - - return $template->template; - } - /** * Initialise the application. * @@ -295,7 +240,7 @@ public function getTemplate($params = false) */ protected function initialiseApp($options = []) { - $user = Factory::getUser(); + $user = $this->getIdentity(); // If the user is a guest we populate it with the guest user group. if ($user->guest) { @@ -397,7 +342,7 @@ public function login($credentials, $options = []) * * @since 3.2 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Purge the messages through the messages model * Example: * Factory::getApplication()->bootComponent('messages')->getMVCFactory() @@ -406,7 +351,7 @@ public function login($credentials, $options = []) public static function purgeMessages() { Factory::getApplication()->bootComponent('messages')->getMVCFactory() - ->createModel('Messages', 'Administrator')->purge(Factory::getUser()->id); + ->createModel('Messages', 'Administrator')->purge(Factory::getApplication()->getIdentity()->id); } /** @@ -420,7 +365,7 @@ public static function purgeMessages() */ protected function render() { - // Get the \JInput object + // Get the Input object $input = $this->input; $component = $input->getCmd('option', 'com_login'); @@ -534,4 +479,42 @@ public function findOption(): string return $option; } + + /** + * Initialise the template. + * + * @return void + * + * @throws \InvalidArgumentException + * @since 6.1.0 + */ + protected function initialiseTemplate(): void + { + $adminStyle = $this->getIdentity() ? (int) $this->getIdentity()->getParam('admin_style') : 0; + $template = $this->bootComponent('templates')->getMVCFactory() + ->createModel('Style', 'Administrator')->getAdminTemplate($adminStyle); + + $template->template = InputFilter::getInstance()->clean($template->template, 'cmd'); + $template->params = new Registry($template->params); + + // Fallback template + if (!$this->isValidTemplate($template)) { + $this->getLogger()->error(Text::_('JERROR_ALERTNOTEMPLATE'), ['category' => 'system']); + $template->params = new Registry(); + $template->template = 'atum'; + + // Check, the data were found and if template really exists + if ($this->isValidTemplate($template)) { + throw new \InvalidArgumentException( + Text::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $template->template) + ); + } + } + + // Cache the result + $this->template = $template; + + // Pass the parent template to the state + $this->set('themeInherits', $template->parent); + } } diff --git a/libraries/src/Application/ApiApplication.php b/libraries/src/Application/ApiApplication.php index 188f8509dfb26..c42e22de95420 100644 --- a/libraries/src/Application/ApiApplication.php +++ b/libraries/src/Application/ApiApplication.php @@ -172,15 +172,33 @@ protected function respond($options = []) if ($forceCORS) { /** * Enable CORS (Cross-origin resource sharing) - * Obtain allowed CORS origin from Global Settings. - * Set to * (=all) if not set. + * Obtain allowed CORS origin(s) from Global Settings. + * Set to * (=all) if not set. A comma-separated list of exact + * origins is supported, e.g. "https://a.example.com,https://b.example.com". */ $allowedOrigin = $this->get('cors_allow_origin', '*'); - $this->setHeader('Access-Control-Allow-Origin', $allowedOrigin, true); - $this->setHeader('Access-Control-Allow-Headers', 'Authorization'); + $requestOrigin = $this->input->server->get('HTTP_ORIGIN', null, 'raw'); - if ($this->input->server->getString('HTTP_ORIGIN', null) !== null) { - $this->setHeader('Access-Control-Allow-Origin', $this->input->server->getString('HTTP_ORIGIN'), true); + if ($allowedOrigin !== '*') { + $this->setHeader('Vary', 'Origin', false); + } + + if ($allowedOrigin === '*') { + /** + * Wildcard configuration: echo back "*". Credentials must never + * be allowed alongside a wildcard origin (browsers reject + * credentialed responses with Access-Control-Allow-Origin: * + * anyway, per the Fetch/CORS specification). + */ + $this->setHeader('Access-Control-Allow-Origin', '*', true); + } elseif ($requestOrigin !== null && $this->isOriginAllowed($requestOrigin, $allowedOrigin)) { + /** + * Only reflect the request's Origin header back if it is + * present in the configured whitelist. This is what makes it + * safe to also allow credentials (cookies / HTTP auth) for + * this specific, validated origin. + */ + $this->setHeader('Access-Control-Allow-Origin', $requestOrigin, true); $this->setHeader('Access-Control-Allow-Credentials', 'true', true); } } @@ -190,28 +208,22 @@ protected function respond($options = []) } /** - * Gets the name of the current template. + * Checks whether a request's Origin header matches an entry in the + * configured CORS origin whitelist. * - * @param boolean $params True to return the template parameters + * @param string $requestOrigin The Origin header sent by the browser. + * @param string $allowedOrigins The configured cors_allow_origin value; a single + * origin, or a comma-separated list of origins. * - * @return string|\stdClass + * @return boolean True if the request origin is present in the whitelist. * - * @since 4.0.0 + * @since 6.1.3 */ - public function getTemplate($params = false) + private function isOriginAllowed(string $requestOrigin, string $allowedOrigins): bool { - // The API application should not need to use a template - if ($params) { - $template = new \stdClass(); - $template->template = 'system'; - $template->params = new Registry(); - $template->inheritable = 0; - $template->parent = ''; - - return $template; - } + $whitelist = array_map('trim', explode(',', $allowedOrigins)); - return 'system'; + return \in_array($requestOrigin, $whitelist, true); } /** @@ -355,7 +367,7 @@ function ($carry, $route) { ); /** - * Obtain allowed CORS origin from Global Settings. + * Obtain allowed CORS origin(s) from Global Settings. * Set to * (=all) if not set. */ $allowedOrigin = $this->get('cors_allow_origin', '*'); @@ -364,7 +376,7 @@ function ($carry, $route) { * Obtain allowed CORS headers from Global Settings. * Set to sensible default if not set. */ - $allowedHeaders = $this->get('cors_allow_headers', 'Content-Type,X-Joomla-Token'); + $allowedHeaders = $this->get('cors_allow_headers', 'Content-Type,X-Joomla-Token,Authorization'); /** * Obtain allowed CORS methods from Global Settings. @@ -372,10 +384,30 @@ function ($carry, $route) { */ $allowedMethods = $this->get('cors_allow_methods', implode(',', $matchingRoutesMethods)); + // Obtain the current request ORIGIN from the respective HTTP header + $requestOrigin = $this->input->server->get('HTTP_ORIGIN', null, 'raw'); + // No use to go through the regular route handling hassle, // so let's simply output the headers and exit. $this->setHeader('status', '204'); - $this->setHeader('Access-Control-Allow-Origin', $allowedOrigin); + + if ($allowedOrigin !== '*') { + // Set regardless of the outcome so shared caches partition on Origin. + $this->setHeader('Vary', 'Origin', false); + } + + if ($allowedOrigin === '*') { + $this->setHeader('Access-Control-Allow-Origin', '*'); + } elseif ($requestOrigin !== null && $this->isOriginAllowed($requestOrigin, $allowedOrigin)) { + $this->setHeader('Access-Control-Allow-Origin', $requestOrigin); + $this->setHeader('Access-Control-Allow-Credentials', 'true'); + } else { + // Invalid cors origin requested, respond early without CORS header + $this->setHeader('status', 403, true); + $this->sendHeaders(); + $this->close(); + } + $this->setHeader('Access-Control-Allow-Headers', $allowedHeaders); $this->setHeader('Access-Control-Allow-Methods', $allowedMethods); $this->sendHeaders(); @@ -390,7 +422,7 @@ function ($carry, $route) { * * @since 4.0.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Inject the router or load it from the dependency injection container * Example: * Factory::getContainer()->get(ApiRouter::class); @@ -439,4 +471,29 @@ public function dispatch($component = null) new AfterDispatchEvent('onAfterDispatch', ['subject' => $this]) ); } + + /** + * Gets current template data + * + * This overrides the parent to skip the template validity check to prevent InvalidArgumentException being thrown + * when getTemplate() is called in the API application + * + * @param boolean $params An optional associative array of configuration settings + * + * @return string|\stdClass The name of the template if the params argument is false. The template object if the params argument is true. + * + * @since 6.1.1 + */ + public function getTemplate($params = false) + { + if (!\is_object($this->template)) { + $this->initialiseTemplate(); + } + + if ($params) { + return $this->template; + } + + return $this->template->template; + } } diff --git a/libraries/src/Application/CMSApplication.php b/libraries/src/Application/CMSApplication.php index 3dcec60b661be..39010e1b577da 100644 --- a/libraries/src/Application/CMSApplication.php +++ b/libraries/src/Application/CMSApplication.php @@ -17,6 +17,7 @@ use Joomla\CMS\Event\Application\AfterRenderEvent; use Joomla\CMS\Event\Application\AfterRespondEvent; use Joomla\CMS\Event\Application\AfterRouteEvent; +use Joomla\CMS\Event\Application\BeforeExecuteEvent; use Joomla\CMS\Event\Application\BeforeRenderEvent; use Joomla\CMS\Event\Application\BeforeRespondEvent; use Joomla\CMS\Event\ErrorEvent; @@ -31,7 +32,6 @@ use Joomla\CMS\Extension\ExtensionManagerTrait; use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; -use Joomla\CMS\Input\Input; use Joomla\CMS\Language\LanguageFactoryInterface; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; @@ -48,6 +48,7 @@ use Joomla\DI\Container; use Joomla\DI\ContainerAwareInterface; use Joomla\DI\ContainerAwareTrait; +use Joomla\Input\Input; use Joomla\Registry\Registry; use Joomla\String\StringHelper; @@ -168,7 +169,7 @@ abstract class CMSApplication extends WebApplication implements ContainerAwareIn * Class constructor. * * @param ?Input $input An optional argument to provide dependency injection for the application's input - * object. If the argument is a JInput object that object will become the + * object. If the argument is a Input object that object will become the * application's input object, otherwise a default input object is created. * @param ?Registry $config An optional argument to provide dependency injection for the application's config * object. If the argument is a Registry object that object will become the @@ -300,6 +301,21 @@ public function execute() $this->setupLogging(); $this->createExtensionNamespaceMap(); + // Load the behaviour plugins + PluginHelper::importPlugin('behaviour', null, true, $this->getDispatcher()); + + // Load the system plugins + PluginHelper::importPlugin('system', null, true, $this->getDispatcher()); + + // Trigger the onBeforeExecute event + $this->dispatchEvent( + 'onBeforeExecute', + new BeforeExecuteEvent('onBeforeExecute', ['subject' => $this, 'container' => $this->getContainer()]) + ); + + // Mark beforeExecute in the profiler. + JDEBUG ? $this->profiler->mark('beforeExecute event dispatched') : null; + // Perform application routines. $this->doExecute(); @@ -484,7 +500,7 @@ protected function checkUserRequiresReset($option, $view, $layout, $urls = []) * * @since 3.2 * - * @deprecated 3.2 will be removed in 6.0 + * @deprecated 3.2 will be removed in 7.0 * Use get() instead * Example: Factory::getApplication()->get($varname, $default); */ @@ -492,7 +508,7 @@ public function getCfg($varname, $default = null) { try { Log::add( - \sprintf('%s() is deprecated and will be removed in 6.0. Use Factory->getApplication()->get() instead.', __METHOD__), + \sprintf('%s() is deprecated and will be removed in 7.0. Use Factory->getApplication()->get() instead.', __METHOD__), Log::WARNING, 'deprecated' ); @@ -528,7 +544,7 @@ public function getClientId() * * @since 3.2 * @throws \RuntimeException - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use the application service from the DI container instead * Example: Factory::getContainer()->get($name); */ @@ -583,7 +599,7 @@ public function getMenu($name = null, $options = []) } if ($this->menuFactory === null) { - @trigger_error('Menu factory must be set in 5.0', E_USER_DEPRECATED); + @trigger_error('Menu factory must be set in 7.0', E_USER_DEPRECATED); $this->menuFactory = $this->getContainer()->get(MenuFactoryInterface::class); } @@ -672,7 +688,7 @@ public function getPathway() * * @since 3.2 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Inject the router or load it from the dependency injection container * Example: Factory::getContainer()->get($name); */ @@ -690,28 +706,32 @@ public static function getRouter($name = null, array $options = []) } /** - * Gets the name of the current template. + * Gets current template data * * @param boolean $params An optional associative array of configuration settings * * @return string|\stdClass The name of the template if the params argument is false. The template object if the params argument is true. * + * @throws \InvalidArgumentException * @since 3.2 */ public function getTemplate($params = false) { - if ($params) { - $template = new \stdClass(); + if (!\is_object($this->template)) { + $this->initialiseTemplate(); + } - $template->template = 'system'; - $template->params = new Registry(); - $template->inheritable = 0; - $template->parent = ''; + if (!$this->isValidTemplate($this->template)) { + throw new \InvalidArgumentException( + Text::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $this->template->template) + ); + } - return $template; + if ($params) { + return $this->template; } - return 'system'; + return $this->template->template; } /** @@ -805,11 +825,7 @@ protected function initialiseApp($options = []) $this->set('editor', $editor); - // Load the behaviour plugins - PluginHelper::importPlugin('behaviour', null, true, $this->getDispatcher()); - // Trigger the onAfterInitialise event. - PluginHelper::importPlugin('system', null, true, $this->getDispatcher()); $this->dispatchEvent( 'onAfterInitialise', new AfterInitialiseEvent('onAfterInitialise', ['subject' => $this]) @@ -1144,7 +1160,7 @@ protected function render() * * @since 3.2 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Implement the route functionality in the extending class, this here will be removed without replacement */ protected function route() @@ -1286,23 +1302,6 @@ public function checkToken($method = 'post') return $session::checkToken($method); } - /** - * Flag if the application instance is a CLI or web based application. - * - * Helper function, you should use the native PHP functions to detect if it is a CLI application. - * - * @return boolean - * - * @since 4.0.0 - * - * @deprecated 4.0 will be removed in 6.0 - * Will be removed without replacements - */ - public function isCli() - { - return false; - } - /** * No longer used * @@ -1312,7 +1311,7 @@ public function isCli() * * @throws \Exception * - * @deprecated 4.2 will be removed in 6.0 + * @deprecated 4.2 will be removed in 7.0 * Will be removed without replacements */ protected function isTwoFactorAuthenticationRequired(): bool @@ -1329,7 +1328,7 @@ protected function isTwoFactorAuthenticationRequired(): bool * * @throws \Exception * - * @deprecated 4.2 will be removed in 6.0 + * @deprecated 4.2 will be removed in 7.0 * Will be removed without replacements */ private function hasUserConfiguredTwoFactorAuthentication(): bool @@ -1406,4 +1405,44 @@ public function setMenuFactory(MenuFactoryInterface $menuFactory): void { $this->menuFactory = $menuFactory; } + + /** + * Initialise the template + * + * @return void + * + * @since 6.1.0 + */ + protected function initialiseTemplate(): void + { + $this->template = (object) [ + 'template' => 'system', + 'params' => new Registry(), + 'inheritable' => 0, + 'parent' => '', + ]; + } + + /** + * Check if a template is valid + * + * @param \stdClass $template The template object + * + * @return bool True if the template is valid, false otherwise. A template is valid if its index.php file exists + * either in the template itself or in its parent template. + * + * @since 6.1.0 + */ + protected function isValidTemplate($template): bool + { + if (!empty($template->template) && is_file(JPATH_THEMES . '/' . $template->template . '/index.php')) { + return true; + } + + if (!empty($template->parent) && is_file(JPATH_THEMES . '/' . $template->parent . '/index.php')) { + return true; + } + + return false; + } } diff --git a/libraries/src/Application/CMSApplicationInterface.php b/libraries/src/Application/CMSApplicationInterface.php index 9082b2aeb576f..73f87a8c5e9df 100644 --- a/libraries/src/Application/CMSApplicationInterface.php +++ b/libraries/src/Application/CMSApplicationInterface.php @@ -24,7 +24,7 @@ * * @since 4.0.0 * @note In Joomla 6 this interface will no longer extend EventAwareInterface - * @property-read Input $input {@deprecated 4.0 will be removed in 6.0} The Joomla Input property. Deprecated in favour of getInput() + * @property-read Input $input {@deprecated 4.0 will be removed in 7.0} The Joomla Input property. Deprecated in favour of getInput() */ interface CMSApplicationInterface extends ExtensionManagerInterface, ConfigurationAwareApplicationInterface, EventAwareInterface { @@ -96,7 +96,7 @@ interface CMSApplicationInterface extends ExtensionManagerInterface, Configurati * Constant defining an enqueued message message * * @var string - * @since 5.4.2 + * @since 6.0.2 */ public const MSG_MESSAGE = 'message'; @@ -104,7 +104,7 @@ interface CMSApplicationInterface extends ExtensionManagerInterface, Configurati * Constant defining an enqueued success message * * @var string - * @since 5.4.2 + * @since 6.0.2 */ public const MSG_SUCCESS = 'success'; @@ -140,20 +140,6 @@ public function getMessageQueue(); */ public function isClient($identifier); - /** - * Flag if the application instance is a CLI or web based application. - * - * Helper function, you should use the native PHP functions to detect if it is a CLI application. - * - * @return boolean - * - * @since 4.0.0 - * - * @deprecated 4.0 will be removed in 6.0 - * Will be removed without replacement. CLI will be handled by the joomla/console package instead - */ - public function isCli(); - /** * Get the application identity. * diff --git a/libraries/src/Application/CMSWebApplicationInterface.php b/libraries/src/Application/CMSWebApplicationInterface.php index 73a728fdb3312..cc702434eaeb2 100644 --- a/libraries/src/Application/CMSWebApplicationInterface.php +++ b/libraries/src/Application/CMSWebApplicationInterface.php @@ -56,7 +56,7 @@ public function getMenu($name = null, $options = []); * * @since 4.0.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Inject the router or load it from the dependency injection container * Example: Factory::getContainer()->get($name); */ diff --git a/libraries/src/Application/ConsoleApplication.php b/libraries/src/Application/ConsoleApplication.php index 684551145dcbf..1d28b9ba9d0aa 100644 --- a/libraries/src/Application/ConsoleApplication.php +++ b/libraries/src/Application/ConsoleApplication.php @@ -158,7 +158,7 @@ public function __construct( * * @since 4.0.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * This is a B/C proxy for deprecated read accesses, use getInput() method instead * Example: * $app->getInput(); @@ -390,23 +390,6 @@ public function isClient($identifier) return $this->getName() === $identifier; } - /** - * Flag if the application instance is a CLI or web based application. - * - * Helper function, you should use the native PHP functions to detect if it is a CLI application. - * - * @return boolean - * - * @since 4.0.0 - * - * @deprecated 4.0 will be removed in 6.0 - * Will be removed without replacement. CLI will be handled by the joomla/console package instead - */ - public function isCli() - { - return true; - } - /** * Sets the session for the application to use, if required. * @@ -477,7 +460,7 @@ public function setName(string $name): void * * @throws \InvalidArgumentException * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Inject the router or load it from the dependency injection container * Example: Factory::getContainer()->get(ApiRouter::class); */ diff --git a/libraries/src/Application/EventAware.php b/libraries/src/Application/EventAware.php index 76ca8c95ae1b5..62016788be90c 100644 --- a/libraries/src/Application/EventAware.php +++ b/libraries/src/Application/EventAware.php @@ -72,7 +72,7 @@ public function registerEvent($event, callable $handler) * * This is a legacy method, implementing old-style (Joomla! 3.x) plugin calls. It's best to go directly through the * Dispatcher and handle the returned EventInterface object instead of going through this method. This method is - * deprecated and will be removed in Joomla! 5.x. + * deprecated and will be removed in Joomla! 7.0. * * This method will only return the 'result' argument of the event * diff --git a/libraries/src/Application/EventAwareInterface.php b/libraries/src/Application/EventAwareInterface.php index c5ae193027629..962a997315056 100644 --- a/libraries/src/Application/EventAwareInterface.php +++ b/libraries/src/Application/EventAwareInterface.php @@ -42,7 +42,7 @@ public function getDispatcher(); * * This is a legacy method, implementing old-style (Joomla! 3.x) plugin calls. It's best to go directly through the * Dispatcher and handle the returned EventInterface object instead of going through this method. This method is - * deprecated and will be removed in Joomla! 5.x. + * deprecated and will be removed in Joomla! 7.0. * * This method will only return the 'result' argument of the event * diff --git a/libraries/src/Application/MultiFactorAuthenticationHandler.php b/libraries/src/Application/MultiFactorAuthenticationHandler.php index 087d56dbb28b5..8afcef52bbcde 100644 --- a/libraries/src/Application/MultiFactorAuthenticationHandler.php +++ b/libraries/src/Application/MultiFactorAuthenticationHandler.php @@ -317,24 +317,27 @@ public function isMultiFactorAuthenticationPage(bool $onlyCaptive = false): bool return false; } - $allowedViews = ['captive']; - $allowedTasks = [ - 'captive.display', 'captive.captive', 'captive.validate', - 'methods.display', - ]; + $allowedTasks = ['captive.captive', 'captive.validate', 'callback.callback', 'captive.select', 'methods.display']; + $allowedViews = ['captive', 'methods']; if (!$onlyCaptive) { - $allowedViews = array_merge($allowedViews, ['method', 'methods', 'callback']); $allowedTasks = array_merge( $allowedTasks, [ - 'method.display', 'method.add', 'method.edit', 'method.regenerateBackupCodes', - 'method.delete', 'method.save', 'methods.disable', 'methods.doNotShowThisAgain', + 'method.add', 'method.edit', 'method.regenerateBackupCodes', + 'method.delete', 'method.save', 'methods.doNotShowThisAgain', + ] + ); + + $allowedViews = array_merge( + $allowedViews, + [ + 'method', 'methods', ] ); } - return \in_array($view, $allowedViews) || \in_array($task, $allowedTasks); + return \in_array($task, $allowedTasks) || (\in_array($view, $allowedViews) && !$task); } /** @@ -349,7 +352,7 @@ private function hasRejectedMultiFactorAuthenticationSetup(): bool $profileKey = 'mfa.dontshow'; /** @var DatabaseInterface $db */ $db = Factory::getContainer()->get(DatabaseInterface::class); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('profile_value')) ->from($db->quoteName('#__user_profiles')) ->where($db->quoteName('user_id') . ' = :userId') @@ -445,7 +448,7 @@ private function migrateFromLegacyMFA(): void // Delete any other record with the same user_id and Method. $method = 'emergencycodes'; $userId = $user->id; - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__user_mfa')) ->where($db->quoteName('user_id') . ' = :user_id') ->where($db->quoteName('method') . ' = :method') diff --git a/libraries/src/Application/SiteApplication.php b/libraries/src/Application/SiteApplication.php index 6610da4290b9f..be6c4e8f0a524 100644 --- a/libraries/src/Application/SiteApplication.php +++ b/libraries/src/Application/SiteApplication.php @@ -18,14 +18,15 @@ use Joomla\CMS\Event\Application\AfterRouteEvent; use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; -use Joomla\CMS\Input\Input; use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Router\Route; use Joomla\CMS\Router\SiteRouter; use Joomla\CMS\Uri\Uri; +use Joomla\CMS\User\User; use Joomla\DI\Container; +use Joomla\Input\Input; use Joomla\Registry\Registry; use Joomla\String\StringHelper; @@ -71,7 +72,7 @@ final class SiteApplication extends CMSApplication * Class constructor. * * @param ?Input $input An optional argument to provide dependency injection for the application's input - * object. If the argument is a JInput object that object will become the + * object. If the argument is a Input object that object will become the * application's input object, otherwise a default input object is created. * @param ?Registry $config An optional argument to provide dependency injection for the application's config * object. If the argument is a Registry object that object will become the @@ -109,7 +110,7 @@ public function __construct(?Input $input = null, ?Registry $config = null, ?Web protected function authorise($itemid) { $menus = $this->getMenu(); - $user = Factory::getUser(); + $user = $this->getIdentity(); if (!$menus->authorise($itemid)) { if ($user->id == 0) { @@ -382,7 +383,7 @@ public function getParams($option = null) * * @since 3.2 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Inject the router or load it from the dependency injection container * Example: Factory::getContainer()->get(SiteRouter::class); */ @@ -392,250 +393,89 @@ public static function getRouter($name = 'site', array $options = []) } /** - * Gets the name of the current template. + * Initialise the application. * - * @param boolean $params True to return the template parameters + * @param array $options An optional associative array of configuration settings. * - * @return string|\stdClass The name of the template if the params argument is false. The template object if the params argument is true. + * @return void * * @since 3.2 - * @throws \InvalidArgumentException */ - public function getTemplate($params = false) + protected function initialiseApp($options = []) { - if (\is_object($this->template)) { - if ($this->template->parent) { - if (!is_file(JPATH_THEMES . '/' . $this->template->template . '/index.php')) { - if (!is_file(JPATH_THEMES . '/' . $this->template->parent . '/index.php')) { - throw new \InvalidArgumentException(Text::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $this->template->template)); - } - } - } elseif (!is_file(JPATH_THEMES . '/' . $this->template->template . '/index.php')) { - throw new \InvalidArgumentException(Text::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $this->template->template)); - } - - if ($params) { - return $this->template; - } - - return $this->template->template; - } - - // Get the id of the active menu item - $menu = $this->getMenu(); - $item = $menu->getActive(); - - if (!$item) { - $item = $menu->getItem($this->input->getInt('Itemid', null)); - } + $user = $this->getIdentity(); - $id = 0; - - if (\is_object($item)) { - // Valid item retrieved - $id = $item->template_style_id; - } - - $tid = $this->input->getUint('templateStyle', 0); - - if (is_numeric($tid) && (int) $tid > 0) { - $id = (int) $tid; - } - - /** @var OutputController $cache */ - $cache = $this->getCacheControllerFactory()->createCacheController('output', ['defaultgroup' => 'com_templates']); - - if ($this->getLanguageFilter()) { - $tag = $this->getLanguage()->getTag(); - } else { - $tag = ''; - } - - $cacheId = 'templates0' . $tag; - - if ($cache->contains($cacheId)) { - $templates = $cache->get($cacheId); - } else { - $templates = $this->bootComponent('templates')->getMVCFactory() - ->createModel('Style', 'Administrator')->getSiteTemplates(); - - foreach ($templates as &$template) { - // Create home element - if ($template->home == 1 && !isset($template_home) || $this->getLanguageFilter() && $template->home == $tag) { - $template_home = clone $template; - } - - $template->params = new Registry($template->params); - } - - // Unset the $template reference to the last $templates[n] item cycled in the foreach above to avoid editing it later - unset($template); - - // Add home element, after loop to avoid double execution - if (isset($template_home)) { - $template_home->params = new Registry($template_home->params); - $templates[0] = $template_home; - } - - $cache->store($templates, $cacheId); + // If the user is a guest we populate it with the guest user group. + if ($user->guest) { + $guestUsergroup = ComponentHelper::getParams('com_users')->get('guest_usergroup', 1); + $user->groups = [$guestUsergroup]; } - $template = $templates[$id] ?? $templates[0]; - - // Allows for overriding the active template from the request - $template_override = $this->input->getCmd('template', ''); - - // Only set template override if it is a valid template (= it exists and is enabled) - if (!empty($template_override)) { - if (is_file(JPATH_THEMES . '/' . $template_override . '/index.php')) { - foreach ($templates as $tmpl) { - if ($tmpl->template === $template_override) { - $template = $tmpl; - break; - } - } - } + if (empty($options['language'])) { + $options['language'] = $this->detectLanguage($user); } - // Need to filter the default value as well - $template->template = InputFilter::getInstance()->clean($template->template, 'cmd'); - - // Fallback template - if (!empty($template->parent)) { - if (!is_file(JPATH_THEMES . '/' . $template->template . '/index.php')) { - if (!is_file(JPATH_THEMES . '/' . $template->parent . '/index.php')) { - $this->enqueueMessage(Text::_('JERROR_ALERTNOTEMPLATE'), 'error'); - - // Try to find data for 'cassiopeia' template - $original_tmpl = $template->template; - - foreach ($templates as $tmpl) { - if ($tmpl->template === 'cassiopeia') { - $template = $tmpl; - break; - } - } - - // Check, the data were found and if template really exists - if (!is_file(JPATH_THEMES . '/' . $template->template . '/index.php')) { - throw new \InvalidArgumentException(Text::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $original_tmpl)); - } - } - } - } elseif (!is_file(JPATH_THEMES . '/' . $template->template . '/index.php')) { - $this->enqueueMessage(Text::_('JERROR_ALERTNOTEMPLATE'), 'error'); - - // Try to find data for 'cassiopeia' template - $original_tmpl = $template->template; - - foreach ($templates as $tmpl) { - if ($tmpl->template === 'cassiopeia') { - $template = $tmpl; - break; - } - } + // One last check to make sure we have something + if (!LanguageHelper::exists($options['language'])) { + $lang = $this->config->get('language', 'en-GB'); - // Check, the data were found and if template really exists - if (!is_file(JPATH_THEMES . '/' . $template->template . '/index.php')) { - throw new \InvalidArgumentException(Text::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $original_tmpl)); + if (LanguageHelper::exists($lang)) { + $options['language'] = $lang; + } else { + // As a last ditch fail to english + $options['language'] = 'en-GB'; } } - // Cache the result - $this->template = $template; - - if ($params) { - return $template; - } - - return $template->template; + // Finish initialisation + parent::initialiseApp($options); } /** - * Initialise the application. + * Detect the language to use for the application * - * @param array $options An optional associative array of configuration settings. + * @param User $user The user object * - * @return void + * @return string The detected language * - * @since 3.2 + * @since 6.1.0 */ - protected function initialiseApp($options = []) + private function detectLanguage(User $user): string { - $user = Factory::getUser(); - - // If the user is a guest we populate it with the guest user group. - if ($user->guest) { - $guestUsergroup = ComponentHelper::getParams('com_users')->get('guest_usergroup', 1); - $user->groups = [$guestUsergroup]; - } + // Detect language from input + $lang = $this->input->getString('language'); - if ($plugin = PluginHelper::getPlugin('system', 'languagefilter')) { - $pluginParams = new Registry($plugin->params); - $this->setLanguageFilter(true); - $this->setDetectBrowser($pluginParams->get('detect_browser', 1) == 1); + if ($lang && LanguageHelper::exists($lang)) { + return $lang; } - if (empty($options['language'])) { - // Detect the specified language - $lang = $this->input->getString('language', null); - - // Make sure that the user's language exists - if ($lang && LanguageHelper::exists($lang)) { - $options['language'] = $lang; - } - } - - if (empty($options['language']) && $this->getLanguageFilter()) { + if ($this->getLanguageFilter()) { // Detect cookie language $lang = $this->input->cookie->get(md5($this->get('secret') . 'language'), null, 'string'); - // Make sure that the user's language exists if ($lang && LanguageHelper::exists($lang)) { - $options['language'] = $lang; + return $lang; } } - if (empty($options['language'])) { - // Detect user language - $lang = $user->getParam('language'); + // Detect user language + $lang = $user->getParam('language'); - // Make sure that the user's language exists - if ($lang && LanguageHelper::exists($lang)) { - $options['language'] = $lang; - } + if ($lang && LanguageHelper::exists($lang)) { + return $lang; } - if (empty($options['language']) && $this->getDetectBrowser()) { + if ($this->getDetectBrowser()) { // Detect browser language $lang = LanguageHelper::detectLanguage(); - // Make sure that the user's language exists if ($lang && LanguageHelper::exists($lang)) { - $options['language'] = $lang; + return $lang; } } - if (empty($options['language'])) { - // Detect default language - $params = ComponentHelper::getParams('com_languages'); - $options['language'] = $params->get('site', $this->get('language', 'en-GB')); - } - - // One last check to make sure we have something - if (!LanguageHelper::exists($options['language'])) { - $lang = $this->config->get('language', 'en-GB'); - - if (LanguageHelper::exists($lang)) { - $options['language'] = $lang; - } else { - // As a last ditch fail to english - $options['language'] = 'en-GB'; - } - } - - // Finish initialisation - parent::initialiseApp($options); + // Use default language + return ComponentHelper::getParams('com_languages')->get('site', $this->get('language', 'en-GB')); } /** @@ -721,7 +561,7 @@ protected function render() $this->set('themeFile', 'index.php'); } - if ($this->get('offline') && !Factory::getUser()->authorise('core.login.offline')) { + if ($this->get('offline') && !$this->getIdentity()->authorise('core.login.offline')) { $this->setUserState('users.login.form.data', ['return' => Uri::getInstance()->toString()]); $this->set('themeFile', 'offline.php'); $this->setHeader('Status', '503 Service Temporarily Unavailable', 'true'); @@ -901,4 +741,155 @@ public function setTemplate($template, $styleParams = null) $this->set('themeParams', $this->template->params); } } + + /** + * Initialise the template + * + * @return void + * + * @since 6.1.0 + * + * @throws \InvalidArgumentException + */ + protected function initialiseTemplate(): void + { + $id = $this->getTemplateStyleId(); + + $templates = $this->getTemplates(); + + $template = $templates[$id] ?? $templates[0]; + + // Allows for overriding the active template from the request + $template_override = $this->input->getCmd('template', ''); + + // Only set template override if it is a valid template (= it exists and is enabled) + if (!empty($template_override)) { + $tmpl = $this->findTemplate($templates, $template_override); + + if ($tmpl) { + $template = $tmpl; + } + } + + // Need to filter the default value as well + $template->template = InputFilter::getInstance()->clean($template->template, 'cmd'); + + // Fallback template + if (!$this->isValidTemplate($template)) { + $this->enqueueMessage(Text::_('JERROR_ALERTNOTEMPLATE'), 'error'); + + // Try to find data for 'cassiopeia' template + $original_tmpl = $template->template; + + $template = $this->findTemplate($templates, 'cassiopeia'); + + if ($template === null) { + throw new \InvalidArgumentException(Text::sprintf('JERROR_COULD_NOT_FIND_TEMPLATE', $original_tmpl)); + } + } + + // Cache the result + $this->template = $template; + } + + /** + * Get the template style ID + * + * @return int The template style ID + * + * @since 6.1.0 + */ + private function getTemplateStyleId(): int + { + $menu = $this->getMenu(); + $item = $menu->getActive(); + + if (!$item) { + $item = $menu->getItem($this->input->getInt('Itemid', 0)); + } + + $id = 0; + + if ($item) { + // Valid item retrieved + $id = $item->template_style_id; + } + + $tid = $this->input->getUint('templateStyle', 0); + + if ($tid > 0) { + $id = $tid; + } + + return $id; + } + + /** + * Get all site templates + * + * @return array An array of template objects + * + * @since 6.1.0 + */ + private function getTemplates(): array + { + /** @var OutputController $cache */ + $cache = $this->getCacheControllerFactory() + ->createCacheController('output', ['defaultgroup' => 'com_templates']); + + if ($this->getLanguageFilter()) { + $tag = $this->getLanguage()->getTag(); + } else { + $tag = ''; + } + + $cacheId = 'templates0' . $tag; + + if ($cache->contains($cacheId)) { + $templates = $cache->get($cacheId); + } else { + $templates = $this->bootComponent('templates')->getMVCFactory() + ->createModel('Style', 'Administrator')->getSiteTemplates(); + + foreach ($templates as $template) { + // Create home element + if ($template->home == 1 && !isset($template_home) || $this->getLanguageFilter() && $template->home == $tag) { + $template_home = clone $template; + } + + $template->params = new Registry($template->params); + } + + // Add home element, after loop to avoid double execution + if (isset($template_home)) { + $template_home->params = new Registry($template_home->params); + $templates[0] = $template_home; + } + + $cache->store($templates, $cacheId); + } + + return $templates; + } + + /** + * Find a valid template by name + * + * @param array $templates An array of template objects + * @param string $templateName The template name + * + * @return ?\stdClass The template object if found, null otherwise + * + * @since 6.1.0 + */ + private function findTemplate(array $templates, string $templateName): ?\stdClass + { + foreach ($templates as $template) { + if ($template->template === $templateName && $this->isValidTemplate($template)) { + return $template; + } + } + + return null; + } } diff --git a/libraries/src/Application/WebApplication.php b/libraries/src/Application/WebApplication.php index d276f17ec31bf..a143efefcff55 100644 --- a/libraries/src/Application/WebApplication.php +++ b/libraries/src/Application/WebApplication.php @@ -19,13 +19,13 @@ use Joomla\CMS\Event\Application\BeforeRenderEvent; use Joomla\CMS\Event\Application\BeforeRespondEvent; use Joomla\CMS\Factory; -use Joomla\CMS\Input\Input; use Joomla\CMS\Language\Language; use Joomla\CMS\Session\Session; use Joomla\CMS\Uri\Uri; use Joomla\CMS\User\User; use Joomla\CMS\Version; use Joomla\Filter\OutputFilter; +use Joomla\Input\Input; use Joomla\Registry\Registry; use Joomla\Session\SessionEvent; use Psr\Http\Message\ResponseInterface; @@ -56,16 +56,6 @@ abstract class WebApplication extends AbstractWebApplication */ public $JComponentTitle; - /** - * The item associations - * - * @var integer - * @since 4.3.0 - * - * @deprecated 4.4.0 will be removed in 6.0 as this property is not used anymore - */ - public $item_associations; - /** * The application document object. * @@ -94,7 +84,7 @@ abstract class WebApplication extends AbstractWebApplication * Class constructor. * * @param ?Input $input An optional argument to provide dependency injection for the application's - * input object. If the argument is a JInput object that object will become + * input object. If the argument is a Input object that object will become * the application's input object, otherwise a default input object is created. * @param ?Registry $config An optional argument to provide dependency injection for the application's * config object. If the argument is a Registry object that object will become @@ -111,7 +101,7 @@ abstract class WebApplication extends AbstractWebApplication */ public function __construct(?Input $input = null, ?Registry $config = null, ?WebClient $client = null, ?ResponseInterface $response = null) { - // Ensure we have a CMS Input object otherwise the DI for \Joomla\CMS\Session\Storage\JoomlaStorage fails + // Ensure we have a Input object otherwise the DI for \Joomla\CMS\Session\Storage\JoomlaStorage fails $input = $input ?: new Input(); parent::__construct($input, $config, $client, $response); @@ -136,7 +126,7 @@ public function __construct(?Input $input = null, ?Registry $config = null, ?Web * @since 1.7.3 * @throws \RuntimeException * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use the application service in the DI container instead * Example: \Joomla\CMS\Factory::getContainer()->get($name) */ @@ -144,7 +134,7 @@ public static function getInstance($name = null) { // Only create the object if it doesn't exist. if (empty(static::$instance)) { - if (!is_subclass_of($name, '\\Joomla\\CMS\\Application\\WebApplication')) { + if (!is_subclass_of($name, __CLASS__)) { throw new \RuntimeException(\sprintf('Unable to load application: %s', $name), 500); } @@ -343,7 +333,7 @@ public function loadLanguage(?Language $language = null) * * @since 1.7.3 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * The session should be injected as a service. */ public function loadSession(?Session $session = null) @@ -469,4 +459,42 @@ public function getConfig() { return $this->config; } + + /** + * Proxy to the input property. + * + * @return Input | null + * + * @since 6.0.0 + * @deprecated 4.0 will be removed in 8.0 use $this->getInput() instead + */ + public function __get($name) + { + switch ($name) { + case 'input': + trigger_deprecation( + 'cms/application', + '6.0', + 'Accessing the input property of %s is deprecated, use the %s::getInput() method instead.', + self::class, + self::class + ); + + return $this->getInput(); + + default: + $trace = debug_backtrace(); + trigger_error( + \sprintf( + 'Undefined property via __get(): %1$s in %2$s on line %3$s', + $name, + $trace[0]['file'], + $trace[0]['line'] + ), + E_USER_NOTICE + ); + + return null; + } + } } diff --git a/libraries/src/Association/AssociationExtensionHelper.php b/libraries/src/Association/AssociationExtensionHelper.php index 3a6191187fc57..9e1aca7eca32e 100644 --- a/libraries/src/Association/AssociationExtensionHelper.php +++ b/libraries/src/Association/AssociationExtensionHelper.php @@ -114,11 +114,12 @@ public function getType($typeName = '') $title = ''; return [ - 'fields' => $fields, - 'support' => $support, - 'tables' => $tables, - 'joins' => $joins, - 'title' => $title, + 'fields' => $fields, + 'support' => $support, + 'tables' => $tables, + 'joins' => $joins, + 'title' => $title, + 'urlOptions' => $this->getUrlOptions($typeName), ]; } @@ -247,6 +248,20 @@ public function getTypeFieldName($typeName, $fieldName) return substr($tmp, $pos + 1); } + /** + * Get a table field name for a type + * + * @param string $typeName The item type + * + * @return array + * + * @since 6.1.0 + */ + public function getUrlOptions($type = '') + { + return []; + } + /** * Get default values for support array * diff --git a/libraries/src/Authentication/Password/MD5Handler.php b/libraries/src/Authentication/Password/MD5Handler.php index 8719b5a719675..750971807c44b 100644 --- a/libraries/src/Authentication/Password/MD5Handler.php +++ b/libraries/src/Authentication/Password/MD5Handler.php @@ -10,7 +10,6 @@ namespace Joomla\CMS\Authentication\Password; use Joomla\Authentication\Password\HandlerInterface; -use Joomla\CMS\Crypt\Crypt; use Joomla\CMS\User\UserHelper; // phpcs:disable PSR1.Files.SideEffects @@ -22,7 +21,7 @@ * * @since 4.0.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Support for MD5 hashed passwords will be removed without replacement */ class MD5Handler implements HandlerInterface, CheckIfRehashNeededHandlerInterface @@ -91,6 +90,6 @@ public function validatePassword($plaintext, $hashed) // If the salt is empty AND there is a ':' in the original hash, we must append ':' at the end $testcrypt = md5($plaintext . $salt) . ($salt ? ':' . $salt : (str_contains($hashed, ':') ? ':' : '')); - return Crypt::timingSafeCompare($hashed, $testcrypt); + return hash_equals($hashed, $testcrypt); } } diff --git a/libraries/src/Authentication/Password/PHPassHandler.php b/libraries/src/Authentication/Password/PHPassHandler.php index 823123e5bb178..0e42e97f00c59 100644 --- a/libraries/src/Authentication/Password/PHPassHandler.php +++ b/libraries/src/Authentication/Password/PHPassHandler.php @@ -20,7 +20,7 @@ * * @since 4.0.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Support for PHPass hashed passwords will be removed without replacement */ class PHPassHandler implements HandlerInterface, CheckIfRehashNeededHandlerInterface diff --git a/libraries/src/Cache/Cache.php b/libraries/src/Cache/Cache.php index cef3fa92bfe8b..0850b9d84bd04 100644 --- a/libraries/src/Cache/Cache.php +++ b/libraries/src/Cache/Cache.php @@ -87,7 +87,7 @@ public function __construct($options) * * @since 1.7.0 * - * @deprecated 4.2 will be removed in 6.0 + * @deprecated 4.2 will be removed in 7.0 * Use the cache controller factory instead * Example: Factory::getContainer()->get(CacheControllerFactoryInterface::class)->createCacheController($type, $options); */ diff --git a/libraries/src/Cache/CacheController.php b/libraries/src/Cache/CacheController.php index 038d1e321d602..d5e5465dd1503 100644 --- a/libraries/src/Cache/CacheController.php +++ b/libraries/src/Cache/CacheController.php @@ -87,7 +87,7 @@ public function __call($name, $arguments) * @since 1.7.0 * @throws \RuntimeException * - * @deprecated 4.2 will be removed in 6.0 + * @deprecated 4.2 will be removed in 7.0 * Use the cache controller factory instead * Example: Factory::getContainer()->get(CacheControllerFactoryInterface::class)->createCacheController($type, $options); */ @@ -122,7 +122,7 @@ public static function getInstance($type = 'output', $options = []) // Only trigger a deprecation notice if the file and class are found @trigger_error( - 'Support for including cache controllers using path lookup is deprecated and will be removed in 5.0.' + 'Support for including cache controllers using path lookup is deprecated and will be removed in 7.0.' . ' Use a custom cache controller factory instead.', E_USER_DEPRECATED ); @@ -141,7 +141,7 @@ public static function getInstance($type = 'output', $options = []) * * @since 1.7.0 * - * @deprecated 4.2 will be removed in 6.0 + * @deprecated 4.2 will be removed in 7.0 * Use the cache controller factory instead * Example: Factory::getContainer()->get(CacheControllerFactoryInterface::class)->createCacheController($type, $options); */ @@ -156,7 +156,7 @@ public static function addIncludePath($path = '') if (!empty($path) && !\in_array($path, $paths)) { // Only trigger a deprecation notice when adding a lookup path @trigger_error( - 'Support for including cache controllers using path lookup is deprecated and will be removed in 5.0.' + 'Support for including cache controllers using path lookup is deprecated and will be removed in 7.0.' . ' Use a custom cache controller factory instead.', E_USER_DEPRECATED ); diff --git a/libraries/src/Cache/CacheControllerFactoryAwareTrait.php b/libraries/src/Cache/CacheControllerFactoryAwareTrait.php index b7a5446bcd246..8684255e926ac 100644 --- a/libraries/src/Cache/CacheControllerFactoryAwareTrait.php +++ b/libraries/src/Cache/CacheControllerFactoryAwareTrait.php @@ -45,7 +45,7 @@ protected function getCacheControllerFactory(): CacheControllerFactoryInterface } @trigger_error( - \sprintf('A cache controller is needed in %s. An UnexpectedValueException will be thrown in 5.0.', __CLASS__), + \sprintf('A cache controller is needed in %s. An UnexpectedValueException will be thrown in 7.0.', __CLASS__), E_USER_DEPRECATED ); diff --git a/libraries/src/Cache/Storage/RedisStorage.php b/libraries/src/Cache/Storage/RedisStorage.php index 19a352c4ee62e..123d82d017772 100644 --- a/libraries/src/Cache/Storage/RedisStorage.php +++ b/libraries/src/Cache/Storage/RedisStorage.php @@ -307,7 +307,7 @@ public function clean($group, $mode = null) */ public static function isSupported() { - return class_exists('\\Redis'); + return class_exists(\Redis::class); } /** diff --git a/libraries/src/Captcha/Google/HttpBridgePostRequestMethod.php b/libraries/src/Captcha/Google/HttpBridgePostRequestMethod.php index acee2c848c368..edf171bd82b6f 100644 --- a/libraries/src/Captcha/Google/HttpBridgePostRequestMethod.php +++ b/libraries/src/Captcha/Google/HttpBridgePostRequestMethod.php @@ -9,9 +9,11 @@ namespace Joomla\CMS\Captcha\Google; -use Joomla\CMS\Http\HttpFactory; +use Joomla\CMS\Version; use Joomla\Http\Exception\InvalidResponseCodeException; use Joomla\Http\Http; +use Joomla\Http\HttpFactory; +use Joomla\Registry\Registry; use ReCaptcha\RequestMethod; use ReCaptcha\RequestParameters; @@ -51,7 +53,10 @@ final class HttpBridgePostRequestMethod implements RequestMethod */ public function __construct(?Http $http = null) { - $this->http = $http ?: HttpFactory::getHttp(); + $options = new Registry(); + $options->set('userAgent', (new Version())->getUserAgent('Joomla', true, false)); + + $this->http = $http ?: (new HttpFactory())->getHttp($options); } /** diff --git a/libraries/src/Categories/Categories.php b/libraries/src/Categories/Categories.php index 24b8ee3310c26..de4b6e9e307bb 100644 --- a/libraries/src/Categories/Categories.php +++ b/libraries/src/Categories/Categories.php @@ -86,6 +86,14 @@ class Categories implements CategoryInterface, DatabaseAwareInterface */ protected $_key; + /** + * Name of the items access field + * + * @var string + * @since 6.2.0 + */ + protected $_accessfield; + /** * Name of the items state field * @@ -111,15 +119,17 @@ class Categories implements CategoryInterface, DatabaseAwareInterface */ public function __construct($options) { - $this->_extension = $options['extension']; - $this->_table = $options['table']; - $this->_field = isset($options['field']) && $options['field'] ? $options['field'] : 'catid'; - $this->_key = isset($options['key']) && $options['key'] ? $options['key'] : 'id'; - $this->_statefield = $options['statefield'] ?? 'state'; - - $options['access'] ??= 'true'; - $options['published'] ??= 1; - $options['countItems'] ??= 0; + $this->_extension = $options['extension']; + $this->_table = $options['table']; + $this->_field = isset($options['field']) && $options['field'] ? $options['field'] : 'catid'; + $this->_key = isset($options['key']) && $options['key'] ? $options['key'] : 'id'; + $this->_accessfield = $options['accessfield'] ?? null; + $this->_statefield = $options['statefield'] ?? 'state'; + + $options['access'] ??= 'true'; + $options['published'] ??= 1; + $options['countItems'] ??= 0; + $options['accessOnItems'] ??= 1; $options['currentlang'] = Multilanguage::isEnabled() ? Factory::getLanguage()->getTag() : 0; $this->_options = $options; @@ -135,7 +145,7 @@ public function __construct($options) * * @since 1.6 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use the ComponentInterface to get the categories * Example: Factory::getApplication()->bootComponent($component)->getCategory($options, $section); */ @@ -237,7 +247,7 @@ protected function _load($id) try { $db = $this->getDatabase(); } catch (DatabaseNotFoundException) { - @trigger_error('Database must be set, this will not be caught anymore in 5.0.', E_USER_DEPRECATED); + @trigger_error('Database must be set, this will not be caught anymore in 7.0.', E_USER_DEPRECATED); $db = Factory::getContainer()->get(DatabaseInterface::class); } @@ -256,7 +266,7 @@ protected function _load($id) // Record that has this $id has been checked $this->_checkedCategories[$id] = true; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('c.id'), @@ -351,11 +361,18 @@ protected function _load($id) // Note: i for item if ($this->_options['countItems'] == 1) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select('COUNT(' . $db->quoteName($db->escape('i.' . $this->_key)) . ')') ->from($db->quoteName($db->escape($this->_table), 'i')) ->where($db->quoteName($db->escape('i.' . $this->_field)) . ' = ' . $db->quoteName('c.id')); + if ($this->_accessfield && $this->_options['accessOnItems']) { + $subQuery->where( + $db->quoteName($db->escape('i.' . $this->_accessfield)) + . ' IN (' . implode(',', $query->bindArray($user->getAuthorisedViewLevels())) . ')' + ); + } + if ($this->_options['published'] == 1) { $subQuery->where($db->quoteName($db->escape('i.' . $this->_statefield)) . ' = 1'); } diff --git a/libraries/src/Categories/CategoryNode.php b/libraries/src/Categories/CategoryNode.php index 07186ec2d71b1..120a8649cdb14 100644 --- a/libraries/src/Categories/CategoryNode.php +++ b/libraries/src/Categories/CategoryNode.php @@ -10,7 +10,6 @@ namespace Joomla\CMS\Categories; use Joomla\CMS\Factory; -use Joomla\CMS\Object\LegacyErrorHandlingTrait; use Joomla\CMS\Object\LegacyPropertyManagementTrait; use Joomla\CMS\Tree\NodeInterface; use Joomla\CMS\Tree\NodeTrait; @@ -28,7 +27,6 @@ #[\AllowDynamicProperties] class CategoryNode implements NodeInterface { - use LegacyErrorHandlingTrait; use LegacyPropertyManagementTrait; use NodeTrait; diff --git a/libraries/src/Changelog/Changelog.php b/libraries/src/Changelog/Changelog.php index 51928fb4399b4..75ce0209b28f8 100644 --- a/libraries/src/Changelog/Changelog.php +++ b/libraries/src/Changelog/Changelog.php @@ -9,12 +9,11 @@ namespace Joomla\CMS\Changelog; -use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Object\LegacyErrorHandlingTrait; use Joomla\CMS\Object\LegacyPropertyManagementTrait; use Joomla\CMS\Version; +use Joomla\Http\HttpFactory; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects @@ -28,7 +27,6 @@ */ class Changelog { - use LegacyErrorHandlingTrait; use LegacyPropertyManagementTrait; /** @@ -351,7 +349,7 @@ public function loadFromXml($url) $httpOption->set('userAgent', $version->getUserAgent('Joomla', true, false)); try { - $http = HttpFactory::getHttp($httpOption); + $http = (new HttpFactory())->getHttp($httpOption); $response = $http->get($url); } catch (\RuntimeException) { $response = null; diff --git a/libraries/src/Client/ClientHelper.php b/libraries/src/Client/ClientHelper.php index 76186c32338b4..987436116bffb 100644 --- a/libraries/src/Client/ClientHelper.php +++ b/libraries/src/Client/ClientHelper.php @@ -39,10 +39,9 @@ public static function getCredentials($client, $force = false) static $credentials = []; $client = strtolower($client); + $app = Factory::getApplication(); if (!isset($credentials[$client]) || $force) { - $app = Factory::getApplication(); - // Fetch the client layer configuration options for the specific client switch ($client) { case 'ftp': @@ -63,7 +62,7 @@ public static function getCredentials($client, $force = false) // If user and pass are not set in global config lets see if they are in the session if ($options['enabled'] && ($options['user'] == '' || $options['pass'] == '')) { - $session = Factory::getSession(); + $session = $app->getSession(); $options['user'] = $session->get($client . '.user', null, 'JClientHelper'); $options['pass'] = $session->get($client . '.pass', null, 'JClientHelper'); } @@ -95,11 +94,11 @@ public static function setCredentials($client, $user, $pass) { $return = false; $client = strtolower($client); + $app = Factory::getApplication(); // Test if the given credentials are valid switch ($client) { case 'ftp': - $app = Factory::getApplication(); $options = ['enabled' => $app->get('ftp_enable'), 'host' => $app->get('ftp_host'), 'port' => $app->get('ftp_port')]; if ($options['enabled']) { @@ -122,7 +121,7 @@ public static function setCredentials($client, $user, $pass) if ($return) { // Save valid credentials to the session - $session = Factory::getSession(); + $session = $app->getSession(); $session->set($client . '.user', $user, 'JClientHelper'); $session->set($client . '.pass', $pass, 'JClientHelper'); @@ -146,11 +145,11 @@ public static function hasCredentials($client) { $return = false; $client = strtolower($client); + $app = Factory::getApplication(); // Get (unmodified) credentials for this client switch ($client) { case 'ftp': - $app = Factory::getApplication(); $options = ['enabled' => $app->get('ftp_enable'), 'user' => $app->get('ftp_user'), 'pass' => $app->get('ftp_pass')]; break; @@ -167,7 +166,7 @@ public static function hasCredentials($client) $return = true; } else { // Check if login credentials are available in the session - $session = Factory::getSession(); + $session = $app->getSession(); $user = $session->get($client . '.user', null, 'JClientHelper'); $pass = $session->get($client . '.pass', null, 'JClientHelper'); diff --git a/libraries/src/Component/ComponentHelper.php b/libraries/src/Component/ComponentHelper.php index eb508008a035d..8ee5923a80675 100644 --- a/libraries/src/Component/ComponentHelper.php +++ b/libraries/src/Component/ComponentHelper.php @@ -320,7 +320,7 @@ public static function renderComponent($option, $params = []) * @var string * @since 1.5 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement */ \define('JPATH_COMPONENT', JPATH_BASE . '/components/' . $option); @@ -333,7 +333,7 @@ public static function renderComponent($option, $params = []) * @var string * @since 1.5 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement */ \define('JPATH_COMPONENT_SITE', JPATH_SITE . '/components/' . $option); @@ -346,7 +346,7 @@ public static function renderComponent($option, $params = []) * @var string * @since 1.5 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement */ \define('JPATH_COMPONENT_ADMINISTRATOR', JPATH_ADMINISTRATOR . '/components/' . $option); @@ -382,8 +382,8 @@ protected static function load() { $loader = function () { $db = Factory::getDbo(); - $query = $db->getQuery(true) - ->select($db->quoteName(['extension_id', 'element', 'params', 'enabled'], ['id', 'option', null, null])) + $query = $db->createQuery() + ->select($db->quoteName(['extension_id', 'element', 'params', 'enabled', 'custom_data'], ['id', 'option', null, null, null])) ->from($db->quoteName('#__extensions')) ->where( [ diff --git a/libraries/src/Component/ComponentRecord.php b/libraries/src/Component/ComponentRecord.php index abb32312191de..f46d056c8d026 100644 --- a/libraries/src/Component/ComponentRecord.php +++ b/libraries/src/Component/ComponentRecord.php @@ -65,6 +65,14 @@ class ComponentRecord */ public $enabled; + /** + * The component custom data + * + * @var string + * @since 6.1.0 + */ + public $custom_data; + /** * Class constructor * @@ -88,7 +96,7 @@ public function __construct($data = []) * * @since 3.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Access the item parameters through the `getParams()` method * Example: * $componentRecord->getParams(); @@ -112,7 +120,7 @@ public function __get($name) * * @since 3.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Set the item parameters through the `setParams()` method * Example: * $componentRecord->setParams($value); diff --git a/libraries/src/Component/Router/Rules/MenuRules.php b/libraries/src/Component/Router/Rules/MenuRules.php index 4deac6ec64a1a..0ab853bd0e0fd 100644 --- a/libraries/src/Component/Router/Rules/MenuRules.php +++ b/libraries/src/Component/Router/Rules/MenuRules.php @@ -47,7 +47,7 @@ class MenuRules implements RulesInterface * * @var Registry * @since 5.2.0 - * @deprecated 5.2.0 will be removed in 6.0 + * @deprecated 5.2.0 will be removed in 7.0 * without replacement */ private $sefparams; @@ -171,7 +171,7 @@ public function preprocess(&$query) } } - // TODO: Remove this whole block in 6.0 as it is a bug + // TODO: Remove this whole block in 7.0 as it is a bug if (!$this->sefparams->get('strictrouting', 0)) { // Check if the active menuitem matches the requested language if ( diff --git a/libraries/src/Component/Router/Rules/PreprocessRules.php b/libraries/src/Component/Router/Rules/PreprocessRules.php index b75a9e42ba576..831ef15f62c58 100644 --- a/libraries/src/Component/Router/Rules/PreprocessRules.php +++ b/libraries/src/Component/Router/Rules/PreprocessRules.php @@ -107,7 +107,7 @@ public function preprocess(&$query) return; } - $dbquery = $this->getDatabase()->getQuery(true); + $dbquery = $this->getDatabase()->createQuery(); $id = (int) $query[$key]; $dbquery->select($dbquery->quoteName('alias')) diff --git a/libraries/src/Console/AddUserCommand.php b/libraries/src/Console/AddUserCommand.php index 93c944641852a..578b46fa79ddf 100644 --- a/libraries/src/Console/AddUserCommand.php +++ b/libraries/src/Console/AddUserCommand.php @@ -189,7 +189,7 @@ protected function doExecute(InputInterface $input, OutputInterface $output): in protected function getGroupId($groupName) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('title') . ' = :groupName') @@ -257,7 +257,7 @@ protected function getUserGroups(): array } // Generate select list for user - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__usergroups')) ->order($db->quoteName('id') . 'ASC'); diff --git a/libraries/src/Console/AddUserToGroupCommand.php b/libraries/src/Console/AddUserToGroupCommand.php index bd2bcf9fc274b..c7cf919a828c4 100644 --- a/libraries/src/Console/AddUserToGroupCommand.php +++ b/libraries/src/Console/AddUserToGroupCommand.php @@ -120,7 +120,7 @@ protected function doExecute(InputInterface $input, OutputInterface $output): in $this->userGroups = $this->getGroups($user); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('id') . ' = :userGroup'); @@ -182,7 +182,7 @@ protected function getGroups($user): array $userGroups = Access::getGroupsByUser($user->id, false); // Generate select list for user - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__usergroups')) ->whereNotIn($db->quoteName('id'), $userGroups) @@ -218,7 +218,7 @@ protected function getGroups($user): array protected function getGroupId($groupName) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('title') . '= :groupName') @@ -240,7 +240,7 @@ protected function getGroupId($groupName) protected function getUserId($username) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where($db->quoteName('username') . '= :username') diff --git a/libraries/src/Console/CheckJoomlaUpdatesCommand.php b/libraries/src/Console/CheckJoomlaUpdatesCommand.php index 7f31704b74245..ec59345350693 100644 --- a/libraries/src/Console/CheckJoomlaUpdatesCommand.php +++ b/libraries/src/Console/CheckJoomlaUpdatesCommand.php @@ -51,7 +51,7 @@ class CheckJoomlaUpdatesCommand extends AbstractCommand * @param string|null $name The name of the command; if the name is empty and no default is set, a name must be set in the configure() method * * @since 5.1.0 - * @deprecated 5.1.0 will be removed in 6.0 + * @deprecated 5.1.0 will be removed in 7.0 * Use core:update:check instead of core:check-updates * */ diff --git a/libraries/src/Console/CoreUpdateChannelCommand.php b/libraries/src/Console/CoreUpdateChannelCommand.php index bfc9a0b7e826b..ac15dccbd7c23 100644 --- a/libraries/src/Console/CoreUpdateChannelCommand.php +++ b/libraries/src/Console/CoreUpdateChannelCommand.php @@ -10,7 +10,7 @@ namespace Joomla\CMS\Console; use Joomla\CMS\Component\ComponentHelper; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; use Joomla\Component\Joomlaupdate\Administrator\Model\UpdateModel; use Joomla\Console\Command\AbstractCommand; use Joomla\Database\DatabaseInterface; @@ -134,7 +134,7 @@ protected function doExecute(InputInterface $input, OutputInterface $output): in } // Storing the parameters in the DB - $table = Table::getInstance('extension'); + $table = new Extension($this->db); $table->load(['type' => 'component', 'element' => 'com_joomlaupdate']); $table->params = $params->toString(); $table->store(); diff --git a/libraries/src/Console/DeleteUserCommand.php b/libraries/src/Console/DeleteUserCommand.php index 6dc7f5c8f9dd9..ac100d0bdefce 100644 --- a/libraries/src/Console/DeleteUserCommand.php +++ b/libraries/src/Console/DeleteUserCommand.php @@ -119,7 +119,7 @@ protected function doExecute(InputInterface $input, OutputInterface $output): in if ($user->block == 0) { foreach ($groups as $groupId) { if (Access::checkGroup($groupId, 'core.admin')) { - $queryUser = $db->getQuery(true); + $queryUser = $db->createQuery(); $queryUser->select('COUNT(*)') ->from($db->quoteName('#__users', 'u')) ->leftJoin( diff --git a/libraries/src/Console/ExtensionDisableCommand.php b/libraries/src/Console/ExtensionDisableCommand.php new file mode 100644 index 0000000000000..4a874720c613b --- /dev/null +++ b/libraries/src/Console/ExtensionDisableCommand.php @@ -0,0 +1,216 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Console; + +use Joomla\CMS\Table\Extension; +use Joomla\Component\Templates\Administrator\Table\StyleTable; +use Joomla\Console\Command\AbstractCommand; +use Joomla\Database\DatabaseAwareTrait; +use Joomla\Database\DatabaseInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Console command to disable extensions + * + * @since 6.1.0 + */ +class ExtensionDisableCommand extends AbstractCommand +{ + use DatabaseAwareTrait; + + /** + * The default command name + * + * @var string + * @since 6.1.0 + */ + protected static $defaultName = 'extension:disable'; + + /** + * @var InputInterface + * @since 6.1.0 + */ + private $cliInput; + + /** + * @var SymfonyStyle + * @since 6.1.0 + */ + private $ioStyle; + + /** + * Exit Code for extensions already enabled\disabled + * @since 6.1.0 + */ + public const DISABLE_NOCHANGE = 3; + + /** + * Exit Code for extensions enable\disable failure + * @since 6.1.0 + */ + public const DISABLE_FAILED = 1; + + /** + * Exit Code for disable parent template with child failure + * @since 6.1.0 + */ + public const DISABLE_WITHCHILD_NOT_PERMITTED = 5; + + /** + * Exit Code for disable home template failure + * @since 6.1.0 + */ + public const DISABLE_HOME_NOT_PERMITTED = 6; + + /** + * Exit Code for extensions protected enable\disable failure + * @since 6.1.0 + */ + public const DISABLE_PROTECTED = 4; + + /** + * Exit Code for extensions not found + * @since 6.1.0 + */ + public const DISABLE_NOT_FOUND = 2; + + /** + * Exit Code for extensions enable\disable success + * @since 6.1.0 + */ + public const DISABLE_SUCCESSFUL = 0; + + /** + * Command constructor. + * + * @param DatabaseInterface $db The database + * + * @since 6.1.0 + */ + public function __construct(DatabaseInterface $db) + { + parent::__construct(); + + $this->setDatabase($db); + } + + /** + * Configures the IO + * + * @param InputInterface $input Console Input + * @param OutputInterface $output Console Output + * + * @return void + * + * @since 6.1.0 + * + */ + private function configureIO(InputInterface $input, OutputInterface $output): void + { + $this->cliInput = $input; + $this->ioStyle = new SymfonyStyle($input, $output); + } + + /** + * Initialise the command. + * + * @return void + * + * @since 6.1.0 + */ + protected function configure(): void + { + $this->addArgument( + 'extensionId', + InputArgument::REQUIRED, + 'ID of extension to be disabled (run extension:list command to check)' + ); + + $help = "%command.name% is used to disable an extension. + \nThe command requires one argument, the ID of the extension to disable. + \nYou may find this ID by running the extension:list command. + \nUsage: php %command.full_name% "; + + $this->setDescription('Disable an extension'); + $this->setHelp($help); + } + + /** + * Internal function to execute the command. + * + * @param InputInterface $input The input to inject into the command. + * @param OutputInterface $output The output to inject into the command. + * + * @return integer The command exit code + * + * @since 6.1.0 + */ + protected function doExecute(InputInterface $input, OutputInterface $output): int + { + $this->configureIO($input, $output); + + $extensionId = $this->cliInput->getArgument('extensionId'); + $this->ioStyle->title('Disable Extension'); + + // Get a table object for the extension type + $table = new Extension($this->getDatabase()); + + if ((int) $extensionId === 0 || !$table->load($extensionId)) { + $this->ioStyle->error("Extension with ID of $extensionId not found."); + + return self::DISABLE_NOT_FOUND; + } + + if ($table->type === 'template') { + $style = new StyleTable($this->getDatabase()); + + if ($style->load(['template' => $table->element, 'client_id' => $table->client_id, 'home' => 1])) { + $this->ioStyle->note("Template with ID of $extensionId $table->element is home."); + return self::DISABLE_HOME_NOT_PERMITTED; + } + + // Parent template cannot be disabled if there are children + if ($style->load(['parent' => $table->element, 'client_id' => $table->client_id])) { + $this->ioStyle->note("Template with ID of $extensionId $table->element have child."); + return self::DISABLE_WITHCHILD_NOT_PERMITTED; + } + } + + $type = ucfirst($table->type); + + if ($table->protected === 1) { + $this->ioStyle->error("$type with ID of $extensionId $table->name is protectd."); + return self::DISABLE_PROTECTED; + } + + if ($table->enabled === 0) { + $this->ioStyle->warning("$type with ID of $extensionId $table->name already is disabled."); + return self::DISABLE_NOCHANGE; + } + + $table->enabled = 0; + + if (!$table->store()) { + $this->ioStyle->error("$type with ID of $extensionId $table->name not disabled."); + return self::DISABLE_FAILED; + } + + $this->ioStyle->success("$type with ID of $extensionId $table->name disabled."); + + return self::DISABLE_SUCCESSFUL; + } +} diff --git a/libraries/src/Console/ExtensionDiscoverInstallCommand.php b/libraries/src/Console/ExtensionDiscoverInstallCommand.php index 9306da19403d3..d6d38c6622ea8 100644 --- a/libraries/src/Console/ExtensionDiscoverInstallCommand.php +++ b/libraries/src/Console/ExtensionDiscoverInstallCommand.php @@ -128,7 +128,7 @@ public function processDiscover($eid): int } $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['extension_id'])) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('state') . ' = -1'); diff --git a/libraries/src/Console/ExtensionEnableCommand.php b/libraries/src/Console/ExtensionEnableCommand.php new file mode 100644 index 0000000000000..69b2a1e3335a1 --- /dev/null +++ b/libraries/src/Console/ExtensionEnableCommand.php @@ -0,0 +1,179 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Console; + +use Joomla\CMS\Table\Extension; +use Joomla\Console\Command\AbstractCommand; +use Joomla\Database\DatabaseAwareTrait; +use Joomla\Database\DatabaseInterface; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Console command to enable extensions + * + * @since 6.1.0 + */ +class ExtensionEnableCommand extends AbstractCommand +{ + use DatabaseAwareTrait; + + /** + * The default command name + * + * @var string + * @since 6.1.0 + */ + protected static $defaultName = 'extension:enable'; + + /** + * @var InputInterface + * @since 6.1.0 + */ + private $cliInput; + + /** + * @var SymfonyStyle + * @since 6.1.0 + */ + private $ioStyle; + + /** + * Exit Code for extensions already enabled\disabled + * @since 6.1.0 + */ + public const ENABLE_NOCHANGE = 3; + + /** + * Exit Code for extensions enable\disable failure + * @since 6.1.0 + */ + public const ENABLE_FAILED = 1; + + /** + * Exit Code for extensions not found + * @since 6.1.0 + */ + public const ENABLE_NOT_FOUND = 2; + + /** + * Exit Code for extensions enable\disable success + * @since 6.1.0 + */ + public const ENABLE_SUCCESSFUL = 0; + + /** + * Command constructor. + * + * @param DatabaseInterface $db The database + * + * @since 6.1.0 + */ + public function __construct(DatabaseInterface $db) + { + parent::__construct(); + + $this->setDatabase($db); + } + + /** + * Configures the IO + * + * @param InputInterface $input Console Input + * @param OutputInterface $output Console Output + * + * @return void + * + * @since 6.1.0 + * + */ + private function configureIO(InputInterface $input, OutputInterface $output): void + { + $this->cliInput = $input; + $this->ioStyle = new SymfonyStyle($input, $output); + } + + /** + * Initialise the command. + * + * @return void + * + * @since 6.1.0 + */ + protected function configure(): void + { + $this->addArgument( + 'extensionId', + InputArgument::REQUIRED, + 'ID of extension to be enabled (run extension:list command to check)' + ); + + $help = "%command.name% is used to enable an extension. + \nThe command requires one argument, the ID of the extension to enable. + \nYou may find this ID by running the extension:list command. + \nUsage: php %command.full_name% "; + + $this->setDescription('Enable an extension'); + $this->setHelp($help); + } + + /** + * Internal function to execute the command. + * + * @param InputInterface $input The input to inject into the command. + * @param OutputInterface $output The output to inject into the command. + * + * @return integer The command exit code + * + * @since 6.1.0 + */ + protected function doExecute(InputInterface $input, OutputInterface $output): int + { + $this->configureIO($input, $output); + $commandSelected = $input->getFirstArgument(); + + $extensionId = $this->cliInput->getArgument('extensionId'); + + $this->ioStyle->title('Enable Extension'); + + // Get a table object for the extension type + $table = new Extension($this->getDatabase()); + + if ((int) $extensionId === 0 || !$table->load($extensionId)) { + $this->ioStyle->error("Extension with ID of $extensionId not found."); + + return self::ENABLE_NOT_FOUND; + } + + $type = ucfirst($table->type); + + if ($table->enabled === 1) { + $this->ioStyle->warning("$type with ID of $extensionId $table->name already is enabled."); + return self::ENABLE_NOCHANGE; + } + + $table->enabled = 1; + + if (!$table->store()) { + $this->ioStyle->error("$type with ID of $extensionId $table->name not enabled."); + return self::ENABLE_FAILED; + } + + $this->ioStyle->success("$type with ID of $extensionId $table->name enabled."); + + return self::ENABLE_SUCCESSFUL; + } +} diff --git a/libraries/src/Console/ExtensionInstallCommand.php b/libraries/src/Console/ExtensionInstallCommand.php index 557646a68ede4..80efcc8323a28 100644 --- a/libraries/src/Console/ExtensionInstallCommand.php +++ b/libraries/src/Console/ExtensionInstallCommand.php @@ -12,6 +12,8 @@ use Joomla\CMS\Installer\Installer; use Joomla\CMS\Installer\InstallerHelper; use Joomla\Console\Command\AbstractCommand; +use Joomla\Database\DatabaseAwareTrait; +use Joomla\Database\DatabaseInterface; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -28,6 +30,8 @@ */ class ExtensionInstallCommand extends AbstractCommand { + use DatabaseAwareTrait; + /** * The default command name * @@ -62,6 +66,20 @@ class ExtensionInstallCommand extends AbstractCommand */ public const INSTALLATION_SUCCESSFUL = 0; + /** + * Command constructor. + * + * @param DatabaseInterface $db The database + * + * @since 6.0.0 + */ + public function __construct(DatabaseInterface $db) + { + parent::__construct(); + + $this->setDatabase($db); + } + /** * Configures the IO * @@ -130,7 +148,8 @@ public function processPathInstallation($path): bool return false; } - $jInstaller = Installer::getInstance(); + $jInstaller = new Installer(); + $jInstaller->setDatabase($this->getDatabase()); $result = $jInstaller->install($package['extractdir']); InstallerHelper::cleanupInstall($tmpPath, $package['extractdir']); @@ -163,6 +182,7 @@ public function processUrlInstallation($url): bool } $jInstaller = new Installer(); + $jInstaller->setDatabase($this->getDatabase()); $result = $jInstaller->install($package['extractdir']); InstallerHelper::cleanupInstall($path, $package['extractdir']); diff --git a/libraries/src/Console/ExtensionsListCommand.php b/libraries/src/Console/ExtensionsListCommand.php index 6015d3eb66806..faf607aeb3e2c 100644 --- a/libraries/src/Console/ExtensionsListCommand.php +++ b/libraries/src/Console/ExtensionsListCommand.php @@ -155,7 +155,7 @@ public function setExtensions($extensions = null): void private function getAllExtensionsFromDB(): array { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select('*') ->from('#__extensions'); $db->setQuery($query); diff --git a/libraries/src/Console/FinderIndexCommand.php b/libraries/src/Console/FinderIndexCommand.php index 66d7ebed1b5dc..f93b45e90db26 100644 --- a/libraries/src/Console/FinderIndexCommand.php +++ b/libraries/src/Console/FinderIndexCommand.php @@ -9,6 +9,9 @@ namespace Joomla\CMS\Console; +use Joomla\CMS\Event\Finder\BeforeIndexEvent; +use Joomla\CMS\Event\Finder\BuildIndexEvent; +use Joomla\CMS\Event\Finder\StartIndexEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\LanguageAwareInterface; use Joomla\CMS\Language\LanguageAwareTrait; @@ -17,6 +20,7 @@ use Joomla\Component\Finder\Administrator\Indexer\Indexer; use Joomla\Console\Command\AbstractCommand; use Joomla\Database\DatabaseInterface; +use Joomla\Event\DispatcherAwareTrait; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -36,6 +40,7 @@ class FinderIndexCommand extends AbstractCommand implements LanguageAwareInterface { use LanguageAwareTrait; + use DispatcherAwareTrait; /** * The default command name @@ -246,7 +251,7 @@ private function configureIO(InputInterface $input, OutputInterface $output): vo try { $language = $this->getLanguage(); } catch (\UnexpectedValueException) { - @trigger_error(\sprintf('Language must be set in 6.0 in %s', __METHOD__), E_USER_DEPRECATED); + @trigger_error(\sprintf('Language must be set in 7.0 in %s', __METHOD__), E_USER_DEPRECATED); $language = Factory::getLanguage(); } @@ -274,7 +279,7 @@ private function getFilters(): void // Get the taxonomy ids used by the filters. $db = $this->db; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select('filter_id, title, data') ->from($db->quoteName('#__finder_filters')); @@ -288,7 +293,7 @@ private function getFilters(): void } // Get taxonomy records. - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select('t.title, p.title AS parent') ->from($db->quoteName('#__finder_taxonomy') . ' AS t') @@ -356,14 +361,16 @@ private function index() Indexer::resetState(); // Import the plugins. - PluginHelper::importPlugin('system'); - PluginHelper::importPlugin('finder'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('system', null, true, $dispatcher); + PluginHelper::importPlugin('finder', null, true, $dispatcher); // Starting Indexer. $this->ioStyle->text(Text::_('FINDER_CLI_STARTING_INDEXER')); // Trigger the onStartIndex event. - $app->triggerEvent('onStartIndex'); + + $dispatcher->dispatch('onStartIndex', new StartIndexEvent('onStartIndex')); // Remove the script time limit. if (\function_exists('set_time_limit')) { @@ -377,7 +384,7 @@ private function index() $this->ioStyle->text(Text::_('FINDER_CLI_SETTING_UP_PLUGINS')); // Trigger the onBeforeIndex event. - $app->triggerEvent('onBeforeIndex'); + $dispatcher->dispatch('onBeforeIndex', new BeforeIndexEvent('onBeforeIndex')); // Startup reporting. $this->ioStyle->text(Text::sprintf('FINDER_CLI_SETUP_ITEMS', $state->totalItems, round(microtime(true) - $this->time, 3))); @@ -397,7 +404,7 @@ private function index() $state->batchOffset = 0; // Trigger the onBuildIndex event. - Factory::getApplication()->triggerEvent('onBuildIndex'); + $dispatcher->dispatch('onBuildIndex', new BuildIndexEvent('onBuildIndex')); // Batch reporting. $text = Text::sprintf('FINDER_CLI_BATCH_COMPLETE', $i + 1, $processingTime = round(microtime(true) - $this->qtime, 3)); @@ -474,7 +481,7 @@ private function putFilters() foreach ($filter as $element) { // Look for the old taxonomy in the new taxonomy table. - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->select('t.id') ->from($db->quoteName('#__finder_taxonomy') . ' AS t') @@ -496,7 +503,7 @@ private function putFilters() $taxonomyIds = empty($tids) ? '' : implode(',', $tids); // Update the filter with the new taxonomy ids. - $query = $db->getQuery(true); + $query = $db->createQuery(); $query ->update($db->quoteName('#__finder_filters')) ->set($db->quoteName('data') . ' = ' . $db->quote($taxonomyIds)) diff --git a/libraries/src/Console/ListUserCommand.php b/libraries/src/Console/ListUserCommand.php index a9a2d593d594f..23064f2bd142e 100644 --- a/libraries/src/Console/ListUserCommand.php +++ b/libraries/src/Console/ListUserCommand.php @@ -76,13 +76,13 @@ protected function doExecute(InputInterface $input, OutputInterface $output): in $this->configureIO($input, $output); $this->ioStyle->title('List Users'); - $groupsQuery = $db->getQuery(true) + $groupsQuery = $db->createQuery() ->select($db->quoteName(['title', 'id'])) ->from($db->quoteName('#__usergroups')); $groups = $db->setQuery($groupsQuery)->loadAssocList('id', 'title'); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName(['u.id', 'u.username', 'u.name', 'u.email', 'u.block'])) ->select($query->groupConcat($query->castAs('CHAR', $db->quoteName('g.group_id'))) . ' AS ' . $db->quoteName('groups')) ->innerJoin($db->quoteName('#__user_usergroup_map', 'g'), $db->quoteName('g.user_id') . ' = ' . $db->quoteName('u.id')) diff --git a/libraries/src/Console/RemoveUserFromGroupCommand.php b/libraries/src/Console/RemoveUserFromGroupCommand.php index 39f04bbb43c66..5befc9ad60dfe 100644 --- a/libraries/src/Console/RemoveUserFromGroupCommand.php +++ b/libraries/src/Console/RemoveUserFromGroupCommand.php @@ -119,7 +119,7 @@ protected function doExecute(InputInterface $input, OutputInterface $output): in $this->userGroups = $this->getGroups($user); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('id') . ' = :userGroup'); @@ -131,7 +131,7 @@ protected function doExecute(InputInterface $input, OutputInterface $output): in $result = $db->loadResult(); if (Access::checkGroup($userGroup, 'core.admin')) { - $queryUser = $db->getQuery(true); + $queryUser = $db->createQuery(); $queryUser->select('COUNT(*)') ->from($db->quoteName('#__users', 'u')) ->leftJoin( @@ -188,7 +188,7 @@ protected function getGroups($user): array $userGroups = Access::getGroupsByUser($user->id, false); if (!$option) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__usergroups')) ->whereIn($db->quoteName('id'), $userGroups); @@ -242,7 +242,7 @@ protected function getGroups($user): array protected function getGroupId($groupName) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('title') . '= :groupName') diff --git a/libraries/src/Console/SetConfigurationCommand.php b/libraries/src/Console/SetConfigurationCommand.php index 7db330f30e2b3..a13cbff03a2d9 100644 --- a/libraries/src/Console/SetConfigurationCommand.php +++ b/libraries/src/Console/SetConfigurationCommand.php @@ -12,7 +12,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\Console\Command\AbstractCommand; -use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseFactory; use Joomla\Registry\Registry; use Symfony\Component\Console\Input\Input; use Symfony\Component\Console\Input\InputArgument; @@ -363,7 +363,7 @@ public function checkDb($options): bool // Get a database object. try { - $db = DatabaseDriver::getInstance($settings); + $db = (new DatabaseFactory())->getDriver($settings['driver'], $settings); $db->getVersion(); } catch (\Exception $e) { $this->ioStyle->error( diff --git a/libraries/src/Console/UpdateCoreCommand.php b/libraries/src/Console/UpdateCoreCommand.php index d1224c5f5dc2a..ca9132d8edad4 100644 --- a/libraries/src/Console/UpdateCoreCommand.php +++ b/libraries/src/Console/UpdateCoreCommand.php @@ -525,24 +525,34 @@ public function checkSchema(): int * * @return boolean True if success * - * @since 5.4.0 + * @since 6.0.0 */ public function checkMajorUpgrade(): bool { $return = true; $language = Factory::getLanguage(); - $language->load('plg_behaviour_compat.sys', JPATH_ADMINISTRATOR); - $language->load('plg_behaviour_compat6.sys', JPATH_ADMINISTRATOR); - if (PluginHelper::isEnabled('behaviour', 'compat')) { - $this->ioStyle->error('The \'' . Text::_('PLG_BEHAVIOUR_COMPAT') . '\' plugin is enabled.'); - $return = false; + $plugin = ExtensionHelper::getExtensionRecord('compat' . Version::MAJOR_VERSION, 'plugin', 0, 'behaviour'); + + if ($plugin) { + $language->load($plugin->name . '.sys', JPATH_ADMINISTRATOR); + + if (PluginHelper::isEnabled($plugin->folder, $plugin->element)) { + $this->ioStyle->error('The \'' . Text::_($plugin->name) . '\' plugin is enabled.'); + $return = false; + } } - if (!PluginHelper::isEnabled('behaviour', 'compat6')) { - $this->ioStyle->error('The \'' . Text::_('PLG_BEHAVIOUR_COMPAT6') . '\' plugin is disabled.'); - $return = false; + $plugin = ExtensionHelper::getExtensionRecord('compat' . (Version::MAJOR_VERSION + 1), 'plugin', 0, 'behaviour'); + + if ($plugin) { + $language->load($plugin->name . '.sys', JPATH_ADMINISTRATOR); + + if (!PluginHelper::isEnabled($plugin->folder, $plugin->element)) { + $this->ioStyle->error('The \'' . Text::_($plugin->name) . '\' plugin is disabled.'); + $return = false; + } } return $return; diff --git a/libraries/src/Crypt/Cipher/CryptoCipher.php b/libraries/src/Crypt/Cipher/CryptoCipher.php index 8a353f9bf3493..769141c5942dc 100644 --- a/libraries/src/Crypt/Cipher/CryptoCipher.php +++ b/libraries/src/Crypt/Cipher/CryptoCipher.php @@ -9,8 +9,7 @@ namespace Joomla\CMS\Crypt\Cipher; -use Joomla\Crypt\CipherInterface; -use Joomla\Crypt\Key; +use Joomla\Crypt\Cipher\Crypto; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -21,111 +20,9 @@ * * @since 3.5 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement use SodiumCipher instead */ -class CryptoCipher implements CipherInterface +class CryptoCipher extends Crypto { - /** - * Method to decrypt a data string. - * - * @param string $data The encrypted string to decrypt. - * @param Key $key The key object to use for decryption. - * - * @return string The decrypted data string. - * - * @since 3.5 - * @throws \RuntimeException - */ - public function decrypt($data, Key $key) - { - // Validate key. - if ($key->getType() !== 'crypto') { - throw new \InvalidArgumentException('Invalid key of type: ' . $key->getType() . '. Expected crypto.'); - } - - // Decrypt the data. - try { - return \Crypto::Decrypt($data, $key->getPublic()); - } catch (\InvalidCiphertextException $ex) { - throw new \RuntimeException('DANGER! DANGER! The ciphertext has been tampered with!', $ex->getCode(), $ex); - } catch (\CryptoTestFailedException $ex) { - throw new \RuntimeException('Cannot safely perform decryption', $ex->getCode(), $ex); - } catch (\CannotPerformOperationException $ex) { - throw new \RuntimeException('Cannot safely perform decryption', $ex->getCode(), $ex); - } - } - - /** - * Method to encrypt a data string. - * - * @param string $data The data string to encrypt. - * @param Key $key The key object to use for encryption. - * - * @return string The encrypted data string. - * - * @since 3.5 - * @throws \RuntimeException - */ - public function encrypt($data, Key $key) - { - // Validate key. - if ($key->getType() !== 'crypto') { - throw new \InvalidArgumentException('Invalid key of type: ' . $key->getType() . '. Expected crypto.'); - } - - // Encrypt the data. - try { - return \Crypto::Encrypt($data, $key->getPublic()); - } catch (\CryptoTestFailedException $ex) { - throw new \RuntimeException('Cannot safely perform encryption', $ex->getCode(), $ex); - } catch (\CannotPerformOperationException $ex) { - throw new \RuntimeException('Cannot safely perform encryption', $ex->getCode(), $ex); - } - } - - /** - * Method to generate a new encryption key object. - * - * @param array $options Key generation options. - * - * @return Key - * - * @since 3.5 - * @throws \RuntimeException - */ - public function generateKey(array $options = []) - { - // Generate the encryption key. - try { - $public = \Crypto::CreateNewRandomKey(); - } catch (\CryptoTestFailedException $ex) { - throw new \RuntimeException('Cannot safely create a key', $ex->getCode(), $ex); - } catch (\CannotPerformOperationException $ex) { - throw new \RuntimeException('Cannot safely create a key', $ex->getCode(), $ex); - } - - // Explicitly flag the private as unused in this cipher. - $private = 'unused'; - - return new Key('crypto', $private, $public); - } - - /** - * Check if the cipher is supported in this environment. - * - * @return boolean - * - * @since 4.0.0 - */ - public static function isSupported(): bool - { - try { - \Crypto::RuntimeTest(); - - return true; - } catch (\CryptoTestFailedException) { - return false; - } - } } diff --git a/libraries/src/Crypt/Cipher/SodiumCipher.php b/libraries/src/Crypt/Cipher/SodiumCipher.php index 8cf156aedb7ed..8f7aaeaa47540 100644 --- a/libraries/src/Crypt/Cipher/SodiumCipher.php +++ b/libraries/src/Crypt/Cipher/SodiumCipher.php @@ -9,9 +9,7 @@ namespace Joomla\CMS\Crypt\Cipher; -use Joomla\Crypt\CipherInterface; -use Joomla\Crypt\Key; -use ParagonIE\Sodium\Compat; +use Joomla\Crypt\Cipher\Sodium; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -21,122 +19,9 @@ * JCrypt cipher for sodium algorithm encryption, decryption and key generation. * * @since 3.8.0 + * @deprecated 6.2.0 will be removed in 8.0 + * Please use \Joomla\Crypt\Cipher\Sodium instead */ -class SodiumCipher implements CipherInterface +class SodiumCipher extends Sodium { - /** - * The message nonce to be used with encryption/decryption - * - * @var string - * @since 3.8.0 - */ - private $nonce; - - /** - * Method to decrypt a data string. - * - * @param string $data The encrypted string to decrypt. - * @param Key $key The key object to use for decryption. - * - * @return string The decrypted data string. - * - * @since 3.8.0 - * @throws \RuntimeException - */ - public function decrypt($data, Key $key) - { - // Validate key. - if ($key->getType() !== 'sodium') { - throw new \InvalidArgumentException('Invalid key of type: ' . $key->getType() . '. Expected sodium.'); - } - - if (!$this->nonce) { - throw new \RuntimeException('Missing nonce to decrypt data'); - } - - $decrypted = Compat::crypto_box_open( - $data, - $this->nonce, - Compat::crypto_box_keypair_from_secretkey_and_publickey($key->getPrivate(), $key->getPublic()) - ); - - if ($decrypted === false) { - throw new \RuntimeException('Malformed message or invalid MAC'); - } - - return $decrypted; - } - - /** - * Method to encrypt a data string. - * - * @param string $data The data string to encrypt. - * @param Key $key The key object to use for encryption. - * - * @return string The encrypted data string. - * - * @since 3.8.0 - * @throws \RuntimeException - */ - public function encrypt($data, Key $key) - { - // Validate key. - if ($key->getType() !== 'sodium') { - throw new \InvalidArgumentException('Invalid key of type: ' . $key->getType() . '. Expected sodium.'); - } - - if (!$this->nonce) { - throw new \RuntimeException('Missing nonce to decrypt data'); - } - - return Compat::crypto_box( - $data, - $this->nonce, - Compat::crypto_box_keypair_from_secretkey_and_publickey($key->getPrivate(), $key->getPublic()) - ); - } - - /** - * Method to generate a new encryption key object. - * - * @param array $options Key generation options. - * - * @return Key - * - * @since 3.8.0 - * @throws \RuntimeException - */ - public function generateKey(array $options = []) - { - // Generate the encryption key. - $pair = Compat::crypto_box_keypair(); - - return new Key('sodium', Compat::crypto_box_secretkey($pair), Compat::crypto_box_publickey($pair)); - } - - /** - * Check if the cipher is supported in this environment. - * - * @return boolean - * - * @since 4.0.0 - */ - public static function isSupported(): bool - { - return class_exists(Compat::class); - } - - /** - * Set the nonce to use for encrypting/decrypting messages - * - * @param string $nonce The message nonce - * - * @return void - * - * @since 3.8.0 - */ - public function setNonce($nonce) - { - $this->nonce = $nonce; - } } diff --git a/libraries/src/Crypt/Crypt.php b/libraries/src/Crypt/Crypt.php index 2b134dee8addc..2bc032fba4954 100644 --- a/libraries/src/Crypt/Crypt.php +++ b/libraries/src/Crypt/Crypt.php @@ -19,6 +19,8 @@ * Crypt is a Joomla Platform class for handling basic encryption/decryption of data. * * @since 3.0.0 + * @deprecated 6.2.0 will be removed in 8.0 + * Please use \Joomla\Crypt\Crypt instead */ class Crypt extends JCrypt { @@ -35,6 +37,8 @@ class Crypt extends JCrypt * @return boolean True if the two strings are exactly the same. * * @since 3.2 + * @deprecated 6.2.0 will be removed in 8.0 + * Please use hash_equals() instead */ public static function timingSafeCompare($known, $unknown) { @@ -80,9 +84,11 @@ public static function timingSafeCompare($known, $unknown) * * @return integer * - * @since 3.5 - * @ref mbstring.func_overload * @throws \RuntimeException + * @deprecated 6.2.0 will be removed in 8.0 + * Please use mb_strlen() instead + * @ref mbstring.func_overload + * @since 3.5 */ public static function safeStrlen($str) { @@ -118,6 +124,8 @@ public static function safeStrlen($str) * @return string * * @since 3.5 + * @deprecated 6.2.0 will be removed in 8.0 + * Please use mb_substr() instead */ public static function safeSubstr($str, $start, $length = null) { diff --git a/libraries/src/Date/Date.php b/libraries/src/Date/Date.php index 0315aa6cfdd4e..a70af5bc4fc99 100644 --- a/libraries/src/Date/Date.php +++ b/libraries/src/Date/Date.php @@ -12,6 +12,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -56,29 +57,6 @@ class Date extends \DateTime */ public static $format = 'Y-m-d H:i:s'; - /** - * Placeholder for a \DateTimeZone object with GMT as the time zone. - * - * @var object - * @since 1.7.0 - * - * @deprecated 4.0 will be removed in 6.0 - * Will be removed without replacement - */ - protected static $gmt; - - /** - * Placeholder for a \DateTimeZone object with the default server - * time zone as the time zone. - * - * @var object - * @since 1.7.0 - * - * @deprecated 4.0 will be removed in 6.0 - * Will be removed without replacement - */ - protected static $stz; - /** * The \DateTimeZone object for usage in rending dates as strings. * @@ -97,13 +75,6 @@ class Date extends \DateTime */ public function __construct($date = 'now', $tz = null) { - // Create the base GMT and server time zone objects. - if (empty(self::$gmt) || empty(self::$stz)) { - // @TODO: This code block stays here only for B/C, can be removed in 5.0 - self::$gmt = new \DateTimeZone('GMT'); - self::$stz = new \DateTimeZone(@date_default_timezone_get()); - } - // If the time zone object is not set, attempt to build it. if (!($tz instanceof \DateTimeZone)) { if (\is_string($tz)) { @@ -439,7 +410,7 @@ public function toISO8601($local = false) public function toSql($local = false, ?DatabaseDriver $db = null) { if ($db === null) { - $db = Factory::getDbo(); + $db = Factory::getContainer()->get(DatabaseInterface::class); } return $this->format($db->getDateFormat(), $local, false); diff --git a/libraries/src/Document/Document.php b/libraries/src/Document/Document.php index b2090cff6577d..099e0c0fcdef3 100644 --- a/libraries/src/Document/Document.php +++ b/libraries/src/Document/Document.php @@ -342,7 +342,7 @@ public function __construct($options = []) * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the \Joomla\CMS\Document\FactoryInterface instead * Example: Factory::getApplication()->getDocument(); */ @@ -980,7 +980,7 @@ public function setModifiedDate($date) \sprintf( 'The $date parameter of %1$s must be a string or a %2$s instance, a %3$s was given.', __METHOD__ . '()', - 'Joomla\\CMS\\Date\\Date', + Date::class, \is_object($date) ? (\get_class($date) . ' instance') : \gettype($date) ) ); diff --git a/libraries/src/Document/HtmlDocument.php b/libraries/src/Document/HtmlDocument.php index ed018d81a18bc..f489245e807d3 100644 --- a/libraries/src/Document/HtmlDocument.php +++ b/libraries/src/Document/HtmlDocument.php @@ -171,7 +171,7 @@ public function getHeadData() $data['custom'] = $this->_custom; /** - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * This property is for backwards compatibility. Pass text through script options in the future */ $data['scriptText'] = Text::getScriptStrings(); @@ -699,7 +699,7 @@ public function countModules(string $positionName, bool $withContentOnly = false * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 + * @deprecated 4.4 will be removed in 7.0 * Load the active menu item directly and count the children with the php count function * `$children = count($app->getMenu()->getActive()->getChildren())` beware getActive could be `null` */ @@ -773,11 +773,14 @@ protected function _fetchTemplate($params = []) // Load the language file for the template $lang = CmsFactory::getLanguage(); + if ($inherits) { + $lang->load('tpl_' . $inherits, $directory . '/' . $inherits) + || $lang->load('tpl_' . $inherits, JPATH_BASE); + } + // 1.5 or core then 1.6 $lang->load('tpl_' . $template, JPATH_BASE) - || ($inherits !== '' && $lang->load('tpl_' . $inherits, JPATH_BASE)) - || $lang->load('tpl_' . $template, $directory . '/' . $template) - || ($inherits !== '' && $lang->load('tpl_' . $inherits, $directory . '/' . $inherits)); + || $lang->load('tpl_' . $template, $directory . '/' . $template); // Assign the variables $this->baseurl = Uri::base(true); @@ -853,28 +856,28 @@ protected function _parseTemplate() { $matches = []; - if (preg_match_all('##iU', $this->_template, $matches)) { + if (preg_match_all('##iU', $this->_template, $matches, PREG_SET_ORDER)) { $messages = []; $template_tags_first = []; $template_tags_last = []; - // Step through the jdocs in reverse order. - for ($i = \count($matches[0]) - 1; $i >= 0; $i--) { - $type = $matches[1][$i]; - $attribs = empty($matches[2][$i]) ? [] : Utility::parseAttributes($matches[2][$i]); + foreach ($matches as $match) { + $type = $match[1]; + $attribs = empty($match[2]) ? [] : Utility::parseAttributes($match[2]); $name = $attribs['name'] ?? null; // Separate buffers to be executed first and last if ($type === 'module' || $type === 'modules') { - $template_tags_first[$matches[0][$i]] = ['type' => $type, 'name' => $name, 'attribs' => $attribs]; + $template_tags_first[$match[0]] = ['type' => $type, 'name' => $name, 'attribs' => $attribs]; } elseif ($type === 'message') { - $messages = [$matches[0][$i] => ['type' => $type, 'name' => $name, 'attribs' => $attribs]]; + $messages = [$match[0] => ['type' => $type, 'name' => $name, 'attribs' => $attribs]]; } else { - $template_tags_last[$matches[0][$i]] = ['type' => $type, 'name' => $name, 'attribs' => $attribs]; + $template_tags_last[$match[0]] = ['type' => $type, 'name' => $name, 'attribs' => $attribs]; } } - $this->_template_tags = $template_tags_first + $messages + array_reverse($template_tags_last); + + $this->_template_tags = $template_tags_first + $messages + $template_tags_last; } return $this; diff --git a/libraries/src/Document/Renderer/Html/ScriptsRenderer.php b/libraries/src/Document/Renderer/Html/ScriptsRenderer.php index b1819c578dec8..78f2f36f6f764 100644 --- a/libraries/src/Document/Renderer/Html/ScriptsRenderer.php +++ b/libraries/src/Document/Renderer/Html/ScriptsRenderer.php @@ -186,7 +186,11 @@ private function renderElement($item): string // Check if script uses media version. if ($version && !str_contains($src, '?') && ($mediaVersion || $version !== 'auto')) { - $src .= '?' . ($version === 'auto' ? $mediaVersion : $version); + $src .= '?' . match ($version) { + 'auto' => $mediaVersion, + 'nocache' => 'nocache-' . rand(0, 1_000_000), + default => $version, + }; } $buffer .= $tab; @@ -358,7 +362,11 @@ private function renderImportmap(array &$assets) // Check if script uses media version. if ($version && !str_contains($src, '?') && !str_ends_with($src, '/') && ($mediaVersion || $version !== 'auto')) { - $src .= '?' . ($version === 'auto' ? $mediaVersion : $version); + $src .= '?' . match ($version) { + 'auto' => $mediaVersion, + 'nocache' => 'nocache-' . rand(0, 1_000_000), + default => $version, + }; } if (!$esmScope) { diff --git a/libraries/src/Document/Renderer/Html/StylesRenderer.php b/libraries/src/Document/Renderer/Html/StylesRenderer.php index 45a6aa39a7a4d..b6ddbcae15ecf 100644 --- a/libraries/src/Document/Renderer/Html/StylesRenderer.php +++ b/libraries/src/Document/Renderer/Html/StylesRenderer.php @@ -175,7 +175,11 @@ private function renderElement($item): string // Check if script uses media version. if ($version && !str_contains($src, '?') && ($mediaVersion || $version !== 'auto')) { - $src .= '?' . ($version === 'auto' ? $mediaVersion : $version); + $src .= '?' . match ($version) { + 'auto' => $mediaVersion, + 'nocache' => 'nocache-' . rand(0, 1_000_000), + default => $version, + }; } $buffer .= $tab; diff --git a/libraries/src/Encrypt/AES/Mcrypt.php b/libraries/src/Encrypt/AES/Mcrypt.php index 207b70e46b375..663ab58606ff6 100644 --- a/libraries/src/Encrypt/AES/Mcrypt.php +++ b/libraries/src/Encrypt/AES/Mcrypt.php @@ -20,7 +20,7 @@ * * @since 4.0.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement */ class Mcrypt extends AbstractAES implements AesInterface diff --git a/libraries/src/Encrypt/Aes.php b/libraries/src/Encrypt/Aes.php index e6525abea0a8b..e307662bf8771 100644 --- a/libraries/src/Encrypt/Aes.php +++ b/libraries/src/Encrypt/Aes.php @@ -51,7 +51,7 @@ class Aes * @param string $mode Encryption mode. Can be ecb or cbc. We recommend using cbc. * @param string $priority Priority which adapter we should try first * - * @deprecated 4.3 $strength will be removed in 6.0 + * @deprecated 4.3 $strength will be removed in 7.0 */ public function __construct($key, $strength = 128, $mode = 'cbc', $priority = 'openssl') { diff --git a/libraries/src/Event/AbstractImmutableEvent.php b/libraries/src/Event/AbstractImmutableEvent.php index 2c521d8bf8d27..d64668f9259a9 100644 --- a/libraries/src/Event/AbstractImmutableEvent.php +++ b/libraries/src/Event/AbstractImmutableEvent.php @@ -62,7 +62,7 @@ public function __construct(string $name, array $arguments = []) * @since 4.0.0 * @throws \BadMethodCallException */ - public function offsetSet($name, $value) + public function offsetSet($name, $value): void { // B/C check for plugins which use $event['result'] = $result; if ($name === 'result') { @@ -95,7 +95,7 @@ public function offsetSet($name, $value) * @since 4.0.0 * @throws \BadMethodCallException */ - public function offsetUnset($name) + public function offsetUnset($name): void { throw new \BadMethodCallException( \sprintf( diff --git a/libraries/src/Event/CoreEventAware.php b/libraries/src/Event/CoreEventAware.php index 42ec3f37c6c75..bcee9232b9c27 100644 --- a/libraries/src/Event/CoreEventAware.php +++ b/libraries/src/Event/CoreEventAware.php @@ -154,6 +154,7 @@ trait CoreEventAware 'onExtensionAfterUpdate' => Extension\AfterUpdateEvent::class, 'onExtensionBeforeSave' => Model\BeforeSaveEvent::class, 'onExtensionAfterSave' => Model\AfterSaveEvent::class, + 'onExtensionBeforeDelete' => Model\BeforeDeleteEvent::class, 'onExtensionAfterDelete' => Model\AfterDeleteEvent::class, 'onExtensionChangeState' => Model\BeforeChangeStateEvent::class, 'onJoomlaBeforeAutoupdate' => Extension\BeforeJoomlaAutoupdateEvent::class, diff --git a/libraries/src/Extension/ExtensionHelper.php b/libraries/src/Extension/ExtensionHelper.php index 6182bf8008d5c..9d52b7dc900be 100644 --- a/libraries/src/Extension/ExtensionHelper.php +++ b/libraries/src/Extension/ExtensionHelper.php @@ -173,11 +173,13 @@ class ExtensionHelper ['plugin', 'ldap', 'authentication', 0], // Core plugin extensions - behaviour - ['plugin', 'compat', 'behaviour', 0], ['plugin', 'compat6', 'behaviour', 0], ['plugin', 'taggable', 'behaviour', 0], ['plugin', 'versionable', 'behaviour', 0], + // Core plugin extensions - captcha + ['plugin', 'powcaptcha', 'captcha', 0], + // Core plugin extensions - content ['plugin', 'confirmconsent', 'content', 0], ['plugin', 'contact', 'content', 0], @@ -220,6 +222,8 @@ class ExtensionHelper ['plugin', 'integer', 'fields', 0], ['plugin', 'list', 'fields', 0], ['plugin', 'media', 'fields', 0], + ['plugin', 'note', 'fields', 0], + ['plugin', 'number', 'fields', 0], ['plugin', 'radio', 'fields', 0], ['plugin', 'sql', 'fields', 0], ['plugin', 'subform', 'fields', 0], @@ -365,6 +369,7 @@ class ExtensionHelper // Core template extensions - site ['template', 'cassiopeia', '', 0], + ['template', 'cassiopeia_extended', '', 0], ]; /** @@ -404,7 +409,7 @@ public static function getCoreExtensionIds() } $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')); @@ -480,7 +485,7 @@ public static function getExtensionRecord(string $element, string $type, ?int $c if (!\array_key_exists($key, self::$loadedExtensions)) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__extensions')) ->where( diff --git a/libraries/src/Extension/LegacyComponent.php b/libraries/src/Extension/LegacyComponent.php index 6374512b4f85f..dcb61435781a4 100644 --- a/libraries/src/Extension/LegacyComponent.php +++ b/libraries/src/Extension/LegacyComponent.php @@ -242,7 +242,7 @@ public function createRouter(CMSApplicationInterface $application, AbstractMenu if (class_exists($class)) { $reflection = new \ReflectionClass($class); - if (\in_array('Joomla\\CMS\\Component\\Router\\RouterInterface', $reflection->getInterfaceNames())) { + if (\in_array(RouterInterface::class, $reflection->getInterfaceNames())) { return new $class($application, $menu); } } diff --git a/libraries/src/Extension/Service/Provider/MVCFactory.php b/libraries/src/Extension/Service/Provider/MVCFactory.php index 171cb665c3790..7f5af202e8e41 100644 --- a/libraries/src/Extension/Service/Provider/MVCFactory.php +++ b/libraries/src/Extension/Service/Provider/MVCFactory.php @@ -9,16 +9,26 @@ namespace Joomla\CMS\Extension\Service\Provider; +use Joomla\CMS\Cache\CacheControllerFactoryAwareInterface; use Joomla\CMS\Cache\CacheControllerFactoryInterface; +use Joomla\CMS\Factory; +use Joomla\CMS\Form\FormFactoryAwareInterface; use Joomla\CMS\Form\FormFactoryInterface; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryInterface; +use Joomla\CMS\Mail\MailerFactoryAwareInterface; use Joomla\CMS\Mail\MailerFactoryInterface; use Joomla\CMS\MVC\Factory\ApiMVCFactory; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\Router\SiteRouter; +use Joomla\CMS\Router\SiteRouterAwareInterface; +use Joomla\CMS\User\UserFactoryAwareInterface; use Joomla\CMS\User\UserFactoryInterface; +use Joomla\Database\DatabaseAwareInterface; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherAwareInterface; use Joomla\Event\DispatcherInterface; // phpcs:disable PSR1.Files.SideEffects @@ -67,22 +77,85 @@ public function register(Container $container) $container->set( MVCFactoryInterface::class, function (Container $container) { - if (\Joomla\CMS\Factory::getApplication()->isClient('api')) { - $factory = new ApiMVCFactory($this->namespace); - } else { - $factory = new \Joomla\CMS\MVC\Factory\MVCFactory($this->namespace); - } - - $factory->setFormFactory($container->get(FormFactoryInterface::class)); - $factory->setDispatcher($container->get(DispatcherInterface::class)); - $factory->setDatabase($container->get(DatabaseInterface::class)); - $factory->setSiteRouter($container->get(SiteRouter::class)); - $factory->setCacheControllerFactory($container->get(CacheControllerFactoryInterface::class)); - $factory->setUserFactory($container->get(UserFactoryInterface::class)); - $factory->setMailerFactory($container->get(MailerFactoryInterface::class)); + $factory = $this->createMVCFactory(); + + $this->injectServicesIntoFactory($factory, $container); return $factory; } ); } + + /** + * Return component namespace + * + * @return string + * + * @since 6.2.0 + */ + protected function getNamespace(): string + { + return $this->namespace; + } + + /** + * Create MVC Factory + * + * @return MVCFactoryInterface + * + * @since 6.2.0 + */ + protected function createMVCFactory(): MVCFactoryInterface + { + if (Factory::getApplication()->isClient('api')) { + return new ApiMVCFactory($this->namespace); + } + + return new \Joomla\CMS\MVC\Factory\MVCFactory($this->namespace); + } + + /** + * Inject services from container into MVC Factory + * + * @param MVCFactoryInterface $factory The MVC Factory + * @param Container $container The DI container + * + * @return void + * + * @since 6.2.0 + */ + protected function injectServicesIntoFactory(MVCFactoryInterface $factory, Container $container): void + { + if ($factory instanceof FormFactoryAwareInterface) { + $factory->setFormFactory($container->get(FormFactoryInterface::class)); + } + + if ($factory instanceof DispatcherAwareInterface) { + $factory->setDispatcher($container->get(DispatcherInterface::class)); + } + + if ($factory instanceof DatabaseAwareInterface) { + $factory->setDatabase($container->get(DatabaseInterface::class)); + } + + if ($factory instanceof SiteRouterAwareInterface) { + $factory->setSiteRouter($container->get(SiteRouter::class)); + } + + if ($factory instanceof CacheControllerFactoryAwareInterface) { + $factory->setCacheControllerFactory($container->get(CacheControllerFactoryInterface::class)); + } + + if ($factory instanceof UserFactoryAwareInterface) { + $factory->setUserFactory($container->get(UserFactoryInterface::class)); + } + + if ($factory instanceof MailerFactoryAwareInterface) { + $factory->setMailerFactory($container->get(MailerFactoryInterface::class)); + } + + if ($factory instanceof LanguageFactoryAwareInterface) { + $factory->setLanguageFactory($container->get(LanguageFactoryInterface::class)); + } + } } diff --git a/libraries/src/Factory.php b/libraries/src/Factory.php index 76a6ff1fc1084..0480bb97193fc 100644 --- a/libraries/src/Factory.php +++ b/libraries/src/Factory.php @@ -61,7 +61,7 @@ abstract class Factory * @var \JConfig * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the configuration object within the application * Example: * Factory::getApplication()->getConfig(); @@ -90,7 +90,7 @@ abstract class Factory * @var Session * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the session service in the DI container or get from the application object * Example: * Factory::getApplication()->getSession(); @@ -103,7 +103,7 @@ abstract class Factory * @var Language * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the language service in the DI container or get from the application object * Example: * Factory::getApplication()->getLanguage(); @@ -116,7 +116,7 @@ abstract class Factory * @var Document * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the document service in the DI container or get from the application object * Example: * Factory::getApplication()->getDocument(); @@ -129,7 +129,7 @@ abstract class Factory * @var DatabaseDriver * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the database service in the DI container * Example: * Factory::getContainer()->get(DatabaseInterface::class); @@ -175,7 +175,7 @@ public static function getApplication() * @see Registry * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the configuration object within the application * Example: * Factory::getApplication()->getConfig(); @@ -256,7 +256,7 @@ public static function getContainer(): Container * @see Session * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the session service in the DI container or get from the application object * Example: * Factory::getApplication()->getSession(); @@ -285,7 +285,7 @@ public static function getSession(array $options = []) * @see Language * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the language service in the DI container or get from the application object * Example: * Factory::getApplication()->getLanguage(); @@ -318,7 +318,7 @@ public static function getLanguage() * @see Document * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the document service in the DI container or get from the application object * Example: * Factory::getApplication()->getDocument(); @@ -353,7 +353,7 @@ public static function getDocument() * @see User * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Load the user service from the dependency injection container or get from the application object * Example: * Factory::getApplication()->getIdentity(); @@ -397,7 +397,7 @@ public static function getUser($id = null) * @see Cache * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the cache controller factory instead * Example: * Factory::getContainer()->get(CacheControllerFactoryInterface::class)->createCacheController($handler, $options); @@ -443,7 +443,7 @@ public static function getCache($group = '', $handler = 'callback', $storage = n * @see DatabaseDriver * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the database service in the DI container * Example: * Factory::getContainer()->get(DatabaseInterface::class); @@ -479,7 +479,7 @@ public static function getDbo() * @see Mail * @since 1.7.0 * - * @deprecated 4.4.0 will be removed in 6.0 + * @deprecated 4.4.0 will be removed in 7.0 * Use the mailer service in the DI container and create a mailer from there * Example: * Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer(); @@ -523,11 +523,11 @@ public static function getDate($time = 'now', $tzOffset = null) if (!class_exists($classname)) { // The class does not exist, default to Date - $classname = 'Joomla\\CMS\\Date\\Date'; + $classname = Date::class; } } else { // No tag, so default to Date - $classname = 'Joomla\\CMS\\Date\\Date'; + $classname = Date::class; } } @@ -554,7 +554,7 @@ public static function getDate($time = 'now', $tzOffset = null) * @see Registry * @since 1.7.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use the configuration object within the application. * Example: Factory::getApplication()->getConfig(); */ @@ -638,7 +638,7 @@ protected static function createContainer(): Container * @see DatabaseDriver * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the database service in the DI container * Example: * Factory::getContainer()->get(DatabaseInterface::class); @@ -701,7 +701,7 @@ protected static function createDbo() * @see Mail * @since 1.7.0 * - * @deprecated 4.4.0 will be removed in 6.0 + * @deprecated 4.4.0 will be removed in 7.0 * Use the mailer service in the DI container and create a mailer from there * Example: * Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer(); @@ -724,7 +724,7 @@ protected static function createMailer() * @see Language * @since 1.7.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Load the language service from the dependency injection container or via $app->getLanguage() * Example: Factory::getContainer()->get(LanguageFactoryInterface::class)->createLanguage($locale, $debug) */ @@ -755,7 +755,7 @@ protected static function createLanguage() * @see Document * @since 1.7.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Load the document service from the dependency injection container or via $app->getDocument() * Example: Factory::getContainer()->get(FactoryInterface::class)->createDocument($type, $attributes); */ diff --git a/libraries/src/Feed/FeedFactory.php b/libraries/src/Feed/FeedFactory.php index 675d3e0bd466b..0e694775dc53a 100644 --- a/libraries/src/Feed/FeedFactory.php +++ b/libraries/src/Feed/FeedFactory.php @@ -9,7 +9,9 @@ namespace Joomla\CMS\Feed; -use Joomla\CMS\Http\HttpFactory; +use Joomla\CMS\Feed\Parser\AtomParser; +use Joomla\CMS\Feed\Parser\RssParser; +use Joomla\Http\HttpFactory; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects @@ -27,7 +29,10 @@ class FeedFactory * @var array The list of registered parser classes for feeds. * @since 3.1.4 */ - protected $parsers = ['rss' => 'Joomla\\CMS\\Feed\\Parser\\RssParser', 'feed' => 'Joomla\\CMS\\Feed\\Parser\\AtomParser']; + protected $parsers = [ + 'rss' => RssParser::class, + 'feed' => AtomParser::class, + ]; /** * Method to load a URI into the feed reader for parsing. @@ -54,7 +59,7 @@ public function getFeed($uri) $options->set('userAgent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0'); try { - $response = HttpFactory::getHttp($options)->get($uri); + $response = (new HttpFactory())->getHttp($options)->get($uri); } catch (\RuntimeException $e) { throw new \RuntimeException('Unable to open the feed.', $e->getCode(), $e); } diff --git a/libraries/src/Filter/InputFilter.php b/libraries/src/Filter/InputFilter.php index de1b5bd6427b3..fcdf648c472c5 100644 --- a/libraries/src/Filter/InputFilter.php +++ b/libraries/src/Filter/InputFilter.php @@ -34,8 +34,8 @@ class InputFilter extends BaseInputFilter * @since 4.0.0 */ public const FORBIDDEN_FILE_EXTENSIONS = [ - 'php', 'phps', 'pht', 'phtml', 'php3', 'php4', 'php5', 'php6', 'php7', 'asp', - 'php8', 'phar', 'inc', 'pl', 'cgi', 'fcgi', 'java', 'jar', 'py', 'aspx', + 'asp', 'php', 'phps', 'pht', 'phtml', 'php3', 'php4', 'php5', 'php6', 'php7', 'php8', 'phar', + 'inc', 'pl', 'cgi', 'fcgi', 'java', 'jar', 'py', 'aspx', 'shtml', 'shtm', 'sht', 'stm', ]; /** @@ -152,8 +152,11 @@ public function emailToPunycode($text) if (preg_match_all($pattern, $text, $matches)) { foreach ($matches[0] as $match) { - $match = (string) str_replace(['?', '"'], '', $match); - $text = (string) str_replace($match, PunycodeHelper::emailToPunycode($match), $text); + try { + $match = (string) str_replace(['?', '"'], '', $match); + $text = (string) str_replace($match, PunycodeHelper::emailToPunycode($match), $text); + } catch (\Exception) { + } } } @@ -498,7 +501,7 @@ protected function stripUSC($source) * * @return array Filtered array of attribute pairs * - * @since 5.4.2 + * @since 6.0.2 */ protected function cleanAttributes(array $attrSet) { diff --git a/libraries/src/Filter/OutputFilter.php b/libraries/src/Filter/OutputFilter.php index a15f5bb21d3a2..144453843476c 100644 --- a/libraries/src/Filter/OutputFilter.php +++ b/libraries/src/Filter/OutputFilter.php @@ -38,7 +38,7 @@ public static function linkXHTMLSafe($input) { $regex = 'href="([^"]*(&(amp;){0})[^"]*)*?"'; - return preg_replace_callback("#$regex#i", ['\\Joomla\\CMS\\Filter\\OutputFilter', 'ampReplaceCallback'], $input); + return preg_replace_callback("#$regex#i", [static::class, 'ampReplaceCallback'], $input); } /** diff --git a/libraries/src/Form/Field/AccessiblemediaField.php b/libraries/src/Form/Field/AccessiblemediaField.php index 2c379d6908e48..0bfdd5e6c3092 100644 --- a/libraries/src/Form/Field/AccessiblemediaField.php +++ b/libraries/src/Form/Field/AccessiblemediaField.php @@ -9,6 +9,8 @@ namespace Joomla\CMS\Form\Field; +use Joomla\CMS\Language\Text; + // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects @@ -68,6 +70,14 @@ class AccessiblemediaField extends SubformField */ protected $layout; + /** + * Media types like 'images, audios, documents, videos' + * + * @var string + * @since 6.1.0 + */ + protected $types; + /** * Method to get certain otherwise inaccessible properties from the form field object. * @@ -84,6 +94,7 @@ public function __get($name) case 'preview': case 'previewHeight': case 'previewWidth': + case 'types': return $this->$name; } @@ -105,6 +116,7 @@ public function __set($name, $value) switch ($name) { case 'directory': case 'preview': + case 'types': $this->$name = (string) $value; break; @@ -146,7 +158,7 @@ public function setup(\SimpleXMLElement $element, $value, $group = null) * most likely within a custom field of type subform * and the value is a stdClass with properties * imagefile and alt_text. So it is fine. - */ + */ if (\is_string($value)) { json_decode($value); @@ -156,30 +168,39 @@ public function setup(\SimpleXMLElement $element, $value, $group = null) * If the value is not empty and is not a valid JSON string, * it is most likely a custom field created in Joomla 3 and * the value is a string that contains the file name. - */ + */ if (is_file(JPATH_ROOT . '/' . $value)) { $value = '{"imagefile":"' . $value . '","alt_text":""}'; } else { $value = ''; } } - } elseif ( - !\is_object($value) - || !property_exists($value, 'imagefile') - || !property_exists($value, 'alt_text') - ) { + } elseif (!\is_object($value)) { return false; + } else { + $mediaTypes = explode(',', (string) ($element['types'] ?? 'images')); + $requiredProperties = \in_array('images', $mediaTypes, true) ? ['imagefile', 'alt_text'] : ['file']; + + foreach ($requiredProperties as $property) { + if (!property_exists($value, $property)) { + return false; + } + } } if (!parent::setup($element, $value, $group)) { return false; } - $this->directory = (string) $this->element['directory']; - $this->preview = (string) $this->element['preview']; - $this->previewHeight = isset($this->element['preview_height']) ? (int) $this->element['preview_height'] : 200; - $this->previewWidth = isset($this->element['preview_width']) ? (int) $this->element['preview_width'] : 200; + $this->directory = (string)$this->element['directory']; + $this->preview = (string)$this->element['preview']; + $this->previewHeight = isset($this->element['preview_height']) ? (int)$this->element['preview_height'] : 200; + $this->previewWidth = isset($this->element['preview_width']) ? (int)$this->element['preview_width'] : 200; + $this->types = isset($this->element['types']) ? (string)$this->element['types'] : 'images'; + $mediaTypes = explode(',', $this->types); + $fieldName = (\in_array('images', $mediaTypes)) ? 'imagefile' : 'file'; + // Build the form source $xml = <<
@@ -188,18 +209,21 @@ public function setup(\SimpleXMLElement $element, $value, $group = null) label="JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_LABEL" > - +XML; + if (\in_array('images', $mediaTypes)) { + $xml .= << +XML; + } + if (\in_array('videos', $mediaTypes) && $this->element['video_poster'] == 1) { + $xml .= << +XML; + } + if (\in_array('documents', $mediaTypes)) { + $xml .= << +XML; + } + $xml .= << XML; + $this->formsource = $xml; $this->layout = 'joomla.form.field.media.accessiblemedia'; return true; } + + /** + * Method to get the field input markup. + * + * @return string The field input markup. + * + * @since 6.1.0 + */ + protected function getInput() + { + $subForm = $this->loadSubForm(); + + $mediaTypes = explode(',', $this->types); + $label = ''; + if (\count($mediaTypes) > 1) { + $labels = []; + + foreach ($mediaTypes as $type) { + $const = 'JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_' . strtoupper($type); + $labels[] = Text::_($const); + } + + if (!empty($labels)) { + $label = Text::sprintf('JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_LABEL', implode(', ', $labels)); + } + } else { + $label = Text::_('JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_MEDIA_TYPE_' . strtoupper($mediaTypes[0])); + } + + $fieldName = (\in_array('images', $mediaTypes)) ? 'imagefile' : 'file'; + if (!empty($label) && $subForm->getField($fieldName)) { + $subForm->setFieldAttribute($fieldName, 'label', $label); + } + + if ($subForm && $subForm->getField('linktext')) { + $subForm->setFieldAttribute('linktext', 'default', Text::_('JLIB_FORM_FIELD_PARAM_ACCESSIBLEMEDIA_PARAMS_LINKTEXT_DEFAULT_VALUE')); + } + + $this->form = $subForm; + + return parent::getInput(); + } } diff --git a/libraries/src/Form/Field/AliastagField.php b/libraries/src/Form/Field/AliastagField.php index 33893f4d2909c..aacc6d885bfd1 100644 --- a/libraries/src/Form/Field/AliastagField.php +++ b/libraries/src/Form/Field/AliastagField.php @@ -43,7 +43,7 @@ protected function getOptions() { // Get list of tag type alias $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ 'DISTINCT ' . $db->quoteName('type_alias', 'value'), diff --git a/libraries/src/Form/Field/AuthorField.php b/libraries/src/Form/Field/AuthorField.php index 4a456e87bae0e..9eef053fdba28 100644 --- a/libraries/src/Form/Field/AuthorField.php +++ b/libraries/src/Form/Field/AuthorField.php @@ -54,7 +54,7 @@ protected function getOptions() $db = $this->getDatabase(); // Construct the query - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('u.id', 'value'), diff --git a/libraries/src/Form/Field/CalendarField.php b/libraries/src/Form/Field/CalendarField.php index 5d76831d0a67e..90751a58a84d8 100644 --- a/libraries/src/Form/Field/CalendarField.php +++ b/libraries/src/Form/Field/CalendarField.php @@ -192,6 +192,14 @@ public function __get($name) public function __set($name, $value) { switch ($name) { + case 'value': + if ($value instanceof \DateTimeInterface) { + $this->value = $value->format('Y-m-d H:i:s'); + } else { + $this->value = (string) $value; + } + break; + case 'maxlength': case 'maxyear': case 'minyear': diff --git a/libraries/src/Form/Field/ChromestyleField.php b/libraries/src/Form/Field/ChromestyleField.php index 0d446326f76c2..a932a46bb9e22 100644 --- a/libraries/src/Form/Field/ChromestyleField.php +++ b/libraries/src/Form/Field/ChromestyleField.php @@ -218,7 +218,7 @@ protected function getTemplates() $db = $this->getDatabase(); // Get the database object and a new query object. - $query = $db->getQuery(true); + $query = $db->createQuery(); // Build the query. $query->select( diff --git a/libraries/src/Form/Field/ComponentlayoutField.php b/libraries/src/Form/Field/ComponentlayoutField.php index 8e043cefabbb8..fb5ec948c485e 100644 --- a/libraries/src/Form/Field/ComponentlayoutField.php +++ b/libraries/src/Form/Field/ComponentlayoutField.php @@ -90,7 +90,7 @@ protected function getInput() // Get the database object and a new query object. $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Build the query. $query->select( diff --git a/libraries/src/Form/Field/ComponentsField.php b/libraries/src/Form/Field/ComponentsField.php index f1fea01e44a48..dea455d7cda22 100644 --- a/libraries/src/Form/Field/ComponentsField.php +++ b/libraries/src/Form/Field/ComponentsField.php @@ -42,7 +42,7 @@ class ComponentsField extends ListField protected function getOptions() { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('name', 'text'), diff --git a/libraries/src/Form/Field/ContenttypeField.php b/libraries/src/Form/Field/ContenttypeField.php index f12cbc8973acd..7abf9ee1837de 100644 --- a/libraries/src/Form/Field/ContenttypeField.php +++ b/libraries/src/Form/Field/ContenttypeField.php @@ -64,7 +64,7 @@ protected function getOptions() { $lang = Factory::getLanguage(); $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('a.type_id', 'value'), diff --git a/libraries/src/Form/Field/DateField.php b/libraries/src/Form/Field/DateField.php new file mode 100644 index 0000000000000..6b628630a8cac --- /dev/null +++ b/libraries/src/Form/Field/DateField.php @@ -0,0 +1,151 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Form\Field; + +use Joomla\CMS\Form\FormField; + +/** + * Date field + * + * @since 6.0.0 + */ +class DateField extends FormField +{ + /** + * The form field type. + * + * @var string + * + * @since 6.0.0 + */ + protected $type = 'Date'; + + /** + * Name of the layout being used to render the field + * + * @var string + * + * @since 6.0.0 + */ + protected $layout = 'joomla.form.field.date'; + + /** + * Min value Y-m-d + * + * @var string + * + * @since 6.0.0 + */ + protected $dateMin = ''; + + /** + * Max value Y-m-d + * + * @var string + * + * @since 6.0.0 + */ + protected $dateMax = ''; + + /** + * Method to attach a Form object to the field. + * + * @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. + * 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]". + * + * @return boolean True on success. + * + * @since 6.0.0 + */ + public function setup(\SimpleXMLElement $element, $value, $group = null) + { + if (!parent::setup($element, $value, $group)) { + return false; + } + + foreach (['min', 'max'] as $attr) { + $this->__set($attr, (string) $element[$attr]); + } + + return true; + } + + /** + * Method to get certain otherwise inaccessible properties from the form field object. + * + * @param string $name The property name for which to get the value. + * + * @return mixed The property value or null. + * + * @since 6.0.0 + */ + public function __get($name) + { + switch ($name) { + case 'min': + return $this->dateMin; + case 'max': + return $this->dateMax; + default: + return parent::__get($name); + } + } + + /** + * Method to set certain otherwise inaccessible properties of the form field object. + * + * @param string $name The property name for which to set the value. + * @param mixed $value The value of the property. + * + * @return void + * + * @since 6.0.0 + */ + public function __set($name, $value) + { + switch ($name) { + case 'value': + if ($value instanceof \DateTimeInterface) { + $this->value = $value->format('Y-m-d'); + } else { + $this->value = (string) $value; + } + break; + case 'min': + $this->dateMin = (string) $value; + break; + case 'max': + $this->dateMax = (string) $value; + break; + default: + parent::__set($name, $value); + } + } + + /** + * Method to get the data to be passed to the layout for rendering. + * + * @return array + * + * @since 6.0.0 + */ + protected function getLayoutData() + { + $data = parent::getLayoutData(); + + $data['min'] = $this->dateMin; + $data['max'] = $this->dateMax; + + return $data; + } +} diff --git a/libraries/src/Form/Field/DatetimeField.php b/libraries/src/Form/Field/DatetimeField.php new file mode 100644 index 0000000000000..6a15f8ec0528a --- /dev/null +++ b/libraries/src/Form/Field/DatetimeField.php @@ -0,0 +1,263 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Form\Field; + +use Joomla\CMS\Factory; +use Joomla\CMS\Form\FormField; +use Joomla\Registry\Registry; + +/** + * DateTime field + * + * @since 6.0.0 + */ +class DatetimeField extends FormField +{ + /** + * The form field type. + * + * @var string + * + * @since 6.0.0 + */ + protected $type = 'DateTime'; + + /** + * Name of the layout being used to render the field + * + * @var string + * + * @since 6.0.0 + */ + protected $layout = 'joomla.form.field.datetime'; + + /** + * Min value Y-m-dTH:i + * + * @var string + * + * @since 6.0.0 + */ + protected $dateMin = ''; + + /** + * Max value Y-m-dTH:i + * + * @var string + * + * @since 6.0.0 + */ + protected $dateMax = ''; + + /** + * The filter. + * + * @var string + * + * @since 6.0.0 + */ + protected $filter = ''; + + /** + * Method to attach a Form object to the field. + * + * @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. + * 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]". + * + * @return boolean True on success. + * + * @since 6.0.0 + */ + public function setup(\SimpleXMLElement $element, $value, $group = null) + { + if (!parent::setup($element, $value, $group)) { + return false; + } + + foreach (['min', 'max', 'filter'] as $attr) { + $this->__set($attr, (string) $element[$attr]); + } + + return true; + } + + /** + * Method to get certain otherwise inaccessible properties from the form field object. + * + * @param string $name The property name for which to get the value. + * + * @return mixed The property value or null. + * + * @since 6.0.0 + */ + public function __get($name) + { + switch ($name) { + case 'min': + return $this->dateMin; + + case 'max': + return $this->dateMax; + + case 'filter': + return $this->filter; + + default: + return parent::__get($name); + } + } + + /** + * Method to set certain otherwise inaccessible properties of the form field object. + * + * @param string $name The property name for which to set the value. + * @param mixed $value The value of the property. + * + * @return void + * + * @since 6.0.0 + */ + public function __set($name, $value) + { + switch ($name) { + case 'value': + if ($value instanceof \DateTimeInterface) { + $this->value = $value->format('Y-m-d H:i:s'); + } else { + $this->value = (string) $value; + } + break; + + case 'min': + $this->dateMin = (string) $value; + break; + + case 'max': + $this->dateMax = (string) $value; + break; + + case 'filter': + $this->filter = (string) $value; + break; + + default: + parent::__set($name, $value); + } + } + + /** + * Method to get the data to be passed to the layout for rendering. + * + * @return array + * + * @since 6.0.0 + */ + protected function getLayoutData() + { + $data = parent::getLayoutData(); + + $data['min'] = $this->dateMin; + $data['max'] = $this->dateMax; + $data['filter'] = $this->filter; + + return $data; + } + + /** + * Method to get the field input markup. + * + * @return string The field input markup. + * + * @since 6.0.0 + */ + protected function getInput() + { + $data = $this->collectLayoutData(); + + if ($this->value) { + $app = Factory::getApplication(); + $value = Factory::getDate($this->value, 'UTC'); + + switch (strtoupper($this->filter)) { + case 'SERVER_UTC': + // Convert a date to UTC based on the server timezone. + $value->setTimezone(new \DateTimeZone($app->get('offset'))); + + // Transform the date string. + $data['value'] = $value->format('Y-m-d\TH:i', true, false); + break; + + case 'USER_UTC': + // Convert a date to UTC based on the user timezone. + $value->setTimezone(new \DateTimeZone($app->getIdentity()->getParam('timezone', $app->get('offset')))); + + // Transform the date string. + $data['value'] = $value->format('Y-m-d\TH:i', true, false); + break; + + default: + $data['value'] = $value->format('Y-m-d\TH:i', false, false); + } + } + + return $this->getRenderer($this->layout)->render($data); + } + + /** + * Method to filter a field value. + * + * @param mixed $value The optional value to use as the default for the field. + * @param string $group The optional dot-separated form group path on which to find the field. + * @param ?Registry $input An optional Registry object with the entire data set to filter + * against the entire form. + * + * @return mixed The filtered value. + * + * @since 6.0.0 + */ + public function filter($value, $group = null, ?Registry $input = null) + { + // Make sure there is a valid SimpleXMLElement. + if (!($this->element instanceof \SimpleXMLElement)) { + throw new \UnexpectedValueException(\sprintf('%s `element` is not an instance of SimpleXMLElement', __METHOD__)); + } + + if (!$value) { + return ''; + } + + $app = Factory::getApplication(); + + switch (strtoupper($this->filter)) { + // Convert a date to UTC based on the server timezone offset. + case 'SERVER_UTC': + // Return an SQL formatted datetime string in UTC. + $return = Factory::getDate($value, $app->get('offset'))->toSql(); + break; + + // Convert a date to UTC based on the user timezone offset. + case 'USER_UTC': + // Get the user timezone setting defaulting to the server timezone setting. + $offset = $app->getIdentity()->getParam('timezone', $app->get('offset')); + + // Return an SQL formatted datetime string in UTC. + $return = Factory::getDate($value, $offset)->toSql(); + break; + + default: + $return = parent::filter($value, $group, $input); + } + + return $return; + } +} diff --git a/libraries/src/Form/Field/EditorField.php b/libraries/src/Form/Field/EditorField.php index 647ad1de252a5..2c298cc5bf5d4 100644 --- a/libraries/src/Form/Field/EditorField.php +++ b/libraries/src/Form/Field/EditorField.php @@ -205,8 +205,8 @@ public function setup(\SimpleXMLElement $element, $value, $group = null) $result = parent::setup($element, $value, $group); if ($result === true) { - $this->height = $this->element['height'] ? (string) $this->element['height'] : '500'; - $this->width = $this->element['width'] ? (string) $this->element['width'] : '100%'; + $this->height = $this->element['height'] ? (string) $this->element['height'] : ''; + $this->width = $this->element['width'] ? (string) $this->element['width'] : ''; $this->assetField = $this->element['asset_field'] ? (string) $this->element['asset_field'] : 'asset_id'; $this->authorField = $this->element['created_by_field'] ? (string) $this->element['created_by_field'] : 'created_by'; $this->asset = $this->form->getValue($this->assetField) ?: (string) $this->element['asset_id']; @@ -283,7 +283,7 @@ protected function getEditor() $db = $this->getDatabase(); // Build the query. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('element')) ->from($db->quoteName('#__extensions')) ->where( diff --git a/libraries/src/Form/Field/EnumField.php b/libraries/src/Form/Field/EnumField.php new file mode 100644 index 0000000000000..65648a525fa91 --- /dev/null +++ b/libraries/src/Form/Field/EnumField.php @@ -0,0 +1,72 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Form\Field; + +// No direct access +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +use Joomla\CMS\Language\Text; + +/** + * Renders a '; } @@ -111,17 +111,12 @@ public static function checkall($name = 'checkall-toggle', $action = 'Joomla.che */ public static function id($rowNum, $recId, $checkedOut = false, $name = 'cid', $stub = 'cb', $title = '', $formId = null) { - if ($formId !== null) { - return $checkedOut ? '' : '' - . ''; - } + Factory::getApplication()->getDocument()->getWebAssetManager()->useScript('list-view'); return $checkedOut ? '' : '' - . ''; + . ''; } /** diff --git a/libraries/src/HTML/Helpers/Jquery.php b/libraries/src/HTML/Helpers/Jquery.php index 73e5abd1d7a05..673bfb01a4e0c 100644 --- a/libraries/src/HTML/Helpers/Jquery.php +++ b/libraries/src/HTML/Helpers/Jquery.php @@ -44,7 +44,7 @@ abstract class Jquery * * @since 3.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use webasset manager instead * Example: * $wa = Factory::getApplication()->getDocument()->getWebAssetManager(); diff --git a/libraries/src/HTML/Helpers/ListHelper.php b/libraries/src/HTML/Helpers/ListHelper.php index 21940aa4c1eda..c6eaed0aeb54b 100644 --- a/libraries/src/HTML/Helpers/ListHelper.php +++ b/libraries/src/HTML/Helpers/ListHelper.php @@ -179,7 +179,7 @@ public static function ordering($name, $query, $attribs = null, $selected = null public static function users($name, $active, $nouser = 0, $javascript = null, $order = 'name') { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('u.id', 'value'), diff --git a/libraries/src/HTML/Helpers/Menu.php b/libraries/src/HTML/Helpers/Menu.php index a4885061ac346..38a109996c46d 100644 --- a/libraries/src/HTML/Helpers/Menu.php +++ b/libraries/src/HTML/Helpers/Menu.php @@ -57,7 +57,7 @@ public static function menus($clientId = 0) if (!isset(static::$menus[$key])) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('id'), @@ -70,7 +70,7 @@ public static function menus($clientId = 0) ->order( [ $db->quoteName('client_id'), - $db->quoteName('title'), + $db->quoteName('ordering'), ] ); @@ -105,7 +105,7 @@ public static function menuItems($config = []) $menus = static::menus($clientId); $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('a.id', 'value'), @@ -245,7 +245,7 @@ public static function ordering(&$row, $id) { if ($id) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('ordering', 'value'), @@ -293,7 +293,7 @@ public static function linkOptions($all = false, $unassigned = false, $clientId $db = Factory::getDbo(); // Get a list of the menu items - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('m.id'), diff --git a/libraries/src/HTML/Helpers/Select.php b/libraries/src/HTML/Helpers/Select.php index 89a7ce33963c2..b1a956af258fa 100644 --- a/libraries/src/HTML/Helpers/Select.php +++ b/libraries/src/HTML/Helpers/Select.php @@ -145,7 +145,7 @@ public static function genericlist( ->registerAndUseScript( 'webcomponent.select-colour', 'system/fields/select-colour.min.js', - ['dependencies' => ['wcpolyfill']], + ['dependencies' => ['core']], ['type' => 'module'] ); } @@ -193,7 +193,7 @@ public static function groupedlist($data, $name, $options = []) // Set default options and overwrite with anything passed in $options = array_merge( HTMLHelper::$formatOptions, - ['format.depth' => 0, 'group.items' => 'items', 'group.label' => 'text', 'group.label.toHtml' => true, 'id' => false], + ['format.depth' => 0, 'group.items' => 'items', 'group.label' => 'text', 'group.attr' => 'attr', 'group.class' => 'class', 'group.label.toHtml' => true, 'id' => false], $options ); @@ -228,9 +228,11 @@ public static function groupedlist($data, $name, $options = []) $groupIndent = str_repeat($options['format.indent'], $options['format.depth']++); foreach ($data as $dataKey => $group) { - $label = $dataKey; - $id = ''; - $noGroup = \is_int($dataKey); + $label = $dataKey; + $id = ''; + $groupClass = ''; + $groupAttribs = ''; + $noGroup = \is_int($dataKey); if ($options['group.items'] == null) { // Sub-list is an associative array @@ -248,6 +250,16 @@ public static function groupedlist($data, $name, $options = []) $id = $group[$options['group.id']]; $noGroup = false; } + + if (isset($options['group.class'], $group[$options['group.class']])) { + $groupClass = $group[$options['group.class']]; + $noGroup = false; + } + + if (isset($options['group.attr'], $group[$options['group.attr']])) { + $groupAttribs = $group[$options['group.attr']]; + $noGroup = false; + } } elseif (\is_object($group)) { // Sub-list is in a property of an object $subList = $group->{$options['group.items']}; @@ -261,6 +273,16 @@ public static function groupedlist($data, $name, $options = []) $id = $group->{$options['group.id']}; $noGroup = false; } + + if (isset($options['group.class'], $group->{$options['group.class']})) { + $groupClass = $group->{$options['group.class']}; + $noGroup = false; + } + + if (isset($options['group.attr'], $group->{$options['group.attr']})) { + $groupAttribs = $group->{$options['group.attr']}; + $noGroup = false; + } } else { throw new \RuntimeException('Invalid group contents.', 1); } @@ -268,9 +290,22 @@ public static function groupedlist($data, $name, $options = []) if ($noGroup) { $html .= static::options($subList, $options); } else { - $html .= $groupIndent . '' . $options['format.eol'] - . static::options($subList, $options) . $groupIndent . '' . $options['format.eol']; + if (\is_array($groupAttribs)) { + $groupAttribs = ArrayHelper::toString($groupAttribs); + } + + $html .= $groupIndent + . '' + . $options['format.eol'] + . static::options($subList, $options) + . $groupIndent + . '' + . $options['format.eol']; } } @@ -547,9 +582,19 @@ public static function options($arr, $optKey = 'value', $optText = 'text', $sele $key = (string) $key; if ($key === '' && $options['groups']) { + @trigger_error( + 'Support for optgroup workaround is deprecated and will be removed in 8.0. Use select.groupedlist instead.', + E_USER_DEPRECATED + ); + $html .= $baseIndent . '' . $options['format.eol']; $baseIndent = str_repeat($options['format.indent'], ++$options['format.depth']); } elseif ($key === '' && $options['groups']) { + @trigger_error( + 'Support for optgroup workaround is deprecated and will be removed in 8.0. Use select.groupedlist instead.', + E_USER_DEPRECATED + ); + $baseIndent = str_repeat($options['format.indent'], --$options['format.depth']); $html .= $baseIndent . '' . $options['format.eol']; } else { diff --git a/libraries/src/HTML/Helpers/SortableList.php b/libraries/src/HTML/Helpers/SortableList.php index 61728dc7b25f8..df32c34508a1b 100644 --- a/libraries/src/HTML/Helpers/SortableList.php +++ b/libraries/src/HTML/Helpers/SortableList.php @@ -20,7 +20,7 @@ * * @since 3.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Sortable List will be deprecated in favour of a new dragula script in 4.0 */ abstract class SortableList @@ -39,7 +39,7 @@ abstract class SortableList * * @since 3.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use the new dragula script * Example: JHtml::_('draggablelist.draggable') and add a class of js-draggable to the tbody element of the table */ diff --git a/libraries/src/HTML/Helpers/Tag.php b/libraries/src/HTML/Helpers/Tag.php index 0657edcbcf8f8..932dd49bf2afd 100644 --- a/libraries/src/HTML/Helpers/Tag.php +++ b/libraries/src/HTML/Helpers/Tag.php @@ -53,7 +53,7 @@ public static function options($config = ['filter.published' => [0, 1]]) if (!isset(static::$items[$hash])) { $config = (array) $config; $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('a.id'), @@ -117,7 +117,7 @@ public static function tags($config = ['filter.published' => [0, 1]]) $hash = md5(serialize($config)); $config = (array) $config; $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('a.id'), @@ -167,7 +167,7 @@ public static function tags($config = ['filter.published' => [0, 1]]) * * @since 3.1 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Will be removed without replacement */ public static function ajaxfield($selector = '#jform_tags', $allowCustom = true) diff --git a/libraries/src/HTML/Helpers/User.php b/libraries/src/HTML/Helpers/User.php index 0a7bb53b739b3..37ac4a988425d 100644 --- a/libraries/src/HTML/Helpers/User.php +++ b/libraries/src/HTML/Helpers/User.php @@ -70,7 +70,7 @@ public static function groups($includeSuperAdmin = false) public static function userlist() { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('a.id', 'value'), diff --git a/libraries/src/HTML/Helpers/WorkflowStage.php b/libraries/src/HTML/Helpers/WorkflowStage.php index 6c71b86d293c0..5ba87d01cb388 100644 --- a/libraries/src/HTML/Helpers/WorkflowStage.php +++ b/libraries/src/HTML/Helpers/WorkflowStage.php @@ -37,7 +37,7 @@ public static function existing($options) { // Get the database object and a new query object. $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Build the query. $query->select( diff --git a/libraries/src/Helper/AuthenticationHelper.php b/libraries/src/Helper/AuthenticationHelper.php index 5d82bf3aa47ca..b1e3c64b6870f 100644 --- a/libraries/src/Helper/AuthenticationHelper.php +++ b/libraries/src/Helper/AuthenticationHelper.php @@ -31,7 +31,7 @@ abstract class AuthenticationHelper * * @since 3.6.3 * - * @deprecated 4.2 will be removed in 6.0 + * @deprecated 4.2 will be removed in 7.0 * Will be removed without replacement */ public static function getTwoFactorMethods() diff --git a/libraries/src/Helper/CMSHelper.php b/libraries/src/Helper/CMSHelper.php index cb2a8accb5418..8d96cc8a25ff7 100644 --- a/libraries/src/Helper/CMSHelper.php +++ b/libraries/src/Helper/CMSHelper.php @@ -79,7 +79,7 @@ public function getCurrentLanguage($detectBrowser = true) public function getLanguageId($langCode) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('lang_id')) ->from($db->quoteName('#__languages')) ->where($db->quoteName('lang_code') . ' = :language') diff --git a/libraries/src/Helper/ContentHelper.php b/libraries/src/Helper/ContentHelper.php index bc9dda2b28183..0d703f8978121 100644 --- a/libraries/src/Helper/ContentHelper.php +++ b/libraries/src/Helper/ContentHelper.php @@ -92,7 +92,7 @@ public static function countRelations(&$items, $config) case 'tag_assigments': $recid_col = 'ct.' . $config->group_col; - $query = $db->getQuery(true) + $query = $db->createQuery() ->from($db->quoteName('#__contentitem_tag_map', 'ct')) ->join( 'INNER', @@ -106,7 +106,7 @@ public static function countRelations(&$items, $config) case 'category_or_group': $recid_col = 'c.' . $config->group_col; - $query = $db->getQuery(true) + $query = $db->createQuery() ->from($db->quoteName($related_tbl, 'c')); break; @@ -244,7 +244,7 @@ public static function getCurrentLanguage($detectBrowser = true) public static function getLanguageId($langCode) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('lang_id')) ->from($db->quoteName('#__languages')) ->where($db->quoteName('lang_code') . ' = :language') diff --git a/libraries/src/Helper/LibraryHelper.php b/libraries/src/Helper/LibraryHelper.php index 6c17ed4d1bc50..dbfe55911dc89 100644 --- a/libraries/src/Helper/LibraryHelper.php +++ b/libraries/src/Helper/LibraryHelper.php @@ -113,7 +113,7 @@ public static function saveParams($element, $params) // Save params in DB $db = Factory::getContainer()->get(DatabaseInterface::class); $paramsString = $params->toString(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__extensions')) ->set($db->quoteName('params') . ' = :params') ->where($db->quoteName('type') . ' = ' . $db->quote('library')) @@ -148,7 +148,7 @@ protected static function loadLibrary($element) { $loader = function ($element) { $db = Factory::getContainer()->get(DatabaseInterface::class); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['extension_id', 'element', 'params', 'enabled'], ['id', 'option', null, null])) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('library')) diff --git a/libraries/src/Helper/MediaHelper.php b/libraries/src/Helper/MediaHelper.php index 623b8e5976851..00f8893c29e68 100644 --- a/libraries/src/Helper/MediaHelper.php +++ b/libraries/src/Helper/MediaHelper.php @@ -519,7 +519,22 @@ private static function isValidSvg($file, $shouldLogErrors = true): bool if ($isValid === false || \count($svgErrors)) { if ($shouldLogErrors) { - Factory::getApplication()->enqueueMessage(Text::_('JLIB_MEDIA_ERROR_WARNIEXSS'), 'error'); + $messages = []; + + foreach ($svgErrors as $error) { + $messages[] = Text::sprintf( + 'JLIB_MEDIA_ERROR_SVG_ISSUE', + htmlspecialchars($error['message'] ?? Text::_('JLIB_MEDIA_ERROR_SVG_UNKNOWN'), ENT_QUOTES, 'UTF-8') + ); + } + + $messageText = Text::_('JLIB_MEDIA_ERROR_WARNIEXSS'); + + if (!empty($messages)) { + $messageText .= '
' . implode('
', $messages); + } + + Factory::getApplication()->enqueueMessage($messageText, 'error'); } return false; diff --git a/libraries/src/Helper/ModuleHelper.php b/libraries/src/Helper/ModuleHelper.php index c84d3c0b28815..8ae3d7dfcf28f 100644 --- a/libraries/src/Helper/ModuleHelper.php +++ b/libraries/src/Helper/ModuleHelper.php @@ -411,10 +411,10 @@ public static function getModuleList() $cacheId = implode(',', $groups) . '.' . $clientId . '.' . $itemId; $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $nowDate = Factory::getDate()->toSql(); - $query->select($db->quoteName(['m.id', 'm.title', 'm.module', 'm.position', 'm.content', 'm.showtitle', 'm.params', 'mm.menuid'])) + $query->select($db->quoteName(['m.id', 'm.title', 'm.module', 'm.position', 'm.content', 'm.showtitle', 'm.params', 'mm.menuid', 'e.custom_data'])) ->from($db->quoteName('#__modules', 'm')) ->join( 'LEFT', @@ -716,15 +716,16 @@ public static function &getModuleById($id) */ protected static function createDummyModule(): \stdClass { - $module = new \stdClass(); - $module->id = 0; - $module->title = ''; - $module->module = ''; - $module->position = ''; - $module->content = ''; - $module->showtitle = 0; - $module->control = ''; - $module->params = ''; + $module = new \stdClass(); + $module->id = 0; + $module->title = ''; + $module->module = ''; + $module->position = ''; + $module->content = ''; + $module->showtitle = 0; + $module->control = ''; + $module->params = ''; + $module->custom_data = ''; return $module; } diff --git a/libraries/src/Helper/RouteHelper.php b/libraries/src/Helper/RouteHelper.php index b63349b08d789..884286c0fda13 100644 --- a/libraries/src/Helper/RouteHelper.php +++ b/libraries/src/Helper/RouteHelper.php @@ -208,7 +208,7 @@ protected function findItem($needles = []) * Fetches the category route * * @param mixed $catid Category ID or CategoryNode instance - * @param mixed $language Language code + * @param string $language Language code * @param string $extension Extension to lookup * * @return string @@ -217,7 +217,7 @@ protected function findItem($needles = []) * * @throws \InvalidArgumentException */ - public static function getCategoryRoute($catid, $language = 0, $extension = '') + public static function getCategoryRoute($catid, $language = null, $extension = '') { // Note: $extension is required but has to be an optional argument in the function call due to argument order if (empty($extension)) { @@ -242,7 +242,7 @@ public static function getCategoryRoute($catid, $language = 0, $extension = '') 'category' => [$id], ]; - if ($language && $language !== '*' && Multilanguage::isEnabled()) { + if (!empty($language) && $language !== '*' && Multilanguage::isEnabled()) { $link .= '&lang=' . $language; $needles['language'] = $language; } diff --git a/libraries/src/Helper/TagsHelper.php b/libraries/src/Helper/TagsHelper.php index 66944dd46d9e2..d461b60ddf266 100644 --- a/libraries/src/Helper/TagsHelper.php +++ b/libraries/src/Helper/TagsHelper.php @@ -12,7 +12,6 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Table\CoreContent; -use Joomla\CMS\Table\Table; use Joomla\CMS\Table\TableInterface; use Joomla\Database\DatabaseInterface; use Joomla\Database\ParameterType; @@ -102,7 +101,7 @@ public function addTagMapping($ucmId, TableInterface $table, $tags = []) $db = $table->getDbo(); $key = $table->getKeyName(); $item = $table->$key; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('ct') . '.type_id') ->from($db->quoteName('#__content_types', 'ct')) ->where($db->quoteName('ct.type_alias') . ' = :alias') @@ -123,7 +122,7 @@ public function addTagMapping($ucmId, TableInterface $table, $tags = []) return true; } - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->insert('#__contentitem_tag_map'); $query->columns( [ @@ -185,7 +184,7 @@ public static function convertPathsToNames($tags) $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('alias'), @@ -327,10 +326,8 @@ public function deleteTagData(TableInterface $table, $contentItemId) throw new \InvalidArgumentException('Multiple primary keys are not supported as a content item id'); } - $result = $this->unTagItem($contentItemId[$key], $table); - - /** @var CoreContent $coreContentTable */ - $coreContentTable = Table::getInstance('CoreContent'); + $result = $this->unTagItem($contentItemId[$key], $table); + $coreContentTable = new CoreContent(Factory::getDbo()); return $result && $coreContentTable->deleteByContentId($contentItemId[$key], $this->typeAlias); } @@ -353,7 +350,7 @@ public function getItemTags($contentType, $id, $getTagData = true) // Initialize some variables. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('m.tag_id')) ->from($db->quoteName('#__contentitem_tag_map', 'm')) ->where( @@ -414,7 +411,7 @@ public function getMultipleItemTags($contentType, array $ids, $getTagData = true /** @var DatabaseInterface $db */ $db = Factory::getContainer()->get(DatabaseInterface::class); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['m.tag_id', 'm.content_item_id'])) ->from($db->quoteName('#__contentitem_tag_map', 'm')) ->where( @@ -493,7 +490,7 @@ public function getTagIds($ids, $prefix) $db = Factory::getDbo(); // Load the tags. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('t.id')) ->from($db->quoteName('#__tags', 't')) ->join('INNER', $db->quoteName('#__contentitem_tag_map', 'm'), $db->quoteName('m.tag_id') . ' = ' . $db->quoteName('t.id')) @@ -539,7 +536,7 @@ public function getTagItemsQuery( ) { // Create a new query object. $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $user = Factory::getUser(); $nullDate = $db->getNullDate(); $nowDate = Factory::getDate()->toSql(); @@ -717,7 +714,7 @@ public function getTagNames($tagIds) $tagIds = ArrayHelper::toInteger($tagIds); $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('title')) ->from($db->quoteName('#__tags')) ->whereIn($db->quoteName('id'), $tagIds) @@ -779,7 +776,7 @@ public static function getTypes($arrayType = 'objectList', $selectTypes = null, { // Initialize some variables. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*'); if (!empty($selectTypes)) { @@ -830,6 +827,26 @@ public static function getTypes($arrayType = 'objectList', $selectTypes = null, * @deprecated 5.3 will be removed in 7.0 */ public function postStoreProcess(TableInterface $table, $newTags = [], $replace = true) + { + @trigger_error('7.0 Method postStoreProcess() is deprecated, use postStore() instead.', \E_USER_DEPRECATED); + + $this->postStore($table, (array) $newTags, (bool) $replace); + } + + /** + * Function that handles saving tags used in a table class after a store(). + * + * @param TableInterface $table Table being processed. + * @param array $newTags Array of new tags. + * @param boolean $replace Flag indicating if all existing tags should be replaced. + * This flag takes precedence before $remove. + * @param boolean $remove Flag indicating if the tags in $newTags should be removed. + * + * @return boolean + * + * @since 6.0.0 + */ + public function postStore(TableInterface $table, array $newTags = [], bool $replace = true, bool $remove = false): bool { if (!empty($table->newTags) && empty($newTags)) { $newTags = $table->newTags; @@ -850,10 +867,10 @@ public function postStoreProcess(TableInterface $table, $newTags = [], $replace } else { // Process the tags $data = $this->getRowData($table); - $coreContentTable = Table::getInstance('CoreContent'); + $coreContentTable = new CoreContent(Factory::getDbo()); $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('ct') . '.*') ->from($db->quoteName('#__content_types', 'ct')) ->where($db->quoteName('ct.type_alias') . ' = :alias') @@ -892,7 +909,7 @@ public function postStoreProcess(TableInterface $table, $newTags = [], $replace $ucmData['special']['ucm_id'] = $ucmData['common']['ucm_id']; } - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('ucm_id')) ->from($db->quoteName('#__ucm_base')) ->where( @@ -913,7 +930,11 @@ public function postStoreProcess(TableInterface $table, $newTags = [], $replace $ucmId = $coreContentTable->core_content_id; // Store the tag data if the article data was saved and run related methods. - $result = $result && $this->tagItem($ucmId, $table, $newTags, $replace); + if ($remove) { + $result = $result && $this->unTagItem($ucmId, $table, $newTags); + } else { + $result = $result && $this->tagItem($ucmId, $table, $newTags, $replace); + } } } @@ -969,7 +990,7 @@ public function preStoreProcess(TableInterface $table, $newTags = []) public static function searchTags($filters = []) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('a.id', 'value'), @@ -1079,7 +1100,7 @@ public function tagDeleteInstances($tagId) // Delete the old tag maps. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__contentitem_tag_map')) ->where($db->quoteName('tag_id') . ' = :id') ->bind(':id', $tagId, ParameterType::INTEGER); @@ -1143,7 +1164,7 @@ public function unTagItem($contentId, TableInterface $table, $tags = []) $key = $table->getKeyName(); $id = (int) $table->$key; $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__contentitem_tag_map')) ->where( [ @@ -1182,7 +1203,7 @@ public function getTags($tagIds) $tagIds = ArrayHelper::toInteger($tagIds); $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select([$db->quoteName('id'), $db->quoteName('title')]) ->from($db->quoteName('#__tags')) ->whereIn($db->quoteName('id'), $tagIds) diff --git a/libraries/src/Helper/UserGroupsHelper.php b/libraries/src/Helper/UserGroupsHelper.php index 13693231dc7f1..421471fae2c57 100644 --- a/libraries/src/Helper/UserGroupsHelper.php +++ b/libraries/src/Helper/UserGroupsHelper.php @@ -198,7 +198,7 @@ public function total() if ($this->total === null) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(' . $db->quoteName('id') . ')') ->from($db->quoteName('#__usergroups')); @@ -226,7 +226,7 @@ public function load($id) $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('id') . ' = :id') @@ -256,7 +256,7 @@ public function loadAll() $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__usergroups')) ->order($db->quoteName('lft') . ' ASC'); diff --git a/libraries/src/Http/Http.php b/libraries/src/Http/Http.php index a49ba3f8ab9c9..e9c7f29fa8634 100644 --- a/libraries/src/Http/Http.php +++ b/libraries/src/Http/Http.php @@ -20,6 +20,8 @@ * HTTP client class. * * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Http instead */ class Http extends FrameworkHttp { @@ -30,8 +32,10 @@ class Http extends FrameworkHttp * these will be added to the request headers. * @param ?FrameworkTransportInterface $transport The HTTP transport object. * - * @since 1.7.3 * @throws \InvalidArgumentException + * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Http::__construct() instead */ public function __construct($options = [], ?FrameworkTransportInterface $transport = null) { diff --git a/libraries/src/Http/HttpFactory.php b/libraries/src/Http/HttpFactory.php index 7bc49a085969e..cde93e5cca893 100644 --- a/libraries/src/Http/HttpFactory.php +++ b/libraries/src/Http/HttpFactory.php @@ -20,6 +20,8 @@ * HTTP factory class. * * @since 3.0.0 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\HttpFactory instead */ class HttpFactory { @@ -31,8 +33,10 @@ class HttpFactory * * @return Http * - * @since 3.0.0 * @throws \RuntimeException + * @since 3.0.0 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\HttpFactory::getHttp() instead */ public static function getHttp($options = [], $adapters = null) { @@ -64,6 +68,8 @@ public static function getHttp($options = [], $adapters = null) * @return TransportInterface|boolean Interface sub-class or boolean false if no adapters are available * * @since 3.0.0 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\HttpFactory::getAvailableDriver() instead */ public static function getAvailableDriver($options = [], $default = null) { @@ -101,6 +107,8 @@ public static function getAvailableDriver($options = [], $default = null) * @return array An array of available transport handlers * * @since 3.0.0 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\HttpFactory::getHttpTransports() instead */ public static function getHttpTransports() { diff --git a/libraries/src/Http/Response.php b/libraries/src/Http/Response.php index 345ee82e2c042..6d79b7bd719f3 100644 --- a/libraries/src/Http/Response.php +++ b/libraries/src/Http/Response.php @@ -20,9 +20,50 @@ * * @since 1.7.3 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use Joomla\Http\Response instead */ class Response extends FrameworkResponse { + /** + * Magic getter for backward compatibility with the 1.x Joomla Framework API + * + * @param string $name The variable to return + * + * @return mixed + * + * @since 6.0.0 + * @deprecated 6.0 will be removed in 8.0 + * Access data via the PSR-7 ResponseInterface instead + */ + public function __get($name) + { + switch (strtolower($name)) { + case 'body': + $stream = $this->getBody(); + $stream->rewind(); + return $stream->getContents(); + + case 'code': + return $this->getStatusCode(); + + case 'headers': + return $this->getHeaders(); + + default: + $trace = debug_backtrace(); + + trigger_error( + \sprintf( + 'Undefined property via __get(): %s in %s on line %s', + $name, + $trace[0]['file'], + $trace[0]['line'] + ), + E_USER_NOTICE + ); + + break; + } + } } diff --git a/libraries/src/Http/Transport/CurlTransport.php b/libraries/src/Http/Transport/CurlTransport.php index 9f5e6ca9e42cc..a526f3f6865af 100644 --- a/libraries/src/Http/Transport/CurlTransport.php +++ b/libraries/src/Http/Transport/CurlTransport.php @@ -27,6 +27,8 @@ * HTTP transport class for using cURL. * * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Curl instead */ class CurlTransport extends AbstractTransport implements TransportInterface { @@ -42,8 +44,10 @@ class CurlTransport extends AbstractTransport implements TransportInterface * * @return Response * - * @since 1.7.3 * @throws \RuntimeException + * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Curl::request() instead */ public function request($method, UriInterface $uri, $data = null, array $headers = [], $timeout = null, $userAgent = null) { @@ -214,8 +218,10 @@ public function request($method, UriInterface $uri, $data = null, array $headers * * @return Response * - * @since 1.7.3 * @throws InvalidResponseCodeException + * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Curl::getResponse() instead */ protected function getResponse($content, $info) { @@ -273,6 +279,8 @@ protected function getResponse($content, $info) * @return boolean true if available, else false * * @since 3.0.0 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Curl::isSupported() instead */ public static function isSupported() { @@ -285,6 +293,8 @@ public static function isSupported() * @return boolean * * @since 3.0.0 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Curl::redirectsAllowed() instead */ private function redirectsAllowed() { diff --git a/libraries/src/Http/Transport/SocketTransport.php b/libraries/src/Http/Transport/SocketTransport.php index 64607f346e2a0..dcd37c25aacaf 100644 --- a/libraries/src/Http/Transport/SocketTransport.php +++ b/libraries/src/Http/Transport/SocketTransport.php @@ -26,6 +26,8 @@ * HTTP transport class for using sockets directly. * * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Socket instead */ class SocketTransport extends AbstractTransport implements TransportInterface { @@ -47,8 +49,10 @@ class SocketTransport extends AbstractTransport implements TransportInterface * * @return Response * - * @since 1.7.3 * @throws \RuntimeException + * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Socket::request() instead */ public function request($method, UriInterface $uri, $data = null, array $headers = [], $timeout = null, $userAgent = null) { @@ -150,8 +154,10 @@ public function request($method, UriInterface $uri, $data = null, array $headers * * @return Response * - * @since 1.7.3 * @throws InvalidResponseCodeException + * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Socket::getResponse() instead */ protected function getResponse($content) { @@ -194,8 +200,10 @@ protected function getResponse($content) * * @return resource Socket connection resource. * - * @since 1.7.3 * @throws \RuntimeException + * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Socket::connect() instead */ protected function connect(UriInterface $uri, $timeout = null) { @@ -276,6 +284,8 @@ protected function connect(UriInterface $uri, $timeout = null) * @return boolean True if available else false * * @since 3.0.0 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Socket::isSupported() instead */ public static function isSupported() { diff --git a/libraries/src/Http/Transport/StreamTransport.php b/libraries/src/Http/Transport/StreamTransport.php index 3a0cb9fb4eb13..5e440725b86bc 100644 --- a/libraries/src/Http/Transport/StreamTransport.php +++ b/libraries/src/Http/Transport/StreamTransport.php @@ -27,6 +27,8 @@ * HTTP transport class for using PHP streams. * * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Stream instead */ class StreamTransport extends AbstractTransport implements TransportInterface { @@ -42,8 +44,10 @@ class StreamTransport extends AbstractTransport implements TransportInterface * * @return Response * - * @since 1.7.3 * @throws \RuntimeException + * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Stream::request() instead */ public function request($method, UriInterface $uri, $data = null, array $headers = [], $timeout = null, $userAgent = null) { @@ -196,8 +200,10 @@ public function request($method, UriInterface $uri, $data = null, array $headers * * @return Response * - * @since 1.7.3 * @throws InvalidResponseCodeException + * @since 1.7.3 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Stream::getResponse() instead */ protected function getResponse(array $headers, $body) { @@ -225,6 +231,8 @@ protected function getResponse(array $headers, $body) * @return boolean true if available else false * * @since 3.0.0 + * @deprecated 6.0 will be removed in 8.0 + * Use Joomla\Http\Transport\Stream::isSupported() instead */ public static function isSupported() { diff --git a/libraries/src/Http/TransportInterface.php b/libraries/src/Http/TransportInterface.php index 4d40986073bcb..c9246ecabb629 100644 --- a/libraries/src/Http/TransportInterface.php +++ b/libraries/src/Http/TransportInterface.php @@ -20,7 +20,7 @@ * * @since 1.7.3 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Implement Joomla\Http\TransportInterface instead */ interface TransportInterface extends FrameworkTransportInterface diff --git a/libraries/src/Image/Image.php b/libraries/src/Image/Image.php index 2ce0229f317ce..624ab44a8ae04 100644 --- a/libraries/src/Image/Image.php +++ b/libraries/src/Image/Image.php @@ -367,27 +367,6 @@ public function createThumbnails($thumbSizes, $creationMethod = self::SCALE_INSI return $thumbsCreated; } - /** - * Method to create thumbnails from the current image and save them to disk. It allows creation by resizing or cropping the original image. - * - * @param mixed $thumbSizes string or array of strings. Example: $thumbSizes = ['150x75','250x150']; - * @param integer $creationMethod 1-3 resize $scaleMethod | 4 create cropping - * @param string $thumbsFolder destination thumbs folder. null generates a thumbs folder in the image folder - * - * @return array - * - * @since 2.5.0 - * @throws \LogicException - * @throws \InvalidArgumentException - * - * @deprecated 4.0 will be removed in 6.0 - * Use \Joomla\CMS\Image\createThumbnails instead - */ - public function createThumbs($thumbSizes, $creationMethod = self::SCALE_INSIDE, $thumbsFolder = null) - { - return $this->createThumbnails($thumbSizes, $creationMethod, $thumbsFolder, false); - } - /** * Method to crop the current image. * diff --git a/libraries/src/Input/Cli.php b/libraries/src/Input/Cli.php index 445ba54d2e4e7..b236e025325bb 100644 --- a/libraries/src/Input/Cli.php +++ b/libraries/src/Input/Cli.php @@ -10,6 +10,7 @@ namespace Joomla\CMS\Input; use Joomla\CMS\Filter\InputFilter; +use Joomla\Input\Input; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -20,7 +21,7 @@ * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the `joomla/console` package instead */ class Cli extends Input @@ -31,7 +32,7 @@ class Cli extends Input * @var string * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the `joomla/console` package instead */ public $executable; @@ -43,7 +44,7 @@ class Cli extends Input * @var array * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the `joomla/console` package instead */ public $args = []; @@ -56,7 +57,7 @@ class Cli extends Input * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the `joomla/console` package instead */ public function __construct(?array $source = null, array $options = []) @@ -81,7 +82,7 @@ public function __construct(?array $source = null, array $options = []) * * @since 3.0.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the `joomla/console` package instead */ public function serialize() @@ -106,7 +107,7 @@ public function serialize() * * @since 3.0.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the `joomla/console` package instead */ public function unserialize($input) @@ -131,7 +132,7 @@ public function unserialize($input) * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the `joomla/console` package instead */ protected function parseArguments() diff --git a/libraries/src/Installer/Adapter/ComponentAdapter.php b/libraries/src/Installer/Adapter/ComponentAdapter.php index 217484b99f88d..e3f29700545fc 100644 --- a/libraries/src/Installer/Adapter/ComponentAdapter.php +++ b/libraries/src/Installer/Adapter/ComponentAdapter.php @@ -16,8 +16,9 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\Table\Asset; +use Joomla\CMS\Table\Category; use Joomla\CMS\Table\Extension; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Menu; use Joomla\CMS\Table\Update; use Joomla\Database\ParameterType; use Joomla\Filesystem\Folder; @@ -338,8 +339,7 @@ protected function createExtensionRoot() */ protected function finaliseInstall() { - /** @var Update $update */ - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); // Clobber any possible pending updates $uid = $update->find( @@ -378,8 +378,7 @@ protected function finaliseInstall() Log::add(Text::_('JLIB_INSTALLER_ABORT_COMP_UPDATESITEMENUS_FAILED'), Log::WARNING, 'jerror'); } - /** @var Asset $asset */ - $asset = Table::getInstance('Asset'); + $asset = new Asset($this->getDatabase()); // Check if an asset already exists for this extension and create it if not if (!$asset->loadByName($this->extension->element)) { @@ -418,7 +417,7 @@ protected function finaliseUninstall(): bool $db = $this->getDatabase(); // Remove the schema version - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__schemas')) ->where($db->quoteName('extension_id') . ' = :extension_id') ->bind(':extension_id', $extensionId, ParameterType::INTEGER); @@ -426,7 +425,7 @@ protected function finaliseUninstall(): bool $db->execute(); // Remove the component container in the assets table. - $asset = Table::getInstance('Asset'); + $asset = new Asset($this->getDatabase()); if ($asset->loadByName($this->getElement())) { $asset->delete(); @@ -436,7 +435,7 @@ protected function finaliseUninstall(): bool $extensionNameWithWildcard = $extensionName . '.%'; // Remove categories for this component - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__categories')) ->where( [ @@ -451,10 +450,11 @@ protected function finaliseUninstall(): bool $db->execute(); // Rebuild the categories for correct lft/rgt - Table::getInstance('category')->rebuild(); + $table = new Category($db); + $table->rebuild(); // Clobber any possible pending updates - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ 'element' => $this->extension->element, @@ -668,7 +668,7 @@ public function prepareDiscoverInstall() // Try to delete existing failed records before retrying $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where( @@ -692,8 +692,7 @@ public function prepareDiscoverInstall() $this->_removeAdminMenus($eid); // Remove the extension record itself - /** @var Extension $extensionTable */ - $extensionTable = Table::getInstance('extension'); + $extensionTable = new Extension($this->getDatabase()); $extensionTable->delete($eid); } } @@ -857,7 +856,7 @@ protected function storeExtension($deleteExisting = false) // Try to delete existing failed records before retrying $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where( @@ -881,8 +880,7 @@ protected function storeExtension($deleteExisting = false) $this->_removeAdminMenus($eid); // Remove the extension record itself - /** @var Extension $extensionTable */ - $extensionTable = Table::getInstance('extension'); + $extensionTable = new Extension($this->getDatabase()); $extensionTable->delete($eid); } } @@ -938,7 +936,7 @@ protected function _buildAdminMenus($componentId = null) $option = $this->element; // If a component exists with this option in the table within the protected menutype 'main' then we don't need to add menus - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('m.id'), @@ -1148,11 +1146,10 @@ protected function _removeAdminMenus($id) { $db = $this->getDatabase(); - /** @var \Joomla\CMS\Table\Menu $table */ - $table = Table::getInstance('menu'); + $table = new Menu($db); // Get the ids of the menu items - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->where( @@ -1221,7 +1218,7 @@ protected function _updateMenus($componentId, $clientId = null) // Update all menu items which contain 'index.php?option=com_extension' or 'index.php?option=com_extension&...' // to use the new component id. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__menu')) ->set($db->quoteName('component_id') . ' = :componentId') ->where($db->quoteName('type') . ' = ' . $db->quote('component')) @@ -1288,7 +1285,7 @@ public function discover() $manifest_details = Installer::parseXMLInstallFile( JPATH_SITE . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml' ); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'component'; $extension->client_id = 0; $extension->element = $component; @@ -1307,7 +1304,7 @@ public function discover() $manifest_details = Installer::parseXMLInstallFile( JPATH_ADMINISTRATOR . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml' ); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'component'; $extension->client_id = 1; $extension->element = $component; @@ -1325,7 +1322,7 @@ public function discover() $manifest_details = Installer::parseXMLInstallFile( JPATH_API . '/components/' . $component . '/' . str_replace('com_', '', $component) . '.xml' ); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'component'; $extension->client_id = 3; $extension->element = $component; @@ -1392,8 +1389,7 @@ protected function _createAdminMenuItem(array &$data, $parentId) { $db = $this->getDatabase(); - /** @var \Joomla\CMS\Table\Menu $table */ - $table = Table::getInstance('menu'); + $table = new Menu($db); try { $table->setLocation($parentId, 'last-child'); @@ -1411,7 +1407,7 @@ protected function _createAdminMenuItem(array &$data, $parentId) $home = $data['home']; // The menu item already exists. Delete it and retry instead of throwing an error. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->where( @@ -1440,8 +1436,7 @@ protected function _createAdminMenuItem(array &$data, $parentId) return false; } - /** @var \Joomla\CMS\Table\Menu $temporaryTable */ - $temporaryTable = Table::getInstance('menu'); + $temporaryTable = new Menu($db); $temporaryTable->delete($menu_id, true); $temporaryTable->load($parentId); $temporaryTable->rebuild($parentId, $temporaryTable->lft, $temporaryTable->level, $temporaryTable->path); diff --git a/libraries/src/Installer/Adapter/FileAdapter.php b/libraries/src/Installer/Adapter/FileAdapter.php index 94bf439616450..570f8720626af 100644 --- a/libraries/src/Installer/Adapter/FileAdapter.php +++ b/libraries/src/Installer/Adapter/FileAdapter.php @@ -13,7 +13,7 @@ use Joomla\CMS\Installer\InstallerAdapter; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Update; use Joomla\Database\ParameterType; use Joomla\Filesystem\File; use Joomla\Filesystem\Folder; @@ -109,7 +109,7 @@ protected function copyBaseFiles() protected function finaliseInstall() { // Clobber any possible pending updates - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ @@ -183,7 +183,7 @@ protected function finaliseUninstall(): bool $db = $this->getDatabase(); // Remove the schema version - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete('#__schemas') ->where('extension_id = :extension_id') ->bind(':extension_id', $extensionId, ParameterType::INTEGER); @@ -191,7 +191,7 @@ protected function finaliseUninstall(): bool $db->execute(); // Clobber any possible pending updates - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ 'element' => $this->extension->element, @@ -456,7 +456,7 @@ protected function extensionExistsInSystem($extension = null) // Get a database connector object $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('file')) diff --git a/libraries/src/Installer/Adapter/LanguageAdapter.php b/libraries/src/Installer/Adapter/LanguageAdapter.php index ee220fdac5114..504ddd3ecaad5 100644 --- a/libraries/src/Installer/Adapter/LanguageAdapter.php +++ b/libraries/src/Installer/Adapter/LanguageAdapter.php @@ -10,6 +10,7 @@ namespace Joomla\CMS\Installer\Adapter; use Joomla\CMS\Application\ApplicationHelper; +use Joomla\CMS\Cache\CacheControllerFactoryInterface; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; @@ -19,7 +20,7 @@ use Joomla\CMS\Language\LanguageHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; use Joomla\CMS\Table\Update; use Joomla\Database\ParameterType; use Joomla\Filesystem\Folder; @@ -107,7 +108,7 @@ protected function finaliseUninstall(): bool // Remove the schema version $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__schemas')) ->where($db->quoteName('extension_id') . ' = :extension_id') ->bind(':extension_id', $extensionId, ParameterType::INTEGER); @@ -115,7 +116,7 @@ protected function finaliseUninstall(): bool $db->execute(); // Clobber any possible pending updates - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ 'element' => $this->extension->element, @@ -128,7 +129,7 @@ protected function finaliseUninstall(): bool } // Clean installed languages cache. - Factory::getCache()->clean('com_languages'); + $this->cleanLanguagesCache(); // Remove the extension table entry $this->extension->delete(); @@ -417,7 +418,7 @@ protected function _install($cname, $basePath, $clientId, &$element) } // Add an entry to the extension table with a whole heap of defaults - $row = Table::getInstance('extension'); + $row = new Extension($this->getDatabase()); $row->name = $this->name; $row->type = 'language'; $row->element = $this->tag; @@ -444,8 +445,7 @@ protected function _install($cname, $basePath, $clientId, &$element) } // Clobber any possible pending updates - /** @var Update $update */ - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find(['element' => $this->tag, 'type' => 'language', 'folder' => '']); if ($uid) { @@ -453,7 +453,7 @@ protected function _install($cname, $basePath, $clientId, &$element) } // Clean installed languages cache. - Factory::getCache()->clean('com_languages'); + $this->cleanLanguagesCache(); return $row->extension_id; } @@ -480,7 +480,7 @@ protected function getSefString($itemLanguageTag) // Get the sef value of all current content languages. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('sef')) ->from($db->quoteName('#__languages')); $db->setQuery($query); @@ -575,7 +575,7 @@ public function update() */ // Clobber any possible pending updates - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find(['element' => $this->tag, 'type' => 'language', 'client_id' => $clientId]); if ($uid) { @@ -583,7 +583,7 @@ public function update() } // Update an entry to the extension table - $row = Table::getInstance('extension'); + $row = new Extension($this->getDatabase()); $eid = $row->find(['element' => $this->tag, 'type' => 'language', 'client_id' => $clientId]); if ($eid) { @@ -607,7 +607,7 @@ public function update() $row->changelogurl = (string) $this->getManifest()->changelogurl; // Clean installed languages cache. - Factory::getCache()->clean('com_languages'); + $this->cleanLanguagesCache(); if (!$row->check() || !$row->store()) { // Install failed, roll back changes @@ -651,7 +651,7 @@ public function discover() } $manifest_details = Installer::parseXMLInstallFile($manifestfile); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'language'; $extension->client_id = $clientId; $extension->element = $language; @@ -711,7 +711,7 @@ public function discover_install() } // Clean installed languages cache. - Factory::getCache()->clean('com_languages'); + $this->cleanLanguagesCache(); return $this->parent->extension->extension_id; } @@ -766,7 +766,7 @@ private function resetUserLanguage(): void // Setting the language of users which have this language as the default language $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('id'), @@ -786,7 +786,7 @@ private function resetUserLanguage(): void $count = 0; // Prepare the query. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__users')) ->set($db->quoteName('params') . ' = :registry') ->where($db->quoteName('id') . ' = :userId') @@ -822,7 +822,7 @@ private function resetUserLanguage(): void */ protected function createContentLanguage($tag) { - $tableLanguage = Table::getInstance('language'); + $tableLanguage = new \Joomla\CMS\Table\Language($this->getDatabase()); // Check if content language already exists. if ($tableLanguage->load(['lang_code' => $tag])) { @@ -849,7 +849,7 @@ protected function createContentLanguage($tag) $contentLanguageNativeTitle = $siteLanguageManifest['nativeName']; } - // Try to load a language string from the installation language var. Will be removed in 4.0. + // Try to load a language string from the installation language var. Will be removed in 7.0. if ($contentLanguageNativeTitle === $contentLanguageTitle) { $manifestfile = JPATH_INSTALLATION . '/language/' . $tag . '/langmetadata.xml'; @@ -900,4 +900,18 @@ protected function createContentLanguage($tag) ); } } + + /** + * Cleans the languages cache + * + * @return void + * + * @since 6.2.0 + */ + private function cleanLanguagesCache(): void + { + $this->getContainer()->get(CacheControllerFactoryInterface::class) + ->createCacheController('callback', ['defaultgroup' => '']) + ->clean('com_languages'); + } } diff --git a/libraries/src/Installer/Adapter/LibraryAdapter.php b/libraries/src/Installer/Adapter/LibraryAdapter.php index b02cd13080c0e..7a39408c48b5c 100644 --- a/libraries/src/Installer/Adapter/LibraryAdapter.php +++ b/libraries/src/Installer/Adapter/LibraryAdapter.php @@ -14,7 +14,7 @@ use Joomla\CMS\Installer\Manifest\LibraryManifest; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; use Joomla\CMS\Table\Update; use Joomla\Database\ParameterType; use Joomla\Filesystem\File; @@ -55,7 +55,7 @@ protected function checkExtensionInFilesystem() // Clear the cached data $this->currentExtensionId = null; - $this->extension = Table::getInstance('Extension', '\\Joomla\\CMS\\Table\\', ['dbo' => $this->getDatabase()]); + $this->extension = new Extension($this->getDatabase()); // From this point we'll consider this an update $this->setRoute('update'); @@ -92,8 +92,7 @@ protected function copyBaseFiles() protected function finaliseInstall() { // Clobber any possible pending updates - /** @var Update $update */ - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ 'element' => $this->element, @@ -169,7 +168,7 @@ protected function finaliseUninstall(): bool $db = $this->getDatabase(); // Remove the schema version - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete('#__schemas') ->where('extension_id = :extension_id') ->bind(':extension_id', $extensionId, ParameterType::INTEGER); @@ -177,7 +176,7 @@ protected function finaliseUninstall(): bool $db->execute(); // Clobber any possible pending updates - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ 'element' => $this->extension->element, @@ -462,7 +461,7 @@ public function discover() $element = str_replace([$mainFolder . DIRECTORY_SEPARATOR, '.xml'], '', $file); $manifestCache = Installer::parseXMLInstallFile($file); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'library'; $extension->client_id = 0; $extension->element = $element; diff --git a/libraries/src/Installer/Adapter/ModuleAdapter.php b/libraries/src/Installer/Adapter/ModuleAdapter.php index 595dd360c72a4..366cbd6681b10 100644 --- a/libraries/src/Installer/Adapter/ModuleAdapter.php +++ b/libraries/src/Installer/Adapter/ModuleAdapter.php @@ -14,7 +14,9 @@ use Joomla\CMS\Installer\InstallerAdapter; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; +use Joomla\CMS\Table\Module; +use Joomla\CMS\Table\Update; use Joomla\Database\ParameterType; use Joomla\Filesystem\Folder; use Joomla\Utilities\ArrayHelper; @@ -46,6 +48,17 @@ class ModuleAdapter extends InstallerAdapter */ protected $scriptElement = null; + /** + * The list of current files that are installed and is read + * from the manifest on disk in the update area to handle doing a diff + * and deleting files that are in the old files list and not in the new + * files list. + * + * @var array + * @since 6.1.0 + * */ + protected $oldFiles = null; + /** * Method to check if the extension is already present in the database * @@ -89,7 +102,7 @@ protected function checkExistingExtension() protected function copyBaseFiles() { // Copy all necessary files - if ($this->parent->parseFiles($this->getManifest()->files, -1) === false) { + if ($this->parent->parseFiles($this->getManifest()->files, -1, $this->oldFiles) === false) { throw new \RuntimeException(Text::_('JLIB_INSTALLER_ABORT_MOD_COPY_FILES')); } @@ -131,7 +144,7 @@ public function discover() foreach ($site_list as $module) { if (file_exists(JPATH_SITE . "/modules/$module/$module.xml")) { $manifest_details = Installer::parseXMLInstallFile(JPATH_SITE . "/modules/$module/$module.xml"); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'module'; $extension->client_id = $site_info->id; $extension->element = $module; @@ -147,7 +160,7 @@ public function discover() foreach ($admin_list as $module) { if (file_exists(JPATH_ADMINISTRATOR . "/modules/$module/$module.xml")) { $manifest_details = Installer::parseXMLInstallFile(JPATH_ADMINISTRATOR . "/modules/$module/$module.xml"); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'module'; $extension->client_id = $admin_info->id; $extension->element = $module; @@ -174,7 +187,7 @@ public function discover() protected function finaliseInstall() { // Clobber any possible pending updates - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ 'element' => $this->element, @@ -217,7 +230,7 @@ protected function finaliseUninstall(): bool $retval = true; // Remove the schema version - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete('#__schemas') ->where('extension_id = :extension_id') ->bind(':extension_id', $extensionId, ParameterType::INTEGER); @@ -249,7 +262,7 @@ protected function finaliseUninstall(): bool $modules = ArrayHelper::toInteger($modules); // Wipe out any items assigned to menus - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__modules_menu')) ->whereIn($db->quoteName('moduleid'), $modules); $db->setQuery($query); @@ -262,8 +275,7 @@ protected function finaliseUninstall(): bool } // Wipe out any instances in the modules table - /** @var \Joomla\CMS\Table\Module $module */ - $module = Table::getInstance('Module'); + $module = new Module($db); foreach ($modules as $modInstanceId) { $module->load($modInstanceId); @@ -277,7 +289,7 @@ protected function finaliseUninstall(): bool // Now we will no longer need the module object, so let's delete it and free up memory $this->extension->delete($this->extension->extension_id); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__modules')) ->where($db->quoteName('module') . ' = :element') ->where($db->quoteName('client_id') . ' = :client_id') @@ -527,6 +539,28 @@ protected function setupUninstall() $this->loadLanguage(($this->extension->client_id ? JPATH_ADMINISTRATOR : JPATH_SITE) . '/modules/' . $element); } + /** + * Method to setup the update routine for the adapter + * + * @return void + * + * @since 6.1.0 + */ + protected function setupUpdates() + { + // Create a new installer because findManifest sets stuff; side effects! + $tmpInstaller = new Installer(); + $tmpInstaller->setDatabase($this->getDatabase()); + + // Look in the extension root + $tmpInstaller->setPath('source', $this->parent->getPath('extension_root')); + + if ($tmpInstaller->findManifest()) { + $old_manifest = $tmpInstaller->getManifest(); + $this->oldFiles = $old_manifest->files; + } + } + /** * Method to store the extension to the database * @@ -635,8 +669,7 @@ protected function storeExtension() // Create unpublished module $name = preg_replace('#[\*?]#', '', Text::_($this->name)); - /** @var \Joomla\CMS\Table\Module $module */ - $module = Table::getInstance('module'); + $module = new Module($this->getDatabase()); $module->title = $name; $module->content = ''; $module->module = $this->element; @@ -669,7 +702,7 @@ protected function _rollback_menu($arg) $moduleId = $arg['id']; // Remove the entry from the #__modules_menu table - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__modules_menu')) ->where($db->quoteName('moduleid') . ' = :module_id') ->bind(':module_id', $moduleId, ParameterType::INTEGER); @@ -700,7 +733,7 @@ protected function _rollback_module($arg) $moduleId = $arg['id']; // Remove the entry from the #__modules table - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__modules')) ->where($db->quoteName('id') . ' = :module_id') ->bind(':module_id', $moduleId, ParameterType::INTEGER); diff --git a/libraries/src/Installer/Adapter/PackageAdapter.php b/libraries/src/Installer/Adapter/PackageAdapter.php index 0f036f853a307..97208284ba037 100644 --- a/libraries/src/Installer/Adapter/PackageAdapter.php +++ b/libraries/src/Installer/Adapter/PackageAdapter.php @@ -18,7 +18,6 @@ use Joomla\CMS\Installer\Manifest\PackageManifest; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Table\Table; use Joomla\CMS\Table\Update; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; @@ -206,8 +205,7 @@ protected function createExtensionRoot() protected function finaliseInstall() { // Clobber any possible pending updates - /** @var Update $update */ - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ 'element' => $this->element, @@ -222,7 +220,7 @@ protected function finaliseInstall() // Set the package ID for each of the installed extensions to track the relationship if (!empty($this->installedIds)) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__extensions')) ->set($db->quoteName('package_id') . ' = :id') ->whereIn($db->quoteName('extension_id'), $this->installedIds) @@ -309,7 +307,7 @@ protected function finaliseUninstall(): bool $db = $this->getDatabase(); // Remove the schema version - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__schemas')) ->where($db->quoteName('extension_id') . ' = :extension_id') ->bind(':extension_id', $this->extension->extension_id, ParameterType::INTEGER); @@ -317,7 +315,7 @@ protected function finaliseUninstall(): bool $db->execute(); // Clobber any possible pending updates - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ 'element' => $this->extension->element, @@ -655,7 +653,7 @@ protected function _getExtensionId($type, $id, $client, $group) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where( diff --git a/libraries/src/Installer/Adapter/PluginAdapter.php b/libraries/src/Installer/Adapter/PluginAdapter.php index 6c88916efb059..07c43f359d921 100644 --- a/libraries/src/Installer/Adapter/PluginAdapter.php +++ b/libraries/src/Installer/Adapter/PluginAdapter.php @@ -14,7 +14,7 @@ use Joomla\CMS\Installer\InstallerAdapter; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; use Joomla\CMS\Table\Update; use Joomla\Database\ParameterType; use Joomla\Filesystem\File; @@ -163,8 +163,7 @@ protected function createExtensionRoot() protected function finaliseInstall() { // Clobber any possible pending updates - /** @var Update $update */ - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ 'element' => $this->element, @@ -206,7 +205,7 @@ protected function finaliseUninstall(): bool $db = $this->getDatabase(); // Remove the schema version - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete('#__schemas') ->where('extension_id = :extension_id') ->bind(':extension_id', $extensionId, ParameterType::INTEGER); @@ -545,7 +544,7 @@ public function discover() $element = empty($manifest_details['filename']) ? $file : $manifest_details['filename']; - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'plugin'; $extension->client_id = 0; $extension->element = $element; @@ -575,7 +574,7 @@ public function discover() $element = empty($manifest_details['filename']) ? $file : $manifest_details['filename']; // Ignore example plugins - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'plugin'; $extension->client_id = 0; $extension->element = $element; diff --git a/libraries/src/Installer/Adapter/TemplateAdapter.php b/libraries/src/Installer/Adapter/TemplateAdapter.php index b3f4444736c54..0af93bed7c80a 100644 --- a/libraries/src/Installer/Adapter/TemplateAdapter.php +++ b/libraries/src/Installer/Adapter/TemplateAdapter.php @@ -15,7 +15,7 @@ use Joomla\CMS\Installer\InstallerAdapter; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Extension; use Joomla\CMS\Table\Update; use Joomla\Database\ParameterType; use Joomla\Filesystem\Folder; @@ -140,8 +140,7 @@ protected function copyBaseFiles() protected function finaliseInstall() { // Clobber any possible pending updates - /** @var Update $update */ - $update = Table::getInstance('update'); + $update = new Update($this->getDatabase()); $uid = $update->find( [ @@ -180,14 +179,14 @@ protected function finaliseInstall() protected function finaliseUninstall(): bool { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $element = $this->extension->element; $clientId = $this->extension->client_id; $extensionId = $this->extension->extension_id; // Set menu that assigned to the template back to default template - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select($db->quoteName('s.id')) ->from($db->quoteName('#__template_styles', 's')) ->where( @@ -208,7 +207,7 @@ protected function finaliseUninstall(): bool $db->execute(); // Remove the template's styles - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__template_styles')) ->where( [ @@ -222,7 +221,7 @@ protected function finaliseUninstall(): bool $db->execute(); // Remove the schema version - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__schemas')) ->where($db->quoteName('extension_id') . ' = :extension_id') ->bind(':extension_id', $extensionId, ParameterType::INTEGER); @@ -230,7 +229,7 @@ protected function finaliseUninstall(): bool $db->execute(); // Remove any overrides - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__template_overrides')) ->where($db->quoteName('template') . ' = :template') ->bind(':template', $element); @@ -238,7 +237,7 @@ protected function finaliseUninstall(): bool $db->execute(); // Clobber any possible pending updates - $update = Table::getInstance('update'); + $update = new Update($db); $uid = $update->find( [ 'element' => $this->extension->element, @@ -315,7 +314,7 @@ protected function parseQueries() { if (\in_array($this->route, ['install', 'discover_install'])) { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $lang = Factory::getLanguage(); $debug = $lang->setDebug(false); @@ -463,7 +462,7 @@ protected function setupUninstall() } // Deny removing a parent template if there are children - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__template_styles')) ->where( @@ -481,7 +480,7 @@ protected function setupUninstall() } // Deny remove default template - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName('#__template_styles')) ->where( @@ -622,7 +621,7 @@ public function discover() } $manifest_details = Installer::parseXMLInstallFile(JPATH_SITE . "/templates/$template/templateDetails.xml"); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'template'; $extension->client_id = $site_info->id; $extension->element = $template; @@ -643,7 +642,7 @@ public function discover() } $manifest_details = Installer::parseXMLInstallFile(JPATH_ADMINISTRATOR . "/templates/$template/templateDetails.xml"); - $extension = Table::getInstance('extension'); + $extension = new Extension($this->getDatabase()); $extension->type = 'template'; $extension->client_id = $admin_info->id; $extension->element = $template; diff --git a/libraries/src/Installer/Installer.php b/libraries/src/Installer/Installer.php index c0004580d9a68..a2f62883bf9db 100644 --- a/libraries/src/Installer/Installer.php +++ b/libraries/src/Installer/Installer.php @@ -9,7 +9,6 @@ namespace Joomla\CMS\Installer; -use Joomla\CMS\Adapter\Adapter; use Joomla\CMS\Application\ApplicationHelper; use Joomla\CMS\Event\Extension\AfterInstallEvent; use Joomla\CMS\Event\Extension\AfterUninstallEvent; @@ -20,6 +19,8 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; +use Joomla\CMS\Object\LegacyErrorHandlingTrait; +use Joomla\CMS\Object\LegacyPropertyManagementTrait; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Table\Extension; use Joomla\CMS\Table\Table; @@ -42,9 +43,35 @@ * * @since 3.1 */ -class Installer extends Adapter implements DatabaseAwareInterface +class Installer implements DatabaseAwareInterface { use DatabaseAwareTrait; + use LegacyErrorHandlingTrait; + use LegacyPropertyManagementTrait; + + /** + * Array of installer adapters + * + * @var string[]|InstallerAdapter[] + * @since 6.0.0 + */ + private $adapters = []; + + /** + * Adapter Class Prefix + * + * @var string + * @since 6.0.0 + */ + private $classprefix = '\\Joomla\\CMS\\Installer\\Adapter'; + + /** + * Base Path for the installer adapters + * + * @var string + * @since 6.0.0 + */ + private $adapterfolder; /** * Array of paths needed by the installer @@ -176,9 +203,11 @@ class Installer extends Adapter implements DatabaseAwareInterface */ public function __construct($basepath = __DIR__, $classprefix = '\\Joomla\\CMS\\Installer\\Adapter', $adapterfolder = 'Adapter') { - parent::__construct($basepath, $classprefix, $adapterfolder); + $this->adapterfolder = $basepath . '/' . $adapterfolder; + $this->classprefix = $classprefix; + $this->loadAdapters(); - $this->extension = Table::getInstance('extension'); + $this->extension = Table::getInstance('Extension'); } /** @@ -551,7 +580,7 @@ public function abort($msg = null, $type = null) case 'extension': // Get database connector object $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $stepId = (int) $step['id']; // Remove the entry from the #__extensions table @@ -574,13 +603,20 @@ public function abort($msg = null, $type = null) break; default: - if ($type && \is_object($this->_adapters[$type])) { + if ($type) { + try { + $adapter = $this->getAdapter($type); + } catch (\InvalidArgumentException $e) { + $stepval = false; + break; + } + // Build the name of the custom rollback method for the type $method = '_rollback_' . $step['type']; // Custom rollback method handler - if (method_exists($this->_adapters[$type], $method)) { - $stepval = $this->_adapters[$type]->$method($step); + if (method_exists($adapter, $method)) { + $stepval = $adapter->$method($step); } } else { // Set it to false @@ -703,7 +739,7 @@ public function discover_install($eid = null) $type = $this->extension->type; $params = ['extension' => $this->extension, 'route' => 'discover_install']; - $adapter = $this->loadAdapter($type, $params); + $adapter = $this->getAdapter($type, $params); if (!\is_object($adapter)) { return false; @@ -775,7 +811,7 @@ public function discover() $results = []; foreach ($this->getAdapters() as $adapter) { - $instance = $this->loadAdapter($adapter); + $instance = $this->getAdapter($adapter); // Joomla! 1.5 installation adapter legacy support if (method_exists($instance, 'discover')) { @@ -865,7 +901,7 @@ public function uninstall($type, $identifier) { $params = ['extension' => $this->extension, 'route' => 'uninstall']; - $adapter = $this->loadAdapter($type, $params); + $adapter = $this->getAdapter($type, $params); if (!\is_object($adapter)) { return false; @@ -921,7 +957,7 @@ public function refreshManifestCache($eid) } // Fetch the adapter - $adapter = $this->loadAdapter($this->extension->type); + $adapter = $this->getAdapter($this->extension->type); if (!\is_object($adapter)) { return false; @@ -972,7 +1008,11 @@ public function setupInstall($route = 'install', $returnAdapter = false) $params = ['route' => $route, 'manifest' => $this->getManifest()]; // Load the adapter - $adapter = $this->loadAdapter($type, $params); + $adapter = $this->getAdapter($type, $params); + + // Ensure cached adapter always points to the current extension + $adapter->setManifest($params['manifest']); + $adapter->setRoute($params['route']); if ($returnAdapter) { return $adapter; @@ -994,7 +1034,7 @@ public function setupInstall($route = 'install', $returnAdapter = false) public function parseQueries(\SimpleXMLElement $element) { // Get the database connector object - $db = & $this->_db; + $db = $this->getDatabase(); if (!$element || !\count($element->children())) { // Either the tag does not exist or has no children therefore we return zero files processed. @@ -1043,7 +1083,7 @@ public function parseSQLFiles($element) return 0; } - $db = &$this->_db; + $db = $this->getDatabase(); $dbDriver = $db->getServerType(); $updateCount = 0; @@ -1150,7 +1190,7 @@ public function setSchemaVersion(\SimpleXMLElement $schema, $eid) usort($files, 'version_compare'); // Update the database - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete('#__schemas') ->where('extension_id = :extension_id') ->bind(':extension_id', $eid, ParameterType::INTEGER); @@ -1236,7 +1276,7 @@ public function parseSchemaUpdates(\SimpleXMLElement $schema, $eid) $files = str_replace('.sql', '', $files); usort($files, 'version_compare'); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('version_id') ->from('#__schemas') ->where('extension_id = :extension_id') @@ -1365,7 +1405,7 @@ protected function updateSchemaTable(int $eid, string $version, bool $update = f */ $db->transactionStart(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete('#__schemas') ->where('extension_id = :extension_id') ->bind(':extension_id', $eid, ParameterType::INTEGER); @@ -2120,7 +2160,7 @@ public function generateManifestCache() public function cleanDiscoveredExtension($type, $element, $folder = '', $client = 0) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__extensions')) ->where('type = :type') ->where('element = :element') @@ -2349,25 +2389,21 @@ public static function parseXMLInstallFile($path) } /** - * Gets a list of available install adapters. + * Discover all adapters in the adapterfolder path * - * @param array $options An array of options to inject into the adapter - * @param array $custom Array of custom install adapters - * - * @return string[] An array of the class names of available install adapters. + * @return void * - * @since 3.4 + * @since 6.0.0 */ - public function getAdapters($options = [], array $custom = []) + protected function loadAdapters() { - $files = new \DirectoryIterator($this->_basepath . '/' . $this->_adapterfolder); - $adapters = []; + $files = new \DirectoryIterator($this->adapterfolder); // Process the core adapters foreach ($files as $file) { $fileName = $file->getFilename(); - // Only load for php files. + // Only load php files. if (!$file->isFile() || $file->getExtension() !== 'php') { continue; } @@ -2375,17 +2411,17 @@ public function getAdapters($options = [], array $custom = []) // Derive the class name from the filename. $name = str_ireplace('.php', '', trim($fileName)); $name = str_ireplace('adapter', '', trim($name)); - $class = rtrim($this->_classprefix, '\\') . '\\' . ucfirst($name) . 'Adapter'; + $class = rtrim($this->classprefix, '\\') . '\\' . ucfirst($name) . 'Adapter'; if (!class_exists($class)) { // Not namespaced - $class = $this->_classprefix . ucfirst($name); + $class = $this->classprefix . ucfirst($name); } // Core adapters should autoload based on classname, keep this fallback just in case if (!class_exists($class)) { // Try to load the adapter object - \JLoader::register($class, $this->_basepath . '/' . $this->_adapterfolder . '/' . $fileName); + \JLoader::register($class, $this->adapterfolder . '/' . $fileName); if (!class_exists($class)) { // Skip to next one @@ -2393,66 +2429,124 @@ public function getAdapters($options = [], array $custom = []) } } - $adapters[] = $name; + $this->adapters[strtolower($name)] = $class; } + } - // Add any custom adapters if specified - if (\count($custom) >= 1) { + /** + * Gets a list of available install adapters. + * + * @param array $options An array of options to inject into the adapter + * @param array $custom Array of custom install adapters + * + * @return string[] An array of the class names of available install adapters. + * + * @since 3.4 + */ + public function getAdapters($options = [], array $custom = []) + { + if (\count($custom)) { foreach ($custom as $adapter) { // Setup the class name // @todo - Can we abstract this to not depend on the Joomla class namespace without PHP namespaces? - $class = $this->_classprefix . ucfirst(trim($adapter)); + $class = $this->classprefix . ucfirst(trim($adapter)); // If the class doesn't exist we have nothing left to do but look at the next type. We did our best. if (!class_exists($class)) { continue; } - $adapters[] = str_ireplace('.php', '', $fileName); + $this->adapters[$adapter] = $class; } } - return $adapters; + return array_keys($this->adapters); } /** - * Method to load an adapter instance + * Get an install adapter instance * - * @param string $adapter Adapter name + * @param string $name Adapter name * @param array $options Adapter options * * @return InstallerAdapter * - * @since 3.4 * @throws \InvalidArgumentException + * @since 6.0.0 */ - public function loadAdapter($adapter, $options = []) + public function getAdapter($name, $options = []) { - $class = rtrim($this->_classprefix, '\\') . '\\' . ucfirst($adapter) . 'Adapter'; + $name = strtolower($name); - if (!class_exists($class)) { - // Not namespaced - $class = $this->_classprefix . ucfirst($adapter); + if (!isset($this->adapters[$name])) { + throw new \InvalidArgumentException(\sprintf('The %s install adapter does not exist.', $name)); } - if (!class_exists($class)) { - throw new \InvalidArgumentException(\sprintf('The %s install adapter does not exist.', $adapter)); + if (\is_string($this->adapters[$name])) { + $class = $this->adapters[$name]; + + // Ensure the adapter type is part of the options array + $options['type'] = $name; + + // Check for a possible service from the container otherwise manually instantiate the class + if (Factory::getContainer()->has($class)) { + return Factory::getContainer()->get($class); + } + + $adapter = new $class($this, $this->getDatabase(), $options); + + if ($adapter instanceof ContainerAwareInterface) { + $adapter->setContainer(Factory::getContainer()); + } + + $this->adapters[$name] = $adapter; } - // Ensure the adapter type is part of the options array - $options['type'] = $adapter; + return $this->adapters[$name]; + } - // Check for a possible service from the container otherwise manually instantiate the class - if (Factory::getContainer()->has($class)) { - return Factory::getContainer()->get($class); + /** + * Method to load an adapter instance + * + * @param string $adapter Adapter name + * @param array $options Adapter options + * + * @return InstallerAdapter + * + * @throws \InvalidArgumentException + * @since 3.4 + * @deprecated 6.0 will be removed in 8.0 + * Use getAdapter() instead + */ + public function loadAdapter($adapter, $options = []) + { + return $this->getAdapter($adapter, $options); + } + + /** + * Set an adapter by name + * + * @param string $name Adapter name + * @param InstallerAdapter|string $adapter Adapter object or class name + * + * @return boolean True if successful + * + * @since 6.0.0 + */ + public function setAdapter($name, $adapter) + { + if (\is_object($adapter)) { + $this->adapters[$name] = $adapter; + + return true; } - $adapter = new $class($this, $this->getDatabase(), $options); + if (class_exists($adapter)) { + $this->adapters[$name] = $adapter; - if ($adapter instanceof ContainerAwareInterface) { - $adapter->setContainer(Factory::getContainer()); + return true; } - return $adapter; + return false; } } diff --git a/libraries/src/Installer/InstallerAdapter.php b/libraries/src/Installer/InstallerAdapter.php index 944e188617c7c..b38bfbe0e7cc9 100644 --- a/libraries/src/Installer/InstallerAdapter.php +++ b/libraries/src/Installer/InstallerAdapter.php @@ -164,13 +164,13 @@ public function __construct(Installer $parent, DatabaseDriver $db, array $option // Get a generic TableExtension instance for use if not already loaded if (!($this->extension instanceof TableInterface)) { - $this->extension = Table::getInstance('extension'); + $this->extension = Table::getInstance('Extension'); } // Sanity check, make sure the type is set by taking the adapter name from the class name if (!$this->type) { // This assumes the adapter short class name in its namespace is `Adapter`, replace this logic in subclasses if needed - $reflection = new \ReflectionClass(\get_called_class()); + $reflection = new \ReflectionClass(static::class); $this->type = str_replace('Adapter', '', $reflection->getShortName()); } @@ -190,7 +190,7 @@ public function __construct(Installer $parent, DatabaseDriver $db, array $option */ protected function canUninstallPackageChild($packageId) { - $package = Table::getInstance('extension'); + $package = new Extension(Factory::getDbo()); // If we can't load this package ID, we have a corrupt database if (!$package->load((int) $packageId)) { @@ -958,7 +958,7 @@ protected function setupScriptfile() // Load the installer from the file if (!file_exists($manifestScriptFile)) { @trigger_error( - 'Installer file must exist when defined. In version 5.0 this will crash.', + 'Installer file must exist when defined. In version 7.0 this will crash.', E_USER_DEPRECATED ); @@ -983,7 +983,7 @@ protected function setupScriptfile() // When none is set, then use the legacy way if (!$container->has(InstallerScriptInterface::class)) { @trigger_error( - 'Legacy installer files are deprecated and will be removed in 6.0. Use a service provider instead.', + 'Legacy installer files are deprecated and will be removed in 7.0. Use a service provider instead.', E_USER_DEPRECATED ); @@ -1006,6 +1006,10 @@ function (Container $container) use ($classname) { // Create a new instance $this->parent->manifestClass = $container->get(InstallerScriptInterface::class); + if (method_exists($this->parent->manifestClass, 'setApplication')) { + $this->parent->manifestClass->setApplication(Factory::getApplication()); + } + // Set the database if ($this->parent->manifestClass instanceof DatabaseAwareInterface) { $this->parent->manifestClass->setDatabase($container->get(DatabaseInterface::class)); @@ -1281,7 +1285,7 @@ public function update() * * @since 4.2.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use getDatabase() instead of directly accessing _db */ public function __get($name) diff --git a/libraries/src/Installer/InstallerHelper.php b/libraries/src/Installer/InstallerHelper.php index 963c9bb7a2f2d..db864c96aa480 100644 --- a/libraries/src/Installer/InstallerHelper.php +++ b/libraries/src/Installer/InstallerHelper.php @@ -12,7 +12,6 @@ use Joomla\Archive\Archive; use Joomla\CMS\Event\Installer\BeforePackageDownloadEvent; use Joomla\CMS\Factory; -use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\Plugin\PluginHelper; @@ -21,6 +20,8 @@ use Joomla\Filesystem\File; use Joomla\Filesystem\Folder; use Joomla\Filesystem\Path; +use Joomla\Http\HttpFactory; +use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -85,8 +86,12 @@ public static function downloadPackage($url, $target = false) $url = $event->getArgument('url', $url); $headers = $event->getArgument('headers', $headers); + $options = new Registry(); + $options->set('userAgent', $version->getUserAgent('Joomla', true, false)); + + // Get the file try { - $response = HttpFactory::getHttp()->get($url, $headers); + $response = (new HttpFactory())->getHttp($options)->get($url, $headers); } catch (\RuntimeException $exception) { Log::add(Text::sprintf('JLIB_INSTALLER_ERROR_DOWNLOAD_SERVER_CONNECT', $exception->getMessage()), Log::WARNING, 'jerror'); diff --git a/libraries/src/Installer/InstallerScript.php b/libraries/src/Installer/InstallerScript.php index 9ab2b78d72843..6bbe30d41126d 100644 --- a/libraries/src/Installer/InstallerScript.php +++ b/libraries/src/Installer/InstallerScript.php @@ -175,7 +175,7 @@ public function getInstances($isModule) $extension = $this->extension; $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the item(s) and retrieve the id if ($isModule) { @@ -263,7 +263,7 @@ public function setParams($paramArray = null, $type = 'edit', $id = 0) $paramsString = json_encode($params); $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($this->paramTable)) ->set('params = :params') ->where($column . ' = :id') @@ -298,7 +298,7 @@ public function getItemArray($element, $table, $column, $identifier) $paramType = is_numeric($identifier) ? ParameterType::INTEGER : ParameterType::STRING; // Build the query - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName($element)) ->from($db->quoteName($table)) ->where($db->quoteName($column) . ' = :id') diff --git a/libraries/src/Installer/InstallerScriptTrait.php b/libraries/src/Installer/InstallerScriptTrait.php new file mode 100644 index 0000000000000..b92384f61a2fe --- /dev/null +++ b/libraries/src/Installer/InstallerScriptTrait.php @@ -0,0 +1,331 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Installer; + +use Joomla\CMS\Application\ApplicationHelper; +use Joomla\CMS\Application\CMSApplicationInterface; +use Joomla\CMS\Language\Text; +use Joomla\CMS\Log\Log; +use Joomla\Filesystem\File; +use Joomla\Filesystem\Folder; +use Joomla\Filesystem\Path; + +trait InstallerScriptTrait +{ + /** + * The extension name. This should be set in the installer script. + * + * @var string + * @since 6.0.0 + */ + protected string $extension; + + /** + * Minimum PHP version required to install the extension + * + * @var string + * @since 6.0.0 + */ + protected string $minimumPhp; + + /** + * Minimum Joomla! version required to install the extension + * + * @var string + * @since 6.0.0 + */ + protected string $minimumJoomla; + + /** + * Allow downgrades of your extension + * + * Use at your own risk as if there is a change in functionality people may wish to downgrade. + * + * @var boolean + * @since 6.0.0 + */ + protected bool $allowDowngrades = false; + + /** + * A list of files to be deleted + * + * @var array + * @since 6.0.0 + */ + protected array $deleteFiles = []; + + /** + * A list of folders to be deleted + * + * @var array + * @since 6.0.0 + */ + protected array $deleteFolders = []; + + /** + * The application object + * + * @var CMSApplicationInterface + * + * @since 6.0.0 + */ + private CMSApplicationInterface $application; + + /** + * Function called after the extension is installed. + * + * @param InstallerAdapter $adapter The adapter calling this method + * + * @return boolean True on success + * + * @since 6.0.0 + */ + public function install(InstallerAdapter $adapter): bool + { + return true; + } + + /** + * Function called after the extension is updated. + * + * @param InstallerAdapter $adapter The adapter calling this method + * + * @return boolean True on success + * + * @since 6.0.0 + */ + public function update(InstallerAdapter $adapter): bool + { + return true; + } + + /** + * Function called after the extension is uninstalled. + * + * @param InstallerAdapter $adapter The adapter calling this method + * + * @return boolean True on success + * + * @since 6.0.0 + */ + public function uninstall(InstallerAdapter $adapter): bool + { + return true; + } + + /** + * Function called before extension installation/update/removal procedure commences. + * + * @param string $type The type of change (install or discover_install, update, uninstall) + * @param InstallerAdapter $adapter The adapter calling this method + * + * @return boolean True on success + * + * @since 6.0.0 + */ + public function preflight(string $type, InstallerAdapter $adapter): bool + { + $this->extension = $adapter->getName(); + + if (!$this->checkCompatibility($type, $adapter)) { + return false; + } + + if (!$this->checkDowngrade($type, $adapter)) { + return false; + } + + return true; + } + + /** + * Function called after extension installation/update/removal procedure commences. + * + * @param string $type The type of change (install or discover_install, update, uninstall) + * @param InstallerAdapter $adapter The adapter calling this method + * + * @return boolean True on success + * + * @since 6.0.0 + */ + public function postflight(string $type, InstallerAdapter $adapter): bool + { + $this->removeFiles(); + + return true; + } + + /** + * Check if the extension passes the minimum requirements to be installed + * + * @return boolean True on success + * + * @since 6.0.0 + */ + protected function checkCompatibility(string $type, InstallerAdapter $adapter): bool + { + // Check for the minimum PHP version before continuing + if (!empty($this->minimumPhp) && version_compare(PHP_VERSION, $this->minimumPhp, '<')) { + Log::add(Text::sprintf('JLIB_INSTALLER_MINIMUM_PHP', $this->minimumPhp), Log::WARNING, 'jerror'); + + return false; + } + + // Check for the minimum Joomla version before continuing + if (!empty($this->minimumJoomla) && version_compare(JVERSION, $this->minimumJoomla, '<')) { + Log::add(Text::sprintf('JLIB_INSTALLER_MINIMUM_JOOMLA', $this->minimumJoomla), Log::WARNING, 'jerror'); + + return false; + } + + return true; + } + + /** + * Check if the extension is allowed to be downgraded + * + * @return boolean False when downgrade not allowed and new version is lower than old version otherwise true + * + * @since 6.0.0 + */ + protected function checkDowngrade(string $type, InstallerAdapter $adapter): bool + { + if ($type !== 'update' || $this->allowDowngrades) { + return true; + } + + $oldManifest = $this->getOldManifest($adapter); + + if ($oldManifest !== null && $oldManifest->version && version_compare($oldManifest->version, $adapter->getManifest()->version, '>')) { + Log::add(Text::_('JLIB_INSTALLER_ERROR_DOWNGRADE'), Log::WARNING, 'jerror'); + + return false; + } + + return true; + } + + /** + * Returns the manifest file if it exists or null + * + * @param InstallerAdapter $adapter + * + * @return SimpleXMLElement|null + * + * @since 6.0.0 + */ + protected function getOldManifest(InstallerAdapter $adapter): ?\SimpleXMLElement + { + $client = ApplicationHelper::getClientInfo('administrator', true); + + $pathname = 'extension_' . $client->name; + + $manifestPath = $adapter->getParent()->getPath($pathname) . '/' . $adapter->getParent()->getPath('manifest'); + + return is_file($manifestPath) ? $adapter->getParent()->isManifest($manifestPath) : null; + } + + /** + * Remove the files and folders in the given array from + * + * @return void + * + * @since 6.0.0 + */ + protected function removeFiles(): void + { + if (!empty($this->deleteFiles)) { + foreach ($this->deleteFiles as $file) { + if (is_file(Path::check(JPATH_ROOT . $file)) && !File::delete(JPATH_ROOT . $file)) { + Log::add(Text::sprintf('JLIB_INSTALLER_ERROR_FILE_FOLDER', $file)); + } + } + } + + if (!empty($this->deleteFolders)) { + foreach ($this->deleteFolders as $folder) { + if (is_dir(Path::check(JPATH_ROOT . $folder)) && !Folder::delete(JPATH_ROOT . $folder)) { + Log::add(Text::sprintf('JLIB_INSTALLER_ERROR_FILE_FOLDER', $folder)); + } + } + } + } + + /** + * Returns the internal application or null when not set. + * + * @return CMSApplicationInterface|null + * + * @since 6.0.0 + */ + protected function getApplication(): ?CMSApplicationInterface + { + return $this->application; + } + + /** + * Sets the application to use. + * + * @param CMSApplicationInterface $application The application + * + * @return void + * + * @since 6.0.0 + */ + public function setApplication(CMSApplicationInterface $application): void + { + $this->application = $application; + } + + /** + * Creates the dashboard menu module + * + * @param string $dashboard The name of the dashboard + * @param string $preset The name of the menu preset + * + * @return void + * + * @throws \Exception + * @since 6.0.0 + */ + protected function addDashboardMenuModule(string $dashboard, string $preset) + { + $model = $this->getApplication()->bootComponent('com_modules')->getMVCFactory()->createModel('Module', 'Administrator', ['ignore_request' => true]); + $module = [ + 'id' => 0, + 'asset_id' => 0, + 'language' => '*', + 'note' => '', + 'published' => 1, + 'assignment' => 0, + 'client_id' => 1, + 'showtitle' => 0, + 'content' => '', + 'module' => 'mod_submenu', + 'position' => 'cpanel-' . $dashboard, + ]; + + // Try to get a translated module title, otherwise fall back to a fixed string. + $titleKey = strtoupper('COM_' . $this->extension . '_DASHBOARD_' . $dashboard . '_TITLE'); + $title = Text::_($titleKey); + $module['title'] = ($title === $titleKey) ? ucfirst($dashboard) . ' Dashboard' : $title; + + $module['access'] = (int) $this->getApplication()->get('access', 1); + $module['params'] = [ + 'menutype' => '*', + 'preset' => $preset, + 'style' => 'System-none', + ]; + + if (!$model->save($module)) { + $this->getApplication()->enqueueMessage(Text::sprintf('JLIB_INSTALLER_ERROR_COMP_INSTALL_FAILED_TO_CREATE_DASHBOARD', $model->getError())); + } + } +} diff --git a/libraries/src/Installer/LegacyInstallerScript.php b/libraries/src/Installer/LegacyInstallerScript.php index df655e9959708..2a41433c64a95 100644 --- a/libraries/src/Installer/LegacyInstallerScript.php +++ b/libraries/src/Installer/LegacyInstallerScript.php @@ -180,7 +180,7 @@ private function callOnScript(string $name, array $arguments): bool try { $this->installerScript->setDatabase($this->getDatabase()); } catch (DatabaseNotFoundException) { - @trigger_error(\sprintf('Database must be set, this will not be caught anymore in 6.0 in %s.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(\sprintf('Database must be set, this will not be caught anymore in 7.0 in %s.', __METHOD__), E_USER_DEPRECATED); $this->installerScript->setDatabase(Factory::getContainer()->get(DatabaseInterface::class)); } } diff --git a/libraries/src/Language/Associations.php b/libraries/src/Language/Associations.php index 34e993e0422a2..b1d3032efa4b0 100644 --- a/libraries/src/Language/Associations.php +++ b/libraries/src/Language/Associations.php @@ -11,8 +11,8 @@ use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; -use Joomla\Database\ParameterType; use Joomla\Registry\Registry; +use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -28,16 +28,16 @@ class Associations /** * Get the associations. * - * @param string $extension The name of the component. - * @param string $tablename The name of the table. - * @param string $context The context - * @param integer $id The primary key value. - * @param string $pk The name of the primary key in the given $table. - * @param string $aliasField If the table has an alias field set it here. Null to not use it - * @param string $catField If the table has a catid field set it here. Null to not use it - * @param array $advClause Additional advanced 'where' clause; use c as parent column key, c2 as associations column key + * @param string $extension The name of the component. + * @param string $tablename The name of the table. + * @param string $context The context + * @param int|int[] $id The primary key value or array of primary keys. + * @param string $pk The name of the primary key in the given $table. + * @param string $aliasField If the table has an alias field set it here. Null to not use it + * @param string $catField If the table has a catid field set it here. Null to not use it + * @param array $advClause Additional advanced 'where' clause; use c as parent column key, c2 as associations column key * - * @return array The associated items + * @return array The associated items, optionally grouped by primary key. * * @since 3.1 * @@ -56,17 +56,14 @@ public static function getAssociations( // To avoid doing duplicate database queries. static $multilanguageAssociations = []; - // Cast before creating cache key. - $id = (int) $id; - // Multilanguage association array key. If the key is already in the array we don't need to run the query again, just return it. - $queryKey = md5(serialize(array_merge([$extension, $tablename, $context, $id], $advClause))); + $queryKey = md5(serialize(array_merge([$extension, $tablename, $context, print_r($id, true)], $advClause))); if (!isset($multilanguageAssociations[$queryKey])) { $multilanguageAssociations[$queryKey] = []; $db = Factory::getDbo(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $categoriesExtraSql = ''; if ($tablename === '#__categories') { @@ -74,7 +71,7 @@ public static function getAssociations( $query->bind(':extension1', $extension); } - $query->select($db->quoteName('c2.language')) + $query->select([$db->quoteName('c2.language'), $db->quoteName('c.' . $pk) . ' AS ' . $db->quoteName('pk')]) ->from($db->quoteName($tablename, 'c')) ->join( 'INNER', @@ -124,8 +121,9 @@ public static function getAssociations( ); } - $query->where($db->quoteName('c.' . $pk) . ' = :id') - ->bind(':id', $id, ParameterType::INTEGER); + $ids = ArrayHelper::toInteger((array) $id); + + $query->where($db->quoteName('c.' . $pk) . 'IN(' . implode(',', $query->bindArray($ids)) . ')'); if ($tablename === '#__categories') { $query->where($db->quoteName('c.extension') . ' = :extension3') @@ -141,17 +139,33 @@ public static function getAssociations( $db->setQuery($query); - try { - $items = $db->loadObjectList('language'); - } catch (\RuntimeException $e) { - throw new \Exception($e->getMessage(), 500, $e); - } + if (\is_array($id)) { + try { + $items = $db->loadObjectList(); + } catch (\RuntimeException $e) { + throw new \Exception($e->getMessage(), 500, $e); + } - if ($items) { - foreach ($items as $tag => $item) { + // Group by id + foreach ($items as $item) { // Do not return itself as result if ((int) $item->{$pk} !== $id) { - $multilanguageAssociations[$queryKey][$tag] = $item; + $multilanguageAssociations[$queryKey][$item->pk][$item->language] = $item; + } + } + } else { + try { + $items = $db->loadObjectList('language'); + } catch (\RuntimeException $e) { + throw new \Exception($e->getMessage(), 500, $e); + } + + if ($items) { + foreach ($items as $tag => $item) { + // Do not return itself as result + if ((int) $item->{$pk} !== $id) { + $multilanguageAssociations[$queryKey][$tag] = $item; + } } } } @@ -176,17 +190,17 @@ public static function isEnabled() // Status of language filter parameter. static $enabled = false; - if (Multilanguage::isEnabled()) { - // If already tested, don't test again. - if (!$tested) { + // If already tested, don't test again. + if (!$tested) { + $tested = true; + + if (Multilanguage::isEnabled()) { $plugin = PluginHelper::getPlugin('system', 'languagefilter'); if (!empty($plugin)) { $params = new Registry($plugin->params); $enabled = (bool) $params->get('item_associations', true); } - - $tested = true; } } diff --git a/libraries/src/Language/Language.php b/libraries/src/Language/Language.php index 7c2089f7a5867..8e70048bb05e5 100644 --- a/libraries/src/Language/Language.php +++ b/libraries/src/Language/Language.php @@ -9,6 +9,7 @@ namespace Joomla\CMS\Language; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\Language\Language as BaseLanguage; use Joomla\String\StringHelper; @@ -40,6 +41,22 @@ class Language extends BaseLanguage */ protected $strings = []; + /** + * Cached fallback chains, keyed by language tag. + * + * @var array + * @since 6.2.0 + */ + protected $fallbackChains = []; + + /** + * Cached admin fallback overrides (language tag => fallback tag), or null until first read. + * + * @var array|null + * @since 6.2.0 + */ + protected $fallbackOverrides = null; + /** * Name of the transliterator function for this language. * @@ -62,7 +79,7 @@ class Language extends BaseLanguage * @var callable * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ protected $ignoredSearchWordsCallback = null; @@ -72,7 +89,7 @@ class Language extends BaseLanguage * @var callable * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ protected $lowerLimitSearchWordCallback = null; @@ -82,7 +99,7 @@ class Language extends BaseLanguage * @var callable * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ protected $upperLimitSearchWordCallback = null; @@ -92,7 +109,7 @@ class Language extends BaseLanguage * @var callable * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ protected $searchDisplayedCharactersNumberCallback = null; @@ -204,7 +221,7 @@ public function __construct($lang = null, $debug = false) * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the language factory instead * Example: Factory::getContainer()->get(LanguageFactoryInterface::class)->createLanguage($lang, $debug); */ @@ -406,7 +423,7 @@ public function setPluralSuffixesCallback(callable $function) * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function getIgnoredSearchWords() { @@ -424,7 +441,7 @@ public function getIgnoredSearchWords() * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function getIgnoredSearchWordsCallback() { @@ -440,7 +457,7 @@ public function getIgnoredSearchWordsCallback() * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function setIgnoredSearchWordsCallback(callable $function) { @@ -457,7 +474,7 @@ public function setIgnoredSearchWordsCallback(callable $function) * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function getLowerLimitSearchWord() { @@ -475,7 +492,7 @@ public function getLowerLimitSearchWord() * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function getLowerLimitSearchWordCallback() { @@ -491,7 +508,7 @@ public function getLowerLimitSearchWordCallback() * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function setLowerLimitSearchWordCallback(callable $function) { @@ -508,7 +525,7 @@ public function setLowerLimitSearchWordCallback(callable $function) * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function getUpperLimitSearchWord() { @@ -526,7 +543,7 @@ public function getUpperLimitSearchWord() * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function getUpperLimitSearchWordCallback() { @@ -542,7 +559,7 @@ public function getUpperLimitSearchWordCallback() * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function setUpperLimitSearchWordCallback(callable $function) { @@ -559,7 +576,7 @@ public function setUpperLimitSearchWordCallback(callable $function) * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function getSearchDisplayedCharactersNumber() { @@ -577,7 +594,7 @@ public function getSearchDisplayedCharactersNumber() * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function getSearchDisplayedCharactersNumberCallback() { @@ -593,7 +610,7 @@ public function getSearchDisplayedCharactersNumberCallback() * * @since 1.7.0 * - * @deprecated 4.4 will be removed in 6.0 without replacement + * @deprecated 4.4 will be removed in 7.0 without replacement */ public function setSearchDisplayedCharactersNumberCallback(callable $function) { @@ -629,6 +646,13 @@ public function load($extension = 'joomla', $basePath = JPATH_BASE, $lang = null $this->load($extension, $basePath, $this->default, false, true); } + // Load the fallback chain next, weakest first, so missing strings are filled per key. + if (!$this->debug) { + foreach (array_reverse($this->getFallbackChain($lang)) as $fallbackLang) { + $this->load($extension, $basePath, $fallbackLang, $reload, false); + } + } + $path = LanguageHelper::getLanguagePath($basePath, $lang); $internal = $extension === 'joomla' || $extension == ''; @@ -661,6 +685,86 @@ public function load($extension = 'joomla', $basePath = JPATH_BASE, $lang = null return false; } + /** + * Resolves the ordered fallback chain for a language tag, strongest first. + * + * The fallback of a tag is taken from the com_languages override, else from the optional + * element of its langmetadata.xml. The chain stops at a language without a fallback, + * the site default, or a cycle, and excludes both the requested language and the site default. + * + * @param string $lang The language tag to resolve the fallback chain for. + * + * @return string[] Ordered list of fallback language tags, strongest first. + * + * @since 6.2.0 + */ + protected function getFallbackChain($lang) + { + if (isset($this->fallbackChains[$lang])) { + return $this->fallbackChains[$lang]; + } + + $chain = []; + $seen = [$lang => true]; + $next = $lang; + $overrides = $this->getFallbackOverrides(); + + while (true) { + if (isset($overrides[$next])) { + $fallback = $overrides[$next]; + } else { + $metadata = ($next === $this->lang ? $this->metadata : LanguageHelper::getMetadata($next)) ?: []; + $fallback = $metadata['fallback'] ?? ''; + } + + if ($fallback === '' || $fallback === $this->default || isset($seen[$fallback])) { + break; + } + + $chain[] = $fallback; + $seen[$fallback] = true; + $next = $fallback; + } + + $this->fallbackChains[$lang] = $chain; + + return $chain; + } + + /** + * Reads and caches the administrator fallback overrides (tag => fallback) from the + * com_languages options. Returns an empty map when the component parameters are not yet available. + * + * @return array Map of language tag => fallback tag. + * + * @since 6.2.0 + */ + protected function getFallbackOverrides() + { + if ($this->fallbackOverrides !== null) { + return $this->fallbackOverrides; + } + + $this->fallbackOverrides = []; + + try { + $overrides = ComponentHelper::getParams('com_languages')->get('fallback_overrides'); + } catch (\Throwable $e) { + return $this->fallbackOverrides; + } + + foreach ((array) $overrides as $override) { + $tag = trim((string) ($override->tag ?? '')); + $fallback = trim((string) ($override->fallback ?? '')); + + if ($tag !== '' && $fallback !== '') { + $this->fallbackOverrides[$tag] = $fallback; + } + } + + return $this->fallbackOverrides; + } + /** * Loads a language file. * diff --git a/libraries/src/Language/LanguageFactoryAwareInterface.php b/libraries/src/Language/LanguageFactoryAwareInterface.php new file mode 100644 index 0000000000000..9fe91526c8e24 --- /dev/null +++ b/libraries/src/Language/LanguageFactoryAwareInterface.php @@ -0,0 +1,33 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Language; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Interface to be implemented by classes depending on a language factory. + * + * @since 6.2.0 + */ +interface LanguageFactoryAwareInterface +{ + /** + * Set the language factory to use. + * + * @param ?LanguageFactoryInterface $languageFactory The language factory to use. + * + * @return void + * + * @since 6.2.0 + */ + public function setLanguageFactory(?LanguageFactoryInterface $languageFactory = null): void; +} diff --git a/libraries/src/Language/LanguageFactoryAwareTrait.php b/libraries/src/Language/LanguageFactoryAwareTrait.php new file mode 100644 index 0000000000000..7bf010931b229 --- /dev/null +++ b/libraries/src/Language/LanguageFactoryAwareTrait.php @@ -0,0 +1,68 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Language; + +use Joomla\CMS\Factory; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Defines the trait for a LanguageFactoryInterface aware class. + * + * @since 6.2.0 + */ +trait LanguageFactoryAwareTrait +{ + /** + * LanguageFactoryInterface + * + * @var LanguageFactoryInterface + * @since 6.2.0 + */ + private $languageFactory; + + /** + * Get the LanguageFactoryInterface. + * + * @return LanguageFactoryInterface + * + * @since 6.2.0 + * @throws \UnexpectedValueException May be thrown if the LanguageFactory has not been set. + */ + protected function getLanguageFactory(): LanguageFactoryInterface + { + if ($this->languageFactory) { + return $this->languageFactory; + } + + @trigger_error( + \sprintf('LanguageFactory must be set in %s. This will not be caught anymore in 8.0', __METHOD__), + E_USER_DEPRECATED + ); + + return Factory::getContainer()->get(LanguageFactoryInterface::class); + } + + /** + * Set the language factory to use. + * + * @param ?LanguageFactoryInterface $languageFactory The language factory to use. + * + * @return void + * + * @since 6.2.0 + */ + public function setLanguageFactory(?LanguageFactoryInterface $languageFactory = null): void + { + $this->languageFactory = $languageFactory; + } +} diff --git a/libraries/src/Language/LanguageHelper.php b/libraries/src/Language/LanguageHelper.php index 0a366ece2ed7a..4ea01ea0bfbc1 100644 --- a/libraries/src/Language/LanguageHelper.php +++ b/libraries/src/Language/LanguageHelper.php @@ -15,7 +15,9 @@ use Joomla\CMS\Installer\Installer; use Joomla\CMS\Log\Log; use Joomla\Database\DatabaseInterface; +use Joomla\Filesystem\Exception\FilesystemException; use Joomla\Filesystem\File; +use Joomla\Filesystem\Folder; use Joomla\Registry\Registry; use Joomla\Utilities\ArrayHelper; @@ -111,6 +113,11 @@ public static function detectLanguage() $browserLang = substr($browserLang, 0, strcspn($browserLang, ';')); $primary_browserLang = substr($browserLang, 0, 2); + // Some browser return only "fr" or "de", so let's try to use it like "fr-fr" or "de-de" + if (\strlen($browserLang) == 2) { + $browserLang = $browserLang . '-' . $browserLang; + } + foreach ($systemLangs as $systemLang) { // Take off 3 letters iso code languages as they can't match browsers' languages and default them to en $Jinstall_lang = $systemLang->lang_code; @@ -169,7 +176,7 @@ public static function getLanguages($key = 'default') $languages = $cache->get('languages'); } else { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__languages')) ->where($db->quoteName('published') . ' = 1') @@ -231,7 +238,7 @@ public static function getInstalledLanguages( } else { $db ??= Factory::getContainer()->get(DatabaseInterface::class); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ $db->quoteName('element'), @@ -380,7 +387,7 @@ public static function getContentLanguages( } else { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__languages')); @@ -444,6 +451,23 @@ public static function parseIniFile($fileName, $debug = false) return []; } + $cacheFile = JPATH_CACHE . '/language/' . ltrim(str_replace([JPATH_ROOT, '/'], ['', '-'], $fileName), '-') . '.' . filemtime($fileName) . '.php'; + + if (is_file($cacheFile)) { + $result = include $cacheFile; + + if (\is_array($result)) { + return $result; + } + + // When $result is not an array, the cache file is corrupted, we will delete it and have it regenerated + try { + File::delete($cacheFile); + } catch (FilesystemException $e) { + // We ignore the error, as the file is for caching only. + } + } + // This was required for https://github.com/joomla/joomla-cms/issues/17198 but not sure what server setup // issue it is solving $disabledFunctions = explode(',', \ini_get('disable_functions')); @@ -471,10 +495,40 @@ public static function parseIniFile($fileName, $debug = false) restore_error_handler(); } + if (!\is_array($strings)) { + $strings = []; + } + // Ini files are processed in the "RAW" mode of parse_ini_string, leaving escaped quotes untouched - lets postprocess them $strings = str_replace('\"', '"', $strings); - return \is_array($strings) ? $strings : []; + // Write cache + try { + Folder::create(\dirname($cacheFile)); + + $data = "getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('enabled')) ->from($db->quoteName('#__extensions')) ->where( @@ -89,40 +91,15 @@ public static function isEnabled(?CMSApplication $app = null, ?DatabaseInterface /** * Method to return a list of language home page menu items. * - * @param ?DatabaseInterface $db The database - * - * @return array of menu objects. + * @return MenuItem[] array of menu item objects. * * @since 3.5 */ - public static function getSiteHomePages(?DatabaseInterface $db = null) + public static function getSiteHomePages() { - // To avoid doing duplicate database queries. - static $multilangSiteHomePages = null; - - if (!isset($multilangSiteHomePages)) { - // Check for Home pages languages. - $db = $db ?: Factory::getDbo(); - $query = $db->getQuery(true) - ->select( - [ - $db->quoteName('language'), - $db->quoteName('id'), - ] - ) - ->from($db->quoteName('#__menu')) - ->where( - [ - $db->quoteName('home') . ' = ' . $db->quote('1'), - $db->quoteName('published') . ' = 1', - $db->quoteName('client_id') . ' = 0', - ] - ); - $db->setQuery($query); - - $multilangSiteHomePages = $db->loadObjectList('language'); - } + /** @var SiteMenu $menu */ + $menu = Factory::getApplication()->getMenu('site'); - return $multilangSiteHomePages; + return $menu->getHomepages(); } } diff --git a/libraries/src/Language/Text.php b/libraries/src/Language/Text.php index 15af9680d16ab..c941b4ce99dc5 100644 --- a/libraries/src/Language/Text.php +++ b/libraries/src/Language/Text.php @@ -10,7 +10,6 @@ namespace Joomla\CMS\Language; use Joomla\CMS\Factory; -use Joomla\CMS\HTML\HTMLHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -328,7 +327,7 @@ public static function script($string = null, $jsSafe = false, $interpretBackSla if ($string === null) { @trigger_error( \sprintf( - 'As of 3.7.0, passing a null value for the first argument of %1$s() is deprecated and will not be supported in 4.0.' + 'As of 3.7.0, passing a null value for the first argument of %1$s() is deprecated and will not be supported in 7.0.' . ' Use the %2$s::getScriptStrings() method to get the strings from the JavaScript language store instead.', __METHOD__, __CLASS__ @@ -351,7 +350,8 @@ public static function script($string = null, $jsSafe = false, $interpretBackSla // Add the string to the array if not null. if ($string !== null) { - $doc = Factory::getDocument(); + $app = Factory::getApplication(); + $doc = $app->getDocument(); // Get previously added strings $strings = $doc->getScriptOptions('joomla.jtext'); @@ -362,7 +362,7 @@ public static function script($string = null, $jsSafe = false, $interpretBackSla static::$strings[$key] = $strings[$key]; // Load core.js dependency - HTMLHelper::_('behavior.core'); + $doc->getWebAssetManager()->useScript('core'); // Update Joomla.Text script options $doc->addScriptOptions('joomla.jtext', $strings, false); diff --git a/libraries/src/Log/Log.php b/libraries/src/Log/Log.php index 7027dada9e235..5069319b4e42c 100644 --- a/libraries/src/Log/Log.php +++ b/libraries/src/Log/Log.php @@ -330,7 +330,7 @@ protected function addLogEntry(LogEntry $entry) } else { @trigger_error( \sprintf( - 'Attempting to automatically resolve loggers to the %s namespace is deprecated as of 4.0 and will be removed in 5.0.' + 'Attempting to automatically resolve loggers to the %s namespace is deprecated as of 4.0 and will be removed in 7.0.' . ' Use the logger registry instead.', __NAMESPACE__ ), diff --git a/libraries/src/Log/Logger/DatabaseLogger.php b/libraries/src/Log/Logger/DatabaseLogger.php index eee2dd67f7865..502d5d9bed116 100644 --- a/libraries/src/Log/Logger/DatabaseLogger.php +++ b/libraries/src/Log/Logger/DatabaseLogger.php @@ -13,6 +13,7 @@ use Joomla\CMS\Log\LogEntry; use Joomla\CMS\Log\Logger; use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseFactory; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -171,6 +172,6 @@ protected function connect() 'prefix' => $this->prefix, ]; - $this->db = DatabaseDriver::getInstance($options); + $this->db = (new DatabaseFactory())->getDriver($options['driver'], $options); } } diff --git a/libraries/src/Log/Logger/FormattedtextLogger.php b/libraries/src/Log/Logger/FormattedtextLogger.php index 874fb5d0ad92a..030bec8d57730 100644 --- a/libraries/src/Log/Logger/FormattedtextLogger.php +++ b/libraries/src/Log/Logger/FormattedtextLogger.php @@ -40,7 +40,7 @@ class FormattedtextLogger extends Logger * @var string * @since 1.7.0 */ - protected $format = '{DATETIME} {PRIORITY} {CLIENTIP} {CATEGORY} {MESSAGE}'; + protected $format = "{DATETIME}\t{PRIORITY}\t{CLIENTIP}\t{CATEGORY}\t{MESSAGE}"; /** * The parsed fields from the format string. diff --git a/libraries/src/Log/Logger/W3cLogger.php b/libraries/src/Log/Logger/W3cLogger.php index 65e7c2a3758d9..c836e058410fb 100644 --- a/libraries/src/Log/Logger/W3cLogger.php +++ b/libraries/src/Log/Logger/W3cLogger.php @@ -31,7 +31,7 @@ class W3cLogger extends FormattedtextLogger * @var string * @since 1.7.0 */ - protected $format = '{DATE} {TIME} {PRIORITY} {CLIENTIP} {CATEGORY} {MESSAGE}'; + protected $format = "{DATE}\t{TIME}\t{PRIORITY}\t{CLIENTIP}\t{CATEGORY}\t{MESSAGE}"; /** * Constructor. diff --git a/libraries/src/MVC/Controller/AdminController.php b/libraries/src/MVC/Controller/AdminController.php index a831e46600fad..a4ff729a77032 100644 --- a/libraries/src/MVC/Controller/AdminController.php +++ b/libraries/src/MVC/Controller/AdminController.php @@ -159,13 +159,7 @@ public function delete() $this->postDeleteHook($model, $cid); } - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToList()); } /** @@ -241,13 +235,7 @@ public function publish() } } - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToList()); } /** @@ -271,7 +259,7 @@ public function reorder() $model = $this->getModel(); $return = $model->reorder($ids, $inc); - $redirect = Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false); + $redirect = $this->getRedirectUrlToList(); if ($return === false) { // Reorder failed. @@ -317,7 +305,7 @@ public function saveorder() // Save the ordering $return = $model->saveorder($pks, $order); - $redirect = Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false); + $redirect = $this->getRedirectUrlToList(); if ($return === false) { // Reorder failed @@ -358,10 +346,7 @@ public function checkin() // Checkin failed. $message = Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()); $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), - false - ), + $this->getRedirectUrlToList(), $message, 'error' ); @@ -371,13 +356,7 @@ public function checkin() // Checkin succeeded. $message = Text::plural($this->text_prefix . '_N_ITEMS_CHECKED_IN', \count($ids)); - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), - false - ), - $message - ); + $this->setRedirect($this->getRedirectUrlToList(), $message); return true; } @@ -452,7 +431,7 @@ public function runTransition() $return = $model->executeTransition($pks, $transitionId); - $redirect = Route::_('index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), false); + $redirect = $this->getRedirectUrlToList(); if ($return === false) { // Transition change failed. @@ -469,6 +448,21 @@ public function runTransition() return true; } + /** + * Gets the URL to redirect to the list view. + * + * @return string The redirect URL. + * + * @since 6.1.0 + */ + protected function getRedirectUrlToList(): string + { + return Route::_( + 'index.php?option=' . $this->option . '&view=' . $this->view_list . $this->getRedirectToListAppend(), + false + ); + } + /** * Gets the URL arguments to append to a list redirect. * diff --git a/libraries/src/MVC/Controller/ApiController.php b/libraries/src/MVC/Controller/ApiController.php index 879445030452a..2c5cefcc1ec73 100644 --- a/libraries/src/MVC/Controller/ApiController.php +++ b/libraries/src/MVC/Controller/ApiController.php @@ -9,6 +9,7 @@ namespace Joomla\CMS\MVC\Controller; +use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\Access\Exception\NotAllowed; use Joomla\CMS\Application\CMSWebApplicationInterface; use Joomla\CMS\Component\ComponentHelper; @@ -18,8 +19,9 @@ use Joomla\CMS\MVC\Model\ListModel; use Joomla\CMS\MVC\Model\State; use Joomla\CMS\MVC\View\JsonApiView; +use Joomla\CMS\Response\JsonResponse; use Joomla\Input\Input; -use Joomla\String\Inflector; +use Joomla\Registry\Registry; use Tobscure\JsonApi\Exception\InvalidParameterException; // phpcs:disable PSR1.Files.SideEffects @@ -108,7 +110,7 @@ class ApiController extends BaseController */ public function __construct($config = [], ?MVCFactoryInterface $factory = null, ?CMSWebApplicationInterface $app = null, ?Input $input = null) { - $this->modelState = new State(); + $this->modelState = new Registry(); parent::__construct($config, $factory, $app, $input); @@ -165,7 +167,8 @@ public function displayItem($id = null) throw new \RuntimeException($e->getMessage()); } - $modelName = $this->input->get('model', Inflector::singularize($this->contentType)); + $inflector = InflectorFactory::create()->build(); + $modelName = $this->input->get('model', $inflector->singularize($this->contentType)); // Create the model, ignoring request data so we can safely set the state in the request from the controller $model = $this->getModel($modelName, '', ['ignore_request' => true, 'state' => $this->modelState]); @@ -296,7 +299,9 @@ public function displayList() */ public function delete($id = null) { - if (!$this->app->getIdentity()->authorise('core.delete', $this->option)) { + if ( + !$this->allowDelete() + ) { throw new NotAllowed('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED', 403); } @@ -304,7 +309,8 @@ public function delete($id = null) $id = $this->input->get('id', 0, 'int'); } - $modelName = $this->input->get('model', Inflector::singularize($this->contentType)); + $inflector = InflectorFactory::create()->build(); + $modelName = $this->input->get('model', $inflector->singularize($this->contentType)); /** @var \Joomla\CMS\MVC\Model\AdminModel $model */ $model = $this->getModel($modelName, '', ['ignore_request' => true]); @@ -318,6 +324,36 @@ public function delete($id = null) if ($model->getError() !== false) { throw new \RuntimeException($model->getError(), 500); } + + // If the model has set a 409 status code in the session, we return a 409 http status codee + if ($this->app->getSession()->get('http_status_code_409', false)) { + $this->app->getSession()->clear('http_status_code_409'); + $this->app->setHeader('status', 409, true); + $this->app->setHeader('Content-Type', 'application/json'); + $this->app->sendHeaders(); + $body = [ + 'status' => 'Conflict', + 'code' => 409, + 'message' => 'Resource not in state that can be deleted, must be trashed before it can be deleted', + ]; + echo new JsonResponse($body); + $this->app->close(); + } + } + + // If the model has set a 404 status code in the session, we return a 404 http status codee + if ($this->app->getSession()->get('http_status_code_404', false)) { + $this->app->getSession()->clear('http_status_code_404'); + $this->app->setHeader('status', 404, true); + $this->app->setHeader('Content-Type', 'application/json'); + $this->app->sendHeaders(); + $body = [ + 'status' => 'not found', + 'code' => 404, + 'message' => 'Resource not found', + ]; + echo new JsonResponse($body); + $this->app->close(); } $this->app->setHeader('status', 204); @@ -354,7 +390,8 @@ public function add() public function edit() { /** @var \Joomla\CMS\MVC\Model\AdminModel $model */ - $model = $this->getModel(Inflector::singularize($this->contentType)); + $inflector = InflectorFactory::create()->build(); + $model = $this->getModel($inflector->singularize($this->contentType)); if (!$model) { throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_MODEL_CREATE')); @@ -403,7 +440,8 @@ public function edit() protected function save($recordKey = null) { /** @var \Joomla\CMS\MVC\Model\AdminModel $model */ - $model = $this->getModel(Inflector::singularize($this->contentType)); + $inflector = InflectorFactory::create()->build(); + $model = $this->getModel($inflector->singularize($this->contentType)); if (!$model) { throw new \RuntimeException(Text::_('JLIB_APPLICATION_ERROR_MODEL_CREATE')); @@ -513,7 +551,13 @@ protected function save($recordKey = null) */ protected function allowEdit($data = [], $key = 'id') { - return $this->app->getIdentity()->authorise('core.edit', $this->option); + $user = $this->app->getIdentity(); + + if (!$user->authorise('core.manage', $this->option)) { + return false; + } + + return $user->authorise('core.edit', $this->option); } /** @@ -531,9 +575,32 @@ protected function allowAdd($data = []) { $user = $this->app->getIdentity(); + if (!$user->authorise('core.manage', $this->option)) { + return false; + } + return $user->authorise('core.create', $this->option) || \count($user->getAuthorisedCategories($this->option, 'core.create')); } + /** + * Method to check if it's allowed to delete a record + * + * @return boolean + * + * @since 6.1.3 + */ + protected function allowDelete(): bool + { + $user = $this->app->getIdentity(); + + // Require generic management permissions for the component + if (!$user->authorise('core.manage', $this->option)) { + return false; + } + + return $user->authorise('core.delete', $this->option); + } + /** * Method to allow extended classes to manipulate the data to be saved for an extension. * diff --git a/libraries/src/MVC/Controller/BaseController.php b/libraries/src/MVC/Controller/BaseController.php index 2ad02cc2eb192..2a02250d6d435 100644 --- a/libraries/src/MVC/Controller/BaseController.php +++ b/libraries/src/MVC/Controller/BaseController.php @@ -12,6 +12,8 @@ use Joomla\Application\AbstractApplication; use Joomla\CMS\Application\CMSApplicationInterface; use Joomla\CMS\Application\CMSWebApplicationInterface; +use Joomla\CMS\Cache\CacheControllerFactoryAwareInterface; +use Joomla\CMS\Cache\CacheControllerFactoryAwareTrait; use Joomla\CMS\Cache\Exception\CacheExceptionInterface; use Joomla\CMS\Document\DocumentAwareInterface; use Joomla\CMS\Factory; @@ -49,10 +51,15 @@ * * @since 2.5.5 */ -class BaseController implements ControllerInterface, DispatcherAwareInterface, LoggerAwareInterface +class BaseController implements + ControllerInterface, + DispatcherAwareInterface, + LoggerAwareInterface, + CacheControllerFactoryAwareInterface { use LoggerAwareTrait; use DispatcherAwareTrait; + use CacheControllerFactoryAwareTrait; /** * The base path of the controller @@ -200,7 +207,7 @@ class BaseController implements ControllerInterface, DispatcherAwareInterface, L * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement. Get the model through the MVCFactory instead */ public static function addModelPath($path, $prefix = '') @@ -261,7 +268,7 @@ public static function createFileName($type, $parts = []) * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Get the controller through the MVCFactory instead * Example: Factory::getApplication()->bootComponent($option)->getMVCFactory()->createController(...); * @@ -378,7 +385,7 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null, $this->input = $input ?: $this->app->getInput(); /** - * @deprecated This is to maintain b/c with the J4.0 implementation of BaseController. In Joomla 6.0 this will be + * @deprecated This is to maintain b/c with the J4.0 implementation of BaseController. In Joomla 7.0 this will be * removed and instead the logger should be injected by the MVCFactory using * BaseController::setLogger() */ @@ -391,7 +398,7 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null, } // Determine the methods to exclude from the base class. - $xMethods = get_class_methods('\\Joomla\\CMS\\MVC\\Controller\\BaseController'); + $xMethods = get_class_methods(BaseController::class); // Get the public methods in this class using reflection. $r = new \ReflectionClass($this); @@ -545,7 +552,7 @@ protected function checkEditId($context, $id) $context, $id, (int) $result, - str_replace("\n", ' ', print_r($values, 1)) + json_encode($values) ), ['category' => 'controller'] ); @@ -688,7 +695,8 @@ public function display($cachable = false, $urlparams = []) try { /** @var \Joomla\CMS\Cache\Controller\ViewController $cache */ - $cache = Factory::getCache($option, 'view'); + $cache = $this->getCacheControllerFactory() + ->createCacheController('view', ['defaultgroup' => $option]); $cache->get($view, 'display'); } catch (CacheExceptionInterface) { $view->display(); @@ -918,7 +926,7 @@ protected function holdEditId($context, $id) 'Holding edit ID %s.%s %s', $context, $id, - str_replace("\n", ' ', print_r($values, 1)) + json_encode($values) ), ['category' => 'controller'] ); @@ -1048,7 +1056,7 @@ protected function releaseEditId($context, $id) 'Releasing edit ID %s.%s %s', $context, $id, - str_replace("\n", ' ', print_r($values, 1)) + json_encode($values) ), ['category' => 'controller'] ); @@ -1220,7 +1228,7 @@ protected function prepareViewModel(ViewInterface $view) * Get the event dispatcher. * * The override was made to keep a backward compatibility for legacy component. - * TODO: Remove the override in 6.0 + * TODO: Remove the override in 7.0 * * @return DispatcherInterface * @@ -1231,7 +1239,7 @@ public function getDispatcher() { if (!$this->dispatcher) { @trigger_error( - \sprintf('Dispatcher for %s should be set through MVC factory. It will throw an exception in 6.0', __CLASS__), + \sprintf('Dispatcher for %s should be set through MVC factory. It will throw an exception in 7.0', __CLASS__), E_USER_DEPRECATED ); diff --git a/libraries/src/MVC/Controller/FormController.php b/libraries/src/MVC/Controller/FormController.php index 2da2087177f46..4c0ef9ef5774b 100644 --- a/libraries/src/MVC/Controller/FormController.php +++ b/libraries/src/MVC/Controller/FormController.php @@ -10,9 +10,11 @@ namespace Joomla\CMS\MVC\Controller; use Doctrine\Inflector\InflectorFactory; +use Joomla\CMS\Application\CMSApplicationInterface; use Joomla\CMS\Application\CMSWebApplicationInterface; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Event\Model; +use Joomla\CMS\Form\Form; use Joomla\CMS\Form\FormFactoryAwareInterface; use Joomla\CMS\Form\FormFactoryAwareTrait; use Joomla\CMS\Form\FormFactoryInterface; @@ -173,13 +175,7 @@ public function add() // Set the internal error and also the redirect error. $this->setMessage(Text::_('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED'), 'error'); - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToList()); return false; } @@ -188,13 +184,7 @@ public function add() $this->app->setUserState($context . '.data', null); // Redirect to the edit screen. - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend(), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToItem()); return true; } @@ -318,20 +308,10 @@ public function cancel($key = null) } $recordId = $this->input->getInt($key); + $checkin = $table->hasField('checked_out') && $table->hasField('checked_out_time'); - // Attempt to check-in the current record. - if ($recordId && $table->hasField('checked_out') && $model->checkin($recordId) === false) { - // Check-in failed, go back to the record and display a notice. - $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'error'); - - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend($recordId, $key), - false - ) - ); - + // Attempt to check-in the current record. If not success, go back to the record and display a notice + if ($recordId && $checkin && !$this->attemptCheckin($model, $recordId, $key)) { return false; } @@ -339,19 +319,17 @@ public function cancel($key = null) $this->releaseEditId($context, $recordId); $this->app->setUserState($context . '.data', null); - $url = 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(); - // Check if there is a return value $return = $this->input->get('return', null, 'base64'); if (!\is_null($return) && Uri::isInternal(base64_decode($return))) { - $url = base64_decode($return); + // If a return param exists and is internal, redirect to it. + $this->setRedirect(Route::_(base64_decode($return), false)); + } else { + // Otherwise use the standard list URL helper. + $this->setRedirect($this->getRedirectUrlToList()); } - // Redirect to the list screen. - $this->setRedirect(Route::_($url, false)); - return true; } @@ -388,36 +366,20 @@ public function edit($key = null, $urlVar = null) // Get the previous record id (if any) and the current record id. $recordId = (int) (\count($cid) ? $cid[0] : $this->input->getInt($urlVar)); - $checkin = $table->hasField('checked_out'); // Access check. if (!$this->allowEdit([$key => $recordId], $key)) { $this->setMessage(Text::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'), 'error'); - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToList()); return false; } - // Attempt to check-out the new record for editing and redirect. - if ($checkin && !$model->checkout($recordId)) { - // Check-out failed, display a notice but allow the user to see the record. - $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKOUT_FAILED', $model->getError()), 'error'); - - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend($recordId, $urlVar), - false - ) - ); + $checkin = $table->hasField('checked_out') && $table->hasField('checked_out_time'); + // Attempt to check-out the new record. If failed, display a notice but allow the user to see the record + if ($checkin && !$this->attemptCheckout($model, $recordId, $urlVar)) { return false; } @@ -425,13 +387,7 @@ public function edit($key = null, $urlVar = null) $this->holdEditId($context, $recordId); $this->app->setUserState($context . '.data', null); - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend($recordId, $urlVar), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToItem($recordId, $urlVar)); return true; } @@ -456,6 +412,22 @@ public function getModel($name = '', $prefix = '', $config = ['ignore_request' = return parent::getModel($name, $prefix, $config); } + /** + * Gets the redirect URL to an item. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The redirect URL to the item. + * + * @since 6.1.0 + */ + protected function getRedirectUrlToItem($recordId = null, $urlVar = 'id'): string + { + return Route::_('index.php?option=' . $this->option . '&view=' . $this->view_item + . $this->getRedirectToItemAppend($recordId, $urlVar), false); + } + /** * Gets the URL arguments to append to an item redirect. * @@ -496,6 +468,22 @@ protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') return $append; } + /** + * Gets the redirect URL to a list. + * + * @return string The redirect URL to the list. + * + * @since 6.1.0 + */ + protected function getRedirectUrlToList(): string + { + return Route::_( + 'index.php?option=' . $this->option . '&view=' . $this->view_list + . $this->getRedirectToListAppend(), + false + ); + } + /** * Gets the URL arguments to append to a list redirect. * @@ -519,6 +507,22 @@ protected function getRedirectToListAppend() return $append; } + /** + * Function that allows child controller access and modify to model data + * before the data is saved. The method must return the modified $validData array + * + * @param BaseDatabaseModel $model The data model object. + * @param array $validData The validated data. + * + * @return array + * + * @since 6.1.0 + */ + protected function preSaveHook(BaseDatabaseModel $model, array $validData = []): array + { + return $validData; + } + /** * Function that allows child controller access to model data * after the data has been saved. @@ -552,7 +556,7 @@ public function save($key = null, $urlVar = null) $model = $this->getModel(); $table = $model->getTable(); $data = $this->input->post->get('jform', [], 'array'); - $checkin = $table->hasField('checked_out'); + $checkin = $table->hasField('checked_out') && $table->hasField('checked_out_time'); $context = "$this->option.edit.$this->context"; $task = $this->getTask(); @@ -571,21 +575,13 @@ public function save($key = null, $urlVar = null) // Populate the row id from the session. $data[$key] = $recordId; + // Give child classes a chance to preprocess the data. + $data = $this->preprocessSaveData($data); + // The save2copy task needs to be handled slightly differently. if ($task === 'save2copy') { - // Check-in the original row. - if ($checkin && $model->checkin($data[$key]) === false) { - // Check-in failed. Go back to the item and display a notice. - $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'error'); - - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend($recordId, $urlVar), - false - ) - ); - + // Check-in the original row. If failed, go back to the record and display a notice + if ($checkin && !$this->attemptCheckin($model, $recordId, $urlVar)) { return false; } @@ -599,13 +595,7 @@ public function save($key = null, $urlVar = null) if (!$this->allowSave($data, $key)) { $this->setMessage(Text::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED'), 'error'); - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToList()); return false; } @@ -620,63 +610,29 @@ public function save($key = null, $urlVar = null) return false; } - // Send an object which can be modified through the plugin event - $objData = (object) $data; - $this->getDispatcher()->dispatch( - 'onContentNormaliseRequestData', - new Model\NormaliseRequestDataEvent('onContentNormaliseRequestData', [ - 'context' => $this->option . '.' . $this->context, - 'data' => $objData, - 'subject' => $form, - ]) - ); - $data = (array) $objData; + // Allow plugins to normalize/modify the data before validation. + $data = $this->normalizeRequestData($form, $data); // Test whether the data is valid. $validData = $model->validate($form, $data); // Check for validation errors. if ($validData === false) { - // Get the validation messages. - $errors = $model->getErrors(); - - // Push up to three validation messages out to the user. - for ($i = 0, $n = \count($errors); $i < $n && $i < 3; $i++) { - if ($errors[$i] instanceof \Exception) { - $this->app->enqueueMessage($errors[$i]->getMessage(), CMSWebApplicationInterface::MSG_ERROR); - } else { - $this->app->enqueueMessage($errors[$i], CMSWebApplicationInterface::MSG_ERROR); - } - } + // Push up to validation error messages out to the user. + $this->handleSaveDataValidationErrorMessages($model->getErrors()); /** * We need the filtered value of calendar fields because the UTC normalisation is * done in the filter and on output. This would apply the Timezone offset on * reload. We set the calendar values we save to the processed date. */ - $filteredData = $form->filter($data); - - foreach ($form->getFieldset() as $field) { - if ($field->type === 'Calendar') { - $fieldName = $field->fieldname; - - if (isset($filteredData[$fieldName])) { - $data[$fieldName] = $filteredData[$fieldName]; - } - } - } + $data = $this->applyFilterForCalendarFieldsToRequestData($form, $data); // Save the data in the session. $this->app->setUserState($context . '.data', $data); // Redirect back to the edit screen. - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend($recordId, $urlVar), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToItem($recordId, $urlVar)); return false; } @@ -685,6 +641,9 @@ public function save($key = null, $urlVar = null) $validData['tags'] = []; } + // Invoke the preSaveHook method to allow for the child class to modify $validData before save. + $validData = $this->preSaveHook($model, $validData); + // Attempt to save the data. if (!$model->save($validData)) { // Save the data in the session. @@ -693,40 +652,21 @@ public function save($key = null, $urlVar = null) // Redirect back to the edit screen. $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError()), 'error'); - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend($recordId, $urlVar), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToItem($recordId, $urlVar)); return false; } // Save succeeded, so check-in the record. - if ($checkin && $model->checkin($validData[$key]) === false) { + if ($checkin && $validData[$key] && !$this->attemptCheckin($model, $validData[$key], $urlVar)) { // Save the data in the session. $this->app->setUserState($context . '.data', $validData); - // Check-in failed, so go back to the record and display a notice. - $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'error'); - - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend($recordId, $urlVar), - false - ) - ); - return false; } - $langKey = $this->text_prefix . ($recordId === 0 && $this->app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS'; - $prefix = $this->app->getLanguage()->hasKey($langKey) ? $this->text_prefix : 'JLIB_APPLICATION'; - - $this->setMessage(Text::_($prefix . ($recordId === 0 && $this->app->isClient('site') ? '_SUBMIT' : '') . '_SAVE_SUCCESS')); + // Set the message after successful save. + $this->setSaveSuccessMessage($recordId); // Redirect the user and adjust session state based on the chosen task. switch ($task) { @@ -738,13 +678,7 @@ public function save($key = null, $urlVar = null) $model->checkout($recordId); // Redirect back to the edit screen. - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend($recordId, $urlVar), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToItem($recordId, $urlVar)); break; case 'save2new': @@ -753,13 +687,7 @@ public function save($key = null, $urlVar = null) $this->app->setUserState($context . '.data', null); // Redirect back to the edit screen. - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend(null, $urlVar), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToItem(null, $urlVar)); break; default: @@ -767,18 +695,16 @@ public function save($key = null, $urlVar = null) $this->releaseEditId($context, $recordId); $this->app->setUserState($context . '.data', null); - $url = 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(); - // Check if there is a return value $return = $this->input->get('return', null, 'base64'); if (!\is_null($return) && Uri::isInternal(base64_decode($return))) { - $url = base64_decode($return); + // Route the provided return URL if internal + $this->setRedirect(Route::_(base64_decode($return), false)); + } else { + // Otherwise use the standard list URL helper. + $this->setRedirect($this->getRedirectUrlToList()); } - - // Redirect to the list screen. - $this->setRedirect(Route::_($url, false)); break; } @@ -823,22 +749,12 @@ public function reload($key = null, $urlVar = null) // Check if it is allowed to edit or create the data if (($recordId && !$this->allowEdit($data, $key)) || (!$recordId && !$this->allowAdd($data))) { - $this->setRedirect( - Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_list - . $this->getRedirectToListAppend(), - false - ) - ); + $this->setRedirect($this->getRedirectUrlToList()); $this->redirect(); } // The redirect url - $redirectUrl = Route::_( - 'index.php?option=' . $this->option . '&view=' . $this->view_item . - $this->getRedirectToItemAppend($recordId, $urlVar), - false - ); + $redirectUrl = $this->getRedirectUrlToItem($recordId, $urlVar); /** @var \Joomla\CMS\Form\Form $form */ $form = $model->getForm($data, false); @@ -848,6 +764,139 @@ public function reload($key = null, $urlVar = null) * done in the filter and on output. This would apply the Timezone offset on * reload. We set the calendar values we save to the processed date. */ + $data = $this->applyFilterForCalendarFieldsToRequestData($form, $data); + + // Save the data in the session. + $this->app->setUserState($this->option . '.edit.' . $this->context . '.data', $data); + + $this->setRedirect($redirectUrl); + $this->redirect(); + } + + /** + * Method to preprocess data gotten from the request before further processing. Child controllers can use this to + * manipulate data before checking access, validation, and saving. + * + * @param array $data The data array. + * + * @return array The processed data array. + * + * @since 6.1.0 + */ + protected function preprocessSaveData(array $data): array + { + return $data; + } + + /** + * Method to perform checkin of a record. + * + * @param BaseDatabaseModel $model The model object. + * @param string|int $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 6.1.0 + */ + protected function attemptCheckin(BaseDatabaseModel $model, $recordId, $urlVar): bool + { + if ($model->checkin($recordId) === false) { + // Check-in failed, go back to the record and display a notice. + $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKIN_FAILED', $model->getError()), 'error'); + + $this->setRedirect($this->getRedirectUrlToItem($recordId, $urlVar)); + + return false; + } + + return true; + } + + /** + * Method to perform checkout of a record. + * + * @param BaseDatabaseModel $model The model object. + * @param string|int $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 6.1.0 + */ + protected function attemptCheckout(BaseDatabaseModel $model, $recordId, $urlVar): bool + { + if ($model->checkout($recordId) === false) { + // Check-out failed, display a notice but allow the user to see the record. + $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_CHECKOUT_FAILED', $model->getError()), 'error'); + + $this->setRedirect($this->getRedirectUrlToItem($recordId, $urlVar)); + + return false; + } + + return true; + } + + /** + * Method to normalize the request data through the plugin event. + * + * @param Form $form The form object. + * @param array $data The data array. + * + * @return array The normalized data. + * + * @since 6.1.0 + */ + protected function normalizeRequestData(Form $form, array $data): array + { + // Send an object which can be modified through the plugin event + $objData = (object) $data; + $this->getDispatcher()->dispatch( + 'onContentNormaliseRequestData', + new Model\NormaliseRequestDataEvent('onContentNormaliseRequestData', [ + 'context' => $this->option . '.' . $this->context, + 'data' => $objData, + 'subject' => $form, + ]) + ); + + return (array) $objData; + } + + /** + * Method to handle save data validation errors. + * + * @param array $errors The array of validation errors. + * + * @return void + * + * @since 6.1.0 + */ + protected function handleSaveDataValidationErrorMessages(array $errors): void + { + // Push up to three validation messages out to the user. + for ($i = 0, $n = \count($errors); $i < $n && $i < 3; $i++) { + if ($errors[$i] instanceof \Exception) { + $this->app->enqueueMessage($errors[$i]->getMessage(), CMSApplicationInterface::MSG_ERROR); + } else { + $this->app->enqueueMessage($errors[$i], CMSApplicationInterface::MSG_ERROR); + } + } + } + + /** + * Method to apply filter and merge filtered calendar fields data to request data. + * + * @param Form $form The form object. + * @param array $data The request data array. + * + * @return array The request data array with filter applied for calendar fields. + * + * @since 6.1.0 + */ + protected function applyFilterForCalendarFieldsToRequestData(Form $form, array $data): array + { $filteredData = $form->filter($data); foreach ($form->getFieldset() as $field) { @@ -866,11 +915,31 @@ public function reload($key = null, $urlVar = null) } } - // Save the data in the session. - $this->app->setUserState($this->option . '.edit.' . $this->context . '.data', $data); + return $data; + } - $this->setRedirect($redirectUrl); - $this->redirect(); + /** + * Method to set the save success message. + * + * @param int $recordId The record id. + * + * @return void + * + * @since 6.1.0 + */ + protected function setSaveSuccessMessage($recordId): void + { + $suffix = ($recordId === 0 && $this->app->isClient('site')) + ? '_SUBMIT_SAVE_SUCCESS' + : '_SAVE_SUCCESS'; + + $langKey = $this->text_prefix . $suffix; + + $prefix = $this->app->getLanguage()->hasKey($langKey) + ? $this->text_prefix + : 'JLIB_APPLICATION'; + + $this->setMessage(Text::_($prefix . $suffix)); } /** @@ -880,7 +949,7 @@ public function reload($key = null, $urlVar = null) * * @since 3.9.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * It is handled by regular save method now. */ public function editAssociations() diff --git a/libraries/src/MVC/Factory/MVCFactory.php b/libraries/src/MVC/Factory/MVCFactory.php index b21b3a1021f54..5806fd91e8ff9 100644 --- a/libraries/src/MVC/Factory/MVCFactory.php +++ b/libraries/src/MVC/Factory/MVCFactory.php @@ -15,6 +15,8 @@ use Joomla\CMS\Factory; use Joomla\CMS\Form\FormFactoryAwareInterface; use Joomla\CMS\Form\FormFactoryAwareTrait; +use Joomla\CMS\Language\LanguageFactoryAwareInterface; +use Joomla\CMS\Language\LanguageFactoryAwareTrait; use Joomla\CMS\Mail\MailerFactoryAwareInterface; use Joomla\CMS\Mail\MailerFactoryAwareTrait; use Joomla\CMS\MVC\Model\ModelInterface; @@ -41,7 +43,7 @@ * * @since 3.10.0 */ -class MVCFactory implements MVCFactoryInterface, FormFactoryAwareInterface, SiteRouterAwareInterface, UserFactoryAwareInterface, MailerFactoryAwareInterface +class MVCFactory implements MVCFactoryInterface, FormFactoryAwareInterface, SiteRouterAwareInterface, UserFactoryAwareInterface, MailerFactoryAwareInterface, LanguageFactoryAwareInterface { use FormFactoryAwareTrait; use DispatcherAwareTrait; @@ -50,6 +52,7 @@ class MVCFactory implements MVCFactoryInterface, FormFactoryAwareInterface, Site use CacheControllerFactoryAwareTrait; use UserFactoryAwareTrait; use MailerFactoryAwareTrait; + use LanguageFactoryAwareTrait; /** * The namespace to create the objects from. @@ -115,6 +118,7 @@ public function createController($name, $prefix, array $config, CMSApplicationIn $this->setCacheControllerOnObject($controller); $this->setUserFactoryOnObject($controller); $this->setMailerFactoryOnObject($controller); + $this->setLanguageFactoryOnObject($controller); if ($controller instanceof LoggerAwareInterface && $this->logger !== null) { $controller->setLogger($this->logger); @@ -166,12 +170,13 @@ public function createModel($name, $prefix = '', array $config = []) $this->setCacheControllerOnObject($model); $this->setUserFactoryOnObject($model); $this->setMailerFactoryOnObject($model); + $this->setLanguageFactoryOnObject($model); if ($model instanceof DatabaseAwareInterface) { try { $model->setDatabase($this->getDatabase()); } catch (DatabaseNotFoundException) { - @trigger_error('Database must be set, this will not be caught anymore in 5.0.', E_USER_DEPRECATED); + @trigger_error('Database must be set, this will not be caught anymore in 7.0.', E_USER_DEPRECATED); $model->setDatabase(Factory::getContainer()->get(DatabaseInterface::class)); } } @@ -267,7 +272,7 @@ public function createTable($name, $prefix = '', array $config = []) try { $db = \array_key_exists('dbo', $config) ? $config['dbo'] : $this->getDatabase(); } catch (DatabaseNotFoundException) { - @trigger_error('Database must be set, this will not be caught anymore in 5.0.', E_USER_DEPRECATED); + @trigger_error('Database must be set, this will not be caught anymore in 7.0.', E_USER_DEPRECATED); $db = Factory::getContainer()->get(DatabaseInterface::class); } @@ -434,4 +439,26 @@ private function setMailerFactoryOnObject($object): void // Ignore it } } + + /** + * Sets the internal mailer factory on the given object. + * + * @param object $object The object + * + * @return void + * + * @since 6.2.0 + */ + private function setLanguageFactoryOnObject($object): void + { + if (!$object instanceof LanguageFactoryAwareInterface) { + return; + } + + try { + $object->setLanguageFactory($this->getLanguageFactory()); + } catch (\UnexpectedValueException) { + // Ignore it + } + } } diff --git a/libraries/src/MVC/Model/AdminModel.php b/libraries/src/MVC/Model/AdminModel.php index 164cecfebef24..ba95f39aaeef7 100644 --- a/libraries/src/MVC/Model/AdminModel.php +++ b/libraries/src/MVC/Model/AdminModel.php @@ -18,13 +18,14 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Router\Route; +use Joomla\CMS\Table\Category; use Joomla\CMS\Table\Table; use Joomla\CMS\Table\TableInterface; use Joomla\CMS\Tag\TaggableTableInterface; use Joomla\CMS\UCM\UCMType; +use Joomla\CMS\Versioning\VersionableModelInterface; use Joomla\Database\ParameterType; use Joomla\Registry\Registry; use Joomla\String\StringHelper; @@ -325,7 +326,13 @@ public function batch($commands, $pks, $contexts) foreach ($this->batch_commands as $identifier => $command) { if (!empty($commands[$identifier])) { - if (!$this->$command($commands[$identifier], $pks, $contexts)) { + if ($command === 'batchTag') { + $removeTags = ArrayHelper::getValue($commands, 'tag_addremove', 'a') === 'r'; + + if (!$this->batchTags($commands[$identifier], $pks, $contexts, $removeTags)) { + return false; + } + } elseif (!$this->$command($commands[$identifier], $pks, $contexts)) { return false; } @@ -447,6 +454,19 @@ protected function batchCopy($value, $pks, $contexts) continue; } + $assetName = $contexts[$pk]; + + // Records might not have own assets id's but their categories + if (!$this->table->hasField('asset_id') && $this->table->hasField('catid')) { + $assetName = $this->option . '.category.' . (int) $this->table->catid; + } + + if (!$this->user->authorise('core.edit', $assetName)) { + $this->setError(Text::_('JLIB_APPLICATION_ERROR_BATCH_CANNOT_EDIT')); + + return false; + } + // Check for asset_id if ($this->table->hasField($this->table->getColumnAlias('asset_id'))) { $oldAssetId = $this->table->asset_id; @@ -503,7 +523,7 @@ protected function batchCopy($value, $pks, $contexts) $dbType = strtolower($db->getServerType()); // Copy rules - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->clear() ->update($db->quoteName('#__assets', 't')); @@ -697,6 +717,23 @@ protected function batchMove($value, $pks, $contexts) * @deprecated 5.3 will be removed in 7.0 */ protected function batchTag($value, $pks, $contexts) + { + return $this->batchTags($value, $pks, $contexts); + } + + /** + * Batch tag a list of item. + * + * @param integer $value The value of the new tag. + * @param array $pks An array of row IDs. + * @param array $contexts An array of item contexts. + * @param boolean $removeTags Flag indicating whether the tags in $value have to be removed. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 6.0.0 + */ + protected function batchTags($value, $pks, $contexts, $removeTags = false) { // Initialize re-usable member properties, and re-usable local variables $this->initBatch(); @@ -713,6 +750,7 @@ protected function batchTag($value, $pks, $contexts) 'subject' => $this->table, 'newTags' => $tags, 'replaceTags' => false, + 'removeTags' => $removeTags, ] ); @@ -861,7 +899,7 @@ public function delete(&$pks) // Multilanguage: if associated, delete the item in the _associations table if ($this->associationsContext && Associations::isEnabled()) { $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( [ 'COUNT(*) AS ' . $db->quoteName('count'), @@ -884,7 +922,7 @@ public function delete(&$pks) $row = $db->loadAssoc(); if (!empty($row['count'])) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__associations')) ->where( [ @@ -911,6 +949,12 @@ public function delete(&$pks) return false; } + if ($this instanceof VersionableModelInterface) { + $typeAlias = $this->typeAlias ?: $this->option . '.' . $this->name; + + $this->deleteHistory($typeAlias, $pk); + } + // Trigger the after event. $dispatcher->dispatch($this->event_after_delete, new Model\AfterDeleteEvent($this->event_after_delete, [ 'context' => $context, @@ -927,14 +971,28 @@ public function delete(&$pks) return false; } + if (Factory::getApplication()->isClient('api')) { + $session = Factory::getApplication()->getSession(); + $session->set('http_status_code_409', true); + } + Log::add(Text::_('JLIB_APPLICATION_ERROR_DELETE_NOT_PERMITTED'), Log::WARNING, 'jerror'); return false; } } else { - $this->setError($table->getError()); + $error = $this->getError(); + if ($error) { + $this->setError($table->getError()); - return false; + return false; + } + if (Factory::getApplication()->isClient('api')) { + $session = Factory::getApplication()->getSession(); + $session->set('http_status_code_404', true); + } + + return true; } } @@ -1005,9 +1063,9 @@ public function getItem($pk = null) } } - // Convert to the CMSObject before adding other data. - $properties = $table->getProperties(1); - $item = ArrayHelper::toObject($properties, CMSObject::class); + // Convert to \stdClass before adding other data + $properties = get_object_vars($table); + $item = ArrayHelper::toObject($properties); if (property_exists($item, 'params')) { $registry = new Registry($item->params); @@ -1351,7 +1409,7 @@ public function save($data) // Get associationskey for edited item $db = $this->getDatabase(); $id = (int) $table->$key; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('key')) ->from($db->quoteName('#__associations')) ->where($db->quoteName('context') . ' = :context') @@ -1363,7 +1421,7 @@ public function save($data) if ($associations || $oldKey !== null) { // Deleting old associations for the associated items - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__associations')) ->where($db->quoteName('context') . ' = :context') ->bind(':context', $this->associationsContext); @@ -1392,7 +1450,7 @@ public function save($data) if (\count($associations) > 1) { // Adding new association for these items $key = md5(json_encode($associations)); - $query = $db->getQuery(true) + $query = $db->createQuery() ->insert($db->quoteName('#__associations')) ->columns( [ @@ -1419,6 +1477,10 @@ public function save($data) } } + if ($this instanceof VersionableModelInterface) { + $this->saveHistory($data, $this->typeAlias); + } + if ($app->getInput()->get('task') == 'editAssociations') { return $this->redirectToAssociations($data); } @@ -1517,7 +1579,7 @@ protected function checkCategoryId($categoryId) { // Check that the category exists if ($categoryId) { - $categoryTable = Table::getInstance('Category'); + $categoryTable = new Category($this->getDatabase()); if (!$categoryTable->load($categoryId)) { if ($error = $categoryTable->getError()) { @@ -1611,7 +1673,7 @@ public function initBatch() * * @since 3.9.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * It is handled by regular save method now. */ public function editAssociations($data) diff --git a/libraries/src/MVC/Model/BaseDatabaseModel.php b/libraries/src/MVC/Model/BaseDatabaseModel.php index 9504cd59fb275..5411e66ccc6e3 100644 --- a/libraries/src/MVC/Model/BaseDatabaseModel.php +++ b/libraries/src/MVC/Model/BaseDatabaseModel.php @@ -98,14 +98,14 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) } /** - * @deprecated 4.3 will be Removed in 6.0 + * @deprecated 4.3 will be Removed in 7.0 * Database instance is injected through the setter function, * subclasses should not use the db instance in constructor anymore */ $db = \array_key_exists('dbo', $config) ? $config['dbo'] : Factory::getDbo(); if ($db) { - @trigger_error('Database is not available in constructor in 6.0.', E_USER_DEPRECATED); + @trigger_error('Database is not available in constructor in 7.0.', E_USER_DEPRECATED); $this->setDatabase($db); // Is needed, when models use the deprecated MVC DatabaseAwareTrait, as the trait is overriding the local functions @@ -155,7 +155,7 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) protected function _getList($query, $limitstart = 0, $limit = 0) { if (\is_string($query)) { - $query = $this->getDatabase()->getQuery(true)->setQuery($query); + $query = $this->getDatabase()->createQuery()->setQuery($query); } $query->setLimit($limit, $limitstart); @@ -340,8 +340,8 @@ protected function bootComponent($component): ComponentInterface /** * Get the event dispatcher. * - * The override was made to keep a backward compatibility for legacy component. - * TODO: Remove the override in 6.0 + * The override was made to keep a backward compatibility for legacy component . + * TODO: Remove the override ONLY when support of Legacy components will be removed (components without Dispatcher and MVCFactory). * * @return DispatcherInterface * @@ -352,7 +352,7 @@ public function getDispatcher() { if (!$this->dispatcher) { @trigger_error( - \sprintf('Dispatcher for %s should be set through MVC factory. It will throw an exception in 6.0', __CLASS__), + \sprintf('Dispatcher for %s should be set through MVC factory. It will throw an exception in 7.0', __CLASS__), E_USER_DEPRECATED ); @@ -371,7 +371,7 @@ public function getDispatcher() * * @since 4.1.0 * - * @deprecated 4.4 will be removed in 6.0. Use $this->getDispatcher() directly. + * @deprecated 4.4 will be removed in 7.0. Use $this->getDispatcher() directly. */ protected function dispatchEvent(EventInterface $event) { @@ -379,7 +379,7 @@ protected function dispatchEvent(EventInterface $event) @trigger_error( \sprintf( - 'Method %s is deprecated and will be removed in 6.0. Use getDispatcher()->dispatch() directly.', + 'Method %s is deprecated and will be removed in 7.0. Use getDispatcher()->dispatch() directly.', __METHOD__ ), E_USER_DEPRECATED @@ -394,7 +394,7 @@ protected function dispatchEvent(EventInterface $event) * @since 4.2.0 * @throws \UnexpectedValueException * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use getDatabase() instead * Example: $model->getDatabase(); */ @@ -416,7 +416,7 @@ public function getDbo() * * @since 4.2.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use setDatabase() instead * Example: $model->setDatabase($db); */ @@ -438,7 +438,7 @@ public function setDbo(?DatabaseInterface $db = null) * * @since 4.2.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use getDatabase() instead of directly accessing _db */ public function __get($name) diff --git a/libraries/src/MVC/Model/BaseModel.php b/libraries/src/MVC/Model/BaseModel.php index 28bd72cb8d11e..0bdd552760543 100644 --- a/libraries/src/MVC/Model/BaseModel.php +++ b/libraries/src/MVC/Model/BaseModel.php @@ -89,7 +89,7 @@ public function __construct($config = []) * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement. Get the model through the MVCFactory + namespace instead * * @see LegacyModelLoaderTrait::getInstance() diff --git a/libraries/src/MVC/Model/DatabaseAwareTrait.php b/libraries/src/MVC/Model/DatabaseAwareTrait.php deleted file mode 100644 index 2eb1917ee562e..0000000000000 --- a/libraries/src/MVC/Model/DatabaseAwareTrait.php +++ /dev/null @@ -1,79 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -namespace Joomla\CMS\MVC\Model; - -use Joomla\Database\DatabaseInterface; - -// phpcs:disable PSR1.Files.SideEffects -\defined('_JEXEC') or die; -// phpcs:enable PSR1.Files.SideEffects - -/** - * Database aware trait. - * - * @since 4.0.0 - * - * @deprecated 4.3 will be removed in 6.0 - * Use the trait from the database package - * Example: \Joomla\Database\DatabaseAwareTrait - */ -trait DatabaseAwareTrait -{ - /** - * The database driver. - * - * @var DatabaseInterface - * @since 4.0.0 - * - * @deprecated 4.3 will be removed in 6.0 - * Use the trait from the database package - * Example: \Joomla\Database\DatabaseAwareTrait::$databaseAwareTraitDatabase - */ - protected $_db; - - /** - * Get the database driver. - * - * @return DatabaseInterface The database driver. - * - * @since 4.0.0 - * @throws \UnexpectedValueException - * - * @deprecated 4.3 will be removed in 6.0 - * Use the trait from the database package - * Example: \Joomla\Database\DatabaseAwareTrait::getDatabase() - */ - public function getDbo() - { - if ($this->_db) { - return $this->_db; - } - - throw new \UnexpectedValueException('Database driver not set in ' . __CLASS__); - } - - /** - * Set the database driver. - * - * @param ?DatabaseInterface $db The database driver. - * - * @return void - * - * @since 4.0.0 - * - * @deprecated 4.3 will be removed in 6.0 - * Use the trait from the database package - * Example: \Joomla\Database\DatabaseAwareTrait::setDatabase() - */ - public function setDbo(?DatabaseInterface $db = null) - { - $this->_db = $db; - } -} diff --git a/libraries/src/MVC/Model/FormModel.php b/libraries/src/MVC/Model/FormModel.php index 0664707647d82..545ae15e0f844 100644 --- a/libraries/src/MVC/Model/FormModel.php +++ b/libraries/src/MVC/Model/FormModel.php @@ -199,7 +199,7 @@ public function validate($form, $data, $group = null) if (!empty($dispatcher->getListeners('onUserBeforeDataValidation'))) { @trigger_error( - 'The `onUserBeforeDataValidation` event is deprecated and will be removed in 6.0.' + 'The `onUserBeforeDataValidation` event is deprecated and will be removed in 7.0.' . 'Use the `onContentBeforeValidateData` event instead.', E_USER_DEPRECATED ); diff --git a/libraries/src/MVC/Model/LegacyModelLoaderTrait.php b/libraries/src/MVC/Model/LegacyModelLoaderTrait.php index 61a73f15dee41..86e3db687ac2e 100644 --- a/libraries/src/MVC/Model/LegacyModelLoaderTrait.php +++ b/libraries/src/MVC/Model/LegacyModelLoaderTrait.php @@ -26,7 +26,7 @@ * * @since 4.0.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement */ trait LegacyModelLoaderTrait @@ -41,7 +41,7 @@ trait LegacyModelLoaderTrait * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement */ protected static function _createFileName($type, $parts = []) @@ -60,7 +60,7 @@ protected static function _createFileName($type, $parts = []) * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement. Get the model through the MVCFactory instead * Example: Factory::getApplication()->bootComponent('com_xxx')->getMVCFactory()->createModel($type, $prefix, $config); */ @@ -114,7 +114,7 @@ public static function getInstance($type, $prefix = '', $config = []) * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement. Get the model through the MVCFactory instead */ public static function addTablePath($path) @@ -133,7 +133,7 @@ public static function addTablePath($path) * * @since 4.0.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Will be removed without replacement */ private static function createModelFromComponent($type, $prefix = '', $config = []): ?ModelInterface diff --git a/libraries/src/MVC/Model/ListModel.php b/libraries/src/MVC/Model/ListModel.php index 1ef86f7d17281..3d427a73fc1cc 100644 --- a/libraries/src/MVC/Model/ListModel.php +++ b/libraries/src/MVC/Model/ListModel.php @@ -89,16 +89,6 @@ class ListModel extends BaseDatabaseModel implements FormFactoryAwareInterface, */ protected $htmlFormName = 'adminForm'; - /** - * A list of filter variables to not merge into the model's state - * - * @var array - * @since 3.4.5 - * @deprecated 4.0 will be removed in 6.0 - * Use $filterForbiddenList instead - */ - protected $filterBlacklist = []; - /** * A list of forbidden filter variables to not merge into the model's state * @@ -107,16 +97,6 @@ class ListModel extends BaseDatabaseModel implements FormFactoryAwareInterface, */ protected $filterForbiddenList = []; - /** - * A list of forbidden variables to not merge into the model's state - * - * @var array - * @since 3.4.5 - * @deprecated 4.0 will be removed in 6.0 - * Use $listForbiddenList instead - */ - protected $listBlacklist = ['select']; - /** * A list of forbidden variables to not merge into the model's state * @@ -147,22 +127,6 @@ public function __construct($config = [], ?MVCFactoryInterface $factory = null) if (empty($this->context)) { $this->context = strtolower($this->option . '.' . $this->getName()); } - - /** - * @deprecated 4.0 will be removed in 6.0 - * Use $this->filterForbiddenList instead - */ - if (!empty($this->filterBlacklist)) { - $this->filterForbiddenList = array_merge($this->filterBlacklist, $this->filterForbiddenList); - } - - /** - * @deprecated 4.0 will be removed in 6.0 - * Use $this->listForbiddenList instead - */ - if (!empty($this->listBlacklist)) { - $this->listForbiddenList = array_merge($this->listBlacklist, $this->listForbiddenList); - } } /** @@ -299,7 +263,7 @@ public function getItems() */ protected function getListQuery() { - return $this->getDatabase()->getQuery(true); + return $this->getDatabase()->createQuery(); } /** @@ -427,7 +391,7 @@ public function getFilterForm($data = [], $loadData = true) { // Try to locate the filter form automatically. Example: ContentModelArticles => "filter_articles" if (empty($this->filterFormName)) { - $classNameParts = explode('Model', \get_called_class()); + $classNameParts = explode('Model', static::class); if (\count($classNameParts) >= 2) { $this->filterFormName = 'filter_' . str_replace('\\', '', strtolower($classNameParts[1])); diff --git a/libraries/src/MVC/Model/WorkflowBehaviorTrait.php b/libraries/src/MVC/Model/WorkflowBehaviorTrait.php index 232f6bcabee96..c3012931fe1bf 100644 --- a/libraries/src/MVC/Model/WorkflowBehaviorTrait.php +++ b/libraries/src/MVC/Model/WorkflowBehaviorTrait.php @@ -83,7 +83,7 @@ public function setUpWorkflow($extension) if (method_exists($this, 'getDatabase')) { $db = $this->getDatabase(); } else { - @trigger_error('From 6.0 implementing the getDatabase method will be mandatory.', E_USER_DEPRECATED); + @trigger_error('From 7.0 implementing the getDatabase method will be mandatory.', E_USER_DEPRECATED); $db = Factory::getContainer()->get(DatabaseDriver::class); } @@ -341,6 +341,10 @@ protected function addTransitionField(Form $form, $data) $field->addAttribute('label', 'COM_CONTENT_WORKFLOW_STAGE'); $field->addAttribute('extension', $extension); + if ($this->workflowEnabled) { + $field->addAttribute('layout', 'joomla.form.field.groupedlist-transition'); + } + $form->setField($field); $table = $this->getTable(); diff --git a/libraries/src/MVC/View/AbstractView.php b/libraries/src/MVC/View/AbstractView.php index a754c187fc501..b405de861dda0 100644 --- a/libraries/src/MVC/View/AbstractView.php +++ b/libraries/src/MVC/View/AbstractView.php @@ -50,7 +50,7 @@ abstract class AbstractView implements ViewInterface, DispatcherAwareInterface, * @var Document * @since 3.0 * - * @deprecated 4.4.0 will be removed in 6.0 + * @deprecated 4.4.0 will be made private in 7.0 * Use $this->getDocument() instead */ public $document; @@ -297,7 +297,7 @@ public function setDocument(Document $document): void * Get the event dispatcher. * * The override was made to keep a backward compatibility for legacy component. - * TODO: Remove the override in 6.0 + * TODO: Remove the override ONLY when support of Legacy components will be removed (components without Dispatcher and MVCFactory). * * @return DispatcherInterface * @@ -308,7 +308,7 @@ public function getDispatcher() { if (!$this->dispatcher) { @trigger_error( - \sprintf('Dispatcher for %s should be set through MVC factory. It will throw an exception in 6.0', __CLASS__), + \sprintf('Dispatcher for %s should be set through MVC factory. It will throw an exception in 7.0', __CLASS__), E_USER_DEPRECATED ); @@ -327,7 +327,7 @@ public function getDispatcher() * * @since 4.1.0 * - * @deprecated 4.4 will be removed in 6.0. Use $this->getDispatcher() directly. + * @deprecated 4.4 will be removed in 7.0. Use $this->getDispatcher() directly. */ protected function dispatchEvent(EventInterface $event) { @@ -335,7 +335,7 @@ protected function dispatchEvent(EventInterface $event) @trigger_error( \sprintf( - 'Method %s is deprecated and will be removed in 6.0. Use getDispatcher()->dispatch() directly.', + 'Method %s is deprecated and will be removed in 7.0. Use getDispatcher()->dispatch() directly.', __METHOD__ ), E_USER_DEPRECATED diff --git a/libraries/src/MVC/View/CategoryFeedView.php b/libraries/src/MVC/View/CategoryFeedView.php index d2b15a2b93a52..7e47a124473b5 100644 --- a/libraries/src/MVC/View/CategoryFeedView.php +++ b/libraries/src/MVC/View/CategoryFeedView.php @@ -45,7 +45,7 @@ public function display($tpl = null) $contentType = $extension . '.' . $this->viewName; $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('ct') . '.*') ->from($db->quoteName('#__content_types', 'ct')) ->where($db->quoteName('ct.type_alias') . ' = :alias') diff --git a/libraries/src/MVC/View/CategoryView.php b/libraries/src/MVC/View/CategoryView.php index b0f7fb5e751b2..e61e64f79bfc2 100644 --- a/libraries/src/MVC/View/CategoryView.php +++ b/libraries/src/MVC/View/CategoryView.php @@ -10,6 +10,10 @@ namespace Joomla\CMS\MVC\View; use Joomla\CMS\Categories\CategoryNode; +use Joomla\CMS\Event\Content\AfterDisplayEvent; +use Joomla\CMS\Event\Content\AfterTitleEvent; +use Joomla\CMS\Event\Content\BeforeDisplayEvent; +use Joomla\CMS\Event\Content\ContentPrepareEvent; use Joomla\CMS\Factory; use Joomla\CMS\Helper\TagsHelper; use Joomla\CMS\Language\Text; @@ -184,7 +188,8 @@ public function commonCategoryDisplay() $this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', '')); if ($this->runPlugins) { - PluginHelper::importPlugin('content'); + $dispatcher = $this->getDispatcher(); + PluginHelper::importPlugin('content', null, true, $dispatcher); foreach ($items as $itemElement) { $itemElement = (object) $itemElement; @@ -193,25 +198,34 @@ public function commonCategoryDisplay() // For some plugins. !empty($itemElement->description) ? $itemElement->text = $itemElement->description : $itemElement->text = ''; - Factory::getApplication()->triggerEvent('onContentPrepare', [$this->extension . '.category', $itemElement, $itemElement->params, 0]); - - $results = Factory::getApplication()->triggerEvent( - 'onContentAfterTitle', - [$this->extension . '.category', $itemElement, $itemElement->core_params ?? $itemElement->params, 0] + $dispatcher->dispatch( + 'onContentPrepare', + new ContentPrepareEvent('onContentPrepare', [ + 'context' => $this->extension . '.category', + 'subject' => $itemElement, + 'params' => $itemElement->params, + 'page' => 0, + ]) ); - $itemElement->event->afterDisplayTitle = trim(implode("\n", $results)); - $results = Factory::getApplication()->triggerEvent( - 'onContentBeforeDisplay', - [$this->extension . '.category', $itemElement, $itemElement->core_params ?? $itemElement->params, 0] - ); - $itemElement->event->beforeDisplayContent = trim(implode("\n", $results)); + $contentEventArguments = [ + 'context' => $this->extension . '.category', + 'subject' => $itemElement, + 'params' => $itemElement->core_params ?? $itemElement->params, + 'page' => 0, + ]; - $results = Factory::getApplication()->triggerEvent( - 'onContentAfterDisplay', - [$this->extension . '.category', $itemElement, $itemElement->core_params ?? $itemElement->params, 0] - ); - $itemElement->event->afterDisplayContent = trim(implode("\n", $results)); + $contentEvents = [ + 'afterDisplayTitle' => new AfterTitleEvent('onContentAfterTitle', $contentEventArguments), + 'beforeDisplayContent' => new BeforeDisplayEvent('onContentBeforeDisplay', $contentEventArguments), + 'afterDisplayContent' => new AfterDisplayEvent('onContentAfterDisplay', $contentEventArguments), + ]; + + foreach ($contentEvents as $resultKey => $event) { + $results = $dispatcher->dispatch($event->getName(), $event)->getArgument('result', []); + + $itemElement->event->{$resultKey} = trim(implode("\n", $results)); + } if ($itemElement->text) { $itemElement->description = $itemElement->text; diff --git a/libraries/src/MVC/View/FormView.php b/libraries/src/MVC/View/FormView.php index 9d0e421818e88..6591073732f40 100644 --- a/libraries/src/MVC/View/FormView.php +++ b/libraries/src/MVC/View/FormView.php @@ -12,9 +12,17 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Form\Form; +use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Text; +use Joomla\CMS\MVC\Model\AdminModel; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Router\Route; use Joomla\CMS\Table\TableInterface; +use Joomla\CMS\Toolbar\Toolbar; use Joomla\CMS\Toolbar\ToolbarHelper; +use Joomla\CMS\Versioning\VersionableModelInterface; +use Joomla\CMS\Versioning\VersionableTableInterface; +use Joomla\Component\Associations\Administrator\Helper\AssociationsHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -64,6 +72,13 @@ class FormView extends HtmlView */ protected $canDo; + /** + * Array of fieldsets not to display + * + * @var string[] + */ + public $ignore_fieldsets = []; + /** * The toolbar title * @@ -85,6 +100,13 @@ class FormView extends HtmlView */ protected $previewLink; + /** + * The jooa11y link + * + * @var string + */ + protected $jooa11yLink; + /** * The help link * @@ -92,6 +114,20 @@ class FormView extends HtmlView */ protected $helpLink; + /** + * Set to true, if saving to menu should be supported + * + * @var boolean + */ + protected $supportSaveMenu = false; + + /** + * Holds the extension for categories, if available + * + * @var string + */ + protected $categorySection; + /** * Constructor * @@ -105,6 +141,14 @@ public function __construct(array $config) $this->helpLink = $config['help_link']; } + if (isset($config['preview_link'])) { + $this->previewLink = $config['preview_link']; + } + + if (isset($config['jooa11y_link'])) { + $this->jooa11yLink = $config['jooa11y_link']; + } + if (isset($config['toolbar_icon'])) { $this->toolbarIcon = $config['toolbar_icon']; } else { @@ -127,14 +171,13 @@ public function __construct(array $config) */ public function display($tpl = null) { + $model = $this->getModel(); + + $model->setUseExceptions(true); + // Prepare view data $this->initializeView(); - // Check for errors. - if (\count($errors = $this->get('Errors'))) { - throw new GenericDataException(implode("\n", $errors), 500); - } - // Build toolbar $this->addToolbar(); @@ -148,10 +191,15 @@ public function display($tpl = null) */ protected function initializeView() { - $this->form = $this->get('Form'); - $this->item = $this->get('Item'); - $this->state = $this->get('State'); - $table = $this->get('Table'); + /** + * @var AdminModel + */ + $model = $this->getModel(); + + $this->form = $model->getForm(); + $this->item = $model->getItem(); + $this->state = $model->getState(); + $table = $model->getTable(); $this->keyName = $table instanceof TableInterface ? $table->getKeyName() : 'id'; $action = empty($this->item->{$this->keyName}) ? '_NEW' : '_EDIT'; @@ -175,81 +223,161 @@ protected function addToolbar() $userId = $user->id; $isNew = empty($this->item->{$this->keyName}); $viewName = $this->getName(); - $checkedOut = $this->getModel()->isCheckedOut($this->item); + $checkedOut = !$isNew && $this->getModel()->isCheckedOut($this->item); $canDo = $this->canDo; + /** + * @var Toolbar $toolbar + */ + $toolbar = $this->getDocument()->getToolbar(); + ToolbarHelper::title( $this->toolbarTitle, $this->toolbarIcon ); // For new records, check the create permission. - if ($isNew && $canDo->get('core.create')) { - ToolbarHelper::saveGroup( - [ - ['apply', $viewName . '.apply'], - ['save', $viewName . '.save'], - ['save2new', $viewName . '.save2new'], - ], - 'btn-success' - ); + if ($isNew) { + if ($canDo->get('core.create') || (isset($this->categorySection) && \count($user->getAuthorisedCategories($this->categorySection, 'core.create')) > 0)) { + $toolbar->apply($viewName . '.apply'); + + $saveGroup = $toolbar->dropdownButton('save-group'); + + $saveGroup->configure( + function (Toolbar $childBar) use ($user, $viewName) { + $childBar->save($viewName . '.save'); + + if ($this->supportSaveMenu && $user->authorise('core.create', 'com_menus.menu')) { + $childBar->save($viewName . '.save2menu', 'JTOOLBAR_SAVE_TO_MENU'); + } - ToolbarHelper::cancel($viewName . '.cancel'); + $childBar->save2new($viewName . '.save2new'); + } + ); + } + + $toolbar->cancel($viewName . '.cancel', 'JTOOLBAR_CANCEL'); } else { + $itemEditable = $canDo->get('core.edit'); + // Since it's an existing record, check the edit permission, or fall back to edit own if the owner. if (property_exists($this->item, 'created_by')) { - $itemEditable = $canDo->get('core.edit') || ($canDo->get('core.edit.own') && $this->item->created_by == $userId); - } else { - $itemEditable = $canDo->get('core.edit'); + $itemEditable = $itemEditable || ($canDo->get('core.edit.own') && $this->item->created_by == $userId); } - $toolbarButtons = []; - - // Can't save the record if it's checked out and editable if (!$checkedOut && $itemEditable) { - $toolbarButtons[] = ['apply', $viewName . '.apply']; - $toolbarButtons[] = ['save', $viewName . '.save']; + $toolbar->apply($viewName . '.apply'); + } - // We can save this record, but check the create permission to see if we can return to make a new one. - if ($canDo->get('core.create')) { - $toolbarButtons[] = ['save2new', $viewName . '.save2new']; + $saveGroup = $toolbar->dropdownButton('save-group'); + + $saveGroup->configure( + function (Toolbar $childBar) use ($checkedOut, $itemEditable, $canDo, $user, $viewName) { + // Can't save the record if it's checked out and editable + if (!$checkedOut && $itemEditable) { + $childBar->save($viewName . '.save'); + + // We can save this record, but check the create permission to see if we can return to make a new one. + if ($canDo->get('core.create')) { + $childBar->save2new($viewName . '.save2new'); + } + } + + // If checked out, we can still save2menu + if ($this->supportSaveMenu && $user->authorise('core.create', 'com_menus.menu')) { + $childBar->save($viewName . '.save2menu', 'JTOOLBAR_SAVE_TO_MENU'); + } + + // If checked out, we can still save + if ($canDo->get('core.create')) { + $childBar->save2copy($viewName . '.save2copy'); + } } - } + ); - // If checked out, we can still save - if ($canDo->get('core.create')) { - $toolbarButtons[] = ['save2copy', $viewName . '.save2copy']; - } + $toolbar->cancel($viewName . '.cancel', 'JTOOLBAR_CLOSE'); - ToolbarHelper::saveGroup( - $toolbarButtons, - 'btn-success' - ); + if ($this->isVersionHistoryAvailable() && $itemEditable) { + $toolbar->versions( + $this->option . '.' . $viewName, + $this->item->{$this->keyName} + ); + } - if (ComponentHelper::isEnabled('com_contenthistory') && $this->state->get('params')->get('save_history', 0) && $itemEditable) { - ToolbarHelper::versions($this->option . '.' . $viewName, $this->item->id); + if ($this->previewLink) { + $toolbar->preview(Route::link('site', $this->previewLink, true), Text::_('JGLOBAL_PREVIEW')) + ->bodyHeight(80) + ->modalWidth(90); } - if (!$isNew && $this->previewLink) { - ToolbarHelper::preview($this->previewLink, Text::_('JGLOBAL_PREVIEW'), 'eye', 80, 90); + if ($this->jooa11yLink && PluginHelper::isEnabled('system', 'jooa11y')) { + $toolbar->jooa11y(Route::link('site', $this->jooa11yLink, true), 'JGLOBAL_JOOA11Y') + ->bodyHeight(80) + ->modalWidth(90); } - ToolbarHelper::cancel($viewName . '.cancel', 'JTOOLBAR_CLOSE'); + if ( + Associations::isEnabled() && + ComponentHelper::isEnabled('com_associations') && + AssociationsHelper::hasSupport($this->option) + ) { + $toolbar->standardButton('contract', 'JTOOLBAR_ASSOCIATIONS', $viewName . '.editAssociations') + ->icon('icon-contract') + ->listCheck(false); + } } - ToolbarHelper::divider(); + $toolbar->divider(); if ($this->form instanceof Form) { $formConfig = $this->form->getXml()->config->inlinehelp; if ($formConfig && (string) $formConfig['button'] === 'show') { $targetClass = (string) $formConfig['targetclass'] ?: 'hide-aware-inline-help'; - ToolbarHelper::inlinehelp($targetClass); + + $toolbar->inlinehelp($targetClass); } } if ($this->helpLink) { - ToolbarHelper::help($this->helpLink); + $toolbar->help($this->helpLink); } } + + /** + * Method to check if version history is available for this view. + * + * + * @return boolean True if version history is available, false otherwise. + * + * @since __DEPPLOY_VERSION__ + */ + protected function isVersionHistoryAvailable(): bool + { + if (!ComponentHelper::isEnabled('com_contenthistory')) { + return false; + } + + if (!$this->state->get('params')->get('save_history', 0)) { + return false; + } + + $model = $this->getModel(); + + // Check if the view support version history uses modern implementation + if ($model instanceof VersionableModelInterface) { + return true; + } + + // Check if view support version history uses legacy implementation + if (PluginHelper::isEnabled('behaviour', 'versionable')) { + $table = $model->getTable(); + + if ($table instanceof VersionableTableInterface) { + return true; + } + } + + return false; + } } diff --git a/libraries/src/MVC/View/HtmlView.php b/libraries/src/MVC/View/HtmlView.php index aefdf17f69680..e2b04263a35d1 100644 --- a/libraries/src/MVC/View/HtmlView.php +++ b/libraries/src/MVC/View/HtmlView.php @@ -203,7 +203,7 @@ public function display($tpl = null) $result = $this->loadTemplate($tpl); - $eventResult = $app->getDispatcher()->dispatch( + $event = $app->getDispatcher()->dispatch( 'onAfterDisplay', AbstractEvent::create( 'onAfterDisplay', @@ -216,9 +216,7 @@ public function display($tpl = null) ) ); - $eventResult->getArgument('used', false); - - echo $result; + echo $event->getArgument('source', $result); } /** @@ -372,16 +370,22 @@ public function loadTemplate($tpl = null) // Clean the template name $layoutTemplate = isset($layoutTemplate) ? preg_replace('/[^A-Z0-9_-]/i', '', $layoutTemplate) : $layoutTemplate; - try { - // Load the language file for the template - $lang = $this->getLanguage(); - } catch (\UnexpectedValueException $e) { - $lang = Factory::getApplication()->getLanguage(); - } + if (Factory::getApplication()->getDocument()->getType() !== 'html') { + try { + // Load the language file for the template + $lang = $this->getLanguage(); + } catch (\UnexpectedValueException $e) { + $lang = Factory::getApplication()->getLanguage(); + } - $lang->load('tpl_' . $template->template, JPATH_BASE) - || $lang->load('tpl_' . $template->parent, JPATH_THEMES . '/' . $template->parent) - || $lang->load('tpl_' . $template->template, JPATH_THEMES . '/' . $template->template); + if ($template->parent) { + $lang->load('tpl_' . $template->parent, JPATH_THEMES . '/' . $template->parent) + || $lang->load('tpl_' . $template->parent, JPATH_BASE); + } + + $lang->load('tpl_' . $template->template, JPATH_BASE) + || $lang->load('tpl_' . $template->template, JPATH_THEMES . '/' . $template->template); + } // Change the template folder if alternative layout is in different template if (isset($layoutTemplate) && $layoutTemplate !== '_' && $layoutTemplate != $template->template) { diff --git a/libraries/src/MVC/View/ListView.php b/libraries/src/MVC/View/ListView.php index e36f955f986dc..23fdcc13875de 100644 --- a/libraries/src/MVC/View/ListView.php +++ b/libraries/src/MVC/View/ListView.php @@ -12,7 +12,6 @@ use Doctrine\Inflector\InflectorFactory; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; -use Joomla\CMS\Layout\FileLayout; use Joomla\CMS\Toolbar\ToolbarHelper; use Joomla\Registry\Registry; @@ -34,7 +33,7 @@ class ListView extends HtmlView * * @var array */ - protected $items; + protected $items = []; /** * The pagination object @@ -69,7 +68,7 @@ class ListView extends HtmlView * * @var array */ - public $activeFilters; + public $activeFilters = []; /** * The sidebar markup @@ -92,6 +91,13 @@ class ListView extends HtmlView */ protected $toolbarIcon; + /** + * The flag which determine whether we want to show archive button + * + * @var boolean + */ + protected $supportsArchive = false; + /** * The flag which determine whether we want to show batch button * @@ -99,6 +105,23 @@ class ListView extends HtmlView */ protected $supportsBatch = true; + /** + * The flag which determine if the current user is allowed to perform batch actions. It is + * used in layout to determine if we need to render batch layout + * + * @var boolean + */ + protected $batchAllowed = false; + + /** + * Holds the extension for categories, if available + * + * @var string + * + * @since 6.0.0 + */ + protected $categorySection; + /** * The help link for the view * @@ -106,6 +129,15 @@ class ListView extends HtmlView */ protected $helpLink; + /** + * Is this view an Empty State + * + * @var boolean + * + * @since 6.0.0 + */ + private $isEmptyState = false; + /** * Constructor * @@ -132,6 +164,10 @@ public function __construct(array $config) $this->supportsBatch = $config['supports_batch']; } + if (isset($config['category'])) { + $this->categorySection = $config['category']; + } + if (isset($config['help_link'])) { $this->helpLink = $config['help_link']; } @@ -152,16 +188,21 @@ public function __construct(array $config) */ public function display($tpl = null) { + $model = $this->getModel(); + + $model->setUseExceptions(true); + // Prepare view data $this->initializeView(); - // Check for errors. - if (\count($errors = $this->get('Errors'))) { - throw new GenericDataException(implode("\n", $errors), 500); + if (!\count($this->items) && \is_callable([$model, 'getIsEmptyState']) && $this->isEmptyState = $model->getIsEmptyState()) { + $this->setLayout('emptystate'); } - // Build toolbar - $this->addToolbar(); + // We don't need toolbar in the modal window. + if ($this->getLayout() !== 'modal') { + $this->addToolbar(); + } parent::display($tpl); } @@ -187,11 +228,20 @@ protected function initializeView() $this->sidebar = HTMLHelper::_('sidebar.render'); } - $this->items = $this->get('Items'); - $this->pagination = $this->get('Pagination'); - $this->state = $this->get('State'); - $this->filterForm = $this->get('FilterForm'); - $this->activeFilters = $this->get('ActiveFilters'); + $model = $this->getModel(); + + $this->items = $model->getItems(); + $this->pagination = $model->getPagination(); + $this->state = $model->getState(); + $this->filterForm = $model->getFilterForm(); + $this->activeFilters = $model->getActiveFilters(); + + // Add form control fields + if ($this->filterForm !== null) { + $this->filterForm + ->addControlField('task') + ->addControlField('boxchecked', '0'); + } } /** @@ -206,68 +256,88 @@ protected function addToolbar() $canDo = $this->canDo; $user = $this->getCurrentUser(); - // Get the toolbar object instance - $bar = $this->getDocument()->getToolbar(); + /** + * @var \Joomla\CMS\Toolbar\Toolbar $toolbar + */ + $toolbar = $this->getDocument()->getToolbar(); $viewName = $this->getName(); $singularViewName = InflectorFactory::create()->build()->singularize($viewName); ToolbarHelper::title(Text::_($this->toolbarTitle), $this->toolbarIcon); - if ($canDo->get('core.create')) { - ToolbarHelper::addNew($singularViewName . '.add'); + // @todo here we should add category support with some parameters + if ($canDo->get('core.create') || (isset($this->categorySection) && \count($user->getAuthorisedCategories($this->categorySection, 'core.create')) > 0)) { + $toolbar->addNew($singularViewName . '.add'); } - if (($canDo->get('core.edit')) || ($canDo->get('core.edit.own'))) { - ToolbarHelper::editList($singularViewName . '.edit'); - } + if (!$this->isEmptyState && $canDo->get('core.edit.state')) { + /** @var \Joomla\CMS\Toolbar\Button\DropdownButton $dropdown */ + $dropdown = $toolbar->dropdownButton('status-group', 'JTOOLBAR_CHANGE_STATUS') + ->toggleSplit(false) + ->icon('icon-ellipsis-h') + ->buttonClass('btn btn-action') + ->listCheck(true); + + $childBar = $dropdown->getChildToolbar(); - if ($canDo->get('core.edit.state')) { - ToolbarHelper::publish($viewName . '.publish', 'JTOOLBAR_PUBLISH', true); - ToolbarHelper::unpublish($viewName . '.unpublish', 'JTOOLBAR_UNPUBLISH', true); + $childBar->publish($viewName . '.publish')->listCheck(true); + $childBar->unpublish($viewName . '.unpublish')->listCheck(true); if (isset($this->items[0]->featured)) { - ToolbarHelper::custom($viewName . '.featured', 'featured', '', 'JFEATURE', true); - ToolbarHelper::custom($viewName . '.unfeatured', 'unfeatured', '', 'JUNFEATURE', true); + $childBar->standardButton('featured', 'JFEATURE', $viewName . '.featured')->listCheck(true); + $childBar->standardButton('unfeatured', 'JUNFEATURE', $viewName . '.unfeatured')->listCheck(true); } - ToolbarHelper::archiveList($viewName . '.archive'); - ToolbarHelper::checkin($viewName . '.checkin'); - } + if ($this->supportsArchive) { + $childBar->archive($viewName . '.archive')->listCheck(true); + } - // Add a batch button - if ( - $this->supportsBatch && $user->authorise('core.create', $this->option) - && $user->authorise('core.edit', $this->option) - && $user->authorise('core.edit.state', $this->option) - ) { - $title = Text::_('JTOOLBAR_BATCH'); + if ($user->authorise('core.admin')) { + $childBar->checkin($viewName . '.checkin'); + } - // Instantiate a new LayoutFile instance and render the popup button - $layout = new FileLayout('joomla.toolbar.popup'); + if ($this->state->get('filter.published') != -2) { + $childBar->trash($viewName . '.trash')->listCheck(true); + } - $dhtml = $layout->render(['title' => $title]); - $bar->appendButton('Custom', $dhtml, 'batch'); + // Add a batch button + if ( + $this->supportsBatch && $user->authorise('core.create', $this->option) + && $user->authorise('core.create', $this->option) + && $user->authorise('core.edit', $this->option) + ) { + $childBar->popupButton('batch', 'JTOOLBAR_BATCH') + ->popupType('inline') + ->textHeader(Text::_($this->option . '_BATCH_OPTIONS')) + ->url('#joomla-dialog-batch') + ->modalWidth('800px') + ->modalHeight('fit-content') + ->listCheck(true); + + $this->batchAllowed = true; + } } if ( - $canDo->get('core.delete') && - ( - $this->state->get('filter.state') == -2 || - $this->state->get('filter.published') == -2 + !$this->isEmptyState + && $canDo->get('core.delete') + && ( + $this->state->get('filter.state') == -2 + || $this->state->get('filter.published') == -2 ) ) { - ToolbarHelper::deleteList('JGLOBAL_CONFIRM_DELETE', $viewName . '.delete', 'JTOOLBAR_DELETE_FROM_TRASH'); - } elseif ($canDo->get('core.edit.state')) { - ToolbarHelper::trash($viewName . '.trash'); + $toolbar->delete($viewName . '.delete', 'JTOOLBAR_DELETE_FROM_TRASH') + ->message('JGLOBAL_CONFIRM_DELETE') + ->listCheck(true); } if ($user->authorise('core.admin', $this->option) || $user->authorise('core.options', $this->option)) { - ToolbarHelper::preferences($this->option); + $toolbar->preferences($this->option); } if ($this->helpLink) { - ToolbarHelper::help($this->helpLink); + $toolbar->help($this->helpLink); } } } diff --git a/libraries/src/Mail/FormatConfigurableMailerInterface.php b/libraries/src/Mail/FormatConfigurableMailerInterface.php new file mode 100644 index 0000000000000..7d98600f2285d --- /dev/null +++ b/libraries/src/Mail/FormatConfigurableMailerInterface.php @@ -0,0 +1,33 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Mail; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Provides a common interface to send emails with HTML. + * + * @since 6.2.0 + */ +interface FormatConfigurableMailerInterface +{ + /** + * Sets message type to HTML. + * + * @param boolean $ishtml Boolean true or false. + * + * @return FormatConfigurableMailerInterface Returns this object for chaining. + * + * @since 6.2.0 + */ + public function isHtml($ishtml = true); +} diff --git a/libraries/src/Mail/Mail.php b/libraries/src/Mail/Mail.php index 91a52379f3bc1..873bec62d7d02 100644 --- a/libraries/src/Mail/Mail.php +++ b/libraries/src/Mail/Mail.php @@ -25,7 +25,7 @@ * * @since 1.7.0 */ -class Mail extends PHPMailer implements MailerInterface +class Mail extends PHPMailer implements MailerInterface, TransportConfigurableMailerInterface, FormatConfigurableMailerInterface { /** * Mail instances container. @@ -33,7 +33,7 @@ class Mail extends PHPMailer implements MailerInterface * @var Mail[] * @since 1.7.3 * - * @deprecated 4.4.0 will be removed in 6.0 + * @deprecated 4.4.0 will be removed in 7.0 * See getInstance() for more details */ public static $instances = []; @@ -105,7 +105,7 @@ public function __construct($exceptions = true) * * @since 4.4.0 * - * @deprecated 4.4.0 will be removed in 6.0 + * @deprecated 4.4.0 will be removed in 7.0 * Use the mailer service in the DI container and create a mailer from there * Example: * Factory::getContainer()->get(MailerFactoryInterface::class)->createMailer(); diff --git a/libraries/src/Mail/MailTemplate.php b/libraries/src/Mail/MailTemplate.php index d2c80c5a428f3..6bfe11459efdd 100644 --- a/libraries/src/Mail/MailTemplate.php +++ b/libraries/src/Mail/MailTemplate.php @@ -17,6 +17,8 @@ use Joomla\CMS\Layout\FileLayout; use Joomla\CMS\Mail\Exception\MailDisabledException; use Joomla\Component\Mails\Administrator\Helper\MailsHelper; +use Joomla\Database\DatabaseAwareTrait; +use Joomla\Database\DatabaseInterface; use Joomla\Database\ParameterType; use Joomla\Filesystem\File; use Joomla\Filesystem\Path; @@ -34,10 +36,12 @@ */ class MailTemplate { + use DatabaseAwareTrait; + /** * Mailer object to send the actual mail. * - * @var \Joomla\CMS\Mail\Mail + * @var MailerInterface * @since 4.0.0 */ protected $mailer; @@ -113,33 +117,48 @@ class MailTemplate * The language factory * * @var LanguageFactoryInterface - * @since 5.4.7 + * @since 6.2.0 */ protected LanguageFactoryInterface $languageFactory; /** * Constructor for the mail templating class * - * @param string $templateId Id of the mail template. - * @param string $language Language of the template to use. - * @param ?Mail $mailer Mail object to send the mail with. + * @param string $templateId Id of the mail template. + * @param string $language Language of the template to use. + * @param ?MailerInterface $mailer Mail object to send the mail with. + * @param ?LanguageFactoryInterface $languageFactory The language factory. + * @param ?DatabaseInterface $db The database. * * @since 4.0.0 */ - public function __construct($templateId, $language, ?Mail $mailer = null, ?LanguageFactoryInterface $languageFactory = null) - { + public function __construct( + $templateId, + $language, + ?MailerInterface $mailer = null, + ?LanguageFactoryInterface $languageFactory = null, + ?DatabaseInterface $db = null + ) { $this->template_id = $templateId; $this->language = $language; if ($mailer) { $this->mailer = $mailer; } else { + @trigger_error('Mailer must be set, this will not be caught anymore in 8.0.', E_USER_DEPRECATED); $this->mailer = Factory::getMailer(); } + $this->setDatabase($db ?? Factory::getContainer()->get(DatabaseInterface::class)); + + if ($db === null) { + @trigger_error('Database must be set, this will not be caught anymore in 8.0.', E_USER_DEPRECATED); + } + if ($languageFactory) { $this->languageFactory = $languageFactory; } else { + @trigger_error('Language factory must be set, this will not be caught anymore in 8.0.', E_USER_DEPRECATED); $this->languageFactory = Factory::getContainer()->get(LanguageFactoryInterface::class); } } @@ -233,6 +252,20 @@ public function addTemplateData($data, $plain = false) } } + /** + * Get the template data. + * + * @param bool $plain Data used for plain-text emails. + * + * @return array + * + * @since 6.1.0 + */ + public function getTemplateData($plain = false): array + { + return !$plain ? $this->data : $this->plain_data; + } + /** * Mark tags as unsafe to ensure escaping in HTML mails * @@ -261,7 +294,7 @@ public function send() { $config = ComponentHelper::getParams('com_mails'); - $mail = static::getTemplate($this->template_id, $this->language); + $mail = $this->loadTemplate($this->template_id, $this->language); // If the Mail Template was not found in the db, we cannot send an email. if ($mail === null) { @@ -281,7 +314,7 @@ public function send() } if ((int) $config->get('alternative_mailconfig', 0) === 1 && (int) $params->get('alternative_mailconfig', 0) === 1) { - if ($this->mailer->Mailer === 'smtp' || $params->get('mailer') === 'smtp') { + if ($this->mailer instanceof TransportConfigurableMailerInterface && $params->get('mailer') === 'smtp') { $smtpauth = ($params->get('smtpauth', $app->get('smtpauth')) == 0) ? null : 1; $smtpuser = $params->get('smtpuser', $app->get('smtpuser')); $smtppass = $params->get('smtppass', $app->get('smtppass')); @@ -291,15 +324,15 @@ public function send() $this->mailer->useSmtp($smtpauth, $smtphost, $smtpuser, $smtppass, $smtpsecure, $smtpport); } - if ($params->get('mailer') === 'sendmail') { - $this->mailer->isSendmail(); + if ($this->mailer instanceof TransportConfigurableMailerInterface && $params->get('mailer') === 'sendmail') { + $this->mailer->useSendmail('joomla'); } $mailfrom = $params->get('mailfrom', $app->get('mailfrom')); $fromname = $params->get('fromname', $app->get('fromname')); if (MailHelper::isEmailAddress($mailfrom)) { - $this->mailer->setFrom(MailHelper::cleanLine($mailfrom), MailHelper::cleanLine($fromname), false); + $this->mailer->setSender(MailHelper::cleanLine($mailfrom), MailHelper::cleanLine($fromname)); } $replyTo = $params->get('replyto', $replyTo); @@ -342,7 +375,9 @@ public function send() } if ($mailStyle === 'html' || $mailStyle === 'both') { - $this->mailer->isHtml(true); + if ($this->mailer instanceof FormatConfigurableMailerInterface) { + $this->mailer->isHtml(true); + } // If HTML body is empty try to convert the Plain template to html if (!$htmlBody) { @@ -396,7 +431,7 @@ public function send() ]); } - $htmlBody = $layoutFile->render(['mail' => $htmlBody, 'extra' => $this->layoutTemplateData], null); + $htmlBody = $layoutFile->render(['mail' => $htmlBody, 'extra' => $this->layoutTemplateData]); $htmlBody = $this->replaceTags($language->_($htmlBody), $this->data); } @@ -420,7 +455,7 @@ public function send() break; case 'to': default: - $this->mailer->addAddress($recipient->mail, $recipient->name); + $this->mailer->addRecipient($recipient->mail, $recipient->name); } } @@ -444,15 +479,29 @@ public function send() } } + $tmpAttachmentFiles = []; foreach ($this->attachments as $attachment) { if (is_file($attachment->file)) { $this->mailer->addAttachment($attachment->file, $this->getAttachmentName($attachment->file, $attachment->name)); - } else { + } elseif ($this->mailer instanceof Mail) { $this->mailer->addStringAttachment($attachment->file, $attachment->name); + } else { + // If the mailer does not support string attachments, create a temporary file and attach it + $tmpFile = tempnam(JPATH_CACHE, 'mailattachment_'); + if (file_put_contents($tmpFile, $attachment->file) !== false) { + $this->mailer->addAttachment($tmpFile, $attachment->name); + $tmpAttachmentFiles[] = $tmpFile; + } } } - return $this->mailer->Send(); + $success = $this->mailer->send(); + + foreach ($tmpAttachmentFiles as $tmpFile) { + @unlink($tmpFile); + } + + return $success; } /** @@ -504,7 +553,7 @@ protected function replaceTags($text, $tags, $isHtml = false) } } - $text = str_replace($match, $replacement, $text); + $text = str_ireplace($match, $replacement, $text); } } } else { @@ -513,7 +562,7 @@ protected function replaceTags($text, $tags, $isHtml = false) $value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8'); } - $text = str_replace('{' . strtoupper($key) . '}', $value, $text); + $text = str_ireplace('{' . strtoupper($key) . '}', $value, $text); } } @@ -521,19 +570,19 @@ protected function replaceTags($text, $tags, $isHtml = false) } /** - * Get a specific mail template + * Get a specific mail template for the given key and language. * * @param string $key Template identifier * @param string $language Language code of the template * - * @return object|null An object with the data of the mail, or null if the template not found in the db. + * @return \stdClass|null An object with the data of the mail, or null if the template not found in the db. * - * @since 4.0.0 + * @since 6.2.0 */ - public static function getTemplate($key, $language) + protected function loadTemplate(string $key, string $language): ?\stdClass { - $db = Factory::getDbo(); - $query = $db->getQuery(true); + $db = $this->getDatabase(); + $query = $db->createQuery(); $query->select('*') ->from($db->quoteName('#__mail_templates')) ->where($db->quoteName('template_id') . ' = :key') @@ -550,6 +599,24 @@ public static function getTemplate($key, $language) return $mail; } + /** + * Get a specific mail template + * + * @param string $key Template identifier + * @param string $language Language code of the template + * + * @return object|null An object with the data of the mail, or null if the template not found in the db. + * + * @since 4.0.0 + * + * @deprecated 6.2.0 this will be removed without replacement in 8.0 + * Use $app->bootComponent('com_mails')->getMVCFactory()->createModel('Template', 'Administrator')->getItem(); instead + */ + public static function getTemplate($key, $language) + { + return (new self($key, $language))->loadTemplate($key, $language); + } + /** * Insert a new mail template into the system * @@ -562,24 +629,23 @@ public static function getTemplate($key, $language) * @return boolean True on success, false on failure * * @since 4.0.0 + * + * @deprecated 6.2.0 this will be removed without replacement in 8.0 + * Use $app->bootComponent('com_mails')->getMVCFactory()->createModel('Template', 'Administrator')->save(); instead */ public static function createTemplate($key, $subject, $body, $tags, $htmlbody = '') { - $db = Factory::getDbo(); - - $template = new \stdClass(); - $template->template_id = $key; - $template->language = ''; - $template->subject = $subject; - $template->body = $body; - $template->htmlbody = $htmlbody; - $template->extension = explode('.', $key, 2)[0] ?? ''; - $template->attachments = ''; - $params = new \stdClass(); - $params->tags = (array) $tags; - $template->params = json_encode($params); - - return $db->insertObject('#__mail_templates', $template); + return Factory::getApplication()->bootComponent('com_mails') + ->getMVCFactory()->createModel('Template', 'Administrator')->save([ + 'template_id' => $key, + 'language' => '', + 'subject' => $subject, + 'body' => $body, + 'htmlbody' => $htmlbody, + 'params' => json_encode(['tags' => (array) $tags]), + 'extension' => explode('.', $key, 2)[0] ?? '', + 'attachments' => '', + ]); } /** @@ -594,22 +660,21 @@ public static function createTemplate($key, $subject, $body, $tags, $htmlbody = * @return boolean True on success, false on failure * * @since 4.0.0 + * + * @deprecated 6.2.0 this will be removed without replacement in 8.0 + * Use $app->bootComponent('com_mails')->getMVCFactory()->createModel('Template', 'Administrator')->save(); instead */ public static function updateTemplate($key, $subject, $body, $tags, $htmlbody = '') { - $db = Factory::getDbo(); - - $template = new \stdClass(); - $template->template_id = $key; - $template->language = ''; - $template->subject = $subject; - $template->body = $body; - $template->htmlbody = $htmlbody; - $params = new \stdClass(); - $params->tags = (array) $tags; - $template->params = json_encode($params); - - return $db->updateObject('#__mail_templates', $template, ['template_id', 'language']); + return Factory::getApplication()->bootComponent('com_mails') + ->getMVCFactory()->createModel('Template', 'Administrator')->save([ + 'template_id' => $key, + 'language' => '', + 'subject' => $subject, + 'body' => $body, + 'htmlbody' => $htmlbody, + 'params' => json_encode(['tags' => (array) $tags]), + ]); } /** @@ -620,17 +685,14 @@ public static function updateTemplate($key, $subject, $body, $tags, $htmlbody = * @return boolean True on success, false on failure * * @since 4.0.0 + * + * @deprecated 6.2.0 this will be removed without replacement in 8.0 + * Use $app->bootComponent('com_mails')->getMVCFactory()->createModel('Template', 'Administrator')->delete(); instead */ public static function deleteTemplate($key) { - $db = Factory::getDbo(); - $query = $db->getQuery(true); - $query->delete($db->quoteName('#__mail_templates')) - ->where($db->quoteName('template_id') . ' = :key') - ->bind(':key', $key); - $db->setQuery($query); - - return $db->execute(); + return Factory::getApplication()->bootComponent('com_mails') + ->getMVCFactory()->createModel('Template', 'Administrator')->delete($key); } /** diff --git a/libraries/src/Mail/TransportConfigurableMailerInterface.php b/libraries/src/Mail/TransportConfigurableMailerInterface.php new file mode 100644 index 0000000000000..afcbe612dbc5e --- /dev/null +++ b/libraries/src/Mail/TransportConfigurableMailerInterface.php @@ -0,0 +1,47 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Mail; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Provides a common interface to send emails through an SMTP or sendmail service. + * + * @since 6.2.0 + */ +interface TransportConfigurableMailerInterface +{ + /** + * Use SMTP for sending the email. + * + * @param string $auth SMTP Authentication [optional] + * @param string $host SMTP Host [optional] + * @param string $user SMTP Username [optional] + * @param string $pass SMTP Password [optional] + * @param string $secure Use secure methods + * @param integer $port The SMTP port + * + * @return boolean True on success + * + * @since 6.2.0 + */ + public function useSmtp($auth = null, $host = null, $user = null, $pass = null, $secure = null, $port = 25); + + /** + * Use sendmail for sending the email. + * + * @return boolean True on success + * + * @since 6.2.0 + */ + public function useSendmail($sendmail = null); +} diff --git a/libraries/src/Menu/AbstractMenu.php b/libraries/src/Menu/AbstractMenu.php index eabff47616c84..f9e541f40edbc 100644 --- a/libraries/src/Menu/AbstractMenu.php +++ b/libraries/src/Menu/AbstractMenu.php @@ -59,7 +59,7 @@ abstract class AbstractMenu * * @since 1.7 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the MenuFactoryInterface from the container instead * Example: Factory::getContainer()->get(MenuFactoryInterface::class)->createMenu($client, $options) */ @@ -117,7 +117,7 @@ public function __construct($options = []) * * @throws \Exception * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use the MenuFactoryInterface from the container instead * Example: Factory::getContainer()->get(MenuFactoryInterface::class)->createMenu($client, $options) */ @@ -395,6 +395,27 @@ protected function getUser() : $this->storedUser; } + /** + * Returns homepages per language. + * + * @return MenuItem[] + * + * @since 6.1.0 + */ + public function getHomepages() + { + // Ensure that defaults are filled. + $this->getMenu(); + + $homepages = []; + + foreach ($this->default as $language => $id) { + $homepages[$language] = $this->items[$id]; + } + + return $homepages; + } + /** * Magic getter for the user object. Returns the injected * one if any, or the current one if none. diff --git a/libraries/src/Menu/SiteMenu.php b/libraries/src/Menu/SiteMenu.php index f99f6015006e8..c33b40c05049c 100644 --- a/libraries/src/Menu/SiteMenu.php +++ b/libraries/src/Menu/SiteMenu.php @@ -69,10 +69,10 @@ public function __construct($options = []) { // Extract the internal dependencies before calling the parent constructor since it calls $this->load() $this->app = isset($options['app']) && $options['app'] instanceof CMSApplication ? $options['app'] : Factory::getApplication(); - $this->language = isset($options['language']) && $options['language'] instanceof Language ? $options['language'] : Factory::getLanguage(); + $this->language = isset($options['language']) && $options['language'] instanceof Language ? $options['language'] : null; if (!isset($options['db']) || !($options['db'] instanceof DatabaseDriver)) { - @trigger_error('Database will be mandatory in 5.0.', E_USER_DEPRECATED); + @trigger_error('Database will be mandatory in 7.0.', E_USER_DEPRECATED); $options['db'] = Factory::getContainer()->get(DatabaseDriver::class); } @@ -93,7 +93,7 @@ public function load() $loader = function () { $currentDate = Factory::getDate()->toSql(); - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select( $this->db->quoteName( [ @@ -191,7 +191,7 @@ public function load() return false; } - foreach ($this->items as &$item) { + foreach ($this->items as $item) { // Get parent information. $parent_tree = []; @@ -233,9 +233,10 @@ public function getItems($attributes, $values, $firstonly = false) if ($this->app->isClient('site')) { // Filter by language if not set if (($key = array_search('language', $attributes)) === false) { - if (Multilanguage::isEnabled()) { + if (Multilanguage::isEnabled() && ($this->language || $this->app->getLanguage())) { + $language = $this->language ?: $this->app->getLanguage(); $attributes[] = 'language'; - $values[] = [Factory::getLanguage()->getTag(), '*']; + $values[] = [$language->getTag(), '*']; } } elseif ($values[$key] === null) { unset($attributes[$key], $values[$key]); diff --git a/libraries/src/Object/CMSObject.php b/libraries/src/Object/CMSObject.php index b94224ab4a009..d94bfd7db6a02 100644 --- a/libraries/src/Object/CMSObject.php +++ b/libraries/src/Object/CMSObject.php @@ -21,7 +21,7 @@ * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use \stdClass or \Joomla\Registry\Registry instead. * Example: new \Joomla\Registry\Registry(); */ @@ -52,7 +52,7 @@ public function __construct($properties = null) * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 3.1.4 will be removed in 7.0 * Classes should provide their own __toString() implementation. */ public function __toString() diff --git a/libraries/src/Object/LegacyErrorHandlingTrait.php b/libraries/src/Object/LegacyErrorHandlingTrait.php index 47686baaab9fb..44fba9af46134 100644 --- a/libraries/src/Object/LegacyErrorHandlingTrait.php +++ b/libraries/src/Object/LegacyErrorHandlingTrait.php @@ -30,7 +30,7 @@ trait LegacyErrorHandlingTrait * * @var array * @since 1.7.0 - * @deprecated 3.1.4 JError has been deprecated + * @deprecated 3.7.0 JError has been deprecated */ // phpcs:disable PSR2.Classes.PropertyDeclaration protected $_errors = []; diff --git a/libraries/src/Object/LegacyPropertyManagementTrait.php b/libraries/src/Object/LegacyPropertyManagementTrait.php index 29537b8cb2674..0960e6536df71 100644 --- a/libraries/src/Object/LegacyPropertyManagementTrait.php +++ b/libraries/src/Object/LegacyPropertyManagementTrait.php @@ -19,7 +19,7 @@ * * @since 4.3.0 * - * @deprecated 4.3.0 will be removed in 6.0 + * @deprecated 4.3.0 will be removed in 7.0 * Will be removed without replacement * Create proper setter functions for the individual properties or use a \Joomla\Registry\Registry */ @@ -35,7 +35,7 @@ trait LegacyPropertyManagementTrait * * @since 1.7.0 * - * @deprecated 4.3.0 will be removed in 6.0 + * @deprecated 4.3.0 will be removed in 7.0 * Defining dynamic properties should not be used anymore */ public function def($property, $default = null) @@ -57,7 +57,7 @@ public function def($property, $default = null) * * @see CMSObject::getProperties() * - * @deprecated 4.3.0 will be removed in 6.0 + * @deprecated 4.3.0 will be removed in 7.0 * Create a proper getter function for the property */ public function get($property, $default = null) @@ -80,7 +80,7 @@ public function get($property, $default = null) * * @see CMSObject::get() * - * @deprecated 4.3.0 will be removed in 6.0 + * @deprecated 4.3.0 will be removed in 7.0 * Create a proper getter function for the property */ public function getProperties($public = true) @@ -126,7 +126,7 @@ public function getProperties($public = true) * * @since 1.7.0 * - * @deprecated 4.3.0 will be removed in 6.0 + * @deprecated 4.3.0 will be removed in 7.0 * Create a proper setter function for the property */ public function set($property, $value = null) @@ -148,7 +148,7 @@ public function set($property, $value = null) * * @see CMSObject::set() * - * @deprecated 4.3.0 will be removed in 6.0 + * @deprecated 4.3.0 will be removed in 7.0 * Create a proper setter function for the property */ public function setProperties($properties) diff --git a/libraries/src/Pathway/Pathway.php b/libraries/src/Pathway/Pathway.php index d4529618fec4c..ab15cc61c0602 100644 --- a/libraries/src/Pathway/Pathway.php +++ b/libraries/src/Pathway/Pathway.php @@ -59,7 +59,7 @@ class Pathway * @since 1.5 * @throws \RuntimeException * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Get the instance from the application * Example: * $app->getPathway() diff --git a/libraries/src/Plugin/CMSPlugin.php b/libraries/src/Plugin/CMSPlugin.php index d45a6a1dda94f..d134dd886f0d7 100644 --- a/libraries/src/Plugin/CMSPlugin.php +++ b/libraries/src/Plugin/CMSPlugin.php @@ -72,24 +72,36 @@ abstract class CMSPlugin implements DispatcherAwareInterface, PluginInterface, L protected $_type = null; /** - * Affects constructor behavior. If true, language files will be loaded automatically. + * If true, language files of the plugin will be loaded automatically. + * + * NOTE: Enabling this feature have a negative effect on performance, + * therefore it is recommended to load a language manually, in the respective event. * * @var boolean * @since 3.1 */ protected $autoloadLanguage = false; + /** + * Internal flag for autoloadLanguage feature. + * + * @var boolean + * + * @since 6.0.0 + */ + private $autoloadLanguageDone = false; + /** * Should I try to detect and register legacy event listeners, i.e. methods which accept unwrapped arguments? While * this maintains a great degree of backwards compatibility to Joomla! 3.x-style plugins it is much slower. You are * advised to implement your plugins using proper Listeners, methods accepting an AbstractEvent as their sole - * parameter, for best performance. Also bear in mind that Joomla! 5.x onwards will only allow proper listeners, + * parameter, for best performance. Also bear in mind that Joomla! 7.0 onwards will only allow proper listeners, * removing support for legacy Listeners. * * @var boolean * @since 4.0.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Implement your plugin methods accepting an AbstractEvent object * Example: * onEventTriggerName(AbstractEvent $event) { @@ -154,11 +166,6 @@ public function __construct($config = []) $this->_type = $config['type']; } - // Load the language files if needed. - if ($this->autoloadLanguage) { - $this->loadLanguage(); - } - if (property_exists($this, 'app')) { @trigger_error('The application should be injected through setApplication() and requested through getApplication().', E_USER_DEPRECATED); $reflection = new \ReflectionClass($this); @@ -178,6 +185,11 @@ public function __construct($config = []) $this->db = Factory::getDbo(); } } + + // Load the language files if needed. + if ($this->autoloadLanguage) { + $this->autoloadLanguage(); + } } /** @@ -193,11 +205,26 @@ public function __construct($config = []) public function loadLanguage($extension = '', $basePath = JPATH_ADMINISTRATOR) { if (empty($extension)) { - $extension = 'Plg_' . $this->_type . '_' . $this->_name; + $extension = 'plg_' . $this->_type . '_' . $this->_name; } $extension = strtolower($extension); - $lang = $this->getApplication() ? $this->getApplication()->getLanguage() : Factory::getLanguage(); + $app = $this->getApplication() ?: Factory::getApplication(); + $lang = $app->getLanguage(); + + if (!$lang) { + // @TODO: Throw an exception in Joomla 7 + @trigger_error( + \sprintf( + 'Trying to load language before Application is initialised is discouraged. This will throw an exception in 7.0. Plugin "%s/%s"', + $this->_type, + $this->_name + ), + E_USER_DEPRECATED + ); + + return false; + } // If language already loaded, don't load it again. if ($lang->getPaths($extension)) { @@ -208,6 +235,45 @@ public function loadLanguage($extension = '', $basePath = JPATH_ADMINISTRATOR) || $lang->load($extension, JPATH_PLUGINS . '/' . $this->_type . '/' . $this->_name); } + /** + * Method to handle language autoload feature in safe way, only when the language is initialised. + * + * @return void + * + * @internal The method does not expect to be called outside the CMSPlugin class. + * + * @since 6.0.0 + */ + final protected function autoloadLanguage(): void + { + if ($this->autoloadLanguageDone) { + return; + } + + $app = $this->getApplication(); + + // Try to get Application from Factory + if (!$app) { + try { + $app = Factory::getApplication(); + } catch (\Exception) { + // Cannot help here + return; + } + } + + // Check whether language already initialised in the Application, otherwise wait for it + if (!$app->getLanguage()) { + $app->getDispatcher()->addListener('onAfterInitialise', function () { + $this->loadLanguage(); + }); + } else { + $this->loadLanguage(); + } + + $this->autoloadLanguageDone = true; + } + /** * Registers legacy Listeners to the Dispatcher, emulating how plugins worked under Joomla! 3.x and below. * @@ -337,7 +403,7 @@ function (AbstractEvent $event) use ($methodName) { /** * Registers a proper event listener, i.e. a method which accepts an AbstractEvent as its sole argument. This is the - * preferred way to implement plugins in Joomla! 4.x and will be the only possible method with Joomla! 5.x onwards. + * preferred way to implement plugins in Joomla! 4.x and will be the only possible method with Joomla! 7.0 onwards. * * @param string $methodName The method name to register * diff --git a/libraries/src/Plugin/PluginHelper.php b/libraries/src/Plugin/PluginHelper.php index 08ac384b26d83..c7a1a1939fed1 100644 --- a/libraries/src/Plugin/PluginHelper.php +++ b/libraries/src/Plugin/PluginHelper.php @@ -13,6 +13,7 @@ use Joomla\CMS\Factory; use Joomla\Event\DispatcherAwareInterface; use Joomla\Event\DispatcherInterface; +use Joomla\Event\SubscriberInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -231,16 +232,26 @@ protected static function import($plugin, $autocreate = true, ?DispatcherInterfa $plugin = Factory::getApplication()->bootPlugin($plugin->name, $plugin->type); - if ($dispatcher && $plugin instanceof DispatcherAwareInterface) { - $plugin->setDispatcher($dispatcher); - } - if (!$autocreate) { return; } - // @TODO: Starting from 7.0 it should use $dispatcher->addSubscriber($plugin); for plugins which implement SubscriberInterface. - $plugin->registerListeners(); + // Check for overridden registerListeners() + $reflection = new \ReflectionClass($plugin); + $registerOverridden = $reflection->hasMethod('registerListeners') && $reflection->getMethod('registerListeners')->class !== CMSPlugin::class; + + // @TODO: From 7.0 when registerListeners() will be removed from CMSPlugin checking for overridden registerListeners() need to be removed. + if ($plugin instanceof SubscriberInterface && !$registerOverridden) { + $dispatcher->addSubscriber($plugin); + } else { + // @TODO: From 7.0 when DispatcherAwareInterface will be removed from CMSPlugin this should be checked for all plugins. + if ($dispatcher && $plugin instanceof DispatcherAwareInterface) { + $plugin->setDispatcher($dispatcher); + } + + // @TODO: From 7.0 it should use $dispatcher->addSubscriber($plugin); for plugins which implement SubscriberInterface. + $plugin->registerListeners(); + } } /** @@ -263,7 +274,7 @@ protected static function load() $loader = function () use ($levels) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select( $db->quoteName( [ @@ -271,12 +282,14 @@ protected static function load() 'element', 'params', 'extension_id', + 'custom_data', ], [ 'type', 'name', 'params', 'id', + null, ] ) ) diff --git a/libraries/src/Router/Route.php b/libraries/src/Router/Route.php index 8be615061a628..61ef044bd1afe 100644 --- a/libraries/src/Router/Route.php +++ b/libraries/src/Router/Route.php @@ -73,7 +73,7 @@ public static function _($url, $xhtml = true, $tls = self::TLS_IGNORE, $absolute { try { /** - * @deprecated 3.9 int conversion will be removed in 6.0 + * @deprecated 3.9 int conversion will be removed in 7.0 * Before 3.9.7 this method silently converted $tls to integer */ if (!\is_int($tls)) { @@ -86,7 +86,7 @@ public static function _($url, $xhtml = true, $tls = self::TLS_IGNORE, $absolute } /** - * @deprecated 3.9 -1 as valid value will be removed in 6.0 + * @deprecated 3.9 -1 as valid value will be removed in 7.0 * Before 3.9.7 this method accepted -1. */ if ($tls === -1) { @@ -99,8 +99,8 @@ public static function _($url, $xhtml = true, $tls = self::TLS_IGNORE, $absolute return static::link($client, $url, $xhtml, $tls, $absolute); } catch (\RuntimeException) { /** - * @deprecated 3.9 this method will not fail silently from 6.0 - * Before 3.9.0 this method failed silently on router error. This B/C will be removed in Joomla 6.0 + * @deprecated 3.9 this method will not fail silently from 7.0 + * Before 3.9.0 this method failed silently on router error. This B/C will be removed in Joomla 7.0 */ return null; } diff --git a/libraries/src/Router/Router.php b/libraries/src/Router/Router.php index ff60e790c33dc..06d3a024f8db6 100644 --- a/libraries/src/Router/Router.php +++ b/libraries/src/Router/Router.php @@ -111,7 +111,7 @@ class Router * * @throws \RuntimeException * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Inject the router or load it from the dependency injection container * Example: Factory::getContainer()->get(SiteRouter::class); */ diff --git a/libraries/src/Service/Provider/Application.php b/libraries/src/Service/Provider/Application.php index c3555a91c97d4..8e9ab01646389 100644 --- a/libraries/src/Service/Provider/Application.php +++ b/libraries/src/Service/Provider/Application.php @@ -16,9 +16,11 @@ use Joomla\CMS\Cache\CacheControllerFactoryInterface; use Joomla\CMS\Console\CheckJoomlaUpdatesCommand; use Joomla\CMS\Console\CoreUpdateChannelCommand; +use Joomla\CMS\Console\ExtensionDisableCommand; use Joomla\CMS\Console\ExtensionDiscoverCommand; use Joomla\CMS\Console\ExtensionDiscoverInstallCommand; use Joomla\CMS\Console\ExtensionDiscoverListCommand; +use Joomla\CMS\Console\ExtensionEnableCommand; use Joomla\CMS\Console\ExtensionInstallCommand; use Joomla\CMS\Console\ExtensionRemoveCommand; use Joomla\CMS\Console\ExtensionsListCommand; @@ -36,7 +38,6 @@ use Joomla\CMS\Console\TasksRunCommand; use Joomla\CMS\Console\TasksStateCommand; use Joomla\CMS\Console\UpdateCoreCommand; -use Joomla\CMS\Input\Input as CMSInput; use Joomla\CMS\Language\LanguageFactoryInterface; use Joomla\CMS\Menu\MenuFactoryInterface; use Joomla\CMS\User\UserFactoryInterface; @@ -49,6 +50,7 @@ use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Event\Priority; +use Joomla\Input\Input as CMSInput; use Joomla\Session\SessionEvents; use Joomla\Session\SessionInterface; use Psr\Log\LoggerInterface; @@ -155,6 +157,8 @@ function (Container $container) { GetConfigurationCommand::getDefaultName() => GetConfigurationCommand::class, ExtensionsListCommand::getDefaultName() => ExtensionsListCommand::class, CheckJoomlaUpdatesCommand::getDefaultName() => CheckJoomlaUpdatesCommand::class, + ExtensionEnableCommand::getDefaultName() => ExtensionEnableCommand::class, + ExtensionDisableCommand::getDefaultName() => ExtensionDisableCommand::class, ExtensionRemoveCommand::getDefaultName() => ExtensionRemoveCommand::class, ExtensionInstallCommand::getDefaultName() => ExtensionInstallCommand::class, ExtensionDiscoverCommand::getDefaultName() => ExtensionDiscoverCommand::class, @@ -179,9 +183,9 @@ function (Container $container) { 'JApplicationApi', function (Container $container) { $app = new ApiApplication(null, $container->get('config'), null, $container); - $app->setDispatcher($container->get('Joomla\Event\DispatcherInterface')); + $app->setDispatcher($container->get(DispatcherInterface::class)); $app->setLogger($container->get(LoggerInterface::class)); - $app->setSession($container->get('Joomla\Session\SessionInterface')); + $app->setSession($container->get(SessionInterface::class)); $app->setMenuFactory($container->get(MenuFactoryInterface::class)); // Ensure that session purging is configured now we have a dispatcher diff --git a/libraries/src/Service/Provider/Console.php b/libraries/src/Service/Provider/Console.php index 4dbdd2c04f2f3..f0631c7f8107c 100644 --- a/libraries/src/Service/Provider/Console.php +++ b/libraries/src/Service/Provider/Console.php @@ -11,9 +11,11 @@ use Joomla\CMS\Console\CheckJoomlaUpdatesCommand; use Joomla\CMS\Console\CoreUpdateChannelCommand; +use Joomla\CMS\Console\ExtensionDisableCommand; use Joomla\CMS\Console\ExtensionDiscoverCommand; use Joomla\CMS\Console\ExtensionDiscoverInstallCommand; use Joomla\CMS\Console\ExtensionDiscoverListCommand; +use Joomla\CMS\Console\ExtensionEnableCommand; use Joomla\CMS\Console\ExtensionInstallCommand; use Joomla\CMS\Console\ExtensionRemoveCommand; use Joomla\CMS\Console\ExtensionsListCommand; @@ -36,6 +38,7 @@ use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; +use Joomla\Event\DispatcherInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -146,6 +149,22 @@ function (Container $container) { true ); + $container->share( + ExtensionEnableCommand::class, + function (Container $container) { + return new ExtensionEnableCommand($container->get(DatabaseInterface::class)); + }, + true + ); + + $container->share( + ExtensionDisableCommand::class, + function (Container $container) { + return new ExtensionDisableCommand($container->get(DatabaseInterface::class)); + }, + true + ); + $container->share( ExtensionRemoveCommand::class, function (Container $container) { @@ -157,7 +176,7 @@ function (Container $container) { $container->share( ExtensionInstallCommand::class, function (Container $container) { - return new ExtensionInstallCommand(); + return new ExtensionInstallCommand($container->get(DatabaseInterface::class)); }, true ); @@ -203,6 +222,8 @@ function (Container $container) { $container->get('config')->get('debug_lang') )); + $command->setDispatcher($container->get(DispatcherInterface::class)); + return $command; }, true diff --git a/libraries/src/Service/Provider/Database.php b/libraries/src/Service/Provider/Database.php index 76a5d033d1240..d58b6918f524f 100644 --- a/libraries/src/Service/Provider/Database.php +++ b/libraries/src/Service/Provider/Database.php @@ -10,6 +10,7 @@ namespace Joomla\CMS\Service\Provider; use Joomla\Database\DatabaseDriver; +use Joomla\Database\DatabaseFactory; use Joomla\Database\DatabaseInterface; use Joomla\Database\Mysql\MysqlDriver; use Joomla\DI\Container; @@ -83,7 +84,6 @@ function (Container $container) { } $options = [ - 'driver' => $dbtype, 'host' => $conf->get('host'), 'user' => $conf->get('user'), 'password' => $conf->get('password'), @@ -120,7 +120,7 @@ function (Container $container) { } try { - $db = DatabaseDriver::getInstance($options); + $db = (new DatabaseFactory())->getDriver($dbtype, $options); } catch (\RuntimeException $e) { if (!headers_sent()) { header('HTTP/1.1 500 Internal Server Error'); diff --git a/libraries/src/Service/Provider/Input.php b/libraries/src/Service/Provider/Input.php index f1d2f82dd3f6f..15e4286db0f4d 100644 --- a/libraries/src/Service/Provider/Input.php +++ b/libraries/src/Service/Provider/Input.php @@ -9,9 +9,9 @@ namespace Joomla\CMS\Service\Provider; -use Joomla\CMS\Input\Input as CMSInput; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; +use Joomla\Input\Input as CMSInput; /** * Service provider for the the Joomla Input object. diff --git a/libraries/src/Service/Provider/Session.php b/libraries/src/Service/Provider/Session.php index a65039891c7d3..4abcef0111e54 100644 --- a/libraries/src/Service/Provider/Session.php +++ b/libraries/src/Service/Provider/Session.php @@ -13,7 +13,6 @@ use Joomla\CMS\Application\ConsoleApplication; use Joomla\CMS\Application\SiteApplication; use Joomla\CMS\Factory; -use Joomla\CMS\Input\Input as CMSInput; use Joomla\CMS\Installation\Application\InstallationApplication; use Joomla\CMS\Session\EventListener\MetadataManagerListener; use Joomla\CMS\Session\MetadataManager; @@ -26,6 +25,7 @@ use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Event\LazyServiceEventListener; +use Joomla\Input\Input as CMSInput; use Joomla\Registry\Registry; use Joomla\Session\HandlerInterface; use Joomla\Session\SessionEvents; diff --git a/libraries/src/Session/MetadataManager.php b/libraries/src/Session/MetadataManager.php index 7accb7422423c..239962790ce8a 100644 --- a/libraries/src/Session/MetadataManager.php +++ b/libraries/src/Session/MetadataManager.php @@ -149,7 +149,7 @@ public function createOrUpdateRecord(SessionInterface $session, User $user) */ public function deletePriorTo($time) { - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->delete($this->db->quoteName('#__session')) ->where($this->db->quoteName('time') . ' < :time') ->bind(':time', $time, ParameterType::INTEGER); @@ -174,7 +174,7 @@ public function deletePriorTo($time) */ private function checkSessionRecordExists(string $sessionId): int { - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('session_id')) ->from($this->db->quoteName('#__session')) ->where($this->db->quoteName('session_id') . ' = :session_id') @@ -208,7 +208,7 @@ private function checkSessionRecordExists(string $sessionId): int */ private function createSessionRecord(SessionInterface $session, User $user) { - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $time = $session->isNew() ? time() : $session->get('session.timer.start'); @@ -275,7 +275,7 @@ private function createSessionRecord(SessionInterface $session, User $user) */ private function updateSessionRecord(SessionInterface $session, User $user) { - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $time = time(); diff --git a/libraries/src/Session/Session.php b/libraries/src/Session/Session.php index 626f9675b63e9..d9def5b00ff2c 100644 --- a/libraries/src/Session/Session.php +++ b/libraries/src/Session/Session.php @@ -150,7 +150,7 @@ public static function getHandlers(): array * * @since 1.5 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Load the session service from the dependency injection container or via $app->getSession() * Example: Factory::getApplication()->getSession(); */ @@ -176,7 +176,7 @@ public static function getInstance() */ public function get($name, $default = null) { - // Handle B/C by checking if a namespace was passed to the method, will be removed at 5.0 + // Handle B/C by checking if a namespace was passed to the method, will be removed at 7.0 if (\func_num_args() > 2) { $args = \func_get_args(); @@ -227,7 +227,7 @@ public function get($name, $default = null) */ public function set($name, $value = null) { - // Handle B/C by checking if a namespace was passed to the method, will be removed at 5.0 + // Handle B/C by checking if a namespace was passed to the method, will be removed at 7.0 if (\func_num_args() > 2) { $args = \func_get_args(); @@ -256,7 +256,7 @@ public function set($name, $value = null) */ public function has($name) { - // Handle B/C by checking if a namespace was passed to the method, will be removed at 5.0 + // Handle B/C by checking if a namespace was passed to the method, will be removed at 7.0 if (\func_num_args() > 1) { $args = \func_get_args(); @@ -299,7 +299,7 @@ public function has($name) */ public function clear() { - // Handle B/C by checking if parameters were passed to this method; if so proxy to the new remove() method, will be removed at 5.0 + // Handle B/C by checking if parameters were passed to this method; if so proxy to the new remove() method, will be removed at 7.0 if (\func_num_args() >= 1) { $args = \func_get_args(); diff --git a/libraries/src/String/PunycodeHelper.php b/libraries/src/String/PunycodeHelper.php index 0a6344bfebdb3..e58a6c9ad73ae 100644 --- a/libraries/src/String/PunycodeHelper.php +++ b/libraries/src/String/PunycodeHelper.php @@ -196,7 +196,7 @@ public static function urlToUTF8($uri) public static function emailToPunycode($email) { if ($email === null) { - @trigger_error(\sprintf('Passing null value is deprecated in %s and will throw an exception in 6.0.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(\sprintf('Passing null value is deprecated in %s and will throw an exception in 7.0.', __METHOD__), E_USER_DEPRECATED); return ''; } diff --git a/libraries/src/TUF/DatabaseStorage.php b/libraries/src/TUF/DatabaseStorage.php index 667767a9ad34b..1267393bcaef5 100644 --- a/libraries/src/TUF/DatabaseStorage.php +++ b/libraries/src/TUF/DatabaseStorage.php @@ -11,7 +11,6 @@ use Joomla\CMS\Table\Table; use Joomla\CMS\Table\TableInterface; -use Joomla\CMS\Table\Tuf; use Tuf\Metadata\StorageBase; // phpcs:disable PSR1.Files.SideEffects diff --git a/libraries/src/TUF/TufFetcher.php b/libraries/src/TUF/TufFetcher.php index 19566c801daff..c8f0b93aee2da 100644 --- a/libraries/src/TUF/TufFetcher.php +++ b/libraries/src/TUF/TufFetcher.php @@ -153,7 +153,7 @@ private function rollBackTufMetadata() { $db = $this->db; - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__tuf_metadata')) ->set($db->quoteName('snapshot') . ' = NULL') ->set($db->quoteName('targets') . ' = NULL') diff --git a/libraries/src/Table/Asset.php b/libraries/src/Table/Asset.php index 6862409bff819..8fac6d715e68c 100644 --- a/libraries/src/Table/Asset.php +++ b/libraries/src/Table/Asset.php @@ -110,7 +110,7 @@ public function check() if ($this->parent_id > 0) { // Get the DatabaseQuery object $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('1') ->from($db->quoteName($this->_tbl)) ->where($db->quoteName('id') . ' = ' . $this->parent_id); @@ -155,7 +155,7 @@ public function rebuild($parentId = null, $leftId = 0, $level = 0, $path = null) } $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Build the structure of the recursive query. if (!isset($this->_cache['rebuild.sql'])) { diff --git a/libraries/src/Table/Category.php b/libraries/src/Table/Category.php index 902bfb25088d8..21cd86ec80480 100644 --- a/libraries/src/Table/Category.php +++ b/libraries/src/Table/Category.php @@ -17,7 +17,6 @@ use Joomla\CMS\Tag\TaggableTableTrait; use Joomla\CMS\User\CurrentUserInterface; use Joomla\CMS\User\CurrentUserTrait; -use Joomla\CMS\Versioning\VersionableTableInterface; use Joomla\Database\DatabaseInterface; use Joomla\Database\ParameterType; use Joomla\Event\DispatcherInterface; @@ -32,7 +31,7 @@ * * @since 1.5 */ -class Category extends Nested implements VersionableTableInterface, TaggableTableInterface, CurrentUserInterface +class Category extends Nested implements TaggableTableInterface, CurrentUserInterface { use TaggableTableTrait; use CurrentUserTrait; @@ -56,7 +55,7 @@ class Category extends Nested implements VersionableTableInterface, TaggableTabl public function __construct(DatabaseInterface $db, ?DispatcherInterface $dispatcher = null) { /** - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * This format was used by tags and versioning before 4.0 before * the introduction of the getTypeAlias function. */ @@ -112,7 +111,7 @@ protected function _getAssetParentId(?Table $table = null, $id = null) if ($this->parent_id > 1) { // Build the query to get the asset id for the parent category. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('asset_id')) ->from($db->quoteName('#__categories')) ->where($db->quoteName('id') . ' = :parentId') @@ -127,7 +126,7 @@ protected function _getAssetParentId(?Table $table = null, $id = null) } elseif ($assetId === null) { // This is a category that needs to parent with the extension. // Build the query to get the asset id for the parent category. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__assets')) ->where($db->quoteName('name') . ' = :extension') diff --git a/libraries/src/Table/Content.php b/libraries/src/Table/Content.php index 943d291214ef9..908fc492419e3 100644 --- a/libraries/src/Table/Content.php +++ b/libraries/src/Table/Content.php @@ -17,7 +17,6 @@ use Joomla\CMS\Tag\TaggableTableTrait; use Joomla\CMS\User\CurrentUserInterface; use Joomla\CMS\User\CurrentUserTrait; -use Joomla\CMS\Versioning\VersionableTableInterface; use Joomla\Database\DatabaseInterface; use Joomla\Database\ParameterType; use Joomla\Event\DispatcherInterface; @@ -33,7 +32,7 @@ * * @since 1.5 */ -class Content extends Table implements VersionableTableInterface, TaggableTableInterface, CurrentUserInterface +class Content extends Table implements TaggableTableInterface, CurrentUserInterface { use TaggableTableTrait; use CurrentUserTrait; @@ -112,7 +111,7 @@ protected function _getAssetParentId(?Table $table = null, $id = null) // Build the query to get the asset id for the parent category. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('asset_id')) ->from($db->quoteName('#__categories')) ->where($db->quoteName('id') . ' = :catid') diff --git a/libraries/src/Table/ContentHistory.php b/libraries/src/Table/ContentHistory.php index a042eb947df1d..a419a3a9f464a 100644 --- a/libraries/src/Table/ContentHistory.php +++ b/libraries/src/Table/ContentHistory.php @@ -169,7 +169,7 @@ public function getHashMatch() $db = $this->getDatabase(); $itemId = $this->item_id; $sha1Hash = $this->sha1_hash; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select('*') ->from($db->quoteName('#__history')) ->where($db->quoteName('item_id') . ' = :item_id') @@ -199,7 +199,7 @@ public function deleteOldVersions($maxVersions) // Get the list of version_id values we want to save $db = $this->getDatabase(); $itemId = $this->item_id; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('version_id')) ->from($db->quoteName('#__history')) ->where($db->quoteName('item_id') . ' = :item_id') @@ -214,7 +214,7 @@ public function deleteOldVersions($maxVersions) // Don't process delete query unless we have at least the maximum allowed versions if (\count($idsToSave) === (int) $maxVersions) { // Delete any rows not in our list and and not flagged to keep forever. - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete($db->quoteName('#__history')) ->where($db->quoteName('item_id') . ' = :item_id') ->whereNotIn($db->quoteName('version_id'), $idsToSave) diff --git a/libraries/src/Table/ContentType.php b/libraries/src/Table/ContentType.php index 6e5ef821c81bd..7ec7f84ad5f2c 100644 --- a/libraries/src/Table/ContentType.php +++ b/libraries/src/Table/ContentType.php @@ -118,7 +118,7 @@ public function fieldmapExpand($assoc = true) public function getTypeId($typeAlias) { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('type_id')) ->from($db->quoteName($this->_tbl)) ->where($db->quoteName('type_alias') . ' = :type_alias') @@ -144,14 +144,25 @@ public function getContentTable() if (\is_object($tableInfo) && isset($tableInfo->special)) { if (\is_object($tableInfo->special) && isset($tableInfo->special->type, $tableInfo->special->prefix)) { - $class = $tableInfo->special->class ?? 'Joomla\\CMS\\Table\\Table'; + if (isset($tableInfo->special->class)) { + $class = $tableInfo->special->class; - if (!class_implements($class, 'Joomla\\CMS\\Table\\TableInterface')) { + if (!class_implements($class, 'Joomla\\CMS\\Table\\TableInterface')) { + // This isn't an instance of TableInterface. Stop. + throw new \RuntimeException('Class must be an instance of Joomla\\CMS\\Table\\TableInterface'); + } + + return $class::getInstance($tableInfo->special->type, $tableInfo->special->prefix); + } + + $class = rtrim($tableInfo->special->prefix, '\\') . '\\' . $tableInfo->special->type; + + if (!class_implements($class, TableInterface::class)) { // This isn't an instance of TableInterface. Stop. throw new \RuntimeException('Class must be an instance of Joomla\\CMS\\Table\\TableInterface'); } - $result = $class::getInstance($tableInfo->special->type, $tableInfo->special->prefix); + $result = new $class($this->getDbo()); } } diff --git a/libraries/src/Table/CoreContent.php b/libraries/src/Table/CoreContent.php index a7142e9a50139..c4d01abbe2e9c 100644 --- a/libraries/src/Table/CoreContent.php +++ b/libraries/src/Table/CoreContent.php @@ -178,7 +178,7 @@ public function deleteByContentId($contentItemId = null, $typeAlias = null) } $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('core_content_id')) ->from($db->quoteName('#__ucm_content')) ->where( @@ -264,7 +264,7 @@ protected function storeUcmBase($updateNulls = true, $isNew = false) { // Store the ucm_base row $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $languageId = ContentHelper::getLanguageId($this->core_language); // Selecting "all languages" doesn't give a language id - we can't store a blank string in non mysql databases, so save 0 (the default value) diff --git a/libraries/src/Table/Extension.php b/libraries/src/Table/Extension.php index b4fdf9889e382..eec6be3bb2ae1 100644 --- a/libraries/src/Table/Extension.php +++ b/libraries/src/Table/Extension.php @@ -105,7 +105,7 @@ public function find($options = []) { // Get the DatabaseQuery object $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); foreach ($options as $col => $val) { $query->where($col . ' = ' . $db->quote($val)); diff --git a/libraries/src/Table/Menu.php b/libraries/src/Table/Menu.php index 6306e5286f1d7..86cb44fa3e22e 100644 --- a/libraries/src/Table/Menu.php +++ b/libraries/src/Table/Menu.php @@ -215,7 +215,7 @@ public function store($updateNulls = true) } elseif ($this->language === '*' && $this->id != 0) { // When editing an item with All language check if there are more menu items with the same alias in any language. $id = (int) $this->id; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('id') ->from($db->quoteName('#__menu')) ->where($db->quoteName('parent_id') . ' = 1') diff --git a/libraries/src/Table/MenuType.php b/libraries/src/Table/MenuType.php index 7a7a36caffd93..f57c196b99eda 100644 --- a/libraries/src/Table/MenuType.php +++ b/libraries/src/Table/MenuType.php @@ -78,7 +78,7 @@ public function check() // Check for unique menutype. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(id)') ->from($db->quoteName('#__menu_types')) ->where($db->quoteName('menutype') . ' = :menutype') @@ -121,7 +121,7 @@ public function store($updateNulls = false) $table->load($this->id); // Verify that no items are checked out - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->where($db->quoteName('menutype') . ' = :menutype') @@ -214,7 +214,7 @@ public function delete($pk = null) $table->load($pk); // Verify that no items are checked out - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->where($db->quoteName('menutype') . ' = :menutype') @@ -313,7 +313,7 @@ protected function _getAssetTitle() protected function _getAssetParentId(?Table $table = null, $id = null) { $assetId = null; - $asset = Table::getInstance('asset'); + $asset = new Asset($this->getDbo()); if ($asset->loadByName('com_menus')) { $assetId = $asset->id; diff --git a/libraries/src/Table/Module.php b/libraries/src/Table/Module.php index 86c0021f99048..1a801b60711f3 100644 --- a/libraries/src/Table/Module.php +++ b/libraries/src/Table/Module.php @@ -96,7 +96,7 @@ protected function _getAssetParentId(?Table $table = null, $id = null) if ($assetId === null) { // Build the query to get the asset id of the parent component. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__assets')) ->where($db->quoteName('name') . ' = ' . $db->quote('com_modules')); diff --git a/libraries/src/Table/Nested.php b/libraries/src/Table/Nested.php index 518e38118c9f2..eadc643cf6344 100644 --- a/libraries/src/Table/Nested.php +++ b/libraries/src/Table/Nested.php @@ -149,7 +149,7 @@ public function getPath($pk = null, $diagnostic = false) // Get the path from the node to the root. $select = ($diagnostic) ? 'p.' . $k . ', p.parent_id, p.level, p.lft, p.rgt' : 'p.*'; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($select) ->from($this->_tbl . ' AS n, ' . $this->_tbl . ' AS p') ->where('n.lft BETWEEN p.lft AND p.rgt') @@ -180,7 +180,7 @@ public function getTree($pk = null, $diagnostic = false) // Get the node and children as a tree. $select = ($diagnostic) ? 'n.' . $k . ', n.parent_id, n.level, n.lft, n.rgt' : 'n.*'; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($select) ->from($this->_tbl . ' AS n, ' . $this->_tbl . ' AS p') ->where('n.lft BETWEEN p.lft AND p.rgt') @@ -264,7 +264,7 @@ public function move($delta, $where = '') $k = $this->_tbl_key; $pk = $this->$k; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($k) ->from($this->_tbl) ->where('parent_id = ' . $this->parent_id); @@ -323,7 +323,7 @@ public function moveByReference($referenceId, $position = 'after', $pk = null, $ // Get the ids of child nodes. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($k) ->from($this->_tbl) ->where('lft BETWEEN ' . (int) $node->lft . ' AND ' . (int) $node->rgt); @@ -468,7 +468,7 @@ public function moveByReference($referenceId, $position = 'after', $pk = null, $ // Set the correct parent id for the moved node if required. if ($node->parent_id != $repositionData->new_parent_id) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($this->_tbl); // Update the title and alias fields if they exist for the table. @@ -577,7 +577,7 @@ public function delete($pk = null, $children = true) return false; } - $query = $db->getQuery(true); + $query = $db->createQuery(); // Should we delete all children along with the node? if ($children) { @@ -695,7 +695,7 @@ public function check() } $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('1') ->from($this->_tbl) ->where($this->_tbl_key . ' = ' . $this->parent_id); @@ -764,7 +764,7 @@ public function store($updateNulls = false) if ($this->_location_id == 0) { // Get the last root node as the reference node. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($this->_tbl_key . ', parent_id, level, lft, rgt') ->from($this->_tbl) ->where('parent_id = 0') @@ -797,7 +797,7 @@ public function store($updateNulls = false) } // Create space in the tree at the new location for the new node in left ids. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($this->_tbl) ->set('lft = lft + 2') ->where($repositionData->left_where); @@ -904,7 +904,7 @@ public function publish($pks = null, $state = 1, $userId = 0) $k = $this->_tbl_key; $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $table = $db->quoteName($this->_tbl); $published = $db->quoteName($this->getColumnAlias('published')); $checkedOut = $db->quoteName($this->getColumnAlias('checked_out')); @@ -1049,7 +1049,7 @@ public function orderUp($pk) try { // Get the primary keys of child nodes. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($this->_tbl_key) ->from($this->_tbl) ->where('lft BETWEEN ' . (int) $node->lft . ' AND ' . (int) $node->rgt); @@ -1115,7 +1115,7 @@ public function orderDown($pk) } $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Get the right sibling node. $sibling = $this->_getNode($node->rgt + 1, 'left'); @@ -1181,7 +1181,7 @@ public function getRootId() // Test for a unique record with parent_id = 0 $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($k) ->from($this->_tbl) ->where('parent_id = 0'); @@ -1259,7 +1259,7 @@ public function rebuild($parentId = null, $leftId = 0, $level = 0, $path = '') } $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Build the structure of the recursive query. if (!isset($this->_cache['rebuild.sql'])) { @@ -1341,7 +1341,7 @@ public function rebuildPath($pk = null) // Get the aliases for the path from the node to the root node. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('p.alias') ->from($this->_tbl . ' AS n, ' . $this->_tbl . ' AS p') ->where('n.lft BETWEEN p.lft AND p.rgt') @@ -1405,7 +1405,7 @@ public function saveorder($idArray = null, $lftArray = null) { try { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); // Validate arguments if (\is_array($idArray) && \is_array($lftArray) && \count($idArray) == \count($lftArray)) { @@ -1447,7 +1447,7 @@ public function saveorder($idArray = null, $lftArray = null) protected function recursiveUpdatePublishedColumn($pk, $newState = null) { $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $table = $db->quoteName($this->_tbl); $key = $db->quoteName($this->_tbl_key); $published = $db->quoteName($this->getColumnAlias('published')); @@ -1552,7 +1552,7 @@ protected function _getNode($id, $key = null) // Get the node data. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($this->_tbl_key . ', parent_id, level, lft, rgt') ->from($this->_tbl) ->where($k . ' = ' . (int) $id); @@ -1682,7 +1682,7 @@ protected function _logtable($showData = true, $showQuery = true) } if ($showData) { - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($this->_tbl_key . ', parent_id, lft, rgt, level') ->from($this->_tbl) ->order($this->_tbl_key); diff --git a/libraries/src/Table/Table.php b/libraries/src/Table/Table.php index ca973a80b3653..793a9040f7ee1 100644 --- a/libraries/src/Table/Table.php +++ b/libraries/src/Table/Table.php @@ -18,7 +18,6 @@ use Joomla\CMS\Object\LegacyPropertyManagementTrait; use Joomla\Database\DatabaseAwareInterface; use Joomla\Database\DatabaseAwareTrait; -use Joomla\Database\DatabaseDriver; use Joomla\Database\DatabaseInterface; use Joomla\Database\DatabaseQuery; use Joomla\Database\Exception\DatabaseNotFoundException; @@ -88,9 +87,9 @@ abstract class Table extends \stdClass implements TableInterface, DispatcherAwar protected $_tbl_keys = []; /** - * DatabaseDriver object. + * DatabaseInterface object. * - * @var DatabaseDriver + * @var DatabaseInterface * @since 1.7.0 * * @deprecated 5.4.0 will be removed in 7.0 @@ -282,9 +281,10 @@ public function getFields($reload = false) * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 - * Use the MvcFactory instead + * @deprecated 4.3 will be removed in 7.0 + * Use the MvcFactory instead or instantiate the table class directly. * Example: Factory::getApplication()->bootComponent('...')->getMVCFactory()->createTable($name, $prefix, $config); + * $table = new \Joomla\CMS\Table\Content($db); */ public static function getInstance($type, $prefix = 'JTable', $config = []) { @@ -333,7 +333,7 @@ public static function getInstance($type, $prefix = 'JTable', $config = []) /* * If unable to find the class file in the Table include paths. Return false. * The warning JLIB_DATABASE_ERROR_NOT_SUPPORTED_FILE_NOT_FOUND has been removed in 3.6.3. - * In 6.0 an Exception (type to be determined) will be thrown. + * in 7.0 an Exception (type to be determined) will be thrown. * For more info see https://github.com/joomla/joomla-cms/issues/11570 */ @@ -361,7 +361,7 @@ public static function getInstance($type, $prefix = 'JTable', $config = []) * * @since 1.7.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Should not be used anymore as tables are loaded through the MvcFactory */ public static function addIncludePath($path = null) @@ -536,9 +536,9 @@ public function getId() } /** - * Method to get the DatabaseDriver object. + * Method to get the DatabaseInterface object. * - * @return DatabaseDriver The internal database driver object. + * @return DatabaseInterface The internal database driver object. * * @since 1.7.0 * @@ -552,9 +552,9 @@ public function getDbo() } /** - * Method to set the DatabaseDriver object. + * Method to set the DatabaseInterface object. * - * @param DatabaseDriver $db A DatabaseDriver object to be used by the table object. + * @param DatabaseInterface $db A DatabaseInterface object to be used by the table object. * * @return boolean True on success. * @@ -564,7 +564,7 @@ public function getDbo() * Use setDatabase() instead * Example: $this->setDatabase($db); */ - public function setDbo(DatabaseDriver $db) + public function setDbo(DatabaseInterface $db) { $this->_db = $db; @@ -813,7 +813,7 @@ public function load($keys = null, $reset = true) } // Initialise the query. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName($this->_tbl)); $fields = array_keys($this->getProperties()); @@ -991,7 +991,7 @@ public function store($updateNulls = false) // Update the asset_id field in this table. $this->asset_id = (int) $asset->id; - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($this->_tbl)) ->set('asset_id = ' . (int) $this->asset_id); $this->appendPrimaryKeys($query); @@ -1120,7 +1120,7 @@ public function delete($pk = null) } // Delete the row by primary key. - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName($this->_tbl)); $this->appendPrimaryKeys($query, $pk); @@ -1203,7 +1203,7 @@ public function checkOut($userId, $pk = null) $time = Factory::getDate()->toSql(); // Check the row out by primary key. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($this->_tbl)) ->set($db->quoteName($checkedOutField) . ' = ' . (int) $userId) ->set($db->quoteName($checkedOutTimeField) . ' = ' . $db->quote($time)); @@ -1286,7 +1286,7 @@ public function checkIn($pk = null) $nullID = $this->_supportNullValue ? 'NULL' : '0'; // Check the row in by primary key. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($this->_tbl)) ->set($db->quoteName($checkedOutField) . ' = ' . $nullID) ->set($db->quoteName($checkedOutTimeField) . ' = ' . $nullDate); @@ -1334,7 +1334,7 @@ public function hasPrimaryKey() $empty = $empty && empty($this->$key); } } else { - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(*)') ->from($db->quoteName($this->_tbl)); $this->appendPrimaryKeys($query); @@ -1403,7 +1403,7 @@ public function hit($pk = null) $hitsField = $this->getColumnAlias('hits'); // Check the row in by primary key. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($this->_tbl)) ->set($db->quoteName($hitsField) . ' = (' . $db->quoteName($hitsField) . ' + 1)'); $this->appendPrimaryKeys($query, $pk); @@ -1454,7 +1454,7 @@ public function isCheckedOut($with = 0, $against = null) // This last check can only be relied on if tracking session metadata if (Factory::getApplication()->get('session_metadata', true)) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(userid)') ->from($db->quoteName('#__session')) ->where($db->quoteName('userid') . ' = ' . (int) $against); @@ -1491,7 +1491,7 @@ public function getNextOrder($where = '') } // Get the largest ordering value for a given where clause. - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('MAX(' . $db->quoteName($this->getColumnAlias('ordering')) . ')') ->from($db->quoteName($this->_tbl)); @@ -1549,11 +1549,11 @@ public function reorder($where = '') $quotedOrderingField = $db->quoteName($this->getColumnAlias('ordering')); - $subquery = $db->getQuery(true) + $subquery = $db->createQuery() ->from($db->quoteName($this->_tbl)) ->selectRowNumber($quotedOrderingField, 'new_ordering'); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($this->_tbl)) ->set($quotedOrderingField . ' = sq.new_ordering'); @@ -1637,7 +1637,7 @@ public function move($delta, $where = '') } $row = null; - $query = $db->getQuery(true); + $query = $db->createQuery(); // Select the primary key and ordering values from the table. $query->select(implode(',', $this->_tbl_keys) . ', ' . $quotedOrderingField) @@ -1788,7 +1788,7 @@ public function publish($pks = null, $state = 1, $userId = 0) foreach ($pks as $pk) { // Update the publishing state for rows with the given primary keys. - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($this->_tbl)) ->set($db->quoteName($publishedField) . ' = ' . (int) $state); diff --git a/libraries/src/Table/Tuf.php b/libraries/src/Table/Tuf.php index 180fca7910625..a451cd974d684 100644 --- a/libraries/src/Table/Tuf.php +++ b/libraries/src/Table/Tuf.php @@ -10,6 +10,8 @@ namespace Joomla\CMS\Table; // phpcs:disable PSR1.Files.SideEffects +use Joomla\Database\DatabaseInterface; + \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects @@ -23,11 +25,11 @@ class Tuf extends Table /** * Constructor * - * @param \Joomla\Database\DatabaseDriver $db A database connector object + * @param DatabaseInterface $db A database connector object * * @since 5.1.0 */ - public function __construct($db) + public function __construct(DatabaseInterface $db) { parent::__construct('#__tuf_metadata', 'id', $db); } diff --git a/libraries/src/Table/Update.php b/libraries/src/Table/Update.php index 9c2933c9de9f3..2f23f8225cd3b 100644 --- a/libraries/src/Table/Update.php +++ b/libraries/src/Table/Update.php @@ -102,7 +102,7 @@ public function find($options = []) $where[] = $col . ' = ' . $db->quote($val); } - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName($this->_tbl_key)) ->from($db->quoteName($this->_tbl)) ->where(implode(' AND ', $where)); diff --git a/libraries/src/Table/User.php b/libraries/src/Table/User.php index f3508ceb8fb93..74796b681cb24 100644 --- a/libraries/src/Table/User.php +++ b/libraries/src/Table/User.php @@ -98,7 +98,7 @@ public function load($userId = null, $reset = true) // Load the user data. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('*') ->from($db->quoteName('#__users')) ->where($db->quoteName('id') . ' = :userid') @@ -165,7 +165,7 @@ public function bind($array, $ignore = '') // Get the titles for the user groups. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->select($db->quoteName('title')) ->from($db->quoteName('#__usergroups')) @@ -256,7 +256,7 @@ public function check() // Check for existing username $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where($db->quoteName('username') . ' = :username') @@ -356,7 +356,7 @@ public function store($updateNulls = true) // Reset groups to the local object. $this->groups = $groups; - $query = $db->getQuery(true); + $query = $db->createQuery(); // Store the group data if the user data was saved. if (\is_array($this->groups) && \count($this->groups)) { @@ -458,7 +458,7 @@ public function delete($userId = null) // Delete the user. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName($this->_tbl)) ->where($db->quoteName($this->_tbl_key) . ' = :key') ->bind(':key', $key, ParameterType::INTEGER); @@ -533,7 +533,7 @@ public function setLastVisit($timeStamp = null, $userId = null) // Update the database row for the user. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName($this->_tbl)) ->set($db->quoteName('lastvisitDate') . ' = :lastvisitDate') ->where($db->quoteName('id') . ' = :id') diff --git a/libraries/src/Table/Usergroup.php b/libraries/src/Table/Usergroup.php index e8b5e0b98bae0..27e2a37ef3d3a 100644 --- a/libraries/src/Table/Usergroup.php +++ b/libraries/src/Table/Usergroup.php @@ -76,7 +76,7 @@ public function check() $parentId = (int) $this->parent_id; $title = trim($this->title); $id = (int) $this->id; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(title)') ->from($this->_tbl) ->where($db->quoteName('title') . ' = :title') @@ -140,7 +140,7 @@ public function rebuild($parentId = 0, $left = 0) { // Get the database object $db = $this->getDatabase(); - $query = $db->getQuery(true); + $query = $db->createQuery(); $parentId = (int) $parentId; // Get all children of this node @@ -248,7 +248,7 @@ public function delete($oid = null) $rgt = (int) $this->rgt; // Select the usergroup ID and its children - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('c.id')) ->from($db->quoteName($this->_tbl, 'c')) ->where($db->quoteName('c.lft') . ' >= :lft') diff --git a/libraries/src/Table/ViewLevel.php b/libraries/src/Table/ViewLevel.php index 333fa864c3bbe..61fedc9ee7aef 100644 --- a/libraries/src/Table/ViewLevel.php +++ b/libraries/src/Table/ViewLevel.php @@ -88,7 +88,7 @@ public function check() // Check for a duplicate title. $db = $this->getDatabase(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('COUNT(' . $db->quoteName('title') . ')') ->from($db->quoteName('#__viewlevels')) ->where($db->quoteName('title') . ' = :title') diff --git a/libraries/src/Tag/TaggableTableTrait.php b/libraries/src/Tag/TaggableTableTrait.php index 988f78544db0e..71a07e4e5bba9 100644 --- a/libraries/src/Tag/TaggableTableTrait.php +++ b/libraries/src/Tag/TaggableTableTrait.php @@ -28,7 +28,7 @@ trait TaggableTableTrait * @var TagsHelper * @since 4.0.0 * @note The tags helper property is set to public for backwards compatibility for Joomla 4.0. It will be made a - * protected property in Joomla 6.0 + * protected property in Joomla 7.0 */ public $tagsHelper; diff --git a/libraries/src/Toolbar/Button/BasicButton.php b/libraries/src/Toolbar/Button/BasicButton.php index cb04fe3583170..cc590220d28b5 100644 --- a/libraries/src/Toolbar/Button/BasicButton.php +++ b/libraries/src/Toolbar/Button/BasicButton.php @@ -40,7 +40,7 @@ class BasicButton extends ToolbarButton * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use render() instead. * * @throws \LogicException diff --git a/libraries/src/Toolbar/Button/ConfirmButton.php b/libraries/src/Toolbar/Button/ConfirmButton.php index 122a6c24d3bb4..f6cd81de1223a 100644 --- a/libraries/src/Toolbar/Button/ConfirmButton.php +++ b/libraries/src/Toolbar/Button/ConfirmButton.php @@ -56,7 +56,7 @@ protected function prepareOptions(array &$options) * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use render() instead. */ public function fetchButton($type = 'Confirm', $msg = '', $name = '', $text = '', $task = '', $list = true, $hideMenu = false) diff --git a/libraries/src/Toolbar/Button/CustomButton.php b/libraries/src/Toolbar/Button/CustomButton.php index daee67d557bd2..eea294ce5a32d 100644 --- a/libraries/src/Toolbar/Button/CustomButton.php +++ b/libraries/src/Toolbar/Button/CustomButton.php @@ -50,7 +50,7 @@ protected function renderButton(array &$options): string * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use render() instead. */ public function fetchButton($type = 'Custom', $html = '', $id = 'custom') diff --git a/libraries/src/Toolbar/Button/HelpButton.php b/libraries/src/Toolbar/Button/HelpButton.php index 61f0026f831d2..ca874c17d2956 100644 --- a/libraries/src/Toolbar/Button/HelpButton.php +++ b/libraries/src/Toolbar/Button/HelpButton.php @@ -68,7 +68,7 @@ protected function prepareOptions(array &$options) * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use render() instead. */ public function fetchButton($type = 'Help', $ref = '', $com = false, $override = null, $component = null) diff --git a/libraries/src/Toolbar/Button/InlinehelpButton.php b/libraries/src/Toolbar/Button/InlinehelpButton.php index 9177b2bd21509..13bca5c6680a0 100644 --- a/libraries/src/Toolbar/Button/InlinehelpButton.php +++ b/libraries/src/Toolbar/Button/InlinehelpButton.php @@ -69,7 +69,7 @@ protected function prepareOptions(array &$options) * * @since 4.1.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use render() instead. */ public function fetchButton( diff --git a/libraries/src/Toolbar/Button/LinkButton.php b/libraries/src/Toolbar/Button/LinkButton.php index 3ee3a87f89578..ae93a5c2b0fd3 100644 --- a/libraries/src/Toolbar/Button/LinkButton.php +++ b/libraries/src/Toolbar/Button/LinkButton.php @@ -64,7 +64,7 @@ protected function prepareOptions(array &$options) * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use render() instead. */ public function fetchButton($type = 'Link', $name = 'back', $text = '', $url = null) diff --git a/libraries/src/Toolbar/Button/PopupButton.php b/libraries/src/Toolbar/Button/PopupButton.php index a84dd6101fc72..201626b5b22ae 100644 --- a/libraries/src/Toolbar/Button/PopupButton.php +++ b/libraries/src/Toolbar/Button/PopupButton.php @@ -150,7 +150,7 @@ protected function renderButton(array &$options): string } @trigger_error( - 'Use of BS Modal is deprecated in Joomla\CMS\Toolbar\Button\PopupButton, and will be removed in 6.0', + 'Use of BS Modal is deprecated in Joomla\CMS\Toolbar\Button\PopupButton, and will be removed in 7.0', E_USER_DEPRECATED ); diff --git a/libraries/src/Toolbar/Button/SeparatorButton.php b/libraries/src/Toolbar/Button/SeparatorButton.php index 4857812fcae21..7e1fd8b39672a 100644 --- a/libraries/src/Toolbar/Button/SeparatorButton.php +++ b/libraries/src/Toolbar/Button/SeparatorButton.php @@ -38,7 +38,7 @@ class SeparatorButton extends ToolbarButton * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use render() instead. */ public function fetchButton() diff --git a/libraries/src/Toolbar/Button/StandardButton.php b/libraries/src/Toolbar/Button/StandardButton.php index 373dc9982803d..cb884b9567b17 100644 --- a/libraries/src/Toolbar/Button/StandardButton.php +++ b/libraries/src/Toolbar/Button/StandardButton.php @@ -67,7 +67,7 @@ protected function prepareOptions(array &$options) * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use render() instead. */ public function fetchButton($type = 'Standard', $name = '', $text = '', $task = '', $list = true, $formId = null) diff --git a/libraries/src/Toolbar/ContainerAwareToolbarFactory.php b/libraries/src/Toolbar/ContainerAwareToolbarFactory.php index 99ff06e3ac6c7..5933cd518ebfa 100644 --- a/libraries/src/Toolbar/ContainerAwareToolbarFactory.php +++ b/libraries/src/Toolbar/ContainerAwareToolbarFactory.php @@ -102,7 +102,7 @@ private function loadButtonClass(string $type) $buttonClasses = [ 'Joomla\\CMS\\Toolbar\\Button\\' . $type . 'Button', /** - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 */ 'JToolbarButton' . $type, ]; diff --git a/libraries/src/Toolbar/Toolbar.php b/libraries/src/Toolbar/Toolbar.php index 6e761db08e4ba..329a9297a48cf 100644 --- a/libraries/src/Toolbar/Toolbar.php +++ b/libraries/src/Toolbar/Toolbar.php @@ -134,7 +134,7 @@ public function __construct($name = 'toolbar', ?ToolbarFactoryInterface $factory * * @since 1.5 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use the ToolbarFactoryInterface instead * Example: * Factory::getContainer()->get(ToolbarFactoryInterface::class)->createToolbar($name) @@ -147,7 +147,7 @@ public static function getInstance($name = 'toolbar') { $toolbar = Factory::getApplication()->getDocument()->getToolbar($name); - // @todo b/c remove with Joomla 7.0 or removed in 6.0 with this function + // @todo b/c remove with Joomla 7.0 or removed in 7.0 with this function if (empty(self::$instances[$name])) { self::$instances[$name] = $toolbar; } @@ -198,7 +198,7 @@ public function appendButton($button, ...$args) @trigger_error( \sprintf( - '%s::appendButton() should only accept %s instance in Joomla 6.0.', + '%s::appendButton() should only accept %s instance in Joomla 7.0.', static::class, ToolbarButton::class ), @@ -275,7 +275,7 @@ public function prependButton($button, ...$args) @trigger_error( \sprintf( - '%s::prependButton() should only accept %s instance in Joomla 6.0.', + '%s::prependButton() should only accept %s instance in Joomla 7.0.', static::class, ToolbarButton::class ), @@ -402,14 +402,14 @@ public function loadButtonType($type, $new = false) * * @since 1.5 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * ToolbarButton classes should be autoloaded via namespaces */ public function addButtonPath($path) { @trigger_error( \sprintf( - 'Registering lookup paths for toolbar buttons is deprecated and will be removed in Joomla 6.0.' + 'Registering lookup paths for toolbar buttons is deprecated and will be removed in Joomla 7.0.' . ' %1$s objects should be autoloaded or a custom %2$s implementation supporting path lookups provided.', ToolbarButton::class, ToolbarFactoryInterface::class @@ -439,14 +439,14 @@ public function addButtonPath($path) * @return array * * @since 4.0.0 - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * ToolbarButton buttons should be autoloaded via namespaces */ public function getButtonPath(): array { @trigger_error( \sprintf( - 'Lookup paths for %s objects is deprecated and will be removed in Joomla 6.0.', + 'Lookup paths for %s objects is deprecated and will be removed in Joomla 7.0.', ToolbarButton::class ), E_USER_DEPRECATED diff --git a/libraries/src/Toolbar/ToolbarButton.php b/libraries/src/Toolbar/ToolbarButton.php index 7c98b47f4a235..e496ada63bc8b 100644 --- a/libraries/src/Toolbar/ToolbarButton.php +++ b/libraries/src/Toolbar/ToolbarButton.php @@ -249,7 +249,7 @@ public function fetchIconClass($identifier) * * @since 3.0 * - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Use render() instead. */ abstract public function fetchButton(); @@ -450,7 +450,7 @@ public function __call(string $name, array $args) throw new \InvalidArgumentException( \sprintf( '%s::%s() miss first argument.', - \get_called_class(), + static::class, $name ) ); @@ -464,7 +464,7 @@ public function __call(string $name, array $args) \sprintf( 'Method %s() not found in class: %s', $name, - \get_called_class() + static::class ) ); } diff --git a/libraries/src/Toolbar/ToolbarHelper.php b/libraries/src/Toolbar/ToolbarHelper.php index dd6ce583cbbb1..013457cfaaad1 100644 --- a/libraries/src/Toolbar/ToolbarHelper.php +++ b/libraries/src/Toolbar/ToolbarHelper.php @@ -12,7 +12,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\FileLayout; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\ContentType; use Joomla\CMS\Uri\Uri; // phpcs:disable PSR1.Files.SideEffects @@ -93,7 +93,7 @@ public static function divider() * * @param string $task The task to perform (picked up by the switch($task) blocks). * @param string $icon The image to display. - * @param string $iconOver @deprecated 4.3 will be removed in 6.0 + * @param string $iconOver @deprecated 4.3 will be removed in 7.0 * @param string $alt The alt text for the icon image. * @param bool $listSelect True if required to check that a standard list item is checked. * @param string $formId The id of action form. @@ -675,8 +675,7 @@ public static function versions($typeAlias, $itemId, $height = 800, $width = 500 $lang = Factory::getLanguage(); $lang->load('com_contenthistory', JPATH_ADMINISTRATOR, $lang->getTag(), true); - /** @var \Joomla\CMS\Table\ContentType $contentTypeTable */ - $contentTypeTable = Table::getInstance('ContentType', '\\Joomla\\CMS\\Table\\'); + $contentTypeTable = new ContentType(Factory::getDbo()); $typeId = $contentTypeTable->getTypeId($typeAlias); // Options array for Layout diff --git a/libraries/src/UCM/UCMBase.php b/libraries/src/UCM/UCMBase.php index 090e3d7775c68..23195a660c07a 100644 --- a/libraries/src/UCM/UCMBase.php +++ b/libraries/src/UCM/UCMBase.php @@ -11,7 +11,6 @@ use Joomla\CMS\Factory; use Joomla\CMS\Helper\ContentHelper; -use Joomla\CMS\Table\Table; use Joomla\CMS\Table\TableInterface; // phpcs:disable PSR1.Files.SideEffects @@ -78,7 +77,7 @@ public function __construct($alias = null, ?UCMType $type = null) protected function store($data, ?TableInterface $table = null, $primaryKey = null) { if (!$table) { - $table = Table::getInstance('Ucm'); + $table = new \Joomla\CMS\Table\Ucm(Factory::getDbo()); } $ucmId = $data['ucm_id'] ?? null; diff --git a/libraries/src/UCM/UCMContent.php b/libraries/src/UCM/UCMContent.php index d86b239c324ef..94554e731ae5d 100644 --- a/libraries/src/UCM/UCMContent.php +++ b/libraries/src/UCM/UCMContent.php @@ -11,6 +11,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Helper\ContentHelper; +use Joomla\CMS\Table\CoreContent; use Joomla\CMS\Table\Table; use Joomla\CMS\Table\TableInterface; use Joomla\Database\ParameterType; @@ -115,7 +116,7 @@ public function delete($pk, ?UCMType $type = null) $pk = explode(',', $pk); } - $query = $db->getQuery(true) + $query = $db->createQuery() ->delete($db->quoteName('#__ucm_content')) ->where($db->quoteName('core_type_id') . ' = :typeId') ->whereIn($db->quoteName('core_content_item_id'), $pk) @@ -190,7 +191,7 @@ public function mapData($original, ?UCMType $type = null) */ protected function store($data, ?TableInterface $table = null, $primaryKey = null) { - $table = $table ?: Table::getInstance('CoreContent'); + $table = $table ?: new CoreContent(Factory::getDbo()); $typeId = $this->getType()->type->type_id; $primaryKey = $primaryKey ?: $this->getPrimaryKey($typeId, $data['core_content_item_id']); @@ -224,7 +225,7 @@ protected function store($data, ?TableInterface $table = null, $primaryKey = nul public function getPrimaryKey($typeId, $contentItemId) { $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('ucm_id')) ->from($db->quoteName('#__ucm_base')) ->where( diff --git a/libraries/src/UCM/UCMType.php b/libraries/src/UCM/UCMType.php index 5c6948711da39..729d169f56184 100644 --- a/libraries/src/UCM/UCMType.php +++ b/libraries/src/UCM/UCMType.php @@ -122,7 +122,7 @@ public function getType($pk = null) return $this->getTypeByAlias($this->alias); } - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('ct') . '.*') ->from($this->db->quoteName('#__content_types', 'ct')) ->where($this->db->quoteName('ct.type_id') . ' = :pk') @@ -145,7 +145,7 @@ public function getType($pk = null) */ public function getTypeByAlias($typeAlias = null) { - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('ct') . '.*') ->from($this->db->quoteName('#__content_types', 'ct')) ->where($this->db->quoteName('ct.type_alias') . ' = :alias') @@ -168,7 +168,7 @@ public function getTypeByAlias($typeAlias = null) */ public function getTypeByTable($tableName) { - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('ct') . '.*') ->from($this->db->quoteName('#__content_types', 'ct')); @@ -203,7 +203,7 @@ public function getTypeId($alias = null) $alias = $this->alias; } - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('ct.type_id')) ->from($this->db->quoteName('#__content_types', 'ct')) ->where($this->db->quoteName('ct.type_alias') . ' = :alias') diff --git a/libraries/src/Updater/Adapter/CollectionAdapter.php b/libraries/src/Updater/Adapter/CollectionAdapter.php index bcd86b7fe8ad1..806a8c1abdf6b 100644 --- a/libraries/src/Updater/Adapter/CollectionAdapter.php +++ b/libraries/src/Updater/Adapter/CollectionAdapter.php @@ -13,7 +13,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; use Joomla\CMS\Language\Text; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Update; use Joomla\CMS\Updater\UpdateAdapter; use Joomla\CMS\Version; @@ -121,7 +121,7 @@ public function _startElement($parser, $name, $attrs = []) } break; case 'EXTENSION': - $update = Table::getInstance('update'); + $update = new Update($this->db); $update->update_site_id = $this->updateSiteId; foreach ($this->updatecols as $col) { diff --git a/libraries/src/Updater/Adapter/ExtensionAdapter.php b/libraries/src/Updater/Adapter/ExtensionAdapter.php index d77449ad5cc88..3e08b1b83c2d6 100644 --- a/libraries/src/Updater/Adapter/ExtensionAdapter.php +++ b/libraries/src/Updater/Adapter/ExtensionAdapter.php @@ -13,7 +13,7 @@ use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; use Joomla\CMS\Language\Text; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\Update; use Joomla\CMS\Updater\UpdateAdapter; use Joomla\CMS\Updater\Updater; use Joomla\CMS\Version; @@ -32,6 +32,15 @@ class ExtensionAdapter extends UpdateAdapter protected $currentUpdate; protected $latest; + /** + * The updates with security fixes + * + * @var array + * + * @since 6.2.0 + */ + protected array $security = []; + /** * Start element parser callback. * @@ -55,7 +64,7 @@ protected function _startElement($parser, $name, $attrs = []) switch ($name) { case 'UPDATE': - $this->currentUpdate = Table::getInstance('update'); + $this->currentUpdate = new Update($this->db); $this->currentUpdate->update_site_id = $this->updateSiteId; $this->currentUpdate->detailsurl = $this->_url; $this->currentUpdate->folder = ''; @@ -134,7 +143,7 @@ protected function _endElement($parser, $name) // Check if DB & version is supported via tag, assume supported if tag isn't present if (isset($this->currentUpdate->supported_databases)) { - $db = Factory::getDbo(); + $db = $this->db; $dbType = strtolower($db->getServerType()); $dbVersion = $db->getVersion(); $supportedDbs = $this->currentUpdate->supported_databases; @@ -219,6 +228,10 @@ protected function _endElement($parser, $name) // We don't have any possible updates yet, assume this is an available update. $this->latest = $this->currentUpdate; } + + if (isset($this->currentUpdate->security)) { + $this->security[] = $this->currentUpdate; + } } } break; @@ -263,7 +276,7 @@ protected function _characterData($parser, $data) * * @param array $options Update options. * - * @return array|boolean Array containing the array of update sites and array of updates. False on failure + * @return array|boolean Array containing the array of update sites, an array of updates and an array of security updates. False on failure * * @since 1.7.0 */ @@ -275,6 +288,14 @@ public function findUpdate($options) return false; } + $this->security = []; + + /** + * Unset the latest update which might have been found for a previous update site, avoid + * strange issue reported at https://github.com/joomla/joomla-cms/issues/46066 + */ + unset($this->latest); + if (\array_key_exists('minimum_stability', $options)) { $this->minimum_stability = $options['minimum_stability']; } @@ -317,7 +338,7 @@ public function findUpdate($options) $updates = []; } - return ['update_sites' => [], 'updates' => $updates]; + return ['update_sites' => [], 'updates' => $updates, 'security' => $this->security]; } /** diff --git a/libraries/src/Updater/Adapter/TufAdapter.php b/libraries/src/Updater/Adapter/TufAdapter.php index 2bb8cb4fe4790..717610f9139ca 100644 --- a/libraries/src/Updater/Adapter/TufAdapter.php +++ b/libraries/src/Updater/Adapter/TufAdapter.php @@ -15,13 +15,15 @@ use Joomla\CMS\Application\ApplicationHelper; use Joomla\CMS\Factory; -use Joomla\CMS\Http\HttpFactory; -use Joomla\CMS\Table\Table; use Joomla\CMS\Table\Tuf as MetadataTable; +use Joomla\CMS\Table\Update; use Joomla\CMS\TUF\TufFetcher; use Joomla\CMS\Updater\ConstraintChecker; use Joomla\CMS\Updater\UpdateAdapter; use Joomla\CMS\Updater\Updater; +use Joomla\CMS\Version; +use Joomla\Http\HttpFactory; +use Joomla\Registry\Registry; use Symfony\Component\OptionsResolver\OptionsResolver; use Tuf\Exception\MetadataException; @@ -51,7 +53,7 @@ public function findUpdate($options) if ($targets) { foreach ($targets as $target) { - $updateTable = Table::getInstance('update'); + $updateTable = new Update($this->db); $updateTable->update_site_id = $options['update_site_id']; $updateTable->bind($target); @@ -80,7 +82,10 @@ public function getUpdateTargets($options) $metadataTable = new MetadataTable($this->db); $metadataTable->load(['update_site_id' => $options['update_site_id']]); - $tufFetcher = new TufFetcher($metadataTable, $options['location'], $this->db, (new HttpFactory())->getHttp(), Factory::getApplication()); + $httpOptions = new Registry(); + $httpOptions->set('userAgent', (new Version())->getUserAgent('Joomla', true, false)); + + $tufFetcher = new TufFetcher($metadataTable, $options['location'], $this->db, (new HttpFactory())->getHttp($httpOptions), Factory::getApplication()); $metaData = $tufFetcher->getValidUpdate(); $metaData = json_decode((string) $metaData, true); diff --git a/libraries/src/Updater/Update.php b/libraries/src/Updater/Update.php index 151376ba51c71..38ab90715d8d8 100644 --- a/libraries/src/Updater/Update.php +++ b/libraries/src/Updater/Update.php @@ -11,7 +11,6 @@ use Joomla\CMS\Factory; use Joomla\CMS\Filter\InputFilter; -use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; use Joomla\CMS\Object\LegacyErrorHandlingTrait; @@ -20,6 +19,7 @@ use Joomla\CMS\TUF\TufFetcher; use Joomla\CMS\Version; use Joomla\Database\DatabaseDriver; +use Joomla\Http\HttpFactory; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects @@ -548,11 +548,14 @@ public function _characterData($parser, $data) */ public function loadFromTuf(TufMetadata $metadataTable, string $url, $minimumStability = Updater::STABILITY_STABLE, $channel = null) { + $options = new Registry(); + $options->set('userAgent', (new Version())->getUserAgent('Joomla', true, false)); + $tufFetcher = new TufFetcher( $metadataTable, $url, Factory::getContainer()->get(DatabaseDriver::class), - (new HttpFactory())->getHttp(), + (new HttpFactory())->getHttp($options), Factory::getApplication(), ); @@ -658,7 +661,7 @@ public function loadFromXml($url, $minimumStability = Updater::STABILITY_STABLE, $httpOption->set('userAgent', $version->getUserAgent('Joomla', true, false)); try { - $http = HttpFactory::getHttp($httpOption); + $http = (new HttpFactory())->getHttp($httpOption); $response = $http->get($url); } catch (\RuntimeException) { $response = null; diff --git a/libraries/src/Updater/UpdateAdapter.php b/libraries/src/Updater/UpdateAdapter.php index b48542f72d465..6b061aa0ead09 100644 --- a/libraries/src/Updater/UpdateAdapter.php +++ b/libraries/src/Updater/UpdateAdapter.php @@ -9,15 +9,16 @@ namespace Joomla\CMS\Updater; -use Joomla\CMS\Adapter\AdapterInstance; use Joomla\CMS\Event\Installer\BeforeUpdateSiteDownloadEvent; use Joomla\CMS\Factory; -use Joomla\CMS\Http\HttpFactory; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; +use Joomla\CMS\Object\LegacyPropertyManagementTrait; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Version; +use Joomla\Database\DatabaseDriver; use Joomla\Database\ParameterType; +use Joomla\Http\HttpFactory; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects @@ -29,8 +30,18 @@ * * @since 1.7.0 */ -abstract class UpdateAdapter extends AdapterInstance +abstract class UpdateAdapter { + use LegacyPropertyManagementTrait; + + /** + * Parent + * + * @var Updater + * @since 1.6 + */ + protected $parent = null; + /** * Resource handle for the XML Parser * @@ -61,7 +72,7 @@ abstract class UpdateAdapter extends AdapterInstance * @var array * @since 3.0.0 */ - protected $updatecols = ['NAME', 'ELEMENT', 'TYPE', 'FOLDER', 'CLIENT', 'VERSION', 'DESCRIPTION', 'INFOURL', 'CHANGELOGURL', 'EXTRA_QUERY']; + protected $updatecols = ['NAME', 'ELEMENT', 'TYPE', 'FOLDER', 'CLIENT', 'VERSION', 'DESCRIPTION', 'INFOURL', 'CHANGELOGURL', 'EXTRA_QUERY', 'SECURITY']; /** * Should we try appending a .xml extension to the update site's URL? @@ -99,6 +110,37 @@ abstract class UpdateAdapter extends AdapterInstance */ protected $minimum_stability = Updater::STABILITY_STABLE; + /** + * Database + * + * @var DatabaseDriver + * @since 1.6 + */ + protected $db = null; + + /** + * Constructor + * + * @param Updater $parent Parent object + * @param DatabaseDriver $db Database object + * @param array $options Configuration Options + * + * @since 1.6 + */ + public function __construct(Updater $parent, DatabaseDriver $db, array $options = []) + { + $this->parent = $parent; + + foreach ($options as $key => $value) { + if (property_exists($this, $key)) { + $this->$key = $value; + } + } + + // Pull in the global dbo in case something happened to it. + $this->db = $db ?: Factory::getDbo(); + } + /** * Gets the reference to the current direct parent * @@ -154,8 +196,8 @@ protected function toggleUpdateSite($updateSiteId, $enabled = true) return; } - $db = $this->parent->getDbo(); - $query = $db->getQuery(true) + $db = $this->db; + $query = $db->createQuery() ->update($db->quoteName('#__update_sites')) ->set($db->quoteName('enabled') . ' = :enabled') ->where($db->quoteName('update_site_id') . ' = :id') @@ -185,8 +227,8 @@ protected function getUpdateSiteName($updateSiteId) return ''; } - $db = $this->parent->getDbo(); - $query = $db->getQuery(true) + $db = $this->db; + $query = $db->createQuery() ->select($db->quoteName('name')) ->from($db->quoteName('#__update_sites')) ->where($db->quoteName('update_site_id') . ' = :id') @@ -209,7 +251,7 @@ protected function getUpdateSiteName($updateSiteId) * * @param array $options The update options, see findUpdate() in children classes * - * @return \Joomla\CMS\Http\Response|bool False if we can't connect to the site, HTTP Response object otherwise + * @return \Joomla\Http\Response|bool False if we can't connect to the site, HTTP Response object otherwise * * @throws \Exception */ @@ -261,7 +303,7 @@ protected function getUpdateSiteResponse($options = []) // Http transport throws an exception when there's no response or an invalid HTTP status code returned. try { - $http = HttpFactory::getHttp($httpOption); + $http = (new HttpFactory())->getHttp($httpOption); $response = $http->get($newUrl, $headers, 20); } catch (\Throwable) { $response = null; diff --git a/libraries/src/Updater/Updater.php b/libraries/src/Updater/Updater.php index 2b6574b2ede48..19519127eefa7 100644 --- a/libraries/src/Updater/Updater.php +++ b/libraries/src/Updater/Updater.php @@ -9,9 +9,14 @@ namespace Joomla\CMS\Updater; -use Joomla\CMS\Adapter\Adapter; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Factory; +use Joomla\CMS\Object\LegacyPropertyManagementTrait; +use Joomla\CMS\Table\Extension; +use Joomla\CMS\Table\Update as UpdateTable; +use Joomla\Database\DatabaseAwareInterface; +use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; +use Joomla\DI\ContainerAwareInterface; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -22,8 +27,11 @@ * * @since 1.7.0 */ -class Updater extends Adapter +class Updater implements DatabaseAwareInterface { + use DatabaseAwareTrait; + use LegacyPropertyManagementTrait; + /** * Development snapshots, nightly builds, pre-release versions and so on * @@ -72,6 +80,30 @@ class Updater extends Adapter */ protected static $instance; + /** + * Array of installer adapters + * + * @var string[]|UpdateAdapter[] + * @since 6.0.0 + */ + private $adapters = []; + + /** + * Adapter Class Prefix + * + * @var string + * @since 6.0.0 + */ + private $classprefix = '\\Joomla\\CMS\\Updater\\Adapter'; + + /** + * Base Path for the installer adapters + * + * @var string + * @since 6.0.0 + */ + private $adapterfolder; + /** * Constructor * @@ -83,7 +115,9 @@ class Updater extends Adapter */ public function __construct($basepath = __DIR__, $classprefix = '\\Joomla\\CMS\\Updater\\Adapter', $adapterfolder = 'Adapter') { - parent::__construct($basepath, $classprefix, $adapterfolder); + $this->adapterfolder = $basepath . '/' . $adapterfolder; + $this->classprefix = $classprefix; + $this->loadAdapters(); } /** @@ -98,6 +132,7 @@ public static function getInstance() { if (!isset(self::$instance)) { self::$instance = new static(); + self::$instance->setDatabase(Factory::getDbo()); } return self::$instance; @@ -153,8 +188,8 @@ public function findUpdates($eid = 0, $cacheTimeout = 0, $minimumStability = sel } // Make sure there is no update left over in the database. - $db = $this->getDbo(); - $query = $db->getQuery(true) + $db = $this->getDatabase(); + $query = $db->createQuery() ->delete($db->quoteName('#__updates')) ->where($db->quoteName('update_site_id') . ' = :id') ->bind(':id', $result['update_site_id'], ParameterType::INTEGER); @@ -222,8 +257,8 @@ public function getAvailableUpdates(int $eid, string $minimumStability = self::S */ private function getUpdateSites($eid = 0) { - $db = $this->getDbo(); - $query = $db->getQuery(true); + $db = $this->getDatabase(); + $query = $db->createQuery(); $query->select( [ @@ -278,19 +313,17 @@ private function getUpdateObjectsForSite($updateSite, $minimumStability = self:: { $retVal = []; - $this->setAdapter($updateSite['type']); - - if (!isset($this->_adapters[$updateSite['type']])) { + try { + // Get the update information from the remote update XML document + /** @var UpdateAdapter $adapter */ + $adapter = $this->getAdapter($updateSite['type']); + } catch (\InvalidArgumentException $e) { // Ignore update sites requiring adapters we don't have installed return $retVal; } $updateSite['minimum_stability'] = $minimumStability; - - // Get the update information from the remote update XML document - /** @var UpdateAdapter $adapter */ - $adapter = $this->_adapters[$updateSite['type']]; - $update_result = $adapter->findUpdate($updateSite); + $update_result = $adapter->findUpdate($updateSite); // Version comparison operator. $operator = $includeCurrent ? 'ge' : 'gt'; @@ -323,11 +356,8 @@ private function getUpdateObjectsForSite($updateSite, $minimumStability = self:: foreach ($update_result['updates'] as $current_update) { $current_update->extra_query = $updateSite['extra_query']; - /** @var \Joomla\CMS\Table\Update $update */ - $update = Table::getInstance('update'); - - /** @var \Joomla\CMS\Table\Extension $extension */ - $extension = Table::getInstance('extension'); + $update = new UpdateTable($this->getDatabase()); + $extension = new Extension($this->getDatabase()); $uid = $update ->find( @@ -358,6 +388,7 @@ private function getUpdateObjectsForSite($updateSite, $minimumStability = self:: if (version_compare($current_update->version, $data['version'], $operator) == 1) { $current_update->extension_id = $eid; + $current_update->security = $this->findHighestSeverity($data['version'], $current_update, $update_result['security'] ?? []); $retVal[] = $current_update; } } else { @@ -376,6 +407,17 @@ private function getUpdateObjectsForSite($updateSite, $minimumStability = self:: // If there is an update, check that the version is newer then replaces if (version_compare($current_update->version, $update->version, $operator) == 1) { $retVal[] = $current_update; + if (!$eid) { + continue; + } + + $extension->load($eid); + $data = json_decode($extension->manifest_cache ?? '', true); + if (empty($data['version'])) { + continue; + } + + $current_update->security = $this->findHighestSeverity($data['version'], $current_update, $update_result['security'] ?? []); } } } @@ -385,6 +427,31 @@ private function getUpdateObjectsForSite($updateSite, $minimumStability = self:: return $retVal; } + /** + * Searches for the highest severity in security updates since the installed version. + * + * @param string $installedVersion The installed version + * @param UpdateTable $update The latest compatible update + * @param array $securityUpdates The found security updates + * + * @return int|null + * + * @since 6.2.0 + */ + private function findHighestSeverity(string $installedVersion, UpdateTable $update, array $securityUpdates): ?int + { + $securityLevel = (int) $update->security; + + /** @var \Joomla\CMS\Table\Update $securityUpdate */ + foreach ($securityUpdates as $securityUpdate) { + if (version_compare($securityUpdate->version, $installedVersion, '>') && $securityLevel < (int) $securityUpdate->security) { + $securityLevel = (int) $securityUpdate->security; + } + } + + return $securityLevel; + } + /** * Returns the IDs of the update sites with cached updates * @@ -397,15 +464,15 @@ private function getUpdateObjectsForSite($updateSite, $minimumStability = self:: */ private function getSitesWithUpdates($timestamp = 0) { - $db = $this->getDbo(); + $db = $this->getDatabase(); $timestamp = (int) $timestamp; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select('DISTINCT ' . $db->quoteName('update_site_id')) ->from($db->quoteName('#__updates')); if ($timestamp) { - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select($db->quoteName('update_site_id')) ->from($db->quoteName('#__update_sites')) ->where( @@ -441,10 +508,10 @@ private function getSitesWithUpdates($timestamp = 0) private function updateLastCheckTimestamp($updateSiteId) { $timestamp = time(); - $db = $this->getDbo(); + $db = $this->getDatabase(); $updateSiteId = (int) $updateSiteId; - $query = $db->getQuery(true) + $query = $db->createQuery() ->update($db->quoteName('#__update_sites')) ->set($db->quoteName('last_check_timestamp') . ' = :timestamp') ->where($db->quoteName('update_site_id') . ' = :id') @@ -453,4 +520,148 @@ private function updateLastCheckTimestamp($updateSiteId) $db->setQuery($query); $db->execute(); } + + /** + * Discover all adapters in the adapterfolder path + * + * @return void + * + * @since 6.0.0 + */ + protected function loadAdapters() + { + $files = new \DirectoryIterator($this->adapterfolder); + + // Process the core adapters + foreach ($files as $file) { + $fileName = $file->getFilename(); + + // Only load php files. + if (!$file->isFile() || $file->getExtension() !== 'php') { + continue; + } + + // Derive the class name from the filename. + $name = str_ireplace('.php', '', trim($fileName)); + $name = str_ireplace('adapter', '', trim($name)); + $class = rtrim($this->classprefix, '\\') . '\\' . ucfirst($name) . 'Adapter'; + + if (!class_exists($class)) { + // Not namespaced + $class = $this->classprefix . ucfirst($name); + } + + // Core adapters should autoload based on classname, keep this fallback just in case + if (!class_exists($class)) { + // Try to load the adapter object + \JLoader::register($class, $this->adapterfolder . '/' . $fileName); + + if (!class_exists($class)) { + // Skip to next one + continue; + } + } + + $this->adapters[strtolower($name)] = $class; + } + } + + /** + * Gets a list of available update adapters. + * + * @param array $options An array of options to inject into the adapter + * @param array $custom Array of custom update adapters + * + * @return string[] An array of the class names of available install adapters. + * + * @since 3.4 + */ + public function getAdapters($options = [], array $custom = []) + { + if (\count($custom)) { + foreach ($custom as $adapter) { + // Setup the class name + // @todo - Can we abstract this to not depend on the Joomla class namespace without PHP namespaces? + $class = $this->classprefix . ucfirst(trim($adapter)); + + // If the class doesn't exist we have nothing left to do but look at the next type. We did our best. + if (!class_exists($class)) { + continue; + } + + $this->adapters[$adapter] = $class; + } + } + + return array_keys($this->adapters); + } + + /** + * Get an update adapter instance + * + * @param string $name Adapter name + * @param array $options Adapter options + * + * @return UpdateAdapter + * + * @throws \InvalidArgumentException + * @since 6.0.0 + */ + public function getAdapter($name, $options = []) + { + $name = strtolower($name); + + if (!isset($this->adapters[$name])) { + throw new \InvalidArgumentException(\sprintf('The %s update adapter does not exist.', $name)); + } + + if (\is_string($this->adapters[$name])) { + $class = $this->adapters[$name]; + + // Ensure the adapter type is part of the options array + $options['type'] = $name; + + // Check for a possible service from the container otherwise manually instantiate the class + if (Factory::getContainer()->has($class)) { + return Factory::getContainer()->get($class); + } + + $adapter = new $class($this, $this->getDatabase(), $options); + + if ($adapter instanceof ContainerAwareInterface) { + $adapter->setContainer(Factory::getContainer()); + } + + $this->adapters[$name] = $adapter; + } + + return $this->adapters[$name]; + } + + /** + * Set an adapter by name + * + * @param string $name Adapter name + * @param UpdateAdapter|string $adapter Adapter object or class name + * + * @return boolean True if successful + * + * @since 6.0.0 + */ + public function setAdapter($name, $adapter) + { + if (\is_object($adapter)) { + $this->adapters[$name] = $adapter; + + return true; + } + + if (class_exists($adapter)) { + $this->adapters[$name] = $adapter; + + return true; + } + + return false; + } } diff --git a/libraries/src/User/CurrentUserTrait.php b/libraries/src/User/CurrentUserTrait.php index bafe46e0a3e81..430a189de4351 100644 --- a/libraries/src/User/CurrentUserTrait.php +++ b/libraries/src/User/CurrentUserTrait.php @@ -32,7 +32,7 @@ trait CurrentUserTrait /** * Returns the current user, if none is set the identity of the global app - * is returned. This will change in 6.0 and an empty user will be returned. + * is returned. This will change in 7.0 and an empty user will be returned. * * @return User * @@ -42,7 +42,7 @@ protected function getCurrentUser(): User { if (!$this->currentUser) { @trigger_error( - \sprintf('User must be set in %s. This will not be caught anymore in 6.0', __METHOD__), + \sprintf('User must be set in %s. This will not be caught anymore in 7.0', __METHOD__), E_USER_DEPRECATED ); $this->currentUser = Factory::getApplication()->getIdentity() ?: Factory::getUser(); diff --git a/libraries/src/User/User.php b/libraries/src/User/User.php index f7273e6334c4b..cef076750124b 100644 --- a/libraries/src/User/User.php +++ b/libraries/src/User/User.php @@ -10,6 +10,7 @@ namespace Joomla\CMS\User; use Joomla\CMS\Access\Access; +use Joomla\CMS\Application\ConsoleApplication; use Joomla\CMS\Event\User\AfterDeleteEvent; use Joomla\CMS\Event\User\AfterSaveEvent; use Joomla\CMS\Event\User\BeforeDeleteEvent; @@ -291,7 +292,7 @@ public function __construct($identifier = 0) * @return User The User object. * * @since 1.7.0 - * @deprecated 4.3 will be removed in 6.0 + * @deprecated 4.3 will be removed in 7.0 * Load the user service from the dependency injection container or via $app->getIdentity() * Example: Factory::getContainer()->get(UserFactoryInterface::class)->loadUserById($id) */ @@ -429,7 +430,7 @@ public function getAuthorisedCategories($component, $action) // @todo: Modify the way permissions are stored in the db to allow for faster implementation and better scaling $db = Factory::getDbo(); - $subQuery = $db->getQuery(true) + $subQuery = $db->createQuery() ->select($db->quoteName(['id', 'asset_id'])) ->from($db->quoteName('#__categories')) ->where( @@ -439,7 +440,7 @@ public function getAuthorisedCategories($component, $action) ] ); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['c.id', 'a.name'])) ->from('(' . $subQuery . ') AS ' . $db->quoteName('c')) ->join('INNER', $db->quoteName('#__assets', 'a'), $db->quoteName('c.asset_id') . ' = ' . $db->quoteName('a.id')) @@ -542,7 +543,7 @@ public function setLastVisit($timestamp = null) */ public function getTimezone() { - $timezone = $this->getParam('timezone', Factory::getApplication()->get('offset', 'GMT')); + $timezone = $this->getParam('timezone', Factory::getApplication()->get('offset', 'UTC')); return new \DateTimeZone($timezone); } @@ -582,18 +583,16 @@ public static function getTable($type = null, $prefix = '\\Joomla\\CMS\\Table\\' // Set the default tabletype; if (!isset($tabletype)) { - $tabletype['name'] = 'user'; - $tabletype['prefix'] = '\\Joomla\\CMS\\Table\\'; + $tabletype = \Joomla\CMS\Table\User::class; } // Set a custom table type is defined if (isset($type)) { - $tabletype['name'] = $type; - $tabletype['prefix'] = $prefix; + $tabletype = rtrim($prefix, '\\') . '\\' . $type; } // Create the user table object - return Table::getInstance($tabletype['name'], $tabletype['prefix']); + return new $tabletype(Factory::getDbo()); } /** @@ -747,15 +746,8 @@ public function save($updateOnly = false) $iAmRehashingSuperadmin = true; } - // Check if we are using a CLI application - $isCli = false; - - if (Factory::getApplication()->isCli()) { - $isCli = true; - } - // We are only worried about edits to this account if I am not a Super Admin. - if (!$iAmSuperAdmin && !$iAmRehashingSuperadmin && !$isCli) { + if (!$iAmSuperAdmin && !$iAmRehashingSuperadmin && !Factory::getApplication() instanceof ConsoleApplication) { // I am not a Super Admin, and this one is, so fail. if (!$isNew && Access::check($this->id, 'core.admin')) { throw new \RuntimeException('User not Super Administrator'); diff --git a/libraries/src/User/UserFactory.php b/libraries/src/User/UserFactory.php index 5669d560f3e38..7f00469884d70 100644 --- a/libraries/src/User/UserFactory.php +++ b/libraries/src/User/UserFactory.php @@ -65,7 +65,7 @@ public function loadUserById(int $id): User public function loadUserByUsername(string $username): User { // Initialise some variables - $query = $this->db->getQuery(true) + $query = $this->db->createQuery() ->select($this->db->quoteName('id')) ->from($this->db->quoteName('#__users')) ->where($this->db->quoteName('username') . ' = :username') diff --git a/libraries/src/User/UserHelper.php b/libraries/src/User/UserHelper.php index c505dec007d5e..a7a7ed765c286 100644 --- a/libraries/src/User/UserHelper.php +++ b/libraries/src/User/UserHelper.php @@ -17,16 +17,17 @@ use Joomla\CMS\Authentication\Password\CheckIfRehashNeededHandlerInterface; use Joomla\CMS\Authentication\Password\MD5Handler; use Joomla\CMS\Authentication\Password\PHPassHandler; -use Joomla\CMS\Crypt\Crypt; +use Joomla\CMS\Event\Model\PrepareDataEvent; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Log\Log; -use Joomla\CMS\Object\CMSObject; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Session\SessionManager; use Joomla\CMS\Uri\Uri; +use Joomla\Crypt\Crypt; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; +use Joomla\Event\DispatcherInterface; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -61,7 +62,7 @@ abstract class UserHelper * @var integer * @since 4.0.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use UserHelper::HASH_ARGON2I instead */ public const HASH_ARGON2I_BC = 2; @@ -84,7 +85,7 @@ abstract class UserHelper * @var integer * @since 4.0.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use UserHelper::HASH_ARGON2ID instead */ public const HASH_ARGON2ID_BC = 3; @@ -103,7 +104,7 @@ abstract class UserHelper * @var integer * @since 4.0.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Use UserHelper::HASH_BCRYPT instead */ public const HASH_BCRYPT_BC = 1; @@ -114,7 +115,7 @@ abstract class UserHelper * @var string * @since 4.0.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Support for MD5 hashed passwords will be removed use any of the other hashing methods */ public const HASH_MD5 = 'md5'; @@ -125,7 +126,7 @@ abstract class UserHelper * @var string * @since 4.0.0 * - * @deprecated 4.0 will be removed in 6.0 + * @deprecated 4.0 will be removed in 7.0 * Support for PHPass hashed passwords will be removed use any of the other hashing methods */ public const HASH_PHPASS = 'phpass'; @@ -171,7 +172,7 @@ public static function addUserToGroup($userId, $groupId) if (!\in_array($groupId, $user->groups)) { // Check whether the group exists. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('id') . ' = :groupId') @@ -197,7 +198,7 @@ public static function addUserToGroup($userId, $groupId) $temp = User::getInstance($userId); $temp->groups = $user->groups; - if (Factory::getSession()->getId()) { + if (Factory::getApplication()->getSession()->getId()) { // Set the group data for the user object in the session. $temp = Factory::getUser(); @@ -287,7 +288,7 @@ public static function setUserGroups($userId, $groups) // Get the titles for the user groups. $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName(['id', 'title'])) ->from($db->quoteName('#__usergroups')) ->whereIn($db->quoteName('id'), $user->groups); @@ -306,7 +307,7 @@ public static function setUserGroups($userId, $groups) $temp = Factory::getUser((int) $userId); $temp->groups = $user->groups; - if (Factory::getSession()->getId()) { + if (Factory::getApplication()->getSession()->getId()) { // Set the group data for the user object in the session. $temp = Factory::getUser(); @@ -337,11 +338,17 @@ public static function getProfile($userId = 0) // Get the dispatcher and load the user's plugins. PluginHelper::importPlugin('user'); - $data = new CMSObject(); + $data = new \stdClass(); $data->id = $userId; // Trigger the data preparation event. - Factory::getApplication()->triggerEvent('onContentPrepareData', ['com_users.profile', &$data]); + Factory::getContainer()->get(DispatcherInterface::class)->dispatch( + 'onContentPrepareData', + new PrepareDataEvent('onContentPrepareData', [ + 'context' => 'com_users.profile', + 'data' => $data, + ]) + ); return $data; } @@ -360,7 +367,7 @@ public static function activateUser($activation) $db = Factory::getDbo(); // Let's get the id of the user we want to activate - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where($db->quoteName('activation') . ' = :activation') @@ -405,7 +412,7 @@ public static function getUserId($username) { // Initialise some variables $db = Factory::getDbo(); - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where($db->quoteName('username') . ' = :username') @@ -593,8 +600,10 @@ public static function checkSuperUserInUsers(array $userIds) */ public static function destroyUserSessions($userId, $keepCurrent = false, $clientId = null) { + $app = Factory::getApplication(); + // Destroy all sessions for the user account if able - if (!Factory::getApplication()->get('session_metadata', true)) { + if (!$app->get('session_metadata', true)) { return false; } @@ -603,7 +612,7 @@ public static function destroyUserSessions($userId, $keepCurrent = false, $clien try { $userId = (int) $userId; - $query = $db->getQuery(true) + $query = $db->createQuery() ->select($db->quoteName('session_id')) ->from($db->quoteName('#__session')) ->where($db->quoteName('userid') . ' = :userid') @@ -630,7 +639,7 @@ public static function destroyUserSessions($userId, $keepCurrent = false, $clien // If true, removes the current session id from the purge list if ($keepCurrent) { - $sessionIds = array_diff($sessionIds, [Factory::getSession()->getId()]); + $sessionIds = array_diff($sessionIds, [$app->getSession()->getId()]); } // If there aren't any active sessions then there's nothing to do here @@ -644,7 +653,7 @@ public static function destroyUserSessions($userId, $keepCurrent = false, $clien try { $db->setQuery( - $db->getQuery(true) + $db->createQuery() ->delete($db->quoteName('#__session')) ->whereIn($db->quoteName('session_id'), $sessionIds, ParameterType::LARGE_OBJECT) )->execute(); diff --git a/libraries/src/Utility/BufferStreamHandler.php b/libraries/src/Utility/BufferStreamHandler.php index d0c290c349c85..0bd543be24036 100644 --- a/libraries/src/Utility/BufferStreamHandler.php +++ b/libraries/src/Utility/BufferStreamHandler.php @@ -6,7 +6,6 @@ * @copyright (C) 2007 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt * - * Remove phpcs exception with deprecated autoloading BufferStreamHandler::stream_register(); * @phpcs:disable PSR1.Files.SideEffects */ @@ -14,13 +13,6 @@ \defined('_JEXEC') or die; -/** - * @deprecated 3.8 will be removed in 5.0 - * Workaround for B/C. (removal missed in 4.0, also remove phpcs exception). - * If BufferStreamHandler is needed directly call BufferStreamHandler::stream_register(); - */ -BufferStreamHandler::stream_register(); - /** * Generic Buffer stream handler * @@ -73,7 +65,7 @@ class BufferStreamHandler public static function stream_register() { if (!self::$registered) { - stream_wrapper_register('buffer', '\\Joomla\\CMS\\Utility\\BufferStreamHandler'); + stream_wrapper_register('buffer', BufferStreamHandler::class); self::$registered = true; } diff --git a/libraries/src/Version.php b/libraries/src/Version.php index e6b85680897fe..8f4082815e7bd 100644 --- a/libraries/src/Version.php +++ b/libraries/src/Version.php @@ -39,7 +39,7 @@ final class Version * @var integer * @since 3.8.0 */ - public const MAJOR_VERSION = 5; + public const MAJOR_VERSION = 6; /** * Minor release version. @@ -47,7 +47,7 @@ final class Version * @var integer * @since 3.8.0 */ - public const MINOR_VERSION = 4; + public const MINOR_VERSION = 2; /** * Patch release version. @@ -55,7 +55,7 @@ final class Version * @var integer * @since 3.8.0 */ - public const PATCH_VERSION = 8; + public const PATCH_VERSION = 0; /** * Extra release version info. @@ -66,7 +66,7 @@ final class Version * @var string * @since 3.8.0 */ - public const EXTRA_VERSION = 'rc3-dev'; + public const EXTRA_VERSION = 'beta2-dev'; /** * Development status. @@ -82,7 +82,7 @@ final class Version * @var string * @since 3.5 */ - public const CODENAME = 'Kutegemea'; + public const CODENAME = 'Mwezi'; /** * Release date. @@ -90,7 +90,7 @@ final class Version * @var string * @since 3.5 */ - public const RELDATE = '15-August-2026'; + public const RELDATE = '18-August-2026'; /** * Release time. @@ -98,7 +98,7 @@ final class Version * @var string * @since 3.5 */ - public const RELTIME = '16:31'; + public const RELTIME = '18:01'; /** * Release timezone. @@ -106,7 +106,7 @@ final class Version * @var string * @since 3.5 */ - public const RELTZ = 'GMT'; + public const RELTZ = 'UTC'; /** * Copyright Notice. diff --git a/libraries/src/Versioning/VersionableControllerTrait.php b/libraries/src/Versioning/VersionableControllerTrait.php index 8e9d8a1e7eeaf..1acf83d697116 100644 --- a/libraries/src/Versioning/VersionableControllerTrait.php +++ b/libraries/src/Versioning/VersionableControllerTrait.php @@ -36,9 +36,9 @@ public function loadhistory() $table = $model->getTable(); $historyId = $this->input->getInt('version_id', null); - if (!$model->loadhistory($historyId, $table)) { - $this->setMessage($model->getError(), 'error'); + $id = $model->getItemIdFromHistory($historyId); + if (false === $id) { $this->setRedirect( Route::_( 'index.php?option=' . $this->option . '&view=' . $this->view_list @@ -51,17 +51,13 @@ public function loadhistory() } // Determine the name of the primary key for the data. - if (empty($key)) { - $key = $table->getKeyName(); - } - - $recordId = $table->$key; + $key = $table->getKeyName(); // To avoid data collisions the urlVar may be different from the primary key. $urlVar = empty($this->urlVar) ? $key : $this->urlVar; // Access check. - if (!$this->allowEdit([$key => $recordId], $key)) { + if (!$this->allowEdit([$key => $id], $key)) { $this->setMessage(Text::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'), 'error'); $this->setRedirect( @@ -79,13 +75,21 @@ public function loadhistory() $this->setRedirect( Route::_( 'index.php?option=' . $this->option . '&view=' . $this->view_item - . $this->getRedirectToItemAppend($recordId, $urlVar), + . $this->getRedirectToItemAppend($id, $urlVar), false ) ); - if (!$table->check() || !$table->store()) { - $this->setMessage($table->getError(), 'error'); + if (!$model->loadhistory($historyId, $table)) { + $this->setMessage($model->getError(), 'error'); + + $this->setRedirect( + Route::_( + 'index.php?option=' . $this->option . '&view=' . $this->view_list + . $this->getRedirectToListAppend(), + false + ) + ); return false; } diff --git a/libraries/src/Versioning/VersionableModelInterface.php b/libraries/src/Versioning/VersionableModelInterface.php new file mode 100644 index 0000000000000..9d13f6bf765c9 --- /dev/null +++ b/libraries/src/Versioning/VersionableModelInterface.php @@ -0,0 +1,58 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\CMS\Versioning; + +// phpcs:disable PSR1.Files.SideEffects + +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * Interface for a versionable model. + * + * @since 6.0.0 + */ +interface VersionableModelInterface +{ + /** + * Method to load a row for editing from the version history table. + * + * @param integer $historyId Key to the version history table. + * + * @return boolean False on failure or error, true otherwise. + * + * @since 6.0.0 + */ + public function loadHistory(int $historyId); + + /** + * Method to save the history. + * + * @param array $data The form data. + * @param string $context The model context. + * + * @return boolean True on success, False on error. + * + * @since 6.0.0 + */ + public function saveHistory(array $data, string $context); + + /** + * Method to delete the history for an item. + * + * @param string $typeAlias Typealias of the content type + * @param integer $id ID of the content item to delete + * + * @return boolean true on success, otherwise false. + * + * @since 6.0.0 + */ + public function deleteHistory($typeAlias, $id); +} diff --git a/libraries/src/Versioning/VersionableModelTrait.php b/libraries/src/Versioning/VersionableModelTrait.php index 7d15df8364120..4e745fc28c709 100644 --- a/libraries/src/Versioning/VersionableModelTrait.php +++ b/libraries/src/Versioning/VersionableModelTrait.php @@ -9,9 +9,15 @@ namespace Joomla\CMS\Versioning; +use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Date\Date; -use Joomla\CMS\Language\Text; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Event\AbstractEvent; +use Joomla\CMS\Factory; +use Joomla\CMS\Plugin\PluginHelper; +use Joomla\CMS\Table\ContentHistory; +use Joomla\CMS\Table\ContentType; +use Joomla\CMS\Workflow\WorkflowServiceInterface; +use Joomla\Database\ParameterType; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects @@ -26,60 +32,129 @@ trait VersionableModelTrait { /** - * Method to load a row for editing from the version history table. + * Fields to be ignored when calculating the hash. * - * @param integer $versionId Key to the version history table. - * @param Table $table Content table object being loaded. + * @var array + * @since 6.0.0 + */ + protected $ignoreChanges = [ + 'modified_by', + 'modified_user_id', + 'modified', + 'modified_time', + 'checked_out', + 'checked_out_time', + 'tagsHelper', + 'version', + 'articletext', + 'rules', + 'hits', + 'path', + 'newTags', + ]; + + /** + * Fields to be converted to int when calculating the hash. * - * @return boolean False on failure or error, true otherwise. + * @var array + * @since 6.0.0 + */ + protected $convertToInt = ['publish_up', 'publish_down', 'ordering', 'featured']; + + /** + * Method to get the item id from the version history table. + * + * @param integer $historyId Key to the version history table. * - * @since 4.0.0 + * @return integer False on failure or error, id otherwise. + * + * @since 6.0.0 */ - public function loadHistory($versionId, Table $table) + public function getItemIdFromHistory($historyId) { - // Only attempt to check the row in if it exists, otherwise do an early exit. - if (!$versionId) { + $rowArray = $this->getHistoryData($historyId); + + if (false === $rowArray) { return false; } - // Get an instance of the row to checkout. - $historyTable = Table::getInstance('ContentHistory'); + $table = $this->getTable(); + $key = $table->getKeyName(); - if (!$historyTable->load($versionId)) { - $this->setError($historyTable->getError()); + if (isset($rowArray[$key])) { + return $rowArray[$key]; + } + + return false; + } + + /** + * Method to get the version data from the version history table. + * + * @param integer $historyId Key to the version history table. + * + * @return mixed False on failure or error, data otherwise. + * + * @since 6.0.0 + */ + protected function getHistoryData($historyId) + { + // Get an instance of the row to checkout. + $historyTable = new ContentHistory($this->getDatabase()); + if (!$historyTable->load($historyId)) { return false; } - $typeAlias = explode('.', $historyTable->item_id); - array_pop($typeAlias); - $rowArray = ArrayHelper::fromObject(json_decode($historyTable->version_data)); - $key = $table->getKeyName(); + return $rowArray; + } - if (implode('.', $typeAlias) != $this->typeAlias) { - $this->setError(Text::_('JLIB_APPLICATION_ERROR_HISTORY_ID_MISMATCH')); + /** + * Method to get a version history table. + * + * @param integer $historyId Key to the version history table. + * + * @return mixed False on failure or error, table otherwise. + * + * @since 6.0.0 + */ + protected function getHistoryTable($historyId) + { + if (empty($historyId)) { + return false; + } - if (isset($rowArray[$key])) { - $table->checkIn($rowArray[$key]); - } + // Get an instance of the row to checkout. + $historyTable = new ContentHistory($this->getDatabase()); + if (!$historyTable->load($historyId)) { return false; } - $this->setState('save_date', $historyTable->save_date); - $this->setState('version_note', $historyTable->version_note); + return $historyTable; + } - /** - * Load data from current version before replacing it with data from history to avoid error - * if there are some required keys missing in the history data - */ + /** + * Method to load a row for editing from the version history table. + * + * @param integer $historyId Key to the version history table. + * + * @return boolean False on failure or error, true otherwise. + * + * @since 6.0.0 + */ + public function loadHistory(int $historyId) + { + $rowArray = $this->getHistoryData($historyId); - if (isset($rowArray[$key])) { - $table->load($rowArray[$key]); + if (false === $rowArray) { + return false; } + $table = $this->getTable(); + // We set checked_out to the current user if ($table->hasField('checked_out')) { $rowArray[$table->getColumnAlias('checked_out')] = $this->getCurrentUser()->id; @@ -94,6 +169,325 @@ public function loadHistory($versionId, Table $table) $rowArray['ordering'] = 0; } - return $table->bind($rowArray); + // Fix null note when restoring history + if (\array_key_exists('note', $rowArray) && $rowArray['note'] === null) { + $rowArray['note'] = ''; + } + + $historyTable = $this->getHistoryTable($historyId); + + $this->setState('save_date', $historyTable->save_date); + $this->setState('version_note', $historyTable->version_note); + + /** + * The version history is created prior to Joomla 6.0, so we can only restore item data, not a full + * restore like we can do with Joomla 6.0+ version history. + */ + if ($historyTable->is_legacy) { + $key = $table->getKeyName(); + + /** + * Load data from current version before replacing it with data from history to avoid error + * if there are some required keys missing in the history data + */ + if (isset($rowArray[$key])) { + $table->load($rowArray[$key]); + } + + $table->bind($rowArray); + + if (!$table->check() || !$table->store()) { + $ret = false; + } else { + $ret = true; + } + } else { + $ret = $this->save($rowArray); + } + + // Mark the restored version as current + if ($ret) { + $this->markVersionAsCurrent($historyTable->version_id, $historyTable->item_id); + } + + return $ret; + } + + /** + * Utility method to get the hash after removing selected values. This lets us detect changes other than + * modified date (which will change on every save). + * + * @param mixed $data Either an object or an array + * + * @return string SHA1 hash on success. Empty string on failure. + * + * @since 6.0.0 + */ + public function getSha1($data) + { + $object = \is_object($data) ? $data : ArrayHelper::toObject($data); + + foreach ($this->ignoreChanges as $remove) { + if (property_exists($object, $remove)) { + unset($object->$remove); + } + } + + // Convert integers, booleans, and nulls to strings to get a consistent hash value + foreach ($object as $name => $value) { + if (\is_object($value)) { + // Go one level down for JSON column values + foreach ($value as $subName => $subValue) { + $object->$subName = \is_int($subValue) || \is_bool($subValue) || $subValue === null ? (string) $subValue : $subValue; + } + } else { + $object->$name = \is_int($value) || \is_bool($value) || $value === null ? (string) $value : $value; + } + } + + // Work around empty values + foreach ($this->convertToInt as $convert) { + if (isset($object->$convert)) { + $object->$convert = (int) $object->$convert; + } + } + + if (isset($object->review_time)) { + $object->review_time = (int) $object->review_time; + } + + return sha1(json_encode($object)); + } + + /** + * Setter for the value + * + * @param array $ignoreChanges + * + * @return void + * + * @since 6.0.0 + */ + public function setIgnoreChanges(array $ignoreChanges): void + { + $this->ignoreChanges = $ignoreChanges; + } + + /** + * Setter for the value + * + * @param array $convertToInt + * + * @return void + * + * @since 6.0.0 + */ + public function setConvertToInt(array $convertToInt): void + { + $this->convertToInt = $convertToInt; + } + + /** + * Method to save the history. + * + * @param array $data The form data. + * @param string $context The model context. + * + * @return boolean True on success, False on error. + * + * @since 6.0.0 + */ + public function saveHistory(array $data, string $context) + { + if (!$this->versionHistoryEnabled($context)) { + return false; + } + + $id = $this->getState($this->getName() . '.id'); + + /** + * Merge item data and form data so that we write all data to the history. We have to rel + * from database to have default data populated for fields which are not passed in $data array, + * avoid error such as Column 'created_by_alias' cannot be null" when restore from version history + */ + $table = $this->getTable(); + $table->load($id); + $itemData = ArrayHelper::fromObject($table); + $data = array_merge($data, $itemData); + + $versionNote = ''; + + if (\array_key_exists('version_note', $data)) { + $versionNote = $data['version_note']; + unset($data['version_note']); + } + + foreach ($this->ignoreChanges as $ignore) { + if (\array_key_exists($ignore, $data)) { + unset($data[$ignore]); + } + } + + return $this->storeHistory($context, $id, ArrayHelper::toObject($data), $versionNote); + } + + /** + * Method to delete the history for an item. + * + * @param string $typeAlias Typealias of the component + * @param integer $id ID of the content item to delete + * + * @return boolean true on success, otherwise false. + * + * @since 6.0.0 + */ + public function deleteHistory($typeAlias, $id) + { + $db = $this->getDatabase(); + $itemid = $typeAlias . '.' . $id; + $query = $db->createQuery(); + $query->delete($db->quoteName('#__history')) + ->where($db->quoteName('item_id') . ' = :item_id') + ->bind(':item_id', $itemid, ParameterType::STRING); + $db->setQuery($query); + + return $db->execute(); + } + + /** + * Method to save a version snapshot to the content history table. + * + * @param string $typeAlias Typealias of the content type + * @param integer $id ID of the content item + * @param mixed $data Array or object of data that can be + * en- and decoded into JSON + * @param string $note Note for the version to store + * + * @return boolean True on success, otherwise false. + * + * @since 6.0.0 + * @throws \Exception + */ + protected function storeHistory(string $typeAlias, int $id, mixed $data, string $note = '') + { + $typeTable = new ContentType($this->getDatabase()); + $typeTable->load(['type_alias' => $typeAlias]); + + $historyTable = new ContentHistory($this->getDatabase()); + $historyTable->item_id = $typeAlias . '.' . $id; + + [$extension, $type] = explode('.', $typeAlias); + + // We should allow workflow items interact with the versioning + $component = Factory::getApplication()->bootComponent($extension); + + if ($component instanceof WorkflowServiceInterface && $component->isWorkflowActive($typeAlias)) { + PluginHelper::importPlugin('workflow'); + + // Pre-processing by observers + $event = AbstractEvent::create( + 'onContentVersioningPrepareTable', + [ + 'subject' => $historyTable, + 'extension' => $typeAlias, + ] + ); + + $this->getDispatcher()->dispatch('onContentVersioningPrepareTable', $event); + } + + // Fix for null ordering - set to 0 if null + if (\is_object($data)) { + if (property_exists($data, 'ordering') && $data->ordering === null) { + $data->ordering = 0; + } + } elseif (\is_array($data)) { + if (\array_key_exists('ordering', $data) && $data['ordering'] === null) { + $data['ordering'] = 0; + } + } + + $historyTable->version_data = json_encode($data); + $historyTable->version_note = $note; + + // Don't save if hash already exists and same version note + $historyTable->sha1_hash = $this->getSha1($data); + + $historyRow = $historyTable->getHashMatch(); + + if ($historyRow) { + if (!$note || ($historyRow->version_note === $note)) { + return true; + } + + // Update existing row to set version note + $historyTable->version_id = $historyRow->version_id; + } + + $result = $historyTable->store(); + + // Load history_limit config from extension. + $context = $type ?? ''; + + $maxVersionsContext = ComponentHelper::getParams($extension)->get('history_limit_' . $context, 0); + $maxVersions = ComponentHelper::getParams($extension)->get('history_limit', 0); + + if ($maxVersionsContext) { + $historyTable->deleteOldVersions($maxVersionsContext); + } elseif ($maxVersions) { + $historyTable->deleteOldVersions($maxVersions); + } + + // Mark this version as current + $this->markVersionAsCurrent($historyTable->version_id, $historyTable->item_id); + + return $result; + } + + /** + * Method to mark a version as current. When a version is marked as current, all other versions of same + * content item will be marked as not current. + * + * @param integer $versionId The version id to mark as current + * @param string $itemId The item id of the content item + * + * @return void + * + * @since 6.0.0 + */ + protected function markVersionAsCurrent(int $versionId, string $itemId): void + { + $db = $this->getDatabase(); + $query = $db->createQuery() + ->update($db->quoteName('#__history')) + ->set($db->quoteName('is_current') . ' = 0') + ->where($db->quoteName('item_id') . ' = :item_id') + ->bind(':item_id', $itemId, ParameterType::STRING); + $db->setQuery($query); + $db->execute(); + + $query->clear() + ->update($db->quoteName('#__history')) + ->set($db->quoteName('is_current') . ' = 1') + ->where($db->quoteName('version_id') . ' = :version_id') + ->bind(':version_id', $versionId, ParameterType::INTEGER); + $db->setQuery($query); + $db->execute(); + } + + /** + * Method to check if version history is enabled for a specific context. + * + * @param string $context The model context. + * + * @return boolean True if version history is enabled, false otherwise. + * + * @since 6.0.0 + */ + protected function versionHistoryEnabled(string $context): bool + { + [$extension, $type] = explode('.', $context); + + return (bool) ComponentHelper::getParams($extension)->get('save_history', 0); } } diff --git a/libraries/src/Versioning/Versioning.php b/libraries/src/Versioning/Versioning.php index 09af725e628a0..aa971665383a5 100644 --- a/libraries/src/Versioning/Versioning.php +++ b/libraries/src/Versioning/Versioning.php @@ -13,7 +13,8 @@ use Joomla\CMS\Event\AbstractEvent; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; -use Joomla\CMS\Table\Table; +use Joomla\CMS\Table\ContentHistory; +use Joomla\CMS\Table\ContentType; use Joomla\CMS\Workflow\WorkflowServiceInterface; use Joomla\Database\ParameterType; @@ -25,6 +26,9 @@ * Handle the versioning of content items * * @since 4.0.0 + * + * @deprecated 6.0.0 will be removed in 8.0 without direct replacement, + * use the new versioning concept (LINK TO DOCUMENTATION) */ class Versioning { @@ -42,7 +46,7 @@ public static function get($typeAlias, $id) { $db = Factory::getDbo(); $itemid = $typeAlias . '.' . $id; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->select($db->quoteName('h.version_note') . ',' . $db->quoteName('h.save_date') . ',' . $db->quoteName('u.name')) ->from($db->quoteName('#__history', 'h')) ->leftJoin($db->quoteName('#__users', 'u'), $db->quoteName('u.id') . ' = ' . $db->quoteName('h.editor_user_id')) @@ -68,7 +72,7 @@ public static function delete($typeAlias, $id) { $db = Factory::getDbo(); $itemid = $typeAlias . '.' . $id; - $query = $db->getQuery(true); + $query = $db->createQuery(); $query->delete($db->quoteName('#__history')) ->where($db->quoteName('item_id') . ' = :item_id') ->bind(':item_id', $itemid, ParameterType::STRING); @@ -92,10 +96,10 @@ public static function delete($typeAlias, $id) */ public static function store($typeAlias, $id, $data, $note = '') { - $typeTable = Table::getInstance('ContentType', '\\Joomla\\CMS\\Table\\'); + $typeTable = new ContentType(Factory::getDbo()); $typeTable->load(['type_alias' => $typeAlias]); - $historyTable = Table::getInstance('ContentHistory', '\\Joomla\\CMS\\Table\\'); + $historyTable = new ContentHistory(Factory::getDbo()); $historyTable->item_id = $typeAlias . '.' . $id; $aliasParts = explode('.', $typeAlias); @@ -134,6 +138,8 @@ public static function store($typeAlias, $id, $data, $note = '') } } + // Mark this as a legacy version so that it will be restored using legacy way + $historyTable->is_legacy = 1; $historyTable->version_data = json_encode($data); $historyTable->version_note = $note; diff --git a/libraries/src/WebAuthn/Server.php b/libraries/src/WebAuthn/Server.php index 195faa4be33d2..0b501d70aa367 100644 --- a/libraries/src/WebAuthn/Server.php +++ b/libraries/src/WebAuthn/Server.php @@ -18,6 +18,7 @@ use Cose\Algorithm\Signature\ECDSA; use Cose\Algorithm\Signature\EdDSA; use Cose\Algorithm\Signature\RSA; +use Lcobucci\Clock\SystemClock; use ParagonIE\ConstantTime\Base64; use ParagonIE\ConstantTime\Base64UrlSafe; use Psr\Http\Message\ServerRequestInterface; @@ -47,7 +48,6 @@ use Webauthn\PublicKeyCredentialSource; use Webauthn\PublicKeyCredentialSourceRepository; use Webauthn\PublicKeyCredentialUserEntity; -use Webauthn\TokenBinding\IgnoreTokenBindingHandler; use Webauthn\TokenBinding\TokenBindingHandler; /** @@ -101,11 +101,11 @@ final class Server /** * Token binding handler * - * @var TokenBindingHandler + * @var ?TokenBindingHandler * @since 5.0.0 - * @deprecated 6.0 Will be removed when we upgrade to WebAuthn library 5.0 or later + * @deprecated 6.0 Will be removed when we upgrade to WebAuthn library 7.0 or later */ - private TokenBindingHandler $tokenBindingHandler; + private ?TokenBindingHandler $tokenBindingHandler; /** * Authentication extension output checker @@ -140,7 +140,7 @@ final class Server * * @since 5.0.0 */ - public function __construct(PublicKeyCredentialRpEntity $relayingParty, PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, ?MetadataStatementRepository $metadataStatementRepository) + public function __construct(PublicKeyCredentialRpEntity $relayingParty, PublicKeyCredentialSourceRepository $publicKeyCredentialSourceRepository, ?MetadataStatementRepository $metadataStatementRepository = null) { $this->rpEntity = $relayingParty; @@ -160,7 +160,6 @@ public function __construct(PublicKeyCredentialRpEntity $relayingParty, PublicKe $this->selectedAlgorithms = ['RS256', 'RS512', 'PS256', 'PS512', 'ES256', 'ES512', 'Ed25519']; $this->publicKeyCredentialSourceRepository = $publicKeyCredentialSourceRepository; - $this->tokenBindingHandler = new IgnoreTokenBindingHandler(); $this->extensionOutputCheckerHandler = new ExtensionOutputCheckerHandler(); $this->metadataStatementRepository = $metadataStatementRepository; } @@ -281,7 +280,7 @@ public function generatePublicKeyCredentialRequestOptions(?string $userVerificat * * @param string $data The data received from the browser * @param PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions The PK creation options used to request attestation. - * @param ServerRequestInterface $serverRequest Abstraction of the request data + * @param ServerRequestInterface|string $serverRequest Abstraction of the request data * * @return PublicKeyCredentialSource * @since 5.0.0 @@ -289,7 +288,7 @@ public function generatePublicKeyCredentialRequestOptions(?string $userVerificat * @throws \JsonException * @throws \Throwable */ - public function loadAndCheckAttestationResponse(string $data, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface $serverRequest): PublicKeyCredentialSource + public function loadAndCheckAttestationResponse(string $data, PublicKeyCredentialCreationOptions $publicKeyCredentialCreationOptions, ServerRequestInterface|string $serverRequest): PublicKeyCredentialSource { // Remove padding from the response data $temp = json_decode($data); @@ -312,7 +311,7 @@ public function loadAndCheckAttestationResponse(string $data, PublicKeyCredentia $authenticatorAttestationResponseValidator = new AuthenticatorAttestationResponseValidator( $attestationStatementSupportManager, $this->publicKeyCredentialSourceRepository, - $this->tokenBindingHandler, + null, $this->extensionOutputCheckerHandler ); @@ -327,7 +326,6 @@ public function loadAndCheckAttestationResponse(string $data, PublicKeyCredentia if (!empty($this->metadataStatementRepository)) { $refObj = new \ReflectionObject($authenticatorAttestationResponseValidator); $refProp = $refObj->getProperty('metadataStatementRepository'); - $refProp->setAccessible(true); $refProp->setValue($authenticatorAttestationResponseValidator, $this->metadataStatementRepository); } @@ -341,7 +339,7 @@ public function loadAndCheckAttestationResponse(string $data, PublicKeyCredentia * @param string $data The data received from the browser * @param PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions THE PK request options used during authentication * @param PublicKeyCredentialUserEntity|null $userEntity The user we are checking against - * @param ServerRequestInterface $serverRequest Abstraction of the request data + * @param ServerRequestInterface|string $serverRequest Abstraction of the request data * * @return PublicKeyCredentialSource * @since 5.0.0 @@ -349,7 +347,7 @@ public function loadAndCheckAttestationResponse(string $data, PublicKeyCredentia * @throws \JsonException * @throws \Throwable */ - public function loadAndCheckAssertionResponse(string $data, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ?PublicKeyCredentialUserEntity $userEntity, ServerRequestInterface $serverRequest): PublicKeyCredentialSource + public function loadAndCheckAssertionResponse(string $data, PublicKeyCredentialRequestOptions $publicKeyCredentialRequestOptions, ?PublicKeyCredentialUserEntity $userEntity, ServerRequestInterface|string $serverRequest): PublicKeyCredentialSource { /** * The library expects $data to be a JSON-encoded array with a 'response' key which is an array of Base64Url- @@ -418,7 +416,7 @@ private function getAttestationStatementSupportManager(): AttestationStatementSu $attestationStatementSupportManager->add(new FidoU2FAttestationStatementSupport()); $attestationStatementSupportManager->add(new AppleAttestationStatementSupport()); $attestationStatementSupportManager->add(new AndroidKeyAttestationStatementSupport()); - $attestationStatementSupportManager->add(new TPMAttestationStatementSupport()); + $attestationStatementSupportManager->add(new TPMAttestationStatementSupport(new SystemClock(new \DateTimeZone('UTC')))); $attestationStatementSupportManager->add(new PackedAttestationStatementSupport($coseAlgorithmManager)); return $attestationStatementSupportManager; diff --git a/libraries/src/Workflow/Workflow.php b/libraries/src/Workflow/Workflow.php index 6eb7d8e73475f..809f2c51aaaf5 100644 --- a/libraries/src/Workflow/Workflow.php +++ b/libraries/src/Workflow/Workflow.php @@ -9,7 +9,7 @@ namespace Joomla\CMS\Workflow; -use Joomla\CMS\Application\CMSApplication; +use Joomla\CMS\Application\CMSApplicationInterface; use Joomla\CMS\Event\AbstractEvent; use Joomla\CMS\Event\Workflow\WorkflowTransitionEvent; use Joomla\CMS\Extension\ComponentInterface; @@ -18,6 +18,7 @@ use Joomla\CMS\Table\Category; use Joomla\Database\DatabaseDriver; use Joomla\Database\ParameterType; +use Joomla\Event\DispatcherAwareInterface; use Joomla\Registry\Registry; use Joomla\Utilities\ArrayHelper; @@ -50,7 +51,7 @@ class Workflow /** * Application Object * - * @var CMSApplication + * @var CMSApplicationInterface * @since 4.0.0 */ protected $app; @@ -98,26 +99,30 @@ class Workflow /** * Class constructor * - * @param string $extension The extension name - * @param ?CMSApplication $app Application Object - * @param ?DatabaseDriver $db Database Driver Object + * @param string $extension The extension name + * @param ?CMSApplicationInterface $app Application Object + * @param ?DatabaseDriver $db Database Driver Object * * @since 4.0.0 */ - public function __construct(string $extension, ?CMSApplication $app = null, ?DatabaseDriver $db = null) + public function __construct(string $extension, ?CMSApplicationInterface $app = null, ?DatabaseDriver $db = null) { $this->extension = $extension; // Initialise default objects if none have been provided if ($app === null) { - @trigger_error('From 6.0 declaring the app dependency will be mandatory.', E_USER_DEPRECATED); + @trigger_error('From 7.0 declaring the app dependency will be mandatory.', E_USER_DEPRECATED); $app = Factory::getApplication(); } + if (!is_a($app, DispatcherAwareInterface::class)) { + trigger_error('The given application object is not Dispatcher aware, which is mandatory.', E_ERROR); + } + $this->app = $app; if ($db === null) { - @trigger_error('From 6.0 declaring the database dependency will be mandatory.', E_USER_DEPRECATED); + @trigger_error('From 7.0 declaring the database dependency will be mandatory.', E_USER_DEPRECATED); $db = Factory::getContainer()->get(DatabaseDriver::class); } @@ -199,7 +204,7 @@ public function getDefaultStageByCategory($catId = 0) // Check if the workflow exists if ($workflow_id = (int) $workflow_id) { - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $query->select( [ @@ -233,7 +238,7 @@ public function getDefaultStageByCategory($catId = 0) } // Use default workflow - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $query->select( [ @@ -285,7 +290,7 @@ public function getValidTransition(array $pks, int $transitionId) return null; } - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $user = $this->app->getIdentity(); @@ -382,7 +387,7 @@ public function executeTransition(array $pks, int $transitionId): bool AbstractEvent::create( 'onWorkflowBeforeTransition', [ - 'eventClass' => 'Joomla\CMS\Event\Workflow\WorkflowTransitionEvent', + 'eventClass' => WorkflowTransitionEvent::class, 'subject' => $this, 'extension' => $this->extension, 'pks' => $pks, @@ -430,7 +435,7 @@ public function executeTransition(array $pks, int $transitionId): bool public function createAssociation(int $pk, int $state): bool { try { - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $query->insert($this->db->quoteName('#__workflow_associations')) ->columns( @@ -468,7 +473,7 @@ public function updateAssociations(array $pks, int $state): bool $pks = ArrayHelper::toInteger($pks); try { - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $query->update($this->db->quoteName('#__workflow_associations')) ->set($this->db->quoteName('stage_id') . ' = :state') @@ -499,7 +504,7 @@ public function deleteAssociation(array $pks): bool $pks = ArrayHelper::toInteger($pks); try { - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $query ->delete($this->db->quoteName('#__workflow_associations')) @@ -526,7 +531,7 @@ public function deleteAssociation(array $pks): bool */ public function getAssociation(int $itemId): ?\stdClass { - $query = $this->db->getQuery(true); + $query = $this->db->createQuery(); $query->select( [ diff --git a/libraries/src/Workflow/WorkflowServiceTrait.php b/libraries/src/Workflow/WorkflowServiceTrait.php index a8e3a662d45b5..a50a0fc2487c8 100644 --- a/libraries/src/Workflow/WorkflowServiceTrait.php +++ b/libraries/src/Workflow/WorkflowServiceTrait.php @@ -11,6 +11,7 @@ use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Event\AbstractEvent; +use Joomla\CMS\Event\Workflow\WorkflowFunctionalityUsedEvent; use Joomla\CMS\Factory; use Joomla\CMS\MVC\Factory\MVCFactoryInterface; use Joomla\CMS\MVC\Model\WorkflowModelInterface; @@ -99,7 +100,7 @@ public function isFunctionalityUsed($functionality, $extension): bool AbstractEvent::create( 'onWorkflowFunctionalityUsed', [ - 'eventClass' => 'Joomla\CMS\Event\Workflow\WorkflowFunctionalityUsedEvent', + 'eventClass' => WorkflowFunctionalityUsedEvent::class, 'subject' => $this, 'extension' => $extension, 'functionality' => $functionality, diff --git a/media_source/README.md b/media_source/README.md new file mode 100644 index 0000000000000..5014feb090de0 --- /dev/null +++ b/media_source/README.md @@ -0,0 +1,127 @@ +# CMS Media source + +The folder contains source files of CMS client-side resources (Stylesheets, JavaScripts, Images and other assets) needed for extensions to work. +Each folder is for a specific extension with a few exceptions like `vendor`, `system`. + +## Building assets + +Before using the assets they must first be built/compiled and placed under `media/` folder. + +Following command helps to build, they will call builder associated with each asset: +- `npm run build -- -a` Build all assets. Will go through all resources and will build each asset. +- `npm run build -- -n ,` Build only specific asset. + +Additionally, each builder may provide their own task, that can be executed separately without running the whole rebuild. +In default configuration the builder uses following tasks: +- `clear` remove all associated files from `media/`. +- `copy` copy static files to `media/` +- `css` process Stylesheets files. Copy or compile to CSS when needed (example for SCSS etc.). +- `js` process JavaScript files. Copy or compile to JS when needed (example for `.es6.js` and `.vue` etc.). +- `gzip` prepare compressed version of css,js files. + +To execute specific task use `-t` argument: +- `npm run build -- -a -t ,` Will apply specified task to all asset builders. +- `npm run build -- -n , -t ,` Will apply specified task to specified asset builders. + +Use watchers while developing an extension allows to automatically refresh the assets while editing. +- `npm run watch -- -n ` Will start watching files changes for specific asset. + +## Adding new assets + +To add new resource follow next steps: +- Create folder under `media_source/` with name of future asset. Example for `com_example` it will be `media_source/com_example/`. +- Add Stylesheets, JavaScript and other needed files for the asset. +- Add the resource name in to `build/build-modules-js/builders-registry.mjs` into the list of `builders` so CLI know it exists. +- (Optionally) When need extra processing add custom builder into the root of the newly created folder `media_source/com_example/builder.mjs`. +- Source files of complex Application (for example Vue based script) place under `src/` like `media_source/com_example/src/` and use custom builder to build the Application. + +Done. And do not forget to run build. + +### Note about JavaScript and Stylesheets + +#### Javascript + +- Modern JavaScript files must have an extension `.es6.js`. + This allows ESLint to check the code style, Joomla is using the Airbnb preset https://github.com/airbnb/javascript. + It also instructs Rollup to do the transforms for ES2017. This step creates both normal and minified files. + Production code WILL NOT have the `.es6` part for ES2017+ files. + +- Legacy JavaScript files must have an extension `.es5.js`. + This instructs ESLint to skip checking this file. + Also, it instructs the tools to create a minified version (production code WILL NOT have the `.es5` part) + + +#### SCSS +- SCSS files starting with `_` will not become entry points for SCSS. + SCSS files will be transformed to CSS, both normal and minified versions. + +### Custom builder + +By default, each resource uses `DefaultModuleBuilder` class to build its asset. +However, each resource may have own `builder.mjs` script with custom logic. +To use custom builder add `builder.mjs` with custom logic in to the root of the resources' folder. + +#### Anatomy of custom builder + +Each builder receives the base path (path to `media_source/`) and target path (path to `media/`) as input, also cmd options. +The builder should provide list of tasks which it is able to run and expose public methods for each task to do so. + +**ATTENTION**: While coding the custom builder avoid writing in to folders outside the current asset scope. This could lead to unexpected collisions. + +Example builder: + +```javascript +export default class ExampleModuleBuilder +{ + tasksBuild = ['clear', 'copy', 'css', 'js']; + tasksExtras = ['gzip']; + + constructor(name = '', basePath = '', targetPath = '', options = {}) { + if (!name) { + throw new Error(`Argument "name" is required for ModuleBuilder.`); + } + + if (!basePath || !targetPath) { + throw new Error(`Arguments "basePath" and "targetPath" is required for "${name}" ModuleBuilder.`); + } + + this.name = name; + this.basePath = path.join(basePath, name); + this.targetPath = path.join(targetPath, name); + this.options = options; + } + + getAllTasks() { + return [ ...this.tasksBuild, ...this.tasksExtras ]; + } + + getBuildTasks() { + return this.tasksBuild; + } + + // The methods to execute each task + async clear() {} + async copy() {} + async css() {} + async js() {} + async gzip() {} +} +``` + +The list of tasks is not strict, and depending on the builder needs. +However, it is required the builder to implement `getBuildTasks()` so the main script knows which tasks need to run while running the complete build. +Method `getAllTasks()` is optional, needed only when builder have tasks that can be executed from CLI but which does not participate in the complete build. + +To simplify the coding it is possible to extend `DefaultModuleBuilder` class. + +```javascript +import DefaultModuleBuilder from '../../build/build-modules-js/builder/default-module-builder.mjs'; + +export default class ExampleModuleBuilder extends DefaultModuleBuilder { + async js() { + await super.js(); + + // Run custom code + } +} +``` diff --git a/build/media_source/cache/index.html b/media_source/cache/index.html similarity index 100% rename from build/media_source/cache/index.html rename to media_source/cache/index.html diff --git a/build/media_source/com_actionlogs/joomla.asset.json b/media_source/com_actionlogs/joomla.asset.json similarity index 100% rename from build/media_source/com_actionlogs/joomla.asset.json rename to media_source/com_actionlogs/joomla.asset.json diff --git a/build/media_source/com_actionlogs/js/admin-actionlogs-default.es6.js b/media_source/com_actionlogs/js/admin-actionlogs-default.es6.js similarity index 100% rename from build/media_source/com_actionlogs/js/admin-actionlogs-default.es6.js rename to media_source/com_actionlogs/js/admin-actionlogs-default.es6.js diff --git a/media_source/com_admin/css/admin-help.css b/media_source/com_admin/css/admin-help.css new file mode 100644 index 0000000000000..4e93135c82138 --- /dev/null +++ b/media_source/com_admin/css/admin-help.css @@ -0,0 +1,81 @@ +@charset "UTF-8"; +#help-sidebar { + min-width: 18rem; +} + +#help-index.main-nav, #help-index ul { + padding-left: 0; + background-color: var(--sidebarwrapper-bg); + inline-size: 18rem; + max-inline-size: 18rem; +} + +#help-index ul .mm-show { + background-color: var(--main-nav-ul-bg); +} + +#helpmenu .has-arrow .item-title { + margin-inline-end: auto; +} + +#helpmenu .has-arrow:after { + display: flex; +} + +.closed #helpmenu li, .closed #helpmenu a:hover { + max-inline-size: 18rem; +} + +#help-index.sidebar-wrapper .item > a { + align-items: baseline; + padding-top: 8px; + padding-bottom: 2px; +} + +#help-index.sidebar-wrapper .item-level-1 > a { + padding-inline-start: .5rem; +} + +#help-index.sidebar-wrapper .item-level-1 > a:not(.has-arrow) { + padding-inline-end: .5rem; +} + +#help-index.sidebar-wrapper .item-level-2 > a { + padding-inline-start: 1rem; +} + +#help-index.sidebar-wrapper .item-level-2 > a:not(.has-arrow) { + padding-inline-end: .5rem; +} + +#help-index.sidebar-wrapper .item-level-3 > a { + padding-inline-start: 1.5rem; +} + +#help-index.sidebar-wrapper .item-level-3 > a:not(.has-arrow) { + padding-inline-end: .5rem; +} + +#help-index a.active { + background-color: var(--sidebar-item-bg-hvr); +} + +.helpmenu .mm-collapse { + display: none; +} + +.helpmenu .mm-collapse.mm-show { + display: block; +} + +#help-index .sidebar-wrapper .item a:hover { + color: var(--sidebar-item-color-hvr); + text-decoration: none; + background-color: var(--sidebar-item-bg-hvr); +} + +#help-index h2 { + padding: .75rem 0 .25rem .75rem; + font-weight: 400; + color: var(--sidebar-item-color); +} diff --git a/build/media_source/com_admin/joomla.asset.json b/media_source/com_admin/joomla.asset.json similarity index 78% rename from build/media_source/com_admin/joomla.asset.json rename to media_source/com_admin/joomla.asset.json index 627ed01b2d73f..4ef83ee4e78d1 100644 --- a/build/media_source/com_admin/joomla.asset.json +++ b/media_source/com_admin/joomla.asset.json @@ -15,6 +15,11 @@ "attributes": { "type": "module" } + }, + { + "name": "com_admin.admin-help", + "type": "style", + "uri": "com_admin/admin-help.min.css" } ] } diff --git a/media_source/com_admin/js/admin-help.es6.js b/media_source/com_admin/js/admin-help.es6.js new file mode 100644 index 0000000000000..4113e6c288837 --- /dev/null +++ b/media_source/com_admin/js/admin-help.es6.js @@ -0,0 +1,122 @@ +/** + * @copyright (C) 2021 Open Source Matters, Inc. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +document.addEventListener('DOMContentLoaded', function (event) { + new MetisMenu('#helpmenu', { + toggle: true, + }); + const helpIndex = document.getElementById('helpmenu'); + if (helpIndex) { + helpIndex.querySelectorAll('a').forEach((element) => element.addEventListener('click', () => { + if (element.classList.contains('has-arrow')) { + // 🔸 Action for a link to a folder, where + helpIndex.querySelectorAll('a.has-arrow').forEach((a) => { + // Remove 'active' from all collapsed folders. + if (element.classList.contains('mm-collapsed')) { + element.classList.remove('active'); + } + }); + } else { + // Action for a link to an article. + const id = element.dataset.id; + if (id) { + // First, reset all other links to default state + helpIndex.querySelectorAll('a:not(has-arrow)').forEach((a) => { + if (a.dataset.id !== id) { + a.classList.remove('active'); + a.removeAttribute('aria-current'); + } else { + element.classList.add('active'); + a.setAttribute('aria-current', 'page'); + } + }); + window.scroll(0, 0); + } + localStorage.setItem('helpIndex.lastClick', id); + + // In narrow screens, close the help menu after selecting an item. + const btn = document.querySelector('button[data-bs-target="#help-index"]'); + const isVisible = !!(btn && btn.offsetParent !== null); + if (isVisible) { + document.querySelector('nav#help-index').classList.add('collapse'); + document.querySelector('nav#help-index').classList.remove('show'); + } + } + })); + } + + // Async restore function + function restoreMenu() { + let lastClick = localStorage.getItem('helpIndex.lastClick'); + if (!lastClick) { + lastClick = 'start-here'; + } + const selectedLink = helpIndex.querySelector(`a[data-id="${lastClick}"]`); + if (!selectedLink) return; + + // Collect parent list items top-down + const lists = []; + let parentLi = selectedLink.closest('li'); + while (parentLi && parentLi !== helpIndex) { + const parentUl = parentLi.parentElement; + const parentLiOfUl = parentUl.closest('li'); + if (parentLiOfUl) { + const li = parentLiOfUl; + if (li) lists.unshift(li); + } + parentLi = parentLiOfUl; + } + + // Trigger clicks in sequence + for (const li of lists) { + li.classList.add('mm-active'); + li.querySelector('ul').classList.add('mm-show'); + li.querySelector('a').classList.add('active'); + li.querySelector('a').setAttribute('aria-expanded', true); + } + + // Optional: highlight selected link + selectedLink.classList.add('active'); + selectedLink.setAttribute('aria-current', 'page'); + + // Give the submenu a moment to fully render before clicking + selectedLink.click(); + } + + // Run restore after MetisMenu setup delay + restoreMenu(); +}); + +// Define Bootstrap breakpoints (in pixels) +const breakpoints = { + sm: 576, + md: 768, + lg: 992, + xl: 1200, + xxl: 1400, +}; + +// Collapse the Help menu on small screens (sm) by causing a page reload +function getCurrentBreakpoint() { + const width = window.innerWidth; + if (width < breakpoints.md) return 'sm'; + return 'xxl'; +} + +let currentBreakpoint = getCurrentBreakpoint(); +let resizeTimeout; + +window.addEventListener('resize', () => { + clearTimeout(resizeTimeout); + + resizeTimeout = setTimeout(() => { + const newBreakpoint = getCurrentBreakpoint(); + + if (newBreakpoint !== currentBreakpoint) { + // Breakpoint changed — reload the page + location.reload(); + } + }, 300); // delay in ms after resizing stops +}); diff --git a/build/media_source/com_associations/css/sidebyside.css b/media_source/com_associations/css/sidebyside.css similarity index 100% rename from build/media_source/com_associations/css/sidebyside.css rename to media_source/com_associations/css/sidebyside.css diff --git a/build/media_source/com_associations/joomla.asset.json b/media_source/com_associations/joomla.asset.json similarity index 100% rename from build/media_source/com_associations/joomla.asset.json rename to media_source/com_associations/joomla.asset.json diff --git a/build/media_source/com_associations/js/admin-associations-default.es6.js b/media_source/com_associations/js/admin-associations-default.es6.js similarity index 100% rename from build/media_source/com_associations/js/admin-associations-default.es6.js rename to media_source/com_associations/js/admin-associations-default.es6.js diff --git a/build/media_source/com_associations/js/admin-associations-modal.es6.js b/media_source/com_associations/js/admin-associations-modal.es6.js similarity index 100% rename from build/media_source/com_associations/js/admin-associations-modal.es6.js rename to media_source/com_associations/js/admin-associations-modal.es6.js diff --git a/build/media_source/com_associations/js/associations-edit.es6.js b/media_source/com_associations/js/associations-edit.es6.js similarity index 100% rename from build/media_source/com_associations/js/associations-edit.es6.js rename to media_source/com_associations/js/associations-edit.es6.js diff --git a/build/media_source/com_associations/js/sidebyside.es6.js b/media_source/com_associations/js/sidebyside.es6.js similarity index 99% rename from build/media_source/com_associations/js/sidebyside.es6.js rename to media_source/com_associations/js/sidebyside.es6.js index 506eae310ea92..682bc148e8352 100644 --- a/build/media_source/com_associations/js/sidebyside.es6.js +++ b/media_source/com_associations/js/sidebyside.es6.js @@ -134,7 +134,11 @@ document.getElementById('target-association').addEventListener('load', ({ target // We need to check if we are not loading a blank iframe. if (target.getAttribute('src') !== '') { document.getElementById('toolbar-target').classList.remove('hidden'); - document.getElementById('toolbar-copy').classList.remove('hidden'); + + const toolbarCopy = document.getElementById('toolbar-copy'); + if (toolbarCopy) { + toolbarCopy.classList.remove('hidden'); + } document.getElementById('select-change').classList.remove('hidden'); const targetLanguage = target.getAttribute('data-language'); diff --git a/build/media_source/com_banners/joomla.asset.json b/media_source/com_banners/joomla.asset.json similarity index 100% rename from build/media_source/com_banners/joomla.asset.json rename to media_source/com_banners/joomla.asset.json diff --git a/build/media_source/com_banners/js/admin-banner-edit.es6.js b/media_source/com_banners/js/admin-banner-edit.es6.js similarity index 100% rename from build/media_source/com_banners/js/admin-banner-edit.es6.js rename to media_source/com_banners/js/admin-banner-edit.es6.js diff --git a/build/media_source/com_cache/joomla.asset.json b/media_source/com_cache/joomla.asset.json similarity index 100% rename from build/media_source/com_cache/joomla.asset.json rename to media_source/com_cache/joomla.asset.json diff --git a/build/media_source/com_cache/js/admin-cache-default.es6.js b/media_source/com_cache/js/admin-cache-default.es6.js similarity index 100% rename from build/media_source/com_cache/js/admin-cache-default.es6.js rename to media_source/com_cache/js/admin-cache-default.es6.js diff --git a/build/media_source/com_categories/css/shared-categories-accordion.css b/media_source/com_categories/css/shared-categories-accordion.css similarity index 100% rename from build/media_source/com_categories/css/shared-categories-accordion.css rename to media_source/com_categories/css/shared-categories-accordion.css diff --git a/build/media_source/com_categories/joomla.asset.json b/media_source/com_categories/joomla.asset.json similarity index 100% rename from build/media_source/com_categories/joomla.asset.json rename to media_source/com_categories/joomla.asset.json diff --git a/build/media_source/com_categories/js/shared-categories-accordion.es6.js b/media_source/com_categories/js/shared-categories-accordion.es6.js similarity index 100% rename from build/media_source/com_categories/js/shared-categories-accordion.es6.js rename to media_source/com_categories/js/shared-categories-accordion.es6.js diff --git a/build/media_source/com_config/joomla.asset.json b/media_source/com_config/joomla.asset.json similarity index 100% rename from build/media_source/com_config/joomla.asset.json rename to media_source/com_config/joomla.asset.json diff --git a/build/media_source/com_config/js/config-default.es6.js b/media_source/com_config/js/config-default.es6.js similarity index 100% rename from build/media_source/com_config/js/config-default.es6.js rename to media_source/com_config/js/config-default.es6.js diff --git a/build/media_source/com_config/js/config-filters.es6.js b/media_source/com_config/js/config-filters.es6.js similarity index 100% rename from build/media_source/com_config/js/config-filters.es6.js rename to media_source/com_config/js/config-filters.es6.js diff --git a/build/media_source/com_config/js/modules-default.es6.js b/media_source/com_config/js/modules-default.es6.js similarity index 100% rename from build/media_source/com_config/js/modules-default.es6.js rename to media_source/com_config/js/modules-default.es6.js diff --git a/build/media_source/com_config/js/templates-default.es6.js b/media_source/com_config/js/templates-default.es6.js similarity index 100% rename from build/media_source/com_config/js/templates-default.es6.js rename to media_source/com_config/js/templates-default.es6.js diff --git a/build/media_source/com_contact/joomla.asset.json b/media_source/com_contact/joomla.asset.json similarity index 100% rename from build/media_source/com_contact/joomla.asset.json rename to media_source/com_contact/joomla.asset.json diff --git a/build/media_source/com_contact/js/admin-contacts-modal.es6.js b/media_source/com_contact/js/admin-contacts-modal.es6.js similarity index 100% rename from build/media_source/com_contact/js/admin-contacts-modal.es6.js rename to media_source/com_contact/js/admin-contacts-modal.es6.js diff --git a/build/media_source/com_contact/js/contacts-list.es6.js b/media_source/com_contact/js/contacts-list.es6.js similarity index 100% rename from build/media_source/com_contact/js/contacts-list.es6.js rename to media_source/com_contact/js/contacts-list.es6.js diff --git a/build/media_source/com_content/joomla.asset.json b/media_source/com_content/joomla.asset.json similarity index 100% rename from build/media_source/com_content/joomla.asset.json rename to media_source/com_content/joomla.asset.json diff --git a/build/media_source/com_content/js/admin-article-pagebreak.es6.js b/media_source/com_content/js/admin-article-pagebreak.es6.js similarity index 100% rename from build/media_source/com_content/js/admin-article-pagebreak.es6.js rename to media_source/com_content/js/admin-article-pagebreak.es6.js diff --git a/build/media_source/com_content/js/admin-article-readmore.es6.js b/media_source/com_content/js/admin-article-readmore.es6.js similarity index 100% rename from build/media_source/com_content/js/admin-article-readmore.es6.js rename to media_source/com_content/js/admin-article-readmore.es6.js diff --git a/build/media_source/com_content/js/admin-articles-default-batch-footer.es6.js b/media_source/com_content/js/admin-articles-default-batch-footer.es6.js similarity index 100% rename from build/media_source/com_content/js/admin-articles-default-batch-footer.es6.js rename to media_source/com_content/js/admin-articles-default-batch-footer.es6.js diff --git a/build/media_source/com_content/js/admin-articles-default-stage-footer.es6.js b/media_source/com_content/js/admin-articles-default-stage-footer.es6.js similarity index 100% rename from build/media_source/com_content/js/admin-articles-default-stage-footer.es6.js rename to media_source/com_content/js/admin-articles-default-stage-footer.es6.js diff --git a/build/media_source/com_content/js/admin-articles-modal.es6.js b/media_source/com_content/js/admin-articles-modal.es6.js similarity index 100% rename from build/media_source/com_content/js/admin-articles-modal.es6.js rename to media_source/com_content/js/admin-articles-modal.es6.js diff --git a/build/media_source/com_content/js/articles-list.es6.js b/media_source/com_content/js/articles-list.es6.js similarity index 100% rename from build/media_source/com_content/js/articles-list.es6.js rename to media_source/com_content/js/articles-list.es6.js diff --git a/build/media_source/com_content/js/articles-status.es6.js b/media_source/com_content/js/articles-status.es6.js similarity index 100% rename from build/media_source/com_content/js/articles-status.es6.js rename to media_source/com_content/js/articles-status.es6.js diff --git a/build/media_source/com_content/js/form-edit.es6.js b/media_source/com_content/js/form-edit.es6.js similarity index 100% rename from build/media_source/com_content/js/form-edit.es6.js rename to media_source/com_content/js/form-edit.es6.js diff --git a/build/media_source/com_contenthistory/joomla.asset.json b/media_source/com_contenthistory/joomla.asset.json similarity index 100% rename from build/media_source/com_contenthistory/joomla.asset.json rename to media_source/com_contenthistory/joomla.asset.json diff --git a/build/media_source/com_contenthistory/js/admin-compare-compare.es6.js b/media_source/com_contenthistory/js/admin-compare-compare.es6.js similarity index 100% rename from build/media_source/com_contenthistory/js/admin-compare-compare.es6.js rename to media_source/com_contenthistory/js/admin-compare-compare.es6.js diff --git a/build/media_source/com_contenthistory/js/admin-history-modal.es6.js b/media_source/com_contenthistory/js/admin-history-modal.es6.js similarity index 100% rename from build/media_source/com_contenthistory/js/admin-history-modal.es6.js rename to media_source/com_contenthistory/js/admin-history-modal.es6.js diff --git a/build/media_source/com_cpanel/joomla.asset.json b/media_source/com_cpanel/joomla.asset.json similarity index 100% rename from build/media_source/com_cpanel/joomla.asset.json rename to media_source/com_cpanel/joomla.asset.json diff --git a/build/media_source/com_cpanel/js/admin-cpanel-default.es6.js b/media_source/com_cpanel/js/admin-cpanel-default.es6.js similarity index 100% rename from build/media_source/com_cpanel/js/admin-cpanel-default.es6.js rename to media_source/com_cpanel/js/admin-cpanel-default.es6.js diff --git a/build/media_source/com_cpanel/js/admin-system-loader.es6.js b/media_source/com_cpanel/js/admin-system-loader.es6.js similarity index 100% rename from build/media_source/com_cpanel/js/admin-system-loader.es6.js rename to media_source/com_cpanel/js/admin-system-loader.es6.js diff --git a/build/media_source/com_fields/joomla.asset.json b/media_source/com_fields/joomla.asset.json similarity index 100% rename from build/media_source/com_fields/joomla.asset.json rename to media_source/com_fields/joomla.asset.json diff --git a/build/media_source/com_fields/js/admin-field-changecontext.es6.js b/media_source/com_fields/js/admin-field-changecontext.es6.js similarity index 100% rename from build/media_source/com_fields/js/admin-field-changecontext.es6.js rename to media_source/com_fields/js/admin-field-changecontext.es6.js diff --git a/build/media_source/com_fields/js/admin-field-edit.es6.js b/media_source/com_fields/js/admin-field-edit.es6.js similarity index 100% rename from build/media_source/com_fields/js/admin-field-edit.es6.js rename to media_source/com_fields/js/admin-field-edit.es6.js diff --git a/build/media_source/com_fields/js/admin-field-typehaschanged.es6.js b/media_source/com_fields/js/admin-field-typehaschanged.es6.js similarity index 100% rename from build/media_source/com_fields/js/admin-field-typehaschanged.es6.js rename to media_source/com_fields/js/admin-field-typehaschanged.es6.js diff --git a/build/media_source/com_fields/js/admin-fields-default-batch.es6.js b/media_source/com_fields/js/admin-fields-default-batch.es6.js similarity index 100% rename from build/media_source/com_fields/js/admin-fields-default-batch.es6.js rename to media_source/com_fields/js/admin-fields-default-batch.es6.js diff --git a/build/media_source/com_fields/js/admin-fields-modal.es6.js b/media_source/com_fields/js/admin-fields-modal.es6.js similarity index 100% rename from build/media_source/com_fields/js/admin-fields-modal.es6.js rename to media_source/com_fields/js/admin-fields-modal.es6.js diff --git a/build/media_source/com_finder/css/dates.css b/media_source/com_finder/css/dates.css similarity index 100% rename from build/media_source/com_finder/css/dates.css rename to media_source/com_finder/css/dates.css diff --git a/build/media_source/com_finder/css/finder.css b/media_source/com_finder/css/finder.css similarity index 100% rename from build/media_source/com_finder/css/finder.css rename to media_source/com_finder/css/finder.css diff --git a/build/media_source/com_finder/css/indexer.css b/media_source/com_finder/css/indexer.css similarity index 100% rename from build/media_source/com_finder/css/indexer.css rename to media_source/com_finder/css/indexer.css diff --git a/build/media_source/com_finder/joomla.asset.json b/media_source/com_finder/joomla.asset.json similarity index 100% rename from build/media_source/com_finder/joomla.asset.json rename to media_source/com_finder/joomla.asset.json diff --git a/build/media_source/com_finder/js/debug.es6.js b/media_source/com_finder/js/debug.es6.js similarity index 100% rename from build/media_source/com_finder/js/debug.es6.js rename to media_source/com_finder/js/debug.es6.js diff --git a/build/media_source/com_finder/js/filters.es6.js b/media_source/com_finder/js/filters.es6.js similarity index 100% rename from build/media_source/com_finder/js/filters.es6.js rename to media_source/com_finder/js/filters.es6.js diff --git a/build/media_source/com_finder/js/finder-edit.es6.js b/media_source/com_finder/js/finder-edit.es6.js similarity index 100% rename from build/media_source/com_finder/js/finder-edit.es6.js rename to media_source/com_finder/js/finder-edit.es6.js diff --git a/build/media_source/com_finder/js/finder.es6.js b/media_source/com_finder/js/finder.es6.js similarity index 100% rename from build/media_source/com_finder/js/finder.es6.js rename to media_source/com_finder/js/finder.es6.js diff --git a/build/media_source/com_finder/js/indexer.es6.js b/media_source/com_finder/js/indexer.es6.js similarity index 100% rename from build/media_source/com_finder/js/indexer.es6.js rename to media_source/com_finder/js/indexer.es6.js diff --git a/build/media_source/com_finder/js/maps.es6.js b/media_source/com_finder/js/maps.es6.js similarity index 100% rename from build/media_source/com_finder/js/maps.es6.js rename to media_source/com_finder/js/maps.es6.js diff --git a/media_source/com_guidedtours/images/6_0/cassiopeiacolors.jpg b/media_source/com_guidedtours/images/6_0/cassiopeiacolors.jpg new file mode 100644 index 0000000000000..ddb7a775e9854 Binary files /dev/null and b/media_source/com_guidedtours/images/6_0/cassiopeiacolors.jpg differ diff --git a/media_source/com_guidedtours/images/6_1/captcha.jpg b/media_source/com_guidedtours/images/6_1/captcha.jpg new file mode 100644 index 0000000000000..a2c66ee99671c Binary files /dev/null and b/media_source/com_guidedtours/images/6_1/captcha.jpg differ diff --git a/media_source/com_guidedtours/images/6_1/media.jpg b/media_source/com_guidedtours/images/6_1/media.jpg new file mode 100644 index 0000000000000..f9c1fc5e80dfa Binary files /dev/null and b/media_source/com_guidedtours/images/6_1/media.jpg differ diff --git a/media_source/com_guidedtours/images/6_1/workflows.jpg b/media_source/com_guidedtours/images/6_1/workflows.jpg new file mode 100644 index 0000000000000..1a06462539355 Binary files /dev/null and b/media_source/com_guidedtours/images/6_1/workflows.jpg differ diff --git a/build/media_source/com_guidedtours/joomla.asset.json b/media_source/com_guidedtours/joomla.asset.json similarity index 100% rename from build/media_source/com_guidedtours/joomla.asset.json rename to media_source/com_guidedtours/joomla.asset.json diff --git a/build/media_source/com_guidedtours/js/tour-edit.es6.js b/media_source/com_guidedtours/js/tour-edit.es6.js similarity index 100% rename from build/media_source/com_guidedtours/js/tour-edit.es6.js rename to media_source/com_guidedtours/js/tour-edit.es6.js diff --git a/build/media_source/com_installer/css/installer.css b/media_source/com_installer/css/installer.css similarity index 100% rename from build/media_source/com_installer/css/installer.css rename to media_source/com_installer/css/installer.css diff --git a/build/media_source/com_installer/joomla.asset.json b/media_source/com_installer/joomla.asset.json similarity index 100% rename from build/media_source/com_installer/joomla.asset.json rename to media_source/com_installer/joomla.asset.json diff --git a/build/media_source/com_installer/js/changelog.es6.js b/media_source/com_installer/js/changelog.es6.js similarity index 100% rename from build/media_source/com_installer/js/changelog.es6.js rename to media_source/com_installer/js/changelog.es6.js diff --git a/build/media_source/com_installer/js/installer.es6.js b/media_source/com_installer/js/installer.es6.js similarity index 100% rename from build/media_source/com_installer/js/installer.es6.js rename to media_source/com_installer/js/installer.es6.js diff --git a/build/media_source/com_joomlaupdate/joomla.asset.json b/media_source/com_joomlaupdate/joomla.asset.json similarity index 100% rename from build/media_source/com_joomlaupdate/joomla.asset.json rename to media_source/com_joomlaupdate/joomla.asset.json diff --git a/build/media_source/com_joomlaupdate/js/admin-update-default.es6.js b/media_source/com_joomlaupdate/js/admin-update-default.es6.js similarity index 100% rename from build/media_source/com_joomlaupdate/js/admin-update-default.es6.js rename to media_source/com_joomlaupdate/js/admin-update-default.es6.js diff --git a/build/media_source/com_joomlaupdate/js/default.es6.js b/media_source/com_joomlaupdate/js/default.es6.js similarity index 100% rename from build/media_source/com_joomlaupdate/js/default.es6.js rename to media_source/com_joomlaupdate/js/default.es6.js diff --git a/build/media_source/com_languages/css/overrider.css b/media_source/com_languages/css/overrider.css similarity index 100% rename from build/media_source/com_languages/css/overrider.css rename to media_source/com_languages/css/overrider.css diff --git a/build/media_source/com_languages/joomla.asset.json b/media_source/com_languages/joomla.asset.json similarity index 100% rename from build/media_source/com_languages/joomla.asset.json rename to media_source/com_languages/joomla.asset.json diff --git a/build/media_source/com_languages/js/admin-language-edit-change-flag.es6.js b/media_source/com_languages/js/admin-language-edit-change-flag.es6.js similarity index 100% rename from build/media_source/com_languages/js/admin-language-edit-change-flag.es6.js rename to media_source/com_languages/js/admin-language-edit-change-flag.es6.js diff --git a/build/media_source/com_languages/js/admin-override-edit-refresh-searchstring.es6.js b/media_source/com_languages/js/admin-override-edit-refresh-searchstring.es6.js similarity index 100% rename from build/media_source/com_languages/js/admin-override-edit-refresh-searchstring.es6.js rename to media_source/com_languages/js/admin-override-edit-refresh-searchstring.es6.js diff --git a/build/media_source/com_languages/js/overrider.es6.js b/media_source/com_languages/js/overrider.es6.js similarity index 100% rename from build/media_source/com_languages/js/overrider.es6.js rename to media_source/com_languages/js/overrider.es6.js diff --git a/build/media_source/com_mails/joomla.asset.json b/media_source/com_mails/joomla.asset.json similarity index 100% rename from build/media_source/com_mails/joomla.asset.json rename to media_source/com_mails/joomla.asset.json diff --git a/build/media_source/com_mails/js/admin-email-template-edit.es6.js b/media_source/com_mails/js/admin-email-template-edit.es6.js similarity index 100% rename from build/media_source/com_mails/js/admin-email-template-edit.es6.js rename to media_source/com_mails/js/admin-email-template-edit.es6.js diff --git a/media_source/com_media/builder.mjs b/media_source/com_media/builder.mjs new file mode 100644 index 0000000000000..216edbdbd6903 --- /dev/null +++ b/media_source/com_media/builder.mjs @@ -0,0 +1,97 @@ +/** + * Assets Builder + */ +import path from 'node:path'; +import fsp from 'node:fs/promises'; +import { rollup } from 'rollup'; +import VuePlugin from 'rollup-plugin-vue'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import replace from '@rollup/plugin-replace'; +import { babel } from '@rollup/plugin-babel'; +import DefaultModuleBuilder from '../../build/build-modules-js/builder/default-module-builder.mjs'; +import { minifyJSContent } from '../../build/build-modules-js/javascript/js-handle.mjs'; + +export const buildMediaManager = async (basePath, targetPath) => { + const srcFile = path.join(basePath, 'src', 'mediamanager.es6.js'); + const targetFile = path.join(targetPath, 'js', 'media-manager.js'); + const targetFileMin = path.join(targetPath, 'js', 'media-manager.min.js'); + const isProduction = process.env.NODE_ENV !== 'DEVELOPMENT'; + + return rollup({ + input: srcFile, + plugins: [ + VuePlugin({ + target: 'browser', + css: false, + compileTemplate: true, + template: { + isProduction, + }, + }), + nodeResolve(), + commonjs(), + replace({ + 'process.env.NODE_ENV': JSON.stringify((process.env.NODE_ENV && process.env.NODE_ENV.toLocaleLowerCase()) || 'production'), + __VUE_OPTIONS_API__: true, + __VUE_PROD_DEVTOOLS__: !isProduction, + preventAssignment: true, + }), + babel({ + exclude: 'node_modules/core-js/**', + babelHelpers: 'bundled', + babelrc: false, + presets: [ + [ + '@babel/preset-env', + { + targets: { + browsers: [ + '> 1%', + 'not op_mini all', + /** https://caniuse.com/es6-module */ + 'chrome >= 61', + 'safari >= 11', + 'edge >= 16', + 'Firefox >= 60', + ], + }, + loose: true, + bugfixes: false, + ignoreBrowserslistConfig: true, + }, + ], + ], + }), + ], + }).then((build) => { + return build.write({ + format: 'es', + sourcemap: !isProduction ? 'inline' : false, + file: targetFile, + }) + .then((value) => (isProduction ? minifyJSContent(value.output[0].code) : value.output[0])) + .then((content) => { + if (isProduction) { + return fsp.writeFile(targetFileMin, content, { encoding: 'utf8', mode: 0o644 }); + } + + // Copy media-manager.js => media-manager.min.js + return fsp.copyFile(targetFile, targetFileMin); + }).then(() => { + return build.close(); + }); + }); +}; + +export default class MediaModuleBuilder extends DefaultModuleBuilder { + /** + * Process JavaScript files and Modules + * @returns { Promise } + */ + async js() { + await super.js(); + + return buildMediaManager(this.basePath, this.targetPath); + } +}; diff --git a/build/media_source/com_media/joomla.asset.json b/media_source/com_media/joomla.asset.json similarity index 100% rename from build/media_source/com_media/joomla.asset.json rename to media_source/com_media/joomla.asset.json diff --git a/build/media_source/com_media/js/edit-images.es6.js b/media_source/com_media/js/edit-images.es6.js similarity index 100% rename from build/media_source/com_media/js/edit-images.es6.js rename to media_source/com_media/js/edit-images.es6.js diff --git a/build/media_source/com_media/scss/_variables.scss b/media_source/com_media/scss/_variables.scss similarity index 100% rename from build/media_source/com_media/scss/_variables.scss rename to media_source/com_media/scss/_variables.scss diff --git a/build/media_source/com_media/scss/components/_animations.scss b/media_source/com_media/scss/components/_animations.scss similarity index 100% rename from build/media_source/com_media/scss/components/_animations.scss rename to media_source/com_media/scss/components/_animations.scss diff --git a/build/media_source/com_media/scss/components/_layout.scss b/media_source/com_media/scss/components/_layout.scss similarity index 100% rename from build/media_source/com_media/scss/components/_layout.scss rename to media_source/com_media/scss/components/_layout.scss diff --git a/build/media_source/com_media/scss/components/_media-breadcrumb.scss b/media_source/com_media/scss/components/_media-breadcrumb.scss similarity index 100% rename from build/media_source/com_media/scss/components/_media-breadcrumb.scss rename to media_source/com_media/scss/components/_media-breadcrumb.scss diff --git a/build/media_source/com_media/scss/components/_media-browser.scss b/media_source/com_media/scss/components/_media-browser.scss similarity index 99% rename from build/media_source/com_media/scss/components/_media-browser.scss rename to media_source/com_media/scss/components/_media-browser.scss index f797126c4398e..f191bf0613317 100644 --- a/build/media_source/com_media/scss/components/_media-browser.scss +++ b/media_source/com_media/scss/components/_media-browser.scss @@ -254,6 +254,10 @@ background-color: hsl(var(--hue), 20%, 97%); border: 1px solid hsl(var(--hue), 35%, 95%); border-radius: $grid-item-border-radius; + + &.with-thumbnail { + padding-bottom: 0; + } } .file-icon, .folder-icon { diff --git a/build/media_source/com_media/scss/components/_media-edit.scss b/media_source/com_media/scss/components/_media-edit.scss similarity index 100% rename from build/media_source/com_media/scss/components/_media-edit.scss rename to media_source/com_media/scss/components/_media-edit.scss diff --git a/build/media_source/com_media/scss/components/_media-infobar.scss b/media_source/com_media/scss/components/_media-infobar.scss similarity index 100% rename from build/media_source/com_media/scss/components/_media-infobar.scss rename to media_source/com_media/scss/components/_media-infobar.scss diff --git a/build/media_source/com_media/scss/components/_media-modal.scss b/media_source/com_media/scss/components/_media-modal.scss similarity index 100% rename from build/media_source/com_media/scss/components/_media-modal.scss rename to media_source/com_media/scss/components/_media-modal.scss diff --git a/build/media_source/com_media/scss/components/_media-toolbar.scss b/media_source/com_media/scss/components/_media-toolbar.scss similarity index 100% rename from build/media_source/com_media/scss/components/_media-toolbar.scss rename to media_source/com_media/scss/components/_media-toolbar.scss diff --git a/build/media_source/com_media/scss/components/_media-tree.scss b/media_source/com_media/scss/components/_media-tree.scss similarity index 100% rename from build/media_source/com_media/scss/components/_media-tree.scss rename to media_source/com_media/scss/components/_media-tree.scss diff --git a/build/media_source/com_media/scss/media-manager.scss b/media_source/com_media/scss/media-manager.scss similarity index 100% rename from build/media_source/com_media/scss/media-manager.scss rename to media_source/com_media/scss/media-manager.scss diff --git a/administrator/components/com_media/resources/scripts/app/Api.es6.js b/media_source/com_media/src/app/Api.es6.js similarity index 100% rename from administrator/components/com_media/resources/scripts/app/Api.es6.js rename to media_source/com_media/src/app/Api.es6.js diff --git a/administrator/components/com_media/resources/scripts/app/Event.es6.js b/media_source/com_media/src/app/Event.es6.js similarity index 100% rename from administrator/components/com_media/resources/scripts/app/Event.es6.js rename to media_source/com_media/src/app/Event.es6.js diff --git a/administrator/components/com_media/resources/scripts/app/Notifications.es6.js b/media_source/com_media/src/app/Notifications.es6.js similarity index 100% rename from administrator/components/com_media/resources/scripts/app/Notifications.es6.js rename to media_source/com_media/src/app/Notifications.es6.js diff --git a/administrator/components/com_media/resources/scripts/app/path.js b/media_source/com_media/src/app/path.js similarity index 99% rename from administrator/components/com_media/resources/scripts/app/path.js rename to media_source/com_media/src/app/path.js index dbfc45d03f6bf..c6098ebd90d10 100644 --- a/administrator/components/com_media/resources/scripts/app/path.js +++ b/media_source/com_media/src/app/path.js @@ -24,4 +24,4 @@ export const dirname = (path) => { if (end === -1) return hasRoot ? '/' : '.'; if (hasRoot && end === 1) return '//'; return path.slice(0, end); -} +}; diff --git a/administrator/components/com_media/resources/scripts/components/app.vue b/media_source/com_media/src/components/app.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/app.vue rename to media_source/com_media/src/components/app.vue diff --git a/administrator/components/com_media/resources/scripts/components/breadcrumb/breadcrumb.vue b/media_source/com_media/src/components/breadcrumb/breadcrumb.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/breadcrumb/breadcrumb.vue rename to media_source/com_media/src/components/breadcrumb/breadcrumb.vue diff --git a/administrator/components/com_media/resources/scripts/components/browser/actionItems/actionItemsContainer.vue b/media_source/com_media/src/components/browser/actionItems/actionItemsContainer.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/browser/actionItems/actionItemsContainer.vue rename to media_source/com_media/src/components/browser/actionItems/actionItemsContainer.vue diff --git a/administrator/components/com_media/resources/scripts/components/browser/actionItems/delete.vue b/media_source/com_media/src/components/browser/actionItems/delete.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/browser/actionItems/delete.vue rename to media_source/com_media/src/components/browser/actionItems/delete.vue diff --git a/administrator/components/com_media/resources/scripts/components/browser/actionItems/download.vue b/media_source/com_media/src/components/browser/actionItems/download.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/browser/actionItems/download.vue rename to media_source/com_media/src/components/browser/actionItems/download.vue diff --git a/administrator/components/com_media/resources/scripts/components/browser/actionItems/edit.vue b/media_source/com_media/src/components/browser/actionItems/edit.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/browser/actionItems/edit.vue rename to media_source/com_media/src/components/browser/actionItems/edit.vue diff --git a/administrator/components/com_media/resources/scripts/components/browser/actionItems/preview.vue b/media_source/com_media/src/components/browser/actionItems/preview.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/browser/actionItems/preview.vue rename to media_source/com_media/src/components/browser/actionItems/preview.vue diff --git a/administrator/components/com_media/resources/scripts/components/browser/actionItems/rename.vue b/media_source/com_media/src/components/browser/actionItems/rename.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/browser/actionItems/rename.vue rename to media_source/com_media/src/components/browser/actionItems/rename.vue diff --git a/administrator/components/com_media/resources/scripts/components/browser/actionItems/share.vue b/media_source/com_media/src/components/browser/actionItems/share.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/browser/actionItems/share.vue rename to media_source/com_media/src/components/browser/actionItems/share.vue diff --git a/administrator/components/com_media/resources/scripts/components/browser/actionItems/toggle.vue b/media_source/com_media/src/components/browser/actionItems/toggle.vue similarity index 100% rename from administrator/components/com_media/resources/scripts/components/browser/actionItems/toggle.vue rename to media_source/com_media/src/components/browser/actionItems/toggle.vue diff --git a/administrator/components/com_media/resources/scripts/components/browser/browser.vue b/media_source/com_media/src/components/browser/browser.vue similarity index 98% rename from administrator/components/com_media/resources/scripts/components/browser/browser.vue rename to media_source/com_media/src/components/browser/browser.vue index 1db1e4086bc5e..10aebf2a68f3e 100644 --- a/administrator/components/com_media/resources/scripts/components/browser/browser.vue +++ b/media_source/com_media/src/components/browser/browser.vue @@ -200,8 +200,7 @@ export default { /* Unselect all browser items */ unselectAllBrowserItems(event) { const clickedDelete = !!((event.target.id !== undefined && event.target.id === 'mediaDelete')); - const notClickedBrowserItems = (this.$refs.browserItems - && !this.$refs.browserItems.contains(event.target)) + const notClickedBrowserItems = (this.$refs.browserItems && !this.$refs.browserItems.contains(event.target)) || event.target === this.$refs.browserItems; const notClickedInfobar = this.$refs.infobar !== undefined diff --git a/administrator/components/com_media/resources/scripts/components/browser/items/audio.vue b/media_source/com_media/src/components/browser/items/audio.vue similarity index 61% rename from administrator/components/com_media/resources/scripts/components/browser/items/audio.vue rename to media_source/com_media/src/components/browser/items/audio.vue index cb33bca7d39f4..078ebad9dd1ad 100644 --- a/administrator/components/com_media/resources/scripts/components/browser/items/audio.vue +++ b/media_source/com_media/src/components/browser/items/audio.vue @@ -7,8 +7,23 @@ @keyup.enter="openPreview()" >
-
-
+
+ +
@@ -51,6 +66,26 @@ export default { showActions: false, }; }, + computed: { + thumbURL() { + let path = this.item.thumb_path || ''; + + if (path && this.item.modified_date) { + path = path + (path.includes('?') ? '&' : '?') + this.item.modified_date; + } + + return path; + }, + thumbWidth() { + return this.item.thumb_width || null; + }, + thumbHeight() { + return this.item.thumb_height || null; + }, + thumbLoading() { + return this.item.thumb_width ? 'lazy' : null; + }, + }, methods: { /* Hide actions dropdown */ hideActions() { diff --git a/administrator/components/com_media/resources/scripts/components/browser/items/directory.vue b/media_source/com_media/src/components/browser/items/directory.vue similarity index 66% rename from administrator/components/com_media/resources/scripts/components/browser/items/directory.vue rename to media_source/com_media/src/components/browser/items/directory.vue index d665740532b7b..9a20a481f30ca 100644 --- a/administrator/components/com_media/resources/scripts/components/browser/items/directory.vue +++ b/media_source/com_media/src/components/browser/items/directory.vue @@ -9,8 +9,23 @@ @dblclick.stop.prevent="onPreviewDblClick()" @keyup.enter="onPreviewDblClick()" > -
-
+
+ +
@@ -47,6 +62,26 @@ export default { showActions: false, }; }, + computed: { + thumbURL() { + let path = this.item.thumb_path || ''; + + if (path && this.item.modified_date) { + path = path + (path.includes('?') ? '&' : '?') + this.item.modified_date; + } + + return path; + }, + thumbWidth() { + return this.item.thumb_width || null; + }, + thumbHeight() { + return this.item.thumb_height || null; + }, + thumbLoading() { + return this.item.thumb_width ? 'lazy' : null; + }, + }, methods: { /* Handle the on preview double click event */ onPreviewDblClick() { diff --git a/administrator/components/com_media/resources/scripts/components/browser/items/document.vue b/media_source/com_media/src/components/browser/items/document.vue similarity index 63% rename from administrator/components/com_media/resources/scripts/components/browser/items/document.vue rename to media_source/com_media/src/components/browser/items/document.vue index e8a259f6a6afc..183f58192a3ba 100644 --- a/administrator/components/com_media/resources/scripts/components/browser/items/document.vue +++ b/media_source/com_media/src/components/browser/items/document.vue @@ -5,8 +5,23 @@ @mouseleave="hideActions()" >
-
-
+
+ +
@@ -54,6 +69,26 @@ export default { showActions: false, }; }, + computed: { + thumbURL() { + let path = this.item.thumb_path || ''; + + if (path && this.item.modified_date) { + path = path + (path.includes('?') ? '&' : '?') + this.item.modified_date; + } + + return path; + }, + thumbWidth() { + return this.item.thumb_width || null; + }, + thumbHeight() { + return this.item.thumb_height || null; + }, + thumbLoading() { + return this.item.thumb_width ? 'lazy' : null; + }, + }, methods: { /* Hide actions dropdown */ hideActions() { diff --git a/administrator/components/com_media/resources/scripts/components/browser/items/file.vue b/media_source/com_media/src/components/browser/items/file.vue similarity index 63% rename from administrator/components/com_media/resources/scripts/components/browser/items/file.vue rename to media_source/com_media/src/components/browser/items/file.vue index 2b816f6e75ade..71a486d0157fe 100644 --- a/administrator/components/com_media/resources/scripts/components/browser/items/file.vue +++ b/media_source/com_media/src/components/browser/items/file.vue @@ -4,8 +4,23 @@ @mouseleave="hideActions()" >
-
-
+
+ +
@@ -53,6 +68,26 @@ export default { showActions: false, }; }, + computed: { + thumbURL() { + let path = this.item.thumb_path || ''; + + if (path && this.item.modified_date) { + path = path + (path.includes('?') ? '&' : '?') + this.item.modified_date; + } + + return path; + }, + thumbWidth() { + return this.item.thumb_width || null; + }, + thumbHeight() { + return this.item.thumb_height || null; + }, + thumbLoading() { + return this.item.thumb_width ? 'lazy' : null; + }, + }, methods: { /* Hide actions dropdown */ hideActions() { diff --git a/administrator/components/com_media/resources/scripts/components/browser/items/image.vue b/media_source/com_media/src/components/browser/items/image.vue similarity index 87% rename from administrator/components/com_media/resources/scripts/components/browser/items/image.vue rename to media_source/com_media/src/components/browser/items/image.vue index 242d9c8b6de48..de5d027c6f94f 100644 --- a/administrator/components/com_media/resources/scripts/components/browser/items/image.vue +++ b/media_source/com_media/src/components/browser/items/image.vue @@ -12,17 +12,17 @@ >