diff options
456 files changed, 3018 insertions, 2051 deletions
diff --git a/composer/Generator/PackageGenerator.php b/composer/Generator/PackageGenerator.php index 7c2d5b6f346..e3f6a378e90 100644 --- a/composer/Generator/PackageGenerator.php +++ b/composer/Generator/PackageGenerator.php @@ -87,7 +87,7 @@ class PackageGenerator { */ protected function generateMetapackage(IOInterface $io, BuilderInterface $builder) { - // Load the existing composer.json file for drupal/core-recommended + // Load the existing composer.json file for drupal/core-recommended. $relative_path = $builder->getPath() . '/composer.json'; $composer_json_path = $this->generatedProjectBaseDir . '/' . $relative_path; $original_composer_json = file_exists($composer_json_path) ? file_get_contents($composer_json_path) : ''; @@ -104,7 +104,7 @@ class PackageGenerator { // Warn the user that a metapackage file has been updated.. $io->write("Updated metapackage file <info>composer/Metapackage/$relative_path</info>."); - // Write the composer.json file back to disk + // Write the composer.json file back to disk. $fs = new Filesystem(); $fs->ensureDirectoryExists(dirname($composer_json_path)); file_put_contents($composer_json_path, $updated_composer_json); diff --git a/composer/Plugin/Scaffold/Operations/AppendOp.php b/composer/Plugin/Scaffold/Operations/AppendOp.php index 4ed8b62d201..77a8ade0d45 100644 --- a/composer/Plugin/Scaffold/Operations/AppendOp.php +++ b/composer/Plugin/Scaffold/Operations/AppendOp.php @@ -140,7 +140,7 @@ class AppendOp extends AbstractOperation { $io->write($interpolator->interpolate(" - Append to <info>[dest-rel-path]</info> from <info>[append-rel-path]</info>")); } - // Write the resulting data + // Write the resulting data. file_put_contents($destination_path, $this->contents()); // Return a ScaffoldResult with knowledge of whether this file is managed. diff --git a/composer/Plugin/VendorHardening/VendorHardeningPlugin.php b/composer/Plugin/VendorHardening/VendorHardeningPlugin.php index 50195be657d..87cc97bc7a6 100644 --- a/composer/Plugin/VendorHardening/VendorHardeningPlugin.php +++ b/composer/Plugin/VendorHardening/VendorHardeningPlugin.php @@ -212,8 +212,8 @@ class VendorHardeningPlugin implements PluginInterface, EventSubscriberInterface */ protected function findBinOverlap(array $binaries, array $clean_paths): array { // Make a filesystem model to explore. This is a keyed array that looks like - // all the places that will be removed by cleanup. 'tests/src' becomes - // $filesystem['tests']['src'] = TRUE; + // all the places that will be removed by cleanup. For example, the path + // "tests/src" becomes "$filesystem['tests']['src'] = TRUE". $filesystem = []; foreach ($clean_paths as $clean_path) { $clean_pieces = explode("/", $clean_path); diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml index 8bbffd2acb2..67bd72d1cc3 100644 --- a/core/config/schema/core.data_types.schema.yml +++ b/core/config/schema/core.data_types.schema.yml @@ -84,6 +84,15 @@ required_label: plural_label: type: label label: 'Plural variants' + constraints: + Regex: + # Normally, labels cannot contain invisible control characters. In this particular + # case, an invisible character (ASCII 3, 0x03) is used to encode translation + # information, so carve out an exception for that only. + # @see \Drupal\views\Plugin\views\field\NumericField + pattern: '/([^\PC\x03])/u' + match: false + message: 'Labels are not allowed to span multiple lines or contain control characters.' # Internal Drupal path path: @@ -1152,29 +1161,25 @@ mailer_dsn.options.smtp: nullable: true label: 'Maximum number of messages to send before re-starting the transport (defaults to 100 messages)' constraints: - Range: - min: 0 + PositiveOrZero: ~ restart_threshold_sleep: type: float nullable: true label: 'Number of seconds to sleep between stopping and re-starting the transport (defaults to no delay)' constraints: - Range: - min: 0 + PositiveOrZero: ~ ping_threshold: type: integer nullable: true label: 'The minimum number of seconds between two messages required to ping the server (defaults to 100 seconds)' constraints: - Range: - min: 0 + PositiveOrZero: ~ max_per_second: type: integer nullable: true label: 'The number of messages to send per second (defaults to no limit)' constraints: - Range: - min: 0 + PositiveOrZero: ~ mailer_dsn.options.smtps: type: mailer_dsn.options.smtp diff --git a/core/core.api.php b/core/core.api.php index 33c04722da4..9005bd48824 100644 --- a/core/core.api.php +++ b/core/core.api.php @@ -2279,7 +2279,7 @@ function hook_mail($key, &$message, $params): void { $variables += [ '%uid' => $node->getOwnerId(), '%url' => $node->toUrl('canonical', ['absolute' => TRUE])->toString(), - '%node_type' => node_get_type_label($node), + '%node_type' => $node->getBundleEntity()->label(), '%title' => $node->getTitle(), '%teaser' => $node->teaser, '%body' => $node->body, diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index f4696ba281b..48c423e95ae 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -456,7 +456,7 @@ function &drupal_register_shutdown_function($callback = NULL, ...$args) { if (empty($callbacks)) { register_shutdown_function('_drupal_shutdown_function'); } - // Save callback and arguments + // Save callback and arguments. $callbacks[] = ['callback' => $callback, 'arguments' => $args]; } return $callbacks; diff --git a/core/includes/form.inc b/core/includes/form.inc index d17e828e971..82a1f7b9c62 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -887,7 +887,7 @@ function batch_process($redirect = NULL, ?Url $url = NULL, $redirect_callback = $batch =& batch_get(); if (isset($batch)) { - // Add process information + // Add process information. $process_info = [ 'current_set' => 0, 'progressive' => TRUE, diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index 35fa223c31d..b94562a51e3 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -1197,7 +1197,7 @@ function install_database_errors($database, $settings_file) { try { $driverExtension = Database::getDriverList()->get($database['namespace']); - // Run driver specific validation + // Run driver specific validation. $errors = $driverExtension->getInstallTasks()->validateDatabaseSettings($database); if (!empty($errors)) { // No point to try further. diff --git a/core/includes/install.inc b/core/includes/install.inc index dc181b04381..1abcad9b0c6 100644 --- a/core/includes/install.inc +++ b/core/includes/install.inc @@ -701,12 +701,12 @@ function drupal_check_module($module) { if (is_file($file)) { require_once $file; } - // Check requirements + // Check requirements. $requirements = \Drupal::moduleHandler()->invoke($module, 'requirements', ['install']) ?? []; $requirements = array_merge($requirements, install_check_class_requirements($extension)); if (!empty($requirements) && RequirementSeverity::maxSeverityFromRequirements($requirements) === RequirementSeverity::Error) { - // Print any error messages + // Print any error messages. foreach ($requirements as $requirement) { if (isset($requirement['severity']) && $requirement['severity'] === RequirementSeverity::Error) { $message = $requirement['description']; diff --git a/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php b/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php index 1e9fca562f5..6d45c3a0acb 100644 --- a/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php +++ b/core/lib/Drupal/Component/ProxyBuilder/ProxyBuilder.php @@ -98,7 +98,7 @@ EOS; $output .= $this->buildUseStatements(); - // The actual class; + // The actual class. $properties = <<<'EOS' /** * The id of the original proxied service. @@ -324,7 +324,7 @@ EOS; $output .= " \\$class_name::$function_name("; } - // Add parameters; + // Add parameters. $parameters = []; foreach ($reflection_method->getParameters() as $parameter) { $parameters[] = '$' . $parameter->getName(); diff --git a/core/lib/Drupal/Component/Utility/DeprecationHelper.php b/core/lib/Drupal/Component/Utility/DeprecationHelper.php index f9a4aebba43..3d2e3d1d153 100644 --- a/core/lib/Drupal/Component/Utility/DeprecationHelper.php +++ b/core/lib/Drupal/Component/Utility/DeprecationHelper.php @@ -38,8 +38,8 @@ final class DeprecationHelper { */ public static function backwardsCompatibleCall(string $currentVersion, string $deprecatedVersion, callable $currentCallable, callable $deprecatedCallable): mixed { // Normalize the version string when it's a dev version to the first point - // release of that minor. E.g. 10.2.x-dev and 10.2-dev both translate to - // 10.2.0 + // release of that minor. E.g. "10.2.x-dev" and "10.2-dev" both translate to + // "10.2.0". $normalizedVersion = str_ends_with($currentVersion, '-dev') ? str_replace(['.x-dev', '-dev'], '.0', $currentVersion) : $currentVersion; return version_compare($normalizedVersion, $deprecatedVersion, '>=') ? $currentCallable() : $deprecatedCallable(); diff --git a/core/lib/Drupal/Component/Utility/Tags.php b/core/lib/Drupal/Component/Utility/Tags.php index f96667f85f0..317d00c4005 100644 --- a/core/lib/Drupal/Component/Utility/Tags.php +++ b/core/lib/Drupal/Component/Utility/Tags.php @@ -20,7 +20,7 @@ class Tags { */ public static function explode($tags) { // This regexp allows the following types of user input: - // this, "company, llc", "and ""this"" w,o.rks", foo bar + // this, "company, llc", "and ""this"" w,o.rks", foo bar. $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x'; preg_match_all($regexp, $tags, $matches); $typed_tags = array_unique($matches[1]); diff --git a/core/lib/Drupal/Component/Utility/UserAgent.php b/core/lib/Drupal/Component/Utility/UserAgent.php index cc42d2f25b8..80cdb19c41e 100644 --- a/core/lib/Drupal/Component/Utility/UserAgent.php +++ b/core/lib/Drupal/Component/Utility/UserAgent.php @@ -45,7 +45,7 @@ class UserAgent { // 1#( language-range [ ";" "q" "=" qvalue ] ) // language-range = ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) | "*" ) // @endcode - // Samples: "hu, en-us;q=0.66, en;q=0.33", "hu,en-us;q=0.5" + // Samples: "hu, en-us;q=0.66, en;q=0.33", "hu,en-us;q=0.5". $ua_langcodes = []; if (preg_match_all('@(?<=[, ]|^)([a-zA-Z-]+|\*)(?:;q=([0-9.]+))?(?:$|\s*,\s*)@', trim($http_accept_language), $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { diff --git a/core/lib/Drupal/Core/Asset/CssOptimizer.php b/core/lib/Drupal/Core/Asset/CssOptimizer.php index 9b5559c696d..8847c1e5caa 100644 --- a/core/lib/Drupal/Core/Asset/CssOptimizer.php +++ b/core/lib/Drupal/Core/Asset/CssOptimizer.php @@ -130,8 +130,7 @@ class CssOptimizer implements AssetOptimizerInterface { if ($reset_base_path) { $base_path = ''; } - // Store the value of $optimize for preg_replace_callback with nested - // @import loops. + // Store $optimize for preg_replace_callback with nested @import loops. if (isset($optimize)) { $_optimize = $optimize; } diff --git a/core/lib/Drupal/Core/Config/Config.php b/core/lib/Drupal/Core/Config/Config.php index 2e78c30b5ac..9d604934f7d 100644 --- a/core/lib/Drupal/Core/Config/Config.php +++ b/core/lib/Drupal/Core/Config/Config.php @@ -209,6 +209,8 @@ class Config extends StorableConfigBase { // Ensure that the schema wrapper has the latest data. $this->schemaWrapper = NULL; $this->data = $this->castValue(NULL, $this->data); + // Reclaim the memory used by the schema wrapper. + $this->schemaWrapper = NULL; } else { foreach ($this->data as $key => $value) { diff --git a/core/lib/Drupal/Core/Config/ConfigBase.php b/core/lib/Drupal/Core/Config/ConfigBase.php index 6c8148612ed..adb8cf70baf 100644 --- a/core/lib/Drupal/Core/Config/ConfigBase.php +++ b/core/lib/Drupal/Core/Config/ConfigBase.php @@ -102,7 +102,7 @@ abstract class ConfigBase implements RefinableCacheableDependencyInterface { } // The name must not contain any of the following characters: - // : ? * < > " ' / \ + // : ? * < > ' " / \ if (preg_match('/[:?*<>"\'\/\\\\]/', $name)) { throw new ConfigNameException("Invalid character in Config object name $name."); } diff --git a/core/lib/Drupal/Core/Config/Schema/Mapping.php b/core/lib/Drupal/Core/Config/Schema/Mapping.php index 22f3040a6f7..3b859dd1ab9 100644 --- a/core/lib/Drupal/Core/Config/Schema/Mapping.php +++ b/core/lib/Drupal/Core/Config/Schema/Mapping.php @@ -166,8 +166,8 @@ class Mapping extends ArrayElement { $all_type_definitions = $typed_data_manager->getDefinitions(); $possible_type_definitions = array_intersect_key($all_type_definitions, array_fill_keys($possible_types, TRUE)); // TRICKY: \Drupal\Core\Config\TypedConfigManager::getDefinition() does the - // necessary resolving, but TypedConfigManager::getDefinitions() does not! - // 🤷♂️ + // necessary resolving, but TypedConfigManager::getDefinitions() does not + // 🤷♂️! // @see \Drupal\Core\Config\TypedConfigManager::getDefinitionWithReplacements() // @see ::getValidKeys() $valid_keys_per_type = []; @@ -273,7 +273,7 @@ class Mapping extends ArrayElement { // use in a regex. So: // `module\.something\.foo_.*` // or - // `.*\.third_party\..*` + // `.*\.third_party\..*`. $regex = str_replace(['.', '[]'], ['\.', '.*'], $name); // Now find all possible types: // 1. `module.something.foo_foo`, `module.something.foo_bar`, etc. diff --git a/core/lib/Drupal/Core/Config/Schema/TypeResolver.php b/core/lib/Drupal/Core/Config/Schema/TypeResolver.php index af9c1c53aba..1cbe3d37976 100644 --- a/core/lib/Drupal/Core/Config/Schema/TypeResolver.php +++ b/core/lib/Drupal/Core/Config/Schema/TypeResolver.php @@ -99,7 +99,7 @@ class TypeResolver { } $previous_name = $name; if (!is_array($data) || !isset($data[$name])) { - // Key not found, return original value + // Key not found, return original value. return $expression; } if (!$parts) { @@ -126,7 +126,7 @@ class TypeResolver { } $data = $data[$name]; } - // Return the original value + // Return the original value. return $expression; } diff --git a/core/lib/Drupal/Core/Config/TypedConfigManager.php b/core/lib/Drupal/Core/Config/TypedConfigManager.php index 99fdb0d5978..ae2ba86b3ad 100644 --- a/core/lib/Drupal/Core/Config/TypedConfigManager.php +++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php @@ -376,14 +376,13 @@ class TypedConfigManager extends TypedDataManager implements TypedConfigManagerI else { // No definition for this level. Collapse multiple wildcards to a single // wildcard to see if there is a greedy match. For example, - // breakpoint.breakpoint.*.* becomes - // breakpoint.breakpoint.* + // "breakpoint.breakpoint.*.*" becomes "breakpoint.breakpoint.*". $one_star = preg_replace('/\.([:\.\*]*)$/', '.*', $replaced); if ($one_star != $replaced && isset($this->definitions[$one_star])) { return $one_star; } - // Check for next level. For example, if breakpoint.breakpoint.* has - // been checked and no match found then check breakpoint.*.* + // Check for next level. For example, if "breakpoint.breakpoint.*" has + // been checked and no match found then check "breakpoint.*.*". return $this->getFallbackName($replaced); } } diff --git a/core/lib/Drupal/Core/Cron.php b/core/lib/Drupal/Core/Cron.php index 1773d810a25..982e4714fc9 100644 --- a/core/lib/Drupal/Core/Cron.php +++ b/core/lib/Drupal/Core/Cron.php @@ -107,7 +107,7 @@ class Cron implements CronInterface { // Add watchdog message. $this->logger->info('Cron run completed.'); - // Return TRUE so other functions can check if it did run successfully + // Return TRUE so other functions can check if it did run successfully. $return = TRUE; } diff --git a/core/lib/Drupal/Core/Database/Query/Condition.php b/core/lib/Drupal/Core/Database/Query/Condition.php index 89757a754f0..c03440e5820 100644 --- a/core/lib/Drupal/Core/Database/Query/Condition.php +++ b/core/lib/Drupal/Core/Database/Query/Condition.php @@ -222,16 +222,16 @@ class Condition implements ConditionInterface, \Countable { } $arguments += $condition['field']->arguments(); // If the operator and value were not passed in to the - // @see ConditionInterface::condition() method (and thus have the - // default value as defined over there) it is assumed to be a valid - // condition on its own: ignore the operator and value parts. + // ConditionInterface::condition() method (and thus have the default + // value as defined over there) it is assumed to be a valid condition + // on its own: ignore the operator and value parts. $ignore_operator = $condition['operator'] === '=' && $condition['value'] === NULL; } elseif (!isset($condition['operator'])) { // Left hand part is a literal string added with the - // @see ConditionInterface::where() method. Put brackets around - // the snippet and collect the arguments from the value part. - // Also ignore the operator and value parts. + // ConditionInterface::where() method. Put brackets around the snippet + // and collect the arguments from the value part. Also ignore the + // operator and value parts. $field_fragment = '(' . $condition['field'] . ')'; $arguments += $condition['value']; $ignore_operator = TRUE; diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php index d284ea285a5..629037ad133 100644 --- a/core/lib/Drupal/Core/Database/Query/Select.php +++ b/core/lib/Drupal/Core/Database/Query/Select.php @@ -810,13 +810,13 @@ class Select extends Query implements SelectInterface { // Create a sanitized comment string to prepend to the query. $comments = $this->connection->makeComment($this->comments); - // SELECT + // SELECT. $query = $comments . 'SELECT '; if ($this->distinct) { $query .= 'DISTINCT '; } - // FIELDS and EXPRESSIONS + // FIELDS and EXPRESSIONS. $fields = []; foreach ($this->tables as $alias => $table) { if (!empty($table['all_fields'])) { @@ -870,13 +870,13 @@ class Select extends Query implements SelectInterface { } } - // WHERE + // WHERE. if (count($this->condition)) { // There is an implicit string cast on $this->condition. $query .= "\nWHERE " . $this->condition; } - // GROUP BY + // GROUP BY. if ($this->group) { $group_by_fields = array_map(function (string $field): string { return $this->connection->escapeField($field); @@ -884,7 +884,7 @@ class Select extends Query implements SelectInterface { $query .= "\nGROUP BY " . implode(', ', $group_by_fields); } - // HAVING + // HAVING. if (count($this->having)) { // There is an implicit string cast on $this->having. $query .= "\nHAVING " . $this->having; @@ -898,7 +898,7 @@ class Select extends Query implements SelectInterface { } } - // ORDER BY + // ORDER BY. if ($this->order) { $query .= "\nORDER BY "; $fields = []; diff --git a/core/lib/Drupal/Core/Database/Schema.php b/core/lib/Drupal/Core/Database/Schema.php index 394fa4578dd..9135ae471a6 100644 --- a/core/lib/Drupal/Core/Database/Schema.php +++ b/core/lib/Drupal/Core/Database/Schema.php @@ -171,7 +171,7 @@ abstract class Schema implements PlaceholderInterface { protected function buildTableNameCondition($table_name, $operator = '=', $add_prefix = TRUE) { $info = $this->connection->getConnectionOptions(); - // Retrieve the table name and schema + // Retrieve the table name and schema. $table_info = $this->getPrefixInfo($table_name, $add_prefix); $condition = $this->connection->condition('AND'); diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php index 221164875ef..1a5de6c18fd 100644 --- a/core/lib/Drupal/Core/DrupalKernel.php +++ b/core/lib/Drupal/Core/DrupalKernel.php @@ -1315,11 +1315,8 @@ class DrupalKernel implements DrupalKernelInterface, TerminableInterface { // Get a list of namespaces and put it onto the container. $namespaces = $this->getModuleNamespacesPsr4($this->getModuleFileNames()); - // Add all components in \Drupal\Core and \Drupal\Component that have one of - // the following directories: - // - Element - // - Entity - // - Plugin + // Add all components in \Drupal\Core and \Drupal\Component that have one or + // more of Element, Entity and Plugin directories. foreach (['Core', 'Component'] as $parent_directory) { $path = 'core/lib/Drupal/' . $parent_directory; $parent_namespace = 'Drupal\\' . $parent_directory; diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php index e7b42bc2af7..ff77c5c33a9 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php @@ -232,7 +232,7 @@ abstract class ContentEntityStorageBase extends EntityStorageBase implements Con throw new EntityStorageException(sprintf("Missing entity bundle. The \"%s\" bundle does not exist", $bundle)); } $values[$bundle_key] = $bundle; - // Bundle is already set + // Bundle is already set. $forbidden_keys[] = $bundle_key; } // Forbid sample generation on any keys whose values were submitted. diff --git a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php index f5699e737de..b3d4a008b76 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php +++ b/core/lib/Drupal/Core/Entity/Plugin/Validation/Constraint/ValidReferenceConstraintValidator.php @@ -138,7 +138,7 @@ class ValidReferenceConstraintValidator extends ConstraintValidator implements C foreach ($invalid_target_ids as $delta => $target_id) { // Check if any of the invalid existing references are simply not // accessible by the user, in which case they need to be excluded from - // validation + // validation. if (isset($previously_referenced_ids[$target_id]) && isset($existing_entities[$target_id]) && !$existing_entities[$target_id]->access('view')) { continue; } diff --git a/core/lib/Drupal/Core/Entity/entity.api.php b/core/lib/Drupal/Core/Entity/entity.api.php index 04b3ead1bb7..af75135015c 100644 --- a/core/lib/Drupal/Core/Entity/entity.api.php +++ b/core/lib/Drupal/Core/Entity/entity.api.php @@ -2226,7 +2226,7 @@ function hook_entity_field_access_alter(array &$grants, array $context) { // take out node module's part in the access handling of this field. We also // don't want to switch node module's grant to // AccessResultInterface::isAllowed() , because the grants of other modules - // should still decide on their own if this field is accessible or not + // should still decide on their own if this field is accessible or not. $grants['node'] = AccessResult::neutral()->inheritCacheability($grants['node']); } } diff --git a/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php b/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php index 28ad2c04451..c5a2b7c8fc8 100644 --- a/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php +++ b/core/lib/Drupal/Core/EventSubscriber/ActiveLinkResponseFilter.php @@ -183,7 +183,7 @@ class ActiveLinkResponseFilter implements EventSubscriberInterface { } // Get the HTML: this will be the opening part of a single tag, e.g.: - // <a href="/" data-drupal-link-system-path="<front>"> + // '<a href="/" data-drupal-link-system-path="<front>">'. $tag = substr($html_markup, $pos_tag_start ?? 0, $pos_tag_end - $pos_tag_start + 1); // Parse it into a DOMDocument so we can reliably read and modify diff --git a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php index 67ab669bade..71cba69d6cf 100644 --- a/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/DefaultExceptionHtmlSubscriber.php @@ -167,8 +167,8 @@ class DefaultExceptionHtmlSubscriber extends HttpExceptionSubscriberBase { $parameters->add($this->redirectDestination->getAsArray() + ['_exception_statuscode' => $status_code]); $response = $this->httpKernel->handle($sub_request, HttpKernelInterface::SUB_REQUEST); - // Only 2xx responses should have their status code overridden; any - // other status code should be passed on: redirects (3xx), error (5xx)… + // Only 2xx responses should have their status code overridden; any other + // status code should be passed on: redirects (3xx), error (5xx) etc. // @see https://www.drupal.org/node/2603788#comment-10504916 if ($response->isSuccessful()) { $response->setStatusCode($status_code); diff --git a/core/lib/Drupal/Core/Extension/module.api.php b/core/lib/Drupal/Core/Extension/module.api.php index 41d84b33346..7eaad4b9ec2 100644 --- a/core/lib/Drupal/Core/Extension/module.api.php +++ b/core/lib/Drupal/Core/Extension/module.api.php @@ -788,7 +788,7 @@ function hook_install_tasks_alter(&$tasks, $install_state) { // phpcs:enable function hook_update_N(&$sandbox) { // For non-batch updates, the signature can simply be: - // function hook_update_N() { + // "function hook_update_N() {". // Example function body for adding a field to a database table, which does // not require a batch operation: @@ -1140,7 +1140,7 @@ function hook_updater_info_alter(&$updaters) { function hook_requirements($phase): array { $requirements = []; - // Report Drupal version + // Report Drupal version. if ($phase == 'runtime') { $requirements['drupal'] = [ 'title' => t('Drupal'), @@ -1149,7 +1149,7 @@ function hook_requirements($phase): array { ]; } - // Test PHP version + // Test PHP version. $requirements['php'] = [ 'title' => t('PHP'), 'value' => ($phase == 'runtime') ? Link::fromTextAndUrl(phpversion(), Url::fromRoute('system.php'))->toString() : phpversion(), @@ -1159,7 +1159,7 @@ function hook_requirements($phase): array { $requirements['php']['severity'] = RequirementSeverity::Error; } - // Report cron status + // Report cron status. if ($phase == 'runtime') { $cron_last = \Drupal::state()->get('system.cron_last'); @@ -1234,14 +1234,14 @@ function hook_requirements_alter(array &$requirements): void { function hook_runtime_requirements(): array { $requirements = []; - // Report Drupal version + // Report Drupal version. $requirements['drupal'] = [ 'title' => t('Drupal'), 'value' => \Drupal::VERSION, 'severity' => RequirementSeverity::Info, ]; - // Test PHP version + // Test PHP version. $requirements['php'] = [ 'title' => t('PHP'), 'value' => Link::fromTextAndUrl(phpversion(), Url::fromRoute('system.php'))->toString(), @@ -1251,7 +1251,7 @@ function hook_runtime_requirements(): array { $requirements['php']['severity'] = RequirementSeverity::Error; } - // Report cron status + // Report cron status. $cron_last = \Drupal::state()->get('system.cron_last'); $requirements['cron']['title'] = t('Cron maintenance tasks'); if (is_numeric($cron_last)) { @@ -1311,7 +1311,7 @@ function hook_runtime_requirements_alter(array &$requirements): void { function hook_update_requirements() { $requirements = []; - // Test PHP version + // Test PHP version. $requirements['php'] = [ 'title' => t('PHP'), 'value' => phpversion(), diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php index 6997c1bb8fa..5a7ec04c169 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php @@ -127,11 +127,11 @@ class DecimalItem extends NumericItemBase { $max = is_numeric($settings['max']) ? $settings['max'] : pow(10, ($precision - $scale)) - 1; $min = is_numeric($settings['min']) ? $settings['min'] : -pow(10, ($precision - $scale)) + 1; - // Get the number of decimal digits for the $max + // Get the number of decimal digits for the $max. $decimal_digits = self::getDecimalDigits($max); // Do the same for the min and keep the higher number of decimal digits. $decimal_digits = max(self::getDecimalDigits($min), $decimal_digits); - // If $min = 1.234 and $max = 1.33 then $decimal_digits = 3 + // If $min = 1.234 and $max = 1.33 then $decimal_digits = 3. $scale = rand($decimal_digits, $scale); // @see "Example #1 Calculate a random floating-point number" in diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php index b6d7a283830..3ca798a5be4 100644 --- a/core/lib/Drupal/Core/Field/WidgetBase.php +++ b/core/lib/Drupal/Core/Field/WidgetBase.php @@ -658,10 +658,11 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface, * The location of processing information within $form_state. */ protected static function getWidgetStateParents(array $parents, $field_name) { + // phpcs:disable Drupal.Files.LineLength // Field processing data is placed at - // phpcs:ignore Drupal.Files.LineLength - // $form_state->get(['field_storage', '#parents', ...$parents..., '#fields', $field_name]), + // "$form_state->get(['field_storage', '#parents', ...$parents..., '#fields', $field_name])" // to avoid clashes between field names and $parents parts. + // phpcs:enable return array_merge(['field_storage', '#parents'], $parents, ['#fields', $field_name]); } diff --git a/core/lib/Drupal/Core/FileTransfer/FTPExtension.php b/core/lib/Drupal/Core/FileTransfer/FTPExtension.php index 8c22591984b..9871b1907d2 100644 --- a/core/lib/Drupal/Core/FileTransfer/FTPExtension.php +++ b/core/lib/Drupal/Core/FileTransfer/FTPExtension.php @@ -132,7 +132,7 @@ class FTPExtension extends FTP implements ChmodInterface { if ($this->isDirectory($path) && $recursive) { $file_list = @ftp_nlist($this->connection, $path); if (!$file_list) { - // Empty directory - returns false + // Empty directory - returns false. return; } foreach ($file_list as $file) { diff --git a/core/lib/Drupal/Core/FileTransfer/Local.php b/core/lib/Drupal/Core/FileTransfer/Local.php index 87dd544c416..28c6b5cca99 100644 --- a/core/lib/Drupal/Core/FileTransfer/Local.php +++ b/core/lib/Drupal/Core/FileTransfer/Local.php @@ -38,7 +38,7 @@ class Local extends FileTransfer implements ChmodInterface { * {@inheritdoc} */ public function connect() { - // No-op + // No-op. } /** diff --git a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php index 5be51f9ca8b..9d9fec5feaa 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteConfigureForm.php @@ -86,7 +86,7 @@ class SiteConfigureForm extends ConfigFormBase { global $install_state; $form['#title'] = $this->t('Configure site'); - // Warn about settings.php permissions risk + // Warn about settings.php permissions risk. $settings_dir = $this->sitePath; $settings_file = $settings_dir . '/settings.php'; // Check that $_POST is empty so we only show this message when the form is diff --git a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php index 586195082a5..6d34a92c8ba 100644 --- a/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php +++ b/core/lib/Drupal/Core/Installer/Form/SiteSettingsForm.php @@ -255,7 +255,7 @@ class SiteSettingsForm extends FormBase { // configure one. if (empty(Settings::get('config_sync_directory'))) { if (empty($install_state['config_install_path'])) { - // Add a randomized config directory name to settings.php + // Add a randomized config directory name to settings.php. $config_sync_directory = $this->createRandomConfigDirectory(); } else { diff --git a/core/lib/Drupal/Core/Recipe/Recipe.php b/core/lib/Drupal/Core/Recipe/Recipe.php index 1eb42b79343..aa539c1c70c 100644 --- a/core/lib/Drupal/Core/Recipe/Recipe.php +++ b/core/lib/Drupal/Core/Recipe/Recipe.php @@ -209,7 +209,7 @@ final class Recipe { ]), ], // The `prompt` and `form` elements, though optional, have their - // own sets of constraints, + // own sets of constraints. 'prompt' => new Optional([ new Collection([ 'method' => [ diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php index 6bb9fb6b188..5d25a5176c9 100644 --- a/core/lib/Drupal/Core/Render/Renderer.php +++ b/core/lib/Drupal/Core/Render/Renderer.php @@ -200,7 +200,7 @@ class Renderer implements RendererInterface { * {@inheritdoc} */ public function renderPlaceholder($placeholder, array $elements) { - // Get the render array for the given placeholder + // Get the render array for the given placeholder. $placeholder_element = $elements['#attached']['placeholders'][$placeholder]; $markup = $this->doRenderPlaceholder($placeholder_element); return $this->doReplacePlaceholder($placeholder, $markup, $elements, $placeholder_element); @@ -753,7 +753,7 @@ class Renderer implements RendererInterface { $message_placeholders[] = $placeholder; } else { - // Get the render array for the given placeholder + // Get the render array for the given placeholder. $fibers[$placeholder] = new \Fiber(function () use ($placeholder_element) { return [$this->doRenderPlaceholder($placeholder_element), $placeholder_element]; }); diff --git a/core/lib/Drupal/Core/Routing/UrlGenerator.php b/core/lib/Drupal/Core/Routing/UrlGenerator.php index 0133cf17254..bf224d90880 100644 --- a/core/lib/Drupal/Core/Routing/UrlGenerator.php +++ b/core/lib/Drupal/Core/Routing/UrlGenerator.php @@ -184,7 +184,7 @@ class UrlGenerator implements UrlGeneratorInterface { $variables = array_flip($variables); $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); - // All params must be given + // All params must be given. if ($diff = array_diff_key($variables, $mergedParams)) { throw new MissingMandatoryParametersException($name, array_keys($diff)); } @@ -217,7 +217,7 @@ class UrlGenerator implements UrlGeneratorInterface { foreach ($tokens as $token) { if ('variable' === $token[0]) { if (!$optional || !array_key_exists($token[3], $defaults) || (isset($mergedParams[$token[3]]) && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]])) { - // Check requirement + // Check requirement. if (!preg_match('#^' . $token[2] . '$#', $mergedParams[$token[3]])) { $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]); throw new InvalidParameterException($message); @@ -228,7 +228,7 @@ class UrlGenerator implements UrlGeneratorInterface { } } else { - // Static text + // Static text. $url = $token[1] . $url; $optional = FALSE; } @@ -330,7 +330,7 @@ class UrlGenerator implements UrlGeneratorInterface { // http://tools.ietf.org/html/rfc3986#section-3.3 so we need to encode // them as they are not used for this purpose here otherwise we would // generate a URI that, when followed by a user agent (e.g. browser), does - // not match this route + // not match this route. $path = strtr($path, ['/../' => '/%2E%2E/', '/./' => '/%2E/']); if (str_ends_with($path, '/..')) { $path = substr($path, 0, -2) . '%2E%2E'; diff --git a/core/lib/Drupal/Core/StreamWrapper/LocalReadOnlyStream.php b/core/lib/Drupal/Core/StreamWrapper/LocalReadOnlyStream.php index 29277393ff1..5fc9a4fca38 100644 --- a/core/lib/Drupal/Core/StreamWrapper/LocalReadOnlyStream.php +++ b/core/lib/Drupal/Core/StreamWrapper/LocalReadOnlyStream.php @@ -57,7 +57,7 @@ abstract class LocalReadOnlyStream extends LocalStream { * @see http://php.net/manual/streamwrapper.stream-lock.php */ public function stream_lock($operation) { - // Disallow exclusive lock or non-blocking lock requests + // Disallow exclusive lock or non-blocking lock requests. if (in_array($operation, [LOCK_EX, LOCK_EX | LOCK_NB])) { trigger_error('stream_lock() exclusive lock operations not supported for read-only stream wrappers', E_USER_WARNING); return FALSE; diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php index 5afa135d026..4b4fd068f89 100644 --- a/core/lib/Drupal/Core/Template/TwigExtension.php +++ b/core/lib/Drupal/Core/Template/TwigExtension.php @@ -100,7 +100,7 @@ class TwigExtension extends AbstractExtension { // This function will receive a renderable array, if an array is detected. new TwigFunction('render_var', [$this, 'renderVar']), // The URL and path function are defined in close parallel to those found - // in \Symfony\Bridge\Twig\Extension\RoutingExtension + // in \Symfony\Bridge\Twig\Extension\RoutingExtension. new TwigFunction('url', [$this, 'getUrl'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), new TwigFunction('path', [$this, 'getPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), new TwigFunction('link', [$this, 'getLink']), diff --git a/core/lib/Drupal/Core/Test/TestRun.php b/core/lib/Drupal/Core/Test/TestRun.php index 5214093ce49..4d0e19e19f8 100644 --- a/core/lib/Drupal/Core/Test/TestRun.php +++ b/core/lib/Drupal/Core/Test/TestRun.php @@ -174,7 +174,7 @@ class TestRun { foreach (file($error_log_path) as $line) { if (preg_match('/\[.*?\] (.*?): (.*?) in (.*) on line (\d+)/', $line, $match)) { // Parse PHP fatal errors for example: PHP Fatal error: Call to - // undefined function break_me() in /path/to/file.php on line 17 + // undefined function break_me() in /path/to/file.php on line 17. $this->insertLogEntry([ 'test_class' => $test_class, 'status' => 'fail', diff --git a/core/lib/Drupal/Core/Test/TestStatus.php b/core/lib/Drupal/Core/Test/TestStatus.php index 91689eb0733..09dbdb5c21b 100644 --- a/core/lib/Drupal/Core/Test/TestStatus.php +++ b/core/lib/Drupal/Core/Test/TestStatus.php @@ -55,7 +55,7 @@ class TestStatus { static::ERROR => 'error', static::SYSTEM => 'exception', ]; - // For status 3 and higher, we want 'exception.' + // For status 3 and higher, we want 'exception'. $label = $statusMap[$status > static::SYSTEM ? static::SYSTEM : $status]; return $label; } diff --git a/core/lib/Drupal/Core/Theme/ThemeInitialization.php b/core/lib/Drupal/Core/Theme/ThemeInitialization.php index 10f173a15e7..7ea13f67ade 100644 --- a/core/lib/Drupal/Core/Theme/ThemeInitialization.php +++ b/core/lib/Drupal/Core/Theme/ThemeInitialization.php @@ -137,7 +137,7 @@ class ThemeInitialization implements ThemeInitializationInterface { $active_theme->getExtension()->load(); } else { - // Include non-engine theme files + // Include non-engine theme files. foreach (array_reverse($active_theme->getBaseThemeExtensions()) as $base) { // Include the theme file or the engine. if ($base->owner) { @@ -222,10 +222,10 @@ class ThemeInitialization implements ThemeInitializationInterface { } } - // Do basically the same as the above for libraries + // Do basically the same as the above for libraries. $values['libraries'] = []; - // Grab libraries from base theme + // Grab libraries from base theme. foreach ($base_themes as $base) { if (!empty($base->libraries)) { foreach ($base->libraries as $library) { diff --git a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php index 29efd63f7e4..71f939e220e 100644 --- a/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php +++ b/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php @@ -184,7 +184,7 @@ class RecursiveContextualValidator implements ContextualValidatorInterface { protected function validateConstraints($value, $cache_key, $constraints) { foreach ($constraints as $constraint) { // Prevent duplicate validation of constraints, in the case - // that constraints belong to multiple validated groups + // that constraints belong to multiple validated groups. if (isset($cache_key)) { $constraint_hash = spl_object_hash($constraint); diff --git a/core/lib/Drupal/Core/Utility/Token.php b/core/lib/Drupal/Core/Utility/Token.php index c139cbf05c3..6e44238c8fa 100644 --- a/core/lib/Drupal/Core/Utility/Token.php +++ b/core/lib/Drupal/Core/Utility/Token.php @@ -305,7 +305,8 @@ class Token { // Iterate through the matches, building an associative array containing // $tokens grouped by $types, pointing to the version of the token found in - // the source text. For example, $results['node']['title'] = '[node:title]'; + // the source text. For example, + // "$results['node']['title'] = '[node:title]'". $results = []; for ($i = 0; $i < count($tokens); $i++) { $results[$types[$i]][$tokens[$i]] = $matches[0][$i]; diff --git a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php index 857e2c1b099..1e69f1bfc7f 100644 --- a/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php +++ b/core/lib/Drupal/Core/Validation/Plugin/Validation/Constraint/UniqueFieldValueValidator.php @@ -158,7 +158,7 @@ class UniqueFieldValueValidator extends ConstraintValidator implements Container private function extractDuplicates(array $item_values): array { $value_frequency = array_count_values($item_values); - // Filter out item values which are not duplicates while preserving deltas + // Filter out item values which are not duplicates while preserving deltas. $duplicate_values = array_intersect($item_values, array_keys(array_filter( $value_frequency, function ($value) { return $value > 1; diff --git a/core/modules/announcements_feed/config/schema/announcements_feed.schema.yml b/core/modules/announcements_feed/config/schema/announcements_feed.schema.yml index 416ad458020..b338b925822 100644 --- a/core/modules/announcements_feed/config/schema/announcements_feed.schema.yml +++ b/core/modules/announcements_feed/config/schema/announcements_feed.schema.yml @@ -8,17 +8,14 @@ announcements_feed.settings: type: integer label: 'Cache announcements for max-age seconds.' constraints: - Range: - min: 0 + PositiveOrZero: ~ cron_interval: type: integer label: 'Cron interval for fetching announcements in seconds.' constraints: - Range: - min: 0 + PositiveOrZero: ~ limit: type: integer label: 'Number of announcements that will be displayed.' constraints: - Range: - min: 0 + PositiveOrZero: ~ diff --git a/core/modules/automated_cron/config/schema/automated_cron.schema.yml b/core/modules/automated_cron/config/schema/automated_cron.schema.yml index 810ae0ed8d7..aee2c4df47f 100644 --- a/core/modules/automated_cron/config/schema/automated_cron.schema.yml +++ b/core/modules/automated_cron/config/schema/automated_cron.schema.yml @@ -10,5 +10,4 @@ automated_cron.settings: type: integer label: 'Run cron every' constraints: - Range: - min: 0 + PositiveOrZero: ~ diff --git a/core/modules/big_pipe/big_pipe.module b/core/modules/big_pipe/big_pipe.module deleted file mode 100644 index d04104799cd..00000000000 --- a/core/modules/big_pipe/big_pipe.module +++ /dev/null @@ -1,45 +0,0 @@ -<?php - -/** - * @file - */ - -/** - * Implements hook_theme_suggestions_HOOK(). - */ -function big_pipe_theme_suggestions_big_pipe_interface_preview(array $variables): array { - $common_callbacks_simplified_suggestions = [ - 'Drupal_block_BlockViewBuilder__lazyBuilder' => 'block', - ]; - - $suggestions = []; - $suggestion = 'big_pipe_interface_preview'; - if ($variables['callback']) { - $callback = preg_replace('/[^a-zA-Z0-9]/', '_', $variables['callback']); - if (is_array($callback)) { - $callback = implode('__', $callback); - } - - // Use simplified template suggestion, if any. - // For example, this simplifies - // phpcs:ignore Drupal.Files.LineLength - // big-pipe-interface-preview--Drupal-block-BlockViewBuilder--lazyBuilder--<BLOCK ID>.html.twig - // to - // big-pipe-interface-preview--block--<BLOCK ID>.html.twig - if (isset($common_callbacks_simplified_suggestions[$callback])) { - $callback = $common_callbacks_simplified_suggestions[$callback]; - } - - $suggestions[] = $suggestion .= '__' . $callback; - if (is_array($variables['arguments'])) { - $arguments = preg_replace('/[^a-zA-Z0-9]/', '_', $variables['arguments']); - foreach ($arguments as $argument) { - if (empty($argument)) { - continue; - } - $suggestions[] = $suggestion . '__' . $argument; - } - } - } - return $suggestions; -} diff --git a/core/modules/big_pipe/src/Hook/BigPipeThemeHooks.php b/core/modules/big_pipe/src/Hook/BigPipeThemeHooks.php new file mode 100644 index 00000000000..5bced86d68d --- /dev/null +++ b/core/modules/big_pipe/src/Hook/BigPipeThemeHooks.php @@ -0,0 +1,50 @@ +<?php + +namespace Drupal\big_pipe\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for big_pipe. + */ +class BigPipeThemeHooks { + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_big_pipe_interface_preview')] + public function themeSuggestionsBigPipeInterfacePreview(array $variables): array { + $common_callbacks_simplified_suggestions = [ + 'Drupal_block_BlockViewBuilder__lazyBuilder' => 'block', + ]; + $suggestions = []; + $suggestion = 'big_pipe_interface_preview'; + if ($variables['callback']) { + $callback = preg_replace('/[^a-zA-Z0-9]/', '_', $variables['callback']); + if (is_array($callback)) { + $callback = implode('__', $callback); + } + // Use simplified template suggestion, if any. + // For example, this simplifies + // phpcs:ignore Drupal.Files.LineLength + // big-pipe-interface-preview--Drupal-block-BlockViewBuilder--lazyBuilder--<BLOCK ID>.html.twig + // to + // big-pipe-interface-preview--block--<BLOCK ID>.html.twig. + if (isset($common_callbacks_simplified_suggestions[$callback])) { + $callback = $common_callbacks_simplified_suggestions[$callback]; + } + $suggestions[] = $suggestion .= '__' . $callback; + if (is_array($variables['arguments'])) { + $arguments = preg_replace('/[^a-zA-Z0-9]/', '_', $variables['arguments']); + foreach ($arguments as $argument) { + if (empty($argument)) { + continue; + } + $suggestions[] = $suggestion . '__' . $argument; + } + } + } + return $suggestions; + } + +} diff --git a/core/modules/big_pipe/tests/modules/big_pipe_test/src/BigPipePlaceholderTestCases.php b/core/modules/big_pipe/tests/modules/big_pipe_test/src/BigPipePlaceholderTestCases.php index 48471501c40..b36cd0a0929 100644 --- a/core/modules/big_pipe/tests/modules/big_pipe_test/src/BigPipePlaceholderTestCases.php +++ b/core/modules/big_pipe/tests/modules/big_pipe_test/src/BigPipePlaceholderTestCases.php @@ -366,7 +366,7 @@ class BigPipePlaceholderTestCases { ]; $exception->embeddedHtmlResponse = NULL; - // cSpell:disable-next-line. + // cSpell:disable-next-line $token = 'PxOHfS_QL-T01NjBgu7Z7I04tIwMp6La5vM-mVxezbU'; // 8. Edge case: response filter throwing an exception for this placeholder. $embedded_response_exception = new BigPipePlaceholderTestCase( diff --git a/core/modules/big_pipe/tests/src/Kernel/BigPipeInterfacePreviewThemeSuggestionsTest.php b/core/modules/big_pipe/tests/src/Kernel/BigPipeInterfacePreviewThemeSuggestionsTest.php index 73ccd3144f1..c2e4ab9782b 100644 --- a/core/modules/big_pipe/tests/src/Kernel/BigPipeInterfacePreviewThemeSuggestionsTest.php +++ b/core/modules/big_pipe/tests/src/Kernel/BigPipeInterfacePreviewThemeSuggestionsTest.php @@ -8,7 +8,7 @@ use Drupal\KernelTests\KernelTestBase; use Drupal\block\Entity\Block; /** - * Tests the big_pipe_theme_suggestions_big_pipe_interface_preview() function. + * Tests the big pipe theme suggestions. * * @group big_pipe */ @@ -58,7 +58,7 @@ class BigPipeInterfacePreviewThemeSuggestionsTest extends KernelTestBase { } /** - * Tests template suggestions from big_pipe_theme_suggestions_big_pipe_interface_preview(). + * Tests theme suggestions from big_pipe. */ public function testBigPipeThemeHookSuggestions(): void { $entity = $this->controller->create([ @@ -77,10 +77,11 @@ class BigPipeInterfacePreviewThemeSuggestionsTest extends KernelTestBase { $variables = []; // In turn this is what createBigPipeJsPlaceholder() uses to // build the BigPipe JS placeholder render array which is used as input - // for big_pipe_theme_suggestions_big_pipe_interface_preview(). + // for big_pipe theme suggestions(). $variables['callback'] = $build['#lazy_builder'][0]; $variables['arguments'] = $build['#lazy_builder'][1]; - $suggestions = big_pipe_theme_suggestions_big_pipe_interface_preview($variables); + $module_handler = $this->container->get('module_handler'); + $suggestions = $module_handler->invoke('big_pipe', 'theme_suggestions_big_pipe_interface_preview', [$variables]); $suggested_id = preg_replace('/[^a-zA-Z0-9]/', '_', $block->id()); $this->assertSame([ 'big_pipe_interface_preview__block', diff --git a/core/modules/block/block.module b/core/modules/block/block.module index 24e28589491..b5e9f56a465 100644 --- a/core/modules/block/block.module +++ b/core/modules/block/block.module @@ -5,36 +5,6 @@ */ use Drupal\block\Hook\BlockHooks; -use Drupal\Core\Installer\InstallerKernel; - -/** - * Initializes blocks for installed themes. - * - * @param string[] $theme_list - * An array of theme names. - * - * @see block_modules_installed() - */ -function block_themes_installed($theme_list): void { - // Do not create blocks during config sync. - if (\Drupal::service('config.installer')->isSyncing()) { - return; - } - // Disable this functionality prior to install profile installation because - // block configuration is often optional or provided by the install profile - // itself. block_theme_initialize() will be called when the install profile is - // installed. - if (InstallerKernel::installationAttempted() && \Drupal::config('core.extension')->get('module.' . \Drupal::installProfile()) === NULL) { - return; - } - - foreach ($theme_list as $theme) { - // Don't initialize themes that are not displayed in the UI. - if (\Drupal::service('theme_handler')->hasUi($theme)) { - block_theme_initialize($theme); - } - } -} /** * Assigns an initial, default set of blocks for a theme. @@ -75,37 +45,6 @@ function block_theme_initialize($theme): void { } /** - * Implements hook_theme_suggestions_HOOK(). - */ -function block_theme_suggestions_block(array $variables): array { - $suggestions = []; - - $suggestions[] = 'block__' . $variables['elements']['#configuration']['provider']; - // Hyphens (-) and underscores (_) play a special role in theme suggestions. - // Theme suggestions should only contain underscores, because within - // drupal_find_theme_templates(), underscores are converted to hyphens to - // match template file names, and then converted back to underscores to match - // pre-processing and other function names. So if your theme suggestion - // contains a hyphen, it will end up as an underscore after this conversion, - // and your function names won't be recognized. So, we need to convert - // hyphens to underscores in block deltas for the theme suggestions. - - // We can safely explode on : because we know the Block plugin type manager - // enforces that delimiter for all derivatives. - $parts = explode(':', $variables['elements']['#plugin_id']); - $suggestion = 'block'; - while ($part = array_shift($parts)) { - $suggestions[] = $suggestion .= '__' . strtr($part, '-', '_'); - } - - if (!empty($variables['elements']['#id'])) { - $suggestions[] = 'block__' . $variables['elements']['#id']; - } - - return $suggestions; -} - -/** * Prepares variables for block templates. * * Default template: block.html.twig. diff --git a/core/modules/block/src/Hook/BlockHooks.php b/core/modules/block/src/Hook/BlockHooks.php index 802a60bccb1..3dfa51bfebb 100644 --- a/core/modules/block/src/Hook/BlockHooks.php +++ b/core/modules/block/src/Hook/BlockHooks.php @@ -12,6 +12,7 @@ use Drupal\Core\Link; use Drupal\Core\Url; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Hook\Attribute\Hook; +use Drupal\Core\Installer\InstallerKernel; /** * Hook implementations for block. @@ -148,7 +149,7 @@ class BlockHooks { /** * Implements hook_modules_installed(). * - * @see block_themes_installed() + * @see BlockHooks::themesInstalled() */ #[Hook('modules_installed')] public function modulesInstalled($modules, bool $is_syncing): void { @@ -170,6 +171,38 @@ class BlockHooks { } /** + * Implements hook_themes_installed(). + * + * Initializes blocks for installed themes. + * + * @param string[] $theme_list + * An array of theme names. + * + * @see BlockHooks::modulesInstalled() + */ + #[Hook('themes_installed')] + public function themesInstalled($theme_list): void { + // Do not create blocks during config sync. + if (\Drupal::service('config.installer')->isSyncing()) { + return; + } + // Disable this functionality prior to install profile installation because + // block configuration is often optional or provided by the install profile + // itself. block_theme_initialize() will be called when the install profile + // is installed. + if (InstallerKernel::installationAttempted() && \Drupal::config('core.extension')->get('module.' . \Drupal::installProfile()) === NULL) { + return; + } + + foreach ($theme_list as $theme) { + // Don't initialize themes that are not displayed in the UI. + if (\Drupal::service('theme_handler')->hasUi($theme)) { + block_theme_initialize($theme); + } + } + } + + /** * Implements hook_rebuild(). */ #[Hook('rebuild')] diff --git a/core/modules/block/src/Hook/BlockThemeHooks.php b/core/modules/block/src/Hook/BlockThemeHooks.php new file mode 100644 index 00000000000..8b5d34fff83 --- /dev/null +++ b/core/modules/block/src/Hook/BlockThemeHooks.php @@ -0,0 +1,40 @@ +<?php + +namespace Drupal\block\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for block. + */ +class BlockThemeHooks { + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_block')] + public function themeSuggestionsBlock(array $variables): array { + $suggestions = []; + $suggestions[] = 'block__' . $variables['elements']['#configuration']['provider']; + // Hyphens (-) and underscores (_) play a special role in theme + // suggestions. Theme suggestions should only contain underscores, because + // within drupal_find_theme_templates(), underscores are converted to + // hyphens to match template file names, and then converted back to + // underscores to match pre-processing and other function names. So if your + // theme suggestion contains a hyphen, it will end up as an underscore + // after this conversion, and your function names won't be recognized. So, + // we need to convert hyphens to underscores in block deltas for the theme + // suggestions. We can safely explode on : because we know the Block plugin + // type manager enforces that delimiter for all derivatives. + $parts = explode(':', $variables['elements']['#plugin_id']); + $suggestion = 'block'; + while ($part = array_shift($parts)) { + $suggestions[] = $suggestion .= '__' . strtr($part, '-', '_'); + } + if (!empty($variables['elements']['#id'])) { + $suggestions[] = 'block__' . $variables['elements']['#id']; + } + return $suggestions; + } + +} diff --git a/core/modules/block/tests/src/FunctionalJavascript/BlockAddTest.php b/core/modules/block/tests/src/FunctionalJavascript/BlockAddTest.php index 84d1960c399..1f92a4fdcc1 100644 --- a/core/modules/block/tests/src/FunctionalJavascript/BlockAddTest.php +++ b/core/modules/block/tests/src/FunctionalJavascript/BlockAddTest.php @@ -52,7 +52,7 @@ class BlockAddTest extends WebDriverTestBase { $assert_session->elementTextContains('css', '.vertical-tabs__menu-item-title', 'Response status'); $assert_session->elementTextNotContains('css', '.vertical-tabs__menu-item-title', $summary_text); - // Search for the "Pages" tab link and click it + // Search for the "Pages" tab link and click it. $this->getSession()->getPage()->find('css', 'a[href="#edit-visibility-request-path"]')->click(); // Check that the corresponding form section is open and visible. $form_section = $this->getSession()->getPage()->find('css', '#edit-visibility-request-path'); diff --git a/core/modules/block/tests/src/Kernel/BlockTemplateSuggestionsTest.php b/core/modules/block/tests/src/Kernel/BlockTemplateSuggestionsTest.php index 049b9f74ccc..7fd894a85bb 100644 --- a/core/modules/block/tests/src/Kernel/BlockTemplateSuggestionsTest.php +++ b/core/modules/block/tests/src/Kernel/BlockTemplateSuggestionsTest.php @@ -8,7 +8,7 @@ use Drupal\block\Entity\Block; use Drupal\KernelTests\KernelTestBase; /** - * Tests the block_theme_suggestions_block() function. + * Tests the block theme suggestions. * * @group block */ @@ -23,7 +23,7 @@ class BlockTemplateSuggestionsTest extends KernelTestBase { ]; /** - * Tests template suggestions from block_theme_suggestions_block(). + * Tests template suggestions from the block module. */ public function testBlockThemeHookSuggestions(): void { $this->installConfig(['system']); @@ -44,7 +44,8 @@ class BlockTemplateSuggestionsTest extends KernelTestBase { $variables['elements']['#base_plugin_id'] = $plugin->getBaseId(); $variables['elements']['#derivative_plugin_id'] = $plugin->getDerivativeId(); $variables['elements']['content'] = []; - $suggestions = block_theme_suggestions_block($variables); + $module_handler = $this->container->get('module_handler'); + $suggestions = $module_handler->invoke('block', 'theme_suggestions_block', [$variables]); $this->assertSame([ 'block__system', 'block__system_menu_block', diff --git a/core/modules/block/tests/src/Kernel/BlockViewBuilderTest.php b/core/modules/block/tests/src/Kernel/BlockViewBuilderTest.php index 377cd31deac..a6b66adee2b 100644 --- a/core/modules/block/tests/src/Kernel/BlockViewBuilderTest.php +++ b/core/modules/block/tests/src/Kernel/BlockViewBuilderTest.php @@ -348,17 +348,17 @@ class BlockViewBuilderTest extends KernelTestBase { $required_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']; - // Check that the expected cacheability metadata is present in: - // - the built render array; + // Check that the expected cacheability metadata is present in the built + // render array. $build = $this->getBlockRenderArray(); $this->assertSame($expected_keys, $build['#cache']['keys']); $this->assertEqualsCanonicalizing($expected_contexts, $build['#cache']['contexts']); $this->assertEqualsCanonicalizing($expected_tags, $build['#cache']['tags']); $this->assertSame($expected_max_age, $build['#cache']['max-age']); $this->assertFalse(isset($build['#create_placeholder'])); - // - the rendered render array; + // And also in the rendered render array. $this->renderer->renderRoot($build); - // - the render cache item. + // And also in the render cache item. $final_cache_contexts = Cache::mergeContexts($expected_contexts, $required_cache_contexts); $cache_item = $cache_bin->get($expected_keys, CacheableMetadata::createFromRenderArray($build)); $this->assertNotEmpty($cache_item, 'The block render element has been cached with the expected cache keys.'); diff --git a/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php b/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php index 871af6072fd..e36eaebfbda 100644 --- a/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php +++ b/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php @@ -72,7 +72,7 @@ class BlockPageVariantTest extends UnitTestCase { public static function providerBuild() { $blocks_config = [ 'block1' => [ - // region, is main content block, is messages block, is title block + // region, is main content block, is messages block, is title block. 'top', FALSE, FALSE, FALSE, ], // Test multiple blocks in the same region. diff --git a/core/modules/block_content/tests/modules/block_content_theme_suggestions_test/block_content_theme_suggestions_test.module b/core/modules/block_content/tests/modules/block_content_theme_suggestions_test/block_content_theme_suggestions_test.module deleted file mode 100644 index 8df5abdcd55..00000000000 --- a/core/modules/block_content/tests/modules/block_content_theme_suggestions_test/block_content_theme_suggestions_test.module +++ /dev/null @@ -1,20 +0,0 @@ -<?php - -/** - * @file - * Support module for testing. - */ - -declare(strict_types=1); - -use Drupal\block_content\BlockContentInterface; - -/** - * Implements hook_preprocess_block(). - */ -function block_content_theme_suggestions_test_preprocess_block(&$variables): void { - $block_content = $variables['elements']['content']['#block_content'] ?? NULL; - if ($block_content instanceof BlockContentInterface) { - $variables['label'] = $block_content->label(); - } -} diff --git a/core/modules/block_content/tests/modules/block_content_theme_suggestions_test/src/Hook/BlockContentThemeSuggestionsTestThemeHooks.php b/core/modules/block_content/tests/modules/block_content_theme_suggestions_test/src/Hook/BlockContentThemeSuggestionsTestThemeHooks.php new file mode 100644 index 00000000000..ec999172c83 --- /dev/null +++ b/core/modules/block_content/tests/modules/block_content_theme_suggestions_test/src/Hook/BlockContentThemeSuggestionsTestThemeHooks.php @@ -0,0 +1,26 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\block_content_theme_suggestions_test\Hook; + +use Drupal\block_content\BlockContentInterface; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for block_content_theme_suggestions_test. + */ +class BlockContentThemeSuggestionsTestThemeHooks { + + /** + * Implements hook_preprocess_block(). + */ + #[Hook('preprocess_block')] + public function preprocessBlock(&$variables): void { + $block_content = $variables['elements']['content']['#block_content'] ?? NULL; + if ($block_content instanceof BlockContentInterface) { + $variables['label'] = $block_content->label(); + } + } + +} diff --git a/core/modules/block_content/tests/src/Functional/BlockContentCreationTest.php b/core/modules/block_content/tests/src/Functional/BlockContentCreationTest.php index 364b5f4524d..e0f77406bb9 100644 --- a/core/modules/block_content/tests/src/Functional/BlockContentCreationTest.php +++ b/core/modules/block_content/tests/src/Functional/BlockContentCreationTest.php @@ -106,7 +106,7 @@ class BlockContentCreationTest extends BlockContentTestBase { $this->drupalGet('block/add/basic'); $this->submitForm($edit, 'Save and configure'); - // Save our block permanently + // Save our block permanently. $this->submitForm(['region' => 'content'], 'Save block'); // Set test_view_mode as a custom display to be available on the list. diff --git a/core/modules/ckeditor5/ckeditor5.ckeditor5.yml b/core/modules/ckeditor5/ckeditor5.ckeditor5.yml index 7624fbfd708..d7ad4e12e48 100644 --- a/core/modules/ckeditor5/ckeditor5.ckeditor5.yml +++ b/core/modules/ckeditor5/ckeditor5.ckeditor5.yml @@ -394,11 +394,8 @@ ckeditor5_list: plugins: - list.List - list.ListProperties - config: - list: - properties: - # @todo Make this configurable in https://www.drupal.org/project/drupal/issues/3274635 - styles: false + # @see \Drupal\ckeditor5\Plugin\CKEditor5Plugin\ListPlugin::getDynamicPluginConfig() + config: {} drupal: label: List library: core/ckeditor5.list @@ -414,6 +411,8 @@ ckeditor5_list: - <ol> - <ol reversed start> - <li> + - <ol type> + - <ul type> ckeditor5_horizontalLine: ckeditor5: diff --git a/core/modules/ckeditor5/ckeditor5.post_update.php b/core/modules/ckeditor5/ckeditor5.post_update.php index db795a147d0..5b60cf18a3e 100644 --- a/core/modules/ckeditor5/ckeditor5.post_update.php +++ b/core/modules/ckeditor5/ckeditor5.post_update.php @@ -6,6 +6,8 @@ */ // cspell:ignore multiblock +use Drupal\Core\Config\Entity\ConfigEntityUpdater; +use Drupal\editor\Entity\Editor; /** * Implements hook_removed_post_updates(). @@ -20,3 +22,21 @@ function ckeditor5_removed_post_updates(): array { 'ckeditor5_post_update_list_start_reversed' => '11.0.0', ]; } + +/** + * Updates Text Editors using CKEditor 5 to native List "type" functionality. + */ +function ckeditor5_post_update_list_type(array &$sandbox = []): void { + $config_entity_updater = \Drupal::classResolver(ConfigEntityUpdater::class); + $config_entity_updater->update($sandbox, 'editor', function (Editor $editor): bool { + // Only try to update editors using CKEditor 5. + if ($editor->getEditor() !== 'ckeditor5') { + return FALSE; + } + $settings = $editor->getSettings(); + + // @see Ckeditor5Hooks::editorPresave() + return array_key_exists('ckeditor5_list', $settings['plugins']) + && array_key_exists('ckeditor5_sourceEditing', $settings['plugins']); + }); +} diff --git a/core/modules/ckeditor5/config/schema/ckeditor5.schema.yml b/core/modules/ckeditor5/config/schema/ckeditor5.schema.yml index 68344494841..3ec380d4fe6 100644 --- a/core/modules/ckeditor5/config/schema/ckeditor5.schema.yml +++ b/core/modules/ckeditor5/config/schema/ckeditor5.schema.yml @@ -142,14 +142,22 @@ ckeditor5.plugin.ckeditor5_list: mapping: reversed: type: boolean + # @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol#reversed label: 'Allow reverse list' constraints: NotNull: [] startIndex: type: boolean + # @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol#start label: 'Allow start index' constraints: NotNull: [] + styles: + type: boolean + # @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol#type + label: 'Allow list style type' + constraints: + NotNull: [] multiBlock: type: boolean label: 'Allow blocks to be created in list items' diff --git a/core/modules/ckeditor5/js/ckeditor5.js b/core/modules/ckeditor5/js/ckeditor5.js index f5af26de838..de97e49a77d 100644 --- a/core/modules/ckeditor5/js/ckeditor5.js +++ b/core/modules/ckeditor5/js/ckeditor5.js @@ -324,7 +324,6 @@ const addedCss = [ `${prefix} .ck.ck-content * {display:revert;background:revert;color:initial;padding:revert;}`, `${prefix} .ck.ck-content li {display:list-item}`, - `${prefix} .ck.ck-content ol li {list-style-type: decimal}`, ]; const prefixedCss = [...addedCss].join('\n'); @@ -625,6 +624,30 @@ }, }; + Drupal.behaviors.editorStyleFix = { + attach(context) { + // CKEditor's DLL injects a style tag that overrides native list + // type styling. The following find the style(s) causing the problem + // and removes them. + // @todo remove this entire behavior when this issue is fixed + // https://github.com/ckeditor/ckeditor5/issues/14613 + [...document.styleSheets] + .filter((sheet) => sheet.ownerNode.hasAttribute('data-cke')) + .forEach((sheet) => { + [...sheet.cssRules].forEach((rule, ruleIndex) => { + if ( + rule?.selectorText && + (rule.selectorText.includes(' ol') || + rule.selectorText.includes(' ul')) && + !rule.selectorText.includes('type') + ) { + sheet.cssRules[ruleIndex].style['list-style-type'] = null; + } + }); + }); + }, + }; + // Redirect on hash change when the original hash has an associated CKEditor 5. function redirectTextareaFragmentToCKEditor5Instance() { const hash = window.location.hash.substring(1); diff --git a/core/modules/ckeditor5/src/HTMLRestrictions.php b/core/modules/ckeditor5/src/HTMLRestrictions.php index e10e81ef46d..1d3c15298d3 100644 --- a/core/modules/ckeditor5/src/HTMLRestrictions.php +++ b/core/modules/ckeditor5/src/HTMLRestrictions.php @@ -492,7 +492,7 @@ final class HTMLRestrictions { } // When allowing all tags on an attribute, transform FilterHtml output from - // ['tag' => ['*'=> TRUE]] to ['tag' => TRUE] + // "['tag' => ['*'=> TRUE]]" to "['tag' => TRUE]". $allowed = $restrictions['allowed']; foreach ($allowed as $element => $attributes) { if (is_array($attributes) && isset($attributes['*']) && $attributes['*'] === TRUE) { @@ -580,7 +580,7 @@ final class HTMLRestrictions { } // When allowing all tags on an attribute, transform FilterHtml output from - // ['tag' => ['*'=> TRUE]] to ['tag' => TRUE] + // "['tag' => ['*'=> TRUE]]" to "['tag' => TRUE]". foreach ($allowed_elements as $element => $attributes) { if (is_array($attributes) && isset($attributes['*']) && $attributes['*'] === TRUE) { $allowed_elements[$element] = TRUE; diff --git a/core/modules/ckeditor5/src/Hook/Ckeditor5Hooks.php b/core/modules/ckeditor5/src/Hook/Ckeditor5Hooks.php index 7eb7601e3d8..adae3e8ebdd 100644 --- a/core/modules/ckeditor5/src/Hook/Ckeditor5Hooks.php +++ b/core/modules/ckeditor5/src/Hook/Ckeditor5Hooks.php @@ -6,12 +6,14 @@ use Drupal\Core\Hook\Order\OrderAfter; use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Asset\AttachedAssetsInterface; use Drupal\Core\Render\Element; +use Drupal\ckeditor5\HTMLRestrictions; use Drupal\ckeditor5\Plugin\Editor\CKEditor5; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Url; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Hook\Attribute\Hook; +use Drupal\editor\EditorInterface; /** * Hook implementations for ckeditor5. @@ -377,4 +379,41 @@ class Ckeditor5Hooks { $definitions['ckeditor5_valid_pair__format_and_editor']['mapping']['image_upload'] = $definitions['editor.editor.*']['mapping']['image_upload']; } + /** + * Implements hook_ENTITY_TYPE_presave() for editor entities. + */ + #[Hook('editor_presave')] + public function editorPresave(EditorInterface $editor): void { + if ($editor->getEditor() === 'ckeditor5') { + $settings = $editor->getSettings(); + // @see ckeditor5_post_update_list_type() + if (array_key_exists('ckeditor5_list', $settings['plugins']) && array_key_exists('ckeditor5_sourceEditing', $settings['plugins'])) { + $source_edited = HTMLRestrictions::fromString(implode(' ', $settings['plugins']['ckeditor5_sourceEditing']['allowed_tags'])); + $format_restrictions = HTMLRestrictions::fromTextFormat($editor->getFilterFormat()); + + // If neither <ol type> or <ul type> are allowed through Source Editing + // (the only way it could possibly be supported until now), and it is + // not an unrestricted text format (such as "Full HTML"), then set the + // new "styles" setting for the List plugin to false. + $ol_type = HTMLRestrictions::fromString('<ol type>'); + $ul_type = HTMLRestrictions::fromString('<ul type>'); + if (!array_key_exists('styles', $settings['plugins']['ckeditor5_list']['properties'])) { + $settings['plugins']['ckeditor5_list']['properties']['styles'] = + $ol_type->diff($source_edited)->allowsNothing() || + $ul_type->diff($source_edited)->allowsNothing() || + $format_restrictions->isUnrestricted(); + } + + // Update the Source Editing configuration too. + $settings['plugins']['ckeditor5_sourceEditing']['allowed_tags'] = $source_edited + ->diff($ol_type) + ->diff($ul_type) + ->toCKEditor5ElementsArray(); + } + + $editor->setSettings($settings); + + } + } + } diff --git a/core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/ListPlugin.php b/core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/ListPlugin.php index 7be9c85684d..523d55e76cf 100644 --- a/core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/ListPlugin.php +++ b/core/modules/ckeditor5/src/Plugin/CKEditor5Plugin/ListPlugin.php @@ -26,7 +26,11 @@ class ListPlugin extends CKEditor5PluginDefault implements CKEditor5PluginConfig */ public function defaultConfiguration() { return [ - 'properties' => ['reversed' => TRUE, 'startIndex' => TRUE], + 'properties' => [ + 'reversed' => TRUE, + 'startIndex' => TRUE, + 'styles' => TRUE, + ], 'multiBlock' => TRUE, ]; } @@ -50,6 +54,12 @@ class ListPlugin extends CKEditor5PluginDefault implements CKEditor5PluginConfig '#title' => $this->t('Allow the user to create paragraphs in list items (or other block elements)'), '#default_value' => $this->configuration['multiBlock'], ]; + $form['styles'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Allow the user to choose a list style type'), + '#description' => $this->t('Available list style types for ordered lists: letters and Roman numerals instead of only numbers. Available list style types for unordered lists: circles and squares instead of only discs.'), + '#default_value' => $this->configuration['properties']['styles'], + ]; return $form; } @@ -62,6 +72,8 @@ class ListPlugin extends CKEditor5PluginDefault implements CKEditor5PluginConfig $form_state->setValue('reversed', (bool) $form_value); $form_value = $form_state->getValue('startIndex'); $form_state->setValue('startIndex', (bool) $form_value); + $form_value = $form_state->getValue('styles'); + $form_state->setValue('styles', (bool) $form_value); $form_value = $form_state->getValue('multiBlock'); $form_state->setValue('multiBlock', (bool) $form_value); } @@ -72,6 +84,7 @@ class ListPlugin extends CKEditor5PluginDefault implements CKEditor5PluginConfig public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { $this->configuration['properties']['reversed'] = $form_state->getValue('reversed'); $this->configuration['properties']['startIndex'] = $form_state->getValue('startIndex'); + $this->configuration['properties']['styles'] = $form_state->getValue('styles'); $this->configuration['multiBlock'] = $form_state->getValue('multiBlock'); } @@ -79,7 +92,13 @@ class ListPlugin extends CKEditor5PluginDefault implements CKEditor5PluginConfig * {@inheritdoc} */ public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array { - $static_plugin_config['list']['properties'] = $this->getConfiguration()['properties'] + $static_plugin_config['list']['properties']; + $static_plugin_config['list']['properties'] = $this->getConfiguration()['properties']; + // Generate configuration to use `type` attribute-based list styles on <ul> + // and <ol> elements. + // @see https://ckeditor.com/docs/ckeditor5/latest/api/module_list_listconfig-ListPropertiesStyleConfig.html#member-useAttribute + if ($this->getConfiguration()['properties']['styles']) { + $static_plugin_config['list']['properties']['styles'] = ['useAttribute' => TRUE]; + } $static_plugin_config['list']['multiBlock'] = $this->getConfiguration()['multiBlock']; return $static_plugin_config; } @@ -89,6 +108,12 @@ class ListPlugin extends CKEditor5PluginDefault implements CKEditor5PluginConfig */ public function getElementsSubset(): array { $subset = $this->getPluginDefinition()->getElements(); + if (!$this->getConfiguration()['properties']['styles']) { + $subset = array_diff($subset, [ + '<ul type>', + '<ol type>', + ]); + } $subset = array_diff($subset, ['<ol reversed start>']); $reversed_enabled = $this->getConfiguration()['properties']['reversed']; $start_index_enabled = $this->getConfiguration()['properties']['startIndex']; diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5AllowedTagsTest.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5AllowedTagsTest.php index d2187c7ce01..63dfe37555c 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5AllowedTagsTest.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5AllowedTagsTest.php @@ -52,7 +52,7 @@ class CKEditor5AllowedTagsTest extends CKEditor5TestBase { * * @var string */ - protected $defaultElementsAfterUpdatingToCkeditor5 = '<br> <p> <h2 id="jump-*"> <h3 id> <h4 id> <h5 id> <h6 id> <cite> <dl> <dt> <dd> <a hreflang href> <blockquote cite> <ul type> <ol type="1 A I" reversed start> <strong> <em> <code> <li>'; + protected $defaultElementsAfterUpdatingToCkeditor5 = '<br> <p> <h2 id="jump-*"> <h3 id> <h4 id> <h5 id> <h6 id> <cite> <dl> <dt> <dd> <a hreflang href> <blockquote cite> <strong> <em> <code> <ul type> <ol type reversed start> <li>'; /** * Test enabling CKEditor 5 in a way that triggers validation. diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php index 45798b4d3c6..a4102bda453 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/CKEditor5Test.php @@ -566,13 +566,14 @@ JS; ], 'settings' => [ 'toolbar' => [ - 'items' => ['sourceEditing', 'numberedList'], + 'items' => ['sourceEditing', 'numberedList', 'bulletedList'], ], 'plugins' => [ 'ckeditor5_list' => [ 'properties' => [ 'reversed' => FALSE, 'startIndex' => FALSE, + 'styles' => FALSE, ], 'multiBlock' => TRUE, ], @@ -605,7 +606,7 @@ JS; $numbered_list_dropdown_selector = '.ck-splitbutton__arrow'; // Check that there is no dropdown available for the numbered list because - // both reversed and startIndex are FALSE. + // reversed, startIndex and styles are FALSE. $assert_session->elementNotExists('css', $numbered_list_dropdown_selector); // Save content so source content is kept after changing the editor config. $page->pressButton('Save'); @@ -640,6 +641,70 @@ JS; $assert_session->elementExists('css', $reversed_order_button_selector); $assert_session->elementTextEquals('css', $reversed_order_button_selector, 'Reversed order'); $assert_session->elementExists('css', $start_index_element_selector); + + // Enable list style types. + $editor = Editor::load('test_format'); + $settings = $editor->getSettings(); + $settings['plugins']['ckeditor5_list']['properties']['styles'] = TRUE; + $editor->setSettings($settings); + $editor->save(); + $this->getSession()->reload(); + $this->waitForEditor(); + + $list_types = [ + 'ol' => [ + 'Lower-roman' => 'i', + 'Upper-roman' => 'I', + 'Lower-latin' => 'a', + 'Upper-latin' => 'A', + ], + 'ul' => [ + 'Square' => 'square', + 'Disc' => 'disc', + 'Circle' => 'circle', + ], + ]; + + foreach ($list_types as $list_tag => $types) { + foreach ($types as $type => $type_attribute) { + $list_to_edit = $assert_session->waitForElementVisible('css', ".ck-editor__editable_inline > *:first-child"); + $list_to_edit->click(); + + // Open the list type toolbar and choose a type. + $list_button_tip_text = $list_tag === 'ol' ? 'Numbered List' : 'Bulleted List'; + $toolbar_selector = '[aria-label="' . str_replace(' L', ' l', $list_button_tip_text) . ' styles toolbar"]'; + $button_selector = '[data-cke-tooltip-text="' . $list_button_tip_text . '"]'; + $page->find('css', '[aria-expanded="false"]' . $button_selector)->click(); + $open_splitbutton = $assert_session->waitForElementVisible('css', '[aria-expanded="true"]' . $button_selector); + $this->assertNotNull($open_splitbutton, "$list_button_tip_text splitbutton is open"); + $toolbar = $assert_session->waitForElementVisible('css', $toolbar_selector); + $this->assertNotNull($toolbar, "Toolbar for selecting $type is available at $toolbar_selector "); + $toolbar_with_tips = $assert_session->waitForElementVisible('css', $toolbar_selector . ' [data-cke-tooltip-text]'); + $this->assertNotNull($toolbar_with_tips); + $toolbar_buttons = $toolbar->findAll('css', 'button'); + // While this is a bit of an indirect way to find the correct button, it + // accounts for the mixed dash characters and worked better than other + // attempts. + $toolbar_button_tips = array_map(fn($item) => str_replace('–', '-', $item->getAttribute('data-cke-tooltip-text')), $toolbar_buttons); + $this->assertNotFalse(array_search($type, $toolbar_button_tips)); + $toolbar_buttons[array_search($type, $toolbar_button_tips)]->click(); + $widget_selector = '.ck-editor__editable_inline > ' . $list_tag . '[type="' . $type_attribute . '"]'; + $widget = $assert_session->waitForElementVisible('css', $widget_selector); + $this->assertNotNull($widget, "The widget exists at $widget_selector"); + + // Confirm the style applied in-editor is for the type of list chosen. + $list_style_type = $this->getSession()->evaluateScript('window.getComputedStyle(document.querySelector(\'' . $widget_selector . '\')).listStyleType'); + $this->assertSame(str_replace('latin', 'alpha', strtolower($type)), $list_style_type, "The $list_style_type list should have the correct style."); + $page->pressButton('Save'); + + $fe_list_style_type = $this->getSession()->evaluateScript('window.getComputedStyle(document.querySelector(\'' . $list_tag . '[type]\')).listStyleType'); + // Confirm the style applied on the default theme is for the type of + // list chosen. + $this->assertSame(str_replace('latin', 'alpha', strtolower($type)), strtolower($fe_list_style_type)); + $this->drupalGet($edit_url); + $this->waitForEditor(); + } + } } /** diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/MediaTest.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/MediaTest.php index 931a461b41d..a53685e2ecd 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/MediaTest.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/MediaTest.php @@ -103,6 +103,7 @@ class MediaTest extends MediaTestBase { 'properties' => [ 'reversed' => FALSE, 'startIndex' => FALSE, + 'styles' => FALSE, ], 'multiBlock' => TRUE, ]; diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php index 2b2a8484870..ac5596a752a 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php @@ -235,39 +235,6 @@ JS; // Edge case: `style`. // @todo https://www.drupal.org/project/drupal/issues/3304832 - - // Edge case: `type` attribute on lists. - // @todo Remove in https://www.drupal.org/project/drupal/issues/3274635. - 'no numberedList-related additions to the Source Editing configuration' => [ - '<ol type="A"><li>foo</li><li>bar</li></ol>', - '<ol><li>foo</li><li>bar</li></ol>', - '', - ], - '<ol type>' => [ - '<ol type="A"><li>foo</li><li>bar</li></ol>', - '<ol type="A"><li>foo</li><li>bar</li></ol>', - '<ol type>', - ], - '<ol type="A">' => [ - '<ol type="A"><li>foo</li><li>bar</li></ol>', - '<ol type="A"><li>foo</li><li>bar</li></ol>', - '<ol type="A">', - ], - 'no bulletedList-related additions to the Source Editing configuration' => [ - '<ul type="circle"><li>foo</li><li>bar</li></ul>', - '<ul><li>foo</li><li>bar</li></ul>', - '', - ], - '<ul type>' => [ - '<ul type="circle"><li>foo</li><li>bar</li></ul>', - '<ul type="circle"><li>foo</li><li>bar</li></ul>', - '<ul type>', - ], - '<ul type="circle">' => [ - '<ul type="circle"><li>foo</li><li>bar</li></ul>', - '<ul type="circle"><li>foo</li><li>bar</li></ul>', - '<ul type="circle">', - ], ]; } diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTestBase.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTestBase.php index 9442f379ee7..740e4515961 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTestBase.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTestBase.php @@ -87,6 +87,7 @@ abstract class SourceEditingTestBase extends CKEditor5TestBase { 'properties' => [ 'reversed' => FALSE, 'startIndex' => FALSE, + 'styles' => FALSE, ], 'multiBlock' => TRUE, ], diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/StyleTest.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/StyleTest.php index 5e6b90a5d8f..71368486a67 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/StyleTest.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/StyleTest.php @@ -196,6 +196,7 @@ JS; 'properties' => [ 'reversed' => FALSE, 'startIndex' => FALSE, + 'styles' => FALSE, ], 'multiBlock' => TRUE, ], @@ -406,7 +407,7 @@ JS; // Close the dropdown. $style_dropdown->click(); - // Select the <ul> and check the available styles + // Select the <ul> and check the available styles. $this->selectTextInsideElement('ul'); $this->assertSame('Styles', $style_dropdown->getText()); $style_dropdown->click(); @@ -447,7 +448,7 @@ JS; $this->assertTrue($buttons[8]->hasClass('ck-off')); $this->assertSame('Items', $style_dropdown->getText()); - // Select the <ol> and check the available styles + // Select the <ol> and check the available styles. $this->selectTextInsideElement('ol'); $this->assertSame('Styles', $style_dropdown->getText()); $style_dropdown->click(); @@ -488,7 +489,7 @@ JS; $this->assertTrue($buttons[8]->hasClass('ck-off')); $this->assertSame('Steps', $style_dropdown->getText()); - // Select the table and check the available styles + // Select the table and check the available styles. $this->selectTextInsideElement('table td'); $this->assertSame('Styles', $style_dropdown->getText()); $style_dropdown->click(); diff --git a/core/modules/ckeditor5/tests/src/Kernel/ConfigurablePluginTest.php b/core/modules/ckeditor5/tests/src/Kernel/ConfigurablePluginTest.php index 16d571cf980..976e388f3ea 100644 --- a/core/modules/ckeditor5/tests/src/Kernel/ConfigurablePluginTest.php +++ b/core/modules/ckeditor5/tests/src/Kernel/ConfigurablePluginTest.php @@ -94,6 +94,7 @@ class ConfigurablePluginTest extends KernelTestBase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], diff --git a/core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php b/core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php index 2b9d4d1fde8..76818df9f78 100644 --- a/core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php +++ b/core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php @@ -609,6 +609,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -621,8 +622,6 @@ class SmartDefaultSettingsTest extends KernelTestBase { '<span>', '<a hreflang>', '<blockquote cite>', - '<ul type>', - '<ol type>', '<h2 id>', '<h3 id>', '<h4 id>', @@ -656,13 +655,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'status' => [ [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:10:"Basic HTML";s:19:"@missing_attributes";s:90:"<a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:10:"Basic HTML";s:19:"@missing_attributes";s:70:"<a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -684,9 +683,9 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'ckeditor5_list' => $basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_list'], 'ckeditor5_sourceEditing' => [ 'allowed_tags' => array_merge( - array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 0, 9), + array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 0, 7), ['<img data-caption>'], - array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 9), + array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 7), ), ], ], @@ -698,13 +697,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ...$basic_html_test_case['expected_db_logs']['status'], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:10:"Basic HTML";s:19:"@missing_attributes";s:109:"<a hreflang> <blockquote cite> <ul type> <ol type> <img data-caption> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:10:"Basic HTML";s:19:"@missing_attributes";s:89:"<a hreflang> <blockquote cite> <img data-caption> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <img data-caption> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <img data-caption> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -725,9 +724,9 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'ckeditor5_list' => $basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_list'], 'ckeditor5_sourceEditing' => [ 'allowed_tags' => array_merge( - array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 0, 9), + array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 0, 7), ['<img data-align>'], - array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 9), + array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 7), ), ], ], @@ -739,13 +738,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ...$basic_html_test_case['expected_db_logs']['status'], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:10:"Basic HTML";s:19:"@missing_attributes";s:107:"<a hreflang> <blockquote cite> <ul type> <ol type> <img data-align> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:10:"Basic HTML";s:19:"@missing_attributes";s:87:"<a hreflang> <blockquote cite> <img data-align> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <img data-align> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <img data-align> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -764,9 +763,9 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'ckeditor5_list' => $basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_list'], 'ckeditor5_sourceEditing' => [ 'allowed_tags' => array_merge( - array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 0, 9), + array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 0, 7), ['<img data-entity-type data-entity-uuid>'], - array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 9), + array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 7), ), ], ], @@ -785,13 +784,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:34:"Basic HTML (without image uploads)";s:19:"@missing_attributes";s:130:"<a hreflang> <blockquote cite> <ul type> <ol type> <img data-entity-type data-entity-uuid> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:34:"Basic HTML (without image uploads)";s:19:"@missing_attributes";s:110:"<a hreflang> <blockquote cite> <img data-entity-type data-entity-uuid> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <img data-entity-type data-entity-uuid> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <img data-entity-type data-entity-uuid> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -819,6 +818,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -844,13 +844,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:30:"Basic HTML (without H4 and H6)";s:19:"@missing_attributes";s:74:"<a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h5 id>";}', + 'a:2:{s:12:"%text_format";s:30:"Basic HTML (without H4 and H6)";s:19:"@missing_attributes";s:54:"<a hreflang> <blockquote cite> <h2 id> <h3 id> <h5 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h5 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <h2 id> <h3 id> <h5 id>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: The tags <em class="placeholder"><h4>, <h6></em>; This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -878,6 +878,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -904,13 +905,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:22:"Basic HTML (with <h1>)";s:19:"@missing_attributes";s:90:"<a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:22:"Basic HTML (with <h1>)";s:19:"@missing_attributes";s:70:"<a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <h1> <a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <h1> <a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -932,6 +933,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -957,13 +959,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:23:"Basic HTML (without H*)";s:19:"@missing_attributes";s:50:"<a hreflang> <blockquote cite> <ul type> <ol type>";}', + 'a:2:{s:12:"%text_format";s:23:"Basic HTML (without H*)";s:19:"@missing_attributes";s:30:"<a hreflang> <blockquote cite>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: The tags <em class="placeholder"><h2>, <h3>, <h4>, <h5>, <h6></em>; This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -1003,7 +1005,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], ] + $basic_html_test_case['expected_ckeditor5_settings']['plugins'], ], - 'expected_superset' => '<ol reversed> <code class="language-*">', + 'expected_superset' => '<code class="language-*"> <ol reversed>', 'expected_fundamental_compatibility_violations' => $basic_html_test_case['expected_fundamental_compatibility_violations'], 'expected_db_logs' => [ 'status' => [ @@ -1017,16 +1019,16 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:23:"Basic HTML (with <pre>)";s:19:"@missing_attributes";s:90:"<a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:23:"Basic HTML (with <pre>)";s:19:"@missing_attributes";s:70:"<a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Code Block, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Code Block, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ - 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: These attributes: <em class="placeholder"> reversed (for <ol>), class (for <code>)</em>; Additional details are available in your logs.', + 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: These attributes: <em class="placeholder"> class (for <code>), reversed (for <ol>)</em>; Additional details are available in your logs.', ], ], ]; @@ -1083,13 +1085,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:45:"Basic HTML (with alignable paragraph support)";s:19:"@missing_attributes";s:90:"<a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:45:"Basic HTML (with alignable paragraph support)";s:19:"@missing_attributes";s:70:"<a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption, Alignment</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption, Alignment</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: These attributes: <em class="placeholder"> class (for <p>, <h2>, <h3>, <h4>, <h5>, <h6>), reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -1120,13 +1122,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:37:"Basic HTML (with Media Embed support)";s:19:"@missing_attributes";s:90:"<a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:37:"Basic HTML (with Media Embed support)";s:19:"@missing_attributes";s:70:"<a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -1168,13 +1170,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:74:"(with Media Embed support, view mode enabled but no view modes configured)";s:19:"@missing_attributes";s:120:"<a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <drupal-media data-view-mode>";}', + 'a:2:{s:12:"%text_format";s:74:"(with Media Embed support, view mode enabled but no view modes configured)";s:19:"@missing_attributes";s:100:"<a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <drupal-media data-view-mode>";}', ], ], ], 'expected_messages' => array_merge_recursive($basic_html_test_case['expected_messages'], [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <drupal-media data-view-mode>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <drupal-media data-view-mode>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -1182,7 +1184,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { ]), 'expected_post_filter_drop_fundamental_compatibility_violations' => [], 'expected_post_update_text_editor_violations' => [ - 'settings.plugins.ckeditor5_sourceEditing.allowed_tags.14' => 'The following attribute(s) can optionally be supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: <em class="placeholder">Media (<drupal-media data-view-mode>)</em>.', + 'settings.plugins.ckeditor5_sourceEditing.allowed_tags.12' => 'The following attribute(s) can optionally be supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: <em class="placeholder">Media (<drupal-media data-view-mode>)</em>.', ], ]; @@ -1220,13 +1222,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:76:"(with Media Embed support, view mode enabled and two view modes configured )";s:19:"@missing_attributes";s:120:"<a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <drupal-media data-view-mode>";}', + 'a:2:{s:12:"%text_format";s:76:"(with Media Embed support, view mode enabled and two view modes configured )";s:19:"@missing_attributes";s:100:"<a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <drupal-media data-view-mode>";}', ], ], ], 'expected_messages' => array_merge_recursive($basic_html_test_case['expected_messages'], [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <drupal-media data-view-mode>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload, Image align, Image caption</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id> <drupal-media data-view-mode>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -1234,7 +1236,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { ]), 'expected_post_filter_drop_fundamental_compatibility_violations' => [], 'expected_post_update_text_editor_violations' => [ - 'settings.plugins.ckeditor5_sourceEditing.allowed_tags.14' => 'The following attribute(s) can optionally be supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: <em class="placeholder">Media (<drupal-media data-view-mode>)</em>.', + 'settings.plugins.ckeditor5_sourceEditing.allowed_tags.12' => 'The following attribute(s) can optionally be supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: <em class="placeholder">Media (<drupal-media data-view-mode>)</em>.', ], ]; @@ -1249,9 +1251,9 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'ckeditor5_list' => $basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_list'], 'ckeditor5_sourceEditing' => [ 'allowed_tags' => array_merge( - array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 0, 9), + array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 0, 7), ['<img data-*>'], - array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 9), + array_slice($basic_html_test_case['expected_ckeditor5_settings']['plugins']['ckeditor5_sourceEditing']['allowed_tags'], 7), ), ], ] + $basic_html_test_case['expected_ckeditor5_settings']['plugins'], @@ -1270,13 +1272,13 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:48:"Basic HTML (with any data-* attribute on images)";s:19:"@missing_attributes";s:103:"<a hreflang> <blockquote cite> <ul type> <ol type> <img data-*> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:48:"Basic HTML (with any data-* attribute on images)";s:19:"@missing_attributes";s:83:"<a hreflang> <blockquote cite> <img data-*> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <ul type> <ol type> <img data-*> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List, Image, Image Upload</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <span> <a hreflang> <blockquote cite> <img data-*> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: This attribute: <em class="placeholder"> reversed (for <ol>)</em>; Additional details are available in your logs.', @@ -1325,6 +1327,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -1336,8 +1339,6 @@ class SmartDefaultSettingsTest extends KernelTestBase { '<dd>', '<a hreflang>', '<blockquote cite>', - '<ul type>', - '<ol type>', '<h2 id>', '<h3 id>', '<h4 id>', @@ -1363,7 +1364,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:15:"Restricted HTML";s:19:"@missing_attributes";s:90:"<a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:15:"Restricted HTML";s:19:"@missing_attributes";s:70:"<a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], 'warning' => [ @@ -1375,10 +1376,10 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <a hreflang> <blockquote cite> <ul type> <ol type> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <a hreflang> <blockquote cite> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ - 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: The <br>, <p> tags were added because they are <a target="_blank" href="/admin/help/ckeditor5#required-tags">required by CKEditor 5</a>. The tags <em class="placeholder"><h2>, <h3>, <h4>, <h5>, <h6>, <*>, <cite>, <dl>, <dt>, <dd>, <a>, <blockquote>, <ul>, <ol>, <strong>, <em>, <code>, <li></em>; These attributes: <em class="placeholder"> id (for <h2>, <h3>, <h4>, <h5>, <h6>), dir (for <*>), lang (for <*>), hreflang (for <a>), href (for <a>), cite (for <blockquote>), type (for <ul>, <ol>), reversed (for <ol>), start (for <ol>)</em>; Additional details are available in your logs.', + 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: The <br>, <p> tags were added because they are <a target="_blank" href="/admin/help/ckeditor5#required-tags">required by CKEditor 5</a>. The tags <em class="placeholder"><h2>, <h3>, <h4>, <h5>, <h6>, <*>, <cite>, <dl>, <dt>, <dd>, <a>, <blockquote>, <strong>, <em>, <code>, <ul>, <ol>, <li></em>; These attributes: <em class="placeholder"> id (for <h2>, <h3>, <h4>, <h5>, <h6>), dir (for <*>), lang (for <*>), hreflang (for <a>), href (for <a>), cite (for <blockquote>), type (for <ul>, <ol>), reversed (for <ol>), start (for <ol>)</em>; Additional details are available in your logs.', ], ], 'expected_post_filter_drop_fundamental_compatibility_violations' => [], @@ -1456,6 +1457,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -1467,8 +1469,6 @@ class SmartDefaultSettingsTest extends KernelTestBase { '<dd>', '<a hreflang>', '<blockquote cite>', - '<ul type>', - '<ol type="1 A I">', '<h2 id="jump-*">', '<h3 id>', '<h4 id>', @@ -1478,7 +1478,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], ], ], - 'expected_superset' => '<br> <p> <ol reversed>', + 'expected_superset' => '<br> <p> <ol type reversed>', 'expected_fundamental_compatibility_violations' => [ '' => 'CKEditor 5 needs at least the <p> and <br> tags to be allowed to be able to function. They are not allowed by the "<em class="placeholder">Limit allowed HTML tags and correct faulty HTML</em>" (<em class="placeholder">filter_html</em>) filter.', ], @@ -1494,7 +1494,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], [ 'As part of migrating to CKEditor 5, it was found that the %text_format text format\'s HTML filters includes plugins that support the following tags, but not some of their attributes. To ensure these attributes remain supported, the following were added to the Source Editing plugin\'s <em>Manually editable HTML tags</em>: @missing_attributes. The text format must be saved to make these changes active.', - 'a:2:{s:12:"%text_format";s:54:"Only the "filter_html" filter and its default settings";s:19:"@missing_attributes";s:107:"<a hreflang> <blockquote cite> <ul type> <ol type="1 A I"> <h2 id="jump-*"> <h3 id> <h4 id> <h5 id> <h6 id>";}', + 'a:2:{s:12:"%text_format";s:54:"Only the "filter_html" filter and its default settings";s:19:"@missing_attributes";s:79:"<a hreflang> <blockquote cite> <h2 id="jump-*"> <h3 id> <h4 id> <h5 id> <h6 id>";}', ], ], 'warning' => [ @@ -1506,10 +1506,10 @@ class SmartDefaultSettingsTest extends KernelTestBase { ], 'expected_messages' => [ 'status' => [ - 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <a hreflang> <blockquote cite> <ul type> <ol type="1 A I"> <h2 id="jump-*"> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', + 'To maintain the capabilities of this text format, <a target="_blank" href="/admin/help/ckeditor5#migration-settings">the CKEditor 5 migration</a> did the following: Enabled these plugins: (<em class="placeholder">Link, Block quote, Code, List</em>). Added these tags/attributes to the Source Editing Plugin\'s <a target="_blank" href="/admin/help/ckeditor5#source-editing">Manually editable HTML tags</a> setting: <cite> <dl> <dt> <dd> <a hreflang> <blockquote cite> <h2 id="jump-*"> <h3 id> <h4 id> <h5 id> <h6 id>. Additional details are available in your logs.', ], 'warning' => [ - 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: The <br>, <p> tags were added because they are <a target="_blank" href="/admin/help/ckeditor5#required-tags">required by CKEditor 5</a>. The tags <em class="placeholder"><h2>, <h3>, <h4>, <h5>, <h6>, <*>, <cite>, <dl>, <dt>, <dd>, <a>, <blockquote>, <ul>, <ol>, <strong>, <em>, <code>, <li></em>; These attributes: <em class="placeholder"> id (for <h2>, <h3>, <h4>, <h5>, <h6>), dir (for <*>), lang (for <*>), hreflang (for <a>), href (for <a>), cite (for <blockquote>), type (for <ul>, <ol>), reversed (for <ol>), start (for <ol>)</em>; Additional details are available in your logs.', + 'Updating to CKEditor 5 added support for some previously unsupported tags/attributes. A plugin introduced support for the following: The <br>, <p> tags were added because they are <a target="_blank" href="/admin/help/ckeditor5#required-tags">required by CKEditor 5</a>. The tags <em class="placeholder"><h2>, <h3>, <h4>, <h5>, <h6>, <*>, <cite>, <dl>, <dt>, <dd>, <a>, <blockquote>, <strong>, <em>, <code>, <ul>, <ol>, <li></em>; These attributes: <em class="placeholder"> id (for <h2>, <h3>, <h4>, <h5>, <h6>), dir (for <*>), lang (for <*>), hreflang (for <a>), href (for <a>), cite (for <blockquote>), type (for <ul>, <ol>), reversed (for <ol>), start (for <ol>)</em>; Additional details are available in your logs.', ], ], ]; diff --git a/core/modules/ckeditor5/tests/src/Kernel/ValidatorsTest.php b/core/modules/ckeditor5/tests/src/Kernel/ValidatorsTest.php index 75735a0cc51..7b9bff386d8 100644 --- a/core/modules/ckeditor5/tests/src/Kernel/ValidatorsTest.php +++ b/core/modules/ckeditor5/tests/src/Kernel/ValidatorsTest.php @@ -135,6 +135,7 @@ class ValidatorsTest extends KernelTestBase { 'properties' => [ 'reversed' => FALSE, 'startIndex' => FALSE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -582,7 +583,7 @@ class ValidatorsTest extends KernelTestBase { ], 'expected_violations' => [], ]; - $data['INVALID: SourceEditing plugin configuration: <ol start type> must not be allowed because List can generate <ol reversed start>'] = [ + $data['INVALID: SourceEditing plugin configuration: <ol start type> must not be allowed because List can generate <ol reversed start type>'] = [ 'ckeditor5_settings' => [ 'toolbar' => [ 'items' => [ @@ -595,6 +596,7 @@ class ValidatorsTest extends KernelTestBase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, + 'styles' => FALSE, ], 'multiBlock' => TRUE, ], @@ -606,10 +608,13 @@ class ValidatorsTest extends KernelTestBase { ], ], 'expected_violations' => [ - 'settings.plugins.ckeditor5_sourceEditing.allowed_tags.0' => 'The following attribute(s) are already supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: <em class="placeholder">List (<ol start>)</em>.', + 'settings.plugins.ckeditor5_sourceEditing.allowed_tags.0' => [ + 'The following attribute(s) are already supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: <em class="placeholder">List (<ol start>)</em>.', + 'The following attribute(s) can optionally be supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: <em class="placeholder">List (<ol type>)</em>.', + ], ], ]; - $data['INVALID: SourceEditing plugin configuration: <ol start type> must not be allowed because List can generate <ol start>'] = [ + $data['INVALID: SourceEditing plugin configuration: <ol start type> must not be allowed because List can generate <ol start type>'] = [ 'ckeditor5_settings' => [ 'toolbar' => [ 'items' => [ @@ -622,6 +627,7 @@ class ValidatorsTest extends KernelTestBase { 'properties' => [ 'reversed' => FALSE, 'startIndex' => FALSE, + 'styles' => FALSE, ], 'multiBlock' => TRUE, ], @@ -633,7 +639,7 @@ class ValidatorsTest extends KernelTestBase { ], ], 'expected_violations' => [ - 'settings.plugins.ckeditor5_sourceEditing.allowed_tags.0' => 'The following attribute(s) can optionally be supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: <em class="placeholder">List (<ol start>)</em>.', + 'settings.plugins.ckeditor5_sourceEditing.allowed_tags.0' => 'The following attribute(s) can optionally be supported by enabled plugins and should not be added to the Source Editing "Manually editable HTML tags" field: <em class="placeholder">List (<ol start type>)</em>.', ], ]; diff --git a/core/modules/ckeditor5/tests/src/Unit/ListPluginTest.php b/core/modules/ckeditor5/tests/src/Unit/ListPluginTest.php index 1efae1f5b7f..f4cc007ac1a 100644 --- a/core/modules/ckeditor5/tests/src/Unit/ListPluginTest.php +++ b/core/modules/ckeditor5/tests/src/Unit/ListPluginTest.php @@ -26,6 +26,7 @@ class ListPluginTest extends UnitTestCase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => FALSE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -34,7 +35,9 @@ class ListPluginTest extends UnitTestCase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => FALSE, - 'styles' => FALSE, + 'styles' => [ + 'useAttribute' => TRUE, + ], ], 'multiBlock' => TRUE, ], @@ -45,6 +48,7 @@ class ListPluginTest extends UnitTestCase { 'properties' => [ 'reversed' => FALSE, 'startIndex' => TRUE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -53,17 +57,40 @@ class ListPluginTest extends UnitTestCase { 'properties' => [ 'reversed' => FALSE, 'startIndex' => TRUE, + 'styles' => [ + 'useAttribute' => TRUE, + ], + ], + 'multiBlock' => TRUE, + ], + ], + ], + 'styles is false' => [ + [ + 'properties' => [ + 'reversed' => TRUE, + 'startIndex' => TRUE, + 'styles' => FALSE, + ], + 'multiBlock' => TRUE, + ], + [ + 'list' => [ + 'properties' => [ + 'reversed' => TRUE, + 'startIndex' => TRUE, 'styles' => FALSE, ], 'multiBlock' => TRUE, ], ], ], - 'both disabled' => [ + 'all disabled' => [ [ 'properties' => [ 'reversed' => FALSE, 'startIndex' => FALSE, + 'styles' => FALSE, ], 'multiBlock' => TRUE, ], @@ -78,11 +105,12 @@ class ListPluginTest extends UnitTestCase { ], ], ], - 'both enabled' => [ + 'all enabled' => [ [ 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, + 'styles' => TRUE, ], 'multiBlock' => TRUE, ], @@ -91,7 +119,9 @@ class ListPluginTest extends UnitTestCase { 'properties' => [ 'reversed' => TRUE, 'startIndex' => TRUE, - 'styles' => FALSE, + 'styles' => [ + 'useAttribute' => TRUE, + ], ], 'multiBlock' => TRUE, ], diff --git a/core/modules/comment/src/Hook/CommentTokensHooks.php b/core/modules/comment/src/Hook/CommentTokensHooks.php index 7d7e9d0c03f..630e74e8752 100644 --- a/core/modules/comment/src/Hook/CommentTokensHooks.php +++ b/core/modules/comment/src/Hook/CommentTokensHooks.php @@ -47,7 +47,7 @@ class CommentTokensHooks { ]; } } - // Core comment tokens + // Core comment tokens. $comment['cid'] = ['name' => $this->t("Comment ID"), 'description' => $this->t("The unique ID of the comment.")]; $comment['uuid'] = ['name' => $this->t('UUID'), 'description' => $this->t("The UUID of the comment.")]; $comment['hostname'] = [ @@ -76,7 +76,7 @@ class CommentTokensHooks { 'name' => $this->t("Edit URL"), 'description' => $this->t("The URL of the comment's edit page."), ]; - // Chained tokens for comments + // Chained tokens for comments. $comment['created'] = [ 'name' => $this->t("Date created"), 'description' => $this->t("The date the comment was posted."), diff --git a/core/modules/comment/src/Plugin/views/field/StatisticsLastCommentName.php b/core/modules/comment/src/Plugin/views/field/StatisticsLastCommentName.php index 098b6855c56..045258af50a 100644 --- a/core/modules/comment/src/Plugin/views/field/StatisticsLastCommentName.php +++ b/core/modules/comment/src/Plugin/views/field/StatisticsLastCommentName.php @@ -39,7 +39,7 @@ class StatisticsLastCommentName extends FieldPluginBase { // last_comment_name only contains data if the user is anonymous. So we // have to join in a specially related user table. $this->ensureMyTable(); - // Join 'users' to this table via vid + // Join 'users' to this table via vid. $definition = [ 'table' => 'users_field_data', 'field' => 'uid', diff --git a/core/modules/comment/tests/src/Functional/CommentAdminTest.php b/core/modules/comment/tests/src/Functional/CommentAdminTest.php index 69c634ba0f9..7d443963bdf 100644 --- a/core/modules/comment/tests/src/Functional/CommentAdminTest.php +++ b/core/modules/comment/tests/src/Functional/CommentAdminTest.php @@ -45,7 +45,7 @@ class CommentAdminTest extends CommentTestBase { // Ensure that doesn't require contact info. $this->setCommentAnonymous(CommentInterface::ANONYMOUS_MAYNOT_CONTACT); - // Test that the comments page loads correctly when there are no comments + // Test that the comments page loads correctly when there are no comments. $this->drupalGet('admin/content/comment'); $this->assertSession()->pageTextContains('No comments available.'); diff --git a/core/modules/comment/tests/src/Functional/CommentNonNodeTest.php b/core/modules/comment/tests/src/Functional/CommentNonNodeTest.php index 203a0fff425..73e645c8918 100644 --- a/core/modules/comment/tests/src/Functional/CommentNonNodeTest.php +++ b/core/modules/comment/tests/src/Functional/CommentNonNodeTest.php @@ -171,7 +171,7 @@ class CommentNonNodeTest extends BrowserTestBase { break; } $match = []; - // Get comment ID + // Get comment ID. preg_match('/#comment-([0-9]+)/', $this->getURL(), $match); // Get comment. diff --git a/core/modules/comment/tests/src/Functional/CommentPagerTest.php b/core/modules/comment/tests/src/Functional/CommentPagerTest.php index 4927803208b..f476526eeef 100644 --- a/core/modules/comment/tests/src/Functional/CommentPagerTest.php +++ b/core/modules/comment/tests/src/Functional/CommentPagerTest.php @@ -287,17 +287,17 @@ class CommentPagerTest extends CommentTestBase { $this->setCommentSettings('default_mode', CommentManagerInterface::COMMENT_MODE_FLAT, 'Comment paging changed.'); $expected_pages = [ - // Page of comment 5 + // Page of comment 5. 1 => 5, - // Page of comment 4 + // Page of comment 4. 2 => 4, - // Page of comment 3 + // Page of comment 3. 3 => 3, - // Page of comment 2 + // Page of comment 2. 4 => 2, - // Page of comment 1 + // Page of comment 1. 5 => 1, - // Page of comment 0 + // Page of comment 0. 6 => 0, ]; @@ -311,17 +311,17 @@ class CommentPagerTest extends CommentTestBase { $this->setCommentSettings('default_mode', CommentManagerInterface::COMMENT_MODE_THREADED, 'Switched to threaded mode.'); $expected_pages = [ - // Page of comment 5 + // Page of comment 5. 1 => 5, - // Page of comment 4 + // Page of comment 4. 2 => 1, - // Page of comment 4 + // Page of comment 4. 3 => 1, - // Page of comment 4 + // Page of comment 4. 4 => 1, - // Page of comment 4 + // Page of comment 4. 5 => 1, - // Page of comment 0 + // Page of comment 0. 6 => 0, ]; diff --git a/core/modules/comment/tests/src/Functional/CommentTestBase.php b/core/modules/comment/tests/src/Functional/CommentTestBase.php index 1744bdd9cde..c4932d47826 100644 --- a/core/modules/comment/tests/src/Functional/CommentTestBase.php +++ b/core/modules/comment/tests/src/Functional/CommentTestBase.php @@ -168,7 +168,7 @@ abstract class CommentTestBase extends BrowserTestBase { break; } $match = []; - // Get comment ID + // Get comment ID. preg_match('/#comment-([0-9]+)/', $this->getURL(), $match); // Get comment. diff --git a/core/modules/comment/tests/src/Functional/Views/DefaultViewRecentCommentsTest.php b/core/modules/comment/tests/src/Functional/Views/DefaultViewRecentCommentsTest.php index 12a781d4c0e..89596107bfe 100644 --- a/core/modules/comment/tests/src/Functional/Views/DefaultViewRecentCommentsTest.php +++ b/core/modules/comment/tests/src/Functional/Views/DefaultViewRecentCommentsTest.php @@ -70,7 +70,7 @@ class DefaultViewRecentCommentsTest extends ViewTestBase { protected function setUp($import_test_views = TRUE, $modules = []): void { parent::setUp($import_test_views, $modules); - // Create a new content type + // Create a new content type. $content_type = $this->drupalCreateContentType(); // Add a node of the new content type. diff --git a/core/modules/comment/tests/src/Kernel/CommentOrphanTest.php b/core/modules/comment/tests/src/Kernel/CommentOrphanTest.php index 8c31076f475..a3e63629bd4 100644 --- a/core/modules/comment/tests/src/Kernel/CommentOrphanTest.php +++ b/core/modules/comment/tests/src/Kernel/CommentOrphanTest.php @@ -77,7 +77,7 @@ class CommentOrphanTest extends EntityKernelTestBase { 'label' => 'Comment', ])->save(); - // Make two comments + // Make two comments. $comment1 = $comment_storage->create([ 'field_name' => 'comment', 'comment_body' => 'test', diff --git a/core/modules/comment/tests/src/Kernel/Views/FilterAndArgumentUserUidTest.php b/core/modules/comment/tests/src/Kernel/Views/FilterAndArgumentUserUidTest.php index 40eaeeaa3cb..d332080e7c8 100644 --- a/core/modules/comment/tests/src/Kernel/Views/FilterAndArgumentUserUidTest.php +++ b/core/modules/comment/tests/src/Kernel/Views/FilterAndArgumentUserUidTest.php @@ -90,7 +90,7 @@ class FilterAndArgumentUserUidTest extends KernelTestBase { 'entity_type' => 'node', 'field_name' => 'comment', ])->save(); - // Comment added by $other_account on $node_commented_by_account + // Comment added by $other_account on $node_commented_by_account. Comment::create([ 'uid' => $other_account->id(), 'entity_id' => $node_commented_by_account->id(), diff --git a/core/modules/config/tests/src/Functional/ConfigDraggableListBuilderTest.php b/core/modules/config/tests/src/Functional/ConfigDraggableListBuilderTest.php index 45e041758d6..38b60f247de 100644 --- a/core/modules/config/tests/src/Functional/ConfigDraggableListBuilderTest.php +++ b/core/modules/config/tests/src/Functional/ConfigDraggableListBuilderTest.php @@ -40,7 +40,7 @@ class ConfigDraggableListBuilderTest extends BrowserTestBase { $role->save(); } - // Navigate to Roles page + // Navigate to Roles page. $this->drupalGet('admin/people/roles'); // Test for the page title. diff --git a/core/modules/config/tests/src/Functional/ConfigImportUITest.php b/core/modules/config/tests/src/Functional/ConfigImportUITest.php index b4e4585e68d..bc1399ae561 100644 --- a/core/modules/config/tests/src/Functional/ConfigImportUITest.php +++ b/core/modules/config/tests/src/Functional/ConfigImportUITest.php @@ -327,7 +327,7 @@ class ConfigImportUITest extends BrowserTestBase { // Verify diff colors are displayed. $this->assertSession()->elementsCount('xpath', '//table[contains(@class, "diff")]', 1); - // Reset data back to original, and remove a key + // Reset data back to original, and remove a key. $sync_data = $original_data; unset($sync_data[$remove_key]); $sync->write($config_name, $sync_data); @@ -340,7 +340,7 @@ class ConfigImportUITest extends BrowserTestBase { // Removed key is escaped. $this->assertSession()->pageTextContains("404: '<em>herp</em>'"); - // Reset data back to original and add a key + // Reset data back to original and add a key. $sync_data = $original_data; $sync_data[$add_key] = $add_data; $sync->write($config_name, $sync_data); diff --git a/core/modules/config_translation/tests/src/Functional/ConfigTranslationListUiTest.php b/core/modules/config_translation/tests/src/Functional/ConfigTranslationListUiTest.php index 230081cf9b3..0cf13d30231 100644 --- a/core/modules/config_translation/tests/src/Functional/ConfigTranslationListUiTest.php +++ b/core/modules/config_translation/tests/src/Functional/ConfigTranslationListUiTest.php @@ -511,7 +511,7 @@ class ConfigTranslationListUiTest extends BrowserTestBase { $this->doFieldListTest(); // Views is tested in - // Drupal\config_translation\Tests\ConfigTranslationViewListUiTest + // Drupal\config_translation\Tests\ConfigTranslationViewListUiTest. // Test the maintenance settings page. $this->doSettingsPageTest('admin/config/development/maintenance'); diff --git a/core/modules/config_translation/tests/src/Functional/ConfigTranslationUiTest.php b/core/modules/config_translation/tests/src/Functional/ConfigTranslationUiTest.php index a7fdd9aa872..371a5b046f9 100644 --- a/core/modules/config_translation/tests/src/Functional/ConfigTranslationUiTest.php +++ b/core/modules/config_translation/tests/src/Functional/ConfigTranslationUiTest.php @@ -253,7 +253,7 @@ class ConfigTranslationUiTest extends ConfigTranslationUiTestBase { public function testSingleLanguageUI(): void { $this->drupalLogin($this->adminUser); - // Delete French language + // Delete French language. $this->drupalGet('admin/config/regional/language/delete/fr'); $this->submitForm([], 'Delete'); $this->assertSession()->pageTextContains('The French (fr) language has been removed.'); @@ -266,7 +266,7 @@ class ConfigTranslationUiTest extends ConfigTranslationUiTestBase { $this->submitForm($edit, 'Save configuration'); $this->assertSession()->pageTextContains('Configuration saved.'); - // Delete English language + // Delete English language. $this->drupalGet('admin/config/regional/language/delete/en'); $this->submitForm([], 'Delete'); $this->assertSession()->pageTextContains('The English (en) language has been removed.'); diff --git a/core/modules/contact/tests/src/Functional/ContactSitewideTest.php b/core/modules/contact/tests/src/Functional/ContactSitewideTest.php index b3cba2bd1ba..260fdb95371 100644 --- a/core/modules/contact/tests/src/Functional/ContactSitewideTest.php +++ b/core/modules/contact/tests/src/Functional/ContactSitewideTest.php @@ -70,7 +70,7 @@ class ContactSitewideTest extends BrowserTestBase { // Ensure that there is no textfield for email. $this->assertSession()->fieldNotExists('mail'); - // Logout and retrieve the page as an anonymous user + // Logout and retrieve the page as an anonymous user. $this->drupalLogout(); user_role_grant_permissions('anonymous', ['access site-wide contact form']); $this->drupalGet('contact'); diff --git a/core/modules/content_moderation/content_moderation.module b/core/modules/content_moderation/content_moderation.module deleted file mode 100644 index fdd55eaec3b..00000000000 --- a/core/modules/content_moderation/content_moderation.module +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -/** - * @file - */ - -use Drupal\content_moderation\ContentPreprocess; - -/** - * Implements hook_preprocess_HOOK(). - */ -function content_moderation_preprocess_node(&$variables): void { - \Drupal::service('class_resolver') - ->getInstanceFromDefinition(ContentPreprocess::class) - ->preprocessNode($variables); -} diff --git a/core/modules/content_moderation/src/Hook/ContentModerationThemeHooks.php b/core/modules/content_moderation/src/Hook/ContentModerationThemeHooks.php new file mode 100644 index 00000000000..8b2c829dc1d --- /dev/null +++ b/core/modules/content_moderation/src/Hook/ContentModerationThemeHooks.php @@ -0,0 +1,21 @@ +<?php + +namespace Drupal\content_moderation\Hook; + +use Drupal\content_moderation\ContentPreprocess; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for content_moderation. + */ +class ContentModerationThemeHooks { + + /** + * Implements hook_preprocess_HOOK(). + */ + #[Hook('preprocess_node')] + public function preprocessNode(&$variables): void { + \Drupal::service('class_resolver')->getInstanceFromDefinition(ContentPreprocess::class)->preprocessNode($variables); + } + +} diff --git a/core/modules/content_moderation/tests/src/Functional/ModerationActionsTest.php b/core/modules/content_moderation/tests/src/Functional/ModerationActionsTest.php index c801e08f4a0..81e44862d5e 100644 --- a/core/modules/content_moderation/tests/src/Functional/ModerationActionsTest.php +++ b/core/modules/content_moderation/tests/src/Functional/ModerationActionsTest.php @@ -80,11 +80,12 @@ class ModerationActionsTest extends BrowserTestBase { ], 'Apply to selected items'); if ($warning_appears) { + $typeLabel = $node->getBundleEntity()->label(); if ($action == 'node_publish_action') { - $this->assertSession()->statusMessageContains(node_get_type_label($node) . ' content items were skipped as they are under moderation and may not be directly published.', 'warning'); + $this->assertSession()->statusMessageContains($typeLabel . ' content items were skipped as they are under moderation and may not be directly published.', 'warning'); } else { - $this->assertSession()->statusMessageContains(node_get_type_label($node) . ' content items were skipped as they are under moderation and may not be directly unpublished.', 'warning'); + $this->assertSession()->statusMessageContains($typeLabel . ' content items were skipped as they are under moderation and may not be directly unpublished.', 'warning'); } } else { diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index 49b15bb022b..7749def59ff 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -159,11 +159,3 @@ function content_translation_language_configuration_element_submit(array $form, \Drupal::service('router.builder')->setRebuildNeeded(); } } - -/** - * Implements hook_preprocess_HOOK() for language-content-settings-table.html.twig. - */ -function content_translation_preprocess_language_content_settings_table(&$variables): void { - \Drupal::moduleHandler()->loadInclude('content_translation', 'inc', 'content_translation.admin'); - _content_translation_preprocess_language_content_settings_table($variables); -} diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php index ad21415ac0a..5ce09394849 100644 --- a/core/modules/content_translation/src/ContentTranslationHandler.php +++ b/core/modules/content_translation/src/ContentTranslationHandler.php @@ -487,7 +487,7 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface, E '#default_value' => User::load($uid), // Validation is done by static::entityFormValidate(). '#validate_reference' => FALSE, - '#maxlength' => 60, + '#maxlength' => 1024, '#description' => $this->t('Leave blank for %anonymous.', ['%anonymous' => \Drupal::config('user.settings')->get('anonymous')]), ]; diff --git a/core/modules/content_translation/src/Hook/ContentTranslationThemeHooks.php b/core/modules/content_translation/src/Hook/ContentTranslationThemeHooks.php new file mode 100644 index 00000000000..b8f91fcb098 --- /dev/null +++ b/core/modules/content_translation/src/Hook/ContentTranslationThemeHooks.php @@ -0,0 +1,21 @@ +<?php + +namespace Drupal\content_translation\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for content_translation. + */ +class ContentTranslationThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for language-content-settings-table.html.twig. + */ + #[Hook('preprocess_language_content_settings_table')] + public function preprocessLanguageContentSettingsTable(&$variables): void { + \Drupal::moduleHandler()->loadInclude('content_translation', 'inc', 'content_translation.admin'); + _content_translation_preprocess_language_content_settings_table($variables); + } + +} diff --git a/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php b/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php index 65e4ea51654..44929204bc6 100644 --- a/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php +++ b/core/modules/content_translation/tests/src/Functional/ContentTranslationUITestBase.php @@ -12,6 +12,7 @@ use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Url; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait; +use Drupal\user\UserInterface; /** * Tests the Content Translation UI. @@ -353,6 +354,18 @@ abstract class ContentTranslationUITestBase extends ContentTranslationTestBase { $metadata = $this->manager->getTranslationMetadata($entity->getTranslation($langcode)); $this->assertEquals($values[$langcode]['uid'], $metadata->getAuthor()->id(), 'Translation author correctly kept.'); $this->assertEquals($values[$langcode]['created'], $metadata->getCreatedTime(), 'Translation date correctly kept.'); + + // Verify that long usernames can be saved as the translation author. + $user = $this->drupalCreateUser([], $this->randomMachineName(UserInterface::USERNAME_MAX_LENGTH)); + $edit = [ + // Format the username as it is entered in autocomplete fields. + 'content_translation[uid]' => $user->getAccountName() . ' (' . $user->id() . ')', + 'content_translation[created]' => $this->container->get('date.formatter')->format($values[$langcode]['created'], 'custom', 'Y-m-d H:i:s O'), + ]; + $this->submitForm($edit, $this->getFormSubmitAction($entity, $langcode)); + $reloaded_entity = $storage->load($this->entityId); + $metadata = $this->manager->getTranslationMetadata($reloaded_entity->getTranslation($langcode)); + $this->assertEquals($user->id(), $metadata->getAuthor()->id(), 'Translation author correctly set.'); } /** diff --git a/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php b/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php index dd1d6f1ae92..b880c7124e1 100644 --- a/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php +++ b/core/modules/contextual/tests/src/FunctionalJavascript/ContextualLinksTest.php @@ -62,7 +62,7 @@ class ContextualLinksTest extends WebDriverTestBase { $contextualLinks = $this->assertSession()->waitForElement('css', '.contextual button'); $this->assertNotEmpty($contextualLinks); - // Confirm touchevents detection is loaded with Contextual Links + // Confirm touchevents detection is loaded with Contextual Links. $this->assertSession()->elementExists('css', 'html.no-touchevents'); // Ensure visibility remains correct after cached paged load. diff --git a/core/modules/datetime/tests/src/Functional/DateFilterTest.php b/core/modules/datetime/tests/src/Functional/DateFilterTest.php index 87896594408..74283c0da8e 100644 --- a/core/modules/datetime/tests/src/Functional/DateFilterTest.php +++ b/core/modules/datetime/tests/src/Functional/DateFilterTest.php @@ -88,7 +88,8 @@ class DateFilterTest extends ViewTestBase { $this->drupalGet('test_exposed_filter_datetime'); $this->assertSession()->statusCodeEquals(200); - // Ensure that invalid date format entries in the exposed filter are validated + // Ensure that invalid date format entries in the exposed filter are + // validated. $edit = ['edit-field-date-value-value' => 'lun 2018-04-27']; $this->submitForm($edit, 'Apply'); $this->assertSession()->pageTextContains('Invalid date format.'); diff --git a/core/modules/datetime/tests/src/Functional/DateTestBase.php b/core/modules/datetime/tests/src/Functional/DateTestBase.php index b7399930273..04c8f4d7b20 100644 --- a/core/modules/datetime/tests/src/Functional/DateTestBase.php +++ b/core/modules/datetime/tests/src/Functional/DateTestBase.php @@ -64,7 +64,7 @@ abstract class DateTestBase extends BrowserTestBase { protected static $timezones = [ // UTC-12, no DST. 'Pacific/Kwajalein', - // UTC-11, no DST + // UTC-11, no DST. 'Pacific/Midway', // UTC-7, no DST. 'America/Phoenix', @@ -72,7 +72,7 @@ abstract class DateTestBase extends BrowserTestBase { 'UTC', // UTC+5:30, no DST. 'Asia/Kolkata', - // UTC+12, no DST + // UTC+12, no DST. 'Pacific/Funafuti', // UTC+13, no DST. 'Pacific/Tongatapu', diff --git a/core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php b/core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php index d6dee40b55e..ccffb9e71c1 100644 --- a/core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php +++ b/core/modules/datetime/tests/src/Functional/DateTimeFieldTest.php @@ -426,7 +426,7 @@ class DateTimeFieldTest extends DateTestBase { $this->assertSession()->elementExists('xpath', '//fieldset[@aria-describedby="edit-' . $field_name . '-0--description"]'); $this->assertSession()->elementExists('xpath', '//div[@id="edit-' . $field_name . '-0--description"]'); - // Assert that Hour and Minute Elements do not appear on Date Only + // Assert that Hour and Minute Elements do not appear on Date Only. $this->assertSession()->elementNotExists('xpath', "//*[@id=\"edit-$field_name-0-value-hour\"]"); $this->assertSession()->elementNotExists('xpath', "//*[@id=\"edit-$field_name-0-value-minute\"]"); diff --git a/core/modules/dblog/config/schema/dblog.schema.yml b/core/modules/dblog/config/schema/dblog.schema.yml index cd59a5dd891..32df3f56152 100644 --- a/core/modules/dblog/config/schema/dblog.schema.yml +++ b/core/modules/dblog/config/schema/dblog.schema.yml @@ -8,7 +8,6 @@ dblog.settings: type: integer label: 'Database log messages to keep' constraints: - Range: - min: 0 + PositiveOrZero: ~ constraints: FullyValidatable: ~ diff --git a/core/modules/editor/tests/src/Unit/EditorXssFilter/StandardTest.php b/core/modules/editor/tests/src/Unit/EditorXssFilter/StandardTest.php index eb5ce5deb9f..75014bcc505 100644 --- a/core/modules/editor/tests/src/Unit/EditorXssFilter/StandardTest.php +++ b/core/modules/editor/tests/src/Unit/EditorXssFilter/StandardTest.php @@ -510,7 +510,7 @@ xss:ex/*XSS*//*/*/pression(alert("XSS"))\'>', '<META http-equiv="refresh" content="text/html base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">', ]; - // META with additional URL parameter + // META with additional URL parameter. // @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#META $data[] = [ '<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert(\'XSS\');">', diff --git a/core/modules/field/tests/modules/field_test/src/Hook/FieldTestHooks.php b/core/modules/field/tests/modules/field_test/src/Hook/FieldTestHooks.php index a8edc9623ff..dd58152a90f 100644 --- a/core/modules/field/tests/modules/field_test/src/Hook/FieldTestHooks.php +++ b/core/modules/field/tests/modules/field_test/src/Hook/FieldTestHooks.php @@ -95,7 +95,7 @@ class FieldTestHooks { */ #[Hook('entity_extra_field_info_alter')] public function entityExtraFieldInfoAlter(&$info): void { - // Remove all extra fields from the 'no_fields' content type; + // Remove all extra fields from the 'no_fields' content type. unset($info['node']['no_fields']); } diff --git a/core/modules/field/tests/src/Functional/FormTest.php b/core/modules/field/tests/src/Functional/FormTest.php index e5c8838f353..c76864f10fe 100644 --- a/core/modules/field/tests/src/Functional/FormTest.php +++ b/core/modules/field/tests/src/Functional/FormTest.php @@ -138,7 +138,7 @@ class FormTest extends FieldTestBase { $this->assertSession()->pageTextContains("{$this->field['label']} does not accept the value -1."); // @todo check that the correct field is flagged for error. - // Create an entity + // Create an entity. $value = mt_rand(1, 127); $edit = [ "{$field_name}[0][value]" => $value, @@ -233,7 +233,7 @@ class FormTest extends FieldTestBase { $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains("{$this->field['label']} field is required."); - // Create an entity + // Create an entity. $value = mt_rand(1, 127); $edit = [ "{$field_name}[0][value]" => $value, @@ -316,7 +316,7 @@ class FormTest extends FieldTestBase { $pattern[$weight] = "<input [^>]*value=\"$value\" [^>]*"; } - // Press 'add more' button -> 4 widgets + // Press 'add more' button -> 4 widgets. $this->submitForm($edit, 'Add another item'); for ($delta = 0; $delta <= $delta_range; $delta++) { $this->assertSession()->fieldValueEquals("{$field_name}[$delta][value]", $values[$delta]); @@ -347,7 +347,7 @@ class FormTest extends FieldTestBase { // Submit: check that the entity is updated with correct values // Re-submit: check that the field can be emptied. - // Test with several multiple fields in a form + // Test with several multiple fields in a form. } /** diff --git a/core/modules/field/tests/src/Functional/NestedFormTest.php b/core/modules/field/tests/src/Functional/NestedFormTest.php index 717d5f84b8c..2a59cd661fb 100644 --- a/core/modules/field/tests/src/Functional/NestedFormTest.php +++ b/core/modules/field/tests/src/Functional/NestedFormTest.php @@ -83,7 +83,7 @@ class NestedFormTest extends FieldTestBase { /** @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface $display_repository */ $display_repository = \Drupal::service('entity_display.repository'); - // Add two fields on the 'entity_test' + // Add two fields on the 'entity_test'. FieldStorageConfig::create($this->fieldStorageSingle)->save(); FieldStorageConfig::create($this->fieldStorageUnlimited)->save(); $this->field['field_name'] = 'field_single'; diff --git a/core/modules/field/tests/src/Functional/Number/NumberFieldTest.php b/core/modules/field/tests/src/Functional/Number/NumberFieldTest.php index 16321397808..531647fac27 100644 --- a/core/modules/field/tests/src/Functional/Number/NumberFieldTest.php +++ b/core/modules/field/tests/src/Functional/Number/NumberFieldTest.php @@ -197,7 +197,7 @@ class NumberFieldTest extends BrowserTestBase { $this->assertSession()->fieldValueEquals("{$field_name}[0][value]", ''); $this->assertSession()->responseContains('placeholder="4"'); - // Submit a valid integer + // Submit a valid integer. $value = rand($minimum, $maximum); $edit = [ "{$field_name}[0][value]" => $value, @@ -207,7 +207,7 @@ class NumberFieldTest extends BrowserTestBase { $id = $match[1]; $this->assertSession()->pageTextContains('entity_test ' . $id . ' has been created.'); - // Try to set a value below the minimum value + // Try to set a value below the minimum value. $this->drupalGet('entity_test/add'); $edit = [ "{$field_name}[0][value]" => $minimum - 1, @@ -215,7 +215,7 @@ class NumberFieldTest extends BrowserTestBase { $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains("{$field_name} must be higher than or equal to {$minimum}."); - // Try to set a decimal value + // Try to set a decimal value. $this->drupalGet('entity_test/add'); $edit = [ "{$field_name}[0][value]" => 1.5, @@ -223,7 +223,7 @@ class NumberFieldTest extends BrowserTestBase { $this->submitForm($edit, 'Save'); $this->assertSession()->pageTextContains("{$field_name} is not a valid number."); - // Try to set a value above the maximum value + // Try to set a value above the maximum value. $this->drupalGet('entity_test/add'); $edit = [ "{$field_name}[0][value]" => $maximum + 1, diff --git a/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php b/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php index 056bf84c01e..1b283ab918a 100644 --- a/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php +++ b/core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceItemTest.php @@ -193,7 +193,7 @@ class EntityReferenceItemTest extends FieldKernelTestBase { $this->assertInstanceOf(\InvalidArgumentException::class, $e); } - // Delete terms so we have nothing to reference and try again + // Delete terms so we have nothing to reference and try again. $term->delete(); $term2->delete(); $entity = EntityTest::create(['name' => $this->randomMachineName()]); @@ -302,7 +302,7 @@ class EntityReferenceItemTest extends FieldKernelTestBase { $this->assertEquals($vocabulary2->id(), $entity->field_test_taxonomy_vocabulary->entity->id()); $this->assertEquals($vocabulary2->label(), $entity->field_test_taxonomy_vocabulary->entity->label()); - // Delete terms so we have nothing to reference and try again + // Delete terms so we have nothing to reference and try again. $this->vocabulary->delete(); $vocabulary2->delete(); $entity = EntityTest::create(['name' => $this->randomMachineName()]); diff --git a/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php b/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php index 52e4c6b4cfc..2123c912264 100644 --- a/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php +++ b/core/modules/field/tests/src/Kernel/EntityReference/Views/EntityReferenceRelationshipTest.php @@ -280,7 +280,7 @@ class EntityReferenceRelationshipTest extends ViewsKernelTestBase { $this->assertEquals($this->entities[$index]->id(), $row->_entity->id()); // Test the forward relationship. - // $this->assertEquals(1, $row->entity_test_entity_test_mul__field_data_test_id); + // $this->assertEquals(1, $row->entity_test_entity_test_mul__field_data_test_id);. // Test that the correct relationship entity is on the row. $this->assertEquals(1, $row->_relationship_entities['field_test_data_with_a_long_name']->id()); diff --git a/core/modules/field/tests/src/Kernel/FieldAttachOtherTest.php b/core/modules/field/tests/src/Kernel/FieldAttachOtherTest.php index 175789b83ef..a7a72a49be2 100644 --- a/core/modules/field/tests/src/Kernel/FieldAttachOtherTest.php +++ b/core/modules/field/tests/src/Kernel/FieldAttachOtherTest.php @@ -270,11 +270,11 @@ class FieldAttachOtherTest extends FieldKernelTestBase { $this->assertEquals($this->fieldTestData->field->getLabel(), $form[$this->fieldTestData->field_name]['widget']['#title'], "First field's form title is {$this->fieldTestData->field->getLabel()}"); $this->assertEquals($this->fieldTestData->field_2->getLabel(), $form[$this->fieldTestData->field_name_2]['widget']['#title'], "Second field's form title is {$this->fieldTestData->field_2->getLabel()}"); for ($delta = 0; $delta < $this->fieldTestData->field_storage->getCardinality(); $delta++) { - // field_test_widget uses 'textfield' + // field_test_widget uses 'textfield'. $this->assertEquals('textfield', $form[$this->fieldTestData->field_name]['widget'][$delta]['value']['#type'], "First field's form delta {$delta} widget is textfield"); } for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) { - // field_test_widget uses 'textfield' + // field_test_widget uses 'textfield'. $this->assertEquals('textfield', $form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], "Second field's form delta {$delta} widget is textfield"); } @@ -292,7 +292,7 @@ class FieldAttachOtherTest extends FieldKernelTestBase { $this->assertFalse(isset($form[$this->fieldTestData->field_name]), 'The first field does not exist in the form'); $this->assertEquals($this->fieldTestData->field_2->getLabel(), $form[$this->fieldTestData->field_name_2]['widget']['#title'], "Second field's form title is {$this->fieldTestData->field_2->getLabel()}"); for ($delta = 0; $delta < $this->fieldTestData->field_storage_2->getCardinality(); $delta++) { - // field_test_widget uses 'textfield' + // field_test_widget uses 'textfield'. $this->assertEquals('textfield', $form[$this->fieldTestData->field_name_2]['widget'][$delta]['value']['#type'], "Second field's form delta {$delta} widget is textfield"); } } diff --git a/core/modules/field/tests/src/Kernel/FieldAttachStorageTest.php b/core/modules/field/tests/src/Kernel/FieldAttachStorageTest.php index 9d6c428cf57..e18f2fa6544 100644 --- a/core/modules/field/tests/src/Kernel/FieldAttachStorageTest.php +++ b/core/modules/field/tests/src/Kernel/FieldAttachStorageTest.php @@ -241,18 +241,18 @@ class FieldAttachStorageTest extends FieldKernelTestBase { ->create(['type' => $this->fieldTestData->field->getTargetBundle()]); $vids = []; - // Create revision 0 + // Create revision 0. $values = $this->_generateTestFieldValues($cardinality); $entity->{$this->fieldTestData->field_name} = $values; $entity->save(); $vids[] = $entity->getRevisionId(); - // Create revision 1 + // Create revision 1. $entity->setNewRevision(); $entity->save(); $vids[] = $entity->getRevisionId(); - // Create revision 2 + // Create revision 2. $entity->setNewRevision(); $entity->save(); $vids[] = $entity->getRevisionId(); @@ -260,7 +260,7 @@ class FieldAttachStorageTest extends FieldKernelTestBase { $controller = $this->container->get('entity_type.manager')->getStorage($entity->getEntityTypeId()); $controller->resetCache(); - // Confirm each revision loads + // Confirm each revision loads. foreach ($vids as $vid) { $revision = $controller->loadRevision($vid); $this->assertCount($cardinality, $revision->{$this->fieldTestData->field_name}, "The test entity revision $vid has $cardinality values."); @@ -275,12 +275,12 @@ class FieldAttachStorageTest extends FieldKernelTestBase { $this->assertCount($cardinality, $revision->{$this->fieldTestData->field_name}, "The test entity revision $vid has $cardinality values."); } - // Confirm the current revision still loads + // Confirm the current revision still loads. $controller->resetCache(); $current = $controller->load($entity->id()); $this->assertCount($cardinality, $current->{$this->fieldTestData->field_name}, "The test entity current revision has $cardinality values."); - // Delete all field data, confirm nothing loads + // Delete all field data, confirm nothing loads. $entity->delete(); $controller->resetCache(); foreach ([0, 1, 2] as $vid) { @@ -333,7 +333,7 @@ class FieldAttachStorageTest extends FieldKernelTestBase { $this->fieldTestData->field_definition['bundle'] = $new_bundle; FieldConfig::create($this->fieldTestData->field_definition)->save(); - // Create a second field for the test bundle + // Create a second field for the test bundle. $field_name = $this->randomMachineName() . '_field_name'; $field_storage = [ 'field_name' => $field_name, @@ -352,7 +352,7 @@ class FieldAttachStorageTest extends FieldKernelTestBase { ]; FieldConfig::create($field)->save(); - // Save an entity with data for both fields + // Save an entity with data for both fields. $entity = $this->container->get('entity_type.manager') ->getStorage($entity_type) ->create(['type' => $this->fieldTestData->field->getTargetBundle()]); @@ -361,7 +361,7 @@ class FieldAttachStorageTest extends FieldKernelTestBase { $entity->{$field_name} = $this->_generateTestFieldValues(1); $entity = $this->entitySaveReload($entity); - // Verify the fields are present on load + // Verify the fields are present on load. $this->assertCount(4, $entity->{$this->fieldTestData->field_name}, 'First field got loaded'); $this->assertCount(1, $entity->{$field_name}, 'Second field got loaded'); @@ -373,7 +373,7 @@ class FieldAttachStorageTest extends FieldKernelTestBase { ->delete(); EntityTestHelper::deleteBundle($this->fieldTestData->field->getTargetBundle(), $entity_type); - // Verify no data gets loaded + // Verify no data gets loaded. $controller = $this->container->get('entity_type.manager')->getStorage($entity->getEntityTypeId()); $controller->resetCache(); $entity = $controller->load($entity->id()); diff --git a/core/modules/field/tests/src/Kernel/FieldCrudTest.php b/core/modules/field/tests/src/Kernel/FieldCrudTest.php index bf1e0cf5c57..cf948bdd06c 100644 --- a/core/modules/field/tests/src/Kernel/FieldCrudTest.php +++ b/core/modules/field/tests/src/Kernel/FieldCrudTest.php @@ -65,7 +65,7 @@ class FieldCrudTest extends FieldKernelTestBase { // - a full fledged $field structure, check that all the values are there // - a minimal $field structure, check all default values are set // defer actual $field comparison to a helper function, used for the two cases above, - // and for testUpdateField + // and for testUpdateField. /** * Tests the creation of a field. diff --git a/core/modules/field/tests/src/Kernel/FieldImportDeleteUninstallTest.php b/core/modules/field/tests/src/Kernel/FieldImportDeleteUninstallTest.php index d0928dc7540..d2030032bd5 100644 --- a/core/modules/field/tests/src/Kernel/FieldImportDeleteUninstallTest.php +++ b/core/modules/field/tests/src/Kernel/FieldImportDeleteUninstallTest.php @@ -90,7 +90,7 @@ class FieldImportDeleteUninstallTest extends FieldKernelTestBase { unset($core_extension['module']['telephone']); $sync->write('core.extension', $core_extension); - // Stage the field deletion + // Stage the field deletion. $sync->delete('field.storage.entity_test.field_test'); $sync->delete('field.field.entity_test.entity_test.field_test'); diff --git a/core/modules/field/tests/src/Kernel/FieldStorageCrudTest.php b/core/modules/field/tests/src/Kernel/FieldStorageCrudTest.php index 849dd240212..01521d89946 100644 --- a/core/modules/field/tests/src/Kernel/FieldStorageCrudTest.php +++ b/core/modules/field/tests/src/Kernel/FieldStorageCrudTest.php @@ -27,7 +27,7 @@ class FieldStorageCrudTest extends FieldKernelTestBase { // @todo Test creation with // - a full fledged $field structure, check that all the values are there // - a minimal $field structure, check all default values are set - // defer actual $field comparison to a helper function, used for the two cases above + // defer actual $field comparison to a helper function, used for the two cases above. /** * Tests the creation of a field storage. @@ -375,13 +375,13 @@ class FieldStorageCrudTest extends FieldKernelTestBase { $field = FieldConfig::load('entity_test.' . $field_definition['bundle'] . '.' . $field_definition['field_name']); $this->assertFalse($field->isDeleted()); - // Save an entity with data for the field + // Save an entity with data for the field. $entity = EntityTest::create(); $values[0]['value'] = mt_rand(1, 127); $entity->{$field_storage->getName()}->value = $values[0]['value']; $entity = $this->entitySaveReload($entity); - // Verify the field is present on load + // Verify the field is present on load. $this->assertCount(1, $entity->{$field_storage->getName()}, "Data in previously deleted field saves and loads correctly"); foreach ($values as $delta => $value) { $this->assertEquals($values[$delta]['value'], $entity->{$field_storage->getName()}[$delta]->value, "Data in previously deleted field saves and loads correctly"); diff --git a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php index 81631820ce6..4a5f7dbe89b 100644 --- a/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php +++ b/core/modules/field/tests/src/Kernel/Migrate/d7/MigrateFieldTest.php @@ -132,7 +132,7 @@ class MigrateFieldTest extends MigrateDrupal7TestBase { $field = FieldStorageConfig::load('node.field_term_entityreference'); $this->assertEquals('taxonomy_term', $field->getSetting('target_type')); - // Make sure that datetime fields get the right datetime_type setting + // Make sure that datetime fields get the right datetime_type setting. $field = FieldStorageConfig::load('node.field_date'); $this->assertEquals('datetime', $field->getSetting('datetime_type')); $field = FieldStorageConfig::load('node.field_date_without_time'); diff --git a/core/modules/field/tests/src/Kernel/Timestamp/TimestampFormatterTest.php b/core/modules/field/tests/src/Kernel/Timestamp/TimestampFormatterTest.php index 01131d84857..9ccbd336958 100644 --- a/core/modules/field/tests/src/Kernel/Timestamp/TimestampFormatterTest.php +++ b/core/modules/field/tests/src/Kernel/Timestamp/TimestampFormatterTest.php @@ -148,7 +148,7 @@ class TimestampFormatterTest extends KernelTestBase { foreach (range(1, 7) as $granularity) { $request_time = \Drupal::requestStack()->getCurrentRequest()->server->get('REQUEST_TIME'); - // Test a timestamp in the past + // Test a timestamp in the past. $value = $request_time - 87654321; $interval = \Drupal::service('date.formatter')->formatTimeDiffSince($value, ['granularity' => $granularity]); $expected = $interval . ' ago'; @@ -164,7 +164,7 @@ class TimestampFormatterTest extends KernelTestBase { $this->renderEntityFields($entity, $this->display); $this->assertRaw($expected); - // Test a timestamp in the future + // Test a timestamp in the future. $value = $request_time + 87654321; $interval = \Drupal::service('date.formatter')->formatTimeDiffUntil($value, ['granularity' => $granularity]); $expected = $interval . ' hence'; diff --git a/core/modules/field/tests/src/Kernel/Views/HandlerFieldFieldTest.php b/core/modules/field/tests/src/Kernel/Views/HandlerFieldFieldTest.php index 3b91b5cc916..b40e39e27e1 100644 --- a/core/modules/field/tests/src/Kernel/Views/HandlerFieldFieldTest.php +++ b/core/modules/field/tests/src/Kernel/Views/HandlerFieldFieldTest.php @@ -199,7 +199,7 @@ class HandlerFieldFieldTest extends KernelTestBase { $view->style_plugin->getField(4, $this->fieldStorages[4]->getName()); $view->destroy(); - // Test delta limit + offset + // Test delta limit + offset. $this->prepareView($view); $view->displayHandlers->get('default')->options['fields'][$field_name]['group_rows'] = TRUE; $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_limit'] = 3; diff --git a/core/modules/field_ui/field_ui.module b/core/modules/field_ui/field_ui.module index 67c049fa505..809328d9abc 100644 --- a/core/modules/field_ui/field_ui.module +++ b/core/modules/field_ui/field_ui.module @@ -23,15 +23,6 @@ function template_preprocess_field_ui_table(&$variables): void { } /** - * Implements hook_preprocess_HOOK(). - */ -function field_ui_preprocess_form_element__new_storage_type(&$variables): void { - // Add support for a variant string so radios in the add field form can be - // programmatically distinguished. - $variables['variant'] = $variables['element']['#variant'] ?? NULL; -} - -/** * Form submission handler for the 'Save and manage fields' button. * * @see field_ui_form_alter() diff --git a/core/modules/field_ui/src/Hook/FieldUiThemeHooks.php b/core/modules/field_ui/src/Hook/FieldUiThemeHooks.php new file mode 100644 index 00000000000..9edd1d038ec --- /dev/null +++ b/core/modules/field_ui/src/Hook/FieldUiThemeHooks.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\field_ui\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for field_ui. + */ +class FieldUiThemeHooks { + + /** + * Implements hook_preprocess_HOOK(). + */ + #[Hook('preprocess_form_element__new_storage_type')] + public function preprocessFormElementNewStorageType(&$variables): void { + // Add support for a variant string so radios in the add field form can be + // programmatically distinguished. + $variables['variant'] = $variables['element']['#variant'] ?? NULL; + } + +} diff --git a/core/modules/field_ui/tests/src/Functional/ManageDisplayTest.php b/core/modules/field_ui/tests/src/Functional/ManageDisplayTest.php index e247bdf12b0..cc2512cbe05 100644 --- a/core/modules/field_ui/tests/src/Functional/ManageDisplayTest.php +++ b/core/modules/field_ui/tests/src/Functional/ManageDisplayTest.php @@ -407,7 +407,7 @@ class ManageDisplayTest extends BrowserTestBase { $options[] = $option->getValue(); } - // Loops trough all the option groups + // Loops trough all the option groups. foreach ($element->optgroup as $optgroup) { $options = array_merge($this->getAllOptionsList($optgroup), $options); } diff --git a/core/modules/file/src/Hook/TokenHooks.php b/core/modules/file/src/Hook/TokenHooks.php index 39fbddfc646..8abaa6567fc 100644 --- a/core/modules/file/src/Hook/TokenHooks.php +++ b/core/modules/file/src/Hook/TokenHooks.php @@ -47,7 +47,7 @@ class TokenHooks { $replacements[$original] = $file->uuid(); break; - // Essential file data + // Essential file data. case 'name': $replacements[$original] = $file->getFilename(); break; diff --git a/core/modules/file/tests/file_deprecated_test/file_deprecated_test.module b/core/modules/file/tests/file_deprecated_test/file_deprecated_test.module deleted file mode 100644 index 625f5ee9dbb..00000000000 --- a/core/modules/file/tests/file_deprecated_test/file_deprecated_test.module +++ /dev/null @@ -1,35 +0,0 @@ -<?php - -/** - * @file - * Support module for testing deprecated file features. - */ - -declare(strict_types=1); - -// cspell:ignore garply tarz - -/** - * Implements hook_file_mimetype_mapping_alter(). - * - * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Kept only for BC test coverage, see \Drupal\KernelTests\Core\File\MimeTypeLegacyTest. - * - * @see https://www.drupal.org/node/3494040 - */ -function file_deprecated_test_file_mimetype_mapping_alter(&$mapping): void { - // Add new mappings. - $mapping['mimetypes']['file_test_mimetype_1'] = 'made_up/file_test_1'; - $mapping['mimetypes']['file_test_mimetype_2'] = 'made_up/file_test_2'; - $mapping['mimetypes']['file_test_mimetype_3'] = 'made_up/doc'; - $mapping['mimetypes']['application-x-compress'] = 'application/x-compress'; - $mapping['mimetypes']['application-x-tarz'] = 'application/x-tarz'; - $mapping['mimetypes']['application-x-garply-waldo'] = 'application/x-garply-waldo'; - $mapping['extensions']['file_test_1'] = 'file_test_mimetype_1'; - $mapping['extensions']['file_test_2'] = 'file_test_mimetype_2'; - $mapping['extensions']['file_test_3'] = 'file_test_mimetype_2'; - $mapping['extensions']['z'] = 'application-x-compress'; - $mapping['extensions']['tar.z'] = 'application-x-tarz'; - $mapping['extensions']['garply.waldo'] = 'application-x-garply-waldo'; - // Override existing mapping. - $mapping['extensions']['doc'] = 'file_test_mimetype_3'; -} diff --git a/core/modules/file/tests/file_deprecated_test/src/Hook/FileDeprecatedTestThemeHooks.php b/core/modules/file/tests/file_deprecated_test/src/Hook/FileDeprecatedTestThemeHooks.php new file mode 100644 index 00000000000..a25027b687a --- /dev/null +++ b/core/modules/file/tests/file_deprecated_test/src/Hook/FileDeprecatedTestThemeHooks.php @@ -0,0 +1,41 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\file_deprecated_test\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for file_deprecated_test. + */ +class FileDeprecatedTestThemeHooks { + // cspell:ignore garply tarz + + /** + * Implements hook_file_mimetype_mapping_alter(). + * + * @deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Kept only for BC test coverage, see \Drupal\KernelTests\Core\File\MimeTypeLegacyTest. + * + * @see https://www.drupal.org/node/3494040 + */ + #[Hook('file_mimetype_mapping_alter')] + public function fileMimetypeMappingAlter(&$mapping): void { + // Add new mappings. + $mapping['mimetypes']['file_test_mimetype_1'] = 'made_up/file_test_1'; + $mapping['mimetypes']['file_test_mimetype_2'] = 'made_up/file_test_2'; + $mapping['mimetypes']['file_test_mimetype_3'] = 'made_up/doc'; + $mapping['mimetypes']['application-x-compress'] = 'application/x-compress'; + $mapping['mimetypes']['application-x-tarz'] = 'application/x-tarz'; + $mapping['mimetypes']['application-x-garply-waldo'] = 'application/x-garply-waldo'; + $mapping['extensions']['file_test_1'] = 'file_test_mimetype_1'; + $mapping['extensions']['file_test_2'] = 'file_test_mimetype_2'; + $mapping['extensions']['file_test_3'] = 'file_test_mimetype_2'; + $mapping['extensions']['z'] = 'application-x-compress'; + $mapping['extensions']['tar.z'] = 'application-x-tarz'; + $mapping['extensions']['garply.waldo'] = 'application-x-garply-waldo'; + // Override existing mapping. + $mapping['extensions']['doc'] = 'file_test_mimetype_3'; + } + +} diff --git a/core/modules/file/tests/file_test/src/FileTestHelper.php b/core/modules/file/tests/file_test/src/FileTestHelper.php index 9a364110415..9ff5f908690 100644 --- a/core/modules/file/tests/file_test/src/FileTestHelper.php +++ b/core/modules/file/tests/file_test/src/FileTestHelper.php @@ -19,7 +19,7 @@ class FileTestHelper { * @see Drupal\file_test\FileTestHelper::reset() */ public static function reset(): void { - // Keep track of calls to these hooks + // Keep track of calls to these hooks. $results = [ 'load' => [], 'validate' => [], diff --git a/core/modules/file/tests/src/Kernel/DeleteTest.php b/core/modules/file/tests/src/Kernel/DeleteTest.php index 95139ef26f9..6afeae8cca6 100644 --- a/core/modules/file/tests/src/Kernel/DeleteTest.php +++ b/core/modules/file/tests/src/Kernel/DeleteTest.php @@ -74,7 +74,7 @@ class DeleteTest extends FileManagedUnitTestBase { ->execute(); \Drupal::service('cron')->run(); - // file_cron() loads + // file_cron() loads. $this->assertFileHooksCalled(['delete']); $this->assertFileDoesNotExist($file->getFileUri()); $this->assertNull(File::load($file->id()), 'File was removed from the database.'); diff --git a/core/modules/file/tests/src/Kernel/FileItemTest.php b/core/modules/file/tests/src/Kernel/FileItemTest.php index c01cf28a115..39c285bb428 100644 --- a/core/modules/file/tests/src/Kernel/FileItemTest.php +++ b/core/modules/file/tests/src/Kernel/FileItemTest.php @@ -89,7 +89,7 @@ class FileItemTest extends FieldKernelTestBase { $handler_id = $field_definition->getSetting('handler'); $this->assertEquals('default:file', $handler_id); - // Create a test entity with the + // Create a test entity with the test file field. $entity = EntityTest::create(); $entity->file_test->target_id = $this->file->id(); $entity->file_test->display = 1; diff --git a/core/modules/file/tests/src/Kernel/SpaceUsedTest.php b/core/modules/file/tests/src/Kernel/SpaceUsedTest.php index 0f3dedf8fb4..c2e7bbd9faf 100644 --- a/core/modules/file/tests/src/Kernel/SpaceUsedTest.php +++ b/core/modules/file/tests/src/Kernel/SpaceUsedTest.php @@ -68,7 +68,7 @@ class SpaceUsedTest extends FileManagedUnitTestBase { $this->assertEquals(300, $file->spaceUsed(3)); $this->assertEquals(370, $file->spaceUsed()); - // Test the status fields + // Test the status fields. $this->assertEquals(4, $file->spaceUsed(NULL, 0)); $this->assertEquals(370, $file->spaceUsed()); diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module index 38da47a437e..4c5e3f7a0ac 100644 --- a/core/modules/filter/filter.module +++ b/core/modules/filter/filter.module @@ -514,7 +514,7 @@ function _filter_url($text, $filter) { $text = implode($chunks); } - // Revert to the original comment contents + // Revert to the original comment contents. _filter_url_escape_comments('', FALSE); $text = $text ? preg_replace_callback('`<!--(.*?)-->`', '_filter_url_escape_comments', $text) : $text; } @@ -630,14 +630,14 @@ function _filter_url_trim($text, $length = NULL) { * Based on: http://photomatt.net/scripts/autop */ function _filter_autop($text) { - // All block level tags + // All block level tags. $block = '(?:table|thead|tfoot|caption|col|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|option|form|map|area|blockquote|address|math|input|p|h[1-6]|fieldset|legend|hr|article|aside|details|figcaption|figure|footer|header|hgroup|menu|nav|section|summary)'; // Split at opening and closing PRE, SCRIPT, STYLE, OBJECT, IFRAME tags // and comments. We don't apply any processing to the contents of these tags // to avoid messing up code. We look for matched pairs and allow basic // nesting. For example: - // "processed<pre>ignored<script>ignored</script>ignored</pre>processed" + // "processed<pre>ignored<script>ignored</script>ignored</pre>processed". $chunks = preg_split('@(<!--.*?-->|</?(?:pre|script|style|object|iframe|drupal-media|svg|!--)[^>]*>)@i', $text, -1, PREG_SPLIT_DELIM_CAPTURE); // Note: PHP ensures the array consists of alternating delimiters and literals // and begins and ends with a literal (inserting NULL as required). @@ -688,28 +688,28 @@ function _filter_autop($text) { } } - // Just to make things a little easier, pad the end + // Just to make things a little easier, pad the end. $chunk = preg_replace('|\n*$|', '', $chunk) . "\n\n"; $chunk = preg_replace('|<br />\s*<br />|', "\n\n", $chunk); - // Space things out a little + // Space things out a little. $chunk = preg_replace('!(<' . $block . '[^>]*>)!', "\n$1", $chunk); - // Space things out a little + // Space things out a little. $chunk = preg_replace('!(</' . $block . '>)!', "$1\n\n", $chunk); - // Take care of duplicates + // Take care of duplicates. $chunk = preg_replace("/\n\n+/", "\n\n", $chunk); $chunk = preg_replace('/^\n|\n\s*\n$/', '', $chunk); - // Make paragraphs, including one at the end + // Make paragraphs, including one at the end. $chunk = '<p>' . preg_replace('/\n\s*\n\n?(.)/', "</p>\n<p>$1", $chunk) . "</p>\n"; - // Problem with nested lists + // Problem with nested lists. $chunk = preg_replace("|<p>(<li.+?)</p>|", "$1", $chunk); $chunk = preg_replace('|<p><blockquote([^>]*)>|i', "<blockquote$1><p>", $chunk); $chunk = str_replace('</blockquote></p>', '</p></blockquote>', $chunk); // Under certain strange conditions it could create a P of entirely - // whitespace + // whitespace. $chunk = preg_replace('|<p>\s*</p>\n?|', '', $chunk); $chunk = preg_replace('!<p>\s*(</?' . $block . '[^>]*>)!', "$1", $chunk); $chunk = preg_replace('!(</?' . $block . '[^>]*>)\s*</p>!', "$1", $chunk); - // Make line breaks + // Make line breaks. $chunk = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $chunk); $chunk = preg_replace('!(</?' . $block . '[^>]*>)\s*<br />!', "$1", $chunk); $chunk = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)!', '$1', $chunk); diff --git a/core/modules/filter/src/FilterFormatFormBase.php b/core/modules/filter/src/FilterFormatFormBase.php index 7e694188e4d..f78c195ed4f 100644 --- a/core/modules/filter/src/FilterFormatFormBase.php +++ b/core/modules/filter/src/FilterFormatFormBase.php @@ -86,7 +86,7 @@ abstract class FilterFormatFormBase extends EntityForm { // Filter order (tabledrag). $form['filters']['order'] = [ '#type' => 'table', - // For filter.admin.js + // For filter.admin.js. '#attributes' => ['id' => 'filter-order'], '#title' => $this->t('Filter processing order'), '#tabledrag' => [ diff --git a/core/modules/help/help.module b/core/modules/help/help.module index 69ab53e1436..17cb448e221 100644 --- a/core/modules/help/help.module +++ b/core/modules/help/help.module @@ -5,15 +5,6 @@ */ /** - * Implements hook_preprocess_HOOK() for block templates. - */ -function help_preprocess_block(&$variables): void { - if ($variables['plugin_id'] == 'help_block') { - $variables['attributes']['role'] = 'complementary'; - } -} - -/** * Ensure that search is updated when extensions are installed or uninstalled. * * @param string[] $extensions diff --git a/core/modules/help/src/Hook/HelpThemeHooks.php b/core/modules/help/src/Hook/HelpThemeHooks.php new file mode 100644 index 00000000000..431c7d089d2 --- /dev/null +++ b/core/modules/help/src/Hook/HelpThemeHooks.php @@ -0,0 +1,25 @@ +<?php + +namespace Drupal\help\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for help. + */ +class HelpThemeHooks { + /** + * @file + */ + + /** + * Implements hook_preprocess_HOOK() for block templates. + */ + #[Hook('preprocess_block')] + public function preprocessBlock(&$variables): void { + if ($variables['plugin_id'] == 'help_block') { + $variables['attributes']['role'] = 'complementary'; + } + } + +} diff --git a/core/modules/image/src/Hook/ImageHooks.php b/core/modules/image/src/Hook/ImageHooks.php index 2d6af269220..910b93037bd 100644 --- a/core/modules/image/src/Hook/ImageHooks.php +++ b/core/modules/image/src/Hook/ImageHooks.php @@ -177,7 +177,7 @@ class ImageHooks { // Private file access for image style derivatives. if (str_starts_with($path, 'styles/')) { $args = explode('/', $path); - // Discard "styles", style name, and scheme from the path + // Discard "styles", style name, and scheme from the path. $args = array_slice($args, 3); // Then the remaining parts are the path to the image. $original_uri = StreamWrapperManager::getScheme($uri) . '://' . implode('/', $args); diff --git a/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php index efeacd6ff16..4ceca734539 100644 --- a/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php +++ b/core/modules/image/tests/src/Functional/ImageFieldDisplayTest.php @@ -81,7 +81,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase { $this->submitForm([], "{$field_name}_settings_edit"); $this->assertSession()->linkByHrefNotExists(Url::fromRoute('entity.image_style.collection')->toString(), 'Link to image styles configuration is absent when permissions are insufficient'); - // Restore 'administer image styles' permission to testing admin user + // Restore 'administer image styles' permission to testing admin user. user_role_change_permissions(reset($admin_user_roles), ['administer image styles' => TRUE]); // Create a new node with an image attached. @@ -384,7 +384,7 @@ class ImageFieldDisplayTest extends ImageFieldTestBase { $this->submitForm([], "{$field_name}_settings_edit"); $this->assertSession()->linkByHrefNotExists(Url::fromRoute('entity.image_style.collection')->toString(), 'Link to image styles configuration is absent when permissions are insufficient'); - // Restore 'administer image styles' permission to testing admin user + // Restore 'administer image styles' permission to testing admin user. user_role_change_permissions(reset($admin_user_roles), ['administer image styles' => TRUE]); // Create a new node with an image attached. diff --git a/core/modules/image/tests/src/Functional/ImageFieldWidgetTest.php b/core/modules/image/tests/src/Functional/ImageFieldWidgetTest.php index dd2e6929a97..7dd717a5d61 100644 --- a/core/modules/image/tests/src/Functional/ImageFieldWidgetTest.php +++ b/core/modules/image/tests/src/Functional/ImageFieldWidgetTest.php @@ -22,7 +22,7 @@ class ImageFieldWidgetTest extends ImageFieldTestBase { * Tests file widget element. */ public function testWidgetElement(): void { - // Check for image widget in add/node/article page + // Check for image widget in add/node/article page. $field_name = $this->randomMachineName(); $min_resolution = 50; $max_resolution = 100; diff --git a/core/modules/inline_form_errors/inline_form_errors.module b/core/modules/inline_form_errors/inline_form_errors.module index 5faac086641..0e4bf06f0a2 100644 --- a/core/modules/inline_form_errors/inline_form_errors.module +++ b/core/modules/inline_form_errors/inline_form_errors.module @@ -5,34 +5,6 @@ */ /** - * Implements hook_preprocess_HOOK() for form element templates. - */ -function inline_form_errors_preprocess_form_element(&$variables): void { - _inline_form_errors_set_errors($variables); -} - -/** - * Implements hook_preprocess_HOOK() for details element templates. - */ -function inline_form_errors_preprocess_details(&$variables): void { - _inline_form_errors_set_errors($variables); -} - -/** - * Implements hook_preprocess_HOOK() for fieldset element templates. - */ -function inline_form_errors_preprocess_fieldset(&$variables): void { - _inline_form_errors_set_errors($variables); -} - -/** - * Implements hook_preprocess_HOOK() for datetime form wrapper templates. - */ -function inline_form_errors_preprocess_datetime_wrapper(&$variables): void { - _inline_form_errors_set_errors($variables); -} - -/** * Populates form errors in the template. */ function _inline_form_errors_set_errors(&$variables): void { diff --git a/core/modules/inline_form_errors/src/Hook/InlineFormErrorsThemeHooks.php b/core/modules/inline_form_errors/src/Hook/InlineFormErrorsThemeHooks.php new file mode 100644 index 00000000000..ac6d6f16bb6 --- /dev/null +++ b/core/modules/inline_form_errors/src/Hook/InlineFormErrorsThemeHooks.php @@ -0,0 +1,47 @@ +<?php + +namespace Drupal\inline_form_errors\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for inline_form_errors. + */ +class InlineFormErrorsThemeHooks { + /** + * @file + */ + + /** + * Implements hook_preprocess_HOOK() for form element templates. + */ + #[Hook('preprocess_form_element')] + public function preprocessFormElement(&$variables): void { + _inline_form_errors_set_errors($variables); + } + + /** + * Implements hook_preprocess_HOOK() for details element templates. + */ + #[Hook('preprocess_details')] + public function preprocessDetails(&$variables): void { + _inline_form_errors_set_errors($variables); + } + + /** + * Implements hook_preprocess_HOOK() for fieldset element templates. + */ + #[Hook('preprocess_fieldset')] + public function preprocessFieldset(&$variables): void { + _inline_form_errors_set_errors($variables); + } + + /** + * Implements hook_preprocess_HOOK() for datetime form wrapper templates. + */ + #[Hook('preprocess_datetime_wrapper')] + public function preprocessDatetimeWrapper(&$variables): void { + _inline_form_errors_set_errors($variables); + } + +} diff --git a/core/modules/jsonapi/src/JsonApiResource/ResourceObject.php b/core/modules/jsonapi/src/JsonApiResource/ResourceObject.php index 6d4cc6ce55f..6564f2b3401 100644 --- a/core/modules/jsonapi/src/JsonApiResource/ResourceObject.php +++ b/core/modules/jsonapi/src/JsonApiResource/ResourceObject.php @@ -98,7 +98,7 @@ class ResourceObject implements CacheableDependencyInterface, ResourceIdentifier $this->links = $links->withContext($this); // If the specified language empty it falls back the same way as in the - // entity system + // entity system. // @see \Drupal\Core\Entity\EntityBase::language() $this->language = $language ?: new Language(['id' => LanguageInterface::LANGCODE_NOT_SPECIFIED]); } diff --git a/core/modules/jsonapi/tests/src/Functional/JsonApiFunctionalTest.php b/core/modules/jsonapi/tests/src/Functional/JsonApiFunctionalTest.php index 199b27d308f..12aa5eeec52 100644 --- a/core/modules/jsonapi/tests/src/Functional/JsonApiFunctionalTest.php +++ b/core/modules/jsonapi/tests/src/Functional/JsonApiFunctionalTest.php @@ -584,7 +584,7 @@ class JsonApiFunctionalTest extends JsonApiFunctionalTestBase { 'resource_meta_title' => $node->getTitle(), ]; $this->assertEquals($expectedMeta, $result['data']['meta']); - // Test if the cache tags bubbled up + // Test if the cache tags bubbled up. $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'jsonapi_test_meta_events.object_meta'); $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.roles'); @@ -602,11 +602,11 @@ class JsonApiFunctionalTest extends JsonApiFunctionalTestBase { } - // Test if the cache tags bubbled up + // Test if the cache tags bubbled up. $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'jsonapi_test_meta_events.object_meta'); $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.roles'); - // Now try the same requests with a superuser, see if we get other caches + // Now try the same requests with a superuser, see if we get other caches. $this->mink->resetSessions(); $this->drupalResetSession(); $this->drupalLogin($this->adminUser); @@ -674,7 +674,7 @@ class JsonApiFunctionalTest extends JsonApiFunctionalTestBase { // Test if the cache tags bubbled up. $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'jsonapi_test_meta_events.relationship_meta'); - // Test if relationship has correct metadata when loading a single resource + // Test if relationship has correct metadata when loading a single resource. $resource = Json::decode($this->drupalGet('jsonapi/node/article/' . $node->uuid())); if ($resource['data']['id'] === $node->uuid()) { $tagNames = $resource['data']['relationships']['field_tags']['meta']['relationship_meta_name']; @@ -687,7 +687,7 @@ class JsonApiFunctionalTest extends JsonApiFunctionalTestBase { } - // Test if the cache tags bubbled up + // Test if the cache tags bubbled up. $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'jsonapi_test_meta_events.relationship_meta'); } @@ -706,7 +706,7 @@ class JsonApiFunctionalTest extends JsonApiFunctionalTestBase { 'fields' => ['name'], ]); - // Test if relationship has correct metadata when loading a single resource + // Test if relationship has correct metadata when loading a single resource. $str = $this->drupalGet('jsonapi/node/article/' . $node->uuid() . '/relationships/field_tags'); $resource = Json::decode($str); diff --git a/core/modules/jsonapi/tests/src/Kernel/EventSubscriber/ResourceObjectNormalizerCacherTest.php b/core/modules/jsonapi/tests/src/Kernel/EventSubscriber/ResourceObjectNormalizerCacherTest.php index d9cda8df404..4f609de47a7 100644 --- a/core/modules/jsonapi/tests/src/Kernel/EventSubscriber/ResourceObjectNormalizerCacherTest.php +++ b/core/modules/jsonapi/tests/src/Kernel/EventSubscriber/ResourceObjectNormalizerCacherTest.php @@ -131,7 +131,7 @@ class ResourceObjectNormalizerCacherTest extends KernelTestBase { $this->installEntitySchema('entity_test_computed_field'); // Use EntityTestComputedField since ComputedTestCacheableStringItemList has - // a max age of 800 + // a max age of 800. $baseMaxAge = 800; $entity = EntityTestComputedField::create([]); $entity->save(); @@ -149,7 +149,7 @@ class ResourceObjectNormalizerCacherTest extends KernelTestBase { $event = new TerminateEvent($http_kernel->reveal(), $request->reveal(), $response->reveal()); $this->cacher->onTerminate($event); - // Change request time to 500 seconds later + // Change request time to 500 seconds later. $current_request = \Drupal::requestStack()->getCurrentRequest(); $current_request->server->set('REQUEST_TIME', $current_request->server->get('REQUEST_TIME') + 500); $resource_normalization = $this->serializer diff --git a/core/modules/language/language.module b/core/modules/language/language.module index fb9420037db..2d65dc70365 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -127,15 +127,6 @@ function language_negotiation_url_prefixes_update(): void { } /** - * Implements hook_preprocess_HOOK() for block templates. - */ -function language_preprocess_block(&$variables): void { - if ($variables['configuration']['provider'] == 'language') { - $variables['attributes']['role'] = 'navigation'; - } -} - -/** * Returns language mappings between browser and Drupal language codes. * * @return array diff --git a/core/modules/language/src/Hook/LanguageThemeHooks.php b/core/modules/language/src/Hook/LanguageThemeHooks.php new file mode 100644 index 00000000000..0629f7ff682 --- /dev/null +++ b/core/modules/language/src/Hook/LanguageThemeHooks.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\language\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for language. + */ +class LanguageThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for block templates. + */ + #[Hook('preprocess_block')] + public function preprocessBlock(&$variables): void { + if ($variables['configuration']['provider'] == 'language') { + $variables['attributes']['role'] = 'navigation'; + } + } + +} diff --git a/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php b/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php index 32ec3a2c6e5..44beb40d3eb 100644 --- a/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php +++ b/core/modules/language/tests/src/Functional/LanguageSwitchingTest.php @@ -356,11 +356,11 @@ class LanguageSwitchingTest extends BrowserTestBase { /** @var \Drupal\Core\Routing\UrlGenerator $generator */ $generator = $this->container->get('url_generator'); - // Verify the English URL is correct + // Verify the English URL is correct. $english_url = $generator->generateFromRoute('entity.user.canonical', ['user' => 2], ['language' => $languages['en']]); $this->assertSession()->elementAttributeContains('xpath', '//div[@id="block-test-language-block"]/ul/li/a[@hreflang="en"]', 'href', $english_url); - // Verify the Italian URL is correct + // Verify the Italian URL is correct. $italian_url = $generator->generateFromRoute('entity.user.canonical', ['user' => 2], ['language' => $languages['it']]); $this->assertSession()->elementAttributeContains('xpath', '//div[@id="block-test-language-block"]/ul/li/a[@hreflang="it"]', 'href', $italian_url); } diff --git a/core/modules/language/tests/src/Kernel/Condition/LanguageConditionTest.php b/core/modules/language/tests/src/Kernel/Condition/LanguageConditionTest.php index 19a74112e61..6b1949a72aa 100644 --- a/core/modules/language/tests/src/Kernel/Condition/LanguageConditionTest.php +++ b/core/modules/language/tests/src/Kernel/Condition/LanguageConditionTest.php @@ -66,7 +66,7 @@ class LanguageConditionTest extends KernelTestBase { // Check for the proper summary. $this->assertEquals('The language is Italian.', $condition->summary()); - // Negate the condition + // Negate the condition. $condition->setConfig('negate', TRUE); $this->assertTrue($condition->execute(), 'Language condition passes as expected.'); // Check for the proper summary. @@ -89,7 +89,7 @@ class LanguageConditionTest extends KernelTestBase { // Check for the proper summary. $this->assertEquals('The language is Italian.', $condition->summary()); - // Negate the condition + // Negate the condition. $condition->setConfig('negate', TRUE); $this->assertFalse($condition->execute(), 'Language condition fails as expected.'); // Check for the proper summary. diff --git a/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageContentSettingsTest.php b/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageContentSettingsTest.php index 28da2b80249..da4bd0750c5 100644 --- a/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageContentSettingsTest.php +++ b/core/modules/language/tests/src/Kernel/Migrate/d7/MigrateLanguageContentSettingsTest.php @@ -76,7 +76,7 @@ class MigrateLanguageContentSettingsTest extends MigrateDrupal7TestBase { $this->assertSame($config->get('default_langcode'), 'und'); // Assert that a content type without a 'language_content_type' variable is - // not translatable + // not translatable. $config = ContentLanguageSettings::loadByEntityTypeBundle('node', 'book'); $this->assertTrue($config->isDefaultConfiguration()); $this->assertFalse($config->isLanguageAlterable()); diff --git a/core/modules/layout_builder/layout_builder.module b/core/modules/layout_builder/layout_builder.module deleted file mode 100644 index 37dc492bf78..00000000000 --- a/core/modules/layout_builder/layout_builder.module +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/** - * @file - */ - -use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; - -/** - * Implements hook_preprocess_HOOK() for language-content-settings-table.html.twig. - */ -function layout_builder_preprocess_language_content_settings_table(&$variables): void { - foreach ($variables['build']['#rows'] as &$row) { - if (isset($row['#field_name']) && $row['#field_name'] === OverridesSectionStorage::FIELD_NAME) { - // Rebuild the label to include a warning about using translations with - // layouts. - $row['data'][1]['data']['field'] = [ - 'label' => $row['data'][1]['data']['field'], - 'description' => [ - '#type' => 'container', - '#markup' => t('<strong>Warning</strong>: Layout Builder does not support translating layouts. (<a href="https://www.drupal.org/docs/8/core/modules/layout-builder/layout-builder-and-content-translation">online documentation</a>)'), - '#attributes' => [ - 'class' => ['layout-builder-translation-warning'], - ], - ], - ]; - } - } -} diff --git a/core/modules/layout_builder/src/Hook/LayoutBuilderThemeHooks.php b/core/modules/layout_builder/src/Hook/LayoutBuilderThemeHooks.php new file mode 100644 index 00000000000..a4da9e469b9 --- /dev/null +++ b/core/modules/layout_builder/src/Hook/LayoutBuilderThemeHooks.php @@ -0,0 +1,40 @@ +<?php + +namespace Drupal\layout_builder\Hook; + +use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage; +use Drupal\Core\Hook\Attribute\Hook; +use Drupal\Core\StringTranslation\StringTranslationTrait; + +/** + * Hook implementations for layout_builder. + */ +class LayoutBuilderThemeHooks { + use StringTranslationTrait; + + /** + * Implements hook_preprocess_HOOK() for language-content-settings-table.html.twig. + */ + #[Hook('preprocess_language_content_settings_table')] + public function preprocessLanguageContentSettingsTable(&$variables): void { + foreach ($variables['build']['#rows'] as &$row) { + if (isset($row['#field_name']) && $row['#field_name'] === OverridesSectionStorage::FIELD_NAME) { + // Rebuild the label to include a warning about using translations with + // layouts. + $row['data'][1]['data']['field'] = [ + 'label' => $row['data'][1]['data']['field'], + 'description' => [ + '#type' => 'container', + '#markup' => $this->t('<strong>Warning</strong>: Layout Builder does not support translating layouts. (<a href="https://www.drupal.org/docs/8/core/modules/layout-builder/layout-builder-and-content-translation">online documentation</a>)'), + '#attributes' => [ + 'class' => [ + 'layout-builder-translation-warning', + ], + ], + ], + ]; + } + } + } + +} diff --git a/core/modules/layout_builder/tests/modules/layout_builder_block_content_dependency_test/layout_builder_block_content_dependency_test.module b/core/modules/layout_builder/tests/modules/layout_builder_block_content_dependency_test/layout_builder_block_content_dependency_test.module deleted file mode 100644 index 93bb03de404..00000000000 --- a/core/modules/layout_builder/tests/modules/layout_builder_block_content_dependency_test/layout_builder_block_content_dependency_test.module +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/** - * @file - * Provides hook implementations for testing Layout Builder with Block Content. - */ - -declare(strict_types=1); - -/** - * Implements hook_modules_installed(). - */ -function layout_builder_block_content_dependency_test_modules_installed(array $modules, bool $is_syncing): void { - // @see Drupal\Tests\layout_builder\Kernel\LayoutBuilderBlockContentDependencyTest - if (in_array('layout_builder', $modules)) { - \Drupal::service('plugin.manager.block')->getDefinitions(); - \Drupal::service('module_installer')->install(['block_content']); - } -} diff --git a/core/modules/layout_builder/tests/modules/layout_builder_block_content_dependency_test/src/Hook/LayoutBuilderBlockContentDependencyTestThemeHooks.php b/core/modules/layout_builder/tests/modules/layout_builder_block_content_dependency_test/src/Hook/LayoutBuilderBlockContentDependencyTestThemeHooks.php new file mode 100644 index 00000000000..1269020852c --- /dev/null +++ b/core/modules/layout_builder/tests/modules/layout_builder_block_content_dependency_test/src/Hook/LayoutBuilderBlockContentDependencyTestThemeHooks.php @@ -0,0 +1,28 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\layout_builder_block_content_dependency_test\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for layout_builder_block_content_dependency_test. + */ +class LayoutBuilderBlockContentDependencyTestThemeHooks { + + /** + * Implements hook_modules_installed(). + */ + #[Hook('modules_installed')] + public function modulesInstalled(array $modules, bool $is_syncing): void { + // @see Drupal\Tests\layout_builder\Kernel\LayoutBuilderBlockContentDependencyTest + if (in_array('layout_builder', $modules)) { + \Drupal::service('plugin.manager.block')->getDefinitions(); + \Drupal::service('module_installer')->install([ + 'block_content', + ]); + } + } + +} diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/BlockFilterTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/BlockFilterTest.php index 8fa2fa1dec5..60ae0570638 100644 --- a/core/modules/layout_builder/tests/src/FunctionalJavascript/BlockFilterTest.php +++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/BlockFilterTest.php @@ -116,7 +116,7 @@ class BlockFilterTest extends WebDriverTestBase { $visible_categories = $this->filterVisibleElements($categories); $this->assertCount(3, $visible_categories); - // Test blocks reappear after being filtered by repeating search for "a" + // Test blocks reappear after being filtered by repeating search for "a". $filter->setValue('a'); $this->assertAnnounceContains('All available blocks are listed.'); diff --git a/core/modules/layout_builder/tests/src/Unit/Plugin/ConfigAction/Deriver/AddComponentDeriverTest.php b/core/modules/layout_builder/tests/src/Unit/Plugin/ConfigAction/Deriver/AddComponentDeriverTest.php new file mode 100644 index 00000000000..b1545a8f737 --- /dev/null +++ b/core/modules/layout_builder/tests/src/Unit/Plugin/ConfigAction/Deriver/AddComponentDeriverTest.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\layout_builder\Unit\Plugin\ConfigAction\Deriver; + +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\layout_builder\Plugin\ConfigAction\Deriver\AddComponentDeriver; +use Drupal\layout_builder\SectionListInterface; +use Drupal\Core\Config\Entity\ConfigEntityInterface; +use Drupal\Tests\UnitTestCase; +use Prophecy\PhpUnit\ProphecyTrait; + +/** + * @coversDefaultClass \Drupal\layout_builder\Plugin\ConfigAction\Deriver\AddComponentDeriver + * @group layout_builder + */ +class AddComponentDeriverTest extends UnitTestCase { + + use ProphecyTrait; + + /** + * Tests derivative generation for entities implementing SectionListInterface. + * + * @covers ::getDerivativeDefinitions + */ + public function testGetDerivativeDefinitions(): void { + $entityTypeManager = $this->prophesize(EntityTypeManagerInterface::class); + $deriver = new AddComponentDeriver($entityTypeManager->reveal()); + $entity_types = []; + + // Create a mock entity type that implements both required interfaces. + $valid_entity_type = $this->prophesize(EntityTypeInterface::class); + $valid_entity_type->entityClassImplements(ConfigEntityInterface::class)->willReturn(TRUE); + $valid_entity_type->entityClassImplements(SectionListInterface::class)->willReturn(TRUE); + $valid_entity_type->id()->willReturn('valid_type'); + $entity_types['valid_type'] = $valid_entity_type->reveal(); + + // Create a mock entity type that only implements ConfigEntityInterface. + $config_only_type = $this->prophesize(EntityTypeInterface::class); + $config_only_type->entityClassImplements(ConfigEntityInterface::class)->willReturn(TRUE); + $config_only_type->entityClassImplements(SectionListInterface::class)->willReturn(FALSE); + $entity_types['config_only'] = $config_only_type->reveal(); + + // Create a mock entity type that only implements SectionListInterface. + $section_only_type = $this->prophesize(EntityTypeInterface::class); + $section_only_type->entityClassImplements(ConfigEntityInterface::class)->willReturn(FALSE); + $section_only_type->entityClassImplements(SectionListInterface::class)->willReturn(TRUE); + $entity_types['section_only'] = $section_only_type->reveal(); + + $entityTypeManager->getDefinitions()->willReturn($entity_types); + + $base_plugin_definition = []; + $derivatives = $deriver->getDerivativeDefinitions($base_plugin_definition); + + $this->assertCount(1, $derivatives, 'Only one derivative should be generated.'); + $this->assertArrayHasKey('addComponentToLayout', $derivatives, 'The derivative should be keyed by addComponentToLayout.'); + $this->assertEquals(['valid_type'], $derivatives['addComponentToLayout']['entity_types'], 'Only the valid entity type should be included in the derivative definition.'); + } + +} diff --git a/core/modules/link/src/Plugin/migrate/process/FieldLink.php b/core/modules/link/src/Plugin/migrate/process/FieldLink.php index 7509b8685f4..15d53779319 100644 --- a/core/modules/link/src/Plugin/migrate/process/FieldLink.php +++ b/core/modules/link/src/Plugin/migrate/process/FieldLink.php @@ -102,7 +102,7 @@ class FieldLink extends ProcessPluginBase { $link_domains = '[a-z][a-z0-9-]{1,62}'; // Starting a parenthesis group with (?: means that it is grouped, but - // is not captured + // is not captured. $authentication = "(?:(?:(?:[\w\.\-\+!$&'\(\)*\+,;=" . $link_i_chars . "]|%[0-9a-f]{2})+(?::(?:[\w" . $link_i_chars . "\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})*)?)?@)"; $domain = '(?:(?:[a-z0-9' . $link_i_chars . ']([a-z0-9' . $link_i_chars . '\-_\[\]])*)(\.(([a-z0-9' . $link_i_chars . '\-_\[\]])+\.)*(' . $link_domains . '|[a-z]{2}))?)'; $ipv4 = '(?:[0-9]{1,3}(\.[0-9]{1,3}){3})'; diff --git a/core/modules/link/tests/src/Functional/LinkFieldTest.php b/core/modules/link/tests/src/Functional/LinkFieldTest.php index bc5ba831b80..54e4dfbc8a7 100644 --- a/core/modules/link/tests/src/Functional/LinkFieldTest.php +++ b/core/modules/link/tests/src/Functional/LinkFieldTest.php @@ -188,9 +188,9 @@ class LinkFieldTest extends BrowserTestBase { $validation_error_2 = 'Manually entered paths should start with one of the following characters: / ? #'; $validation_error_3 = "The path '@link_path' is inaccessible."; $invalid_external_entries = [ - // Invalid protocol + // Invalid protocol. 'invalid://not-a-valid-protocol' => $validation_error_1, - // Missing host name + // Missing host name. 'http://' => $validation_error_1, ]; $invalid_internal_entries = [ diff --git a/core/modules/link/tests/src/Functional/Views/LinkViewsTokensTest.php b/core/modules/link/tests/src/Functional/Views/LinkViewsTokensTest.php index 159865cc8ea..c73347cc333 100644 --- a/core/modules/link/tests/src/Functional/Views/LinkViewsTokensTest.php +++ b/core/modules/link/tests/src/Functional/Views/LinkViewsTokensTest.php @@ -86,16 +86,16 @@ class LinkViewsTokensTest extends ViewTestBase { $this->drupalGet('test_link_tokens'); foreach ($uris as $uri => $title) { - // Formatted link: {{ field_link }}<br /> + // Formatted link: "{{ field_link }}<br />". $this->assertSession()->responseContains("Formatted: <a href=\"$uri\" class=\"test-link-class\">$title</a>"); - // Raw uri: {{ field_link__uri }}<br /> + // Raw uri: "{{ field_link__uri }}<br />". $this->assertSession()->responseContains("Raw uri: $uri"); - // Raw title: {{ field_link__title }}<br /> + // Raw title: "{{ field_link__title }}<br />". $this->assertSession()->responseContains("Raw title: $title"); - // Raw options: {{ field_link__options }}<br /> + // Raw options: "{{ field_link__options }}<br />". // Options is an array and should return empty after token replace. $this->assertSession()->responseContains("Raw options: ."); } diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc index 0cb5e905856..dd3ad4eee75 100644 --- a/core/modules/locale/locale.bulk.inc +++ b/core/modules/locale/locale.bulk.inc @@ -468,7 +468,8 @@ function locale_translate_file_attach_properties($file, array $options = []) { } // Extract project, version and language code from the file name. Supported: - // {project}-{version}.{langcode}.po, {prefix}.{langcode}.po or {langcode}.po + // "{project}-{version}.{langcode}.po", "{prefix}.{langcode}.po" or + // "{langcode}.po". preg_match('! ( # project OR project and version OR empty (group 1) ([a-z_]+) # project name (group 2) diff --git a/core/modules/locale/locale.compare.inc b/core/modules/locale/locale.compare.inc index d9ae64af89a..6d43d44ce9f 100644 --- a/core/modules/locale/locale.compare.inc +++ b/core/modules/locale/locale.compare.inc @@ -56,7 +56,7 @@ function locale_translation_build_projects() { // to fall back to the latest stable release for that branch. if (isset($data['info']['version']) && strpos($data['info']['version'], '-dev')) { if (preg_match("/^(\d+\.x-\d+\.).*$/", $data['info']['version'], $matches)) { - // Example matches: 8.x-1.x-dev, 8.x-1.0-alpha1+5-dev => 8.x-1.x + // Example matches: "8.x-1.x-dev", "8.x-1.0-alpha1+5-dev => 8.x-1.x". $data['info']['version'] = $matches[1] . 'x'; } elseif (preg_match("/^(\d+\.\d+\.).*$/", $data['info']['version'], $matches)) { diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install index d3377f3773e..87b2c223b2a 100644 --- a/core/modules/locale/locale.install +++ b/core/modules/locale/locale.install @@ -123,7 +123,7 @@ function locale_schema(): array { 'customized' => [ 'type' => 'int', 'not null' => TRUE, - // LOCALE_NOT_CUSTOMIZED + // LOCALE_NOT_CUSTOMIZED. 'default' => 0, 'description' => 'Boolean indicating whether the translation is custom to this site.', ], diff --git a/core/modules/locale/tests/src/Functional/LocalePluralFormatTest.php b/core/modules/locale/tests/src/Functional/LocalePluralFormatTest.php index 1bb919413b0..d4c42f730bd 100644 --- a/core/modules/locale/tests/src/Functional/LocalePluralFormatTest.php +++ b/core/modules/locale/tests/src/Functional/LocalePluralFormatTest.php @@ -221,7 +221,7 @@ class LocalePluralFormatTest extends BrowserTestBase { $this->drupalGet($path); $this->submitForm($edit, 'Save translations'); - // User interface input for translating seconds should not be duplicated + // User interface input for translating seconds should not be duplicated. $this->assertSession()->pageTextContainsOnce('@count seconds'); // Member for time should be translated. Change the created time to ensure diff --git a/core/modules/media/media.module b/core/modules/media/media.module index dbf031d16a9..69cb62eddc5 100644 --- a/core/modules/media/media.module +++ b/core/modules/media/media.module @@ -7,8 +7,6 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Hook\Attribute\ProceduralHookScanStop; use Drupal\Core\Render\Element; -use Drupal\Core\Render\Element\RenderElementBase; -use Drupal\Core\Template\Attribute; use Drupal\Core\Url; /** @@ -35,31 +33,6 @@ function template_preprocess_media(array &$variables): void { } /** - * Implements hook_preprocess_HOOK() for media reference widgets. - */ -function media_preprocess_media_reference_help(&$variables): void { - // Most of these attribute checks are copied from - // template_preprocess_fieldset(). Our template extends - // field-multiple-value-form.html.twig to provide our help text, but also - // groups the information within a semantic fieldset with a legend. So, we - // incorporate parity for both. - $element = $variables['element']; - Element::setAttributes($element, ['id']); - RenderElementBase::setAttributes($element); - $variables['attributes'] = $element['#attributes'] ?? []; - $variables['legend_attributes'] = new Attribute(); - $variables['header_attributes'] = new Attribute(); - $variables['description']['attributes'] = new Attribute(); - $variables['legend_span_attributes'] = new Attribute(); - - if (!empty($element['#media_help'])) { - foreach ($element['#media_help'] as $key => $text) { - $variables[substr($key, 1)] = $text; - } - } -} - -/** * Returns the appropriate URL to add media for the current user. * * @todo Remove in https://www.drupal.org/project/drupal/issues/2938116 diff --git a/core/modules/media/src/Hook/MediaThemeHooks.php b/core/modules/media/src/Hook/MediaThemeHooks.php new file mode 100644 index 00000000000..e6dc956377b --- /dev/null +++ b/core/modules/media/src/Hook/MediaThemeHooks.php @@ -0,0 +1,42 @@ +<?php + +namespace Drupal\media\Hook; + +use Drupal\Core\Template\Attribute; +use Drupal\Core\Render\Element\RenderElementBase; +use Drupal\Core\Render\Element; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for media. + */ +class MediaThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for media reference widgets. + */ + #[Hook('preprocess_media_reference_help')] + public function preprocessMediaReferenceHelp(&$variables): void { + // Most of these attribute checks are copied from + // template_preprocess_fieldset(). Our template extends + // field-multiple-value-form.html.twig to provide our help text, but also + // groups the information within a semantic fieldset with a legend. So, we + // incorporate parity for both. + $element = $variables['element']; + Element::setAttributes($element, [ + 'id', + ]); + RenderElementBase::setAttributes($element); + $variables['attributes'] = $element['#attributes'] ?? []; + $variables['legend_attributes'] = new Attribute(); + $variables['header_attributes'] = new Attribute(); + $variables['description']['attributes'] = new Attribute(); + $variables['legend_span_attributes'] = new Attribute(); + if (!empty($element['#media_help'])) { + foreach ($element['#media_help'] as $key => $text) { + $variables[substr($key, 1)] = $text; + } + } + } + +} diff --git a/core/modules/media_library/media_library.module b/core/modules/media_library/media_library.module index 2bd0c676c36..dfee569978d 100644 --- a/core/modules/media_library/media_library.module +++ b/core/modules/media_library/media_library.module @@ -8,7 +8,6 @@ use Drupal\Core\Entity\Entity\EntityFormDisplay; use Drupal\Core\Entity\Entity\EntityViewDisplay; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; -use Drupal\Core\Template\Attribute; use Drupal\image\Entity\ImageStyle; use Drupal\image\Plugin\Field\FieldType\ImageItem; use Drupal\media\MediaTypeInterface; @@ -46,26 +45,6 @@ function template_preprocess_media_library_item(array &$variables): void { } /** - * Implements hook_preprocess_media(). - */ -function media_library_preprocess_media(&$variables): void { - if ($variables['view_mode'] === 'media_library') { - /** @var \Drupal\media\MediaInterface $media */ - $media = $variables['media']; - $variables['#cache']['contexts'][] = 'user.permissions'; - $rel = $media->access('edit') ? 'edit-form' : 'canonical'; - $variables['url'] = $media->toUrl($rel, [ - 'language' => $media->language(), - ]); - $variables += [ - 'preview_attributes' => new Attribute(), - 'metadata_attributes' => new Attribute(), - ]; - $variables['status'] = $media->isPublished(); - } -} - -/** * Implements hook_preprocess_views_view() for the 'media_library' view. */ function media_library_preprocess_views_view__media_library(array &$variables): void { @@ -73,19 +52,6 @@ function media_library_preprocess_views_view__media_library(array &$variables): } /** - * Implements hook_preprocess_views_view_fields(). - */ -function media_library_preprocess_views_view_fields(&$variables): void { - // Add classes to media rendered entity field so it can be targeted for - // JavaScript mouseover and click events. - if ($variables['view']->id() === 'media_library' && isset($variables['fields']['rendered_entity'])) { - if (isset($variables['fields']['rendered_entity']->wrapper_attributes)) { - $variables['fields']['rendered_entity']->wrapper_attributes->addClass('js-click-to-select-trigger'); - } - } -} - -/** * Form #after_build callback for media_library view's exposed filters form. */ function _media_library_views_form_media_library_after_build(array $form, FormStateInterface $form_state) { diff --git a/core/modules/media_library/src/Form/FileUploadForm.php b/core/modules/media_library/src/Form/FileUploadForm.php index e9e25f108fc..892f76dbc10 100644 --- a/core/modules/media_library/src/Form/FileUploadForm.php +++ b/core/modules/media_library/src/Form/FileUploadForm.php @@ -166,7 +166,7 @@ class FileUploadForm extends AddFormBase { '#process' => array_merge(['::validateUploadElement'], $process, ['::processUploadElement']), '#upload_validators' => $item->getUploadValidators(), // Set multiple to true only if available slots is not exactly one - // to ensure correct language (singular or plural) in UI + // to ensure correct language (singular or plural) in UI. '#multiple' => $slots != 1 ? TRUE : FALSE, // Do not limit the number uploaded. There is validation based on the // number selected in the media library that prevents overages. diff --git a/core/modules/media_library/src/Hook/MediaLibraryThemeHooks.php b/core/modules/media_library/src/Hook/MediaLibraryThemeHooks.php new file mode 100644 index 00000000000..68890191ef8 --- /dev/null +++ b/core/modules/media_library/src/Hook/MediaLibraryThemeHooks.php @@ -0,0 +1,48 @@ +<?php + +namespace Drupal\media_library\Hook; + +use Drupal\Core\Template\Attribute; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for media_library. + */ +class MediaLibraryThemeHooks { + + /** + * Implements hook_preprocess_media(). + */ + #[Hook('preprocess_media')] + public function preprocessMedia(&$variables): void { + if ($variables['view_mode'] === 'media_library') { + /** @var \Drupal\media\MediaInterface $media */ + $media = $variables['media']; + $variables['#cache']['contexts'][] = 'user.permissions'; + $rel = $media->access('edit') ? 'edit-form' : 'canonical'; + $variables['url'] = $media->toUrl($rel, [ + 'language' => $media->language(), + ]); + $variables += [ + 'preview_attributes' => new Attribute(), + 'metadata_attributes' => new Attribute(), + ]; + $variables['status'] = $media->isPublished(); + } + } + + /** + * Implements hook_preprocess_views_view_fields(). + */ + #[Hook('preprocess_views_view_fields')] + public function preprocessViewsViewFields(&$variables): void { + // Add classes to media rendered entity field so it can be targeted for + // JavaScript mouseover and click events. + if ($variables['view']->id() === 'media_library' && isset($variables['fields']['rendered_entity'])) { + if (isset($variables['fields']['rendered_entity']->wrapper_attributes)) { + $variables['fields']['rendered_entity']->wrapper_attributes->addClass('js-click-to-select-trigger'); + } + } + } + +} diff --git a/core/modules/media_library/tests/src/FunctionalJavascript/WidgetUploadTest.php b/core/modules/media_library/tests/src/FunctionalJavascript/WidgetUploadTest.php index 86cee3e17ad..736da735412 100644 --- a/core/modules/media_library/tests/src/FunctionalJavascript/WidgetUploadTest.php +++ b/core/modules/media_library/tests/src/FunctionalJavascript/WidgetUploadTest.php @@ -208,7 +208,7 @@ class WidgetUploadTest extends MediaLibraryTestBase { // Assert we can now only upload one more media item. $this->openMediaLibraryForField('field_twin_media'); $this->switchToMediaType('Four'); - // We set the multiple to FALSE if only one file can be uploaded + // We set the multiple to FALSE if only one file can be uploaded. $this->assertFalse($assert_session->fieldExists('Add file')->hasAttribute('multiple')); $assert_session->pageTextContains('One file only.'); $choose_files = $assert_session->elementExists('css', '.form-managed-file'); @@ -559,7 +559,7 @@ class WidgetUploadTest extends MediaLibraryTestBase { $this->openMediaLibraryForField('field_twin_media'); $this->switchToMediaType('Four'); - // We set the multiple to FALSE if only one file can be uploaded + // We set the multiple to FALSE if only one file can be uploaded. $this->assertFalse($assert_session->fieldExists('Add file')->hasAttribute('multiple')); $assert_session->pageTextContains('One file only.'); $choose_files = $assert_session->elementExists('css', '.form-managed-file'); diff --git a/core/modules/menu_link_content/tests/src/Functional/MenuLinkContentDeleteFormTest.php b/core/modules/menu_link_content/tests/src/Functional/MenuLinkContentDeleteFormTest.php index f9239e7f392..dd68b58273e 100644 --- a/core/modules/menu_link_content/tests/src/Functional/MenuLinkContentDeleteFormTest.php +++ b/core/modules/menu_link_content/tests/src/Functional/MenuLinkContentDeleteFormTest.php @@ -50,7 +50,7 @@ class MenuLinkContentDeleteFormTest extends BrowserTestBase { $this->drupalGet($menu_link->toUrl('delete-form')); $this->assertSession()->pageTextContains("Are you sure you want to delete the custom menu link {$menu_link->label()}?"); $this->assertSession()->linkExists('Cancel'); - // Make sure cancel link points to link edit + // Make sure cancel link points to link edit. $this->assertSession()->linkByHrefExists($menu_link->toUrl('edit-form')->toString()); \Drupal::service('module_installer')->install(['menu_ui']); diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module index cf543258433..63f31d60e9d 100644 --- a/core/modules/menu_ui/menu_ui.module +++ b/core/modules/menu_ui/menu_ui.module @@ -223,12 +223,3 @@ function menu_ui_form_node_type_form_builder($entity_type, NodeTypeInterface $ty $type->setThirdPartySetting('menu_ui', 'available_menus', array_values(array_filter($form_state->getValue('menu_options')))); $type->setThirdPartySetting('menu_ui', 'parent', $form_state->getValue('menu_parent')); } - -/** - * Implements hook_preprocess_HOOK() for block templates. - */ -function menu_ui_preprocess_block(&$variables): void { - if ($variables['configuration']['provider'] == 'menu_ui') { - $variables['attributes']['role'] = 'navigation'; - } -} diff --git a/core/modules/menu_ui/src/Hook/MenuUiThemeHooks.php b/core/modules/menu_ui/src/Hook/MenuUiThemeHooks.php new file mode 100644 index 00000000000..e8f8d47aa1f --- /dev/null +++ b/core/modules/menu_ui/src/Hook/MenuUiThemeHooks.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\menu_ui\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for menu_ui. + */ +class MenuUiThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for block templates. + */ + #[Hook('preprocess_block')] + public function preprocessBlock(&$variables): void { + if ($variables['configuration']['provider'] == 'menu_ui') { + $variables['attributes']['role'] = 'navigation'; + } + } + +} diff --git a/core/modules/migrate/src/MigrateExecutable.php b/core/modules/migrate/src/MigrateExecutable.php index a087ae6875e..2cf3a322351 100644 --- a/core/modules/migrate/src/MigrateExecutable.php +++ b/core/modules/migrate/src/MigrateExecutable.php @@ -106,7 +106,7 @@ class MigrateExecutable implements MigrateExecutableInterface { $this->message = $message ?: new MigrateMessage(); $this->getIdMap()->setMessage($this->message); $this->eventDispatcher = $event_dispatcher; - // Record the memory limit in bytes + // Record the memory limit in bytes. $limit = trim(ini_get('memory_limit')); if ($limit == '-1') { $this->memoryLimit = PHP_INT_MAX; @@ -557,7 +557,7 @@ class MigrateExecutable implements MigrateExecutableInterface { $usage = $this->attemptMemoryReclaim(); $pct_memory = $usage / $this->memoryLimit; // Use a lower threshold - we don't want to be in a situation where we - // keep coming back here and trimming a tiny amount + // keep coming back here and trimming a tiny amount. if ($pct_memory > (0.90 * $threshold)) { $this->message->display( $this->t( diff --git a/core/modules/migrate/src/Plugin/migrate/destination/Config.php b/core/modules/migrate/src/Plugin/migrate/destination/Config.php index c77de935a52..2e6c26a1684 100644 --- a/core/modules/migrate/src/Plugin/migrate/destination/Config.php +++ b/core/modules/migrate/src/Plugin/migrate/destination/Config.php @@ -234,7 +234,7 @@ class Config extends DestinationBase implements ContainerFactoryPluginInterface, return 'config_translation'; } // Get the module handling this configuration object from the config_name, - // which is of the form <module_name>.<configuration object name> + // which is of the form "<module_name>.<configuration object name>". return !empty($this->configuration['config_name']) ? explode('.', $this->configuration['config_name'], 2)[0] : NULL; } diff --git a/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php index 40dea1c7a2b..0aefdd99de2 100644 --- a/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php +++ b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php @@ -424,7 +424,7 @@ abstract class SqlBase extends SourcePluginBase implements ContainerFactoryPlugi } // If we are tracking changes, we also need to retrieve all rows to compare - // hashes + // hashes. if ($this->trackChanges) { return FALSE; } diff --git a/core/modules/migrate/tests/src/Functional/MigrateMessageFormTest.php b/core/modules/migrate/tests/src/Functional/MigrateMessageFormTest.php index cfbcdf5b4df..22f6c4fbc46 100644 --- a/core/modules/migrate/tests/src/Functional/MigrateMessageFormTest.php +++ b/core/modules/migrate/tests/src/Functional/MigrateMessageFormTest.php @@ -45,7 +45,7 @@ class MigrateMessageFormTest extends MigrateMessageTestBase { $this->assertEquals($expected_count, $count[$level], sprintf('Count for level %s failed', $level)); } - // Reset the filter + // Reset the filter. $this->submitForm([], 'Reset'); $messages = $this->getMessages(); $this->assertCount(4, $messages); diff --git a/core/modules/migrate/tests/src/Unit/MigrateSourceTest.php b/core/modules/migrate/tests/src/Unit/MigrateSourceTest.php index e344e3e23e8..77e4cf64e64 100644 --- a/core/modules/migrate/tests/src/Unit/MigrateSourceTest.php +++ b/core/modules/migrate/tests/src/Unit/MigrateSourceTest.php @@ -426,7 +426,7 @@ class MigrateSourceTest extends MigrateTestCase { $migration = $this->getMigration(); $source = new StubSourceGeneratorPlugin([], '', [], $migration); - // Test the default value of the skipCount Value; + // Test the default value of the skipCount Value. $this->assertTrue($source->getSkipCount()); $this->assertTrue($source->getCacheCounts()); $this->assertTrue($source->getTrackChanges()); diff --git a/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php index 1cabbebdde6..aefd45d0438 100644 --- a/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php +++ b/core/modules/migrate/tests/src/Unit/Plugin/migrate/destination/EntityContentBaseTest.php @@ -47,7 +47,7 @@ class EntityContentBaseTest extends EntityTestBase { // Syncing should be set once. $entity->setSyncing(Argument::exact(TRUE)) ->shouldBeCalledTimes(1); - // Set an id for the entity + // Set an id for the entity. $entity->id() ->willReturn(5); $destination->setEntity($entity->reveal()); diff --git a/core/modules/migrate_drupal_ui/tests/src/Kernel/MigrationLabelExistTest.php b/core/modules/migrate_drupal_ui/tests/src/Kernel/MigrationLabelExistTest.php index 70741c025e9..257d9292a5d 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Kernel/MigrationLabelExistTest.php +++ b/core/modules/migrate_drupal_ui/tests/src/Kernel/MigrationLabelExistTest.php @@ -29,7 +29,7 @@ class MigrationLabelExistTest extends MigrateDrupalTestBase { /** @var \Drupal\migrate\Plugin\MigrationPluginManager $plugin_manager */ $plugin_manager = $this->container->get('plugin.manager.migration'); - // Get all the migrations + // Get all the migrations. $migrations = $plugin_manager->createInstances(array_keys($plugin_manager->getDefinitions())); /** @var \Drupal\migrate\Plugin\Migration $migration */ foreach ($migrations as $migration) { diff --git a/core/modules/navigation/config/schema/navigation.schema.yml b/core/modules/navigation/config/schema/navigation.schema.yml index ee31849202a..b4a2eca5dbd 100644 --- a/core/modules/navigation/config/schema/navigation.schema.yml +++ b/core/modules/navigation/config/schema/navigation.schema.yml @@ -32,22 +32,19 @@ navigation.settings: label: 'Maximum file sizes (bytes)' constraints: NotNull: [ ] - Range: - min: 0 + PositiveOrZero: ~ height: type: integer label: 'Logo expected height' constraints: NotNull: [ ] - Range: - min: 0 + PositiveOrZero: ~ width: type: integer label: 'Logo expected width' constraints: NotNull: [ ] - Range: - min: 0 + PositiveOrZero: ~ constraints: ValidKeys: '<infer>' constraints: diff --git a/core/modules/navigation/tests/navigation_test/src/Hook/NavigationTestHooks.php b/core/modules/navigation/tests/navigation_test/src/Hook/NavigationTestHooks.php index b61a694e80f..0bdede27721 100644 --- a/core/modules/navigation/tests/navigation_test/src/Hook/NavigationTestHooks.php +++ b/core/modules/navigation/tests/navigation_test/src/Hook/NavigationTestHooks.php @@ -97,7 +97,7 @@ class NavigationTestHooks { unset($tree[$key]); } - // Updates title for items in menu2 + // Updates title for items in menu2. if ($menu_name == 'menu2') { $item->link->updateLink(['title' => 'New Link Title'], FALSE); } diff --git a/core/modules/navigation/tests/src/Functional/NavigationLinkBlockTest.php b/core/modules/navigation/tests/src/Functional/NavigationLinkBlockTest.php index 0f385c5f1ca..f40d63935ea 100644 --- a/core/modules/navigation/tests/src/Functional/NavigationLinkBlockTest.php +++ b/core/modules/navigation/tests/src/Functional/NavigationLinkBlockTest.php @@ -162,7 +162,7 @@ class NavigationLinkBlockTest extends PageCacheTagsTestBase { $this->assertSession()->pageTextNotContains($help_link_title); // Enable Help module and grant permissions to admin user. - // Admin user should be capable to access to all the links + // Admin user should be capable to access to all the links. \Drupal::service('module_installer')->install(['help']); $this->adminUser->addRole($this->drupalCreateRole(['access help pages']))->save(); diff --git a/core/modules/navigation/tests/src/FunctionalJavascript/NavigationBlockUiTest.php b/core/modules/navigation/tests/src/FunctionalJavascript/NavigationBlockUiTest.php index 90b6874c6bc..3af1d714f8d 100644 --- a/core/modules/navigation/tests/src/FunctionalJavascript/NavigationBlockUiTest.php +++ b/core/modules/navigation/tests/src/FunctionalJavascript/NavigationBlockUiTest.php @@ -133,7 +133,7 @@ class NavigationBlockUiTest extends WebDriverTestBase { $this->getSession()->getPage()->pressButton('Enable edit mode'); $this->assertSession()->assertWaitOnAjaxRequest(); - // Add section should not be present + // Add section should not be present. $this->assertSession()->linkNotExists('Add section'); // Configure section should not be present. $this->assertSession()->linkNotExists('Configure Section 1'); diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 6841f24b96b..c99569a1c67 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -109,10 +109,11 @@ function node_type_get_names() { * @return string|false * The node type label or FALSE if the node type is not found. * - * @todo Add this as generic helper method for config entities representing - * entity bundles. + * @deprecated in drupal:11.3.0 and is removed from drupal:13.0.0. Use $node->getBundleEntity()->label() instead. + * @see https://www.drupal.org/node/3533301 */ function node_get_type_label(NodeInterface $node) { + @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.3.0 and is removed from drupal:13.0.0. Use $node->getBundleEntity()->label(). See https://www.drupal.org/node/3533301', E_USER_DEPRECATED); $type = NodeType::load($node->bundle()); return $type ? $type->label() : FALSE; } @@ -558,7 +559,7 @@ function node_access_rebuild($batch_mode = FALSE): void { } } else { - // Try to allocate enough time to rebuild node grants + // Try to allocate enough time to rebuild node grants. Environment::setTimeLimit(240); // Rebuild newest nodes first so that recent content becomes available diff --git a/core/modules/node/src/Form/NodeForm.php b/core/modules/node/src/Form/NodeForm.php index 295e9ab78ce..5498c94c497 100644 --- a/core/modules/node/src/Form/NodeForm.php +++ b/core/modules/node/src/Form/NodeForm.php @@ -125,7 +125,7 @@ class NodeForm extends ContentEntityForm { if ($this->operation == 'edit') { $form['#title'] = $this->t('<em>Edit @type</em> @title', [ - '@type' => node_get_type_label($node), + '@type' => $node->getBundleEntity()->label(), '@title' => $node->label(), ]); } @@ -284,7 +284,7 @@ class NodeForm extends ContentEntityForm { $node->save(); $node_link = $node->toLink($this->t('View'))->toString(); $context = ['@type' => $node->getType(), '%title' => $node->label(), 'link' => $node_link]; - $t_args = ['@type' => node_get_type_label($node), '%title' => $node->access('view') ? $node->toLink()->toString() : $node->label()]; + $t_args = ['@type' => $node->getBundleEntity()->label(), '%title' => $node->access('view') ? $node->toLink()->toString() : $node->label()]; if ($insert) { $this->logger('content')->info('@type: added %title.', $context); diff --git a/core/modules/node/src/Form/NodeRevisionRevertForm.php b/core/modules/node/src/Form/NodeRevisionRevertForm.php index ffb58fb71fb..a1e04e2942d 100644 --- a/core/modules/node/src/Form/NodeRevisionRevertForm.php +++ b/core/modules/node/src/Form/NodeRevisionRevertForm.php @@ -136,7 +136,7 @@ class NodeRevisionRevertForm extends ConfirmFormBase { $this->logger('content')->info('@type: reverted %title revision %revision.', ['@type' => $this->revision->bundle(), '%title' => $this->revision->label(), '%revision' => $this->revision->getRevisionId()]); $this->messenger() ->addStatus($this->t('@type %title has been reverted to the revision from %revision-date.', [ - '@type' => node_get_type_label($this->revision), + '@type' => $this->revision->getBundleEntity()->label(), '%title' => $this->revision->label(), '%revision-date' => $this->dateFormatter->format($original_revision_timestamp), ])); diff --git a/core/modules/node/src/Hook/NodeHooks1.php b/core/modules/node/src/Hook/NodeHooks1.php index d2dbf545c3c..e103717fb61 100644 --- a/core/modules/node/src/Hook/NodeHooks1.php +++ b/core/modules/node/src/Hook/NodeHooks1.php @@ -219,7 +219,7 @@ class NodeHooks1 { $ranking = [ 'relevance' => [ 'title' => $this->t('Keyword relevance'), - // Average relevance values hover around 0.15 + // Average relevance values hover around 0.15. 'score' => 'i.relevance', ], 'sticky' => [ diff --git a/core/modules/node/src/Hook/NodeTokensHooks.php b/core/modules/node/src/Hook/NodeTokensHooks.php index 3d7f0b0adf4..a7a90347313 100644 --- a/core/modules/node/src/Hook/NodeTokensHooks.php +++ b/core/modules/node/src/Hook/NodeTokensHooks.php @@ -109,7 +109,7 @@ class NodeTokensHooks { break; case 'type-name': - $type_name = node_get_type_label($node); + $type_name = $node->getBundleEntity()->label(); $replacements[$original] = $type_name; break; diff --git a/core/modules/node/src/Hook/NodeViewsHooks.php b/core/modules/node/src/Hook/NodeViewsHooks.php index 477784c153d..8729f547c17 100644 --- a/core/modules/node/src/Hook/NodeViewsHooks.php +++ b/core/modules/node/src/Hook/NodeViewsHooks.php @@ -26,7 +26,7 @@ class NodeViewsHooks { if ($view->storage->get('base_table') == 'node') { foreach ($view->displayHandlers as $display) { if (!$display->isDefaulted('access') || !$display->isDefaulted('filters')) { - // Check for no access control + // Check for no access control. $access = $display->getOption('access'); if (empty($access['type']) || $access['type'] == 'none') { $anonymous_role = Role::load(RoleInterface::ANONYMOUS_ID); diff --git a/core/modules/node/src/NodeListBuilder.php b/core/modules/node/src/NodeListBuilder.php index 0fa80dee411..2b356eb2b34 100644 --- a/core/modules/node/src/NodeListBuilder.php +++ b/core/modules/node/src/NodeListBuilder.php @@ -95,7 +95,7 @@ class NodeListBuilder extends EntityListBuilder { '#title' => $entity->label(), '#url' => $entity->toUrl(), ]; - $row['type'] = node_get_type_label($entity); + $row['type'] = $entity->getBundleEntity()->label(); $row['author']['data'] = [ '#theme' => 'username', '#account' => $entity->getOwner(), diff --git a/core/modules/node/src/NodeTranslationHandler.php b/core/modules/node/src/NodeTranslationHandler.php index 6c802440f37..88a3680a572 100644 --- a/core/modules/node/src/NodeTranslationHandler.php +++ b/core/modules/node/src/NodeTranslationHandler.php @@ -50,8 +50,7 @@ class NodeTranslationHandler extends ContentTranslationHandler { * {@inheritdoc} */ protected function entityFormTitle(EntityInterface $entity) { - $type_name = node_get_type_label($entity); - return $this->t('<em>Edit @type</em> @title', ['@type' => $type_name, '@title' => $entity->label()]); + return $this->t('<em>Edit @type</em> @title', ['@type' => $entity->getBundleEntity()->label(), '@title' => $entity->label()]); } /** diff --git a/core/modules/node/src/Plugin/views/wizard/Node.php b/core/modules/node/src/Plugin/views/wizard/Node.php index d66fa956f9a..bef4ddc8da5 100644 --- a/core/modules/node/src/Plugin/views/wizard/Node.php +++ b/core/modules/node/src/Plugin/views/wizard/Node.php @@ -92,7 +92,7 @@ class Node extends WizardPluginBase { * {@inheritdoc} */ public function getAvailableSorts() { - // You can't execute functions in properties, so override the method + // You can't execute functions in properties, so override the method. return [ 'node_field_data-title:ASC' => $this->t('Title'), ]; diff --git a/core/modules/node/tests/modules/node_test/src/Hook/NodeTestHooks.php b/core/modules/node/tests/modules/node_test/src/Hook/NodeTestHooks.php index 201e781d196..11753f8ca2f 100644 --- a/core/modules/node/tests/modules/node_test/src/Hook/NodeTestHooks.php +++ b/core/modules/node/tests/modules/node_test/src/Hook/NodeTestHooks.php @@ -130,7 +130,7 @@ class NodeTestHooks { #[Hook('node_presave')] public function nodePresave(NodeInterface $node): void { if ($node->getTitle() == 'testing_node_presave') { - // Sun, 19 Nov 1978 05:00:00 GMT + // Sun, 19 Nov 1978 05:00:00 GMT. $node->setCreatedTime(280299600); // Drupal 1.0 release. $node->changed = 979534800; diff --git a/core/modules/node/tests/src/Functional/NodeAccessBaseTableTest.php b/core/modules/node/tests/src/Functional/NodeAccessBaseTableTest.php index 2e584f3b826..9eba7e9614d 100644 --- a/core/modules/node/tests/src/Functional/NodeAccessBaseTableTest.php +++ b/core/modules/node/tests/src/Functional/NodeAccessBaseTableTest.php @@ -128,7 +128,7 @@ class NodeAccessBaseTableTest extends NodeTestBase { $num_simple_users = 2; $simple_users = []; - // Nodes keyed by uid and nid: $nodes[$uid][$nid] = $is_private; + // Nodes keyed by uid and nid: "$nodes[$uid][$nid] = $is_private". $this->nodesByUser = []; // Titles keyed by nid. $titles = []; diff --git a/core/modules/node/tests/src/Functional/NodeAccessGrantsCacheContextTest.php b/core/modules/node/tests/src/Functional/NodeAccessGrantsCacheContextTest.php index 27385e9666b..e67b27d4c3f 100644 --- a/core/modules/node/tests/src/Functional/NodeAccessGrantsCacheContextTest.php +++ b/core/modules/node/tests/src/Functional/NodeAccessGrantsCacheContextTest.php @@ -171,7 +171,7 @@ class NodeAccessGrantsCacheContextTest extends NodeTestBase { 3 => 'view.all', ]); - // Uninstall the node_access_test module + // Uninstall the node_access_test module. $this->container->get('module_installer')->uninstall(['node_access_test']); drupal_static_reset('node_access_view_all_nodes'); $this->assertUserCacheContext([ diff --git a/core/modules/node/tests/src/Functional/NodeTranslationUITest.php b/core/modules/node/tests/src/Functional/NodeTranslationUITest.php index ac1e8664bad..42c4df88d3a 100644 --- a/core/modules/node/tests/src/Functional/NodeTranslationUITest.php +++ b/core/modules/node/tests/src/Functional/NodeTranslationUITest.php @@ -479,7 +479,7 @@ class NodeTranslationUITest extends ContentTranslationUITestBase { ->getStorage($this->entityTypeId); $entity = $storage->load($this->entityId); $languages = $this->container->get('language_manager')->getLanguages(); - $type_name = node_get_type_label($entity); + $type_name = $entity->getBundleEntity()->label(); foreach ($this->langcodes as $langcode) { // We only want to test the title for non-english translations. diff --git a/core/modules/node/tests/src/Functional/NodeTypeTest.php b/core/modules/node/tests/src/Functional/NodeTypeTest.php index 4169d88f492..d26e4cef58d 100644 --- a/core/modules/node/tests/src/Functional/NodeTypeTest.php +++ b/core/modules/node/tests/src/Functional/NodeTypeTest.php @@ -147,7 +147,7 @@ class NodeTypeTest extends NodeTestBase { $assert->pageTextContains('Foo'); $assert->pageTextContains('Body'); - // Change the name through the API + // Change the name through the API. /** @var \Drupal\node\NodeTypeInterface $node_type */ $node_type = NodeType::load('page'); $node_type->set('name', 'NewBar'); @@ -277,7 +277,7 @@ class NodeTypeTest extends NodeTestBase { $this->drupalGet('admin/structure/types/manage/page/delete'); $this->submitForm([], 'Delete'); - // Navigate to content type administration screen + // Navigate to content type administration screen. $this->drupalGet('admin/structure/types'); $this->assertSession()->pageTextContains("No content types available. Add content type."); $this->assertSession()->linkExists("Add content type"); diff --git a/core/modules/node/tests/src/Functional/Views/NodeFieldTokensTest.php b/core/modules/node/tests/src/Functional/Views/NodeFieldTokensTest.php index e7f060fe3d4..59c33a921e7 100644 --- a/core/modules/node/tests/src/Functional/Views/NodeFieldTokensTest.php +++ b/core/modules/node/tests/src/Functional/Views/NodeFieldTokensTest.php @@ -53,16 +53,16 @@ class NodeFieldTokensTest extends NodeTestBase { $this->drupalGet('test_node_tokens'); - // Body: {{ body }}<br /> + // Body: "{{ body }}<br />". $this->assertSession()->responseContains("Body: <p>$body</p>"); - // Raw value: {{ body__value }}<br /> + // Raw value: "{{ body__value }}<br />". $this->assertSession()->responseContains("Raw value: $body"); - // Raw summary: {{ body__summary }}<br /> + // Raw summary: "{{ body__summary }}<br />". $this->assertSession()->responseContains("Raw summary: $summary"); - // Raw format: {{ body__format }}<br /> + // Raw format: "{{ body__format }}<br />". $this->assertSession()->responseContains("Raw format: plain_text"); } diff --git a/core/modules/node/tests/src/Kernel/NodeFieldAccessTest.php b/core/modules/node/tests/src/Kernel/NodeFieldAccessTest.php index cfad6986f1e..b69ca50f1be 100644 --- a/core/modules/node/tests/src/Kernel/NodeFieldAccessTest.php +++ b/core/modules/node/tests/src/Kernel/NodeFieldAccessTest.php @@ -82,7 +82,7 @@ class NodeFieldAccessTest extends EntityKernelTestBase { // An unprivileged user. $page_unrelated_user = $this->createUser(['access content']); - // List of all users + // List of all users. $test_users = [ $content_admin_user, $page_creator_user, diff --git a/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php b/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php index 99543ffe90c..56923d7f9c2 100644 --- a/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php +++ b/core/modules/options/tests/src/Functional/OptionsWidgetsTest.php @@ -347,7 +347,7 @@ class OptionsWidgetsTest extends FieldTestBase { $this->card1->setSetting('allowed_values_function', '\Drupal\options_test\OptionsAllowedValues::simpleValues'); $this->card1->save(); - // Display form: with no field data, nothing is selected + // Display form: with no field data, nothing is selected. $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertFalse($this->assertSession()->optionExists('card_1', 0)->isSelected()); $this->assertFalse($this->assertSession()->optionExists('card_1', 1)->isSelected()); diff --git a/core/modules/package_manager/config/schema/package_manager.schema.yml b/core/modules/package_manager/config/schema/package_manager.schema.yml index e048fd67a73..8b304d8352d 100644 --- a/core/modules/package_manager/config/schema/package_manager.schema.yml +++ b/core/modules/package_manager/config/schema/package_manager.schema.yml @@ -11,11 +11,21 @@ package_manager.settings: label: 'Package Manager settings' mapping: executables: - type: sequence + type: mapping label: 'Absolute paths to required executables, or NULL to rely on PATH' - sequence: - type: string - label: 'Absolute path to executable, or NULL' + mapping: + composer: + type: string + label: 'Absolute path to Composer executable, or NULL to auto-detect' + nullable: true + constraints: + IsExecutable: [] + rsync: + type: string + label: 'Absolute path to rsync executable, or NULL to auto-detect' + nullable: true + constraints: + IsExecutable: [] additional_trusted_composer_plugins: type: sequence label: 'Additional trusted composer plugins' diff --git a/core/modules/package_manager/package_manager.info.yml b/core/modules/package_manager/package_manager.info.yml index 20cd7bca565..8131f7db3ac 100644 --- a/core/modules/package_manager/package_manager.info.yml +++ b/core/modules/package_manager/package_manager.info.yml @@ -7,3 +7,4 @@ lifecycle: experimental dependencies: - drupal:update hidden: true +configure: package_manager.settings diff --git a/core/modules/package_manager/package_manager.links.menu.yml b/core/modules/package_manager/package_manager.links.menu.yml new file mode 100644 index 00000000000..44fdbfb730b --- /dev/null +++ b/core/modules/package_manager/package_manager.links.menu.yml @@ -0,0 +1,5 @@ +package_manager.settings: + title: 'Package Manager settings' + description: "Configure Package Manager and the locations of its required executables." + parent: system.admin_config_system + route_name: package_manager.settings diff --git a/core/modules/package_manager/package_manager.routing.yml b/core/modules/package_manager/package_manager.routing.yml new file mode 100644 index 00000000000..c61029bfa9c --- /dev/null +++ b/core/modules/package_manager/package_manager.routing.yml @@ -0,0 +1,7 @@ +package_manager.settings: + path: '/admin/config/system/package-manager' + defaults: + _title: 'Package Manager settings' + _form: '\Drupal\package_manager\Form\SettingsForm' + requirements: + _permission: 'administer software updates' diff --git a/core/modules/package_manager/package_manager.services.yml b/core/modules/package_manager/package_manager.services.yml index 059be554270..ead88254823 100644 --- a/core/modules/package_manager/package_manager.services.yml +++ b/core/modules/package_manager/package_manager.services.yml @@ -14,9 +14,6 @@ services: Drupal\package_manager\ExecutableFinder: public: false decorates: 'PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface' - Drupal\package_manager\ProcessFactory: - public: false - decorates: 'PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface' Drupal\package_manager\TranslatableStringFactory: public: false decorates: 'PhpTuf\ComposerStager\API\Translation\Factory\TranslatableFactoryInterface' @@ -175,7 +172,7 @@ services: PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface: class: PhpTuf\ComposerStager\Internal\Process\Factory\ProcessFactory PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface: - class: PhpTuf\ComposerStager\Internal\Process\Service\ComposerProcessRunner + class: Drupal\package_manager\ComposerRunner PhpTuf\ComposerStager\API\Process\Service\OutputCallbackInterface: class: PhpTuf\ComposerStager\Internal\Process\Service\OutputCallback PhpTuf\ComposerStager\API\Process\Service\ProcessInterface: diff --git a/core/modules/package_manager/src/ComposerRunner.php b/core/modules/package_manager/src/ComposerRunner.php new file mode 100644 index 00000000000..dbc029f6aa3 --- /dev/null +++ b/core/modules/package_manager/src/ComposerRunner.php @@ -0,0 +1,54 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\package_manager; + +use Drupal\Core\Config\ConfigFactoryInterface; +use Drupal\Core\File\FileSystemInterface; +use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface; +use PhpTuf\ComposerStager\API\Path\Value\PathInterface; +use PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface; +use PhpTuf\ComposerStager\API\Process\Service\ComposerProcessRunnerInterface; +use PhpTuf\ComposerStager\API\Process\Service\OutputCallbackInterface; +use PhpTuf\ComposerStager\API\Process\Service\ProcessInterface; +use Symfony\Component\Process\PhpExecutableFinder; + +// cspell:ignore BINDIR + +/** + * Runs Composer through the current PHP interpreter. + * + * @internal + * This is an internal part of Package Manager and may be changed or removed + * at any time without warning. External code should not interact with this + * class. + */ +final class ComposerRunner implements ComposerProcessRunnerInterface { + + public function __construct( + private readonly ExecutableFinderInterface $executableFinder, + private readonly ProcessFactoryInterface $processFactory, + private readonly FileSystemInterface $fileSystem, + private readonly ConfigFactoryInterface $configFactory, + ) {} + + /** + * {@inheritdoc} + */ + public function run(array $command, ?PathInterface $cwd = NULL, array $env = [], ?OutputCallbackInterface $callback = NULL, int $timeout = ProcessInterface::DEFAULT_TIMEOUT): void { + // Run Composer through the PHP interpreter so we don't have to rely on + // PHP being in the PATH. + array_unshift($command, (new PhpExecutableFinder())->find(), $this->executableFinder->find('composer')); + + $home = $this->fileSystem->getTempDirectory(); + $home .= '/package_manager_composer_home-'; + $home .= $this->configFactory->get('system.site')->get('uuid'); + $this->fileSystem->prepareDirectory($home, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); + + $process = $this->processFactory->create($command, $cwd, $env + ['COMPOSER_HOME' => $home]); + $process->setTimeout($timeout); + $process->mustRun($callback); + } + +} diff --git a/core/modules/package_manager/src/ExecutableFinder.php b/core/modules/package_manager/src/ExecutableFinder.php index d8a2f1c21d5..a26de302187 100644 --- a/core/modules/package_manager/src/ExecutableFinder.php +++ b/core/modules/package_manager/src/ExecutableFinder.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Drupal\package_manager; +use Composer\InstalledVersions; use Drupal\Core\Config\ConfigFactoryInterface; use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface; @@ -17,10 +18,19 @@ use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface; */ final class ExecutableFinder implements ExecutableFinderInterface { + /** + * The path where Composer is installed in the project, or FALSE if it's not. + */ + private string|false|null $composerPath = NULL; + public function __construct( private readonly ExecutableFinderInterface $decorated, private readonly ConfigFactoryInterface $configFactory, - ) {} + ) { + $this->composerPath = InstalledVersions::isInstalled('composer/composer') + ? InstalledVersions::getInstallPath('composer/composer') . '/bin/composer' + : FALSE; + } /** * {@inheritdoc} @@ -29,7 +39,15 @@ final class ExecutableFinder implements ExecutableFinderInterface { $executables = $this->configFactory->get('package_manager.settings') ->get('executables'); - return $executables[$name] ?? $this->decorated->find($name); + if (isset($executables[$name])) { + return $executables[$name]; + } + + // If we're looking for Composer, use the project's local copy if available. + if ($name === 'composer' && $this->composerPath && file_exists($this->composerPath)) { + return $this->composerPath; + } + return $this->decorated->find($name); } } diff --git a/core/modules/package_manager/src/Form/SettingsForm.php b/core/modules/package_manager/src/Form/SettingsForm.php new file mode 100644 index 00000000000..5193801bd2b --- /dev/null +++ b/core/modules/package_manager/src/Form/SettingsForm.php @@ -0,0 +1,69 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\package_manager\Form; + +use Drupal\Core\Form\ConfigFormBase; +use Drupal\Core\Form\ConfigTarget; +use Drupal\Core\Form\FormStateInterface; + +/** + * Configures Package Manager settings. + */ +final class SettingsForm extends ConfigFormBase { + + /** + * {@inheritdoc} + */ + public function getFormId(): string { + return 'package_manager_settings_form'; + } + + /** + * {@inheritdoc} + */ + protected function getEditableConfigNames(): array { + return ['package_manager.settings']; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state): array { + $form['executables'] = [ + '#type' => 'details', + '#title' => $this->t('Executable paths'), + '#open' => TRUE, + '#description' => $this->t('Configure the paths to required executables.'), + ]; + $trim = fn (string $value): string => trim($value); + + $form['executables']['composer'] = [ + '#type' => 'textfield', + '#title' => $this->t('Composer executable path'), + '#config_target' => new ConfigTarget( + 'package_manager.settings', + 'executables.composer', + toConfig: $trim, + ), + '#description' => $this->t('The full path to the <code>composer</code> executable (e.g., <code>/usr/local/bin/composer</code>).'), + '#required' => TRUE, + ]; + + $form['executables']['rsync'] = [ + '#type' => 'textfield', + '#title' => $this->t('rsync executable path'), + '#config_target' => new ConfigTarget( + 'package_manager.settings', + 'executables.rsync', + toConfig: $trim, + ), + '#description' => $this->t('The full path to the <code>rsync</code> executable (e.g., <code>/usr/bin/rsync</code>).'), + '#required' => TRUE, + ]; + + return parent::buildForm($form, $form_state); + } + +} diff --git a/core/modules/package_manager/src/Hook/PackageManagerHooks.php b/core/modules/package_manager/src/Hook/PackageManagerHooks.php index 2f07923b8cb..7a206af32bc 100644 --- a/core/modules/package_manager/src/Hook/PackageManagerHooks.php +++ b/core/modules/package_manager/src/Hook/PackageManagerHooks.php @@ -3,6 +3,7 @@ namespace Drupal\package_manager\Hook; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\Url; use Drupal\package_manager\ComposerInspector; use Drupal\Core\Hook\Attribute\Hook; @@ -20,6 +21,8 @@ class PackageManagerHooks { public function help($route_name) : ?string { switch ($route_name) { case 'help.page.package_manager': + $settings_form = Url::fromRoute('package_manager.settings')->toString(); + $output = '<h3 id="package-manager-about">' . $this->t('About') . '</h3>'; $output .= '<p>' . $this->t('Package Manager is a framework for updating Drupal core and installing contributed modules and themes via Composer. It has no user interface, but it provides an API for creating a temporary copy of the current site, making changes to the copy, and then syncing those changes back into the live site.') . '</p>'; $output .= '<p>' . $this->t('Package Manager dispatches events before and after various operations, and external code can integrate with it by subscribing to those events. For more information, see <code>package_manager.api.php</code>.') . '</p>'; @@ -54,8 +57,7 @@ class PackageManagerHooks { $output .= ' <p>' . $this->t('Ask your system administrator to remove <code>proc_open()</code> from the <a href=":url">disable_functions</a> setting in <code>php.ini</code>.', [':url' => 'https://www.php.net/manual/en/ini.core.php#ini.disable-functions']) . '</p>'; $output .= ' </li>'; $output .= ' <li>' . $this->t('What if it says the <code>composer</code> executable cannot be found?'); - $output .= ' <p>' . $this->t("If the <code>composer</code> executable's path cannot be automatically determined, it can be explicitly set by adding the following line to <code>settings.php</code>:") . '</p>'; - $output .= " <pre><code>\$config['package_manager.settings']['executables']['composer'] = '/full/path/to/composer.phar';</code></pre>"; + $output .= ' <p>' . $this->t("If the <code>composer</code> executable's path cannot be automatically determined, you can set it in the <a href=\":settings_form\">settings form</a>.", [':settings_form' => $settings_form]) . '</p>'; $output .= ' </li>'; $output .= ' <li>' . $this->t('What if it says the detected version of Composer is not supported?'); $output .= ' <p>' . $this->t('The version of the <code>composer</code> executable must satisfy <code>@version</code>. See the <a href=":url">the Composer documentation</a> for more information, or use this command to update Composer:', [ @@ -69,8 +71,7 @@ class PackageManagerHooks { $output .= ' </li>'; $output .= '</ul>'; $output .= '<h4 id="package-manager-faq-rsync">' . $this->t('Using rsync') . '</h4>'; - $output .= '<p>' . $this->t('Package Manager must be able to run <code>rsync</code> to copy files between the live site and the stage directory. Package Manager will try to detect the path to <code>rsync</code>, but if it cannot be detected, you can set it explicitly by adding the following line to <code>settings.php</code>:') . '</p>'; - $output .= "<pre><code>\$config['package_manager.settings']['executables']['rsync'] = '/full/path/to/rsync';</code></pre>"; + $output .= '<p>' . $this->t('Package Manager must be able to run <code>rsync</code> to copy files between the live site and the stage directory. Package Manager will try to detect the path to <code>rsync</code>, but if it cannot be detected, you can set it in the <a href=":settings_form">settings form</a>.', [':settings_form' => $settings_form]) . '</p>'; $output .= '<h4 id="package-manager-tuf-info">' . $this->t('Enabling PHP-TUF protection') . '</h4>'; $output .= '<p>' . $this->t('Package Manager requires <a href=":php-tuf">PHP-TUF</a>, which implements <a href=":tuf">The Update Framework</a> as a way to help secure Composer package downloads via the <a href=":php-tuf-plugin">PHP-TUF Composer integration plugin</a>. This plugin must be installed and configured properly in order to use Package Manager.', [ ':php-tuf' => 'https://github.com/php-tuf/php-tuf', diff --git a/core/modules/package_manager/src/Hook/PackageManagerRequirementsHooks.php b/core/modules/package_manager/src/Hook/PackageManagerRequirementsHooks.php index 52cc10bc4e9..b734df3d13f 100644 --- a/core/modules/package_manager/src/Hook/PackageManagerRequirementsHooks.php +++ b/core/modules/package_manager/src/Hook/PackageManagerRequirementsHooks.php @@ -6,6 +6,7 @@ use Drupal\Core\Extension\Requirement\RequirementSeverity; use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Hook\Attribute\Hook; use Drupal\Core\Site\Settings; +use Drupal\Core\Url; use Drupal\package_manager\ComposerInspector; use Drupal\package_manager\Exception\FailureMarkerExistsException; use Drupal\package_manager\FailureMarker; @@ -53,8 +54,9 @@ class PackageManagerRequirementsHooks { $requirements['package_manager_composer'] = [ 'title' => $title, - 'description' => $this->t('Composer was not found. The error message was: @message', [ + 'description' => $this->t('Composer was not found. The error message was: @message. The path to Composer can be configured in <a href=":settings-form">the settings form</a>.', [ '@message' => $message, + ':settings-form' => Url::fromRoute('package_manager.settings')->toString(), ]), 'severity' => RequirementSeverity::Error, ]; diff --git a/core/modules/package_manager/src/Plugin/Validation/Constraint/IsExecutableConstraint.php b/core/modules/package_manager/src/Plugin/Validation/Constraint/IsExecutableConstraint.php new file mode 100644 index 00000000000..1bbe29903ec --- /dev/null +++ b/core/modules/package_manager/src/Plugin/Validation/Constraint/IsExecutableConstraint.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\package_manager\Plugin\Validation\Constraint; + +use Drupal\Core\StringTranslation\TranslatableMarkup; +use Drupal\Core\Validation\Attribute\Constraint; +use Symfony\Component\Validator\Constraint as SymfonyConstraint; + +/** + * Validates that a value is the path of an executable file. + */ +#[Constraint( + id: 'IsExecutable', + label: new TranslatableMarkup('Is executable', [], ['context' => 'Validation']) +)] +final class IsExecutableConstraint extends SymfonyConstraint { + + /** + * The error message shown when the path is not executable. + * + * @var string + */ + public string $message = '"@path" is not an executable file.'; + +} diff --git a/core/modules/package_manager/src/Plugin/Validation/Constraint/IsExecutableConstraintValidator.php b/core/modules/package_manager/src/Plugin/Validation/Constraint/IsExecutableConstraintValidator.php new file mode 100644 index 00000000000..92ca387b1e3 --- /dev/null +++ b/core/modules/package_manager/src/Plugin/Validation/Constraint/IsExecutableConstraintValidator.php @@ -0,0 +1,27 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\package_manager\Plugin\Validation\Constraint; + +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; + +/** + * Validates the IsExecutable constraint. + */ +final class IsExecutableConstraintValidator extends ConstraintValidator { + + /** + * {@inheritdoc} + */ + public function validate($value, Constraint $constraint): void { + assert($constraint instanceof IsExecutableConstraint); + + if ($value === NULL || is_executable($value)) { + return; + } + $this->context->addViolation($constraint->message, ['@path' => $value]); + } + +} diff --git a/core/modules/package_manager/src/ProcessFactory.php b/core/modules/package_manager/src/ProcessFactory.php deleted file mode 100644 index 7e92977e7ff..00000000000 --- a/core/modules/package_manager/src/ProcessFactory.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\package_manager; - -use Drupal\Core\Config\ConfigFactoryInterface; -use Drupal\Core\File\FileSystemInterface; -use PhpTuf\ComposerStager\API\Path\Value\PathInterface; -use PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface; -use PhpTuf\ComposerStager\API\Process\Service\ProcessInterface; - -// cspell:ignore BINDIR - -/** - * Defines a process factory which sets the COMPOSER_HOME environment variable. - * - * @internal - * This is an internal part of Package Manager and may be changed or removed - * at any time without warning. External code should not interact with this - * class. - */ -final class ProcessFactory implements ProcessFactoryInterface { - - public function __construct( - private readonly FileSystemInterface $fileSystem, - private readonly ConfigFactoryInterface $configFactory, - private readonly ProcessFactoryInterface $decorated, - ) {} - - /** - * {@inheritdoc} - */ - public function create(array $command, ?PathInterface $cwd = NULL, array $env = []): ProcessInterface { - $process = $this->decorated->create($command, $cwd, $env); - - $env = $process->getEnv(); - if ($command && $this->isComposerCommand($command)) { - $env['COMPOSER_HOME'] = $this->getComposerHomePath(); - } - // Ensure that the current PHP installation is the first place that will be - // searched when looking for the PHP interpreter. - $env['PATH'] = static::getPhpDirectory() . ':' . getenv('PATH'); - $process->setEnv($env); - return $process; - } - - /** - * Returns the directory which contains the PHP interpreter. - * - * @return string - * The path of the directory containing the PHP interpreter. If the server - * is running in a command-line interface, the directory portion of - * PHP_BINARY is returned; otherwise, the compile-time PHP_BINDIR is. - * - * @see php_sapi_name() - * @see https://www.php.net/manual/en/reserved.constants.php - */ - private static function getPhpDirectory(): string { - if (PHP_SAPI === 'cli' || PHP_SAPI === 'cli-server') { - return dirname(PHP_BINARY); - } - return PHP_BINDIR; - } - - /** - * Returns the path to use as the COMPOSER_HOME environment variable. - * - * @return string - * The path which should be used as COMPOSER_HOME. - */ - private function getComposerHomePath(): string { - $home_path = $this->fileSystem->getTempDirectory(); - $home_path .= '/package_manager_composer_home-'; - $home_path .= $this->configFactory->get('system.site')->get('uuid'); - $this->fileSystem->prepareDirectory($home_path, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS); - - return $home_path; - } - - /** - * Determines if a command is running Composer. - * - * @param string[] $command - * The command parts. - * - * @return bool - * TRUE if the command is running Composer, FALSE otherwise. - */ - private function isComposerCommand(array $command): bool { - $executable = $command[0]; - $executable_parts = explode('/', $executable); - $file = array_pop($executable_parts); - return str_starts_with($file, 'composer'); - } - -} diff --git a/core/modules/package_manager/tests/modules/package_manager_test_validation/package_manager_test_validation.services.yml b/core/modules/package_manager/tests/modules/package_manager_test_validation/package_manager_test_validation.services.yml index bd41327d315..785fde50831 100644 --- a/core/modules/package_manager/tests/modules/package_manager_test_validation/package_manager_test_validation.services.yml +++ b/core/modules/package_manager/tests/modules/package_manager_test_validation/package_manager_test_validation.services.yml @@ -10,3 +10,8 @@ services: autowire: true tags: - { name: event_subscriber } + Drupal\package_manager_test_validation\TestExecutableFinder: + public: false + arguments: + - '@.inner' + decorates: 'PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface' diff --git a/core/modules/package_manager/tests/modules/package_manager_test_validation/src/TestExecutableFinder.php b/core/modules/package_manager/tests/modules/package_manager_test_validation/src/TestExecutableFinder.php new file mode 100644 index 00000000000..05df109d2e4 --- /dev/null +++ b/core/modules/package_manager/tests/modules/package_manager_test_validation/src/TestExecutableFinder.php @@ -0,0 +1,61 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\package_manager_test_validation; + +use PhpTuf\ComposerStager\API\Exception\LogicException; +use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface; +use PhpTuf\ComposerStager\API\Translation\Service\TranslatorInterface; +use PhpTuf\ComposerStager\API\Translation\Value\TranslatableInterface; + +/** + * A test-only executable finder that can be rigged to throw an exception. + */ +final class TestExecutableFinder implements ExecutableFinderInterface { + + public function __construct( + private readonly ExecutableFinderInterface $decorated, + ) {} + + /** + * Throws an exception when finding a specific executable, for testing. + * + * @param string $name + * The name of the executable for which ::find() will throw an exception. + */ + public static function throwFor(string $name): void { + \Drupal::keyValue('package_manager_test.executable_errors') + ->set($name, TRUE); + } + + /** + * {@inheritdoc} + */ + public function find(string $name): string { + $should_throw = \Drupal::keyValue('package_manager_test.executable_errors') + ->get($name); + + if ($should_throw) { + throw new LogicException(new class () implements TranslatableInterface { + + /** + * {@inheritdoc} + */ + public function trans(?TranslatorInterface $translator = NULL, ?string $locale = NULL): string { + return 'Not found!'; + } + + /** + * {@inheritdoc} + */ + public function __toString(): string { + return $this->trans(); + } + + }); + } + return $this->decorated->find($name); + } + +} diff --git a/core/modules/package_manager/tests/src/Build/PackageUpdateTest.php b/core/modules/package_manager/tests/src/Build/PackageUpdateTest.php index da6fc5eae32..fbfc3a0b706 100644 --- a/core/modules/package_manager/tests/src/Build/PackageUpdateTest.php +++ b/core/modules/package_manager/tests/src/Build/PackageUpdateTest.php @@ -40,7 +40,7 @@ class PackageUpdateTest extends TemplateProjectTestBase { // Change both modules' upstream version. static::copyFixtureFilesTo("$fixtures/alpha/1.1.0", $alpha_repo_path); static::copyFixtureFilesTo("$fixtures/updated_module/1.1.0", $updated_module_repo_path); - // Make .git folder + // Make .git folder. // Use the API endpoint to create a stage and update updated_module to // 1.1.0. Even though both modules have version 1.1.0 available, only diff --git a/core/modules/package_manager/tests/src/Functional/ComposerRequirementTest.php b/core/modules/package_manager/tests/src/Functional/ComposerRequirementTest.php index 45046a8e2ad..368b2ce7337 100644 --- a/core/modules/package_manager/tests/src/Functional/ComposerRequirementTest.php +++ b/core/modules/package_manager/tests/src/Functional/ComposerRequirementTest.php @@ -21,6 +21,16 @@ class ComposerRequirementTest extends PackageManagerTestBase { protected static $modules = ['package_manager']; /** + * {@inheritdoc} + */ + protected static $configSchemaCheckerExclusions = [ + // We test what happens when the configured path to Composer is invalid, + // so we need to be able to skip schema-based validation, which would + // normally confirm that the configured path to Composer is executable. + 'package_manager.settings', + ]; + + /** * Tests that Composer version and path are listed on the status report. */ public function testComposerInfoShown(): void { @@ -47,7 +57,10 @@ class ComposerRequirementTest extends PackageManagerTestBase { $config->set('executables.composer', '/path/to/composer')->save(); $this->getSession()->reload(); $assert_session->statusCodeEquals(200); - $assert_session->pageTextContains('Composer was not found. The error message was: Failed to run process: The command "\'/path/to/composer\' \'--format=json\'" failed.'); + $assert_session->pageTextContains('Composer was not found. The error message was: '); + // Check for the part of the command string that is constant (the path to + // the PHP interpreter will vary). + $assert_session->pageTextContains("/php' '/path/to/composer' '--format=json'\" failed."); } } diff --git a/core/modules/package_manager/tests/src/Functional/SettingsFormTest.php b/core/modules/package_manager/tests/src/Functional/SettingsFormTest.php new file mode 100644 index 00000000000..58b9b2d39db --- /dev/null +++ b/core/modules/package_manager/tests/src/Functional/SettingsFormTest.php @@ -0,0 +1,75 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\package_manager\Functional; + +use Drupal\Tests\BrowserTestBase; +use PhpTuf\ComposerStager\API\Exception\LogicException; +use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface; + +/** + * Tests the Package Manager settings form. + * + * @group package_manager + */ +final class SettingsFormTest extends BrowserTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = ['package_manager']; + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * Tests that executable paths can be configured through the settings form. + */ + public function testSettingsForm(): void { + $assert_session = $this->assertSession(); + $account = $this->drupalCreateUser(['administer software updates']); + $this->drupalLogin($account); + + /** @var \PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface $executable_finder */ + $executable_finder = \Drupal::service(ExecutableFinderInterface::class); + try { + $composer_path = $executable_finder->find('composer'); + $rsync_path = $executable_finder->find('rsync'); + } + catch (LogicException) { + $this->markTestSkipped('This test requires Composer and rsync to be available in the PATH.'); + } + + $this->drupalGet('/admin/config/system/package-manager'); + $assert_session->statusCodeEquals(200); + // Submit the settings form with the detected paths, with whitespace added + // to test that it is trimmed out. + $this->submitForm([ + 'composer' => "$composer_path ", + 'rsync' => " $rsync_path", + ], 'Save configuration'); + $assert_session->pageTextContains('The configuration options have been saved.'); + + // Verify the paths were saved in config. + $config = $this->config('package_manager.settings'); + $this->assertSame($composer_path, $config->get('executables.composer')); + $this->assertSame($rsync_path, $config->get('executables.rsync')); + + // Verify the paths are shown in the form. + $this->drupalGet('/admin/config/system/package-manager'); + $assert_session->fieldValueEquals('composer', $composer_path); + $assert_session->fieldValueEquals('rsync', $rsync_path); + + // Ensure that the executable paths are confirmed to be executable. + $this->submitForm([ + 'composer' => 'rm -rf /', + 'rsync' => 'cat /etc/passwd', + ], 'Save configuration'); + $assert_session->statusMessageContains('"rm -rf /" is not an executable file.', 'error'); + $assert_session->statusMessageContains('"cat /etc/passwd" is not an executable file.', 'error'); + } + +} diff --git a/core/modules/package_manager/tests/src/Kernel/ComposerInspectorTest.php b/core/modules/package_manager/tests/src/Kernel/ComposerInspectorTest.php index 61f922824bd..e1fb87024cf 100644 --- a/core/modules/package_manager/tests/src/Kernel/ComposerInspectorTest.php +++ b/core/modules/package_manager/tests/src/Kernel/ComposerInspectorTest.php @@ -81,7 +81,7 @@ class ComposerInspectorTest extends PackageManagerKernelTestBase { ->getProjectRoot(); $inspector = $this->container->get(ComposerInspector::class); - // Overwrite the composer.json file and treat it as a + // Overwrite the composer.json file and treat it as a. $file = new JsonFile($project_root . '/composer.json'); $this->assertTrue($file->exists()); $data = $file->read(); diff --git a/core/modules/package_manager/tests/src/Kernel/DirectWriteTest.php b/core/modules/package_manager/tests/src/Kernel/DirectWriteTest.php index 8c34ae00273..90498f55795 100644 --- a/core/modules/package_manager/tests/src/Kernel/DirectWriteTest.php +++ b/core/modules/package_manager/tests/src/Kernel/DirectWriteTest.php @@ -16,6 +16,7 @@ use Drupal\package_manager\Exception\SandboxEventException; use Drupal\package_manager\PathLocator; use Drupal\package_manager\StatusCheckTrait; use Drupal\package_manager\ValidationResult; +use Drupal\package_manager_test_validation\TestExecutableFinder; use PhpTuf\ComposerStager\API\Core\BeginnerInterface; use PhpTuf\ComposerStager\API\Core\CommitterInterface; use PhpTuf\ComposerStager\API\Path\Factory\PathFactoryInterface; @@ -35,6 +36,11 @@ class DirectWriteTest extends PackageManagerKernelTestBase implements EventSubsc use StringTranslationTrait; /** + * {@inheritdoc} + */ + protected static $modules = ['package_manager_test_validation']; + + /** * Whether we are in maintenance mode before a require operation. * * @var bool|null @@ -244,12 +250,10 @@ class DirectWriteTest extends PackageManagerKernelTestBase implements EventSubsc */ public function testPreconditionBypass(string $service_class): void { // Set up conditions where the active and sandbox directories are the same, - // and the path to rsync isn't valid. + // and detecting rsync will fail. $path = $this->container->get(PathFactoryInterface::class) ->create('/the/absolute/apex'); - $this->config('package_manager.settings') - ->set('executables.rsync', "C:\Not Rsync.exe") - ->save(); + TestExecutableFinder::throwFor('rsync'); /** @var \PhpTuf\ComposerStager\API\Precondition\Service\PreconditionInterface $precondition */ $precondition = $this->container->get($service_class); diff --git a/core/modules/package_manager/tests/src/Kernel/ProcessFactoryTest.php b/core/modules/package_manager/tests/src/Kernel/ProcessFactoryTest.php deleted file mode 100644 index db27b06efa8..00000000000 --- a/core/modules/package_manager/tests/src/Kernel/ProcessFactoryTest.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\Tests\package_manager\Kernel; - -use Drupal\package_manager\ProcessFactory; -use PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface; - -/** - * @coversDefaultClass \Drupal\package_manager\ProcessFactory - * @group auto_updates - * @internal - */ -class ProcessFactoryTest extends PackageManagerKernelTestBase { - - /** - * Tests that the process factory prepends the PHP directory to PATH. - */ - public function testPhpDirectoryPrependedToPath(): void { - $factory = $this->container->get(ProcessFactoryInterface::class); - $this->assertInstanceOf(ProcessFactory::class, $factory); - - // Ensure that the directory of the PHP interpreter can be found. - $reflector = new \ReflectionObject($factory); - $method = $reflector->getMethod('getPhpDirectory'); - $php_dir = $method->invoke(NULL); - $this->assertNotEmpty($php_dir); - - // The process factory should always put the PHP interpreter's directory - // at the beginning of the PATH environment variable. - $env = $factory->create(['whoami'])->getEnv(); - $this->assertStringStartsWith("$php_dir:", $env['PATH']); - } - -} diff --git a/core/modules/package_manager/tests/src/Kernel/ServicesTest.php b/core/modules/package_manager/tests/src/Kernel/ServicesTest.php index a1db5a517c1..9e52f9b4075 100644 --- a/core/modules/package_manager/tests/src/Kernel/ServicesTest.php +++ b/core/modules/package_manager/tests/src/Kernel/ServicesTest.php @@ -9,14 +9,12 @@ use Drupal\package_manager\ExecutableFinder; use Drupal\package_manager\LoggingBeginner; use Drupal\package_manager\LoggingCommitter; use Drupal\package_manager\LoggingStager; -use Drupal\package_manager\ProcessFactory; use Drupal\package_manager\TranslatableStringFactory; use Drupal\Tests\package_manager\Traits\AssertPreconditionsTrait; use PhpTuf\ComposerStager\API\Core\BeginnerInterface; use PhpTuf\ComposerStager\API\Core\CommitterInterface; use PhpTuf\ComposerStager\API\Core\StagerInterface; use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface; -use PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface; use PhpTuf\ComposerStager\API\Translation\Factory\TranslatableFactoryInterface; /** @@ -38,11 +36,9 @@ class ServicesTest extends KernelTestBase { * Tests that Package Manager's public services can be instantiated. */ public function testPackageManagerServices(): void { - // Ensure that any overridden Composer Stager services were overridden - // correctly. + // Ensure that certain Composer Stager services are decorated correctly. $overrides = [ ExecutableFinderInterface::class => ExecutableFinder::class, - ProcessFactoryInterface::class => ProcessFactory::class, TranslatableFactoryInterface::class => TranslatableStringFactory::class, BeginnerInterface::class => LoggingBeginner::class, StagerInterface::class => LoggingStager::class, diff --git a/core/modules/package_manager/tests/src/Unit/ComposerRunnerTest.php b/core/modules/package_manager/tests/src/Unit/ComposerRunnerTest.php new file mode 100644 index 00000000000..91253d377d2 --- /dev/null +++ b/core/modules/package_manager/tests/src/Unit/ComposerRunnerTest.php @@ -0,0 +1,63 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\Tests\package_manager\Unit; + +use Drupal\Core\File\FileSystemInterface; +use Drupal\package_manager\ComposerRunner; +use Drupal\Tests\UnitTestCase; +use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface; +use PhpTuf\ComposerStager\API\Process\Factory\ProcessFactoryInterface; +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\Group; +use Prophecy\Argument; + +// cspell:ignore BINDIR + +/** + * Tests Package Manager's Composer runner service. + * + * @internal + */ +#[CoversClass(ComposerRunner::class)] +#[Group('package_manager')] +class ComposerRunnerTest extends UnitTestCase { + + /** + * Tests that the Composer runner runs Composer through the PHP interpreter. + */ + public function testRunner(): void { + $executable_finder = $this->prophesize(ExecutableFinderInterface::class); + $executable_finder->find('composer') + ->willReturn('/mock/composer') + ->shouldBeCalled(); + + $process_factory = $this->prophesize(ProcessFactoryInterface::class); + $process_factory->create( + // Internally, ComposerRunner uses Symfony's PhpExecutableFinder to locate + // the PHP interpreter, which should resolve to PHP_BINARY a command-line + // test environment. + [PHP_BINARY, '/mock/composer', '--version'], + NULL, + Argument::withKey('COMPOSER_HOME'), + )->shouldBeCalled(); + + $file_system = $this->prophesize(FileSystemInterface::class); + $file_system->getTempDirectory()->shouldBeCalled(); + $file_system->prepareDirectory(Argument::cetera())->shouldBeCalled(); + + $runner = new ComposerRunner( + $executable_finder->reveal(), + $process_factory->reveal(), + $file_system->reveal(), + $this->getConfigFactoryStub([ + 'system.site' => [ + 'uuid' => 'testing', + ], + ]), + ); + $runner->run(['--version']); + } + +} diff --git a/core/modules/package_manager/tests/src/Unit/ExecutableFinderTest.php b/core/modules/package_manager/tests/src/Unit/ExecutableFinderTest.php index 811d7547e04..69becb1fd8d 100644 --- a/core/modules/package_manager/tests/src/Unit/ExecutableFinderTest.php +++ b/core/modules/package_manager/tests/src/Unit/ExecutableFinderTest.php @@ -6,6 +6,7 @@ namespace Drupal\Tests\package_manager\Unit; use Drupal\package_manager\ExecutableFinder; use Drupal\Tests\UnitTestCase; +use org\bovigo\vfs\vfsStream; use PhpTuf\ComposerStager\API\Finder\Service\ExecutableFinderInterface; /** @@ -36,4 +37,41 @@ class ExecutableFinderTest extends UnitTestCase { $finder->find('rsync'); } + /** + * Tests that the executable finder tries to use a local copy of Composer. + */ + public function testComposerInstalledInProject(): void { + vfsStream::setup('root', NULL, [ + 'composer-path' => [ + 'bin' => [], + ], + ]); + $composer_path = 'vfs://root/composer-path/bin/composer'; + touch($composer_path); + $this->assertFileExists($composer_path); + + $decorated = $this->prophesize(ExecutableFinderInterface::class); + $decorated->find('composer')->willReturn('the real Composer'); + + $finder = new ExecutableFinder( + $decorated->reveal(), + $this->getConfigFactoryStub([ + 'package_manager.settings' => [ + 'executables' => [], + ], + ]), + ); + $reflector = new \ReflectionProperty($finder, 'composerPath'); + $reflector->setValue($finder, $composer_path); + $this->assertSame($composer_path, $finder->find('composer')); + + // If the executable disappears, or Composer isn't locally installed, the + // decorated executable finder should be called. + unlink($composer_path); + $this->assertSame('the real Composer', $finder->find('composer')); + + $reflector->setValue($finder, FALSE); + $this->assertSame('the real Composer', $finder->find('composer')); + } + } diff --git a/core/modules/path/tests/src/Functional/PathAliasTest.php b/core/modules/path/tests/src/Functional/PathAliasTest.php index 1c196dcdd54..6a922c295da 100644 --- a/core/modules/path/tests/src/Functional/PathAliasTest.php +++ b/core/modules/path/tests/src/Functional/PathAliasTest.php @@ -153,7 +153,7 @@ class PathAliasTest extends PathTestBase { // Set alias to second test node. $edit['path[0][value]'] = '/node/' . $node2->id(); - // Leave $edit['alias'] the same + // Leave "$edit['alias']" the same. $this->drupalGet('admin/config/search/path/add'); $this->submitForm($edit, 'Save'); diff --git a/core/modules/pgsql/src/Driver/Database/pgsql/Connection.php b/core/modules/pgsql/src/Driver/Database/pgsql/Connection.php index 40b2de75cf0..f7601226614 100644 --- a/core/modules/pgsql/src/Driver/Database/pgsql/Connection.php +++ b/core/modules/pgsql/src/Driver/Database/pgsql/Connection.php @@ -151,8 +151,8 @@ class Connection extends DatabaseConnection implements SupportsTemporaryTablesIn // so backslashes in the password need to be doubled up. // The bug was reported against pdo_pgsql 1.0.2, backslashes in passwords // will break on this doubling up when the bug is fixed, so check the - // version - // elseif (phpversion('pdo_pgsql') < 'version_this_was_fixed_in') { + // version. + // "elseif (phpversion('pdo_pgsql') < 'version_this_was_fixed_in') {". else { $connection_options['password'] = str_replace('\\', '\\\\', $connection_options['password']); } diff --git a/core/modules/pgsql/src/Hook/PgsqlRequirementsHooks.php b/core/modules/pgsql/src/Hook/PgsqlRequirementsHooks.php index 65fa78a5e71..0e7bbd97628 100644 --- a/core/modules/pgsql/src/Hook/PgsqlRequirementsHooks.php +++ b/core/modules/pgsql/src/Hook/PgsqlRequirementsHooks.php @@ -2,18 +2,14 @@ namespace Drupal\pgsql\Hook; -use Drupal\Core\Database\Database; -use Drupal\Core\Extension\Requirement\RequirementSeverity; -use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\Hook\Attribute\Hook; +use Drupal\pgsql\Install\Requirements\PgsqlRequirements; /** * Hook implementations for pgsql module. */ class PgsqlRequirementsHooks { - use StringTranslationTrait; - /** * Implements hook_update_requirements(). * @@ -22,34 +18,8 @@ class PgsqlRequirementsHooks { #[Hook('update_requirements')] #[Hook('runtime_requirements')] public function checkRequirements(): array { - $requirements = []; - // Test with PostgreSQL databases for the status of the pg_trgm extension. - if (Database::isActiveConnection()) { - $connection = Database::getConnection(); - - // Set the requirement just for postgres. - if ($connection->driver() == 'pgsql') { - $requirements['pgsql_extension_pg_trgm'] = [ - 'severity' => RequirementSeverity::OK, - 'title' => $this->t('PostgreSQL pg_trgm extension'), - 'value' => $this->t('Available'), - 'description' => $this->t('The pg_trgm PostgreSQL extension is present.'), - ]; - - // If the extension is not available, set the requirement error. - if (!$connection->schema()->extensionExists('pg_trgm')) { - $requirements['pgsql_extension_pg_trgm']['severity'] = RequirementSeverity::Error; - $requirements['pgsql_extension_pg_trgm']['value'] = $this->t('Not created'); - $requirements['pgsql_extension_pg_trgm']['description'] = $this->t('The <a href=":pg_trgm">pg_trgm</a> PostgreSQL extension is not present. The extension is required by Drupal to improve performance when using PostgreSQL. See <a href=":requirements">Drupal database server requirements</a> for more information.', [ - ':pg_trgm' => 'https://www.postgresql.org/docs/current/pgtrgm.html', - ':requirements' => 'https://www.drupal.org/docs/system-requirements/database-server-requirements', - ]); - } - - } - } - - return $requirements; + // We want the identical check from the install time requirements. + return PgsqlRequirements::getRequirements(); } } diff --git a/core/modules/pgsql/tests/src/Kernel/pgsql/SchemaTest.php b/core/modules/pgsql/tests/src/Kernel/pgsql/SchemaTest.php index e10ed33d190..1073e697163 100644 --- a/core/modules/pgsql/tests/src/Kernel/pgsql/SchemaTest.php +++ b/core/modules/pgsql/tests/src/Kernel/pgsql/SchemaTest.php @@ -200,7 +200,7 @@ class SchemaTest extends DriverSpecificSchemaTestBase { $this->assertFalse($this->schema->fieldExists($table_name_new, $field_name)); $this->assertTrue($this->schema->fieldExists($table_name_new, $field_name_new)); - // Adding an unique key + // Adding an unique key. $unique_key_name = $unique_key_introspect_name = 'unique'; $this->schema->addUniqueKey($table_name_new, $unique_key_name, [$field_name_new]); @@ -210,7 +210,7 @@ class SchemaTest extends DriverSpecificSchemaTestBase { $unique_key_introspect_name = $ensure_identifiers_length->invoke($this->schema, $table_name_new, $unique_key_name, 'key'); $this->assertEquals([$field_name_new], $introspect_index_schema->invoke($this->schema, $table_name_new)['unique keys'][$unique_key_introspect_name]); - // Dropping an unique key + // Dropping an unique key. $this->schema->dropUniqueKey($table_name_new, $unique_key_name); // Dropping a field. diff --git a/core/modules/responsive_image/responsive_image.module b/core/modules/responsive_image/responsive_image.module index 9fe3dc72b50..790164bf56a 100644 --- a/core/modules/responsive_image/responsive_image.module +++ b/core/modules/responsive_image/responsive_image.module @@ -78,9 +78,8 @@ function template_preprocess_responsive_image_formatter(&$variables): void { * - responsive_image_style_id: The ID of the responsive image style. */ function template_preprocess_responsive_image(&$variables): void { - // Make sure that width and height are proper values - // If they exists we'll output them - // @see https://www.w3.org/community/respimg/2012/06/18/florians-compromise/ + // Make sure that width and height are proper values, if they exist we'll + // output them. if (isset($variables['width']) && empty($variables['width'])) { unset($variables['width']); unset($variables['height']); diff --git a/core/modules/responsive_image/tests/src/Functional/ResponsiveImageFieldDisplayTest.php b/core/modules/responsive_image/tests/src/Functional/ResponsiveImageFieldDisplayTest.php index 5c5e6be5838..7dbd91fb730 100644 --- a/core/modules/responsive_image/tests/src/Functional/ResponsiveImageFieldDisplayTest.php +++ b/core/modules/responsive_image/tests/src/Functional/ResponsiveImageFieldDisplayTest.php @@ -537,7 +537,7 @@ class ResponsiveImageFieldDisplayTest extends ImageFieldTestBase { // Ensure that preview works. $this->previewNodeImage($test_image, $field_name, 'article'); - // Look for a picture tag in the preview output + // Look for a picture tag in the preview output. $this->assertSession()->responseMatches('/picture/'); $nid = $this->uploadNodeImage($test_image, $field_name, 'article'); diff --git a/core/modules/rest/tests/src/Functional/ResourceTestBase.php b/core/modules/rest/tests/src/Functional/ResourceTestBase.php index 02866375e54..2a0d3179987 100644 --- a/core/modules/rest/tests/src/Functional/ResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php @@ -358,7 +358,7 @@ abstract class ResourceTestBase extends BrowserTestBase { // sets it to 'text/html' by default. We also cannot detect the presence // of Apache either here in the CLI. For now having this documented here // is all we can do. - // $this->assertFalse($response->hasHeader('Content-Type')); + // "$this->assertFalse($response->hasHeader('Content-Type'));". $this->assertSame('', (string) $response->getBody()); } else { diff --git a/core/modules/search/config/schema/search.schema.yml b/core/modules/search/config/schema/search.schema.yml index 4dc4d53e057..519c37d0760 100644 --- a/core/modules/search/config/schema/search.schema.yml +++ b/core/modules/search/config/schema/search.schema.yml @@ -10,8 +10,7 @@ search.settings: type: integer label: 'AND/OR combination limit' constraints: - Range: - min: 0 + PositiveOrZero: ~ default_page: type: string label: 'Default search page' diff --git a/core/modules/search/search.module b/core/modules/search/search.module index 76d7bf1044e..0dc96f3ee89 100644 --- a/core/modules/search/search.module +++ b/core/modules/search/search.module @@ -9,22 +9,6 @@ use Drupal\Component\Utility\Unicode; use Drupal\search\SearchTextProcessorInterface; /** - * Implements hook_theme_suggestions_HOOK(). - */ -function search_theme_suggestions_search_result(array $variables): array { - return ['search_result__' . $variables['plugin_id']]; -} - -/** - * Implements hook_preprocess_HOOK() for block templates. - */ -function search_preprocess_block(&$variables): void { - if ($variables['plugin_id'] == 'search_form_block') { - $variables['attributes']['role'] = 'search'; - } -} - -/** * @defgroup search Search interface * @{ * The Drupal search interface manages a global search mechanism. diff --git a/core/modules/search/src/Hook/SearchThemeHooks.php b/core/modules/search/src/Hook/SearchThemeHooks.php new file mode 100644 index 00000000000..d18f53a8d29 --- /dev/null +++ b/core/modules/search/src/Hook/SearchThemeHooks.php @@ -0,0 +1,32 @@ +<?php + +namespace Drupal\search\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for search. + */ +class SearchThemeHooks { + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_search_result')] + public function themeSuggestionsSearchResult(array $variables): array { + return [ + 'search_result__' . $variables['plugin_id'], + ]; + } + + /** + * Implements hook_preprocess_HOOK() for block templates. + */ + #[Hook('preprocess_block')] + public function preprocessBlock(&$variables): void { + if ($variables['plugin_id'] == 'search_form_block') { + $variables['attributes']['role'] = 'search'; + } + } + +} diff --git a/core/modules/search/tests/src/Functional/SearchCommentCountToggleTest.php b/core/modules/search/tests/src/Functional/SearchCommentCountToggleTest.php index 261df5bafea..0b2e12c4201 100644 --- a/core/modules/search/tests/src/Functional/SearchCommentCountToggleTest.php +++ b/core/modules/search/tests/src/Functional/SearchCommentCountToggleTest.php @@ -76,12 +76,12 @@ class SearchCommentCountToggleTest extends BrowserTestBase { $this->searchableNodes['1 comment'] = $this->drupalCreateNode($node_params); $this->searchableNodes['0 comments'] = $this->drupalCreateNode($node_params); - // Create a comment array + // Create a comment array. $edit_comment = []; $edit_comment['subject[0][value]'] = $this->randomMachineName(); $edit_comment['comment_body[0][value]'] = $this->randomMachineName(); - // Post comment to the test node with comment + // Post comment to the test node with comment. $this->drupalGet('comment/reply/node/' . $this->searchableNodes['1 comment']->id() . '/comment'); $this->submitForm($edit_comment, 'Save'); @@ -99,12 +99,12 @@ class SearchCommentCountToggleTest extends BrowserTestBase { ]; $this->drupalGet('search/node'); - // Test comment count display for nodes with comment status set to Open + // Test comment count display for nodes with comment status set to Open. $this->submitForm($edit, 'Search'); $this->assertSession()->pageTextContains('0 comments'); $this->assertSession()->pageTextContains('1 comment'); - // Test comment count display for nodes with comment status set to Closed + // Test comment count display for nodes with comment status set to Closed. $this->searchableNodes['0 comments']->set('comment', CommentItemInterface::CLOSED); $this->searchableNodes['0 comments']->save(); $this->searchableNodes['1 comment']->set('comment', CommentItemInterface::CLOSED); @@ -114,7 +114,7 @@ class SearchCommentCountToggleTest extends BrowserTestBase { $this->assertSession()->pageTextNotContains('0 comments'); $this->assertSession()->pageTextContains('1 comment'); - // Test comment count display for nodes with comment status set to Hidden + // Test comment count display for nodes with comment status set to Hidden. $this->searchableNodes['0 comments']->set('comment', CommentItemInterface::HIDDEN); $this->searchableNodes['0 comments']->save(); $this->searchableNodes['1 comment']->set('comment', CommentItemInterface::HIDDEN); diff --git a/core/modules/search/tests/src/Functional/SearchConfigSettingsFormTest.php b/core/modules/search/tests/src/Functional/SearchConfigSettingsFormTest.php index d6ca9ced6ed..6e07c0f7674 100644 --- a/core/modules/search/tests/src/Functional/SearchConfigSettingsFormTest.php +++ b/core/modules/search/tests/src/Functional/SearchConfigSettingsFormTest.php @@ -146,7 +146,7 @@ class SearchConfigSettingsFormTest extends BrowserTestBase { $this->drupalGet('admin/config/search/pages'); $this->clickLink('Edit', 1); - // Ensure that the default setting was picked up from the default config + // Ensure that the default setting was picked up from the default config. $this->assertTrue($this->assertSession()->optionExists('edit-extra-type-settings-boost', 'bi')->isSelected()); // Change extra type setting and also modify a common search setting. diff --git a/core/modules/search/tests/src/Functional/SearchNodeUpdateAndDeletionTest.php b/core/modules/search/tests/src/Functional/SearchNodeUpdateAndDeletionTest.php index 94a3b86850b..89c6e465cc6 100644 --- a/core/modules/search/tests/src/Functional/SearchNodeUpdateAndDeletionTest.php +++ b/core/modules/search/tests/src/Functional/SearchNodeUpdateAndDeletionTest.php @@ -65,17 +65,17 @@ class SearchNodeUpdateAndDeletionTest extends BrowserTestBase { $search_index = \Drupal::service('search.index'); assert($search_index instanceof SearchIndexInterface); - // Search the node to verify it appears in search results + // Search the node to verify it appears in search results. $edit = ['keys' => 'knights']; $this->drupalGet('search/node'); $this->submitForm($edit, 'Search'); $this->assertSession()->pageTextContains($node->label()); - // Update the node + // Update the node. $node->body->value = "We want a shrubbery!"; $node->save(); - // Run indexer again + // Run indexer again. $node_search_plugin->updateIndex(); // Search again to verify the new text appears in test results. @@ -100,7 +100,7 @@ class SearchNodeUpdateAndDeletionTest extends BrowserTestBase { // Update the search index. $node_search_plugin->updateIndex(); - // Search the node to verify it appears in search results + // Search the node to verify it appears in search results. $edit = ['keys' => 'dragons']; $this->drupalGet('search/node'); $this->submitForm($edit, 'Search'); diff --git a/core/modules/search/tests/src/Kernel/SearchExcerptTest.php b/core/modules/search/tests/src/Kernel/SearchExcerptTest.php index 76c9551966f..8f9845cbc92 100644 --- a/core/modules/search/tests/src/Kernel/SearchExcerptTest.php +++ b/core/modules/search/tests/src/Kernel/SearchExcerptTest.php @@ -61,7 +61,7 @@ class SearchExcerptTest extends KernelTestBase { $this->assertStringContainsString('í', $result, 'Entities are converted in excerpt'); // The node body that will produce this rendered $text is: - // 123456789 HTMLTest +123456789+‘ +‘ +‘ +‘ +12345678 +‘ +‘ +‘ ‘ + // 123456789 HTMLTest +123456789+‘ +‘ +‘ +‘ +12345678 +‘ +‘ +‘ ‘. $text = "<div class=\"field field--name-body field--type-text-with-summary field--label-hidden\"><div class=\"field__items\"><div class=\"field__item even\" property=\"content:encoded\"><p>123456789 HTMLTest +123456789+‘ +‘ +‘ +‘ +12345678 +‘ +‘ +‘ ‘</p>\n</div></div></div> "; $result = $this->doSearchExcerpt('HTMLTest', $text); $this->assertNotEmpty($result, 'Rendered Multi-byte HTML encodings are not corrupted in search excerpts'); diff --git a/core/modules/serialization/tests/src/Kernel/FieldItemSerializationTest.php b/core/modules/serialization/tests/src/Kernel/FieldItemSerializationTest.php index 2f5a958054b..00732e0d7f8 100644 --- a/core/modules/serialization/tests/src/Kernel/FieldItemSerializationTest.php +++ b/core/modules/serialization/tests/src/Kernel/FieldItemSerializationTest.php @@ -185,11 +185,12 @@ class FieldItemSerializationTest extends NormalizerTestBase { $this->assertTrue($denormalized_entity->field_test_boolean->value); }; - // Asserts denormalizing the entity DOES yield the value we set: - // - when using the detailed representation + // Asserts denormalizing the entity DOES yield the value we set in two + // cases. + // One is when using the detailed representation. $core_normalization['field_test_boolean'][0]['value'] = TRUE; $assert_denormalization($core_normalization); - // - and when using the shorthand representation + // The second is and when using the shorthand representation. $core_normalization['field_test_boolean'][0] = TRUE; $assert_denormalization($core_normalization); @@ -200,11 +201,12 @@ class FieldItemSerializationTest extends NormalizerTestBase { $core_normalization = $this->container->get('serializer')->normalize($this->entity, $format); $this->assertSame('👎', $core_normalization['field_test_boolean'][0]['value']); - // Asserts denormalizing the entity DOES NOT ANYMORE yield the value we set: - // - when using the detailed representation + // Asserts denormalizing the entity DOES NOT ANYMORE yield the value we set + // in two cases. + // One is when using the detailed representation. $core_normalization['field_test_boolean'][0]['value'] = '👍'; $assert_denormalization($core_normalization); - // - and when using the shorthand representation + // The second is when using the shorthand representation. $core_normalization['field_test_boolean'][0] = '👍'; $assert_denormalization($core_normalization); } diff --git a/core/modules/settings_tray/settings_tray.module b/core/modules/settings_tray/settings_tray.module index a1a936d0339..f2460e6eb72 100644 --- a/core/modules/settings_tray/settings_tray.module +++ b/core/modules/settings_tray/settings_tray.module @@ -4,7 +4,6 @@ * @file */ -use Drupal\block\Entity\Block; use Drupal\block\BlockInterface; /** @@ -23,30 +22,3 @@ function _settings_tray_has_block_overrides(BlockInterface $block) { // and remove this function. return \Drupal::config($block->getEntityType()->getConfigPrefix() . '.' . $block->id())->hasOverrides(); } - -/** - * Implements hook_preprocess_HOOK() for block templates. - */ -function settings_tray_preprocess_block(&$variables): void { - // Only blocks that have a settings_tray form and have no configuration - // overrides will have a "Quick Edit" link. We could wait for the contextual - // links to be initialized on the client side, and then add the class and - // data- attribute below there (via JavaScript). But that would mean that it - // would be impossible to show Settings Tray's clickable regions immediately - // when the page loads. When latency is high, this will cause flicker. - // @see \Drupal\settings_tray\Access\BlockPluginHasSettingsTrayFormAccessCheck - /** @var \Drupal\settings_tray\Access\BlockPluginHasSettingsTrayFormAccessCheck $access_checker */ - $access_checker = \Drupal::service('access_check.settings_tray.block.settings_tray_form'); - /** @var \Drupal\Core\Block\BlockManagerInterface $block_plugin_manager */ - $block_plugin_manager = \Drupal::service('plugin.manager.block'); - /** @var \Drupal\Core\Block\BlockPluginInterface $block_plugin */ - $block_plugin = $block_plugin_manager->createInstance($variables['plugin_id']); - if (isset($variables['elements']['#contextual_links']['block']['route_parameters']['block'])) { - $block = Block::load($variables['elements']['#contextual_links']['block']['route_parameters']['block']); - if ($access_checker->accessBlockPlugin($block_plugin)->isAllowed() && !_settings_tray_has_block_overrides($block)) { - // Add class and attributes to all blocks to allow JavaScript to target. - $variables['attributes']['class'][] = 'settings-tray-editable'; - $variables['attributes']['data-drupal-settingstray'] = 'editable'; - } - } -} diff --git a/core/modules/settings_tray/src/Hook/SettingsTrayThemeHooks.php b/core/modules/settings_tray/src/Hook/SettingsTrayThemeHooks.php new file mode 100644 index 00000000000..741dadba454 --- /dev/null +++ b/core/modules/settings_tray/src/Hook/SettingsTrayThemeHooks.php @@ -0,0 +1,41 @@ +<?php + +namespace Drupal\settings_tray\Hook; + +use Drupal\block\Entity\Block; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for settings_tray. + */ +class SettingsTrayThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for block templates. + */ + #[Hook('preprocess_block')] + public function preprocessBlock(&$variables): void { + // Only blocks that have a settings_tray form and have no configuration + // overrides will have a "Quick Edit" link. We could wait for the contextual + // links to be initialized on the client side, and then add the class and + // data- attribute below there (via JavaScript). But that would mean that it + // would be impossible to show Settings Tray's clickable regions immediately + // when the page loads. When latency is high, this will cause flicker. + // @see \Drupal\settings_tray\Access\BlockPluginHasSettingsTrayFormAccessCheck + /** @var \Drupal\settings_tray\Access\BlockPluginHasSettingsTrayFormAccessCheck $access_checker */ + $access_checker = \Drupal::service('access_check.settings_tray.block.settings_tray_form'); + /** @var \Drupal\Core\Block\BlockManagerInterface $block_plugin_manager */ + $block_plugin_manager = \Drupal::service('plugin.manager.block'); + /** @var \Drupal\Core\Block\BlockPluginInterface $block_plugin */ + $block_plugin = $block_plugin_manager->createInstance($variables['plugin_id']); + if (isset($variables['elements']['#contextual_links']['block']['route_parameters']['block'])) { + $block = Block::load($variables['elements']['#contextual_links']['block']['route_parameters']['block']); + if ($access_checker->accessBlockPlugin($block_plugin)->isAllowed() && !_settings_tray_has_block_overrides($block)) { + // Add class and attributes to all blocks to allow JavaScript to target. + $variables['attributes']['class'][] = 'settings-tray-editable'; + $variables['attributes']['data-drupal-settingstray'] = 'editable'; + } + } + } + +} diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index 2488fd97717..a7285c14f55 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -4,11 +4,8 @@ * @file */ -use Drupal\Component\Render\FormattableMarkup; use Drupal\Core\Access\AccessResult; use Drupal\Core\Cache\Cache; -use Drupal\Core\Cache\CacheableMetadata; -use Drupal\Core\Url; use Drupal\shortcut\ShortcutSetInterface; /** @@ -136,89 +133,3 @@ function shortcut_renderable_links($shortcut_set = NULL): array { return $shortcut_links; } - -/** - * Implements hook_preprocess_HOOK() for block templates. - */ -function shortcut_preprocess_block(&$variables): void { - if ($variables['configuration']['provider'] == 'shortcut') { - $variables['attributes']['role'] = 'navigation'; - } -} - -/** - * Implements hook_preprocess_HOOK() for page title templates. - */ -function shortcut_preprocess_page_title(&$variables): void { - // Only display the shortcut link if the user has the ability to edit - // shortcuts, the feature is enabled for the current theme and if the page's - // actual content is being shown (for example, we do not want to display it on - // "access denied" or "page not found" pages). - if (shortcut_set_edit_access()->isAllowed() && theme_get_setting('third_party_settings.shortcut.module_link') && !\Drupal::request()->attributes->has('exception')) { - $link = Url::fromRouteMatch(\Drupal::routeMatch())->getInternalPath(); - $route_match = \Drupal::routeMatch(); - - // Replicate template_preprocess_html()'s processing to get the title in - // string form, so we can set the default name for the shortcut. - $name = $variables['title'] ?? ''; - if (is_array($name)) { - $name = \Drupal::service('renderer')->render($name); - } - $query = [ - 'link' => $link, - 'name' => trim(strip_tags($name)), - ]; - - $shortcut_set = \Drupal::entityTypeManager() - ->getStorage('shortcut_set') - ->getDisplayedToUser(\Drupal::currentUser()); - - // Pages with the add or remove shortcut button need cache invalidation when - // a shortcut is added, edited, or removed. - $cacheability_metadata = CacheableMetadata::createFromRenderArray($variables); - $cacheability_metadata->addCacheTags(\Drupal::entityTypeManager()->getDefinition('shortcut')->getListCacheTags()); - $cacheability_metadata->applyTo($variables); - - // Check if $link is already a shortcut and set $link_mode accordingly. - $shortcuts = \Drupal::entityTypeManager()->getStorage('shortcut')->loadByProperties(['shortcut_set' => $shortcut_set->id()]); - /** @var \Drupal\shortcut\ShortcutInterface $shortcut */ - foreach ($shortcuts as $shortcut) { - if (($shortcut_url = $shortcut->getUrl()) && $shortcut_url->isRouted() && $shortcut_url->getRouteName() == $route_match->getRouteName() && $shortcut_url->getRouteParameters() == $route_match->getRawParameters()->all()) { - $shortcut_id = $shortcut->id(); - break; - } - } - $link_mode = isset($shortcut_id) ? "remove" : "add"; - - if ($link_mode == "add") { - $link_text = shortcut_set_switch_access()->isAllowed() ? t('Add to %shortcut_set shortcuts', ['%shortcut_set' => $shortcut_set->label()]) : t('Add to shortcuts'); - $route_name = 'shortcut.link_add_inline'; - $route_parameters = ['shortcut_set' => $shortcut_set->id()]; - } - else { - $query['id'] = $shortcut_id; - $link_text = shortcut_set_switch_access()->isAllowed() ? t('Remove from %shortcut_set shortcuts', ['%shortcut_set' => $shortcut_set->label()]) : t('Remove from shortcuts'); - $route_name = 'entity.shortcut.link_delete_inline'; - $route_parameters = ['shortcut' => $shortcut_id]; - } - - $query += \Drupal::destination()->getAsArray(); - $variables['title_suffix']['add_or_remove_shortcut'] = [ - '#attached' => [ - 'library' => [ - 'shortcut/drupal.shortcut', - ], - ], - '#type' => 'link', - '#title' => new FormattableMarkup('<span class="shortcut-action__icon"></span><span class="shortcut-action__message">@text</span>', ['@text' => $link_text]), - '#url' => Url::fromRoute($route_name, $route_parameters), - '#options' => ['query' => $query], - '#attributes' => [ - 'class' => [ - 'shortcut-action', - 'shortcut-action--' . $link_mode, - ], - ], - ]; - } -} diff --git a/core/modules/shortcut/src/Hook/ShortcutThemeHooks.php b/core/modules/shortcut/src/Hook/ShortcutThemeHooks.php new file mode 100644 index 00000000000..c86a64a140d --- /dev/null +++ b/core/modules/shortcut/src/Hook/ShortcutThemeHooks.php @@ -0,0 +1,111 @@ +<?php + +namespace Drupal\shortcut\Hook; + +use Drupal\Component\Render\FormattableMarkup; +use Drupal\Core\Cache\CacheableMetadata; +use Drupal\Core\Url; +use Drupal\Core\Hook\Attribute\Hook; +use Drupal\Core\StringTranslation\StringTranslationTrait; + +/** + * Hook implementations for shortcut. + */ +class ShortcutThemeHooks { + use StringTranslationTrait; + + /** + * Implements hook_preprocess_HOOK() for block templates. + */ + #[Hook('preprocess_block')] + public function preprocessBlock(&$variables): void { + if ($variables['configuration']['provider'] == 'shortcut') { + $variables['attributes']['role'] = 'navigation'; + } + } + + /** + * Implements hook_preprocess_HOOK() for page title templates. + */ + #[Hook('preprocess_page_title')] + public function preprocessPageTitle(&$variables): void { + // Only display the shortcut link if the user has the ability to edit + // shortcuts, the feature is enabled for the current theme and if the + // page's actual content is being shown (for example, we do not want to + // display it on "access denied" or "page not found" pages). + if (shortcut_set_edit_access()->isAllowed() && theme_get_setting('third_party_settings.shortcut.module_link') && !\Drupal::request()->attributes->has('exception')) { + $link = Url::fromRouteMatch(\Drupal::routeMatch())->getInternalPath(); + $route_match = \Drupal::routeMatch(); + // Replicate template_preprocess_html()'s processing to get the title in + // string form, so we can set the default name for the shortcut. + $name = $variables['title'] ?? ''; + if (is_array($name)) { + $name = \Drupal::service('renderer')->render($name); + } + $query = [ + 'link' => $link, + 'name' => trim(strip_tags($name)), + ]; + $shortcut_set = \Drupal::entityTypeManager()->getStorage('shortcut_set')->getDisplayedToUser(\Drupal::currentUser()); + // Pages with the add or remove shortcut button need cache invalidation + // when a shortcut is added, edited, or removed. + $cacheability_metadata = CacheableMetadata::createFromRenderArray($variables); + $cacheability_metadata->addCacheTags(\Drupal::entityTypeManager()->getDefinition('shortcut')->getListCacheTags()); + $cacheability_metadata->applyTo($variables); + // Check if $link is already a shortcut and set $link_mode accordingly. + $shortcuts = \Drupal::entityTypeManager()->getStorage('shortcut')->loadByProperties([ + 'shortcut_set' => $shortcut_set->id(), + ]); + /** @var \Drupal\shortcut\ShortcutInterface $shortcut */ + foreach ($shortcuts as $shortcut) { + if (($shortcut_url = $shortcut->getUrl()) && $shortcut_url->isRouted() && $shortcut_url->getRouteName() == $route_match->getRouteName() && $shortcut_url->getRouteParameters() == $route_match->getRawParameters()->all()) { + $shortcut_id = $shortcut->id(); + break; + } + } + $link_mode = isset($shortcut_id) ? "remove" : "add"; + if ($link_mode == "add") { + $link_text = shortcut_set_switch_access()->isAllowed() ? $this->t('Add to %shortcut_set shortcuts', [ + '%shortcut_set' => $shortcut_set->label(), + ]) : $this->t('Add to shortcuts'); + $route_name = 'shortcut.link_add_inline'; + $route_parameters = [ + 'shortcut_set' => $shortcut_set->id(), + ]; + } + else { + $query['id'] = $shortcut_id; + $link_text = shortcut_set_switch_access()->isAllowed() ? $this->t('Remove from %shortcut_set shortcuts', [ + '%shortcut_set' => $shortcut_set->label(), + ]) : $this->t('Remove from shortcuts'); + $route_name = 'entity.shortcut.link_delete_inline'; + $route_parameters = [ + 'shortcut' => $shortcut_id, + ]; + } + $query += \Drupal::destination()->getAsArray(); + $variables['title_suffix']['add_or_remove_shortcut'] = [ + '#attached' => [ + 'library' => [ + 'shortcut/drupal.shortcut', + ], + ], + '#type' => 'link', + '#title' => new FormattableMarkup('<span class="shortcut-action__icon"></span><span class="shortcut-action__message">@text</span>', [ + '@text' => $link_text, + ]), + '#url' => Url::fromRoute($route_name, $route_parameters), + '#options' => [ + 'query' => $query, + ], + '#attributes' => [ + 'class' => [ + 'shortcut-action', + 'shortcut-action--' . $link_mode, + ], + ], + ]; + } + } + +} diff --git a/core/modules/shortcut/src/Plugin/migrate/destination/EntityShortcutSet.php b/core/modules/shortcut/src/Plugin/migrate/destination/EntityShortcutSet.php index 0f0ec102a84..dfc334b8f1d 100644 --- a/core/modules/shortcut/src/Plugin/migrate/destination/EntityShortcutSet.php +++ b/core/modules/shortcut/src/Plugin/migrate/destination/EntityShortcutSet.php @@ -18,7 +18,7 @@ class EntityShortcutSet extends EntityConfigBase { protected function getEntity(Row $row, array $old_destination_id_values) { $entity = parent::getEntity($row, $old_destination_id_values); // Set the "syncing" flag to TRUE, to avoid duplication of default - // shortcut links + // shortcut links. $entity->setSyncing(TRUE); return $entity; } diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml index cfd2f82952c..854ef2a178e 100644 --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -157,15 +157,13 @@ system.diff: label: 'Number of leading lines in a diff' constraints: # @see \Drupal\Component\Diff\DiffFormatter - Range: - min: 0 + PositiveOrZero: ~ lines_trailing: type: integer label: 'Number of trailing lines in a diff' constraints: # @see \Drupal\Component\Diff\DiffFormatter - Range: - min: 0 + PositiveOrZero: ~ system.logging: type: config_object @@ -355,8 +353,7 @@ system.file: type: integer label: 'Maximum age for temporary files' constraints: - Range: - min: 0 + PositiveOrZero: ~ system.image: type: config_object @@ -426,8 +423,7 @@ system.advisories: # Minimum can be set to 0 as it just means the advisories will be retrieved on every call. # @see \Drupal\system\SecurityAdvisories\SecurityAdvisoriesFetcher::getSecurityAdvisories constraints: - Range: - min: 0 + PositiveOrZero: ~ block.settings.system_branding_block: type: block_settings diff --git a/core/modules/system/src/Controller/DbUpdateController.php b/core/modules/system/src/Controller/DbUpdateController.php index 0bd9e737f59..4fdb93c8b45 100644 --- a/core/modules/system/src/Controller/DbUpdateController.php +++ b/core/modules/system/src/Controller/DbUpdateController.php @@ -228,7 +228,7 @@ class DbUpdateController extends ControllerBase { $this->keyValueExpirableFactory->get('update_available_release')->deleteAll(); $build['info_header'] = [ - '#markup' => '<p>' . $this->t('Use this utility to update your database whenever a module, theme, or the core software is updated.') . '</p><p>' . $this->t('For more detailed information, see the <a href="https://www.drupal.org/upgrade">upgrading handbook</a>. If you are unsure what these terms mean you should probably contact your hosting provider.') . '</p>', + '#markup' => '<p>' . $this->t('Use this utility to update your database whenever a module, theme, or the core software is updated.') . '</p><p>' . $this->t('For more detailed information, see the <a href="https://www.drupal.org/docs/updating-drupal">Updating Drupal guide</a>. If you are unsure what these terms mean you should probably contact your hosting provider.') . '</p>', ]; $info[] = $this->t("<strong>Back up your code</strong>. Hint: when backing up module code, do not leave that backup in the 'modules' or 'sites/*/modules' directories as this may confuse Drupal's auto-discovery mechanism."); diff --git a/core/modules/system/src/CronController.php b/core/modules/system/src/CronController.php index 6ba1e031a4d..59bc6e9289a 100644 --- a/core/modules/system/src/CronController.php +++ b/core/modules/system/src/CronController.php @@ -37,7 +37,7 @@ class CronController extends ControllerBase { public function run() { $this->cron->run(); - // HTTP 204 is "No content", meaning "I did what you asked and we're done." + // HTTP 204 is "No content", meaning "I did what you asked and we're done.". return new Response('', 204); } diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php index 13297f3578c..551e813c611 100644 --- a/core/modules/system/src/Form/ModulesListForm.php +++ b/core/modules/system/src/Form/ModulesListForm.php @@ -329,7 +329,7 @@ class ModulesListForm extends FormBase { // Disable the checkbox for required modules. if (!empty($module->info['required'])) { // Used when displaying modules that are required by the installation - // profile + // profile. $row['enable']['#disabled'] = TRUE; $row['#required_by'][] = $distribution . (!empty($module->info['explanation']) ? ' (' . $module->info['explanation'] . ')' : ''); } diff --git a/core/modules/system/src/Form/ModulesUninstallForm.php b/core/modules/system/src/Form/ModulesUninstallForm.php index 97f76abe40e..9d51b67f2d3 100644 --- a/core/modules/system/src/Form/ModulesUninstallForm.php +++ b/core/modules/system/src/Form/ModulesUninstallForm.php @@ -138,7 +138,7 @@ class ModulesUninstallForm extends FormBase { $form['modules'] = []; // Only build the rest of the form if there are any modules available to - // uninstall; + // uninstall. if (empty($uninstallable)) { return $form; } diff --git a/core/modules/system/src/Form/ThemeSettingsForm.php b/core/modules/system/src/Form/ThemeSettingsForm.php index 9133eb8aa10..44f44179f5a 100644 --- a/core/modules/system/src/Form/ThemeSettingsForm.php +++ b/core/modules/system/src/Form/ThemeSettingsForm.php @@ -140,7 +140,8 @@ class ThemeSettingsForm extends ConfigFormBase { $themes = $this->themeHandler->listInfo(); - // Default settings are defined in theme_get_setting() in includes/theme.inc + // Default settings are defined in theme_get_setting() in + // includes/theme.inc. if ($theme) { if (!$this->themeHandler->hasUi($theme)) { throw new NotFoundHttpException(); @@ -168,7 +169,7 @@ class ThemeSettingsForm extends ConfigFormBase { '#value' => $config_key, ]; - // Toggle settings + // Toggle settings. $toggles = [ 'node_user_picture' => $this->t('User pictures in posts'), 'comment_user_picture' => $this->t('User pictures in comments'), @@ -176,7 +177,7 @@ class ThemeSettingsForm extends ConfigFormBase { 'favicon' => $this->t('Shortcut icon'), ]; - // Some features are not always available + // Some features are not always available. $disabled = []; if (!user_picture_enabled()) { $disabled['toggle_node_user_picture'] = TRUE; diff --git a/core/modules/system/src/Hook/SystemThemeHooks.php b/core/modules/system/src/Hook/SystemThemeHooks.php new file mode 100644 index 00000000000..728a02f7498 --- /dev/null +++ b/core/modules/system/src/Hook/SystemThemeHooks.php @@ -0,0 +1,138 @@ +<?php + +namespace Drupal\system\Hook; + +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for system. + */ +class SystemThemeHooks { + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_html')] + public function themeSuggestionsHtml(array $variables): array { + $path_args = explode('/', trim(\Drupal::service('path.current')->getPath(), '/')); + return theme_get_suggestions($path_args, 'html'); + } + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_page')] + public function themeSuggestionsPage(array $variables): array { + $path_args = explode('/', trim(\Drupal::service('path.current')->getPath(), '/')); + $suggestions = theme_get_suggestions($path_args, 'page'); + $supported_http_error_codes = [ + 401, + 403, + 404, + ]; + $exception = \Drupal::requestStack()->getCurrentRequest()->attributes->get('exception'); + if ($exception instanceof HttpExceptionInterface && in_array($exception->getStatusCode(), $supported_http_error_codes, TRUE)) { + $suggestions[] = 'page__4xx'; + $suggestions[] = 'page__' . $exception->getStatusCode(); + } + return $suggestions; + } + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_maintenance_page')] + public function themeSuggestionsMaintenancePage(array $variables): array { + $suggestions = []; + // Dead databases will show error messages so supplying this template will + // allow themers to override the page and the content completely. + $offline = defined('MAINTENANCE_MODE'); + try { + \Drupal::service('path.matcher')->isFrontPage(); + } + catch (\Exception) { + // The database is not yet available. + $offline = TRUE; + } + if ($offline) { + $suggestions[] = 'maintenance_page__offline'; + } + return $suggestions; + } + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_region')] + public function themeSuggestionsRegion(array $variables): array { + $suggestions = []; + if (!empty($variables['elements']['#region'])) { + $suggestions[] = 'region__' . $variables['elements']['#region']; + } + return $suggestions; + } + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_field')] + public function themeSuggestionsField(array $variables): array { + $suggestions = []; + $element = $variables['element']; + $suggestions[] = 'field__' . $element['#field_type']; + $suggestions[] = 'field__' . $element['#field_name']; + $suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#bundle']; + $suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#field_name']; + $suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#field_name'] . '__' . $element['#bundle']; + return $suggestions; + } + + /** + * @} End of "defgroup authorize". + */ + + /** + * Implements hook_preprocess_HOOK() for block templates. + */ + #[Hook('preprocess_block')] + public function preprocessBlock(&$variables): void { + switch ($variables['base_plugin_id']) { + case 'system_branding_block': + $variables['site_logo'] = ''; + if ($variables['content']['site_logo']['#access'] && $variables['content']['site_logo']['#uri']) { + $variables['site_logo'] = $variables['content']['site_logo']['#uri']; + } + $variables['site_name'] = ''; + if ($variables['content']['site_name']['#access'] && $variables['content']['site_name']['#markup']) { + $variables['site_name'] = $variables['content']['site_name']['#markup']; + } + $variables['site_slogan'] = ''; + if ($variables['content']['site_slogan']['#access'] && $variables['content']['site_slogan']['#markup']) { + $variables['site_slogan'] = [ + '#markup' => $variables['content']['site_slogan']['#markup'], + ]; + } + break; + } + } + + /** + * Implements hook_preprocess_toolbar(). + */ + #[Hook('preprocess_toolbar')] + public function preprocessToolbar(array &$variables, $hook, $info): void { + // When Claro is the admin theme, Claro overrides the active theme's if that + // active theme is not Claro. Because of these potential overrides, the + // toolbar cache should be invalidated any time the default or admin theme + // changes. + $variables['#cache']['tags'][] = 'config:system.theme'; + // If Claro is the admin theme but not the active theme, still include + // Claro's toolbar preprocessing. + if (_system_is_claro_admin_and_not_active()) { + require_once DRUPAL_ROOT . '/core/themes/claro/claro.theme'; + claro_preprocess_toolbar($variables, $hook, $info); + } + } + +} diff --git a/core/modules/system/src/SystemManager.php b/core/modules/system/src/SystemManager.php index 43a53fe0542..563188e017f 100644 --- a/core/modules/system/src/SystemManager.php +++ b/core/modules/system/src/SystemManager.php @@ -120,7 +120,7 @@ class SystemManager { * An array of system requirements. */ public function listRequirements() { - // Load .install files + // Load .install files. include_once DRUPAL_ROOT . '/core/includes/install.inc'; drupal_load_updates(); diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 0fbcf9b6c1f..8fac07911e9 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -9,7 +9,6 @@ use Drupal\Core\Extension\Extension; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Url; use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; /** * Disabled option on forms and settings. @@ -61,81 +60,6 @@ function system_hook_info(): array { } /** - * Implements hook_theme_suggestions_HOOK(). - */ -function system_theme_suggestions_html(array $variables): array { - $path_args = explode('/', trim(\Drupal::service('path.current')->getPath(), '/')); - return theme_get_suggestions($path_args, 'html'); -} - -/** - * Implements hook_theme_suggestions_HOOK(). - */ -function system_theme_suggestions_page(array $variables): array { - $path_args = explode('/', trim(\Drupal::service('path.current')->getPath(), '/')); - $suggestions = theme_get_suggestions($path_args, 'page'); - - $supported_http_error_codes = [401, 403, 404]; - $exception = \Drupal::requestStack()->getCurrentRequest()->attributes->get('exception'); - if ($exception instanceof HttpExceptionInterface && in_array($exception->getStatusCode(), $supported_http_error_codes, TRUE)) { - $suggestions[] = 'page__4xx'; - $suggestions[] = 'page__' . $exception->getStatusCode(); - } - - return $suggestions; -} - -/** - * Implements hook_theme_suggestions_HOOK(). - */ -function system_theme_suggestions_maintenance_page(array $variables): array { - $suggestions = []; - - // Dead databases will show error messages so supplying this template will - // allow themers to override the page and the content completely. - $offline = defined('MAINTENANCE_MODE'); - try { - \Drupal::service('path.matcher')->isFrontPage(); - } - catch (Exception) { - // The database is not yet available. - $offline = TRUE; - } - if ($offline) { - $suggestions[] = 'maintenance_page__offline'; - } - - return $suggestions; -} - -/** - * Implements hook_theme_suggestions_HOOK(). - */ -function system_theme_suggestions_region(array $variables): array { - $suggestions = []; - if (!empty($variables['elements']['#region'])) { - $suggestions[] = 'region__' . $variables['elements']['#region']; - } - return $suggestions; -} - -/** - * Implements hook_theme_suggestions_HOOK(). - */ -function system_theme_suggestions_field(array $variables): array { - $suggestions = []; - $element = $variables['element']; - - $suggestions[] = 'field__' . $element['#field_type']; - $suggestions[] = 'field__' . $element['#field_name']; - $suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#bundle']; - $suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#field_name']; - $suggestions[] = 'field__' . $element['#entity_type'] . '__' . $element['#field_name'] . '__' . $element['#bundle']; - - return $suggestions; -} - -/** * Prepares variables for the list of available bundles. * * Default template: entity-add-list.html.twig. @@ -307,34 +231,6 @@ function system_authorized_batch_process() { } /** - * @} End of "defgroup authorize". - */ - -/** - * Implements hook_preprocess_HOOK() for block templates. - */ -function system_preprocess_block(&$variables): void { - switch ($variables['base_plugin_id']) { - case 'system_branding_block': - $variables['site_logo'] = ''; - if ($variables['content']['site_logo']['#access'] && $variables['content']['site_logo']['#uri']) { - $variables['site_logo'] = $variables['content']['site_logo']['#uri']; - } - $variables['site_name'] = ''; - if ($variables['content']['site_name']['#access'] && $variables['content']['site_name']['#markup']) { - $variables['site_name'] = $variables['content']['site_name']['#markup']; - } - $variables['site_slogan'] = ''; - if ($variables['content']['site_slogan']['#access'] && $variables['content']['site_slogan']['#markup']) { - $variables['site_slogan'] = [ - '#markup' => $variables['content']['site_slogan']['#markup'], - ]; - } - break; - } -} - -/** * Checks the existence of the directory specified in $form_element. * * This function is called from the system_settings form to check all core @@ -478,21 +374,3 @@ function _system_is_claro_admin_and_not_active() { $active_theme = \Drupal::theme()->getActiveTheme()->getName(); return $active_theme !== 'claro' && $admin_theme === 'claro'; } - -/** - * Implements hook_preprocess_toolbar(). - */ -function system_preprocess_toolbar(array &$variables, $hook, $info): void { - // When Claro is the admin theme, Claro overrides the active theme's if that - // active theme is not Claro. Because of these potential overrides, the - // toolbar cache should be invalidated any time the default or admin theme - // changes. - $variables['#cache']['tags'][] = 'config:system.theme'; - - // If Claro is the admin theme but not the active theme, still include Claro's - // toolbar preprocessing. - if (_system_is_claro_admin_and_not_active()) { - require_once DRUPAL_ROOT . '/core/themes/claro/claro.theme'; - claro_preprocess_toolbar($variables, $hook, $info); - } -} diff --git a/core/modules/system/tests/modules/batch_test/src/BatchTestCallbacks.php b/core/modules/system/tests/modules/batch_test/src/BatchTestCallbacks.php index 24da9ebff84..aa4dc2e1a29 100644 --- a/core/modules/system/tests/modules/batch_test/src/BatchTestCallbacks.php +++ b/core/modules/system/tests/modules/batch_test/src/BatchTestCallbacks.php @@ -111,7 +111,7 @@ class BatchTestCallbacks { // 'finished' callback. $batch_test_helper->stack("op 5 id $id"); $context['results'][5][] = $id; - // This test is to test finished > 1 + // This test is to test finished > 1. $context['finished'] = 3.14; } diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestOptionalContainerForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestOptionalContainerForm.php index 62157258cea..314d4675182 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestOptionalContainerForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestOptionalContainerForm.php @@ -37,7 +37,7 @@ class FormTestOptionalContainerForm extends FormBase { '#optional' => FALSE, ]; - // Non-empty containers + // Non-empty containers. $form['nonempty_optional'] = [ '#type' => 'container', '#attributes' => ['class' => ['nonempty_optional']], diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestStorageForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestStorageForm.php index 637399b3638..cde0058a5db 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/FormTestStorageForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestStorageForm.php @@ -34,7 +34,7 @@ class FormTestStorageForm extends FormBase { if ($form_state->isRebuilding()) { $form_state->setUserInput([]); } - // Initialize + // Initialize. $storage = $form_state->getStorage(); $session = $this->getRequest()->getSession(); if (empty($storage)) { @@ -42,7 +42,7 @@ class FormTestStorageForm extends FormBase { if (empty($user_input)) { $session->set('constructions', 0); } - // Put the initial thing into the storage + // Put the initial thing into the storage. $storage = [ 'thing' => [ 'title' => 'none', diff --git a/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php b/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php index 6de8e4ad185..b6b54647efa 100644 --- a/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php +++ b/core/modules/system/tests/modules/form_test/src/Form/JavascriptStatesForm.php @@ -446,7 +446,7 @@ class JavascriptStatesForm extends FormBase { '#title' => 'Textfield in details', ]; - // Select trigger + // Select trigger. $form['header_select'] = [ '#type' => 'html_tag', '#tag' => 'h3', diff --git a/core/modules/system/tests/modules/icon_test/config/schema/icon_test.schema.yml b/core/modules/system/tests/modules/icon_test/config/schema/icon_test.schema.yml index 113b165e50e..ed96b94968d 100644 --- a/core/modules/system/tests/modules/icon_test/config/schema/icon_test.schema.yml +++ b/core/modules/system/tests/modules/icon_test/config/schema/icon_test.schema.yml @@ -8,14 +8,12 @@ icon.icon_pack_options.test_path: type: integer label: 'Width' constraints: - Range: - min: 0 + PositiveOrZero: ~ height: type: integer label: 'Height' constraints: - Range: - min: 0 + PositiveOrZero: ~ icon.icon_pack_options.test_svg: type: mapping @@ -27,8 +25,7 @@ icon.icon_pack_options.test_svg: type: integer label: 'Size' constraints: - Range: - min: 0 + PositiveOrZero: ~ icon.icon_pack_options.test_svg_sprite: type: mapping @@ -40,14 +37,12 @@ icon.icon_pack_options.test_svg_sprite: type: integer label: 'Width' constraints: - Range: - min: 0 + PositiveOrZero: ~ height: type: integer label: 'Height' constraints: - Range: - min: 0 + PositiveOrZero: ~ alt: type: label label: 'Alt' @@ -62,14 +57,12 @@ icon.icon_pack_options.test_settings: type: integer label: 'Width' constraints: - Range: - min: 0 + PositiveOrZero: ~ height: type: integer label: 'Height' constraints: - Range: - min: 0 + PositiveOrZero: ~ title: type: label label: 'Title' diff --git a/core/modules/system/tests/modules/layout_test/layout_test.module b/core/modules/system/tests/modules/layout_test/layout_test.module deleted file mode 100644 index 18459369b0a..00000000000 --- a/core/modules/system/tests/modules/layout_test/layout_test.module +++ /dev/null @@ -1,15 +0,0 @@ -<?php - -/** - * @file - * Provides hook implementations for Layout Test. - */ - -declare(strict_types=1); - -/** - * Implements hook_preprocess_HOOK() for layout templates. - */ -function template_preprocess_layout_test_2col(&$variables): void { - $variables['region_attributes']['left']->addClass('class-added-by-preprocess'); -} diff --git a/core/modules/system/tests/modules/layout_test/src/Hook/LayoutTestThemeHooks.php b/core/modules/system/tests/modules/layout_test/src/Hook/LayoutTestThemeHooks.php new file mode 100644 index 00000000000..35774e5de4b --- /dev/null +++ b/core/modules/system/tests/modules/layout_test/src/Hook/LayoutTestThemeHooks.php @@ -0,0 +1,22 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\layout_test\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for layout_test. + */ +class LayoutTestThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for layout templates. + */ + #[Hook('preprocess_layout_test_2col')] + public function templatePreprocessLayoutTest2col(&$variables): void { + $variables['region_attributes']['left']->addClass('class-added-by-preprocess'); + } + +} diff --git a/core/modules/system/tests/modules/module_test/module_test.file.inc b/core/modules/system/tests/modules/module_test/module_test.file.inc deleted file mode 100644 index 5ba5f5614ca..00000000000 --- a/core/modules/system/tests/modules/module_test/module_test.file.inc +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/** - * @file - * Install, update and uninstall functions for the module_test module. - * - * Provides a hook to test \Drupal::moduleHandler()->getImplementationInfo() - * loading includes. - */ - -declare(strict_types=1); - -/** - * Implements hook_test_hook(). - */ -function module_test_test_hook(): array { - return ['module_test' => 'success!']; -} - -/** - * Implements hook_test_reset_implementations_hook(). - */ -function module_test_test_reset_implementations_hook(): string { - return __FUNCTION__; -} - -/** - * Implements hook_test_reset_implementations_alter(). - */ -function module_test_test_reset_implementations_alter(array &$data): void { - $data[] = __FUNCTION__; -} diff --git a/core/modules/system/tests/modules/module_test/module_test.module b/core/modules/system/tests/modules/module_test/module_test.module index 35561f09c8a..b3f3e131a58 100644 --- a/core/modules/system/tests/modules/module_test/module_test.module +++ b/core/modules/system/tests/modules/module_test/module_test.module @@ -7,57 +7,6 @@ declare(strict_types=1); -use Drupal\Core\Extension\Extension; - -/** - * Implements hook_system_info_alter(). - * - * Manipulate module dependencies to test dependency chains. - */ -function module_test_system_info_alter(&$info, Extension $file, $type): void { - if (\Drupal::state()->get('module_test.dependency') == 'missing dependency') { - if ($file->getName() == 'dblog') { - // Make dblog module depend on config. - $info['dependencies'][] = 'config'; - } - elseif ($file->getName() == 'config') { - // Make config module depend on a non-existing module. - $info['dependencies'][] = 'foo'; - } - } - elseif (\Drupal::state()->get('module_test.dependency') == 'dependency') { - if ($file->getName() == 'dblog') { - // Make dblog module depend on config. - $info['dependencies'][] = 'config'; - } - elseif ($file->getName() == 'config') { - // Make config module depend on help module. - $info['dependencies'][] = 'help'; - } - elseif ($file->getName() == 'entity_test') { - // Make entity test module depend on help module. - $info['dependencies'][] = 'help'; - } - } - elseif (\Drupal::state()->get('module_test.dependency') == 'version dependency') { - if ($file->getName() == 'dblog') { - // Make dblog module depend on config. - $info['dependencies'][] = 'config'; - } - elseif ($file->getName() == 'config') { - // Make config module depend on a specific version of help module. - $info['dependencies'][] = 'help (1.x)'; - } - elseif ($file->getName() == 'help') { - // Set help module to a version compatible with the above. - $info['version'] = '8.x-1.0'; - } - } - if ($file->getName() == 'stark' && $type == 'theme') { - $info['regions']['test_region'] = 'Test region'; - } -} - /** * Implements hook_hook_info(). */ @@ -77,21 +26,3 @@ function module_test_load($param) { $result = \Drupal::moduleHandler()->invokeAll('test_hook'); return $result[$param]; } - -/** - * Implements hook_modules_installed(). - */ -function module_test_modules_installed($modules): void { - // Record the ordered list of modules that were passed in to this hook so we - // can check that the modules were enabled in the correct sequence. - \Drupal::state()->set('module_test.install_order', $modules); -} - -/** - * Implements hook_modules_uninstalled(). - */ -function module_test_modules_uninstalled($modules): void { - // Record the ordered list of modules that were passed in to this hook so we - // can check that the modules were uninstalled in the correct sequence. - \Drupal::state()->set('module_test.uninstall_order', $modules); -} diff --git a/core/modules/system/tests/modules/module_test/src/Hook/ModuleTestFileThemeHooks.php b/core/modules/system/tests/modules/module_test/src/Hook/ModuleTestFileThemeHooks.php new file mode 100644 index 00000000000..381a9458260 --- /dev/null +++ b/core/modules/system/tests/modules/module_test/src/Hook/ModuleTestFileThemeHooks.php @@ -0,0 +1,40 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\module_test\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for module_test. + */ +class ModuleTestFileThemeHooks { + + /** + * Implements hook_test_hook(). + */ + #[Hook('test_hook')] + public function testHook(): array { + return [ + 'module_test' => 'success!', + ]; + } + + /** + * Implements hook_test_reset_implementations_hook(). + */ + #[Hook('test_reset_implementations_hook')] + public function testResetImplementationsHook(): string { + return 'module_test_test_reset_implementations_hook'; + } + + /** + * Implements hook_test_reset_implementations_alter(). + */ + #[Hook('test_reset_implementations_alter')] + public function testResetImplementationsAlter(array &$data): void { + $data[] = 'module_test_test_reset_implementations_alter'; + } + +} diff --git a/core/modules/system/tests/modules/module_test/src/Hook/ModuleTestThemeHooks.php b/core/modules/system/tests/modules/module_test/src/Hook/ModuleTestThemeHooks.php new file mode 100644 index 00000000000..a34adbe620c --- /dev/null +++ b/core/modules/system/tests/modules/module_test/src/Hook/ModuleTestThemeHooks.php @@ -0,0 +1,85 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\module_test\Hook; + +use Drupal\Core\Extension\Extension; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for module_test. + */ +class ModuleTestThemeHooks { + + /** + * Implements hook_system_info_alter(). + * + * Manipulate module dependencies to test dependency chains. + */ + #[Hook('system_info_alter')] + public function systemInfoAlter(&$info, Extension $file, $type): void { + if (\Drupal::state()->get('module_test.dependency') == 'missing dependency') { + if ($file->getName() == 'dblog') { + // Make dblog module depend on config. + $info['dependencies'][] = 'config'; + } + elseif ($file->getName() == 'config') { + // Make config module depend on a non-existing module. + $info['dependencies'][] = 'foo'; + } + } + elseif (\Drupal::state()->get('module_test.dependency') == 'dependency') { + if ($file->getName() == 'dblog') { + // Make dblog module depend on config. + $info['dependencies'][] = 'config'; + } + elseif ($file->getName() == 'config') { + // Make config module depend on help module. + $info['dependencies'][] = 'help'; + } + elseif ($file->getName() == 'entity_test') { + // Make entity test module depend on help module. + $info['dependencies'][] = 'help'; + } + } + elseif (\Drupal::state()->get('module_test.dependency') == 'version dependency') { + if ($file->getName() == 'dblog') { + // Make dblog module depend on config. + $info['dependencies'][] = 'config'; + } + elseif ($file->getName() == 'config') { + // Make config module depend on a specific version of help module. + $info['dependencies'][] = 'help (1.x)'; + } + elseif ($file->getName() == 'help') { + // Set help module to a version compatible with the above. + $info['version'] = '8.x-1.0'; + } + } + if ($file->getName() == 'stark' && $type == 'theme') { + $info['regions']['test_region'] = 'Test region'; + } + } + + /** + * Implements hook_modules_installed(). + */ + #[Hook('modules_installed')] + public function modulesInstalled($modules): void { + // Record the ordered list of modules that were passed in to this hook so we + // can check that the modules were enabled in the correct sequence. + \Drupal::state()->set('module_test.install_order', $modules); + } + + /** + * Implements hook_modules_uninstalled(). + */ + #[Hook('modules_uninstalled')] + public function modulesUninstalled($modules): void { + // Record the ordered list of modules that were passed in to this hook so we + // can check that the modules were uninstalled in the correct sequence. + \Drupal::state()->set('module_test.uninstall_order', $modules); + } + +} diff --git a/core/modules/system/tests/modules/olivero_test/olivero_test.module b/core/modules/system/tests/modules/olivero_test/olivero_test.module deleted file mode 100644 index 5d697759254..00000000000 --- a/core/modules/system/tests/modules/olivero_test/olivero_test.module +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/** - * @file - * Functions to support testing the Olivero theme. - */ - -declare(strict_types=1); - -/** - * Implements hook_preprocess_field_multiple_value_form(). - */ -function olivero_test_preprocess_field_multiple_value_form(&$variables): void { - // Set test multiple value form field to disabled - if ($variables["element"]["#field_name"] === "field_multiple_value_form_field") { - $variables['element']['#disabled'] = TRUE; - } -} - -/** - * Implements hook_preprocess_html(). - */ -function olivero_test_preprocess_html(&$variables): void { - $variables['#attached']['library'][] = 'olivero_test/log-errors'; -} diff --git a/core/modules/system/tests/modules/olivero_test/src/Hook/OliveroTestThemeHooks.php b/core/modules/system/tests/modules/olivero_test/src/Hook/OliveroTestThemeHooks.php new file mode 100644 index 00000000000..1a5f7247a74 --- /dev/null +++ b/core/modules/system/tests/modules/olivero_test/src/Hook/OliveroTestThemeHooks.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\olivero_test\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for olivero_test. + */ +class OliveroTestThemeHooks { + + /** + * Implements hook_preprocess_field_multiple_value_form(). + */ + #[Hook('preprocess_field_multiple_value_form')] + public function preprocessFieldMultipleValueForm(&$variables): void { + // Set test multiple value form field to disabled. + if ($variables["element"]["#field_name"] === "field_multiple_value_form_field") { + $variables['element']['#disabled'] = TRUE; + } + } + + /** + * Implements hook_preprocess_html(). + */ + #[Hook('preprocess_html')] + public function preprocessHtml(&$variables): void { + $variables['#attached']['library'][] = 'olivero_test/log-errors'; + } + +} diff --git a/core/modules/system/tests/modules/pager_test/pager_test.module b/core/modules/system/tests/modules/pager_test/pager_test.module deleted file mode 100644 index e4556eddba3..00000000000 --- a/core/modules/system/tests/modules/pager_test/pager_test.module +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/** - * @file - * Hook implementations for this module. - */ - -declare(strict_types=1); - -/** - * Implements hook_preprocess_HOOK(). - */ -function pager_test_preprocess_pager(&$variables): void { - // Nothing to do if there is only one page. - $element = $variables['pager']['#element']; - /** @var \Drupal\Core\Pager\PagerManagerInterface $pager_manager */ - $pager_manager = \Drupal::service('pager.manager'); - $pager = $pager_manager->getPager($element); - - // Nothing to do if there is no pager. - if (!isset($pager)) { - return; - } - - // Nothing to do if there is only one page. - if ($pager->getTotalPages() <= 1) { - return; - } - - foreach ($variables['items']['pages'] as &$pager_item) { - $pager_item['attributes']['pager-test'] = 'yes'; - $pager_item['attributes']->addClass('lizards'); - } - unset($pager_item); - - foreach (['first', 'previous', 'next', 'last'] as $special_pager_item) { - if (isset($variables['items'][$special_pager_item])) { - $variables['items'][$special_pager_item]['attributes']->addClass('lizards'); - $variables['items'][$special_pager_item]['attributes']['pager-test'] = $special_pager_item; - } - } -} diff --git a/core/modules/system/tests/modules/pager_test/src/Hook/PagerTestThemeHooks.php b/core/modules/system/tests/modules/pager_test/src/Hook/PagerTestThemeHooks.php new file mode 100644 index 00000000000..ae72036a552 --- /dev/null +++ b/core/modules/system/tests/modules/pager_test/src/Hook/PagerTestThemeHooks.php @@ -0,0 +1,50 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\pager_test\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for pager_test. + */ +class PagerTestThemeHooks { + + /** + * Implements hook_preprocess_HOOK(). + */ + #[Hook('preprocess_pager')] + public function preprocessPager(&$variables): void { + // Nothing to do if there is only one page. + $element = $variables['pager']['#element']; + /** @var \Drupal\Core\Pager\PagerManagerInterface $pager_manager */ + $pager_manager = \Drupal::service('pager.manager'); + $pager = $pager_manager->getPager($element); + // Nothing to do if there is no pager. + if (!isset($pager)) { + return; + } + // Nothing to do if there is only one page. + if ($pager->getTotalPages() <= 1) { + return; + } + foreach ($variables['items']['pages'] as &$pager_item) { + $pager_item['attributes']['pager-test'] = 'yes'; + $pager_item['attributes']->addClass('lizards'); + } + unset($pager_item); + foreach ([ + 'first', + 'previous', + 'next', + 'last', + ] as $special_pager_item) { + if (isset($variables['items'][$special_pager_item])) { + $variables['items'][$special_pager_item]['attributes']->addClass('lizards'); + $variables['items'][$special_pager_item]['attributes']['pager-test'] = $special_pager_item; + } + } + } + +} diff --git a/core/modules/system/tests/modules/router_test_directory/router_test.module b/core/modules/system/tests/modules/router_test_directory/router_test.module deleted file mode 100644 index 2158075059c..00000000000 --- a/core/modules/system/tests/modules/router_test_directory/router_test.module +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/** - * @file - * Test module. - */ - -declare(strict_types=1); - -use Drupal\Core\Url; - -/** - * Implements hook_preprocess_HOOK(). - * - * Performs an operation that calls the RouteProvider's collection method - * during an exception page view. (which is rendered during a subrequest.) - * - * @see \Drupal\FunctionalTests\Routing\RouteCachingQueryAlteredTest - */ -function router_test_preprocess_page(&$variables): void { - $request = \Drupal::request(); - if ($request->getPathInfo() === '/router-test/rejects-query-strings') { - // Create a URL from the request, e.g. for a breadcrumb or other contextual - // information. - Url::createFromRequest($request); - } -} diff --git a/core/modules/system/tests/modules/router_test_directory/src/Hook/RouterTestThemeHooks.php b/core/modules/system/tests/modules/router_test_directory/src/Hook/RouterTestThemeHooks.php new file mode 100644 index 00000000000..da642b8b13b --- /dev/null +++ b/core/modules/system/tests/modules/router_test_directory/src/Hook/RouterTestThemeHooks.php @@ -0,0 +1,33 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\router_test\Hook; + +use Drupal\Core\Url; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for router_test. + */ +class RouterTestThemeHooks { + + /** + * Implements hook_preprocess_HOOK(). + * + * Performs an operation that calls the RouteProvider's collection method + * during an exception page view. (which is rendered during a subrequest.) + * + * @see \Drupal\FunctionalTests\Routing\RouteCachingQueryAlteredTest + */ + #[Hook('preprocess_page')] + public function preprocessPage(&$variables): void { + $request = \Drupal::request(); + if ($request->getPathInfo() === '/router-test/rejects-query-strings') { + // Create a URL from the request, e.g. for a breadcrumb or other contextual + // information. + Url::createFromRequest($request); + } + } + +} diff --git a/core/modules/system/tests/modules/theme_region_test/src/Hook/ThemeRegionTestThemeHooks.php b/core/modules/system/tests/modules/theme_region_test/src/Hook/ThemeRegionTestThemeHooks.php new file mode 100644 index 00000000000..5cff4c19531 --- /dev/null +++ b/core/modules/system/tests/modules/theme_region_test/src/Hook/ThemeRegionTestThemeHooks.php @@ -0,0 +1,24 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\theme_region_test\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for theme_region_test. + */ +class ThemeRegionTestThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for region templates. + */ + #[Hook('preprocess_region')] + public function preprocessRegion(&$variables): void { + if ($variables['region'] == 'sidebar_first') { + $variables['attributes']['class'][] = 'new_class'; + } + } + +} diff --git a/core/modules/system/tests/modules/theme_region_test/theme_region_test.module b/core/modules/system/tests/modules/theme_region_test/theme_region_test.module deleted file mode 100644 index 5e9dc670a47..00000000000 --- a/core/modules/system/tests/modules/theme_region_test/theme_region_test.module +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -/** - * @file - * Provides hook implementations for testing purposes. - */ - -declare(strict_types=1); - -/** - * Implements hook_preprocess_HOOK() for region templates. - */ -function theme_region_test_preprocess_region(&$variables): void { - if ($variables['region'] == 'sidebar_first') { - $variables['attributes']['class'][] = 'new_class'; - } -} diff --git a/core/modules/system/tests/modules/theme_test/src/Hook/ThemeTestThemeHooks1.php b/core/modules/system/tests/modules/theme_test/src/Hook/ThemeTestThemeHooks1.php new file mode 100644 index 00000000000..ddd0e7efc39 --- /dev/null +++ b/core/modules/system/tests/modules/theme_test/src/Hook/ThemeTestThemeHooks1.php @@ -0,0 +1,62 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\theme_test\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for theme_test. + */ +class ThemeTestThemeHooks1 { + + /** + * Implements hook_preprocess_HOOK() for HTML document templates. + */ + #[Hook('preprocess_html')] + public function preprocessHtml(&$variables): void { + $variables['html_attributes']['theme_test_html_attribute'] = 'theme test html attribute value'; + $variables['attributes']['theme_test_body_attribute'] = 'theme test body attribute value'; + $variables['attributes']['theme_test_page_variable'] = 'Page variable is an array.'; + } + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_theme_test_preprocess_suggestions')] + public function themeSuggestionsThemeTestPreprocessSuggestions($variables): array { + return [ + 'theme_test_preprocess_suggestions__' . $variables['foo'], + ]; + } + + /** + * Implements hook_preprocess_HOOK(). + */ + #[Hook('preprocess_theme_test_preprocess_suggestions')] + public function preprocessThemeTestPreprocessSuggestions(&$variables): void { + $variables['foo'] = 'Theme hook implementor=theme_theme_test_preprocess_suggestions().'; + } + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_theme_test_suggestion_provided')] + public function themeSuggestionsThemeTestSuggestionProvided(array $variables): array { + return [ + 'theme_test_suggestion_provided__foo', + ]; + } + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_node')] + public function themeSuggestionsNode(array $variables): array { + $xss = '<script type="text/javascript">alert(\'yo\');</script>'; + $suggestions[] = 'node__' . $xss; + return $suggestions; + } + +} diff --git a/core/modules/system/tests/modules/theme_test/theme_test.module b/core/modules/system/tests/modules/theme_test/theme_test.module index 72c92352b61..b987fb0d40f 100644 --- a/core/modules/system/tests/modules/theme_test/theme_test.module +++ b/core/modules/system/tests/modules/theme_test/theme_test.module @@ -8,30 +8,6 @@ declare(strict_types=1); /** - * Implements hook_preprocess_HOOK() for HTML document templates. - */ -function theme_test_preprocess_html(&$variables): void { - $variables['html_attributes']['theme_test_html_attribute'] = 'theme test html attribute value'; - $variables['attributes']['theme_test_body_attribute'] = 'theme test body attribute value'; - - $variables['attributes']['theme_test_page_variable'] = 'Page variable is an array.'; -} - -/** - * Implements hook_theme_suggestions_HOOK(). - */ -function theme_test_theme_suggestions_theme_test_preprocess_suggestions($variables): array { - return ['theme_test_preprocess_suggestions__' . $variables['foo']]; -} - -/** - * Implements hook_preprocess_HOOK(). - */ -function theme_test_preprocess_theme_test_preprocess_suggestions(&$variables): void { - $variables['foo'] = 'Theme hook implementor=theme_theme_test_preprocess_suggestions().'; -} - -/** * Prepares variables for test render element templates. * * Default template: theme-test-render-element.html.twig. @@ -45,23 +21,6 @@ function template_preprocess_theme_test_render_element(&$variables): void { } /** - * Implements hook_theme_suggestions_HOOK(). - */ -function theme_test_theme_suggestions_theme_test_suggestion_provided(array $variables): array { - return ['theme_test_suggestion_provided__foo']; -} - -/** - * Implements hook_theme_suggestions_HOOK(). - */ -function theme_test_theme_suggestions_node(array $variables): array { - $xss = '<script type="text/javascript">alert(\'yo\');</script>'; - $suggestions[] = 'node__' . $xss; - - return $suggestions; -} - -/** * Implements template_preprocess_HOOK() for theme_test_registered_by_module. */ function template_preprocess_theme_test_registered_by_module(): void { diff --git a/core/modules/system/tests/src/Functional/Database/SelectTableSortDefaultTest.php b/core/modules/system/tests/src/Functional/Database/SelectTableSortDefaultTest.php index 60b7c12b5a1..72e95946a5d 100644 --- a/core/modules/system/tests/src/Functional/Database/SelectTableSortDefaultTest.php +++ b/core/modules/system/tests/src/Functional/Database/SelectTableSortDefaultTest.php @@ -28,7 +28,7 @@ class SelectTableSortDefaultTest extends DatabaseTestBase { ['field' => 'Task ID', 'sort' => 'asc', 'first' => 'eat', 'last' => 'perform at superbowl'], ['field' => 'Task', 'sort' => 'asc', 'first' => 'code', 'last' => 'sleep'], ['field' => 'Task', 'sort' => 'desc', 'first' => 'sleep', 'last' => 'code'], - // More elements here + // More elements here. ]; @@ -56,7 +56,7 @@ class SelectTableSortDefaultTest extends DatabaseTestBase { ['field' => 'Task ID', 'sort' => 'asc', 'first' => 'eat', 'last' => 'perform at superbowl'], ['field' => 'Task', 'sort' => 'asc', 'first' => 'code', 'last' => 'sleep'], ['field' => 'Task', 'sort' => 'desc', 'first' => 'sleep', 'last' => 'code'], - // More elements here + // More elements here. ]; diff --git a/core/modules/system/tests/src/Functional/FileTransfer/FileTransferTest.php b/core/modules/system/tests/src/Functional/FileTransfer/FileTransferTest.php index fa6bda652de..61ea15323c1 100644 --- a/core/modules/system/tests/src/Functional/FileTransfer/FileTransferTest.php +++ b/core/modules/system/tests/src/Functional/FileTransfer/FileTransferTest.php @@ -77,7 +77,7 @@ class FileTransferTest extends BrowserTestBase { $this->_writeDirectory($base . DIRECTORY_SEPARATOR . $key, $file); } else { - // Just write the filename into the file + // Just write the filename into the file. file_put_contents($base . DIRECTORY_SEPARATOR . $file, $file); } } diff --git a/core/modules/system/tests/src/Functional/Form/ElementTest.php b/core/modules/system/tests/src/Functional/Form/ElementTest.php index 0ebf9e4ce77..294c4e2ec34 100644 --- a/core/modules/system/tests/src/Functional/Form/ElementTest.php +++ b/core/modules/system/tests/src/Functional/Form/ElementTest.php @@ -154,10 +154,10 @@ class ElementTest extends BrowserTestBase { * Tests the submit_button attribute. */ protected function testSubmitButtonAttribute(): void { - // Set the submit_button attribute to true + // Set the submit_button attribute to true. $this->drupalGet('form-test/submit-button-attribute'); $this->assertSession()->elementsCount('xpath', '//input[@type="submit"]', 1); - // Set the submit_button attribute to false + // Set the submit_button attribute to false. $this->drupalGet('form-test/submit-button-attribute/1'); $this->assertSession()->elementsCount('xpath', '//input[@type="button"]', 1); } diff --git a/core/modules/system/tests/src/Functional/Form/FormTest.php b/core/modules/system/tests/src/Functional/Form/FormTest.php index f45e45e6159..c7cb67c72c7 100644 --- a/core/modules/system/tests/src/Functional/Form/FormTest.php +++ b/core/modules/system/tests/src/Functional/Form/FormTest.php @@ -306,12 +306,12 @@ class FormTest extends BrowserTestBase { ]; $this->submitForm($edit, 'Submit'); // Verify that the error message is displayed with invalid token even when - // required fields are filled.' + // required fields are filled. $this->assertSession()->elementExists('xpath', '//div[contains(@class, "error")]'); $this->assertSession()->pageTextContains('The form has become outdated.'); $this->assertSession()->fieldValueEquals('integer_step', 5); - // Check a form with a URL field + // Check a form with a URL field. $this->drupalGet(Url::fromRoute('form_test.url')); $this->assertSession() ->elementExists('css', 'input[name="form_token"]') diff --git a/core/modules/system/tests/src/Functional/Menu/LocalTasksTest.php b/core/modules/system/tests/src/Functional/Menu/LocalTasksTest.php index f2df8a91458..c7d6f6d7d2b 100644 --- a/core/modules/system/tests/src/Functional/Menu/LocalTasksTest.php +++ b/core/modules/system/tests/src/Functional/Menu/LocalTasksTest.php @@ -170,7 +170,7 @@ class LocalTasksTest extends BrowserTestBase { $this->assertEquals('Settings', $result[0]->getText(), 'The settings tab is active.'); $this->assertEquals('Derive 1', $result[1]->getText(), 'The derive1 tab is active.'); - // Ensures that the local tasks contains the proper 'provider key' + // Ensures that the local tasks contains the proper 'provider key'. $definitions = $this->container->get('plugin.manager.menu.local_task')->getDefinitions(); $this->assertEquals('menu_test', $definitions['menu_test.local_task_test_tasks_view']['provider']); $this->assertEquals('menu_test', $definitions['menu_test.local_task_test_tasks_edit']['provider']); diff --git a/core/modules/system/tests/src/Functional/Module/DependencyTest.php b/core/modules/system/tests/src/Functional/Module/DependencyTest.php index 7f2d218388a..2a51e4b8de8 100644 --- a/core/modules/system/tests/src/Functional/Module/DependencyTest.php +++ b/core/modules/system/tests/src/Functional/Module/DependencyTest.php @@ -142,7 +142,7 @@ class DependencyTest extends ModuleTestBase { $this->assertSession()->fieldEnabled('modules[system_no_module_version_dependency_test][enable]'); $this->assertSession()->fieldDisabled('modules[system_no_module_version_test][enable]'); - // Remove the version requirement from the dependency definition + // Remove the version requirement from the dependency definition. $info = [ 'type' => 'module', 'core_version_requirement' => '*', @@ -253,9 +253,8 @@ class DependencyTest extends ModuleTestBase { $this->resetAll(); $this->assertModules(['module_test'], TRUE); \Drupal::state()->set('module_test.dependency', 'dependency'); - // module_test creates a dependency chain: - // - dblog depends on config - // - config depends on help + // module_test creates a dependency chain: dblog depends on config which + // depends on help. $expected_order = ['help', 'config', 'dblog']; // Enable the modules through the UI, verifying that the dependency chain diff --git a/core/modules/system/tests/src/Functional/Pager/PagerTest.php b/core/modules/system/tests/src/Functional/Pager/PagerTest.php index 9d0cae26b41..3cbde95efb4 100644 --- a/core/modules/system/tests/src/Functional/Pager/PagerTest.php +++ b/core/modules/system/tests/src/Functional/Pager/PagerTest.php @@ -179,7 +179,7 @@ class PagerTest extends BrowserTestBase { // We loop through the page with the test data query parameters, and check // that the active page for each pager element has the expected page - // (1-indexed) and resulting query parameter + // (1-indexed) and resulting query parameter. foreach ($test_data as $data) { $input_query = str_replace(' ', '%20', $data['input_query']); $this->drupalGet($this->getAbsoluteUrl(parse_url($this->getUrl())['path'] . $input_query), ['external' => TRUE]); diff --git a/core/modules/system/tests/src/Functional/ParamConverter/UpcastingTest.php b/core/modules/system/tests/src/Functional/ParamConverter/UpcastingTest.php index a3a89112afe..165fb692952 100644 --- a/core/modules/system/tests/src/Functional/ParamConverter/UpcastingTest.php +++ b/core/modules/system/tests/src/Functional/ParamConverter/UpcastingTest.php @@ -41,19 +41,19 @@ class UpcastingTest extends BrowserTestBase { $user = $this->drupalCreateUser(['access content']); $foo = 'bar'; - // paramconverter_test/test_user_node_foo/{user}/{node}/{foo} + // Test "paramconverter_test/test_user_node_foo/{user}/{node}/{foo}". $this->drupalGet("paramconverter_test/test_user_node_foo/" . $user->id() . '/' . $node->id() . "/$foo"); // Verify user and node upcast by entity name. $this->assertSession()->pageTextContains("user: {$user->label()}, node: {$node->label()}, foo: $foo"); - // paramconverter_test/test_node_user_user/{node}/{foo}/{user} - // options.parameters.foo.type = entity:user + // Test "paramconverter_test/test_node_user_user/{node}/{foo}/{user}" with + // "options.parameters.foo.type = entity:user". $this->drupalGet("paramconverter_test/test_node_user_user/" . $node->id() . "/" . $user->id() . "/" . $user->id()); // Verify foo converted to user as well. $this->assertSession()->pageTextContains("user: {$user->label()}, node: {$node->label()}, foo: {$user->label()}"); - // paramconverter_test/test_node_node_foo/{user}/{node}/{foo} - // options.parameters.user.type = entity:node + // Test "paramconverter_test/test_node_node_foo/{user}/{node}/{foo}" with + // "options.parameters.user.type = entity:node". $this->drupalGet("paramconverter_test/test_node_node_foo/" . $node->id() . "/" . $node->id() . "/$foo"); // Verify that user is upcast to node (rather than to user). $this->assertSession()->pageTextContains("user: {$node->label()}, node: {$node->label()}, foo: $foo"); @@ -65,8 +65,8 @@ class UpcastingTest extends BrowserTestBase { public function testSameTypes(): void { $node = $this->drupalCreateNode(['title' => $this->randomMachineName(8)]); $parent = $this->drupalCreateNode(['title' => $this->randomMachineName(8)]); - // paramconverter_test/node/{node}/set/parent/{parent} - // options.parameters.parent.type = entity:node + // Test "paramconverter_test/node/{node}/set/parent/{parent}" with + // "options.parameters.parent.type = entity:node". $this->drupalGet("paramconverter_test/node/" . $node->id() . "/set/parent/" . $parent->id()); $this->assertSession()->pageTextContains("Setting '" . $parent->getTitle() . "' as parent of '" . $node->getTitle() . "'."); } diff --git a/core/modules/system/tests/src/Functional/System/AccessDeniedTest.php b/core/modules/system/tests/src/Functional/System/AccessDeniedTest.php index 0163c594a06..51d8d20713e 100644 --- a/core/modules/system/tests/src/Functional/System/AccessDeniedTest.php +++ b/core/modules/system/tests/src/Functional/System/AccessDeniedTest.php @@ -115,7 +115,7 @@ class AccessDeniedTest extends BrowserTestBase { $this->assertSession()->statusCodeEquals(403); $this->assertSession()->pageTextContains('Username'); - // Log back in, set the custom 403 page to /user/login and remove the block + // Log back in, set the custom 403 page to /user/login and remove the block. $this->drupalLogin($this->adminUser); $this->config('system.site')->set('page.403', '/user/login')->save(); $block->disable()->save(); diff --git a/core/modules/system/tests/src/Functional/System/PageTitleTest.php b/core/modules/system/tests/src/Functional/System/PageTitleTest.php index d225842a236..cf2a5a61512 100644 --- a/core/modules/system/tests/src/Functional/System/PageTitleTest.php +++ b/core/modules/system/tests/src/Functional/System/PageTitleTest.php @@ -126,7 +126,7 @@ class PageTitleTest extends BrowserTestBase { $this->assertSession()->titleEquals('Foo | Drupal'); $this->assertSession()->elementTextEquals('xpath', '//h1[@class="page-title"]', 'Foo'); - // Test forms + // Test forms. $this->drupalGet('form-test/object-builder'); $this->assertSession()->titleEquals('Test dynamic title | Drupal'); diff --git a/core/modules/system/tests/src/FunctionalJavascript/Form/ElementsTableSelectTest.php b/core/modules/system/tests/src/FunctionalJavascript/Form/ElementsTableSelectTest.php index a41129b9cff..10ffd2523d3 100644 --- a/core/modules/system/tests/src/FunctionalJavascript/Form/ElementsTableSelectTest.php +++ b/core/modules/system/tests/src/FunctionalJavascript/Form/ElementsTableSelectTest.php @@ -51,7 +51,7 @@ class ElementsTableSelectTest extends WebDriverTestBase { $this->click($row); $this->assertSession()->assertWaitOnAjaxRequest(); $page->hasCheckedField($row); - // Check other rows are not checked + // Check other rows are not checked. for ($j = 1; $j <= 3; $j++) { if ($j == $i) { continue; diff --git a/core/modules/system/tests/src/FunctionalJavascript/OffCanvasTest.php b/core/modules/system/tests/src/FunctionalJavascript/OffCanvasTest.php index 9839fc3edd4..462bf5a9e67 100644 --- a/core/modules/system/tests/src/FunctionalJavascript/OffCanvasTest.php +++ b/core/modules/system/tests/src/FunctionalJavascript/OffCanvasTest.php @@ -96,7 +96,7 @@ class OffCanvasTest extends OffCanvasTestBase { $page->clickLink('Display more links!'); $this->waitForOffCanvasToOpen(); $web_assert->linkExists('Off_canvas link!'); - // Click off-canvas link inside off-canvas dialog + // Click off-canvas link inside off-canvas dialog. $page->clickLink('Off_canvas link!'); $this->waitForOffCanvasToOpen(); $web_assert->elementTextContains('css', '.ui-dialog[aria-describedby="drupal-off-canvas"]', 'Thing 2 says hello'); @@ -109,7 +109,7 @@ class OffCanvasTest extends OffCanvasTestBase { $page->clickLink('Display more links!'); $this->waitForOffCanvasToOpen(); $web_assert->linkExists('Off_canvas link!'); - // Click off-canvas link inside off-canvas dialog + // Click off-canvas link inside off-canvas dialog. $page->clickLink('Off_canvas link!'); $this->waitForOffCanvasToOpen(); $web_assert->elementTextContains('css', '.ui-dialog[aria-describedby="drupal-off-canvas"]', 'Thing 2 says hello'); diff --git a/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php b/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php index b8b18a5c9ba..9a69e563f01 100644 --- a/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php +++ b/core/modules/system/tests/src/Kernel/Migrate/d7/MigrateSystemConfigurationTest.php @@ -27,8 +27,7 @@ class MigrateSystemConfigurationTest extends MigrateDrupal7TestBase { 'system.authorize' => [], 'system.cron' => [ 'threshold' => [ - // Auto-run is not handled by the migration. - // 'autorun' => 0, + // Auto-run is not handled by the migration, so ignore "'autorun' => 0". 'requirements_warning' => 172800, 'requirements_error' => 1209600, ], diff --git a/core/modules/taxonomy/src/Hook/TaxonomyThemeHooks.php b/core/modules/taxonomy/src/Hook/TaxonomyThemeHooks.php new file mode 100644 index 00000000000..89f177daf24 --- /dev/null +++ b/core/modules/taxonomy/src/Hook/TaxonomyThemeHooks.php @@ -0,0 +1,25 @@ +<?php + +namespace Drupal\taxonomy\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for taxonomy. + */ +class TaxonomyThemeHooks { + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_taxonomy_term')] + public function themeSuggestionsTaxonomyTerm(array $variables): array { + $suggestions = []; + /** @var \Drupal\taxonomy\TermInterface $term */ + $term = $variables['elements']['#taxonomy_term']; + $suggestions[] = 'taxonomy_term__' . $term->bundle(); + $suggestions[] = 'taxonomy_term__' . $term->id(); + return $suggestions; + } + +} diff --git a/core/modules/taxonomy/src/Hook/TaxonomyTokensHooks.php b/core/modules/taxonomy/src/Hook/TaxonomyTokensHooks.php index 12c8f7dc885..7c7fbf63d98 100644 --- a/core/modules/taxonomy/src/Hook/TaxonomyTokensHooks.php +++ b/core/modules/taxonomy/src/Hook/TaxonomyTokensHooks.php @@ -65,7 +65,7 @@ class TaxonomyTokensHooks { 'name' => $this->t("Term count"), 'description' => $this->t("The number of terms belonging to the taxonomy vocabulary."), ]; - // Chained tokens for taxonomies + // Chained tokens for taxonomies. $term['vocabulary'] = [ 'name' => $this->t("Vocabulary"), 'description' => $this->t("The vocabulary the taxonomy term belongs to."), diff --git a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php index 7b7a57363bc..f4fd0c8641f 100644 --- a/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php +++ b/core/modules/taxonomy/src/Plugin/views/argument_default/Tid.php @@ -181,7 +181,7 @@ class Tid extends ArgumentDefaultPluginBase implements CacheableDependencyInterf } if (!empty($this->options['limit'])) { $tids = []; - // Filter by vocabulary + // Filter by vocabulary. foreach ($taxonomy as $tid => $vocab) { if (!empty($this->options['vids'][$vocab])) { $tids[] = $tid; diff --git a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php index 6d1b18c7647..e48931b5267 100644 --- a/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php +++ b/core/modules/taxonomy/src/Plugin/views/filter/TaxonomyIndexTid.php @@ -289,7 +289,7 @@ class TaxonomyIndexTid extends ManyToOne { } if (!$form_state->get('exposed')) { - // Retain the helper option + // Retain the helper option. $this->helper->buildOptionsForm($form, $form_state); // Show help text if not exposed to end users. @@ -330,7 +330,7 @@ class TaxonomyIndexTid extends ManyToOne { } // If view is an attachment and is inheriting exposed filters, then assume - // exposed input has already been validated + // exposed input has already been validated. if (!empty($this->view->is_attachment) && $this->view->display_handler->usesExposed()) { $this->validated_exposed_input = (array) $this->view->exposed_raw_input[$this->options['expose']['identifier']]; } @@ -418,7 +418,7 @@ class TaxonomyIndexTid extends ManyToOne { * {@inheritdoc} */ public function adminSummary() { - // Set up $this->valueOptions for the parent summary + // Set up $this->valueOptions for the parent summary. $this->valueOptions = []; if ($this->value) { diff --git a/core/modules/taxonomy/src/Plugin/views/relationship/NodeTermData.php b/core/modules/taxonomy/src/Plugin/views/relationship/NodeTermData.php index 5987d9fe933..28c9cc8b06b 100644 --- a/core/modules/taxonomy/src/Plugin/views/relationship/NodeTermData.php +++ b/core/modules/taxonomy/src/Plugin/views/relationship/NodeTermData.php @@ -109,7 +109,7 @@ class NodeTermData extends RelationshipPluginBase { $def['type'] = empty($this->options['required']) ? 'LEFT' : 'INNER'; } else { - // If vocabularies are supplied join a subselect instead + // If vocabularies are supplied join a subselect instead. $def['left_table'] = $this->tableAlias; $def['left_field'] = 'nid'; $def['field'] = 'nid'; diff --git a/core/modules/taxonomy/src/TermViewsData.php b/core/modules/taxonomy/src/TermViewsData.php index 7ca182d9693..c6a1463fc25 100644 --- a/core/modules/taxonomy/src/TermViewsData.php +++ b/core/modules/taxonomy/src/TermViewsData.php @@ -139,12 +139,12 @@ class TermViewsData extends EntityViewsData { $data['taxonomy_index']['table']['join'] = [ 'taxonomy_term_field_data' => [ - // Links directly to taxonomy_term_field_data via tid + // Links directly to taxonomy_term_field_data via tid. 'left_field' => 'tid', 'field' => 'tid', ], 'node_field_data' => [ - // Links directly to node via nid + // Links directly to node via nid. 'left_field' => 'nid', 'field' => 'nid', ], diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index 28e54b11f71..6694f62e563 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -10,21 +10,6 @@ use Drupal\Core\Render\Element; use Drupal\taxonomy\Entity\Term; /** - * Implements hook_theme_suggestions_HOOK(). - */ -function taxonomy_theme_suggestions_taxonomy_term(array $variables): array { - $suggestions = []; - - /** @var \Drupal\taxonomy\TermInterface $term */ - $term = $variables['elements']['#taxonomy_term']; - - $suggestions[] = 'taxonomy_term__' . $term->bundle(); - $suggestions[] = 'taxonomy_term__' . $term->id(); - - return $suggestions; -} - -/** * Prepares variables for taxonomy term templates. * * Default template: taxonomy-term.html.twig. diff --git a/core/modules/taxonomy/tests/src/Functional/TermLanguageTest.php b/core/modules/taxonomy/tests/src/Functional/TermLanguageTest.php index 4fa2b896c25..11ba24f7c06 100644 --- a/core/modules/taxonomy/tests/src/Functional/TermLanguageTest.php +++ b/core/modules/taxonomy/tests/src/Functional/TermLanguageTest.php @@ -164,7 +164,7 @@ class TermLanguageTest extends TaxonomyTestBase { ]); $term->save(); - // Overview page in the other language shows the translated term + // Overview page in the other language shows the translated term. $this->drupalGet('bb/admin/structure/taxonomy/manage/' . $this->vocabulary->id() . '/overview'); $this->assertSession()->responseMatches('|<a[^>]*>' . $translated_title . '</a>|'); } diff --git a/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php index 83a3ce1521c..ccaab589e5c 100644 --- a/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php @@ -133,7 +133,7 @@ abstract class TextItemBase extends FieldItemBase { $settings = $field_definition->getSettings(); if (empty($settings['max_length'])) { - // Textarea handling + // Textarea handling. $value = $random->paragraphs(); } else { diff --git a/core/modules/toolbar/src/Hook/ToolbarThemeHooks.php b/core/modules/toolbar/src/Hook/ToolbarThemeHooks.php new file mode 100644 index 00000000000..fb08f0ffde6 --- /dev/null +++ b/core/modules/toolbar/src/Hook/ToolbarThemeHooks.php @@ -0,0 +1,23 @@ +<?php + +namespace Drupal\toolbar\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for toolbar. + */ +class ToolbarThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for HTML document templates. + */ + #[Hook('preprocess_html')] + public function preprocessHtml(&$variables): void { + if (!\Drupal::currentUser()->hasPermission('access toolbar')) { + return; + } + $variables['attributes']['class'][] = 'toolbar-loading'; + } + +} diff --git a/core/modules/toolbar/tests/modules/toolbar_test/src/Hook/ToolbarTestThemeHooks.php b/core/modules/toolbar/tests/modules/toolbar_test/src/Hook/ToolbarTestThemeHooks.php new file mode 100644 index 00000000000..e1d40c8219a --- /dev/null +++ b/core/modules/toolbar/tests/modules/toolbar_test/src/Hook/ToolbarTestThemeHooks.php @@ -0,0 +1,30 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\toolbar_test\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for toolbar_test. + */ +class ToolbarTestThemeHooks { + + /** + * Implements hook_preprocess_HOOK(). + */ + #[Hook('preprocess_menu')] + public function preprocessMenu(&$variables): void { + // All the standard hook_theme variables should be populated when the + // Toolbar module is rendering a menu. + foreach ([ + 'menu_name', + 'items', + 'attributes', + ] as $variable) { + $variables[$variable]; + } + } + +} diff --git a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module deleted file mode 100644 index 8980eb4a6ef..00000000000 --- a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/** - * @file - * A dummy module to test API interaction with the Toolbar module. - */ - -declare(strict_types=1); - -/** - * Implements hook_preprocess_HOOK(). - */ -function toolbar_test_preprocess_menu(&$variables): void { - // All the standard hook_theme variables should be populated when the - // Toolbar module is rendering a menu. - foreach (['menu_name', 'items', 'attributes'] as $variable) { - $variables[$variable]; - } -} diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index 51986310901..4bfcd89e187 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -118,17 +118,6 @@ function toolbar_menu_navigation_links(array $tree) { } /** - * Implements hook_preprocess_HOOK() for HTML document templates. - */ -function toolbar_preprocess_html(&$variables): void { - if (!\Drupal::currentUser()->hasPermission('access toolbar')) { - return; - } - - $variables['attributes']['class'][] = 'toolbar-loading'; -} - -/** * Returns the rendered subtree of each top-level toolbar link. * * @return array diff --git a/core/modules/update/update.compare.inc b/core/modules/update/update.compare.inc index 05c6565ce19..800b10d0e50 100644 --- a/core/modules/update/update.compare.inc +++ b/core/modules/update/update.compare.inc @@ -32,7 +32,7 @@ function update_process_project_info(&$projects): void { $info = $project['info']; if (isset($info['version'])) { - // Check for development snapshots + // Check for development snapshots. if (preg_match('@(dev|HEAD)@', $info['version'])) { $install_type = 'dev'; } diff --git a/core/modules/user/config/schema/user.schema.yml b/core/modules/user/config/schema/user.schema.yml index d58cb3dc4ea..54990b28497 100644 --- a/core/modules/user/config/schema/user.schema.yml +++ b/core/modules/user/config/schema/user.schema.yml @@ -115,27 +115,22 @@ user.flood: type: integer label: 'IP limit' constraints: - Range: - min: 0 + PositiveOrZero: ~ ip_window: type: integer label: 'IP window' constraints: - Range: - min: 0 + PositiveOrZero: ~ user_limit: type: integer label: 'User limit' constraints: - Range: - min: 0 + PositiveOrZero: ~ user_window: type: integer label: 'User window' constraints: - Range: - min: 0 - + PositiveOrZero: ~ user.role.*: type: config_entity label: 'User role settings' diff --git a/core/modules/user/src/Hook/UserThemeHooks.php b/core/modules/user/src/Hook/UserThemeHooks.php new file mode 100644 index 00000000000..9d334a68523 --- /dev/null +++ b/core/modules/user/src/Hook/UserThemeHooks.php @@ -0,0 +1,26 @@ +<?php + +namespace Drupal\user\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for user. + */ +class UserThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for block templates. + */ + #[Hook('preprocess_block')] + public function preprocessBlock(&$variables): void { + if ($variables['configuration']['provider'] == 'user') { + switch ($variables['elements']['#plugin_id']) { + case 'user_login_block': + $variables['attributes']['role'] = 'form'; + break; + } + } + } + +} diff --git a/core/modules/user/src/Plugin/Validation/Constraint/UserNameConstraintValidator.php b/core/modules/user/src/Plugin/Validation/Constraint/UserNameConstraintValidator.php index 0310a62e453..12b46aee574 100644 --- a/core/modules/user/src/Plugin/Validation/Constraint/UserNameConstraintValidator.php +++ b/core/modules/user/src/Plugin/Validation/Constraint/UserNameConstraintValidator.php @@ -32,23 +32,23 @@ class UserNameConstraintValidator extends ConstraintValidator { } if (preg_match('/[^\x{80}-\x{F7} a-z0-9@+_.\'-]/i', $name) || preg_match( - // Non-printable ISO-8859-1 + NBSP + // Non-printable ISO-8859-1 + NBSP. '/[\x{80}-\x{A0}' . - // Soft-hyphen + // Soft-hyphen. '\x{AD}' . - // Various space characters + // Various space characters. '\x{2000}-\x{200F}' . - // Bidirectional text overrides + // Bidirectional text overrides. '\x{2028}-\x{202F}' . - // Various text hinting characters + // Various text hinting characters. '\x{205F}-\x{206F}' . - // Byte order mark + // Byte order mark. '\x{FEFF}' . - // Full-width latin + // Full-width latin. '\x{FF01}-\x{FF60}' . - // Replacement characters + // Replacement characters. '\x{FFF9}-\x{FFFD}' . - // NULL byte and control characters + // NULL byte and control characters. '\x{0}-\x{1F}]/u', $name) ) { diff --git a/core/modules/user/src/Plugin/views/access/Permission.php b/core/modules/user/src/Plugin/views/access/Permission.php index ac66b6229b8..aeeb52ca290 100644 --- a/core/modules/user/src/Plugin/views/access/Permission.php +++ b/core/modules/user/src/Plugin/views/access/Permission.php @@ -129,7 +129,7 @@ class Permission extends AccessPluginBase implements CacheableDependencyInterfac */ public function buildOptionsForm(&$form, FormStateInterface $form_state) { parent::buildOptionsForm($form, $form_state); - // Get list of permissions + // Get list of permissions. $perms = []; $permissions = $this->permissionHandler->getPermissions(); foreach ($permissions as $perm => $perm_item) { diff --git a/core/modules/user/src/Plugin/views/argument_validator/User.php b/core/modules/user/src/Plugin/views/argument_validator/User.php index 6133434644c..b8db861db79 100644 --- a/core/modules/user/src/Plugin/views/argument_validator/User.php +++ b/core/modules/user/src/Plugin/views/argument_validator/User.php @@ -83,7 +83,7 @@ class User extends Entity { */ public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = []) { // Filter trash out of the options so we don't store giant unnecessary - // arrays + // arrays. $options['roles'] = array_filter($options['roles']); } diff --git a/core/modules/user/src/Plugin/views/filter/Name.php b/core/modules/user/src/Plugin/views/filter/Name.php index 267ef6176df..3a03b09fddf 100644 --- a/core/modules/user/src/Plugin/views/filter/Name.php +++ b/core/modules/user/src/Plugin/views/filter/Name.php @@ -133,7 +133,7 @@ class Name extends InOperator { * {@inheritdoc} */ public function adminSummary() { - // Set up $this->valueOptions for the parent summary + // Set up $this->valueOptions for the parent summary. $this->valueOptions = []; if ($this->value) { diff --git a/core/modules/user/tests/src/Functional/UserAdminTest.php b/core/modules/user/tests/src/Functional/UserAdminTest.php index a400af7a7e0..fa159a757eb 100644 --- a/core/modules/user/tests/src/Functional/UserAdminTest.php +++ b/core/modules/user/tests/src/Functional/UserAdminTest.php @@ -138,14 +138,14 @@ class UserAdminTest extends BrowserTestBase { $account = $user_storage->load($user_c->id()); $this->assertTrue($account->isBlocked(), 'User C blocked'); - // Test filtering on admin page for blocked users + // Test filtering on admin page for blocked users. $this->drupalGet('admin/people', ['query' => ['status' => 2]]); $this->assertSession()->elementNotExists('xpath', static::getLinkSelectorForUser($user_a)); $this->assertSession()->elementNotExists('xpath', static::getLinkSelectorForUser($user_b)); $this->assertSession()->elementExists('xpath', static::getLinkSelectorForUser($user_c)); // Test unblocking of a user from /admin/people page and sending of - // activation mail + // activation mail. $edit_unblock = []; $edit_unblock['action'] = 'user_unblock_user_action'; $edit_unblock['user_bulk_form[4]'] = TRUE; diff --git a/core/modules/user/tests/src/Functional/UserCancelTest.php b/core/modules/user/tests/src/Functional/UserCancelTest.php index 65787a0729b..27ab5fc6142 100644 --- a/core/modules/user/tests/src/Functional/UserCancelTest.php +++ b/core/modules/user/tests/src/Functional/UserCancelTest.php @@ -279,7 +279,7 @@ class UserCancelTest extends BrowserTestBase { public function testUserBlockUnpublishNodeAccess(): void { \Drupal::service('module_installer')->install(['node_access_test', 'user_form_test']); - // Setup node access + // Setup node access. node_access_rebuild(); $this->addPrivateField(NodeType::load('page')); \Drupal::state()->set('node_access_test.private', TRUE); diff --git a/core/modules/user/tests/src/Functional/UserSearchTest.php b/core/modules/user/tests/src/Functional/UserSearchTest.php index dd957dfe88d..d69eee78341 100644 --- a/core/modules/user/tests/src/Functional/UserSearchTest.php +++ b/core/modules/user/tests/src/Functional/UserSearchTest.php @@ -93,7 +93,7 @@ class UserSearchTest extends BrowserTestBase { $this->assertSession()->pageTextContains($keys); $this->assertSession()->pageTextContains($user2->getAccountName()); - // Verify that wildcard search works for email + // Verify that wildcard search works for email. $subkey = substr($keys, 0, 2) . '*' . substr($keys, 4, 2); $edit = ['keys' => $subkey]; $this->drupalGet('search/user'); diff --git a/core/modules/user/tests/src/Functional/Views/BulkFormAccessTest.php b/core/modules/user/tests/src/Functional/Views/BulkFormAccessTest.php index 1841c4ab4d3..575af2625d2 100644 --- a/core/modules/user/tests/src/Functional/Views/BulkFormAccessTest.php +++ b/core/modules/user/tests/src/Functional/Views/BulkFormAccessTest.php @@ -65,7 +65,7 @@ class BulkFormAccessTest extends UserTestBase { $no_edit_user = User::load($no_edit_user->id()); $this->assertFalse($no_edit_user->isBlocked(), 'The user is not blocked.'); - // Create a normal user which can be edited by the admin user + // Create a normal user which can be edited by the admin user. $normal_user = $this->drupalCreateUser(); $this->assertTrue($normal_user->access('update', $admin_user)); diff --git a/core/modules/user/tests/src/FunctionalJavascript/UserPasswordResetTest.php b/core/modules/user/tests/src/FunctionalJavascript/UserPasswordResetTest.php index a8fc7da8b47..394e82442f1 100644 --- a/core/modules/user/tests/src/FunctionalJavascript/UserPasswordResetTest.php +++ b/core/modules/user/tests/src/FunctionalJavascript/UserPasswordResetTest.php @@ -93,7 +93,7 @@ class UserPasswordResetTest extends WebDriverTestBase { $resetURL = $this->getResetURL(); $this->drupalGet($resetURL); - // Login + // Login. $this->submitForm([], 'Log in'); // Generate file. diff --git a/core/modules/user/tests/src/Kernel/Migrate/d6/MigrateUserConfigsTest.php b/core/modules/user/tests/src/Kernel/Migrate/d6/MigrateUserConfigsTest.php index 538a26eabbd..cb34fc2ee84 100644 --- a/core/modules/user/tests/src/Kernel/Migrate/d6/MigrateUserConfigsTest.php +++ b/core/modules/user/tests/src/Kernel/Migrate/d6/MigrateUserConfigsTest.php @@ -59,7 +59,7 @@ class MigrateUserConfigsTest extends MigrateDrupal6TestBase { // Tests migration of user_register using the AccountSettingsForm. - // Map D6 value to D8 value + // Map D6 value to D8 value. $user_register_map = [ [0, UserInterface::REGISTER_ADMINISTRATORS_ONLY], [1, UserInterface::REGISTER_VISITORS], @@ -67,7 +67,7 @@ class MigrateUserConfigsTest extends MigrateDrupal6TestBase { ]; foreach ($user_register_map as $map) { - // Tests migration of user_register = 1 + // Tests migration of "user_register = 1". Database::getConnection('default', 'migrate') ->update('variable') ->fields(['value' => serialize($map[0])]) diff --git a/core/modules/user/tests/src/Kernel/UserDeleteTest.php b/core/modules/user/tests/src/Kernel/UserDeleteTest.php index 148e9f24139..d59e507d19f 100644 --- a/core/modules/user/tests/src/Kernel/UserDeleteTest.php +++ b/core/modules/user/tests/src/Kernel/UserDeleteTest.php @@ -40,7 +40,7 @@ class UserDeleteTest extends KernelTestBase { $uids = [$user_a->id(), $user_b->id(), $user_c->id()]; - // These users should have a role + // These users should have a role. $connection = Database::getConnection(); $query = $connection->select('user__roles', 'r'); $roles_created = $query diff --git a/core/modules/user/tests/src/Kernel/Views/ArgumentValidateTest.php b/core/modules/user/tests/src/Kernel/Views/ArgumentValidateTest.php index ed4049eded3..ab12bb8381c 100644 --- a/core/modules/user/tests/src/Kernel/Views/ArgumentValidateTest.php +++ b/core/modules/user/tests/src/Kernel/Views/ArgumentValidateTest.php @@ -62,7 +62,7 @@ class ArgumentValidateTest extends ViewsKernelTestBase { $this->assertTrue($view->argument['null']->validateArgument($this->account->id())); // Reset argument validation. $view->argument['null']->argument_validated = NULL; - // Fail for a valid numeric, but for a user that doesn't exist + // Fail for a valid numeric, but for a user that doesn't exist. $this->assertFalse($view->argument['null']->validateArgument(32)); $form = []; @@ -82,7 +82,7 @@ class ArgumentValidateTest extends ViewsKernelTestBase { $this->assertTrue($view->argument['null']->validateArgument($this->account->getAccountName())); // Reset argument validation. $view->argument['null']->argument_validated = NULL; - // Fail for a valid string, but for a user that doesn't exist + // Fail for a valid string, but for a user that doesn't exist. $this->assertFalse($view->argument['null']->validateArgument($this->randomMachineName())); } diff --git a/core/modules/user/tests/src/Unit/Views/Argument/RolesRidTest.php b/core/modules/user/tests/src/Unit/Views/Argument/RolesRidTest.php index 53538044b7e..a608dd81732 100644 --- a/core/modules/user/tests/src/Unit/Views/Argument/RolesRidTest.php +++ b/core/modules/user/tests/src/Unit/Views/Argument/RolesRidTest.php @@ -31,7 +31,7 @@ class RolesRidTest extends UnitTestCase { 'label' => 'test <strong>rid 2</strong>', ], 'user_role'); - // Creates a stub entity storage; + // Creates a stub entity storage. $role_storage = $this->createMock('Drupal\Core\Entity\EntityStorageInterface'); $role_storage->expects($this->any()) ->method('loadMultiple') diff --git a/core/modules/user/user.module b/core/modules/user/user.module index b2bb0d9f833..39eb3c9e6e8 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -112,19 +112,6 @@ function user_is_blocked($name) { } /** - * Implements hook_preprocess_HOOK() for block templates. - */ -function user_preprocess_block(&$variables): void { - if ($variables['configuration']['provider'] == 'user') { - switch ($variables['elements']['#plugin_id']) { - case 'user_login_block': - $variables['attributes']['role'] = 'form'; - break; - } - } -} - -/** * Prepares variables for username templates. * * Default template: username.html.twig. diff --git a/core/modules/views/config/schema/views.field.schema.yml b/core/modules/views/config/schema/views.field.schema.yml index 4f47cb6141e..1cddb405f7f 100644 --- a/core/modules/views/config/schema/views.field.schema.yml +++ b/core/modules/views/config/schema/views.field.schema.yml @@ -119,15 +119,6 @@ views.field.numeric: format_plural_string: type: plural_label label: 'Plural variants' - constraints: - Regex: - # Normally, labels cannot contain invisible control characters. In this particular - # case, an invisible character (ASCII 3, 0x03) is used to encode translation - # information, so carve out an exception for that only. - # @see \Drupal\views\Plugin\views\field\NumericField - pattern: '/([^\PC\x03])/u' - match: false - message: 'Labels are not allowed to span multiple lines or contain control characters.' prefix: type: label label: 'Prefix' diff --git a/core/modules/views/src/EventSubscriber/RouteSubscriber.php b/core/modules/views/src/EventSubscriber/RouteSubscriber.php index 6e6ca6e6544..23e4640de98 100644 --- a/core/modules/views/src/EventSubscriber/RouteSubscriber.php +++ b/core/modules/views/src/EventSubscriber/RouteSubscriber.php @@ -76,7 +76,7 @@ class RouteSubscriber extends RouteSubscriberBase { public static function getSubscribedEvents(): array { $events = parent::getSubscribedEvents(); $events[RoutingEvents::FINISHED] = ['routeRebuildFinished']; - // Ensure to run after the entity resolver subscriber + // Ensure to run after the entity resolver subscriber. // @see \Drupal\Core\EventSubscriber\EntityRouteAlterSubscriber $events[RoutingEvents::ALTER] = ['onAlterRoutes', -175]; diff --git a/core/modules/views/src/Form/ViewsExposedForm.php b/core/modules/views/src/Form/ViewsExposedForm.php index 9f90160ff55..e623618c5ae 100644 --- a/core/modules/views/src/Form/ViewsExposedForm.php +++ b/core/modules/views/src/Form/ViewsExposedForm.php @@ -79,7 +79,7 @@ class ViewsExposedForm extends FormBase implements WorkspaceSafeFormInterface { // Let form plugins know this is for exposed widgets. $form_state->set('exposed', TRUE); - // Check if the form was already created + // Check if the form was already created. if ($cache = $this->exposedFormCache->getForm($view->storage->id(), $view->current_display)) { return $cache; } diff --git a/core/modules/views/src/Hook/ViewsHooks.php b/core/modules/views/src/Hook/ViewsHooks.php index 5a7b28735f5..136714de6c9 100644 --- a/core/modules/views/src/Hook/ViewsHooks.php +++ b/core/modules/views/src/Hook/ViewsHooks.php @@ -96,7 +96,7 @@ class ViewsHooks { \Drupal::moduleHandler()->loadInclude('views', 'inc', 'views.theme'); // Some quasi clever array merging here. $base = ['file' => 'views.theme.inc']; - // Our extra version of pager + // Our extra version of pager. $hooks['views_mini_pager'] = $base + [ 'variables' => [ 'tags' => [], @@ -151,7 +151,7 @@ class ViewsHooks { 'parameters' => [], ], ]; - // Default view themes + // Default view themes. $hooks['views_view_field'] = $base + ['variables' => ['view' => NULL, 'field' => NULL, 'row' => NULL]]; $hooks['views_view_grouping'] = $base + [ 'variables' => [ diff --git a/core/modules/views/src/ManyToOneHelper.php b/core/modules/views/src/ManyToOneHelper.php index 56afc646c4b..62b3ead7021 100644 --- a/core/modules/views/src/ManyToOneHelper.php +++ b/core/modules/views/src/ManyToOneHelper.php @@ -92,7 +92,7 @@ class ManyToOneHelper { // need to create a new relationship to use. $relationship = $this->handler->relationship; - // Determine the primary table to seek + // Determine the primary table to seek. if (empty($this->handler->query->relationships[$relationship])) { $base_table = $this->handler->view->storage->get('base_table'); } @@ -140,7 +140,7 @@ class ManyToOneHelper { $field = $this->handler->relationship . '_' . $this->handler->table . '.' . $this->handler->field; $join = $this->getJoin(); - // Shortcuts + // Shortcuts. $options = $this->handler->options; $view = $this->handler->view; $query = $this->handler->query; diff --git a/core/modules/views/src/Plugin/views/HandlerBase.php b/core/modules/views/src/Plugin/views/HandlerBase.php index b3503f44218..7c74d7244c5 100644 --- a/core/modules/views/src/Plugin/views/HandlerBase.php +++ b/core/modules/views/src/Plugin/views/HandlerBase.php @@ -703,7 +703,7 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface { */ public function getJoin() { // Get the join from this table that links back to the base table. - // Determine the primary table to seek + // Determine the primary table to seek. if (empty($this->query->relationships[$this->relationship])) { $base_table = $this->view->storage->get('base_table'); } @@ -878,7 +878,7 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface { */ public function displayExposedForm($form, FormStateInterface $form_state) { $item = &$this->options; - // Flip + // Flip. $item['exposed'] = empty($item['exposed']); // If necessary, set new defaults: @@ -958,7 +958,7 @@ abstract class HandlerBase extends PluginBase implements ViewsHandlerInterface { $form_state->get('rerender', TRUE); $form_state->setRebuild(); - // Write to cache + // Write to cache. $view->cacheSet(); } diff --git a/core/modules/views/src/Plugin/views/area/View.php b/core/modules/views/src/Plugin/views/area/View.php index b15e72c0864..d1949d79a8d 100644 --- a/core/modules/views/src/Plugin/views/area/View.php +++ b/core/modules/views/src/Plugin/views/area/View.php @@ -111,11 +111,11 @@ class View extends AreaPluginBase { } $view->setDisplay($display_id); - // Avoid recursion + // Avoid recursion. $view->parent_views += $this->view->parent_views; $view->parent_views[] = "$view_name:$display_id"; - // Check if the view is part of the parent views of this view + // Check if the view is part of the parent views of this view. $search = "$view_name:$display_id"; if (in_array($search, $this->view->parent_views)) { \Drupal::messenger()->addError($this->t("Recursion detected in view @view display @display.", ['@view' => $view_name, '@display' => $display_id])); diff --git a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php index 1caeead7b39..7746046b6bf 100644 --- a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php +++ b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php @@ -511,7 +511,7 @@ abstract class ArgumentPluginBase extends HandlerBase implements CacheableDepend $plugin->validateOptionsForm($form['argument_default'][$default_id], $form_state, $option_values['argument_default'][$default_id]); } - // Summary plugin + // Summary plugin. $summary_id = $option_values['summary']['format']; $plugin = $this->getPlugin('style', $summary_id); if ($plugin) { @@ -548,7 +548,7 @@ abstract class ArgumentPluginBase extends HandlerBase implements CacheableDepend $option_values['default_argument_options'] = $options; } - // Summary plugin + // Summary plugin. $summary_id = $option_values['summary']['format']; $plugin = $this->getPlugin('style', $summary_id); if ($plugin) { @@ -1000,7 +1000,7 @@ abstract class ArgumentPluginBase extends HandlerBase implements CacheableDepend * code that goes into summaryQuery() */ public function summaryBasics($count_field = TRUE) { - // Add the number of nodes counter + // Add the number of nodes counter. $distinct = ($this->view->display_handler->getOption('distinct') && empty($this->query->no_distinct)); $count_alias = $this->query->addField($this->view->storage->get('base_table'), $this->view->storage->get('base_field'), 'num_records', ['count' => TRUE, 'distinct' => $distinct]); diff --git a/core/modules/views/src/Plugin/views/argument/DayDate.php b/core/modules/views/src/Plugin/views/argument/DayDate.php index a4a94da0699..fa1a1ebfe48 100644 --- a/core/modules/views/src/Plugin/views/argument/DayDate.php +++ b/core/modules/views/src/Plugin/views/argument/DayDate.php @@ -28,7 +28,7 @@ class DayDate extends Date { public function summaryName($data) { $day = str_pad($data->{$this->name_alias}, 2, '0', STR_PAD_LEFT); // strtotime() respects server timezone, so we need to set the time fixed - // as utc time + // as utc time. return $this->dateFormatter->format(strtotime("200505" . $day . " 00:00:00 UTC"), 'custom', $this->format, 'UTC'); } diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php index d3adc61de5a..5c7d9225f0b 100644 --- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php @@ -763,7 +763,7 @@ abstract class DisplayPluginBase extends PluginBase implements DisplayPluginInte return $this->view->displayHandlers->get($display_id)->getRoutedDisplay(); } - // No routed display exists, so return NULL + // No routed display exists, so return NULL. return NULL; } diff --git a/core/modules/views/src/Plugin/views/display/PathPluginBase.php b/core/modules/views/src/Plugin/views/display/PathPluginBase.php index 65eaa6991e4..214b1e1026d 100644 --- a/core/modules/views/src/Plugin/views/display/PathPluginBase.php +++ b/core/modules/views/src/Plugin/views/display/PathPluginBase.php @@ -213,7 +213,7 @@ abstract class PathPluginBase extends DisplayPluginBase implements DisplayRouter // Store whether the view will return a response. $route->setOption('returns_response', !empty($this->getPluginDefinition()['returns_response'])); - // Symfony 4 requires that UTF-8 route patterns have the "utf8" option set + // Symfony 4 requires that UTF-8 route patterns have the "utf8" option set. $route->setOption('utf8', TRUE); return $route; diff --git a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php index ec4808deae9..c6d3e39405a 100644 --- a/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php +++ b/core/modules/views/src/Plugin/views/exposed_form/ExposedFormPluginBase.php @@ -201,7 +201,7 @@ abstract class ExposedFormPluginBase extends PluginBase implements CacheableDepe $form['actions']['submit']['#value'] = $this->options['submit_button']; } - // Check if there is exposed sorts for this view + // Check if there is exposed sorts for this view. $exposed_sorts = []; $exposed_sorts_options = []; foreach ($this->view->sort as $id => $handler) { diff --git a/core/modules/views/src/Plugin/views/field/Custom.php b/core/modules/views/src/Plugin/views/field/Custom.php index 29c840d2790..870983b557a 100644 --- a/core/modules/views/src/Plugin/views/field/Custom.php +++ b/core/modules/views/src/Plugin/views/field/Custom.php @@ -48,7 +48,7 @@ class Custom extends FieldPluginBase { public function buildOptionsForm(&$form, FormStateInterface $form_state) { parent::buildOptionsForm($form, $form_state); - // Remove the checkbox + // Remove the checkbox. unset($form['alter']['alter_text']); unset($form['alter']['text']['#states']); unset($form['alter']['help']['#states']); diff --git a/core/modules/views/src/Plugin/views/field/EntityField.php b/core/modules/views/src/Plugin/views/field/EntityField.php index ad9f935e160..9e1de3ee8e6 100644 --- a/core/modules/views/src/Plugin/views/field/EntityField.php +++ b/core/modules/views/src/Plugin/views/field/EntityField.php @@ -227,7 +227,7 @@ class EntityField extends FieldPluginBase implements CacheableDependencyInterfac $this->limit_values = TRUE; } - // If "First and last only" is chosen, limit the values + // If "First and last only" is chosen, limit the values. if (!empty($this->options['delta_first_last'])) { $this->limit_values = TRUE; } diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php index b60cfbf199d..7fdd3dd024e 100644 --- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php +++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php @@ -193,7 +193,7 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf */ protected function addAdditionalFields($fields = NULL) { if (!isset($fields)) { - // Notice check + // Notice check. if (empty($this->additional_fields)) { return; } @@ -1565,7 +1565,7 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf } $alt = $this->viewsTokenReplace($alter['alt'], $tokens); - // Set the title attribute of the link only if it improves accessibility + // Set the title attribute of the link only if it improves accessibility. if ($alt && $alt != $text) { $options['attributes']['title'] = Html::decodeEntities($alt); } @@ -1630,7 +1630,7 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf $final_url = CoreUrl::fromUri($path, $options); // Build the link based on our altered Url object, adding on the optional - // prefix and suffix + // prefix and suffix. $render = [ '#type' => 'link', '#title' => $text, @@ -1885,7 +1885,7 @@ abstract class FieldPluginBase extends HandlerBase implements FieldHandlerInterf $value = $matches[1]; } } - // Remove scraps of HTML entities from the end of a strings + // Remove scraps of HTML entities from the end of a strings. $value = rtrim(preg_replace('/(?:<(?!.+>)|&(?!.+;)).*$/us', '', $value)); if (!empty($alter['ellipsis'])) { diff --git a/core/modules/views/src/Plugin/views/filter/Combine.php b/core/modules/views/src/Plugin/views/filter/Combine.php index ffb13966844..4ab58875333 100644 --- a/core/modules/views/src/Plugin/views/filter/Combine.php +++ b/core/modules/views/src/Plugin/views/filter/Combine.php @@ -35,7 +35,7 @@ class Combine extends StringFilter { parent::buildOptionsForm($form, $form_state); $this->view->initStyle(); - // Allow to choose all fields as possible + // Allow to choose all fields as possible. if ($this->view->style_plugin->usesFields()) { $options = []; foreach ($this->view->display_handler->getHandlers('field') as $name => $field) { diff --git a/core/modules/views/src/Plugin/views/filter/StringFilter.php b/core/modules/views/src/Plugin/views/filter/StringFilter.php index 233c2067d07..54bf215b8d6 100644 --- a/core/modules/views/src/Plugin/views/filter/StringFilter.php +++ b/core/modules/views/src/Plugin/views/filter/StringFilter.php @@ -389,7 +389,7 @@ class StringFilter extends FilterPluginBase implements FilterOperatorsInterface $operator = $this->getConditionOperator('LIKE'); foreach ($matches as $match) { $phrase = FALSE; - // Strip off phrase quotes + // Strip off phrase quotes. if ($match[2][0] == '"') { $match[2] = substr($match[2], 1, -1); $phrase = TRUE; diff --git a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php index db329710cb7..92b8ee4d1e4 100644 --- a/core/modules/views/src/Plugin/views/join/JoinPluginBase.php +++ b/core/modules/views/src/Plugin/views/join/JoinPluginBase.php @@ -398,7 +398,7 @@ class JoinPluginBase extends PluginBase implements JoinPluginInterface { } // Convert a single-valued array of values to the single-value case, - // and transform from IN() notation to = notation + // and transform from IN() notation to = notation. if (is_array($info['value']) && count($info['value']) == 1) { $info['value'] = array_shift($info['value']); } diff --git a/core/modules/views/src/Plugin/views/query/QueryPluginBase.php b/core/modules/views/src/Plugin/views/query/QueryPluginBase.php index a3dd5d95cb7..597a4ee91a8 100644 --- a/core/modules/views/src/Plugin/views/query/QueryPluginBase.php +++ b/core/modules/views/src/Plugin/views/query/QueryPluginBase.php @@ -190,7 +190,7 @@ abstract class QueryPluginBase extends PluginBase implements CacheableDependency $group = empty($groups) ? 1 : max(array_keys($groups)) + 1; } - // Create an empty group + // Create an empty group. if (empty($groups[$group])) { $groups[$group] = ['conditions' => [], 'args' => []]; } diff --git a/core/modules/views/src/Plugin/views/query/Sql.php b/core/modules/views/src/Plugin/views/query/Sql.php index 815bce2b838..1e9620cecec 100644 --- a/core/modules/views/src/Plugin/views/query/Sql.php +++ b/core/modules/views/src/Plugin/views/query/Sql.php @@ -229,7 +229,7 @@ class Sql extends QueryPluginBase { 'join' => NULL, ]; - // Init the tables with our primary table + // Init the tables with our primary table. $this->tables[$base_table][$base_table] = [ 'count' => 1, 'alias' => $base_table, @@ -625,7 +625,7 @@ class Sql extends QueryPluginBase { * cannot be ensured. */ public function ensureTable($table, $relationship = NULL, ?JoinPluginBase $join = NULL) { - // Ensure a relationship + // Ensure a relationship. if (empty($relationship)) { $relationship = $this->view->storage->get('base_table'); } @@ -782,7 +782,7 @@ class Sql extends QueryPluginBase { } // First, if this is our link point/anchor table, just use the - // relationship + // relationship. if ($join->leftTable == $this->relationships[$relationship]['table']) { $join->leftTable = $relationship; } @@ -882,14 +882,14 @@ class Sql extends QueryPluginBase { $alias = $table . '_' . $field; } - // Make sure an alias is assigned + // Make sure an alias is assigned. $alias = $alias ?: $field; // PostgreSQL truncates aliases to 63 characters: // https://www.drupal.org/node/571548. // We limit the length of the original alias up to 60 characters - // to get a unique alias later if its have duplicates + // to get a unique alias later if its have duplicates. $alias = strtolower(substr($alias, 0, 60)); // Create a field info array. diff --git a/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php b/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php index 14225c3f445..96b6d33d1b2 100644 --- a/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php +++ b/core/modules/views/src/Plugin/views/relationship/GroupwiseMax.php @@ -191,7 +191,7 @@ class GroupwiseMax extends RelationshipPluginBase { // Either load another view, or create one on the fly. if ($options['subquery_view']) { $temp_view = Views::getView($options['subquery_view']); - // Remove all fields from default display + // Remove all fields from default display. unset($temp_view->display['default']['display_options']['fields']); } else { diff --git a/core/modules/views/src/Plugin/views/sort/SortPluginBase.php b/core/modules/views/src/Plugin/views/sort/SortPluginBase.php index 79e537cfd67..9b5acc29d54 100644 --- a/core/modules/views/src/Plugin/views/sort/SortPluginBase.php +++ b/core/modules/views/src/Plugin/views/sort/SortPluginBase.php @@ -100,7 +100,7 @@ abstract class SortPluginBase extends HandlerBase implements CacheableDependency $form['expose_button'] = [ '#prefix' => '<div class="views-expose clearfix">', '#suffix' => '</div>', - // Should always come first + // Should always come first. '#weight' => -1000, ]; diff --git a/core/modules/views/src/Plugin/views/style/StylePluginBase.php b/core/modules/views/src/Plugin/views/style/StylePluginBase.php index ca8df3ba8fe..ffe742452c9 100644 --- a/core/modules/views/src/Plugin/views/style/StylePluginBase.php +++ b/core/modules/views/src/Plugin/views/style/StylePluginBase.php @@ -575,7 +575,7 @@ abstract class StylePluginBase extends PluginBase { $groupings = [['field' => $groupings, 'rendered' => $rendered]]; } - // Make sure fields are rendered + // Make sure fields are rendered. $this->renderFields($this->view->result); $sets = []; if ($groupings) { @@ -710,7 +710,7 @@ abstract class StylePluginBase extends PluginBase { // - HTML views are rendered inside a render context: then we want to // use ::render(), so that attachments and cacheability are bubbled. // - non-HTML views are rendered outside a render context: then we - // want to use ::renderInIsolation(), so that no bubbling happens + // want to use ::renderInIsolation(), so that no bubbling happens. if ($renderer->hasRenderContext()) { $renderer->render($data); } diff --git a/core/modules/views/src/Plugin/views/style/Table.php b/core/modules/views/src/Plugin/views/style/Table.php index 561628ac682..d14e433c2f3 100644 --- a/core/modules/views/src/Plugin/views/style/Table.php +++ b/core/modules/views/src/Plugin/views/style/Table.php @@ -191,7 +191,7 @@ class Table extends StylePluginBase implements CacheableDependencyInterface { } // If the field is the column, mark it so, or the column - // it's set to is a column, that's ok + // it's set to is a column, that's ok. if ($field == $column || $columns[$column] == $column && !empty($sanitized[$column])) { $sanitized[$field] = $column; } @@ -332,7 +332,7 @@ class Table extends StylePluginBase implements CacheableDependencyInterface { '#return_value' => $field, '#parents' => ['style_options', 'default'], '#id' => $radio_id, - // Because 'radio' doesn't fully support '#id' =( + // Because 'radio' doesn't fully support "'#id' =(". '#attributes' => ['id' => $radio_id], '#default_value' => $default, '#states' => [ @@ -395,13 +395,13 @@ class Table extends StylePluginBase implements CacheableDependencyInterface { ], ]; - // Markup for the field name + // Markup for the field name. $form['info'][$field]['name'] = [ '#markup' => $field_names[$field], ]; } - // Provide a radio for no default sort + // Provide a radio for no default sort. $form['default'][-1] = [ '#title' => $this->t('No default sort'), '#title_display' => 'invisible', diff --git a/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php b/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php index d53e93cecec..802c73144e6 100644 --- a/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php +++ b/core/modules/views/src/Plugin/views/wizard/WizardPluginBase.php @@ -722,7 +722,7 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface { * arrays of options for that display. */ protected function buildDisplayOptions($form, FormStateInterface $form_state) { - // Display: Default + // Display: Default. $display_options['default'] = $this->defaultDisplayOptions(); $display_options['default'] += [ 'filters' => [], @@ -731,17 +731,17 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface { $display_options['default']['filters'] += $this->defaultDisplayFilters($form, $form_state); $display_options['default']['sorts'] += $this->defaultDisplaySorts($form, $form_state); - // Display: Page + // Display: Page. if (!$form_state->isValueEmpty(['page', 'create'])) { $display_options['page'] = $this->pageDisplayOptions($form, $form_state); - // Display: Feed (attached to the page) + // Display: Feed (attached to the page). if (!$form_state->isValueEmpty(['page', 'feed'])) { $display_options['feed'] = $this->pageFeedDisplayOptions($form, $form_state); } } - // Display: Block + // Display: Block. if (!$form_state->isValueEmpty(['block', 'create'])) { $display_options['block'] = $this->blockDisplayOptions($form, $form_state); } @@ -773,13 +773,13 @@ abstract class WizardPluginBase extends PluginBase implements WizardInterface { // instances. $executable = $view->getExecutable(); - // Display: Default + // Display: Default. $default_display = $executable->newDisplay('default', 'Default', 'default'); foreach ($display_options['default'] as $option => $value) { $default_display->setOption($option, $value); } - // Display: Page + // Display: Page. if (isset($display_options['page'])) { $display = $executable->newDisplay('page', 'Page', 'page_1'); // The page display is usually the main one (from the user's point of diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php index 407260ed285..554c38cdaba 100644 --- a/core/modules/views/src/ViewExecutable.php +++ b/core/modules/views/src/ViewExecutable.php @@ -157,7 +157,7 @@ class ViewExecutable { // phpcs:ignore Drupal.NamingConventions.ValidVariableName.LowerCamelName, Drupal.Commenting.VariableComment.Missing public $feedIcons = []; - // Exposed widget input + // Exposed widget input. /** * All the form data from $form_state->getValues(). @@ -1177,7 +1177,7 @@ class ViewExecutable { // use whatever value the argument handler now has, not the raw value. $substitutions["{{ raw_arguments.$id }}"] = strip_tags(Html::decodeEntities($argument->getValue())); - // Test to see if we should use this argument's title + // Test to see if we should use this argument's title. if (!empty($argument->options['title_enable']) && !empty($argument->options['title'])) { $title = $argument->options['title']; } @@ -1385,7 +1385,7 @@ class ViewExecutable { $this->built = TRUE; $this->build_time = microtime(TRUE) - $start; - // Attach displays + // Attach displays. $this->attachDisplays(); // Let modules modify the view just after building it. @@ -1688,7 +1688,7 @@ class ViewExecutable { $this->preExecute($args); - // Execute the view + // Execute the view. $output = $this->display_handler->execute(); $this->postExecute(); @@ -1750,7 +1750,7 @@ class ViewExecutable { // Allow hook_views_pre_view() to set the dom_id, then ensure it is set. $this->dom_id = !empty($this->dom_id) ? $this->dom_id : hash('sha256', $this->storage->id() . \Drupal::time()->getRequestTime() . mt_rand()); - // Allow the display handler to set up for execution + // Allow the display handler to set up for execution. $this->display_handler->preExecute(); } @@ -2336,10 +2336,10 @@ class ViewExecutable { public function getHandler($display_id, $type, $id) { // Get info about the types so we can get the right data. $types = static::getHandlerTypes(); - // Initialize the display + // Initialize the display. $this->setDisplay($display_id); - // Get the existing configuration + // Get the existing configuration. $fields = $this->displayHandlers->get($display_id)->getOption($types[$type]['plural']); return $fields[$id] ?? NULL; diff --git a/core/modules/views/src/Views.php b/core/modules/views/src/Views.php index 87a2bc2f5d8..46393b68e0c 100644 --- a/core/modules/views/src/Views.php +++ b/core/modules/views/src/Views.php @@ -436,13 +436,13 @@ class Views { if (!isset(static::$handlerTypes)) { static::$handlerTypes = [ 'field' => [ - // Title + // Title. 'title' => static::t('Fields'), // Lowercase title for mid-sentence. 'ltitle' => static::t('fields'), // Singular title. 'stitle' => static::t('Field'), - // Singular lowercase title for mid sentence + // Singular lowercase title for mid sentence. 'lstitle' => static::t('field'), 'plural' => 'fields', ], diff --git a/core/modules/views/src/ViewsDataHelper.php b/core/modules/views/src/ViewsDataHelper.php index a784843d018..2311ab90aa0 100644 --- a/core/modules/views/src/ViewsDataHelper.php +++ b/core/modules/views/src/ViewsDataHelper.php @@ -67,7 +67,7 @@ class ViewsDataHelper { $strings = []; $skip_bases = []; foreach ($table_data as $field => $info) { - // Collect table data from this table + // Collect table data from this table. if ($field == 'table') { // Calculate what tables this table can join to. if (!empty($info['join'])) { @@ -96,15 +96,15 @@ class ViewsDataHelper { } } foreach (['title', 'group', 'help', 'base', 'aliases'] as $string) { - // First, try the lowest possible level + // First, try the lowest possible level. if (!empty($info[$key][$string])) { $strings[$field][$key][$string] = $info[$key][$string]; } - // Then try the field level + // Then try the field level. elseif (!empty($info[$string])) { $strings[$field][$key][$string] = $info[$string]; } - // Finally, try the table level + // Finally, try the table level. elseif (!empty($table_data['table'][$string])) { $strings[$field][$key][$string] = $table_data['table'][$string]; } diff --git a/core/modules/views/tests/modules/views_test_data/src/Hook/ViewsTestDataThemeHooks.php b/core/modules/views/tests/modules/views_test_data/src/Hook/ViewsTestDataThemeHooks.php new file mode 100644 index 00000000000..c03ad9ba030 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_data/src/Hook/ViewsTestDataThemeHooks.php @@ -0,0 +1,26 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\views_test_data\Hook; + +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for views_test_data. + */ +class ViewsTestDataThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for views table templates. + */ + #[Hook('preprocess_views_view_table')] + public function preprocessViewsViewTable(&$variables): void { + if ($variables['view']->storage->id() == 'test_view_render') { + $views_render_test = \Drupal::state()->get('views_render.test'); + $views_render_test++; + \Drupal::state()->set('views_render.test', $views_render_test); + } + } + +} diff --git a/core/modules/views/tests/modules/views_test_data/src/Plugin/views/query/QueryTest.php b/core/modules/views/tests/modules/views_test_data/src/Plugin/views/query/QueryTest.php index 0d1e494c705..9a35a3ca8b2 100644 --- a/core/modules/views/tests/modules/views_test_data/src/Plugin/views/query/QueryTest.php +++ b/core/modules/views/tests/modules/views_test_data/src/Plugin/views/query/QueryTest.php @@ -145,7 +145,7 @@ class QueryTest extends QueryPluginBase { } if ($match) { // If the query explicit defines fields to use, filter all others out. - // Filter out fields + // Filter out fields. if ($this->fields) { $element = array_intersect_key($element, $this->fields); } diff --git a/core/modules/views/tests/modules/views_test_data/views_test_data.module b/core/modules/views/tests/modules/views_test_data/views_test_data.module index 421dff3e88d..75259026c3d 100644 --- a/core/modules/views/tests/modules/views_test_data/views_test_data.module +++ b/core/modules/views/tests/modules/views_test_data/views_test_data.module @@ -44,17 +44,6 @@ function views_test_data_handler_test_access_callback_argument($argument = FALSE } /** - * Implements hook_preprocess_HOOK() for views table templates. - */ -function views_test_data_preprocess_views_view_table(&$variables): void { - if ($variables['view']->storage->id() == 'test_view_render') { - $views_render_test = \Drupal::state()->get('views_render.test'); - $views_render_test++; - \Drupal::state()->set('views_render.test', $views_render_test); - } -} - -/** * Prepares variables for the mapping row style test templates. * * Default template: views-view-mapping-test.html.twig. diff --git a/core/modules/views/tests/modules/views_test_rss/src/Hook/ViewsTestRssThemeHooks.php b/core/modules/views/tests/modules/views_test_rss/src/Hook/ViewsTestRssThemeHooks.php new file mode 100644 index 00000000000..1fe64d6aa8a --- /dev/null +++ b/core/modules/views/tests/modules/views_test_rss/src/Hook/ViewsTestRssThemeHooks.php @@ -0,0 +1,28 @@ +<?php + +declare(strict_types=1); + +namespace Drupal\views_test_rss\Hook; + +use Drupal\Core\Hook\Attribute\Hook; +use Drupal\Core\StringTranslation\StringTranslationTrait; + +/** + * Hook implementations for views_test_rss. + */ +class ViewsTestRssThemeHooks { + use StringTranslationTrait; + + /** + * Implements hook_preprocess_HOOK(). + */ + #[Hook('preprocess_views_view_rss')] + public function preprocessViewsViewRss(&$variables): void { + $variables['channel_elements'][] = [ + '#type' => 'html_tag', + '#tag' => 'copyright', + '#value' => $this->t('Copyright 2019 Dries Buytaert'), + ]; + } + +} diff --git a/core/modules/views/tests/modules/views_test_rss/views_test_rss.module b/core/modules/views/tests/modules/views_test_rss/views_test_rss.module deleted file mode 100644 index 1b0dda574c4..00000000000 --- a/core/modules/views/tests/modules/views_test_rss/views_test_rss.module +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -/** - * @file - * Hook implementations for this module. - */ - -declare(strict_types=1); - -/** - * Implements hook_preprocess_HOOK(). - */ -function views_test_rss_preprocess_views_view_rss(&$variables): void { - $variables['channel_elements'][] = [ - '#type' => 'html_tag', - '#tag' => 'copyright', - '#value' => t('Copyright 2019 Dries Buytaert'), - ]; -} diff --git a/core/modules/views/tests/src/Functional/GlossaryTest.php b/core/modules/views/tests/src/Functional/GlossaryTest.php index 25c08d5f159..317eda212e9 100644 --- a/core/modules/views/tests/src/Functional/GlossaryTest.php +++ b/core/modules/views/tests/src/Functional/GlossaryTest.php @@ -57,7 +57,7 @@ class GlossaryTest extends ViewTestBase { } } - // Execute glossary view + // Execute glossary view. $view = Views::getView('glossary'); $view->setDisplay('attachment_1'); $view->executeDisplay('attachment_1'); @@ -86,7 +86,7 @@ class GlossaryTest extends ViewTestBase { ], [ 'config:views.view.glossary', - // Listed for letter 'a' + // Listed for letter 'a'. 'node:' . $nodes_by_char['a'][0]->id(), 'node:' . $nodes_by_char['a'][1]->id(), 'node:' . $nodes_by_char['a'][2]->id(), // Link for letter 'd'. 'node:1', diff --git a/core/modules/views/tests/src/Functional/Handler/HandlerTest.php b/core/modules/views/tests/src/Functional/Handler/HandlerTest.php index fa9af239ca3..b76b92a5b26 100644 --- a/core/modules/views/tests/src/Functional/Handler/HandlerTest.php +++ b/core/modules/views/tests/src/Functional/Handler/HandlerTest.php @@ -80,7 +80,7 @@ class HandlerTest extends ViewTestBase { // Check defaults. $this->assertEquals((object) ['value' => [], 'operator' => NULL], HandlerBase::breakString('')); - // Test ors + // Test ors. $handler = HandlerBase::breakString('word1 word2+word'); $this->assertEquals(['word1', 'word2', 'word'], $handler->value); $this->assertEquals('or', $handler->operator); @@ -114,13 +114,13 @@ class HandlerTest extends ViewTestBase { $this->assertEquals(['wõrd1', 'wõrd2', 'wõrd'], $handler->value); $this->assertEquals('and', $handler->operator); - // Test a single word + // Test a single word. $handler = HandlerBase::breakString('word'); $this->assertEquals(['word'], $handler->value); $this->assertEquals('and', $handler->operator); $s1 = $this->randomMachineName(); - // Generate three random numbers which can be used below; + // Generate three random numbers which can be used below. $n1 = rand(0, 100); $n2 = rand(0, 100); $n3 = rand(0, 100); @@ -168,7 +168,7 @@ class HandlerTest extends ViewTestBase { $this->assertEquals([(int) $s1, $n2, $n3], $handlerBase->value); $this->assertEquals('or', $handlerBase->operator); - // Generate three random decimals which can be used below; + // Generate three random decimals which can be used below. $d1 = rand(0, 10) / 10; $d2 = rand(0, 10) / 10; $d3 = rand(0, 10) / 10; diff --git a/core/modules/views/tests/src/Functional/Plugin/ArgumentDefaultTest.php b/core/modules/views/tests/src/Functional/Plugin/ArgumentDefaultTest.php index ebc7092dafb..cda2b3537bb 100644 --- a/core/modules/views/tests/src/Functional/Plugin/ArgumentDefaultTest.php +++ b/core/modules/views/tests/src/Functional/Plugin/ArgumentDefaultTest.php @@ -127,7 +127,7 @@ class ArgumentDefaultTest extends ViewTestBase { $this->assertEquals($random, $view->argument['null']->getDefaultArgument(), 'Fixed argument should be used by default.'); - // Make sure that a normal argument provided is used + // Make sure that a normal argument provided is used. $random_string = $this->randomMachineName(); $view->executeDisplay('default', [$random_string]); diff --git a/core/modules/views/tests/src/Functional/Plugin/DisplayTest.php b/core/modules/views/tests/src/Functional/Plugin/DisplayTest.php index 5aecbea3e36..f3a824e48c6 100644 --- a/core/modules/views/tests/src/Functional/Plugin/DisplayTest.php +++ b/core/modules/views/tests/src/Functional/Plugin/DisplayTest.php @@ -392,7 +392,7 @@ class DisplayTest extends ViewTestBase { // Remove the relationship used by other handlers. $view->removeHandler('default', 'relationship', 'uid'); - // Validate display + // Validate display. $errors = $view->validate(); // Check that the error messages are shown. $this->assertCount(2, $errors['default'], 'Error messages found for required relationship'); diff --git a/core/modules/views/tests/src/Functional/Plugin/MiniPagerTest.php b/core/modules/views/tests/src/Functional/Plugin/MiniPagerTest.php index 8852c9e7be4..d81ddc46562 100644 --- a/core/modules/views/tests/src/Functional/Plugin/MiniPagerTest.php +++ b/core/modules/views/tests/src/Functional/Plugin/MiniPagerTest.php @@ -84,7 +84,7 @@ class MiniPagerTest extends ViewTestBase { $this->assertSession()->pageTextContains($this->nodes[18]->label()); $this->assertSession()->pageTextContains($this->nodes[19]->label()); - // Test @total value in result summary + // Test @total value in result summary. $view = Views::getView('test_mini_pager'); $view->setDisplay('page_4'); $this->executeView($view); diff --git a/core/modules/views/tests/src/Functional/Plugin/PagerTest.php b/core/modules/views/tests/src/Functional/Plugin/PagerTest.php index cf381282443..b981440107c 100644 --- a/core/modules/views/tests/src/Functional/Plugin/PagerTest.php +++ b/core/modules/views/tests/src/Functional/Plugin/PagerTest.php @@ -334,7 +334,7 @@ class PagerTest extends ViewTestBase { $this->executeView($view); $this->assertCount(3, $view->result, 'Make sure that only a certain count of items is returned'); - // Test items per page = 0 + // Test items per page = 0. $view = Views::getView('test_view_pager_full_zero_items_per_page'); $this->executeView($view); diff --git a/core/modules/views/tests/src/Kernel/BasicTest.php b/core/modules/views/tests/src/Kernel/BasicTest.php index ba766c1e72c..dd0f5e452fc 100644 --- a/core/modules/views/tests/src/Kernel/BasicTest.php +++ b/core/modules/views/tests/src/Kernel/BasicTest.php @@ -101,7 +101,7 @@ class BasicTest extends ViewsKernelTestBase { * Tests simple argument. */ public function testSimpleArgument(): void { - // Execute with a view + // Execute with a view. $view = Views::getView('test_simple_argument'); $view->setArguments([27]); $this->executeView($view); diff --git a/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php b/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php index b53d7314047..0d62a0186ae 100644 --- a/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php +++ b/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php @@ -123,7 +123,7 @@ class EntityViewsDataTest extends KernelTestBase { ->setTranslatable(TRUE) ->setSetting('max_length', 255); - // A base field with cardinality > 1 + // A base field with cardinality > 1. $this->commonBaseFields['string'] = BaseFieldDefinition::create('string') ->setLabel('Strong') ->setTranslatable(TRUE) diff --git a/core/modules/views/tests/src/Kernel/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php b/core/modules/views/tests/src/Kernel/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php index a3bcc66be58..cc839de62cd 100644 --- a/core/modules/views/tests/src/Kernel/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php +++ b/core/modules/views/tests/src/Kernel/EventSubscriber/ViewsEntitySchemaSubscriberIntegrationTest.php @@ -332,9 +332,9 @@ class ViewsEntitySchemaSubscriberIntegrationTest extends ViewsKernelTestBase { // base + translation <-> base + translation + revision // base + revision <-> base + translation + revision // base <-> base + revision - // base <-> base + translation + revision + // base <-> base + translation + revision. - // Base <-> base + translation + // Base <-> base + translation. $this->updateEntityTypeToTranslatable(TRUE); [$view, $display] = $this->getUpdatedViewAndDisplay(); @@ -351,7 +351,7 @@ class ViewsEntitySchemaSubscriberIntegrationTest extends ViewsKernelTestBase { $this->resetEntityType(); - // Base + translation <-> base + translation + revision + // Base + translation <-> base + translation + revision. $this->updateEntityTypeToTranslatable(TRUE); [$view, $display] = $this->getUpdatedViewAndDisplay(); @@ -375,7 +375,7 @@ class ViewsEntitySchemaSubscriberIntegrationTest extends ViewsKernelTestBase { $this->resetEntityType(); - // Base + revision <-> base + translation + revision + // Base + revision <-> base + translation + revision. $this->updateEntityTypeToRevisionable(); [$view, $display] = $this->getUpdatedViewAndDisplay(); @@ -399,7 +399,7 @@ class ViewsEntitySchemaSubscriberIntegrationTest extends ViewsKernelTestBase { $this->resetEntityType(); - // Base <-> base + revision + // Base <-> base + revision. $this->updateEntityTypeToRevisionable(TRUE); [$view, $display] = $this->getUpdatedViewAndDisplay(); @@ -416,7 +416,7 @@ class ViewsEntitySchemaSubscriberIntegrationTest extends ViewsKernelTestBase { $this->resetEntityType(); - // Base <-> base + translation + revision + // Base <-> base + translation + revision. $this->updateEntityTypeToRevisionable(TRUE); $this->updateEntityTypeToTranslatable(TRUE); [$view, $display] = $this->getUpdatedViewAndDisplay(); @@ -445,7 +445,7 @@ class ViewsEntitySchemaSubscriberIntegrationTest extends ViewsKernelTestBase { * Tests some possible entity table updates for a revision view. */ public function testVariousTableUpdatesForRevisionView(): void { - // Base + revision <-> base + translation + revision + // Base + revision <-> base + translation + revision. $this->updateEntityTypeToRevisionable(TRUE); [$view, $display] = $this->getUpdatedViewAndDisplay(TRUE); diff --git a/core/modules/views/tests/src/Kernel/Handler/AreaTextTest.php b/core/modules/views/tests/src/Kernel/Handler/AreaTextTest.php index a96bb66e652..e8da8768519 100644 --- a/core/modules/views/tests/src/Kernel/Handler/AreaTextTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/AreaTextTest.php @@ -46,7 +46,7 @@ class AreaTextTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Add a text header + // Add a text header. $string = $this->randomMachineName(); $view->displayHandlers->get('default')->overrideOption('header', [ 'area' => [ diff --git a/core/modules/views/tests/src/Kernel/Handler/ArgumentNullTest.php b/core/modules/views/tests/src/Kernel/Handler/ArgumentNullTest.php index f48cbf89b40..9d2c8111146 100644 --- a/core/modules/views/tests/src/Kernel/Handler/ArgumentNullTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/ArgumentNullTest.php @@ -35,7 +35,7 @@ class ArgumentNullTest extends ViewsKernelTestBase { * Tests the NullArgument handler for text areas. */ public function testAreaText(): void { - // Test validation + // Test validation. $view = Views::getView('test_view'); $view->setDisplay(); diff --git a/core/modules/views/tests/src/Kernel/Handler/FieldBooleanTest.php b/core/modules/views/tests/src/Kernel/Handler/FieldBooleanTest.php index 2d1c79b71c3..cc3d66716d1 100644 --- a/core/modules/views/tests/src/Kernel/Handler/FieldBooleanTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/FieldBooleanTest.php @@ -25,7 +25,7 @@ class FieldBooleanTest extends ViewsKernelTestBase { * Modifies the default dataset by removing the age for specific entries. */ public function dataSet() { - // Use default dataset but remove the age from john and paul + // Use default dataset but remove the age from john and paul. $data = parent::dataSet(); $data[0]['age'] = 0; $data[3]['age'] = 0; diff --git a/core/modules/views/tests/src/Kernel/Handler/FieldKernelTest.php b/core/modules/views/tests/src/Kernel/Handler/FieldKernelTest.php index b8a0d79bee5..5aaf400fb0f 100644 --- a/core/modules/views/tests/src/Kernel/Handler/FieldKernelTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/FieldKernelTest.php @@ -808,7 +808,7 @@ class FieldKernelTest extends ViewsKernelTestBase { $this->assertEquals($expect[$key], $result_text); } - // Test also word_boundary + // Test also word_boundary. $alter['word_boundary'] = TRUE; $expect = [ 'Tuy nhiên', diff --git a/core/modules/views/tests/src/Kernel/Handler/FilterEqualityTest.php b/core/modules/views/tests/src/Kernel/Handler/FilterEqualityTest.php index aeb4d145c1e..fe00082e063 100644 --- a/core/modules/views/tests/src/Kernel/Handler/FilterEqualityTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/FilterEqualityTest.php @@ -51,7 +51,7 @@ class FilterEqualityTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'name' => [ 'id' => 'name', @@ -80,7 +80,7 @@ class FilterEqualityTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->newDisplay('page', 'Page', 'page_1'); - // Filter: Name, Operator: =, Value: Ringo + // Filter: Name, Operator: =, Value: Ringo. $filters['name']['group_info']['default_group'] = 1; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -102,7 +102,7 @@ class FilterEqualityTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'name' => [ 'id' => 'name', @@ -140,7 +140,7 @@ class FilterEqualityTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->newDisplay('page', 'Page', 'page_1'); - // Filter: Name, Operator: !=, Value: Ringo + // Filter: Name, Operator: !=, Value: Ringo. $filters['name']['group_info']['default_group'] = 2; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); diff --git a/core/modules/views/tests/src/Kernel/Handler/FilterInOperatorTest.php b/core/modules/views/tests/src/Kernel/Handler/FilterInOperatorTest.php index e812d2fd417..2bfbfcd63b2 100644 --- a/core/modules/views/tests/src/Kernel/Handler/FilterInOperatorTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/FilterInOperatorTest.php @@ -126,7 +126,7 @@ class FilterInOperatorTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = Views::getView('test_view'); - // Filter: Age, Operator: in, Value: 26, 30 + // Filter: Age, Operator: in, Value: 26, 30. $filters['age']['group_info']['default_group'] = 1; $view->setDisplay(); $view->displayHandlers->get('default')->overrideOption('filters', $filters); @@ -155,7 +155,7 @@ class FilterInOperatorTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = Views::getView('test_view'); - // Filter: Age, Operator: in, Value: 26, 30 + // Filter: Age, Operator: in, Value: 26, 30. $filters['age']['group_info']['default_group'] = 2; $view->setDisplay(); $view->displayHandlers->get('default')->overrideOption('filters', $filters); diff --git a/core/modules/views/tests/src/Kernel/Handler/FilterNumericTest.php b/core/modules/views/tests/src/Kernel/Handler/FilterNumericTest.php index b0a355f8dbd..3e049815fc7 100644 --- a/core/modules/views/tests/src/Kernel/Handler/FilterNumericTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/FilterNumericTest.php @@ -55,7 +55,7 @@ class FilterNumericTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'age' => [ 'id' => 'age', @@ -85,7 +85,7 @@ class FilterNumericTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->newDisplay('page', 'Page', 'page_1'); - // Filter: Age, Operator: =, Value: 28 + // Filter: Age, Operator: =, Value: 28. $filters['age']['group_info']['default_group'] = 1; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -212,7 +212,7 @@ class FilterNumericTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->newDisplay('page', 'Page', 'page_1'); - // Filter: Age, Operator: between, Value: 26 and 29 + // Filter: Age, Operator: between, Value: 26 and 29. $filters['age']['group_info']['default_group'] = 2; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -244,7 +244,7 @@ class FilterNumericTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->newDisplay('page', 'Page', 'page_1'); - // Filter: Age, Operator: between, Value: 26 and 29 + // Filter: Age, Operator: between, Value: 26 and 29. $filters['age']['group_info']['default_group'] = 3; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -348,7 +348,7 @@ class FilterNumericTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->newDisplay('page', 'Page', 'page_1'); - // Filter: Age, Operator: regular_expression, Value: 2[7-8] + // Filter: Age, Operator: regular_expression, Value: 2[7-8]. $filters['age']['group_info']['default_group'] = 6; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -379,7 +379,7 @@ class FilterNumericTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->newDisplay('page', 'Page', 'page_1'); - // Filter: Age, Operator: not_regular_expression, Value: 2[7-8] + // Filter: Age, Operator: not_regular_expression, Value: 2[7-8]. $filters['age']['group_info']['default_group'] = 7; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -410,7 +410,7 @@ class FilterNumericTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'age' => [ 'id' => 'age', @@ -428,7 +428,7 @@ class FilterNumericTest extends ViewsKernelTestBase { $view->destroy(); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'age' => [ 'id' => 'age', diff --git a/core/modules/views/tests/src/Kernel/Handler/FilterStringTest.php b/core/modules/views/tests/src/Kernel/Handler/FilterStringTest.php index 96d7f91c6fc..43434d16743 100644 --- a/core/modules/views/tests/src/Kernel/Handler/FilterStringTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/FilterStringTest.php @@ -102,7 +102,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'name' => [ 'id' => 'name', @@ -123,7 +123,7 @@ class FilterStringTest extends ViewsKernelTestBase { $this->assertIdenticalResultset($view, $resultset, $this->columnMap); $view->destroy(); - // Get the original dataset + // Get the original dataset. $data_set = $this->dataSet(); // Adds a new data point in the views_test_data table. $query = Database::getConnection()->insert('views_test_data') @@ -141,7 +141,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'name' => [ 'id' => 'name', @@ -169,7 +169,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Name, Operator: =, Value: Ringo + // Filter: Name, Operator: =, Value: Ringo. $filters['name']['group_info']['default_group'] = 1; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -193,7 +193,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'name' => [ 'id' => 'name', @@ -230,7 +230,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Name, Operator: !=, Value: Ringo + // Filter: Name, Operator: !=, Value: Ringo. $filters['name']['group_info']['default_group'] = '2'; $view->setDisplay('page_1'); @@ -264,7 +264,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'name' => [ 'id' => 'name', @@ -292,7 +292,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Name, Operator: contains, Value: ing + // Filter: Name, Operator: contains, Value: ing. $filters['name']['group_info']['default_group'] = '3'; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -316,7 +316,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'description' => [ 'id' => 'description', @@ -343,7 +343,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'description' => [ 'id' => 'description', @@ -407,7 +407,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Name, Operator: contains, Value: ing + // Filter: Name, Operator: contains, Value: ing. $filters['name']['group_info']['default_group'] = '3'; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -427,7 +427,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Description, Operator: contains, Value: actor + // Filter: Description, Operator: contains, Value: actor. $filters['description']['group_info']['default_group'] = '1'; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -451,7 +451,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'description' => [ 'id' => 'description', @@ -479,7 +479,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Name, Operator: starts, Value: George + // Filter: Name, Operator: starts, Value: George. $filters['description']['group_info']['default_group'] = 2; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -502,7 +502,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Name, Operator: not_regular_expression, Value: ^Rin + // Filter: Name, Operator: not_regular_expression, Value: ^Rin. $filters['name']['group_info']['default_group'] = 6; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -535,7 +535,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'description' => [ 'id' => 'description', @@ -558,7 +558,7 @@ class FilterStringTest extends ViewsKernelTestBase { [ 'name' => 'Paul', ], - // There is no Meredith returned because their description is empty + // There is no Meredith returned because their description is empty. ]; $this->assertIdenticalResultset($view, $resultset, $this->columnMap); } @@ -570,7 +570,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Name, Operator: not_starts, Value: George + // Filter: Name, Operator: not_starts, Value: George. $filters['description']['group_info']['default_group'] = 3; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -588,7 +588,7 @@ class FilterStringTest extends ViewsKernelTestBase { [ 'name' => 'Paul', ], - // There is no Meredith returned because their description is empty + // There is no Meredith returned because their description is empty. ]; $this->assertIdenticalResultset($view, $resultset, $this->columnMap); } @@ -600,7 +600,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'description' => [ 'id' => 'description', @@ -631,7 +631,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Description, Operator: ends, Value: Beatles + // Filter: Description, Operator: ends, Value: Beatles. $filters['description']['group_info']['default_group'] = 4; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -657,7 +657,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'description' => [ 'id' => 'description', @@ -677,7 +677,7 @@ class FilterStringTest extends ViewsKernelTestBase { [ 'name' => 'Paul', ], - // There is no Meredith returned because their description is empty + // There is no Meredith returned because their description is empty. ]; $this->assertIdenticalResultset($view, $resultset, $this->columnMap); } @@ -689,7 +689,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Description, Operator: not_ends, Value: Beatles + // Filter: Description, Operator: not_ends, Value: Beatles. $filters['description']['group_info']['default_group'] = 5; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -704,7 +704,7 @@ class FilterStringTest extends ViewsKernelTestBase { [ 'name' => 'Paul', ], - // There is no Meredith returned because their description is empty + // There is no Meredith returned because their description is empty. ]; $this->assertIdenticalResultset($view, $resultset, $this->columnMap); } @@ -716,7 +716,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'description' => [ 'id' => 'description', @@ -736,7 +736,7 @@ class FilterStringTest extends ViewsKernelTestBase { [ 'name' => 'Paul', ], - // There is no Meredith returned because their description is empty + // There is no Meredith returned because their description is empty. ]; $this->assertIdenticalResultset($view, $resultset, $this->columnMap); } @@ -748,7 +748,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Description, Operator: not (does not contains), Value: Beatles + // Filter: Description, Operator: not (does not contains), Value: Beatles. $filters['description']['group_info']['default_group'] = 6; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -763,7 +763,7 @@ class FilterStringTest extends ViewsKernelTestBase { [ 'name' => 'Paul', ], - // There is no Meredith returned because their description is empty + // There is no Meredith returned because their description is empty. ]; $this->assertIdenticalResultset($view, $resultset, $this->columnMap); @@ -776,7 +776,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'name' => [ 'id' => 'name', @@ -807,7 +807,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Name, Operator: shorterthan, Value: 5 + // Filter: Name, Operator: shorterthan, Value: 5. $filters['name']['group_info']['default_group'] = 4; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -832,7 +832,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'name' => [ 'id' => 'name', @@ -860,7 +860,7 @@ class FilterStringTest extends ViewsKernelTestBase { $filters = $this->getGroupedExposedFilters(); $view = $this->getBasicPageView(); - // Filter: Name, Operator: longerthan, Value: 4 + // Filter: Name, Operator: longerthan, Value: 4. $filters['name']['group_info']['default_group'] = 5; $view->setDisplay('page_1'); $view->displayHandlers->get('page_1')->overrideOption('filters', $filters); @@ -882,7 +882,7 @@ class FilterStringTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering + // Change the filtering. $view->displayHandlers->get('default')->overrideOption('filters', [ 'description' => [ 'id' => 'description', diff --git a/core/modules/views/tests/src/Kernel/Handler/SortDateTest.php b/core/modules/views/tests/src/Kernel/Handler/SortDateTest.php index a1d72775a75..e6f65f2bc5f 100644 --- a/core/modules/views/tests/src/Kernel/Handler/SortDateTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/SortDateTest.php @@ -201,7 +201,7 @@ class SortDateTest extends ViewsKernelTestBase { ], ]); - // Change the ordering + // Change the ordering. $view->displayHandlers->get('default')->overrideOption('sorts', [ 'created' => [ 'id' => 'created', diff --git a/core/modules/views/tests/src/Kernel/Handler/SortTest.php b/core/modules/views/tests/src/Kernel/Handler/SortTest.php index a27e46ebac5..444ed8c7ce5 100644 --- a/core/modules/views/tests/src/Kernel/Handler/SortTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/SortTest.php @@ -28,7 +28,7 @@ class SortTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the ordering + // Change the ordering. $view->displayHandlers->get('default')->overrideOption('sorts', [ 'age' => [ 'order' => 'ASC', @@ -52,7 +52,7 @@ class SortTest extends ViewsKernelTestBase { $view->destroy(); $view->setDisplay(); - // Reverse the ordering + // Reverse the ordering. $view->displayHandlers->get('default')->overrideOption('sorts', [ 'age' => [ 'order' => 'DESC', @@ -81,7 +81,7 @@ class SortTest extends ViewsKernelTestBase { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the ordering + // Change the ordering. $view->displayHandlers->get('default')->overrideOption('sorts', [ 'name' => [ 'order' => 'ASC', @@ -105,7 +105,7 @@ class SortTest extends ViewsKernelTestBase { $view->destroy(); $view->setDisplay(); - // Reverse the ordering + // Reverse the ordering. $view->displayHandlers->get('default')->overrideOption('sorts', [ 'name' => [ 'order' => 'DESC', diff --git a/core/modules/views/tests/src/Kernel/Plugin/SqlQueryTest.php b/core/modules/views/tests/src/Kernel/Plugin/SqlQueryTest.php index 271447fc8b1..3b36afd04ff 100644 --- a/core/modules/views/tests/src/Kernel/Plugin/SqlQueryTest.php +++ b/core/modules/views/tests/src/Kernel/Plugin/SqlQueryTest.php @@ -109,7 +109,7 @@ class SqlQueryTest extends ViewsKernelTestBase { $this->assertSame('default', $view->getQuery()->getConnection()->getKey()); $this->assertSame('default', $view->getQuery()->getConnection()->getTarget()); - // Test the database connection with the option 'replica' set to TRUE; + // Test the database connection with the option 'replica' set to TRUE. $view->getQuery()->options['replica'] = TRUE; $this->assertSame('default', $view->getQuery()->getConnection()->getKey()); $this->assertSame('replica', $view->getQuery()->getConnection()->getTarget()); diff --git a/core/modules/views/tests/src/Kernel/ViewStorageTest.php b/core/modules/views/tests/src/Kernel/ViewStorageTest.php index 4f7eed048a8..0ea14bf8032 100644 --- a/core/modules/views/tests/src/Kernel/ViewStorageTest.php +++ b/core/modules/views/tests/src/Kernel/ViewStorageTest.php @@ -71,7 +71,7 @@ class ViewStorageTest extends ViewsKernelTestBase { $this->createTests(); $this->displayTests(); - // Helper method tests + // Helper method tests. $this->displayMethodTests(); } diff --git a/core/modules/views/tests/src/Unit/Plugin/field/FieldPluginBaseTest.php b/core/modules/views/tests/src/Unit/Plugin/field/FieldPluginBaseTest.php index 79a3ff64888..ae182e2189a 100644 --- a/core/modules/views/tests/src/Unit/Plugin/field/FieldPluginBaseTest.php +++ b/core/modules/views/tests/src/Unit/Plugin/field/FieldPluginBaseTest.php @@ -181,7 +181,7 @@ class FieldPluginBaseTest extends UnitTestCase { ->willReturnCallback( // Pretend to do a render. function (&$elements, $is_root_call = FALSE) { - // Mock the ability to theme links + // Mock the ability to theme links. $link = $this->linkGenerator->generate($elements['#title'], $elements['#url']); if (isset($elements['#prefix'])) { $link = $elements['#prefix'] . $link; @@ -367,7 +367,7 @@ class FieldPluginBaseTest extends UnitTestCase { // entity_type flag. $entity_type_id = 'node'; $data[] = ['test-path', ['entity_type' => $entity_type_id], '<a href="/test-path">value</a>']; - // Prefix + // Prefix. $data[] = ['test-path', ['prefix' => 'test_prefix'], 'test_prefix<a href="/test-path">value</a>']; // suffix. $data[] = ['test-path', ['suffix' => 'test_suffix'], '<a href="/test-path">value</a>test_suffix']; diff --git a/core/modules/views/views.theme.inc b/core/modules/views/views.theme.inc index 04c5de5a535..e6e85343e9c 100644 --- a/core/modules/views/views.theme.inc +++ b/core/modules/views/views.theme.inc @@ -159,7 +159,7 @@ function template_preprocess_views_view_fields(&$variables): void { $object->wrapper_attributes = new Attribute($attributes); } - // Set up field label + // Set up field label. $object->label = $view->field[$id]->label(); // Set up field label wrapper and its attributes. @@ -300,7 +300,7 @@ function template_preprocess_views_view_summary(&$variables): void { $url->setRouteParameters($parameters); } catch (Exception) { - // If the given route doesn't exist, default to <front> + // If the given route doesn't exist, default to "<front>". $url = Url::fromRoute('<front>'); } } @@ -387,7 +387,7 @@ function template_preprocess_views_view_summary_unformatted(&$variables): void { $url->setRouteParameters($parameters); } catch (Exception) { - // If the given route doesn't exist, default to <front> + // If the given route doesn't exist, default to <front>. $url = Url::fromRoute('<front>'); } } diff --git a/core/modules/views_ui/src/Form/Ajax/AddHandler.php b/core/modules/views_ui/src/Form/Ajax/AddHandler.php index 1934593779e..171a87ac7cb 100644 --- a/core/modules/views_ui/src/Form/Ajax/AddHandler.php +++ b/core/modules/views_ui/src/Form/Ajax/AddHandler.php @@ -166,7 +166,7 @@ class AddHandler extends ViewsFormBase { '#markup' => '<div class="js-form-item form-item">' . $this->t('There are no @types available to add.', ['@types' => $ltitle]) . '</div>', ]; } - // Add a div to show the selected items + // Add a div to show the selected items. $form['selected'] = [ '#type' => 'item', '#markup' => '<span class="views-ui-view-title">' . $this->t('Selected:') . '</span><div class="views-selected-options"></div>', diff --git a/core/modules/views_ui/src/Form/Ajax/ConfigHandler.php b/core/modules/views_ui/src/Form/Ajax/ConfigHandler.php index e0ac4d9e92b..94de2c7a8eb 100644 --- a/core/modules/views_ui/src/Form/Ajax/ConfigHandler.php +++ b/core/modules/views_ui/src/Form/Ajax/ConfigHandler.php @@ -244,7 +244,7 @@ class ConfigHandler extends ViewsFormBase { // extra stuff on the form is not sent through. $handler->unpackOptions($handler->options, $options, NULL, FALSE); - // Store the item back on the view + // Store the item back on the view. $executable->setHandler($display_id, $type, $id, $handler->options); // Ensure any temporary options are removed. @@ -252,7 +252,7 @@ class ConfigHandler extends ViewsFormBase { unset($view->temporary_options[$type][$id]); } - // Write to cache + // Write to cache. $view->cacheSet(); } @@ -264,7 +264,7 @@ class ConfigHandler extends ViewsFormBase { $display_id = $form_state->get('display_id'); $type = $form_state->get('type'); $id = $form_state->get('id'); - // Store the item back on the view + // Store the item back on the view. [$was_defaulted, $is_defaulted] = $view->getOverrideValues($form, $form_state); $executable = $view->getExecutable(); // If the display selection was changed toggle the override value. @@ -274,7 +274,7 @@ class ConfigHandler extends ViewsFormBase { } $executable->removeHandler($display_id, $type, $id); - // Write to cache + // Write to cache. $view->cacheSet(); } diff --git a/core/modules/views_ui/src/Form/Ajax/ConfigHandlerExtra.php b/core/modules/views_ui/src/Form/Ajax/ConfigHandlerExtra.php index 8e711233899..a6f1bcdc236 100644 --- a/core/modules/views_ui/src/Form/Ajax/ConfigHandlerExtra.php +++ b/core/modules/views_ui/src/Form/Ajax/ConfigHandlerExtra.php @@ -112,10 +112,10 @@ class ConfigHandlerExtra extends ViewsFormBase { $item[$key] = $value; } - // Store the item back on the view + // Store the item back on the view. $view->getExecutable()->setHandler($form_state->get('display_id'), $form_state->get('type'), $form_state->get('id'), $item); - // Write to cache + // Write to cache. $view->cacheSet(); } diff --git a/core/modules/views_ui/src/Form/Ajax/ConfigHandlerGroup.php b/core/modules/views_ui/src/Form/Ajax/ConfigHandlerGroup.php index b208139f5ee..5e8a8851908 100644 --- a/core/modules/views_ui/src/Form/Ajax/ConfigHandlerGroup.php +++ b/core/modules/views_ui/src/Form/Ajax/ConfigHandlerGroup.php @@ -105,10 +105,10 @@ class ConfigHandlerGroup extends ViewsFormBase { $handler->submitGroupByForm($form, $form_state); - // Store the item back on the view + // Store the item back on the view. $executable->setHandler($form_state->get('display_id'), $form_state->get('type'), $form_state->get('id'), $item); - // Write to cache + // Write to cache. $view->cacheSet(); } diff --git a/core/modules/views_ui/src/Form/Ajax/Rearrange.php b/core/modules/views_ui/src/Form/Ajax/Rearrange.php index 52be994b276..57911220fae 100644 --- a/core/modules/views_ui/src/Form/Ajax/Rearrange.php +++ b/core/modules/views_ui/src/Form/Ajax/Rearrange.php @@ -72,7 +72,7 @@ class Rearrange extends ViewsFormBase { $count = 0; - // Get relationship labels + // Get relationship labels. $relationships = []; foreach ($display->getHandlers('relationship') as $id => $handler) { $relationships[$id] = $handler->adminLabel(); @@ -161,7 +161,7 @@ class Rearrange extends ViewsFormBase { $old_fields = $display->getOption($types[$type]['plural']); $new_fields = $order = []; - // Make an array with the weights + // Make an array with the weights. foreach ($form_state->getValue('fields') as $field => $info) { // Add each value that is a field with a weight to our list, but only if // it has had its 'removed' checkbox checked. @@ -170,7 +170,7 @@ class Rearrange extends ViewsFormBase { } } - // Sort the array + // Sort the array. asort($order); // Create a new list of fields in the new order. @@ -179,7 +179,7 @@ class Rearrange extends ViewsFormBase { } $display->setOption($types[$type]['plural'], $new_fields); - // Store in cache + // Store in cache. $view->cacheSet(); } diff --git a/core/modules/views_ui/src/Form/Ajax/RearrangeFilter.php b/core/modules/views_ui/src/Form/Ajax/RearrangeFilter.php index b0a3ad6b942..9bb23d40831 100644 --- a/core/modules/views_ui/src/Form/Ajax/RearrangeFilter.php +++ b/core/modules/views_ui/src/Form/Ajax/RearrangeFilter.php @@ -69,7 +69,7 @@ class RearrangeFilter extends ViewsFormBase { } $count = 0; - // Get relationship labels + // Get relationship labels. $relationships = []; foreach ($display->getHandlers('relationship') as $id => $handler) { $relationships[$id] = $handler->adminLabel(); @@ -242,7 +242,7 @@ class RearrangeFilter extends ViewsFormBase { // Whatever button was clicked, re-calculate field information. $new_fields = $order = []; - // Make an array with the weights + // Make an array with the weights. foreach ($form_state->getValue('filters') as $field => $info) { // Add each value that is a field with a weight to our list, but only if // it has had its 'removed' checkbox checked. @@ -258,7 +258,7 @@ class RearrangeFilter extends ViewsFormBase { } } - // Sort the array + // Sort the array. asort($order); // Create a new list of fields in the new order. @@ -271,7 +271,7 @@ class RearrangeFilter extends ViewsFormBase { $triggering_element = $form_state->getTriggeringElement(); if (!empty($triggering_element['#group'])) { if ($triggering_element['#group'] == 'add') { - // Add a new group + // Add a new group. $groups['groups'][] = 'AND'; } else { diff --git a/core/modules/views_ui/src/Hook/ViewsUiHooks.php b/core/modules/views_ui/src/Hook/ViewsUiHooks.php index 2d076aca439..45d5bafa096 100644 --- a/core/modules/views_ui/src/Hook/ViewsUiHooks.php +++ b/core/modules/views_ui/src/Hook/ViewsUiHooks.php @@ -75,7 +75,7 @@ class ViewsUiHooks { #[Hook('theme')] public function theme() : array { return [ - // Edit a view + // Edit a view. 'views_ui_display_tab_setting' => [ 'variables' => [ 'description' => '', @@ -127,7 +127,7 @@ class ViewsUiHooks { 'render element' => 'form', 'file' => 'views_ui.theme.inc', ], - // On behalf of a plugin + // On behalf of a plugin. 'views_ui_style_plugin_table' => [ 'render element' => 'form', 'file' => 'views_ui.theme.inc', diff --git a/core/modules/views_ui/src/Hook/ViewsUiThemeHooks.php b/core/modules/views_ui/src/Hook/ViewsUiThemeHooks.php new file mode 100644 index 00000000000..8284cbf1afa --- /dev/null +++ b/core/modules/views_ui/src/Hook/ViewsUiThemeHooks.php @@ -0,0 +1,70 @@ +<?php + +namespace Drupal\views_ui\Hook; + +use Drupal\Component\Utility\Xss; +use Drupal\Core\Hook\Attribute\Hook; + +/** + * Hook implementations for views_ui. + */ +class ViewsUiThemeHooks { + + /** + * Implements hook_preprocess_HOOK() for views templates. + */ + #[Hook('preprocess_views_view')] + public function preprocessViewsView(&$variables): void { + $view = $variables['view']; + // Render title for the admin preview. + if (!empty($view->live_preview)) { + $variables['title'] = [ + '#markup' => $view->getTitle(), + '#allowed_tags' => Xss::getHtmlTagList(), + ]; + } + if (!empty($view->live_preview) && \Drupal::moduleHandler()->moduleExists('contextual')) { + $view->setShowAdminLinks(FALSE); + foreach ([ + 'title', + 'header', + 'exposed', + 'rows', + 'pager', + 'more', + 'footer', + 'empty', + 'attachment_after', + 'attachment_before', + ] as $section) { + if (!empty($variables[$section])) { + $variables[$section] = [ + '#theme' => 'views_ui_view_preview_section', + '#view' => $view, + '#section' => $section, + '#content' => $variables[$section], + '#theme_wrappers' => [ + 'views_ui_container', + ], + '#attributes' => [ + 'class' => [ + 'contextual-region', + ], + ], + ]; + } + } + } + } + + /** + * Implements hook_theme_suggestions_HOOK(). + */ + #[Hook('theme_suggestions_views_ui_view_preview_section')] + public function themeSuggestionsViewsUiViewPreviewSection(array $variables): array { + return [ + 'views_ui_view_preview_section__' . $variables['section'], + ]; + } + +} diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php index e112480de1d..2c57b1eedd3 100644 --- a/core/modules/views_ui/src/ViewEditForm.php +++ b/core/modules/views_ui/src/ViewEditForm.php @@ -210,7 +210,7 @@ class ViewEditForm extends ViewFormBase { } } - // Add the edit display content + // Add the edit display content. $tab_content = $this->getDisplayTab($view); $tab_content['#theme_wrappers'] = ['container']; $tab_content['#attributes'] = ['class' => ['views-display-tab']]; @@ -647,13 +647,13 @@ class ViewEditForm extends ViewFormBase { */ public function submitDisplayUndoDelete($form, FormStateInterface $form_state) { $view = $this->entity; - // Create the new display + // Create the new display. $id = $form_state->get('display_id'); $displays = $view->get('display'); $displays[$id]['deleted'] = FALSE; $view->set('display', $displays); - // Store in cache + // Store in cache. $view->cacheSet(); // Redirect to the top-level edit page. @@ -669,10 +669,10 @@ class ViewEditForm extends ViewFormBase { public function submitDisplayEnable($form, FormStateInterface $form_state) { $view = $this->entity; $id = $form_state->get('display_id'); - // setOption doesn't work because this would might affect upper displays + // setOption doesn't work because this would might affect upper displays. $view->getExecutable()->displayHandlers->get($id)->setOption('enabled', TRUE); - // Store in cache + // Store in cache. $view->cacheSet(); // Redirect to the top-level edit page. @@ -690,7 +690,7 @@ class ViewEditForm extends ViewFormBase { $id = $form_state->get('display_id'); $view->getExecutable()->displayHandlers->get($id)->setOption('enabled', FALSE); - // Store in cache + // Store in cache. $view->cacheSet(); // Redirect to the top-level edit page. @@ -753,7 +753,7 @@ class ViewEditForm extends ViewFormBase { $element['#attributes']['class'] = ['views-display-top', 'clearfix']; $element['#attributes']['id'] = ['views-display-top']; - // Extra actions for the display + // Extra actions for the display. $element['extra_actions'] = [ '#type' => 'dropbutton', '#attributes' => [ @@ -1084,7 +1084,7 @@ class ViewEditForm extends ViewFormBase { ]; } - // Render the array of links + // Render the array of links. $build['#actions'] = [ '#type' => 'dropbutton', '#links' => $actions, diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php index c8606eb098f..2db8de84b04 100644 --- a/core/modules/views_ui/src/ViewUI.php +++ b/core/modules/views_ui/src/ViewUI.php @@ -477,7 +477,7 @@ class ViewUI implements ViewEntityInterface { } $id = $this->getExecutable()->addHandler($display_id, $type, $table, $field); - // Check to see if we have group by settings + // Check to see if we have group by settings. $key = $type; // Footer,header and empty text have a different internal handler // type(area). @@ -494,11 +494,11 @@ class ViewUI implements ViewEntityInterface { } // Check to see if this type has settings, if so add the settings form - // first + // first. if ($handler && $handler->hasExtraOptions()) { $this->addFormToStack('handler-extra', $display_id, $type, $id); } - // Then add the form to the stack + // Then add the form to the stack. $this->addFormToStack('handler', $display_id, $type, $id); } } @@ -507,7 +507,7 @@ class ViewUI implements ViewEntityInterface { unset($this->form_cache); } - // Store in cache + // Store in cache. $this->cacheSet(); } diff --git a/core/modules/views_ui/tests/src/Functional/DisplayTest.php b/core/modules/views_ui/tests/src/Functional/DisplayTest.php index eebd1861d59..cf603f6c8df 100644 --- a/core/modules/views_ui/tests/src/Functional/DisplayTest.php +++ b/core/modules/views_ui/tests/src/Functional/DisplayTest.php @@ -161,7 +161,7 @@ class DisplayTest extends UITestBase { $path = 'admin/structure/views/view/test_display/edit/block_1'; $link_display_path = 'admin/structure/views/nojs/display/test_display/block_1/link_display'; - // Test the link text displays 'None' and not 'Block 1' + // Test the link text displays 'None' and not 'Block 1'. $this->drupalGet($path); $this->assertSession()->elementTextEquals('xpath', "//a[contains(@href, '{$link_display_path}')]", 'None'); @@ -187,7 +187,7 @@ class DisplayTest extends UITestBase { $this->assertSession()->linkExists('Custom URL', 0, 'The link option has custom URL as summary.'); - // Test the default link_url value for new display + // Test the default link_url value for new display. $this->submitForm([], 'Add Block'); $this->assertSession()->addressEquals('admin/structure/views/view/test_display/edit/block_2'); $this->clickLink('Custom URL'); diff --git a/core/modules/views_ui/tests/src/Functional/HandlerTest.php b/core/modules/views_ui/tests/src/Functional/HandlerTest.php index 93d3a3006d4..4d24e830979 100644 --- a/core/modules/views_ui/tests/src/Functional/HandlerTest.php +++ b/core/modules/views_ui/tests/src/Functional/HandlerTest.php @@ -146,7 +146,7 @@ class HandlerTest extends UITestBase { $display = $view->getDisplay('default'); $this->assertTrue(isset($display['display_options'][$type_info['plural']][$id]), 'Ensure the field was added to the view itself.'); - // Remove the item and check that it's removed + // Remove the item and check that it's removed. $this->drupalGet($edit_handler_url); $this->submitForm([], 'Remove'); $this->assertSession()->linkByHrefNotExists($edit_handler_url, 0, 'The handler edit link does not appears in the UI after removing.'); diff --git a/core/modules/views_ui/tests/src/Functional/ViewEditTest.php b/core/modules/views_ui/tests/src/Functional/ViewEditTest.php index dbe0c0c3e3f..9e16c59ecbb 100644 --- a/core/modules/views_ui/tests/src/Functional/ViewEditTest.php +++ b/core/modules/views_ui/tests/src/Functional/ViewEditTest.php @@ -85,7 +85,7 @@ class ViewEditTest extends UITestBase { $machine_name_edit_url = 'admin/structure/views/nojs/display/test_view/test_1/display_id'; $error_text = 'Display machine name must contain only lowercase letters, numbers, or underscores.'; - // Test that potential invalid display ID requests are detected + // Test that potential invalid display ID requests are detected. $this->drupalGet('admin/structure/views/ajax/handler/test_view/fake_display_name/filter/title'); $arguments = [ '@display_id' => 'fake_display_name', diff --git a/core/modules/views_ui/tests/src/FunctionalJavascript/FilterEntityReferenceTest.php b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterEntityReferenceTest.php index eca6f479ed5..9458b59985a 100644 --- a/core/modules/views_ui/tests/src/FunctionalJavascript/FilterEntityReferenceTest.php +++ b/core/modules/views_ui/tests/src/FunctionalJavascript/FilterEntityReferenceTest.php @@ -92,7 +92,7 @@ class FilterEntityReferenceTest extends WebDriverTestBase { ->isVisible()); $this->assertTrue($page->findField('options[widget]')->isVisible()); - // Ensure that disabled form elements from selection handler do not show up + // Ensure that disabled form elements from selection handler do not show up. // @see \Drupal\views\Plugin\views\filter\EntityReference method // buildExtraOptionsForm. $this->assertFalse($page->hasField('options[reference_default:node][target_bundles_update]')); diff --git a/core/modules/views_ui/views_ui.module b/core/modules/views_ui/views_ui.module index d0e00a1ca7b..ab752170442 100644 --- a/core/modules/views_ui/views_ui.module +++ b/core/modules/views_ui/views_ui.module @@ -4,49 +4,10 @@ * @file */ -use Drupal\Component\Utility\Xss; use Drupal\Core\Url; use Drupal\views\ViewExecutable; /** - * Implements hook_preprocess_HOOK() for views templates. - */ -function views_ui_preprocess_views_view(&$variables): void { - $view = $variables['view']; - - // Render title for the admin preview. - if (!empty($view->live_preview)) { - $variables['title'] = [ - '#markup' => $view->getTitle(), - '#allowed_tags' => Xss::getHtmlTagList(), - ]; - } - - if (!empty($view->live_preview) && \Drupal::moduleHandler()->moduleExists('contextual')) { - $view->setShowAdminLinks(FALSE); - foreach (['title', 'header', 'exposed', 'rows', 'pager', 'more', 'footer', 'empty', 'attachment_after', 'attachment_before'] as $section) { - if (!empty($variables[$section])) { - $variables[$section] = [ - '#theme' => 'views_ui_view_preview_section', - '#view' => $view, - '#section' => $section, - '#content' => $variables[$section], - '#theme_wrappers' => ['views_ui_container'], - '#attributes' => ['class' => ['contextual-region']], - ]; - } - } - } -} - -/** - * Implements hook_theme_suggestions_HOOK(). - */ -function views_ui_theme_suggestions_views_ui_view_preview_section(array $variables): array { - return ['views_ui_view_preview_section__' . $variables['section']]; -} - -/** * Returns contextual links for each handler of a certain section. * * @todo Bring in relationships. diff --git a/core/modules/workflows/tests/src/Unit/WorkflowTest.php b/core/modules/workflows/tests/src/Unit/WorkflowTest.php index a17b8f7bf0b..a2eb0bcbde9 100644 --- a/core/modules/workflows/tests/src/Unit/WorkflowTest.php +++ b/core/modules/workflows/tests/src/Unit/WorkflowTest.php @@ -166,7 +166,7 @@ class WorkflowTest extends UnitTestCase { ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft') ->addTransition('publish', 'Publish', ['draft'], 'published'); - // Ensure we're returning state objects and they are set up correctly + // Ensure we're returning state objects and they are set up correctly. $this->assertInstanceOf(State::class, $workflow->getTypePlugin()->getState('draft')); $this->assertEquals('archived', $workflow->getTypePlugin()->getState('archived')->id()); $this->assertEquals('Archived', $workflow->getTypePlugin()->getState('archived')->label()); @@ -447,7 +447,7 @@ class WorkflowTest extends UnitTestCase { ->addTransition('create_new_draft', 'Create new draft', ['draft'], 'draft') ->addTransition('publish', 'Publish', ['draft'], 'published'); - // Ensure we're returning state objects and they are set up correctly + // Ensure we're returning state objects and they are set up correctly. $this->assertInstanceOf(Transition::class, $workflow->getTypePlugin()->getTransition('create_new_draft')); $this->assertEquals('publish', $workflow->getTypePlugin()->getTransition('publish')->id()); $this->assertEquals('Publish', $workflow->getTypePlugin()->getTransition('publish')->label()); diff --git a/core/modules/workspaces/tests/src/Kernel/WorkspaceCRUDTest.php b/core/modules/workspaces/tests/src/Kernel/WorkspaceCRUDTest.php index 6c4ac5ef105..9703526116d 100644 --- a/core/modules/workspaces/tests/src/Kernel/WorkspaceCRUDTest.php +++ b/core/modules/workspaces/tests/src/Kernel/WorkspaceCRUDTest.php @@ -231,7 +231,7 @@ class WorkspaceCRUDTest extends KernelTestBase { $workspace->save(); $this->workspaceManager->setActiveWorkspace($workspace); - // Create a new node in the 'stage' workspace + // Create a new node in the 'stage' workspace. $node = $this->createNode(['status' => TRUE]); // Create an additional workspace-specific revision for the node. diff --git a/core/profiles/demo_umami/config/install/editor.editor.basic_html.yml b/core/profiles/demo_umami/config/install/editor.editor.basic_html.yml index 60cd331cc87..a2ea7d8d5f7 100644 --- a/core/profiles/demo_umami/config/install/editor.editor.basic_html.yml +++ b/core/profiles/demo_umami/config/install/editor.editor.basic_html.yml @@ -37,6 +37,7 @@ settings: properties: reversed: false startIndex: true + styles: true multiBlock: false ckeditor5_sourceEditing: allowed_tags: @@ -46,8 +47,6 @@ settings: - '<dd>' - '<a hreflang>' - '<blockquote cite>' - - '<ul type>' - - '<ol type>' - '<h2 id>' - '<h3 id>' - '<h4 id>' diff --git a/core/profiles/demo_umami/config/install/editor.editor.full_html.yml b/core/profiles/demo_umami/config/install/editor.editor.full_html.yml index 307861f05c8..4c17465ec66 100644 --- a/core/profiles/demo_umami/config/install/editor.editor.full_html.yml +++ b/core/profiles/demo_umami/config/install/editor.editor.full_html.yml @@ -42,6 +42,7 @@ settings: properties: reversed: false startIndex: false + styles: true multiBlock: true ckeditor5_sourceEditing: allowed_tags: { } diff --git a/core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install b/core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install index 97eff3e068f..50186837d97 100644 --- a/core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install +++ b/core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.install @@ -19,16 +19,16 @@ function demo_umami_content_install($is_syncing): void { return; } - // Sort node IDs in descending order + // Sort node IDs in descending order. rsort($nids); $nodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple($nids); - // Use a counter to determine the "days ago" offset + // Use a counter to determine the "days ago" offset. $counter = 1; foreach ($nodes as $node) { - // Get all translation languages for the node + // Get all translation languages for the node. $languages = $node->getTranslationLanguages(); foreach ($languages as $language) { // Load the translated version of the node. @@ -54,7 +54,7 @@ function demo_umami_content_install($is_syncing): void { \Drupal::logger('system')->error($e->getMessage()); } } - // Increment the counter for the next node + // Increment the counter for the next node. $counter++; } } diff --git a/core/profiles/demo_umami/modules/demo_umami_content/src/InstallHelper.php b/core/profiles/demo_umami/modules/demo_umami_content/src/InstallHelper.php index 3d8e38c1d3b..966946c4e94 100644 --- a/core/profiles/demo_umami/modules/demo_umami_content/src/InstallHelper.php +++ b/core/profiles/demo_umami/modules/demo_umami_content/src/InstallHelper.php @@ -426,7 +426,7 @@ class InstallHelper implements ContainerInjectionInterface { if (!empty($data['slug'])) { $values['path'] = [['alias' => '/' . $data['slug']]]; } - // Save node alias + // Save node alias. $this->saveNodePath($langcode, 'page', $data['id'], $data['slug']); // Set article author. @@ -463,7 +463,7 @@ class InstallHelper implements ContainerInjectionInterface { if (!empty($data['slug'])) { $values['path'] = [['alias' => '/' . $data['slug']]]; } - // Save node alias + // Save node alias. $this->saveNodePath($langcode, 'recipe', $data['id'], $data['slug']); // Set field_media_image field. if (!empty($data['image_reference'])) { @@ -563,7 +563,7 @@ class InstallHelper implements ContainerInjectionInterface { if (!empty($data['slug'])) { $values['path'] = [['alias' => '/' . $data['slug']]]; } - // Save node alias + // Save node alias. $this->saveNodePath($langcode, 'article', $data['id'], $data['slug']); // Set article author. if (!empty($data['author'])) { diff --git a/core/profiles/standard/config/install/editor.editor.basic_html.yml b/core/profiles/standard/config/install/editor.editor.basic_html.yml index a31e41506fd..368bed22c17 100644 --- a/core/profiles/standard/config/install/editor.editor.basic_html.yml +++ b/core/profiles/standard/config/install/editor.editor.basic_html.yml @@ -39,6 +39,7 @@ settings: properties: reversed: false startIndex: true + styles: true multiBlock: true ckeditor5_sourceEditing: allowed_tags: @@ -48,8 +49,6 @@ settings: - '<dd>' - '<a hreflang>' - '<blockquote cite>' - - '<ul type>' - - '<ol type>' - '<h2 id>' - '<h3 id>' - '<h4 id>' diff --git a/core/profiles/standard/config/install/editor.editor.full_html.yml b/core/profiles/standard/config/install/editor.editor.full_html.yml index e30fc15eaf3..3b5a2729fc8 100644 --- a/core/profiles/standard/config/install/editor.editor.full_html.yml +++ b/core/profiles/standard/config/install/editor.editor.full_html.yml @@ -89,6 +89,7 @@ settings: properties: reversed: true startIndex: true + styles: true multiBlock: true ckeditor5_sourceEditing: allowed_tags: { } diff --git a/core/tests/Drupal/BuildTests/Composer/ComposerBuildTestBase.php b/core/tests/Drupal/BuildTests/Composer/ComposerBuildTestBase.php index 5c563016f52..8ab2b3b9fc7 100644 --- a/core/tests/Drupal/BuildTests/Composer/ComposerBuildTestBase.php +++ b/core/tests/Drupal/BuildTests/Composer/ComposerBuildTestBase.php @@ -36,7 +36,7 @@ abstract class ComposerBuildTestBase extends BuildTestBase { $this->assertFileExists($drupal_php_path); // Read back the Drupal version that was set and assert it matches - // expectations + // expectations. $this->executeCommand("php -r 'include \"$drupal_php_path\"; print \Drupal::VERSION;'"); $this->assertCommandSuccessful(); $this->assertCommandOutputContains($expectedVersion); diff --git a/core/tests/Drupal/BuildTests/Composer/Template/ComposerProjectTemplatesTest.php b/core/tests/Drupal/BuildTests/Composer/Template/ComposerProjectTemplatesTest.php index f7155bbac01..74b32658ba2 100644 --- a/core/tests/Drupal/BuildTests/Composer/Template/ComposerProjectTemplatesTest.php +++ b/core/tests/Drupal/BuildTests/Composer/Template/ComposerProjectTemplatesTest.php @@ -174,7 +174,7 @@ class ComposerProjectTemplatesTest extends ComposerBuildTestBase { #[DataProvider('provideTemplateCreateProject')] public function testTemplateCreateProject($project, $package_dir, $docroot_dir): void { - // Make a working COMPOSER_HOME directory for setting global composer config + // Make a working COMPOSER_HOME directory for setting global composer config. $composer_home = $this->getWorkspaceDirectory() . '/composer-home'; mkdir($composer_home); // Create an empty global composer.json file, just to avoid warnings. @@ -430,7 +430,7 @@ JSON; } $stability = VersionParser::parseStability($version); if ($stability === 'dev') { - // Strip off "-dev"; + // Strip off "-dev". $version_towards = substr($version, 0, -4); if (!str_ends_with($version_towards, '.0')) { diff --git a/core/tests/Drupal/BuildTests/Framework/Tests/BuildTestTest.php b/core/tests/Drupal/BuildTests/Framework/Tests/BuildTestTest.php index 7f97eb53027..388cc937254 100644 --- a/core/tests/Drupal/BuildTests/Framework/Tests/BuildTestTest.php +++ b/core/tests/Drupal/BuildTests/Framework/Tests/BuildTestTest.php @@ -196,7 +196,7 @@ class BuildTestTest extends BuildTestBase { $this->assertFileExists($full_path . DIRECTORY_SEPARATOR . 'docroot/sites/default/default.settings.php'); $this->assertFileExists($full_path . DIRECTORY_SEPARATOR . 'vendor'); - // Verify expected files do not exist + // Verify expected files do not exist. $this->assertFileDoesNotExist($full_path . DIRECTORY_SEPARATOR . 'docroot/sites/default/settings.php'); $this->assertFileDoesNotExist($full_path . DIRECTORY_SEPARATOR . 'docroot/sites/default/settings.local.php'); $this->assertFileDoesNotExist($full_path . DIRECTORY_SEPARATOR . 'docroot/sites/default/files'); diff --git a/core/tests/Drupal/FunctionalJavascriptTests/MachineName/MachineNameTransliterationTest.php b/core/tests/Drupal/FunctionalJavascriptTests/MachineName/MachineNameTransliterationTest.php index 19cc4bf3a40..9bf96e4fbf4 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/MachineName/MachineNameTransliterationTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/MachineName/MachineNameTransliterationTest.php @@ -79,6 +79,7 @@ class MachineNameTransliterationTest extends WebDriverTestBase { ['fr', 'ᐑ', 'wii'], // This test is not working with chromedriver as '𐌰𐌸' chars are not // accepted. + // phpcs:ignore Drupal.Commenting.InlineComment.InvalidEndChar // ['en', '𐌰𐌸', '__'], ['en', 'Ä Ö Ü Å Ø äöüåøhello', 'a_o_u_a_o_aouaohello'], ['de', 'Ä Ö Ü Å Ø äöüåøhello', 'ae_oe_ue_a_o_aeoeueaohello'], diff --git a/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php index 0a14594369b..73365503305 100644 --- a/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php +++ b/core/tests/Drupal/FunctionalJavascriptTests/TableDrag/TableDragTest.php @@ -107,7 +107,7 @@ class TableDragTest extends WebDriverTestBase { $session = $this->getSession(); $page = $session->getPage(); - // Confirm touchevents detection is loaded with Tabledrag + // Confirm touchevents detection is loaded with Tabledrag. $this->assertNotNull($this->assertSession()->waitForElement('css', 'html.no-touchevents')); $weight_select1 = $page->findField("table[1][weight]"); $weight_select2 = $page->findField("table[2][weight]"); diff --git a/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php b/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php index 248c70e2965..cac1c8bcedc 100644 --- a/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php +++ b/core/tests/Drupal/FunctionalTests/Bootstrap/UncaughtExceptionTest.php @@ -246,7 +246,7 @@ class UncaughtExceptionTest extends BrowserTestBase { $this->assertSession()->pageTextContains('The website encountered an unexpected error. Try again later.'); $this->assertSession()->pageTextContains($this->expectedExceptionMessage); - // Find fatal error logged to the error.log + // Find fatal error logged to the error.log. $errors = file(\Drupal::root() . '/' . $this->siteDirectory . '/error.log'); $this->assertCount(10, $errors, 'The error + the error that the logging service is broken has been written to the error log.'); $this->assertStringContainsString('Failed to log error', $errors[0], 'The error handling logs when an error could not be logged to the logger.'); diff --git a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php index 54bb662e211..ed4a7f750ba 100644 --- a/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php +++ b/core/tests/Drupal/FunctionalTests/BrowserTestBaseTest.php @@ -491,7 +491,7 @@ class BrowserTestBaseTest extends BrowserTestBase { */ public function testLocalTimeZone(): void { $expected = 'Australia/Sydney'; - // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php + // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php. $this->assertEquals($expected, date_default_timezone_get()); // The 'Australia/Sydney' time zone is also set in diff --git a/core/tests/Drupal/FunctionalTests/Core/Recipe/StandardRecipeTest.php b/core/tests/Drupal/FunctionalTests/Core/Recipe/StandardRecipeTest.php index b1651400689..b6d86e2754e 100644 --- a/core/tests/Drupal/FunctionalTests/Core/Recipe/StandardRecipeTest.php +++ b/core/tests/Drupal/FunctionalTests/Core/Recipe/StandardRecipeTest.php @@ -121,7 +121,7 @@ class StandardRecipeTest extends StandardTest { // Ensure we have truly rebuilt the standard profile using recipes. // Uncomment the code below to see the differences in a single file. - // phpcs:ignore Drupal.Files.LineLength + // phpcs:ignore Drupal.Commenting.InlineComment.InvalidEndChar, Drupal.Files.LineLength // $this->assertSame($sync->read('node.settings'), $active->read('node.settings')); $comparer = $this->configImporter()->getStorageComparer(); $expected_list = $comparer->getEmptyChangelist(); diff --git a/core/tests/Drupal/FunctionalTests/Installer/InstallerPostInstallTest.php b/core/tests/Drupal/FunctionalTests/Installer/InstallerPostInstallTest.php index 80d8abf2d5b..62606ac87aa 100644 --- a/core/tests/Drupal/FunctionalTests/Installer/InstallerPostInstallTest.php +++ b/core/tests/Drupal/FunctionalTests/Installer/InstallerPostInstallTest.php @@ -32,7 +32,7 @@ class InstallerPostInstallTest extends InstallerTestBase { // Confirm that the install_profile is correct. $this->drupalGet('/system-test/get-install-profile'); $this->assertSession()->pageTextContains('minimal'); - // Make an anonymous visit to the installer + // Make an anonymous visit to the installer. $this->drupalLogout(); $this->visitInstaller(); // Ensure that the install profile is still correct. diff --git a/core/tests/Drupal/KernelTests/Config/Schema/MappingTest.php b/core/tests/Drupal/KernelTests/Config/Schema/MappingTest.php index f375f6f3dd6..20f21373046 100644 --- a/core/tests/Drupal/KernelTests/Config/Schema/MappingTest.php +++ b/core/tests/Drupal/KernelTests/Config/Schema/MappingTest.php @@ -100,7 +100,6 @@ class MappingTest extends KernelTestBase { // Avoid showing "Powered by Drupal" on 404 responses. 'visibility' => [ 'I_CAN_CHOOSE_THIS' => [ - // This is what determines the 'id' => 'response_status', 'negate' => FALSE, 'status_codes' => [ @@ -219,7 +218,7 @@ class MappingTest extends KernelTestBase { // Special case: deprecated is needed for deprecated config schema: // - deprecated keys are treated as optional // - if a deprecated property path is itself a mapping, then the keys inside - // are not optional + // are not optional. yield 'No dynamic type: config_schema_deprecated_test.settings' => [ 'config_schema_deprecated_test.settings', NULL, diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigDiffTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigDiffTest.php index bbebfcf7ab4..00698b22a27 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigDiffTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigDiffTest.php @@ -48,7 +48,7 @@ class ConfigDiffTest extends KernelTestBase { [$change_key . ': ' . $original_data[$change_key]], [$change_key . ': ' . $change_data]); - // Reset data back to original, and remove a key + // Reset data back to original, and remove a key. $sync_data = $original_data; unset($sync_data[$remove_key]); $sync->write($config_name, $sync_data); @@ -62,7 +62,7 @@ class ConfigDiffTest extends KernelTestBase { FALSE ); - // Reset data back to original and add a key + // Reset data back to original and add a key. $sync_data = $original_data; $sync_data[$add_key] = $add_data; $sync->write($config_name, $sync_data); diff --git a/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php b/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php index 4cd56888088..dcdc149c86a 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/ConfigSchemaTest.php @@ -459,9 +459,13 @@ class ConfigSchemaTest extends KernelTestBase { ]; // Save config which has a schema that enforces types. - $this->config('config_schema_test.schema_data_types') + $config_object = $this->config('config_schema_test.schema_data_types'); + $config_object ->setData($untyped_to_typed) ->save(); + // Ensure the schemaWrapper property is reset after saving to prevent a + // memory leak. + $this->assertNull((new \ReflectionObject($config_object))->getProperty('schemaWrapper')->getValue($config_object)); $this->assertSame($typed_values, $this->config('config_schema_test.schema_data_types')->get()); // Save config which does not have a schema that enforces types. diff --git a/core/tests/Drupal/KernelTests/Core/Config/Storage/DatabaseStorageTest.php b/core/tests/Drupal/KernelTests/Core/Config/Storage/DatabaseStorageTest.php index 8eb71360bd3..ce38b4a5682 100644 --- a/core/tests/Drupal/KernelTests/Core/Config/Storage/DatabaseStorageTest.php +++ b/core/tests/Drupal/KernelTests/Core/Config/Storage/DatabaseStorageTest.php @@ -83,7 +83,7 @@ class DatabaseStorageTest extends ConfigStorageTestBase { $this->fail('Expected exception not thrown from exists()'); } catch (DatabaseExceptionWrapper) { - // Exception was expected + // Exception was expected. } try { @@ -91,7 +91,7 @@ class DatabaseStorageTest extends ConfigStorageTestBase { $this->fail('Expected exception not thrown from read()'); } catch (DatabaseExceptionWrapper) { - // Exception was expected + // Exception was expected. } try { @@ -99,7 +99,7 @@ class DatabaseStorageTest extends ConfigStorageTestBase { $this->fail('Expected exception not thrown from readMultiple()'); } catch (DatabaseExceptionWrapper) { - // Exception was expected + // Exception was expected. } try { @@ -107,7 +107,7 @@ class DatabaseStorageTest extends ConfigStorageTestBase { $this->fail('Expected exception not thrown from deleteAll()'); } catch (DatabaseExceptionWrapper) { - // Exception was expected + // Exception was expected. } try { @@ -115,7 +115,7 @@ class DatabaseStorageTest extends ConfigStorageTestBase { $this->fail('Expected exception not thrown from listAll()'); } catch (DatabaseExceptionWrapper) { - // Exception was expected + // Exception was expected. } try { @@ -123,7 +123,7 @@ class DatabaseStorageTest extends ConfigStorageTestBase { $this->fail('Expected exception not thrown from deleteAll()'); } catch (DatabaseExceptionWrapper) { - // Exception was expected + // Exception was expected. } try { @@ -131,7 +131,7 @@ class DatabaseStorageTest extends ConfigStorageTestBase { $this->fail('Expected exception not thrown from getAllCollectionNames()'); } catch (DatabaseExceptionWrapper) { - // Exception was expected + // Exception was expected. } $this->assertTrue(TRUE); diff --git a/core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSchemaTestBase.php b/core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSchemaTestBase.php index a3b46ab67e1..07db421d76d 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSchemaTestBase.php +++ b/core/tests/Drupal/KernelTests/Core/Database/DriverSpecificSchemaTestBase.php @@ -1292,7 +1292,7 @@ abstract class DriverSpecificSchemaTestBase extends DriverSpecificKernelTestBase $this->assertFalse($this->schema->fieldExists($table_name_new, $field_name)); $this->assertTrue($this->schema->fieldExists($table_name_new, $field_name_new)); - // Adding an unique key + // Adding an unique key. $unique_key_name = $unique_key_introspect_name = 'unique'; $this->schema->addUniqueKey($table_name_new, $unique_key_name, [$field_name_new]); @@ -1300,7 +1300,7 @@ abstract class DriverSpecificSchemaTestBase extends DriverSpecificKernelTestBase $introspect_index_schema = new \ReflectionMethod(get_class($this->schema), 'introspectIndexSchema'); $this->assertEquals([$field_name_new], $introspect_index_schema->invoke($this->schema, $table_name_new)['unique keys'][$unique_key_introspect_name]); - // Dropping an unique key + // Dropping an unique key. $this->schema->dropUniqueKey($table_name_new, $unique_key_name); // Dropping a field. diff --git a/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php b/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php index 2a0f685d2ac..6f6571fa6b0 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/InsertTest.php @@ -168,7 +168,7 @@ class InsertTest extends DatabaseTestBase { // INSERT INTO test (age, name, job) // SELECT tp.age AS age, tp.name AS name, tp.job AS job // FROM test_people tp - // WHERE tp.name = 'Meredith' + // WHERE tp.name = 'Meredith'. $this->connection->insert('test') ->from($query) ->execute(); @@ -189,7 +189,7 @@ class InsertTest extends DatabaseTestBase { // INSERT INTO test_people_copy // SELECT * // FROM test_people tp - // WHERE tp.name = 'Meredith' + // WHERE tp.name = 'Meredith'. $this->connection->insert('test_people_copy') ->from($query) ->execute(); diff --git a/core/tests/Drupal/KernelTests/Core/Database/SelectCloneTest.php b/core/tests/Drupal/KernelTests/Core/Database/SelectCloneTest.php index 15364ad53af..8dcefa33f43 100644 --- a/core/tests/Drupal/KernelTests/Core/Database/SelectCloneTest.php +++ b/core/tests/Drupal/KernelTests/Core/Database/SelectCloneTest.php @@ -35,7 +35,7 @@ class SelectCloneTest extends DatabaseTestBase { $clone_result = $clone->countQuery()->execute()->fetchField(); $query_result = $query->countQuery()->execute()->fetchField(); - // Make sure the cloned query has not been modified + // Make sure the cloned query has not been modified. $this->assertEquals(3, $clone_result, 'The cloned query returns the expected number of rows'); $this->assertEquals(2, $query_result, 'The query returns the expected number of rows'); } diff --git a/core/tests/Drupal/KernelTests/Core/Datetime/DrupalDateTimeTest.php b/core/tests/Drupal/KernelTests/Core/Datetime/DrupalDateTimeTest.php index e1542a30c38..78f87858c37 100644 --- a/core/tests/Drupal/KernelTests/Core/Datetime/DrupalDateTimeTest.php +++ b/core/tests/Drupal/KernelTests/Core/Datetime/DrupalDateTimeTest.php @@ -92,7 +92,7 @@ class DrupalDateTimeTest extends KernelTestBase { * Tests the ability to override the time zone in the format method. */ public function testTimezoneFormat(): void { - // Create a date in UTC + // Create a date in UTC. $date = DrupalDateTime::createFromTimestamp(87654321, 'UTC'); // Verify that the date format method displays the default time zone. diff --git a/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php b/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php index 54d72e9fbff..bc6368dadc7 100644 --- a/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php +++ b/core/tests/Drupal/KernelTests/Core/DrupalKernel/DrupalKernelTest.php @@ -248,7 +248,7 @@ class DrupalKernelTest extends KernelTestBase { $classloader = $this->prophesize(ClassLoader::class); // Assert that we call the setApcuPrefix on the classloader if - // class_loader_auto_detect is set to TRUE; + // class_loader_auto_detect is set to TRUE. if ($value) { $classloader->setApcuPrefix(Argument::type('string'))->shouldBeCalled(); } diff --git a/core/tests/Drupal/KernelTests/Core/DrupalKernel/ServiceDestructionTest.php b/core/tests/Drupal/KernelTests/Core/DrupalKernel/ServiceDestructionTest.php index 76e6d2d9532..b54b3065955 100644 --- a/core/tests/Drupal/KernelTests/Core/DrupalKernel/ServiceDestructionTest.php +++ b/core/tests/Drupal/KernelTests/Core/DrupalKernel/ServiceDestructionTest.php @@ -28,7 +28,7 @@ class ServiceDestructionTest extends KernelTestBase { // The service has not been destructed yet. $this->assertNull(\Drupal::state()->get('service_provider_test.destructed')); - // Call the class and then terminate the kernel + // Call the class and then terminate the kernel. $this->container->get('service_provider_test_class'); $response = new Response(); diff --git a/core/tests/Drupal/KernelTests/Core/Entity/ConfigEntityAdapterTest.php b/core/tests/Drupal/KernelTests/Core/Entity/ConfigEntityAdapterTest.php index f8c9848bfcf..9820f7f05d5 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/ConfigEntityAdapterTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/ConfigEntityAdapterTest.php @@ -42,7 +42,7 @@ class ConfigEntityAdapterTest extends KernelTestBase { $this->installConfig(static::$modules); // ConfigTest::create doesn't work with the following exception: - // "Multiple entity types found for Drupal\config_test\Entity\ConfigTest." + // "Multiple entity types found for Drupal\config_test\Entity\ConfigTest". $this->entity = \Drupal::entityTypeManager()->getStorage('config_test')->create([ 'id' => 'system', 'label' => 'foobar', diff --git a/core/tests/Drupal/KernelTests/Core/Entity/ConfigEntityQueryTest.php b/core/tests/Drupal/KernelTests/Core/Entity/ConfigEntityQueryTest.php index 4dac0039460..2269e9151d5 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/ConfigEntityQueryTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/ConfigEntityQueryTest.php @@ -551,28 +551,28 @@ class ConfigEntityQueryTest extends KernelTestBase { ]; // Sort key: id - // Sorting with 'DESC' upper case + // Sorting with 'DESC' upper case. $this->queryResults = $this->entityStorage->getQuery() ->tableSort($header) ->sort('id', 'DESC') ->execute(); $this->assertSame(['7', '6', '5', '4', '3', '2', '1'], array_values($this->queryResults)); - // Sorting with 'ASC' upper case + // Sorting with 'ASC' upper case. $this->queryResults = $this->entityStorage->getQuery() ->tableSort($header) ->sort('id', 'ASC') ->execute(); $this->assertSame(['1', '2', '3', '4', '5', '6', '7'], array_values($this->queryResults)); - // Sorting with 'desc' lower case + // Sorting with 'desc' lower case. $this->queryResults = $this->entityStorage->getQuery() ->tableSort($header) ->sort('id', 'desc') ->execute(); $this->assertSame(['7', '6', '5', '4', '3', '2', '1'], array_values($this->queryResults)); - // Sorting with 'asc' lower case + // Sorting with 'asc' lower case. $this->queryResults = $this->entityStorage->getQuery() ->tableSort($header) ->sort('id', 'asc') @@ -580,28 +580,28 @@ class ConfigEntityQueryTest extends KernelTestBase { $this->assertSame(['1', '2', '3', '4', '5', '6', '7'], array_values($this->queryResults)); // Sort key: number - // Sorting with 'DeSc' mixed upper and lower case + // Sorting with 'DeSc' mixed upper and lower case. $this->queryResults = $this->entityStorage->getQuery() ->tableSort($header) ->sort('number', 'DeSc') ->execute(); $this->assertSame(['7', '3', '5', '2', '1', '4', '6'], array_values($this->queryResults)); - // Sorting with 'AsC' mixed upper and lower case + // Sorting with 'AsC' mixed upper and lower case. $this->queryResults = $this->entityStorage->getQuery() ->tableSort($header) ->sort('number', 'AsC') ->execute(); $this->assertSame(['6', '4', '1', '2', '5', '3', '7'], array_values($this->queryResults)); - // Sorting with 'dEsC' mixed upper and lower case + // Sorting with 'dEsC' mixed upper and lower case. $this->queryResults = $this->entityStorage->getQuery() ->tableSort($header) ->sort('number', 'dEsC') ->execute(); $this->assertSame(['7', '3', '5', '2', '1', '4', '6'], array_values($this->queryResults)); - // Sorting with 'aSc' mixed upper and lower case + // Sorting with 'aSc' mixed upper and lower case. $this->queryResults = $this->entityStorage->getQuery() ->tableSort($header) ->sort('number', 'aSc') diff --git a/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php b/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php index bd7ec5c89c7..7beb22610fb 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/Element/EntityAutocompleteElementFormTest.php @@ -296,7 +296,7 @@ class EntityAutocompleteElementFormTest extends EntityKernelTestBase implements public function testInvalidEntityAutocompleteElement(): void { $form_builder = $this->container->get('form_builder'); - // Test 'single' with an entity label that doesn't exist + // Test 'single' with an entity label that doesn't exist. $form_state = (new FormState()) ->setValues([ 'single' => 'single - non-existent label', diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php index 1c65e7f9642..4c5e2c966ae 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityFieldTest.php @@ -254,7 +254,7 @@ class EntityFieldTest extends EntityKernelTestBase { // Test emptying a field by assigning an empty value, NULL and an empty // array behave the same. foreach ([NULL, [], 'unset'] as $empty) { - // Make sure a value is present + // Make sure a value is present. $entity->name->value = 'a value'; $this->assertTrue(isset($entity->name->value), "$entity_type: Name is set."); // Now, empty the field. diff --git a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php index 3140cab146b..920ddd114c1 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/EntityQueryTest.php @@ -426,6 +426,7 @@ class EntityQueryTest extends EntityKernelTestBase { // As we do not have any conditions, here are the possible colors and // language codes, already in order, with the first occurrence of the // entity id marked with *: + // 8 NULL pl * // 12 NULL pl * diff --git a/core/tests/Drupal/KernelTests/Core/Entity/FieldSqlStorageTest.php b/core/tests/Drupal/KernelTests/Core/Entity/FieldSqlStorageTest.php index 8b6d9ed52eb..5d04166e294 100644 --- a/core/tests/Drupal/KernelTests/Core/Entity/FieldSqlStorageTest.php +++ b/core/tests/Drupal/KernelTests/Core/Entity/FieldSqlStorageTest.php @@ -503,7 +503,7 @@ class FieldSqlStorageTest extends EntityKernelTestBase { $expected = 'short_entity_type_revision__short_field_name'; $this->assertEquals($expected, $this->tableMapping->getDedicatedRevisionTableName($field_storage)); - // Short entity type, long field name + // Short entity type, long field name. $entity_type = 'short_entity_type'; $field_name = 'long_field_name_abcdefghijklmnopqrstuvwxyz'; $field_storage = FieldStorageConfig::create([ @@ -516,7 +516,7 @@ class FieldSqlStorageTest extends EntityKernelTestBase { $expected = 'short_entity_type_r__' . substr(hash('sha256', $field_storage->uuid()), 0, 10); $this->assertEquals($expected, $this->tableMapping->getDedicatedRevisionTableName($field_storage)); - // Long entity type, short field name + // Long entity type, short field name. $entity_type = 'long_entity_type_all_forty_three_characters'; $field_name = 'short_field_name'; $field_storage = FieldStorageConfig::create([ diff --git a/core/tests/Drupal/KernelTests/Core/Extension/ModuleExtensionListTest.php b/core/tests/Drupal/KernelTests/Core/Extension/ModuleExtensionListTest.php index 0981068243e..b3146ebb145 100644 --- a/core/tests/Drupal/KernelTests/Core/Extension/ModuleExtensionListTest.php +++ b/core/tests/Drupal/KernelTests/Core/Extension/ModuleExtensionListTest.php @@ -22,7 +22,7 @@ class ModuleExtensionListTest extends KernelTestBase { ->save(); // The installation profile is provided by a container parameter. - // Saving the configuration doesn't automatically trigger invalidation + // Saving the configuration doesn't automatically trigger invalidation. $this->container->get('kernel')->rebuildContainer(); /** @var \Drupal\Core\Extension\ModuleExtensionList $module_extension_list */ diff --git a/core/tests/Drupal/KernelTests/Core/Extension/ThemeExtensionListTest.php b/core/tests/Drupal/KernelTests/Core/Extension/ThemeExtensionListTest.php index 0ccae25b155..5bf173aff86 100644 --- a/core/tests/Drupal/KernelTests/Core/Extension/ThemeExtensionListTest.php +++ b/core/tests/Drupal/KernelTests/Core/Extension/ThemeExtensionListTest.php @@ -22,7 +22,7 @@ class ThemeExtensionListTest extends KernelTestBase { ->save(); // The installation profile is provided by a container parameter. - // Saving the configuration doesn't automatically trigger invalidation + // Saving the configuration doesn't automatically trigger invalidation. $this->container->get('kernel')->rebuildContainer(); /** @var \Drupal\Core\Extension\ThemeExtensionList $theme_extension_list */ diff --git a/core/tests/Drupal/KernelTests/Core/Field/Entity/BaseFieldOverrideTest.php b/core/tests/Drupal/KernelTests/Core/Field/Entity/BaseFieldOverrideTest.php index 0262f800bc8..e9815b9a6b8 100644 --- a/core/tests/Drupal/KernelTests/Core/Field/Entity/BaseFieldOverrideTest.php +++ b/core/tests/Drupal/KernelTests/Core/Field/Entity/BaseFieldOverrideTest.php @@ -96,7 +96,8 @@ class BaseFieldOverrideTest extends KernelTestBase { ->setTargetEntityTypeId('entity_test') ->setReadOnly(TRUE) // Ensure that the internal property is inherited from the base field and - // not the parent class. @see FieldConfigBase::isInternal + // not the parent class. + // @see FieldConfigBase::isInternal ->setInternal(TRUE) ->setComputed(FALSE); diff --git a/core/tests/Drupal/KernelTests/Core/File/FileCopyTest.php b/core/tests/Drupal/KernelTests/Core/File/FileCopyTest.php index a7bf5b9dd70..56d26fdafdb 100644 --- a/core/tests/Drupal/KernelTests/Core/File/FileCopyTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/FileCopyTest.php @@ -21,7 +21,7 @@ class FileCopyTest extends FileTestBase { * Copy a normal file. */ public function testNormal(): void { - // Create a file for testing + // Create a file for testing. $uri = $this->createUri(); // Copying to a new name. @@ -51,7 +51,7 @@ class FileCopyTest extends FileTestBase { * Copy a non-existent file. */ public function testNonExistent(): void { - // Copy non-existent file + // Copy non-existent file. $desired_filepath = $this->randomMachineName(); $this->assertFileDoesNotExist($desired_filepath); $this->expectException(FileNotExistsException::class); @@ -63,7 +63,7 @@ class FileCopyTest extends FileTestBase { * Copy a file onto itself. */ public function testOverwriteSelf(): void { - // Create a file for testing + // Create a file for testing. $uri = $this->createUri(); // Copy the file onto itself with renaming works. diff --git a/core/tests/Drupal/KernelTests/Core/File/FileDeleteRecursiveTest.php b/core/tests/Drupal/KernelTests/Core/File/FileDeleteRecursiveTest.php index 8fa28491f6a..761e408a878 100644 --- a/core/tests/Drupal/KernelTests/Core/File/FileDeleteRecursiveTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/FileDeleteRecursiveTest.php @@ -15,7 +15,7 @@ class FileDeleteRecursiveTest extends FileTestBase { * Delete a normal file. */ public function testSingleFile(): void { - // Create a file for testing + // Create a file for testing. $filepath = 'public://' . $this->randomMachineName(); file_put_contents($filepath, ''); diff --git a/core/tests/Drupal/KernelTests/Core/File/FileDeleteTest.php b/core/tests/Drupal/KernelTests/Core/File/FileDeleteTest.php index 27a76157bb0..aacba78f408 100644 --- a/core/tests/Drupal/KernelTests/Core/File/FileDeleteTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/FileDeleteTest.php @@ -17,10 +17,10 @@ class FileDeleteTest extends FileTestBase { * Delete a normal file. */ public function testNormal(): void { - // Create a file for testing + // Create a file for testing. $uri = $this->createUri(); - // Delete a regular file + // Delete a regular file. $this->assertTrue(\Drupal::service('file_system')->delete($uri), 'Deleted worked.'); $this->assertFileDoesNotExist($uri); } @@ -29,7 +29,7 @@ class FileDeleteTest extends FileTestBase { * Try deleting a missing file. */ public function testMissing(): void { - // Try to delete a non-existing file + // Try to delete a non-existing file. $this->assertTrue(\Drupal::service('file_system')->delete('public://' . $this->randomMachineName()), 'Returns true when deleting a non-existent file.'); } diff --git a/core/tests/Drupal/KernelTests/Core/File/FileMoveTest.php b/core/tests/Drupal/KernelTests/Core/File/FileMoveTest.php index bc0d8073153..e9236bc918c 100644 --- a/core/tests/Drupal/KernelTests/Core/File/FileMoveTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/FileMoveTest.php @@ -21,7 +21,7 @@ class FileMoveTest extends FileTestBase { * Move a normal file. */ public function testNormal(): void { - // Create a file for testing + // Create a file for testing. $uri = $this->createUri(); // Moving to a new name. diff --git a/core/tests/Drupal/KernelTests/Core/File/MimeType/ExtensionMimeTypeGuesserLegacyTest.php b/core/tests/Drupal/KernelTests/Core/File/MimeType/ExtensionMimeTypeGuesserLegacyTest.php index 8cb96454408..df359c2873f 100644 --- a/core/tests/Drupal/KernelTests/Core/File/MimeType/ExtensionMimeTypeGuesserLegacyTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/MimeType/ExtensionMimeTypeGuesserLegacyTest.php @@ -60,7 +60,7 @@ class ExtensionMimeTypeGuesserLegacyTest extends KernelTestBase { ]; $this->expectDeprecation( - 'The deprecated alter hook hook_file_mimetype_mapping_alter() is implemented in these locations: file_deprecated_test_file_mimetype_mapping_alter. This hook is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Implement a \Drupal\Core\File\Event\MimeTypeMapLoadedEvent listener instead. See https://www.drupal.org/node/3494040' + 'The deprecated alter hook hook_file_mimetype_mapping_alter() is implemented in these locations: Drupal\file_deprecated_test\Hook\FileDeprecatedTestThemeHooks::fileMimetypeMappingAlter. This hook is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Implement a \Drupal\Core\File\Event\MimeTypeMapLoadedEvent listener instead. See https://www.drupal.org/node/3494040' ); /** @var \Drupal\Core\File\MimeType\ExtensionMimeTypeGuesser $guesser */ diff --git a/core/tests/Drupal/KernelTests/Core/File/MimeType/LegacyMimeTypeTest.php b/core/tests/Drupal/KernelTests/Core/File/MimeType/LegacyMimeTypeTest.php index ae713fc27ae..2eb87a14242 100644 --- a/core/tests/Drupal/KernelTests/Core/File/MimeType/LegacyMimeTypeTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/MimeType/LegacyMimeTypeTest.php @@ -27,7 +27,7 @@ class LegacyMimeTypeTest extends KernelTestBase { */ public function testHookFileMimetypeMappingAlter(): void { $this->expectDeprecation( - 'The deprecated alter hook hook_file_mimetype_mapping_alter() is implemented in these locations: file_deprecated_test_file_mimetype_mapping_alter. This hook is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Implement a \Drupal\Core\File\Event\MimeTypeMapLoadedEvent listener instead. See https://www.drupal.org/node/3494040' + 'The deprecated alter hook hook_file_mimetype_mapping_alter() is implemented in these locations: Drupal\file_deprecated_test\Hook\FileDeprecatedTestThemeHooks::fileMimetypeMappingAlter. This hook is deprecated in drupal:11.2.0 and is removed from drupal:12.0.0. Implement a \Drupal\Core\File\Event\MimeTypeMapLoadedEvent listener instead. See https://www.drupal.org/node/3494040' ); $map = \Drupal::service(MimeTypeMapInterface::class); diff --git a/core/tests/Drupal/KernelTests/Core/File/ReadOnlyStreamWrapperTest.php b/core/tests/Drupal/KernelTests/Core/File/ReadOnlyStreamWrapperTest.php index 54f01270198..8bfcc728c64 100644 --- a/core/tests/Drupal/KernelTests/Core/File/ReadOnlyStreamWrapperTest.php +++ b/core/tests/Drupal/KernelTests/Core/File/ReadOnlyStreamWrapperTest.php @@ -38,51 +38,51 @@ class ReadOnlyStreamWrapperTest extends FileTestBase { // Checks that the stream wrapper type is declared as local. $this->assertSame(1, $type & StreamWrapperInterface::LOCAL); - // Generate a test file + // Generate a test file. $filename = $this->randomMachineName(); $site_path = $this->container->getParameter('site.path'); $filepath = $site_path . '/files/' . $filename; file_put_contents($filepath, $filename); - // Generate a read-only stream wrapper instance + // Generate a read-only stream wrapper instance. $uri = $this->scheme . '://' . $filename; \Drupal::service('stream_wrapper_manager')->getViaScheme($this->scheme); $file_system = \Drupal::service('file_system'); - // Attempt to open a file in read/write mode + // Attempt to open a file in read/write mode. $handle = @fopen($uri, 'r+'); $this->assertFalse($handle, 'Unable to open a file for reading and writing with the read-only stream wrapper.'); - // Attempt to open a file in binary read mode + // Attempt to open a file in binary read mode. $handle = fopen($uri, 'rb'); $this->assertNotFalse($handle, 'Able to open a file for reading in binary mode with the read-only stream wrapper.'); $this->assertTrue(fclose($handle), 'Able to close file opened in binary mode using the read_only stream wrapper.'); - // Attempt to open a file in text read mode + // Attempt to open a file in text read mode. $handle = fopen($uri, 'rt'); $this->assertNotFalse($handle, 'Able to open a file for reading in text mode with the read-only stream wrapper.'); $this->assertTrue(fclose($handle), 'Able to close file opened in text mode using the read_only stream wrapper.'); - // Attempt to open a file in read mode + // Attempt to open a file in read mode. $handle = fopen($uri, 'r'); $this->assertNotFalse($handle, 'Able to open a file for reading with the read-only stream wrapper.'); - // Attempt to change file permissions + // Attempt to change file permissions. $this->assertFalse(@chmod($uri, 0777), 'Unable to change file permissions when using read-only stream wrapper.'); - // Attempt to acquire an exclusive lock for writing + // Attempt to acquire an exclusive lock for writing. $this->assertFalse(@flock($handle, LOCK_EX | LOCK_NB), 'Unable to acquire an exclusive lock using the read-only stream wrapper.'); - // Attempt to obtain a shared lock + // Attempt to obtain a shared lock. $this->assertTrue(flock($handle, LOCK_SH | LOCK_NB), 'Able to acquire a shared lock using the read-only stream wrapper.'); - // Attempt to release a shared lock + // Attempt to release a shared lock. $this->assertTrue(flock($handle, LOCK_UN | LOCK_NB), 'Able to release a shared lock using the read-only stream wrapper.'); - // Attempt to truncate the file + // Attempt to truncate the file. $this->assertFalse(@ftruncate($handle, 0), 'Unable to truncate using the read-only stream wrapper.'); - // Attempt to write to the file + // Attempt to write to the file. $this->assertEquals(0, @fwrite($handle, $this->randomMachineName()), 'Unable to write to file using the read-only stream wrapper.'); - // Attempt to flush output to the file + // Attempt to flush output to the file. $this->assertFalse(@fflush($handle), 'Unable to flush output to file using the read-only stream wrapper.'); // Attempt to close the stream. (Suppress errors, as fclose triggers // fflush.) $this->assertTrue(fclose($handle), 'Able to close file using the read_only stream wrapper.'); - // Test the rename() function + // Test the rename() function. $this->assertFalse(@rename($uri, $this->scheme . '://new_name.txt'), 'Unable to rename files using the read-only stream wrapper.'); - // Test the unlink() function + // Test the unlink() function. $this->assertTrue(@$file_system->unlink($uri), 'Able to unlink file using read-only stream wrapper.'); $this->assertFileExists($filepath); @@ -93,7 +93,7 @@ class ReadOnlyStreamWrapperTest extends FileTestBase { /** @var \Drupal\Core\File\FileSystemInterface $file_system */ $file_system = \Drupal::service('file_system'); $this->assertFalse(@$file_system->mkdir($read_only_dir, 0775, 0), 'Unable to create directory with read-only stream wrapper.'); - // Create a temporary directory for testing purposes + // Create a temporary directory for testing purposes. $this->assertTrue($file_system->mkdir($dir), 'Test directory created.'); // Test the rmdir() function by attempting to remove the directory. $this->assertFalse(@$file_system->rmdir($read_only_dir), 'Unable to delete directory with read-only stream wrapper.'); diff --git a/core/tests/Drupal/KernelTests/Core/KeyValueStore/StorageTestBase.php b/core/tests/Drupal/KernelTests/Core/KeyValueStore/StorageTestBase.php index 91af498b01c..f689e4d9124 100644 --- a/core/tests/Drupal/KernelTests/Core/KeyValueStore/StorageTestBase.php +++ b/core/tests/Drupal/KernelTests/Core/KeyValueStore/StorageTestBase.php @@ -38,7 +38,7 @@ abstract class StorageTestBase extends KernelTestBase { protected function setUp(): void { parent::setUp(); - // Define two data collections, + // Define two data collections. $this->collections = [0 => 'zero', 1 => 'one']; // Create several objects for testing. diff --git a/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php b/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php index 4cc3a8148ef..5ef26929c46 100644 --- a/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php +++ b/core/tests/Drupal/KernelTests/Core/Routing/RouteProviderTest.php @@ -706,7 +706,7 @@ class RouteProviderTest extends KernelTestBase { $this->assertEquals(0, $result->count()); $candidates = $provider->getCandidateOutlines(explode('/', trim($shortest, '/'))); $this->assertCount(7, $candidates); - // A longer patten is not found and returns no candidates + // A longer patten is not found and returns no candidates. $path_to_test = '/test/1/test2/2/test3/3/4/5/6/test4'; $result = $provider->getRoutesByPattern($path_to_test); $this->assertEquals(0, $result->count()); diff --git a/core/tests/Drupal/KernelTests/KernelTestBase.php b/core/tests/Drupal/KernelTests/KernelTestBase.php index c45e937d371..02a9abbc9ad 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBase.php +++ b/core/tests/Drupal/KernelTests/KernelTestBase.php @@ -967,7 +967,7 @@ abstract class KernelTestBase extends TestCase implements ServiceProviderInterfa ->save(); // The installation profile is provided by a container parameter. Saving - // the configuration doesn't automatically trigger invalidation + // the configuration doesn't automatically trigger invalidation. $this->container->get('kernel')->rebuildContainer(); } diff --git a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php index db658255c82..80d3d18007b 100644 --- a/core/tests/Drupal/KernelTests/KernelTestBaseTest.php +++ b/core/tests/Drupal/KernelTests/KernelTestBaseTest.php @@ -250,7 +250,7 @@ class KernelTestBaseTest extends KernelTestBase { * Tests the assumption that local time is in 'Australia/Sydney'. */ public function testLocalTimeZone(): void { - // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php + // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php. $this->assertEquals('Australia/Sydney', date_default_timezone_get()); } diff --git a/core/tests/Drupal/TestSite/TestSiteClaroInstallTestScript.php b/core/tests/Drupal/TestSite/TestSiteClaroInstallTestScript.php index 26cc8a29033..14f92944b31 100644 --- a/core/tests/Drupal/TestSite/TestSiteClaroInstallTestScript.php +++ b/core/tests/Drupal/TestSite/TestSiteClaroInstallTestScript.php @@ -32,17 +32,17 @@ class TestSiteClaroInstallTestScript implements TestSetupInterface { $system_theme_config = \Drupal::configFactory()->getEditable('system.theme'); $system_theme_config->set('default', 'claro')->save(); - // Create an article that will have no comments + // Create an article that will have no comments. $article_no_comments = Node::create(['type' => 'article']); $article_no_comments->set('title', 'Article without comments'); - // Enable comments + // Enable comments. $article_no_comments->set('comment', 2); $article_no_comments->save(); - // Create an article that will have comments + // Create an article that will have comments. $article_with_comments = Node::create(['type' => 'article']); $article_with_comments->set('title', 'Article with comments'); - // Enable comments + // Enable comments. $article_with_comments->set('comment', 2); $article_with_comments->save(); @@ -60,7 +60,7 @@ class TestSiteClaroInstallTestScript implements TestSetupInterface { // Whether the comment is 'approved' or not. 'status' => 1, ]; - // Create comment entities out of our field values + // Create comment entities out of our field values. $comment1 = Comment::create($values); $comment1->save(); diff --git a/core/tests/Drupal/TestSite/TestSiteOliveroInstallTestScript.php b/core/tests/Drupal/TestSite/TestSiteOliveroInstallTestScript.php index 02e945b7e2d..f175156ad05 100644 --- a/core/tests/Drupal/TestSite/TestSiteOliveroInstallTestScript.php +++ b/core/tests/Drupal/TestSite/TestSiteOliveroInstallTestScript.php @@ -32,17 +32,17 @@ class TestSiteOliveroInstallTestScript implements TestSetupInterface { $system_theme_config = \Drupal::configFactory()->getEditable('system.theme'); $system_theme_config->set('default', 'olivero')->save(); - // Create an article that will have no comments + // Create an article that will have no comments. $article_no_comments = Node::create(['type' => 'article']); $article_no_comments->set('title', 'Article without comments'); - // Enable comments + // Enable comments. $article_no_comments->set('comment', 2); $article_no_comments->save(); - // Create an article that will have comments + // Create an article that will have comments. $article_with_comments = Node::create(['type' => 'article']); $article_with_comments->set('title', 'Article with comments'); - // Enable comments + // Enable comments. $article_with_comments->set('comment', 2); $article_with_comments->save(); @@ -60,7 +60,7 @@ class TestSiteOliveroInstallTestScript implements TestSetupInterface { // Whether the comment is 'approved' or not. 'status' => 1, ]; - // Create comment entities out of our field values + // Create comment entities out of our field values. $comment1 = Comment::create($values); $comment1->save(); diff --git a/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php b/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php index b57d2740704..87cd766c288 100644 --- a/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php +++ b/core/tests/Drupal/Tests/Component/DependencyInjection/ContainerTest.php @@ -988,7 +988,7 @@ class ContainerTest extends TestCase { 'configurator' => 'configurator_service_test_does_not_exist', ]; - // Raw argument + // Raw argument. $services['service_with_raw_argument'] = [ 'class' => '\Drupal\Tests\Component\DependencyInjection\MockInstantiationService', 'arguments' => $this->getCollection([$this->getRaw('ccc')]), diff --git a/core/tests/Drupal/Tests/Component/Serialization/JsonTest.php b/core/tests/Drupal/Tests/Component/Serialization/JsonTest.php index 3e9169c5969..c36c4a619f9 100644 --- a/core/tests/Drupal/Tests/Component/Serialization/JsonTest.php +++ b/core/tests/Drupal/Tests/Component/Serialization/JsonTest.php @@ -53,7 +53,7 @@ class JsonTest extends TestCase { // Characters that must be escaped. // We check for unescaped " separately. $this->htmlUnsafe = ['<', '>', '\'', '&']; - // The following are the encoded forms of: < > ' & " + // The following are the encoded forms of '<', '>', "'", '&', and '"'. $this->htmlUnsafeEscaped = ['\u003C', '\u003E', '\u0027', '\u0026', '\u0022']; } @@ -110,7 +110,7 @@ class JsonTest extends TestCase { foreach ($this->htmlUnsafe as $char) { $this->assertStringNotContainsString($char, $json, sprintf('A JSON encoded string does not contain %s.', $char)); } - // Verify that JSON encoding escapes the HTML unsafe characters + // Verify that JSON encoding escapes the HTML unsafe characters. foreach ($this->htmlUnsafeEscaped as $char) { $this->assertStringContainsString($char, $json, sprintf('A JSON encoded string contains %s.', $char)); } diff --git a/core/tests/Drupal/Tests/Component/Utility/XssTest.php b/core/tests/Drupal/Tests/Component/Utility/XssTest.php index 693a75d6f92..5857d2acf7d 100644 --- a/core/tests/Drupal/Tests/Component/Utility/XssTest.php +++ b/core/tests/Drupal/Tests/Component/Utility/XssTest.php @@ -607,7 +607,7 @@ class XssTest extends TestCase { */ public static function providerTestFilterXssAdminNotNormalized() { return [ - // DRUPAL-SA-2008-044 + // DRUPAL-SA-2008-044. ['<object />', 'object', 'Admin HTML filter -- should not allow object tag.'], ['<script />', 'script', 'Admin HTML filter -- should not allow script tag.'], ]; diff --git a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php index e44218405bb..1bcc9cab78d 100644 --- a/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php +++ b/core/tests/Drupal/Tests/Core/Access/AccessResultTest.php @@ -207,7 +207,7 @@ class AccessResultTest extends UnitTestCase { $this->assertEquals('forbidden message', $access->getReason()); $this->assertDefaultCacheability($access); - // NEUTRAL && ALLOW == NEUTRAL + // NEUTRAL && ALLOW == NEUTRAL. $access = $neutral->andIf($allowed); $this->assertFalse($access->isAllowed()); $this->assertFalse($access->isForbidden()); @@ -231,7 +231,7 @@ class AccessResultTest extends UnitTestCase { $this->assertEquals('forbidden message', $access->getReason()); $this->assertDefaultCacheability($access); - // FORBIDDEN && ALLOWED = FORBIDDEN + // FORBIDDEN && ALLOWED = FORBIDDEN. $access = $forbidden->andIf($allowed); $this->assertFalse($access->isAllowed()); $this->assertTrue($access->isForbidden()); @@ -239,7 +239,7 @@ class AccessResultTest extends UnitTestCase { $this->assertEquals('forbidden message', $access->getReason()); $this->assertDefaultCacheability($access); - // FORBIDDEN && NEUTRAL = FORBIDDEN + // FORBIDDEN && NEUTRAL = FORBIDDEN. $access = $forbidden->andIf($neutral); $this->assertFalse($access->isAllowed()); $this->assertTrue($access->isForbidden()); @@ -247,7 +247,7 @@ class AccessResultTest extends UnitTestCase { $this->assertEquals('forbidden message', $access->getReason()); $this->assertDefaultCacheability($access); - // FORBIDDEN && FORBIDDEN = FORBIDDEN + // FORBIDDEN && FORBIDDEN = FORBIDDEN. $access = $forbidden->andIf($forbidden); $this->assertFalse($access->isAllowed()); $this->assertTrue($access->isForbidden()); diff --git a/core/tests/Drupal/Tests/Core/Config/ConfigTest.php b/core/tests/Drupal/Tests/Core/Config/ConfigTest.php index e313731c9eb..a0f6447554d 100644 --- a/core/tests/Drupal/Tests/Core/Config/ConfigTest.php +++ b/core/tests/Drupal/Tests/Core/Config/ConfigTest.php @@ -449,7 +449,7 @@ class ConfigTest extends UnitTestCase { 'Config object name ' . str_repeat('a', Config::MAX_NAME_LENGTH) . '. exceeds maximum allowed length of ' . Config::MAX_NAME_LENGTH . ' characters.', ], ]; - // Name must not contain : ? * < > " ' / \ + // Name must not contain ":", "?", "*", "<", ">", """, "'", "/", or "\". foreach ([':', '?', '*', '<', '>', '"', "'", '/', '\\'] as $char) { $name = 'name.' . $char; $return[] = [ diff --git a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php index 2e8125f331d..e99ce613883 100644 --- a/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/ContentEntityBaseUnitTest.php @@ -660,7 +660,7 @@ class ContentEntityBaseUnitTest extends UnitTestCase { * @covers ::set */ public function testSet(): void { - // Exercise set(), check if it returns $this + // Exercise set(), check if it returns $this. $this->assertSame( $this->entity, $this->entity->set('id', 0) diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php index af2743a8072..4bb5c1f1ec3 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityFieldManagerTest.php @@ -280,7 +280,7 @@ class EntityFieldManagerTest extends UnitTestCase { $this->assertSame($expected, $this->entityFieldManager->getFieldDefinitions('test_entity_type', 'test_entity_bundle')); // Test that base fields and bundle fields from the bundle class and - // entity class are retrieved + // entity class are retrieved. $expected = [ 'id' => $field_definition, 'some_extra_field' => $bundle_fields['the_entity_id']['test_entity_bundle_class']['some_extra_field'], @@ -620,11 +620,11 @@ class EntityFieldManagerTest extends UnitTestCase { $storage->loadMultiple(Argument::type('array'))->willReturn([]); // By default, make the storage entity class lookup return the - // EntityTypeManagerTestEntity class + // EntityTypeManagerTestEntity class. $storage->getEntityClass(NULL)->willReturn(EntityTypeManagerTestEntity::class); $storage->getEntityClass(Argument::type('string'))->willReturn(EntityTypeManagerTestEntity::class); // When using the "test_entity_bundle_class" bundle, return the - // EntityTypeManagerTestEntityBundle class + // EntityTypeManagerTestEntityBundle class. $storage->getEntityClass('test_entity_bundle_class')->willReturn(EntityTypeManagerTestEntityBundle::class); $this->entityTypeManager->getStorage('test_entity_type')->willReturn($storage->reveal()); diff --git a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php index 2381b64b83a..9dbc2308b2d 100644 --- a/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/KeyValueStore/KeyValueEntityStorageTest.php @@ -610,7 +610,7 @@ class KeyValueEntityStorageTest extends UnitTestCase { */ protected function getMockEntity(string $class = EntityBaseTest::class, array $arguments = [], array $methods = []): EntityInterface&MockObject { // Ensure the entity is passed at least an array of values and an entity - // type ID + // type ID. if (!isset($arguments[0])) { $arguments[0] = []; } diff --git a/core/tests/Drupal/Tests/Core/Form/ConfigTargetTest.php b/core/tests/Drupal/Tests/Core/Form/ConfigTargetTest.php index 5c7ad53788d..73acc7f5ade 100644 --- a/core/tests/Drupal/Tests/Core/Form/ConfigTargetTest.php +++ b/core/tests/Drupal/Tests/Core/Form/ConfigTargetTest.php @@ -357,7 +357,7 @@ class ConfigTargetTest extends UnitTestCase { 'second', ], // In case of multiple targets, the return value must be an array with the - // keys matching + // keys matching. // @see ::testMultiTarget() fromConfig: fn (int $first, int $second): string => "$first|$second", toConfig: fn (): mixed => $toConfigReturnValue, diff --git a/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php b/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php index 887aa67098b..06629fdc6ff 100644 --- a/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php +++ b/core/tests/Drupal/Tests/Core/Menu/StaticMenuLinkOverridesTest.php @@ -53,7 +53,7 @@ class StaticMenuLinkOverridesTest extends UnitTestCase { $data[] = [['test1' => ['parent' => 'test0']], 'test1', ['parent' => 'test0']]; // Non existing ID. $data[] = [['test1' => ['parent' => 'test0']], 'test2', []]; - // Ensure that the ID is encoded properly + // Ensure that the ID is encoded properly. $data[] = [['test1__la___ma' => ['parent' => 'test0']], 'test1.la__ma', ['parent' => 'test0']]; return $data; diff --git a/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php b/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php index 91e21361a0f..6685372e507 100644 --- a/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php +++ b/core/tests/Drupal/Tests/Core/Render/RendererBubblingTest.php @@ -535,7 +535,7 @@ class RendererBubblingTest extends RendererTestBase { $this->setUpRequest(); $this->setUpMemoryCache(); - // Ensure a logic exception + // Ensure a logic exception. $data = [ '#cache' => [ 'keys' => ['llama', 'bar'], diff --git a/core/tests/Drupal/Tests/Core/Routing/RedirectDestinationTest.php b/core/tests/Drupal/Tests/Core/Routing/RedirectDestinationTest.php index 60a7e0c9573..f19eb9541e9 100644 --- a/core/tests/Drupal/Tests/Core/Routing/RedirectDestinationTest.php +++ b/core/tests/Drupal/Tests/Core/Routing/RedirectDestinationTest.php @@ -104,7 +104,7 @@ class RedirectDestinationTest extends UnitTestCase { // A request with a destination query. $data[] = [$request, '/example']; - // A request without a destination query, + // A request without a destination query. $request = Request::create('/'); $data[] = [$request, '/current-path']; diff --git a/core/tests/Drupal/Tests/Core/StringTranslation/ByteSizeMarkupTest.php b/core/tests/Drupal/Tests/Core/StringTranslation/ByteSizeMarkupTest.php index 8f597af977f..3a3287c357a 100644 --- a/core/tests/Drupal/Tests/Core/StringTranslation/ByteSizeMarkupTest.php +++ b/core/tests/Drupal/Tests/Core/StringTranslation/ByteSizeMarkupTest.php @@ -51,15 +51,15 @@ class ByteSizeMarkupTest extends UnitTestCase { ['1 ZB', pow($kb, 7)], ['1 YB', pow($kb, 8)], ['1024 YB', pow($kb, 9)], - // Rounded to 1 MB - not 1000 or 1024 kilobytes + // Rounded to 1 MB - not 1000 or 1024 kilobytes. ['1 MB', ($kb * $kb) - 1], ['-1 MB', -(($kb * $kb) - 1)], - // Decimal Megabytes + // Decimal Megabytes. ['3.46 MB', 3623651], ['3.77 GB', 4053371676], - // Decimal Petabytes + // Decimal Petabytes. ['59.72 PB', 67234178751368124], - // Decimal Yottabytes + // Decimal Yottabytes. ['194.67 YB', 235346823821125814962843827], ]; } diff --git a/core/tests/Drupal/Tests/Core/Test/TestSuiteBaseTest.php b/core/tests/Drupal/Tests/Core/Test/TestSuiteBaseTest.php index db4ccefa9cb..0de9aa85ce9 100644 --- a/core/tests/Drupal/Tests/Core/Test/TestSuiteBaseTest.php +++ b/core/tests/Drupal/Tests/Core/Test/TestSuiteBaseTest.php @@ -15,7 +15,7 @@ class TestSuiteBaseTest extends TestCase { * Tests the assumption that local time is in 'Australia/Sydney'. */ public function testLocalTimeZone(): void { - // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php + // The 'Australia/Sydney' time zone is set in core/tests/bootstrap.php. $this->assertEquals('Australia/Sydney', date_default_timezone_get()); } diff --git a/core/tests/Drupal/Tests/DrupalTestBrowser.php b/core/tests/Drupal/Tests/DrupalTestBrowser.php index 6c9b10b3ff1..663779fde1a 100644 --- a/core/tests/Drupal/Tests/DrupalTestBrowser.php +++ b/core/tests/Drupal/Tests/DrupalTestBrowser.php @@ -94,7 +94,7 @@ class DrupalTestBrowser extends AbstractBrowser { if (str_starts_with($key, 'http-')) { $headers[substr($key, 5)] = $val; } - // CONTENT_* are not prefixed with HTTP_ + // "CONTENT_*" are not prefixed with "HTTP_". elseif (isset($content_headers[$key])) { $headers[$key] = $val; } @@ -134,7 +134,7 @@ class DrupalTestBrowser extends AbstractBrowser { $method = $request->getMethod(); $uri = $request->getUri(); - // Let BrowserKit handle redirects + // Let BrowserKit handle redirects. try { $response = $this->getClient()->request($method, $uri, $request_options); } diff --git a/core/themes/claro/css/base/elements.css b/core/themes/claro/css/base/elements.css index 4223e540085..1eca003beb1 100644 --- a/core/themes/claro/css/base/elements.css +++ b/core/themes/claro/css/base/elements.css @@ -194,7 +194,6 @@ ul { margin-block: 0.25em; margin-inline: 1.5em 0; padding-inline-start: 0; - list-style-type: disc; list-style-image: none; } diff --git a/core/themes/claro/css/base/elements.pcss.css b/core/themes/claro/css/base/elements.pcss.css index 746dd678a66..d7af4b70c01 100644 --- a/core/themes/claro/css/base/elements.pcss.css +++ b/core/themes/claro/css/base/elements.pcss.css @@ -158,7 +158,6 @@ ul { margin-block: 0.25em; margin-inline: 1.5em 0; padding-inline-start: 0; - list-style-type: disc; list-style-image: none; } ol { diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine index 7ba1c275c64..d5c57f36cbb 100644 --- a/core/themes/engines/twig/twig.engine +++ b/core/themes/engines/twig/twig.engine @@ -104,7 +104,7 @@ function twig_render_template($template_file, array $variables): string|MarkupIn $output['debug_info'] .= "\n-->"; } } - // Check if the template_file belongs to a custom theme + // Check if the template_file belongs to a custom theme. $template_override_status_output = "BEGIN OUTPUT"; $template_override_suffix_output = "END OUTPUT"; if (str_starts_with($template_file, $variables['directory'])) { diff --git a/core/themes/olivero/css/base/base.css b/core/themes/olivero/css/base/base.css index 1b689ca67da..1b8ca5f6bdb 100644 --- a/core/themes/olivero/css/base/base.css +++ b/core/themes/olivero/css/base/base.css @@ -155,6 +155,5 @@ ul { margin-inline-start: 1.5em; margin-inline-end: 0; padding-inline-start: 0; - list-style-type: disc; list-style-image: none; } diff --git a/core/themes/olivero/css/base/base.pcss.css b/core/themes/olivero/css/base/base.pcss.css index 69a24cf9ede..c8d0d70d405 100644 --- a/core/themes/olivero/css/base/base.pcss.css +++ b/core/themes/olivero/css/base/base.pcss.css @@ -137,6 +137,5 @@ ul { margin-inline-start: 1.5em; margin-inline-end: 0; padding-inline-start: 0; - list-style-type: disc; list-style-image: none; } diff --git a/core/themes/olivero/olivero.theme b/core/themes/olivero/olivero.theme index 479a45aeec0..717dc58f504 100644 --- a/core/themes/olivero/olivero.theme +++ b/core/themes/olivero/olivero.theme @@ -22,7 +22,7 @@ function olivero_preprocess_html(&$variables): void { $variables['attributes']['class'][] = 'is-always-mobile-nav'; } - // Convert custom hex to hsl so we can use the hue value + // Convert custom hex to hsl so we can use the hue value. $brand_color_hex = theme_get_setting('base_primary_color') ?? '#1b9ae4'; [$h, $s, $l] = _olivero_hex_to_hsl($brand_color_hex); |