diff --git a/.drone.yml b/.drone.yml
index 894e5a9d3ede6..6617cee6950f8 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -53,8 +53,15 @@ steps:
- ./libraries/vendor/bin/phpcs --extensions=php -p --standard=ruleset.xml .
- echo $(date)
+ - name: phan
+ image: joomlaprojects/docker-images:php7.4-ast
+ depends_on: [ phpcs ]
+ failure: ignore
+ commands:
+ - ./libraries/vendor/bin/phan
+
- name: npm
- image: node:16-alpine
+ image: node:16-bullseye-slim
depends_on: [ phpcs ]
volumes:
- name: npm-cache
@@ -195,135 +202,117 @@ steps:
commands:
- npm run lint:js
- - name: prepare_codeception_tests
+ - name: prepare_system_tests
depends_on:
- npm
image: joomlaprojects/docker-images:systemtests
+ volumes:
+ - name: cypress-cache
+ path: /root/.cache/Cypress
commands:
- - sed -i 's/tests\\/Codeception\\/_output/\\/drone\\/src\\/tests\\/Codeception\\/_output/' codeception.yml
+ - sed -i 's/tests\\/Codeception\\/_output/\\/drone\\/src\\/tests\\/cypress\\/output/' codeception.yml
- php libraries/vendor/bin/codecept build
+ - npx cypress install
+ - npx cypress verify
- name: phpmin-api-mysql
depends_on:
- - prepare_codeception_tests
+ - prepare_system_tests
image: joomlaprojects/docker-images:systemtests
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysql
+ - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysql mysqli mysql jos_
- - name: phpmax-api-mysql
+ - name: phpmin-api-postgres
depends_on:
- - prepare_codeception_tests
- image: joomlaprojects/docker-images:systemtests8.1
+ - prepare_system_tests
+ image: joomlaprojects/docker-images:systemtests
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysqlphpmax
-
-# - name: phpnext-api-mysql
-# depends_on:
-# - phpmax-api-mysql
-# image: joomlaprojects/docker-images:systemtests8.2
-# failure: ignore
-# environment:
-# JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
-# commands:
-# - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysqlphpnext
+ - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgres pgsql postgres jos_
- - name: phpmin-api-postgres
+ - name: phpmax-api-mysql
depends_on:
- - prepare_codeception_tests
- image: joomlaprojects/docker-images:systemtests
+ - phpmin-api-mysql
+ - phpmin-api-postgres
+ image: joomlaprojects/docker-images:systemtests8.1
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgres
+ - bash tests/Codeception/drone-api-run.sh "$(pwd)" mysqlphpmax mysqli mysql phpmax_
- name: phpmax-api-postgres
depends_on:
- - prepare_codeception_tests
+ - phpmin-api-mysql
+ - phpmin-api-postgres
image: joomlaprojects/docker-images:systemtests8.1
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgresphpmax
-
-# - name: phpnext-api-postgres
-# depends_on:
-# - phpmin-api-postgres
-# image: joomlaprojects/docker-images:systemtests8.2
-# failure: ignore
-# environment:
-# JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
-# commands:
-# - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgresphpnext
+ - bash tests/Codeception/drone-api-run.sh "$(pwd)" postgresphpmax pgsql postgres phpmax_
- name: phpmin-system-mysql
depends_on:
- phpmax-api-mysql
- phpmax-api-postgres
image: joomlaprojects/docker-images:cypress
+ volumes:
+ - name: cypress-cache
+ path: /root/.cache/Cypress
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- bash tests/cypress/drone-system-run.sh "$(pwd)" cmysql mysqli mysql
- - name: phpmax-system-mysql
+ - name: phpmin-system-postgres
depends_on:
- phpmax-api-mysql
- phpmax-api-postgres
- image: joomlaprojects/docker-images:cypress8.1
+ image: joomlaprojects/docker-images:cypress
+ volumes:
+ - name: cypress-cache
+ path: /root/.cache/Cypress
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/cypress/drone-system-run.sh "$(pwd)" cmysqlmax mysqli mysql
-
-# - name: phpnext-system-mysql
-# depends_on:
-# - phpmax-system-mysql
-# image: joomlaprojects/docker-images:systemtests8.2
-# failure: ignore
-# environment:
-# JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
-# commands:
-# - bash tests/Codeception/drone-system-run.sh "$(pwd)" mysqlphpnext
+ - bash tests/cypress/drone-system-run.sh "$(pwd)" cpostgres pgsql postgres
- - name: phpmin-system-postgres
+ - name: phpmax-system-mysql
depends_on:
- - phpmax-api-mysql
- - phpmax-api-postgres
- image: joomlaprojects/docker-images:cypress
+ - phpmin-system-mysql
+ - phpmin-system-postgres
+ image: joomlaprojects/docker-images:cypress8.1
+ volumes:
+ - name: cypress-cache
+ path: /root/.cache/Cypress
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- - bash tests/cypress/drone-system-run.sh "$(pwd)" cpostgres pgsql postgres
+ - bash tests/cypress/drone-system-run.sh "$(pwd)" cmysqlmax mysqli mysql
- name: phpmax-system-postgres
depends_on:
- - phpmax-api-mysql
- - phpmax-api-postgres
+ - phpmin-system-mysql
+ - phpmin-system-postgres
image: joomlaprojects/docker-images:cypress8.1
+ volumes:
+ - name: cypress-cache
+ path: /root/.cache/Cypress
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- bash tests/cypress/drone-system-run.sh "$(pwd)" cpostgresmax pgsql postgres
-# - name: phpnext-system-postgres
-# depends_on:
-# - phpmax-system-postgres
-# image: joomlaprojects/docker-images:systemtests8.2
-# failure: ignore
-# environment:
-# JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
-# commands:
-# - bash tests/Codeception/drone-system-run.sh "$(pwd)" postgresphpnext
-
- name: phpmin-system-mysql8
depends_on:
- phpmax-system-mysql
- phpmax-system-postgres
image: joomlaprojects/docker-images:cypress
+ volumes:
+ - name: cypress-cache
+ path: /root/.cache/Cypress
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
@@ -334,35 +323,23 @@ steps:
- phpmax-system-mysql
- phpmax-system-postgres
image: joomlaprojects/docker-images:cypress8.1
+ volumes:
+ - name: cypress-cache
+ path: /root/.cache/Cypress
environment:
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
commands:
- bash tests/cypress/drone-system-run.sh "$(pwd)" cmysql8max mysqli mysql8
-# - name: phpnext-system-mysql8
-# depends_on:
-# - phpmax-system-mysql8
-# image: joomlaprojects/docker-images:systemtests8.2
-# failure: ignore
-# environment:
-# JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
-# commands:
-# - bash tests/Codeception/drone-system-run.sh "$(pwd)" mysql8phpnext
-
- name: artifacts-system-tests
image: cschlosser/drone-ftps
depends_on:
- # - phpnext-system-mysql
- # - phpnext-system-mysql8
- # - phpnext-system-postgres
- phpmax-system-mysql
- phpmax-system-mysql8
- phpmax-system-postgres
- phpmin-system-mysql
- phpmin-system-mysql8
- phpmin-system-postgres
- # - phpnext-api-mysql
- # - phpnext-api-postgres
- phpmax-api-mysql
- phpmax-api-postgres
- phpmin-api-mysql
@@ -389,6 +366,9 @@ volumes:
- name: composer-cache
host:
path: /tmp/composer-cache
+ - name: cypress-cache
+ host:
+ path: /tmp/cypress-cache
- name: npm-cache
host:
path: /tmp/npm-cache
@@ -517,6 +497,6 @@ trigger:
---
kind: signature
-hmac: c850e892dfbe03549fe506a436dcafe7880cff3c78e9a3130582abbe7c13c3f9
+hmac: 824f98a6e4e05eea6d469af34ea3c9f9a47649b4fdda22438df692e3958d60fe
...
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 32e34f654da80..4954021a38ac0 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -16,5 +16,10 @@ Pull Request for Issue # .
-### Documentation Changes Required
+### Link to documentations
+Please select:
+- [ ] Documentation link for docs.joomla.org:
+- [ ] No documentation changes for docs.joomla.org needed
+- [ ] Pull Request link for manual.joomla.org:
+- [ ] No documentation changes for manual.joomla.org needed
diff --git a/.phan/config.php b/.phan/config.php
new file mode 100644
index 0000000000000..e8873f0ff8752
--- /dev/null
+++ b/.phan/config.php
@@ -0,0 +1,357 @@
+ '7.2',
+
+ // If enabled, missing properties will be created when
+ // they are first seen. If false, we'll report an
+ // error message if there is an attempt to write
+ // to a class property that wasn't explicitly
+ // defined.
+ 'allow_missing_properties' => true,
+
+ // If enabled, null can be cast to any type and any
+ // type can be cast to null. Setting this to true
+ // will cut down on false positives.
+ 'null_casts_as_any_type' => true,
+
+ // If enabled, allow null to be cast as any array-like type.
+ //
+ // This is an incremental step in migrating away from `null_casts_as_any_type`.
+ // If `null_casts_as_any_type` is true, this has no effect.
+ 'null_casts_as_array' => true,
+
+ // If enabled, allow any array-like type to be cast to null.
+ // This is an incremental step in migrating away from `null_casts_as_any_type`.
+ // If `null_casts_as_any_type` is true, this has no effect.
+ 'array_casts_as_null' => true,
+
+ // If enabled, scalars (int, float, bool, string, null)
+ // are treated as if they can cast to each other.
+ // This does not affect checks of array keys. See `scalar_array_key_cast`.
+ 'scalar_implicit_cast' => true,
+
+ // If enabled, any scalar array keys (int, string)
+ // are treated as if they can cast to each other.
+ // E.g. `array` can cast to `array` and vice versa.
+ // Normally, a scalar type such as int could only cast to/from int and mixed.
+ 'scalar_array_key_cast' => true,
+
+ // If this has entries, scalars (int, float, bool, string, null)
+ // are allowed to perform the casts listed.
+ //
+ // E.g. `['int' => ['float', 'string'], 'float' => ['int'], 'string' => ['int'], 'null' => ['string']]`
+ // allows casting null to a string, but not vice versa.
+ // (subset of `scalar_implicit_cast`)
+ 'scalar_implicit_partial' => [],
+
+ // If enabled, Phan will warn if **any** type in a method invocation's object
+ // is definitely not an object,
+ // or if **any** type in an invoked expression is not a callable.
+ // Setting this to true will introduce numerous false positives
+ // (and reveal some bugs).
+ 'strict_method_checking' => false,
+
+ // If enabled, Phan will warn if **any** type of the object expression for a property access
+ // does not contain that property.
+ 'strict_object_checking' => false,
+
+ // If enabled, Phan will warn if **any** type in the argument's union type
+ // cannot be cast to a type in the parameter's expected union type.
+ // Setting this to true will introduce numerous false positives
+ // (and reveal some bugs).
+ 'strict_param_checking' => false,
+
+ // If enabled, Phan will warn if **any** type in a property assignment's union type
+ // cannot be cast to a type in the property's declared union type.
+ // Setting this to true will introduce numerous false positives
+ // (and reveal some bugs).
+ 'strict_property_checking' => false,
+
+ // If enabled, Phan will warn if **any** type in a returned value's union type
+ // cannot be cast to the declared return type.
+ // Setting this to true will introduce numerous false positives
+ // (and reveal some bugs).
+ 'strict_return_checking' => false,
+
+ // If true, seemingly undeclared variables in the global
+ // scope will be ignored.
+ //
+ // This is useful for projects with complicated cross-file
+ // globals that you have no hope of fixing.
+ 'ignore_undeclared_variables_in_global_scope' => true,
+
+ // Set this to false to emit `PhanUndeclaredFunction` issues for internal functions that Phan has signatures for,
+ // but aren't available in the codebase, or from Reflection.
+ // (may lead to false positives if an extension isn't loaded)
+ //
+ // If this is true(default), then Phan will not warn.
+ //
+ // Even when this is false, Phan will still infer return values and check parameters of internal functions
+ // if Phan has the signatures.
+ 'ignore_undeclared_functions_with_known_signatures' => true,
+
+ // Backwards Compatibility Checking. This is slow
+ // and expensive, but you should consider running
+ // it before upgrading your version of PHP to a
+ // new version that has backward compatibility
+ // breaks.
+ //
+ // If you are migrating from PHP 5 to PHP 7,
+ // you should also look into using
+ // [php7cc (no longer maintained)](https://github.com/sstalle/php7cc)
+ // and [php7mar](https://github.com/Alexia/php7mar),
+ // which have different backwards compatibility checks.
+ //
+ // If you are still using versions of php older than 5.6,
+ // `PHP53CompatibilityPlugin` may be worth looking into if you are not running
+ // syntax checks for php 5.3 through another method such as
+ // `InvokePHPNativeSyntaxCheckPlugin` (see .phan/plugins/README.md).
+ 'backward_compatibility_checks' => false,
+
+ // If true, check to make sure the return type declared
+ // in the doc-block (if any) matches the return type
+ // declared in the method signature.
+ 'check_docblock_signature_return_type_match' => true,
+
+ // This setting maps case-insensitive strings to union types.
+ //
+ // This is useful if a project uses phpdoc that differs from the phpdoc2 standard.
+ //
+ // If the corresponding value is the empty string,
+ // then Phan will ignore that union type (E.g. can ignore 'the' in `@return the value`)
+ //
+ // If the corresponding value is not empty,
+ // then Phan will act as though it saw the corresponding UnionTypes(s)
+ // when the keys show up in a UnionType of `@param`, `@return`, `@var`, `@property`, etc.
+ //
+ // This matches the **entire string**, not parts of the string.
+ // (E.g. `@return the|null` will still look for a class with the name `the`, but `@return the` will be ignored with the below setting)
+ //
+ // (These are not aliases, this setting is ignored outside of doc comments).
+ // (Phan does not check if classes with these names exist)
+ //
+ // Example setting: `['unknown' => '', 'number' => 'int|float', 'char' => 'string', 'long' => 'int', 'the' => '']`
+ 'phpdoc_type_mapping' => [],
+
+ // Set to true in order to attempt to detect dead
+ // (unreferenced) code. Keep in mind that the
+ // results will only be a guess given that classes,
+ // properties, constants and methods can be referenced
+ // as variables (like `$class->$property` or
+ // `$class->$method()`) in ways that we're unable
+ // to make sense of.
+ //
+ // To more aggressively detect dead code,
+ // you may want to set `dead_code_detection_prefer_false_negative` to `false`.
+ 'dead_code_detection' => false,
+
+ // Set to true in order to attempt to detect unused variables.
+ // `dead_code_detection` will also enable unused variable detection.
+ //
+ // This has a few known false positives, e.g. for loops or branches.
+ 'unused_variable_detection' => false,
+
+ // Set to true in order to attempt to detect redundant and impossible conditions.
+ //
+ // This has some false positives involving loops,
+ // variables set in branches of loops, and global variables.
+ 'redundant_condition_detection' => false,
+
+ // If enabled, Phan will act as though it's certain of real return types of a subset of internal functions,
+ // even if those return types aren't available in reflection (real types were taken from php 7.3 or 8.0-dev, depending on target_php_version).
+ //
+ // Note that with php 7 and earlier, php would return null or false for many internal functions if the argument types or counts were incorrect.
+ // As a result, enabling this setting with target_php_version 8.0 may result in false positives for `--redundant-condition-detection` when codebases also support php 7.x.
+ 'assume_real_types_for_internal_functions' => false,
+
+ // If true, this runs a quick version of checks that takes less
+ // time at the cost of not running as thorough
+ // of an analysis. You should consider setting this
+ // to true only when you wish you had more **undiagnosed** issues
+ // to fix in your code base.
+ //
+ // In quick-mode the scanner doesn't rescan a function
+ // or a method's code block every time a call is seen.
+ // This means that the problem here won't be detected:
+ //
+ // ```php
+ // false,
+
+ // Override to hardcode existence and types of (non-builtin) globals in the global scope.
+ // Class names should be prefixed with `\`.
+ //
+ // (E.g. `['_FOO' => '\FooClass', 'page' => '\PageClass', 'userId' => 'int']`)
+ 'globals_type_map' => [],
+
+ // The minimum severity level to report on. This can be
+ // set to `Issue::SEVERITY_LOW`, `Issue::SEVERITY_NORMAL` or
+ // `Issue::SEVERITY_CRITICAL`. Setting it to only
+ // critical issues is a good place to start on a big
+ // sloppy mature code base.
+ 'minimum_severity' => Issue::SEVERITY_NORMAL,
+
+ // Add any issue types (such as `'PhanUndeclaredMethod'`)
+ // to this list to inhibit them from being reported.
+ 'suppress_issue_types' => ['PhanDeprecatedClass', 'PhanUndeclaredConstant','PhanDeprecatedFunction'],
+
+ // A regular expression to match files to be excluded
+ // from parsing and analysis and will not be read at all.
+ //
+ // This is useful for excluding groups of test or example
+ // directories/files, unanalyzable files, or files that
+ // can't be removed for whatever reason.
+ // (e.g. `'@Test\.php$@'`, or `'@vendor/.*/(tests|Tests)/@'`)
+ 'exclude_file_regex' => '@^vendor/.*/(tests?|Tests?)/@',
+
+ // A list of files that will be excluded from parsing and analysis
+ // and will not be read at all.
+ //
+ // This is useful for excluding hopelessly unanalyzable
+ // files that can't be removed for whatever reason.
+ 'exclude_file_list' => [
+ 'administrator\components\com_joomlaupdate\finalisation.php'
+ ],
+
+ // A directory list that defines files that will be excluded
+ // from static analysis, but whose class and method
+ // information should be included.
+ //
+ // Generally, you'll want to include the directories for
+ // third-party code (such as "vendor/") in this list.
+ //
+ // n.b.: If you'd like to parse but not analyze 3rd
+ // party code, directories containing that code
+ // should be added to the `directory_list` as well as
+ // to `exclude_analysis_directory_list`.
+ 'exclude_analysis_directory_list' => [
+ 'libraries/vendor/',
+ 'libraries/php-encryption',
+ 'libraries/phpass'
+ ],
+
+ // Enable this to enable checks of require/include statements referring to valid paths.
+ // The settings `include_paths` and `warn_about_relative_include_statement` affect the checks.
+ 'enable_include_path_checks' => false,
+
+ // The number of processes to fork off during the analysis
+ // phase.
+ 'processes' => 1,
+
+ // List of case-insensitive file extensions supported by Phan.
+ // (e.g. `['php', 'html', 'htm']`)
+ 'analyzed_file_extensions' => [
+ 'php',
+ ],
+
+ // You can put paths to stubs of internal extensions in this config option.
+ // If the corresponding extension is **not** loaded, then Phan will use the stubs instead.
+ // Phan will continue using its detailed type annotations,
+ // but load the constants, classes, functions, and classes (and their Reflection types)
+ // from these stub files (doubling as valid php files).
+ // Use a different extension from php to avoid accidentally loading these.
+ // The `tools/make_stubs` script can be used to generate your own stubs (compatible with php 7.0+ right now)
+ //
+ // (e.g. `['xdebug' => '.phan/internal_stubs/xdebug.phan_php']`)
+ 'autoload_internal_extension_signatures' => [
+ 'redis' => '.phan/redis.phan_php',
+ 'memcached' => '.phan/memcached.phan_php',
+ 'dom' => '.phan/dom.phan_php',
+ ],
+
+ // A list of plugin files to execute.
+ //
+ // Plugins which are bundled with Phan can be added here by providing their name (e.g. `'AlwaysReturnPlugin'`)
+ //
+ // Documentation about available bundled plugins can be found [here](https://github.com/phan/phan/tree/v4/.phan/plugins).
+ //
+ // Alternately, you can pass in the full path to a PHP file with the plugin's implementation (e.g. `'vendor/phan/phan/.phan/plugins/AlwaysReturnPlugin.php'`)
+ 'plugins' => [],
+
+ // A list of directories that should be parsed for class and
+ // method information. After excluding the directories
+ // defined in `exclude_analysis_directory_list`, the remaining
+ // files will be statically analyzed for errors.
+ //
+ // Thus, both first-party and third-party code being used by
+ // your application should be included in this list.
+ 'directory_list' => [
+ 'libraries',
+ 'libraries/vendor/joomla',
+ 'administrator',
+ 'components',
+ 'plugins'
+ ],
+
+ // A list of individual files to include in analysis
+ // with a path relative to the root directory of the
+ // project.
+ 'file_list' => [],
+];
diff --git a/.phan/dom.phan_php b/.phan/dom.phan_php
new file mode 100644
index 0000000000000..ebb92e84dd117
--- /dev/null
+++ b/.phan/dom.phan_php
@@ -0,0 +1,418 @@
+item->id);
}
- if (Associations::isEnabled() && ComponentHelper::isEnabled('com_associations')) {
+ if (
+ Associations::isEnabled() &&
+ ComponentHelper::isEnabled('com_associations') &&
+ AssociationsHelper::hasSupport($component)
+ ) {
ToolbarHelper::custom('category.editAssociations', 'contract', '', 'JTOOLBAR_ASSOCIATIONS', false, false);
}
}
diff --git a/administrator/components/com_contact/src/Table/ContactTable.php b/administrator/components/com_contact/src/Table/ContactTable.php
index 85c248abbd28c..95f74cabab5b4 100644
--- a/administrator/components/com_contact/src/Table/ContactTable.php
+++ b/administrator/components/com_contact/src/Table/ContactTable.php
@@ -119,8 +119,13 @@ public function store($updateNulls = true)
$table = Table::getInstance('ContactTable', __NAMESPACE__ . '\\', array('dbo' => $this->getDbo()));
if ($table->load(array('alias' => $this->alias, 'catid' => $this->catid)) && ($table->id != $this->id || $this->id == 0)) {
+ // Is the existing contact trashed?
$this->setError(Text::_('COM_CONTACT_ERROR_UNIQUE_ALIAS'));
+ if ($table->published === -2) {
+ $this->setError(Text::_('COM_CONTACT_ERROR_UNIQUE_ALIAS_TRASHED'));
+ }
+
return false;
}
diff --git a/administrator/components/com_content/src/Field/Modal/ArticleField.php b/administrator/components/com_content/src/Field/Modal/ArticleField.php
index 995187559c289..a497aecd62789 100644
--- a/administrator/components/com_content/src/Field/Modal/ArticleField.php
+++ b/administrator/components/com_content/src/Field/Modal/ArticleField.php
@@ -123,6 +123,9 @@ protected function getInput()
} catch (\RuntimeException $e) {
Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
}
+ if (empty($title)) {
+ $value = '';
+ }
}
$title = empty($title) ? Text::_('COM_CONTENT_SELECT_AN_ARTICLE') : htmlspecialchars($title, ENT_QUOTES, 'UTF-8');
diff --git a/administrator/components/com_cpanel/src/View/Cpanel/HtmlView.php b/administrator/components/com_cpanel/src/View/Cpanel/HtmlView.php
index 520d7704f9ca9..58df45b02ea30 100644
--- a/administrator/components/com_cpanel/src/View/Cpanel/HtmlView.php
+++ b/administrator/components/com_cpanel/src/View/Cpanel/HtmlView.php
@@ -10,8 +10,8 @@
namespace Joomla\Component\Cpanel\Administrator\View\Cpanel;
-use Joomla\CMS\Application\ApplicationHelper;
use Joomla\CMS\Factory;
+use Joomla\CMS\Filter\OutputFilter;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
@@ -61,7 +61,7 @@ public function display($tpl = null)
$app = Factory::getApplication();
$dashboard = $app->input->getCmd('dashboard', '');
- $position = ApplicationHelper::stringURLSafe($dashboard);
+ $position = OutputFilter::stringURLSafe($dashboard);
// Generate a title for the view cpanel
if (!empty($dashboard)) {
diff --git a/administrator/components/com_fields/src/Helper/FieldsHelper.php b/administrator/components/com_fields/src/Helper/FieldsHelper.php
index ecfdefdd20345..99cd4d3ec17ce 100644
--- a/administrator/components/com_fields/src/Helper/FieldsHelper.php
+++ b/administrator/components/com_fields/src/Helper/FieldsHelper.php
@@ -19,6 +19,7 @@
use Joomla\CMS\Object\CMSObject;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\Component\Fields\Administrator\Model\FieldsModel;
+use Joomla\Component\Fields\Administrator\Model\FieldModel;
use Joomla\Database\ParameterType;
// phpcs:disable PSR1.Files.SideEffects
@@ -38,7 +39,7 @@ class FieldsHelper
private static $fieldsCache = null;
/**
- * @var FieldsModel
+ * @var FieldModel
*/
private static $fieldCache = null;
diff --git a/administrator/components/com_fields/src/Model/FieldModel.php b/administrator/components/com_fields/src/Model/FieldModel.php
index 5ae40ea68c880..c0ff23176a82d 100644
--- a/administrator/components/com_fields/src/Model/FieldModel.php
+++ b/administrator/components/com_fields/src/Model/FieldModel.php
@@ -452,6 +452,8 @@ protected function generateNewTitle($categoryId, $name, $title)
*/
public function delete(&$pks)
{
+ $db = $this->getDatabase();
+
$success = parent::delete($pks);
if ($success) {
@@ -461,20 +463,20 @@ public function delete(&$pks)
if (!empty($pks)) {
// Delete Values
- $query = $this->getDatabase()->getQuery(true);
+ $query = $db->getQuery(true);
- $query->delete($query->quoteName('#__fields_values'))
- ->whereIn($query->quoteName('field_id'), $pks);
+ $query->delete($db->quoteName('#__fields_values'))
+ ->whereIn($db->quoteName('field_id'), $pks);
- $this->getDatabase()->setQuery($query)->execute();
+ $db->setQuery($query)->execute();
// Delete Assigned Categories
- $query = $this->getDatabase()->getQuery(true);
+ $query = $db->getQuery(true);
- $query->delete($query->quoteName('#__fields_categories'))
- ->whereIn($query->quoteName('field_id'), $pks);
+ $query->delete($db->quoteName('#__fields_categories'))
+ ->whereIn($db->quoteName('field_id'), $pks);
- $this->getDatabase()->setQuery($query)->execute();
+ $db->setQuery($query)->execute();
}
}
@@ -620,15 +622,16 @@ public function setFieldValue($fieldId, $itemId, $value)
$fieldId = (int) $fieldId;
// Deleting the existing record as it is a reset
- $query = $this->getDatabase()->getQuery(true);
+ $db = $this->getDatabase();
+ $query = $db->getQuery(true);
- $query->delete($query->quoteName('#__fields_values'))
- ->where($query->quoteName('field_id') . ' = :fieldid')
- ->where($query->quoteName('item_id') . ' = :itemid')
+ $query->delete($db->quoteName('#__fields_values'))
+ ->where($db->quoteName('field_id') . ' = :fieldid')
+ ->where($db->quoteName('item_id') . ' = :itemid')
->bind(':fieldid', $fieldId, ParameterType::INTEGER)
->bind(':itemid', $itemId);
- $this->getDatabase()->setQuery($query)->execute();
+ $db->setQuery($query)->execute();
}
if ($needsInsert) {
@@ -703,16 +706,17 @@ public function getFieldValues(array $fieldIds, $itemId)
// Fill the cache when it doesn't exist
if (!array_key_exists($key, $this->valueCache)) {
// Create the query
- $query = $this->getDatabase()->getQuery(true);
+ $db = $this->getDatabase();
+ $query = $db->getQuery(true);
- $query->select($query->quoteName(['field_id', 'value']))
- ->from($query->quoteName('#__fields_values'))
- ->whereIn($query->quoteName('field_id'), ArrayHelper::toInteger($fieldIds))
- ->where($query->quoteName('item_id') . ' = :itemid')
+ $query->select($db->quoteName(['field_id', 'value']))
+ ->from($db->quoteName('#__fields_values'))
+ ->whereIn($db->quoteName('field_id'), ArrayHelper::toInteger($fieldIds))
+ ->where($db->quoteName('item_id') . ' = :itemid')
->bind(':itemid', $itemId);
// Fetch the row from the database
- $rows = $this->getDatabase()->setQuery($query)->loadObjectList();
+ $rows = $db->setQuery($query)->loadObjectList();
$data = array();
@@ -757,20 +761,21 @@ public function getFieldValues(array $fieldIds, $itemId)
public function cleanupValues($context, $itemId)
{
// Delete with inner join is not possible so we need to do a subquery
- $fieldsQuery = $this->getDatabase()->getQuery(true);
- $fieldsQuery->select($fieldsQuery->quoteName('id'))
- ->from($fieldsQuery->quoteName('#__fields'))
- ->where($fieldsQuery->quoteName('context') . ' = :context');
+ $db = $this->getDatabase();
+ $fieldsQuery = $db->getQuery(true);
+ $fieldsQuery->select($db->quoteName('id'))
+ ->from($db->quoteName('#__fields'))
+ ->where($db->quoteName('context') . ' = :context');
- $query = $this->getDatabase()->getQuery(true);
+ $query = $db->getQuery(true);
- $query->delete($query->quoteName('#__fields_values'))
- ->where($query->quoteName('field_id') . ' IN (' . $fieldsQuery . ')')
- ->where($query->quoteName('item_id') . ' = :itemid')
+ $query->delete($db->quoteName('#__fields_values'))
+ ->where($db->quoteName('field_id') . ' IN (' . $fieldsQuery . ')')
+ ->where($db->quoteName('item_id') . ' = :itemid')
->bind(':itemid', $itemId)
->bind(':context', $context);
- $this->getDatabase()->setQuery($query)->execute();
+ $db->setQuery($query)->execute();
}
/**
diff --git a/administrator/components/com_finder/src/Controller/DisplayController.php b/administrator/components/com_finder/src/Controller/DisplayController.php
index 820f6b65f36ba..ec4905231e7d2 100644
--- a/administrator/components/com_finder/src/Controller/DisplayController.php
+++ b/administrator/components/com_finder/src/Controller/DisplayController.php
@@ -71,7 +71,7 @@ public function display($cachable = false, $urlparams = array())
if ($view === 'filter' && $layout === 'edit' && !$this->checkEditId('com_finder.edit.filter', $filterId)) {
// Somehow the person just went to the form - we don't allow that.
if (!\count($this->app->getMessageQueue())) {
- $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $f_id), 'error');
+ $this->setMessage(Text::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $filterId), 'error');
}
$this->setRedirect(Route::_('index.php?option=com_finder&view=filters', false));
diff --git a/administrator/components/com_finder/src/Indexer/Query.php b/administrator/components/com_finder/src/Indexer/Query.php
index 0e220ddc6a2da..a5bea020c25b0 100644
--- a/administrator/components/com_finder/src/Indexer/Query.php
+++ b/administrator/components/com_finder/src/Indexer/Query.php
@@ -1245,8 +1245,8 @@ protected function getTokenData($token)
$searchTerm = $token->term;
$searchStem = $token->stem;
- $term = $query->quoteName('t.term');
- $stem = $query->quoteName('t.stem');
+ $term = $db->quoteName('t.term');
+ $stem = $db->quoteName('t.stem');
if ($this->wordmode === 'begin') {
$searchTerm .= '%';
diff --git a/administrator/components/com_finder/src/Indexer/Result.php b/administrator/components/com_finder/src/Indexer/Result.php
index 4d7e9abce813b..6a067a76df219 100644
--- a/administrator/components/com_finder/src/Indexer/Result.php
+++ b/administrator/components/com_finder/src/Indexer/Result.php
@@ -394,6 +394,11 @@ public function getTaxonomy($branch = null)
*/
public function addTaxonomy($branch, $title, $state = 1, $access = 1, $language = '')
{
+ // We can't add taxonomies with empty titles
+ if (!trim($title)) {
+ return;
+ }
+
// Filter the input.
$branch = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,_]+#mui', ' ', $branch);
@@ -424,6 +429,11 @@ public function addTaxonomy($branch, $title, $state = 1, $access = 1, $language
*/
public function addNestedTaxonomy($branch, ImmutableNodeInterface $contentNode, $state = 1, $access = 1, $language = '')
{
+ // We can't add taxonomies with empty titles
+ if (!trim($contentNode->title)) {
+ return;
+ }
+
// Filter the input.
$branch = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,_]+#mui', ' ', $branch);
diff --git a/administrator/components/com_finder/src/Table/FilterTable.php b/administrator/components/com_finder/src/Table/FilterTable.php
index 621076fa65ccb..932fb30caf88a 100644
--- a/administrator/components/com_finder/src/Table/FilterTable.php
+++ b/administrator/components/com_finder/src/Table/FilterTable.php
@@ -157,7 +157,7 @@ public function store($updateNulls = true)
$table = new static($this->getDbo());
if ($table->load(array('alias' => $this->alias)) && ($table->filter_id != $this->filter_id || $this->filter_id == 0)) {
- $this->setError(Text::_('JLIB_DATABASE_ERROR_ARTICLE_UNIQUE_ALIAS'));
+ $this->setError(Text::_('COM_FINDER_FILTER_ERROR_UNIQUE_ALIAS'));
return false;
}
diff --git a/administrator/components/com_languages/tmpl/overrides/default.php b/administrator/components/com_languages/tmpl/overrides/default.php
index 954a765486f3e..872e4e2e30b28 100644
--- a/administrator/components/com_languages/tmpl/overrides/default.php
+++ b/administrator/components/com_languages/tmpl/overrides/default.php
@@ -93,11 +93,11 @@