From a103dcc755aa335f8270ed7ae783ccbd3ca4ee4e Mon Sep 17 00:00:00 2001 From: "lee.5151" <lee.5151@osu.edu> Date: Mon, 8 Jul 2024 11:21:19 -0400 Subject: [PATCH] Upgrading drupal/scheduler (2.0.3 => 2.0.4) --- composer.json | 2 +- composer.lock | 16 +-- vendor/composer/installed.json | 16 +-- vendor/composer/installed.php | 10 +- web/modules/scheduler/.eslintignore | 7 +- web/modules/scheduler/.eslintrc.json | 13 -- web/modules/scheduler/.gitlab-ci.yml | 38 ++--- .../scheduler/js/scheduler_default_time.js | 46 +++--- .../scheduler/js/scheduler_default_time_8x.js | 44 +++--- .../scheduler/js/scheduler_vertical_tabs.js | 61 ++++---- .../scheduler/phpstan-baseline-to-fix.neon | 9 -- web/modules/scheduler/scheduler.info.yml | 6 +- .../scheduler_rules_integration.info.yml | 6 +- .../TimestampDatetimeNoDefaultWidget.php | 4 +- .../scheduler/src/SchedulerManager.php | 5 +- .../scheduler/src/SchedulerPluginManager.php | 4 +- .../scheduler_access_test.info.yml | 6 +- .../scheduler_api_legacy_test.info.yml | 6 +- .../scheduler_api_test.info.yml | 6 +- .../scheduler_extras.info.yml | 6 +- .../Functional/SchedulerTokenReplaceTest.php | 10 +- .../Functional/SchedulerViewsAccessTest.php | 14 ++ .../SchedulerJavascriptDefaultTimeTest.php | 4 +- .../SchedulerJavascriptTestBase.php | 35 ++++- .../SchedulerJavascriptVerticalTabsTest.php | 132 ++++++++++++++++++ 25 files changed, 351 insertions(+), 155 deletions(-) delete mode 100644 web/modules/scheduler/.eslintrc.json create mode 100644 web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptVerticalTabsTest.php diff --git a/composer.json b/composer.json index 207f844929..ab5058a338 100644 --- a/composer.json +++ b/composer.json @@ -145,7 +145,7 @@ "drupal/recaptcha_v3": "^2.0", "drupal/redirect": "^1.8", "drupal/roleassign": "2.0.2", - "drupal/scheduler": "2.0.3", + "drupal/scheduler": "2.0.4", "drupal/simple_gmap": "3.1.0", "drupal/simple_sitemap": "4.1.9", "drupal/smtp": "1.2", diff --git a/composer.lock b/composer.lock index 489f06f8ad..3d96c833a2 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "7d237beef02700d6a2f5d3ab090f6792", + "content-hash": "99dc24e60634b6d9442ce25eb8d4c8f1", "packages": [ { "name": "algolia/places", @@ -5436,17 +5436,17 @@ }, { "name": "drupal/scheduler", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://git.drupalcode.org/project/scheduler.git", - "reference": "2.0.3" + "reference": "2.0.4" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/scheduler-2.0.3.zip", - "reference": "2.0.3", - "shasum": "1ef7a92afcb8e138cf697dc35f15cbc2353801b4" + "url": "https://ftp.drupal.org/files/projects/scheduler-2.0.4.zip", + "reference": "2.0.4", + "shasum": "50ee56a90243363453dcdeeaf96dbd6cbec9b7c8" }, "require": { "drupal/core": "^8 || ^9 || ^10" @@ -5462,8 +5462,8 @@ "type": "drupal-module", "extra": { "drupal": { - "version": "2.0.3", - "datestamp": "1714312557", + "version": "2.0.4", + "datestamp": "1719580022", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 9322661462..c47b110063 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -5703,18 +5703,18 @@ }, { "name": "drupal/scheduler", - "version": "2.0.3", - "version_normalized": "2.0.3.0", + "version": "2.0.4", + "version_normalized": "2.0.4.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/scheduler.git", - "reference": "2.0.3" + "reference": "2.0.4" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/scheduler-2.0.3.zip", - "reference": "2.0.3", - "shasum": "1ef7a92afcb8e138cf697dc35f15cbc2353801b4" + "url": "https://ftp.drupal.org/files/projects/scheduler-2.0.4.zip", + "reference": "2.0.4", + "shasum": "50ee56a90243363453dcdeeaf96dbd6cbec9b7c8" }, "require": { "drupal/core": "^8 || ^9 || ^10" @@ -5730,8 +5730,8 @@ "type": "drupal-module", "extra": { "drupal": { - "version": "2.0.3", - "datestamp": "1714312557", + "version": "2.0.4", + "datestamp": "1719580022", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 37d2303980..7e5fda48c0 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'osu-asc-webservices/d8-upstream', 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => 'd2f29e21f9b833a6bd43863efaf810f305055609', + 'reference' => '6877cfc0e77a628513ba677a59cf65fa63a22872', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -980,9 +980,9 @@ 'dev_requirement' => false, ), 'drupal/scheduler' => array( - 'pretty_version' => '2.0.3', - 'version' => '2.0.3.0', - 'reference' => '2.0.3', + 'pretty_version' => '2.0.4', + 'version' => '2.0.4.0', + 'reference' => '2.0.4', 'type' => 'drupal-module', 'install_path' => __DIR__ . '/../../web/modules/scheduler', 'aliases' => array(), @@ -1519,7 +1519,7 @@ 'osu-asc-webservices/d8-upstream' => array( 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => 'd2f29e21f9b833a6bd43863efaf810f305055609', + 'reference' => '6877cfc0e77a628513ba677a59cf65fa63a22872', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/web/modules/scheduler/.eslintignore b/web/modules/scheduler/.eslintignore index 14313bdae6..0da6c5f6f7 100644 --- a/web/modules/scheduler/.eslintignore +++ b/web/modules/scheduler/.eslintignore @@ -1,6 +1,7 @@ -# These files fail eslint standards. If possible they may be fixed in due course -# then removed from this ignore file. -# See https://www.drupal.org/project/scheduler/issues/3314451 +# These files have been fixed on the Gitlab Templates ESLint job, which uses a better config. +# However, this config is not used in DrupalCI so the files still need to be ignored. +# This .eslintignore file is deleted in the pipeline before ESLint is run, so that the files are not ignored there. +# See https://www.drupal.org/project/scheduler/issues/3432976 js/scheduler_default_time.js js/scheduler_default_time_8x.js diff --git a/web/modules/scheduler/.eslintrc.json b/web/modules/scheduler/.eslintrc.json deleted file mode 100644 index 5cdd8fcf9f..0000000000 --- a/web/modules/scheduler/.eslintrc.json +++ /dev/null @@ -1,13 +0,0 @@ -// This file does not strictly need to exist in contrib, because eslint config -// files placed futher up in the directory structure will be merged and -// inherited. The top-level .eslintrc.json extends ./core/.eslintrc.json. -// -// However, this file is added for two reasons: -// (a) Drupalci eslint does not have a 'sniff all files' argument, but making a -// change to this file will cause all js and yml files to be checked. -// See https://www.drupal.org/project/scheduler/issues/3314451 -// (b) If a patch has changes to .yml files but no changes to .js files then -// eslint is not executed allowing a .yml fault to be missed. Making a -// temporary change to this file will cause the modified .yml to be checked. -// See https://www.drupal.org/project/drupalci_testbot/issues/3333051 -{} diff --git a/web/modules/scheduler/.gitlab-ci.yml b/web/modules/scheduler/.gitlab-ci.yml index 28f84cc9b0..8b4a33f653 100644 --- a/web/modules/scheduler/.gitlab-ci.yml +++ b/web/modules/scheduler/.gitlab-ci.yml @@ -16,11 +16,11 @@ include: ################ variables: OPT_IN_TEST_CURRENT: 1 + OPT_IN_TEST_MAX_PHP: 1 OPT_IN_TEST_NEXT_MINOR: 1 OPT_IN_TEST_NEXT_MAJOR: 1 OPT_IN_TEST_PREVIOUS_MINOR: 1 OPT_IN_TEST_PREVIOUS_MAJOR: 1 - OPT_IN_TEST_MAX_PHP: 1 _SHOW_ENVIRONMENT_VARIABLES: 1 _PHPUNIT_CONCURRENT: 1 @@ -36,6 +36,7 @@ variables: printf "CI_DEFAULT_BRANCH = %s\n" $CI_DEFAULT_BRANCH && printf "CI_COMMIT_BRANCH = %s\n" $CI_COMMIT_BRANCH && printf "CI_COMMIT_TAG = %s\n" $CI_COMMIT_TAG && + printf "CI_COMMIT_TITLE = %s\n" "$CI_COMMIT_TITLE" && printf "CI_MERGE_REQUEST_IID = %s\n" $CI_MERGE_REQUEST_IID && printf "CI_MERGE_REQUEST_TITLE = %s\n" "$CI_MERGE_REQUEST_TITLE" && printf "CI_PROJECT_ROOT_NAMESPACE = %s\n" $CI_PROJECT_ROOT_NAMESPACE && @@ -43,23 +44,29 @@ variables: printf "CI_PROJECT_NAME = %s\n" $CI_PROJECT_NAME && printf "CI_JOB_NAME = %s\n" "$CI_JOB_NAME" && printf "CI_JOB_NAME chopped = %s\n" "${CI_JOB_NAME%:*}" && + printf "DRUPAL_CORE = %s\n" $DRUPAL_CORE && + printf "PHP_VERSION = %s\n" $PHP_VERSION && printf "MODULE_NAME = %s\n" $MODULE_NAME # -------------------------------- BUILD --------------------------------------- .composer-base: after_script: + # Delete the .eslintignore file, it is only required for DrupalCI + # @todo remove the file and this delete when no longer running DrupalCI + - rm $CI_PROJECT_DIR/$_WEB_ROOT/modules/custom/$CI_PROJECT_NAME/.eslintignore || true # Show the last two commits. Current directory /builds/project/scheduler ($CI_PROJECT_DIR) is correct. - git show -2 --stat --oneline + - *show-variables composer (max PHP version): + # Using when: manual needs 'allow failure: true' otherwise the overall pipeline status shows 'blocked' rules: - !reference [ .opt-in-max-php-rule ] - when: manual allow_failure: true composer (previous minor): - # Using when: manual needs 'allow failure: true' otherwise the overall pipeline status shows 'blocked' rules: - !reference [ .opt-in-previous-minor-rule ] - when: manual @@ -83,6 +90,10 @@ composer (next major): eslint: allow_failure: false + after_script: + - cd $CI_PROJECT_DIR/$_WEB_ROOT/modules/custom/$CI_PROJECT_NAME + - test -f .eslintignore && echo "=== This is .eslintignore ===" && cat .eslintignore || true + - test -f .prettierignore && echo "=== This is .prettierignore ===" && cat .prettierignore || true stylelint: allow_failure: false @@ -95,19 +106,13 @@ phpstan: - test -f phpstan.neon && echo "=== This is phpstan.neon ===" && cat phpstan.neon - php $CI_PROJECT_DIR/scripts/phpstan-baseline-summary.php phpstan-baseline-to-fix.neon -# Do not automatically run, but allow the jobs to be started manually. +# Do not automatically run 'next minor', but allow it to be started manually. phpstan (next minor): rules: - !reference [ .opt-in-next-minor-rule ] - !reference [ .skip-phpstan-rule ] - when: manual -phpstan (next major): - rules: - - !reference [ .opt-in-next-major-rule ] - - !reference [ .skip-phpstan-rule ] - - when: manual - # -------------------------------- TEST ---------------------------------------- phpunit: @@ -144,23 +149,22 @@ phpunit: fi - echo "End of before_script _PHPUNIT_CONCURRENT=$_PHPUNIT_CONCURRENT _PHPUNIT_EXTRA=$_PHPUNIT_EXTRA" +# Do not automatically run 'next minor' PHPUnit but allow it to be started +# manually. To do this the .phpunit-tests-exist-rule has to be removed. +# The other variants all have 'manual' on the Composer job instead. phpunit (next minor): allow_failure: true rules: - !reference [ .opt-in-next-minor-rule ] - !reference [ .skip-phpunit-rule ] - # Do not automatically run, but allow the job to be started manually. - # To do this the .phpunit-tests-exist-rule has to be removed. - when: manual variables: - # Use core ignoreFile to show deprecations. + # Use core ignoreFile to show deprecations. This is only used when $_PHPUNIT_CONCURRENT=1 so make sure that is also set. + _PHPUNIT_CONCURRENT: 1 SYMFONY_DEPRECATIONS_HELPER: "ignoreFile=$CI_PROJECT_DIR/$_WEB_ROOT/core/.deprecation-ignore.txt" phpunit (next major): - rules: - - !reference [ .opt-in-next-major-rule ] - - !reference [ .skip-phpunit-rule ] - - when: manual variables: - # Use core ignoreFile to show deprecations. + # Use core ignoreFile to show deprecations. This is only used when $_PHPUNIT_CONCURRENT=1 so make sure that is also set. + _PHPUNIT_CONCURRENT: 1 SYMFONY_DEPRECATIONS_HELPER: "ignoreFile=$CI_PROJECT_DIR/$_WEB_ROOT/core/.deprecation-ignore.txt" diff --git a/web/modules/scheduler/js/scheduler_default_time.js b/web/modules/scheduler/js/scheduler_default_time.js index c1b90e3a7b..6510938ed4 100644 --- a/web/modules/scheduler/js/scheduler_default_time.js +++ b/web/modules/scheduler/js/scheduler_default_time.js @@ -4,9 +4,6 @@ */ (function ($, drupalSettings, once) { - - 'use strict'; - /** * Provide default time if schedulerDefaultTime is set. * @@ -17,19 +14,25 @@ * @see https://www.drupal.org/project/scheduler/issues/2913829 */ Drupal.behaviors.setSchedulerDefaultTime = { - attach: function (context) { - + attach(context) { // Drupal.behaviors are called many times per page. Using .once() adds the // class onto the matched DOM element and uses this to prevent it running // on subsequent calls. - const $default_time = once('default-time-done', '#edit-scheduler-settings', context); + const $defaultTime = once( + 'default-time-done', + '#edit-scheduler-settings', + context, + ); - if ($default_time.length && typeof drupalSettings.schedulerDefaultTime !== "undefined") { - var operations = ["publish", "unpublish"]; + if ( + $defaultTime.length && + typeof drupalSettings.schedulerDefaultTime !== 'undefined' + ) { + const operations = ['publish', 'unpublish']; operations.forEach(function (value) { - var element = $("input#edit-" + value + "-on-0-value-time", context); + const element = $(`input#edit-${value}-on-0-value-time`, context); // Only set the time when there is no value and the field is required. - if (element.val() === "" && element.prop("required")) { + if (element.val() === '' && element.prop('required')) { element.val(drupalSettings.schedulerDefaultTime); } }); @@ -38,15 +41,22 @@ // Also use this jQuery behaviors function to set any pre-existing time // values with seconds removed if those drupalSettings values exist. This // is required by some browsers to make the seconds hidden. - if (typeof drupalSettings.schedulerHideSecondsPublishOn !== "undefined") { - var element = $("input#edit-publish-on-0-value-time", context); - element.val(drupalSettings.schedulerHideSecondsPublishOn); + if (typeof drupalSettings.schedulerHideSecondsPublishOn !== 'undefined') { + const elementPublishOn = $( + 'input#edit-publish-on-0-value-time', + context, + ); + elementPublishOn.val(drupalSettings.schedulerHideSecondsPublishOn); } - if (typeof drupalSettings.schedulerHideSecondsUnpublishOn !== "undefined") { - var element = $("input#edit-unpublish-on-0-value-time", context); - element.val(drupalSettings.schedulerHideSecondsUnpublishOn); + if ( + typeof drupalSettings.schedulerHideSecondsUnpublishOn !== 'undefined' + ) { + const elementUnpublishOn = $( + 'input#edit-unpublish-on-0-value-time', + context, + ); + elementUnpublishOn.val(drupalSettings.schedulerHideSecondsUnpublishOn); } - - } + }, }; })(jQuery, drupalSettings, once); diff --git a/web/modules/scheduler/js/scheduler_default_time_8x.js b/web/modules/scheduler/js/scheduler_default_time_8x.js index 7e2363f1e2..3b00f0da1e 100644 --- a/web/modules/scheduler/js/scheduler_default_time_8x.js +++ b/web/modules/scheduler/js/scheduler_default_time_8x.js @@ -6,9 +6,6 @@ */ (function ($, drupalSettings) { - - 'use strict'; - /** * Provide default time if schedulerDefaultTime is set. * @@ -19,19 +16,23 @@ * @see https://www.drupal.org/project/scheduler/issues/2913829 */ Drupal.behaviors.setSchedulerDefaultTime = { - attach: function (context) { - + attach(context) { // Drupal.behaviors are called many times per page. Using .once() adds the // class onto the matched DOM element and uses this to prevent it running // on subsequent calls. - const $default_time = $(context).find('#edit-scheduler-settings').once('default-time-done'); + const $defaultTime = $(context) + .find('#edit-scheduler-settings') + .once('default-time-done'); - if ($default_time.length && typeof drupalSettings.schedulerDefaultTime !== "undefined") { - var operations = ["publish", "unpublish"]; + if ( + $defaultTime.length && + typeof drupalSettings.schedulerDefaultTime !== 'undefined' + ) { + const operations = ['publish', 'unpublish']; operations.forEach(function (value) { - var element = $("input#edit-" + value + "-on-0-value-time", context); + const element = $(`input#edit-${value}-on-0-value-time`, context); // Only set the time when there is no value and the field is required. - if (element.val() === "" && element.prop("required")) { + if (element.val() === '' && element.prop('required')) { element.val(drupalSettings.schedulerDefaultTime); } }); @@ -40,15 +41,22 @@ // Also use this jQuery behaviors function to set any pre-existing time // values with seconds removed if those drupalSettings values exist. This // is required by some browsers to make the seconds hidden. - if (typeof drupalSettings.schedulerHideSecondsPublishOn !== "undefined") { - var element = $("input#edit-publish-on-0-value-time", context); - element.val(drupalSettings.schedulerHideSecondsPublishOn); + if (typeof drupalSettings.schedulerHideSecondsPublishOn !== 'undefined') { + const elementPublishOn = $( + 'input#edit-publish-on-0-value-time', + context, + ); + elementPublishOn.val(drupalSettings.schedulerHideSecondsPublishOn); } - if (typeof drupalSettings.schedulerHideSecondsUnpublishOn !== "undefined") { - var element = $("input#edit-unpublish-on-0-value-time", context); - element.val(drupalSettings.schedulerHideSecondsUnpublishOn); + if ( + typeof drupalSettings.schedulerHideSecondsUnpublishOn !== 'undefined' + ) { + const elementUnpublishOn = $( + 'input#edit-unpublish-on-0-value-time', + context, + ); + elementUnpublishOn.val(drupalSettings.schedulerHideSecondsUnpublishOn); } - - } + }, }; })(jQuery, drupalSettings); diff --git a/web/modules/scheduler/js/scheduler_vertical_tabs.js b/web/modules/scheduler/js/scheduler_vertical_tabs.js index 1d46bc0fbb..99d35be8c1 100644 --- a/web/modules/scheduler/js/scheduler_vertical_tabs.js +++ b/web/modules/scheduler/js/scheduler_vertical_tabs.js @@ -4,42 +4,53 @@ */ (function ($) { - - 'use strict'; - /** * Provide summary information for vertical tabs. */ Drupal.behaviors.scheduler_settings = { - attach: function (context) { + attach(context) { + // Provide summary when editing an entity. This is only applicable to + // themes that provide vertical tabs or modal details blocks with a + // summary area, such as Bartik or Claro. It does nothing in Stark. + $('details#edit-scheduler-settings', context).drupalSetSummary( + function (context) { + const publishOn = document.querySelector( + '#edit-publish-on-0-value-date', + ); + const unpublishOn = document.querySelector( + '#edit-unpublish-on-0-value-date', + ); + const values = []; + if (publishOn.value) { + values.push(Drupal.t('Scheduled for publishing')); + } + if (unpublishOn.value) { + values.push(Drupal.t('Scheduled for unpublishing')); + } + if (!values.length) { + values.push(Drupal.t('Not scheduled')); + } + return values.join('<br/>'); + }, + ); - // Provide summary when editing a node. - $('details#edit-scheduler-settings', context).drupalSetSummary(function (context) { - var values = []; - if ($('#edit-publish-on-0-value-date').val()) { - values.push(Drupal.t('Scheduled for publishing')); - } - if ($('#edit-unpublish-on-0-value-date').val()) { - values.push(Drupal.t('Scheduled for unpublishing')); - } - if (!values.length) { - values.push(Drupal.t('Not scheduled')); - } - return values.join('<br/>'); - }); - - // Provide summary during content type configuration. + // Provide summary during entity type configuration. $('#edit-scheduler', context).drupalSetSummary(function (context) { - var values = []; - if ($('#edit-scheduler-publish-enable', context).is(':checked')) { + const publishingEnabled = document.querySelector( + '#edit-scheduler-publish-enable', + ); + const unpublishingEnabled = document.querySelector( + '#edit-scheduler-unpublish-enable', + ); + const values = []; + if (publishingEnabled.matches(':checked')) { values.push(Drupal.t('Publishing enabled')); } - if ($('#edit-scheduler-unpublish-enable', context).is(':checked')) { + if (unpublishingEnabled.matches(':checked')) { values.push(Drupal.t('Unpublishing enabled')); } return values.join('<br/>'); }); - } + }, }; - })(jQuery); diff --git a/web/modules/scheduler/phpstan-baseline-to-fix.neon b/web/modules/scheduler/phpstan-baseline-to-fix.neon index 05e597383b..d4c262a8f3 100644 --- a/web/modules/scheduler/phpstan-baseline-to-fix.neon +++ b/web/modules/scheduler/phpstan-baseline-to-fix.neon @@ -55,15 +55,6 @@ parameters: count: 1 path: src/Routing/SchedulerRouteSubscriber.php - - - message: """ - #^Call to deprecated method loadRevision\\(\\) of class Drupal\\\\Core\\\\Entity\\\\EntityStorageInterface\\: - in drupal\\:10\\.1\\.0 and is removed from drupal\\:11\\.0\\.0\\. Use - \\\\Drupal\\\\Core\\\\Entity\\\\RevisionableStorageInterface\\:\\:loadRevision instead\\.$# - """ - count: 1 - path: src/SchedulerManager.php - - message: "#^\\\\Drupal calls should be avoided in classes, use dependency injection instead$#" count: 17 diff --git a/web/modules/scheduler/scheduler.info.yml b/web/modules/scheduler/scheduler.info.yml index 5fdeb2d309..674ef1f1a8 100644 --- a/web/modules/scheduler/scheduler.info.yml +++ b/web/modules/scheduler/scheduler.info.yml @@ -20,7 +20,7 @@ libraries: - vertical-tabs - default-time -# Information added by Drupal.org packaging script on 2024-04-28 -version: '2.0.3' +# Information added by Drupal.org packaging script on 2024-06-28 +version: '2.0.4' project: 'scheduler' -datestamp: 1714312560 +datestamp: 1719579867 diff --git a/web/modules/scheduler/scheduler_rules_integration/scheduler_rules_integration.info.yml b/web/modules/scheduler/scheduler_rules_integration/scheduler_rules_integration.info.yml index ae2230263d..2640f13cb2 100644 --- a/web/modules/scheduler/scheduler_rules_integration/scheduler_rules_integration.info.yml +++ b/web/modules/scheduler/scheduler_rules_integration/scheduler_rules_integration.info.yml @@ -6,7 +6,7 @@ dependencies: - rules:rules - scheduler:scheduler -# Information added by Drupal.org packaging script on 2024-04-28 -version: '2.0.3' +# Information added by Drupal.org packaging script on 2024-06-28 +version: '2.0.4' project: 'scheduler' -datestamp: 1714312560 +datestamp: 1719579867 diff --git a/web/modules/scheduler/src/Plugin/Field/FieldWidget/TimestampDatetimeNoDefaultWidget.php b/web/modules/scheduler/src/Plugin/Field/FieldWidget/TimestampDatetimeNoDefaultWidget.php index 2c62a1ed0d..31aa7dc5b6 100644 --- a/web/modules/scheduler/src/Plugin/Field/FieldWidget/TimestampDatetimeNoDefaultWidget.php +++ b/web/modules/scheduler/src/Plugin/Field/FieldWidget/TimestampDatetimeNoDefaultWidget.php @@ -40,7 +40,9 @@ public function __construct( FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, - $scheduler_settings, + // Trailing comma is incompatible with PHPUnit 9.6.19 in Drupal 9.5 PHP 7.4. + // phpcs:ignore Drupal.Functions.MultiLineFunctionDeclaration.MissingTrailingComma + $scheduler_settings ) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); $this->schedulerSettings = $scheduler_settings; diff --git a/web/modules/scheduler/src/SchedulerManager.php b/web/modules/scheduler/src/SchedulerManager.php index 9efd36bd41..71ae13aa29 100644 --- a/web/modules/scheduler/src/SchedulerManager.php +++ b/web/modules/scheduler/src/SchedulerManager.php @@ -103,7 +103,9 @@ public function __construct( EventDispatcherInterface $eventDispatcher, TimeInterface $time, EntityFieldManagerInterface $entityFieldManager, - SchedulerPluginManager $pluginManager, + // Trailing comma is incompatible with PHPUnit 9.6.19 in Drupal 9.5 PHP 7.4. + // phpcs:ignore Drupal.Functions.MultiLineFunctionDeclaration.MissingTrailingComma + SchedulerPluginManager $pluginManager ) { $this->dateFormatter = $dateFormatter; $this->logger = $logger; @@ -908,6 +910,7 @@ public function getThirdPartySetting(EntityInterface $entity, $setting, $default * Array of loaded entity objects, keyed by id. */ protected function loadEntities(array $ids, string $type) { + /** @var \Drupal\Core\Entity\RevisionableStorageInterface $storage */ $storage = $this->entityTypeManager->getStorage($type); $entities = []; foreach ($ids as $id) { diff --git a/web/modules/scheduler/src/SchedulerPluginManager.php b/web/modules/scheduler/src/SchedulerPluginManager.php index f138358e49..0823abe671 100644 --- a/web/modules/scheduler/src/SchedulerPluginManager.php +++ b/web/modules/scheduler/src/SchedulerPluginManager.php @@ -29,7 +29,9 @@ public function __construct( \Traversable $namespaces, CacheBackendInterface $cacheBackend, ModuleHandlerInterface $module_handler, - EntityTypeManagerInterface $entity_type_manager, + // Trailing comma is incompatible with PHPUnit 9.6.19 in Drupal 9.5 PHP 7.4. + // phpcs:ignore Drupal.Functions.MultiLineFunctionDeclaration.MissingTrailingComma + EntityTypeManagerInterface $entity_type_manager ) { $subdir = 'Plugin/Scheduler'; $plugin_interface = SchedulerPluginInterface::class; diff --git a/web/modules/scheduler/tests/modules/scheduler_access_test/scheduler_access_test.info.yml b/web/modules/scheduler/tests/modules/scheduler_access_test/scheduler_access_test.info.yml index 2be40bda1d..753c4316a1 100644 --- a/web/modules/scheduler/tests/modules/scheduler_access_test/scheduler_access_test.info.yml +++ b/web/modules/scheduler/tests/modules/scheduler_access_test/scheduler_access_test.info.yml @@ -5,7 +5,7 @@ package: Testing dependencies: - scheduler:scheduler -# Information added by Drupal.org packaging script on 2024-04-28 -version: '2.0.3' +# Information added by Drupal.org packaging script on 2024-06-28 +version: '2.0.4' project: 'scheduler' -datestamp: 1714312560 +datestamp: 1719579867 diff --git a/web/modules/scheduler/tests/modules/scheduler_api_test/scheduler_api_legacy_test/scheduler_api_legacy_test.info.yml b/web/modules/scheduler/tests/modules/scheduler_api_test/scheduler_api_legacy_test/scheduler_api_legacy_test.info.yml index 74b94fe764..998ab7baf9 100644 --- a/web/modules/scheduler/tests/modules/scheduler_api_test/scheduler_api_legacy_test/scheduler_api_legacy_test.info.yml +++ b/web/modules/scheduler/tests/modules/scheduler_api_test/scheduler_api_legacy_test/scheduler_api_legacy_test.info.yml @@ -6,7 +6,7 @@ dependencies: - scheduler:scheduler - scheduler_api_test:scheduler_api_test -# Information added by Drupal.org packaging script on 2024-04-28 -version: '2.0.3' +# Information added by Drupal.org packaging script on 2024-06-28 +version: '2.0.4' project: 'scheduler' -datestamp: 1714312560 +datestamp: 1719579867 diff --git a/web/modules/scheduler/tests/modules/scheduler_api_test/scheduler_api_test.info.yml b/web/modules/scheduler/tests/modules/scheduler_api_test/scheduler_api_test.info.yml index 484ca81d5a..783788c263 100644 --- a/web/modules/scheduler/tests/modules/scheduler_api_test/scheduler_api_test.info.yml +++ b/web/modules/scheduler/tests/modules/scheduler_api_test/scheduler_api_test.info.yml @@ -6,7 +6,7 @@ dependencies: - scheduler:scheduler - drupal:media -# Information added by Drupal.org packaging script on 2024-04-28 -version: '2.0.3' +# Information added by Drupal.org packaging script on 2024-06-28 +version: '2.0.4' project: 'scheduler' -datestamp: 1714312560 +datestamp: 1719579867 diff --git a/web/modules/scheduler/tests/modules/scheduler_extras/scheduler_extras.info.yml b/web/modules/scheduler/tests/modules/scheduler_extras/scheduler_extras.info.yml index e54b693e8b..71f2bddae9 100644 --- a/web/modules/scheduler/tests/modules/scheduler_extras/scheduler_extras.info.yml +++ b/web/modules/scheduler/tests/modules/scheduler_extras/scheduler_extras.info.yml @@ -5,7 +5,7 @@ package: Testing dependencies: - scheduler:scheduler -# Information added by Drupal.org packaging script on 2024-04-28 -version: '2.0.3' +# Information added by Drupal.org packaging script on 2024-06-28 +version: '2.0.4' project: 'scheduler' -datestamp: 1714312560 +datestamp: 1719579867 diff --git a/web/modules/scheduler/tests/src/Functional/SchedulerTokenReplaceTest.php b/web/modules/scheduler/tests/src/Functional/SchedulerTokenReplaceTest.php index bb666c641c..b6397224a8 100644 --- a/web/modules/scheduler/tests/src/Functional/SchedulerTokenReplaceTest.php +++ b/web/modules/scheduler/tests/src/Functional/SchedulerTokenReplaceTest.php @@ -80,13 +80,12 @@ public function testSchedulerTokenReplacement($entityTypeId, $bundle) { * @dataProvider dataSchedulerWithoutTokenModule() */ public function testSchedulerWithoutTokenModule($entityTypeId, $bundle) { - // This test is not run for commerce products because that module requires - // the token module, so it has to be uninstalled too. - $this->container->get('module_installer')->uninstall(['commerce_product']); - $this->container->get('module_installer')->uninstall(['token']); + // Commerce product requires the token module, so that has to be uninstalled + // also. Using FALSE allows both to be uninstalled in the same call. + $this->container->get('module_installer')->uninstall(['commerce_product', 'token'], FALSE); $this->drupalLogin($this->schedulerUser); - // Check that the entity add page can be accessed successfully, so show that + // Check that the entity add page can be accessed successfully, to show that // the token.entity_mapper service is avoided when not available. $this->drupalGet($this->entityAddUrl($entityTypeId, $bundle)); $this->assertSession()->statusCodeEquals(200); @@ -115,6 +114,7 @@ public function dataSchedulerTokenReplacement() { public function dataSchedulerWithoutTokenModule() { $data = $this->dataStandardEntityTypes(); unset($data['#commerce_product']); + unset($data['#taxonomy_term']); return $data; } diff --git a/web/modules/scheduler/tests/src/Functional/SchedulerViewsAccessTest.php b/web/modules/scheduler/tests/src/Functional/SchedulerViewsAccessTest.php index a416b84102..03cb44e8b3 100644 --- a/web/modules/scheduler/tests/src/Functional/SchedulerViewsAccessTest.php +++ b/web/modules/scheduler/tests/src/Functional/SchedulerViewsAccessTest.php @@ -165,6 +165,20 @@ public function testViewScheduledContentUser($entityTypeId, $bundle) { $assert->pageTextNotContains("$entityTypeId created by Scheduler Editor for unpublishing"); $assert->pageTextContains("$entityTypeId created by Scheduler Viewer for publishing"); $assert->pageTextContains("$entityTypeId created by Scheduler Viewer for unpublishing"); + + // Access the scheduled tab for the admin user, and check for the 'empty' + // text. This verifies that the uid argument plugin is working. In 10.2 the + // user id shown, but from 10.3+ the user entity is returned so the view + // displays the user name instead. + $this->drupalGet("user/{$this->adminUser->id()}/$url_end"); + $assert->statusCodeEquals(200); + if (version_compare(\Drupal::VERSION, '10.3', '>=')) { + $assert->pageTextMatches("/No scheduled (content|media) for user {$this->adminUser->getDisplayName()}/"); + } + else { + $assert->pageTextMatches("/No scheduled (content|media) for user {$this->adminUser->id()}/"); + } + } /** diff --git a/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptDefaultTimeTest.php b/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptDefaultTimeTest.php index 2c0ae45cd4..40ae8cab51 100644 --- a/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptDefaultTimeTest.php +++ b/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptDefaultTimeTest.php @@ -28,11 +28,12 @@ protected function setUp(): void { // to local testing having a different locale to drupal.org testing. // @see https://www.drupal.org/project/scheduler/issues/2913829 from #18. $this->drupalLogin($this->schedulerUser); + $this->nodetype->setThirdPartySetting('scheduler', 'fields_display_mode', 'fieldset') + ->setThirdPartySetting('scheduler', 'expand_fieldset', 'always')->save(); $this->drupalGet('node/add/' . $this->type); $page = $this->getSession()->getPage(); $title = "Add a {$this->typeName} to determine the date-picker format"; $page->fillField('edit-title-0-value', $title); - $page->clickLink('Scheduling options'); // Set the date using a day and month which could be correctly interpreted // either way. Set the year to be next year to ensure a future date. // Use a time format which includes 'pm' as this may be necessary, and will @@ -41,7 +42,6 @@ protected function setUp(): void { $page->fillField('edit-publish-on-0-value-time', '06:00:00pm'); $page->pressButton('Save'); $node = $this->drupalGetNodeByTitle($title); - $this->drupalGet('node/' . $node->id()); // If the saved month is 2 then the format is d/m/Y, otherwise it is m/d/Y. $this->datepickerFormat = (date('n', $node->publish_on->value) == 2 ? 'd/m/Y' : 'm/d/Y'); } diff --git a/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptTestBase.php b/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptTestBase.php index 9747b39c85..c164ee0784 100644 --- a/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptTestBase.php +++ b/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptTestBase.php @@ -3,6 +3,7 @@ namespace Drupal\Tests\scheduler\FunctionalJavascript; use Drupal\FunctionalJavascriptTests\WebDriverTestBase; +use Drupal\Tests\DocumentElement; use Drupal\Tests\scheduler\Traits\SchedulerCommerceProductSetupTrait; use Drupal\Tests\scheduler\Traits\SchedulerMediaSetupTrait; use Drupal\Tests\scheduler\Traits\SchedulerSetupTrait; @@ -40,9 +41,13 @@ abstract class SchedulerJavascriptTestBase extends WebDriverTestBase { protected $profile = 'testing'; /** - * {@inheritdoc} + * The default theme. + * + * The vertical tabs test needs 'claro' theme not 'stark'. + * + * @var string */ - protected $defaultTheme = 'stark'; + protected $defaultTheme = 'claro'; /** * {@inheritdoc} @@ -73,4 +78,30 @@ protected function flushCache() { $module_handler->invokeAll('cache_flush'); } + /** + * Looks for the specified text and returns TRUE when it is unavailable. + * + * Core JSWebAssert has a function waitForText() but there is no equivalent to + * wait until text is hidden, as there is for some other page elements. + * Therefore define that function here, based on waitForText() in + * core/tests/Drupal/FunctionalJavascriptTests/JSWebAssert.php. + * + * @param string $text + * The text to wait for. + * @param int $timeout + * (Optional) Timeout in milliseconds, defaults to 10000. + * + * @return bool + * TRUE if not found, FALSE if found. + */ + public function waitForNoText($text, $timeout = 10000) { + $page = $this->getSession()->getPage(); + return (bool) $page->waitFor($timeout / 1000, function (DocumentElement $page) use ($text) { + $actual = preg_replace('/\\s+/u', ' ', $page->getText()); + // Negative look-ahead on the text that should be hidden. + $regex = '/^((?!' . preg_quote($text, '/') . ').)*$/ui'; + return (bool) preg_match($regex, $actual); + }); + } + } diff --git a/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptVerticalTabsTest.php b/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptVerticalTabsTest.php new file mode 100644 index 0000000000..47d4c32bd9 --- /dev/null +++ b/web/modules/scheduler/tests/src/FunctionalJavascript/SchedulerJavascriptVerticalTabsTest.php @@ -0,0 +1,132 @@ +<?php + +namespace Drupal\Tests\scheduler\FunctionalJavascript; + +/** + * Tests the JavaScript functionality of vertical tabs summary information. + * + * @group scheduler_js + */ +class SchedulerJavascriptVerticalTabsTest extends SchedulerJavascriptTestBase { + + /** + * Test editing an entity. + * + * @dataProvider dataStandardEntityTypes() + */ + public function testEditEntitySummary($entityTypeId, $bundle) { + $this->drupalLogin($this->schedulerUser); + /** @var \Drupal\Tests\WebAssert $assert */ + $assert = $this->assertSession(); + + // Set the entity edit form to use a vertical tab for the Scheduler dates. + $this->entityTypeObject($entityTypeId) + ->setThirdPartySetting('scheduler', 'fields_display_mode', 'vertical_tab') + ->setThirdPartySetting('scheduler', 'expand_fieldset', 'always')->save(); + $titleField = $this->titleField($entityTypeId); + + // Create an entity with a scheduled publishing date. + $entity = $this->createEntity($entityTypeId, $bundle, [ + 'publish_on' => strtotime('+2 months'), + "$titleField" => "$entityTypeId to publish", + ]); + $this->drupalGet($entity->toUrl('edit-form')); + $assert->pageTextContains('Scheduled for publishing'); + $assert->pageTextNotContains('Scheduled for unpublishing'); + $assert->pageTextNotContains('Not scheduled'); + + // Create an entity with a scheduled unpublishing date. + $entity = $this->createEntity($entityTypeId, $bundle, [ + 'unpublish_on' => strtotime('+3 months'), + "$titleField" => "$entityTypeId to unpublish", + ]); + $this->drupalGet($entity->toUrl('edit-form')); + $assert->pageTextNotContains('Scheduled for publishing'); + $assert->pageTextContains('Scheduled for unpublishing'); + $assert->pageTextNotContains('Not scheduled'); + + // In Claro, Node and Product have a separate vertical "tab" block which is + // always open. Taxonomy Term does not have vertical tabs, only the separate + // fieldset, but this also shows the summary. Media has the old-style block + // with side tabs, so we need to click 'Scheduling options'. + // In Drupal 10.3 the form for editing Taxonomy Terms seemed to change, and + // vertical tabs are implemented in a different way to 10.2. We now need to + // click to bring focus on that tab, ready for filling the date fields. + $page = $this->getSession()->getPage(); + if ($entityTypeId == 'media' || ($entityTypeId == 'taxonomy_term' && version_compare(\Drupal::VERSION, '10.3', '>='))) { + $page->clickLink('Scheduling options'); + } + + $page->fillField('edit-publish-on-0-value-date', '05/02/' . (date('Y') + 1)); + $page->fillField('edit-publish-on-0-value-time', '06:00:00pm'); + $assert->waitForText('Scheduled for publishing'); + $assert->pageTextContains('Scheduled for publishing'); + + // Setting the date and time values to '' only actually removes the first + // component of each of the fields. But this is enough for drupal.behaviors + // to update the summary correctly. + $page->fillField('edit-publish-on-0-value-date', ''); + $page->fillField('edit-publish-on-0-value-time', ''); + $page->fillField('edit-unpublish-on-0-value-date', ''); + $page->fillField('edit-unpublish-on-0-value-time', ''); + $assert->waitForText('Not scheduled'); + $assert->pageTextNotContains('Scheduled for publishing'); + $assert->pageTextNotContains('Scheduled for unpublishing'); + $assert->pageTextContains('Not scheduled'); + } + + /** + * Test configuring an entity type. + * + * @dataProvider dataStandardEntityTypes() + */ + public function testConfigureEntityTypeSummary($entityTypeId, $bundle) { + /** @var \Drupal\Tests\WebAssert $assert */ + $assert = $this->assertSession(); + + $this->drupalLogin($this->adminUser); + $this->drupalGet($this->entityTypeObject($entityTypeId)->toUrl('edit-form')); + + $page = $this->getSession()->getPage(); + if (in_array($entityTypeId, ['node', 'media'])) { + // For node and media bring focus to the Scheduler vertical tab. + $page->clickLink('Scheduler'); + } + else { + // For taxonomy term and product, open the closed modal details block. + $page->pressButton('Scheduler'); + } + + // Both options are enabled by default. + $assert->pageTextContains('Publishing enabled'); + $assert->pageTextContains('Advanced options'); + $assert->pageTextContains('Unpublishing enabled'); + + // Turn off the unpublishing enabled checkbox. + $page->uncheckField('edit-scheduler-unpublish-enable'); + $this->waitForNoText('Unpublishing enabled'); + $assert->pageTextContains('Publishing enabled'); + $assert->pageTextContains('Advanced options'); + $assert->pageTextNotContains('Unpublishing enabled'); + + // Turn off the publishing enabled checkbox. + $page->uncheckField('edit-scheduler-publish-enable'); + $this->waitForNoText('Publishing enabled'); + $assert->pageTextNotContains('Publishing enabled'); + $assert->pageTextNotContains('Advanced options'); + + // Turn on the publishing enabled checkbox. + $page->checkField('edit-scheduler-publish-enable'); + $assert->waitForText('Publishing enabled'); + $assert->pageTextContains('Publishing enabled'); + $assert->pageTextNotContains('Unpublishing enabled'); + $assert->pageTextContains('Advanced options'); + + // Turn on the unpublishing enabled checkbox. + $page->checkField('edit-scheduler-unpublish-enable'); + $assert->waitForText('Unpublishing enabled'); + $assert->pageTextContains('Unpublishing enabled'); + + } + +} -- GitLab