diff --git a/.github/cd.gitignore b/.github/cd.gitignore new file mode 100644 index 000000000..44d8613c7 --- /dev/null +++ b/.github/cd.gitignore @@ -0,0 +1,11 @@ +/docroot/sites/*/settings.*.php +/docroot/sites/*/services*.yml +/docroot/sites/*/files +/docroot/sites/*/private +/docroot/sites/simpletest + +# Directories specific to this template +/docroot/libraries +/docroot/modules/contrib +/docroot/profiles/contrib +/docroot/themes/contrib diff --git a/.github/workflows/acquia_cms_ci.workflow.yml b/.github/workflows/acquia_cms_ci.workflow.yml index a17943db9..0e9d91c72 100644 --- a/.github/workflows/acquia_cms_ci.workflow.yml +++ b/.github/workflows/acquia_cms_ci.workflow.yml @@ -9,6 +9,8 @@ on: paths-ignore: - README.md +env: + ORCA_VERSION: ^4 jobs: static_code_analysis: if: ${{ github.event_name == 'pull_request' }} @@ -17,7 +19,6 @@ jobs: # Provide your package's name. ORCA_SUT_NAME: acquia/acquia_cms ORCA_SUT_BRANCH: develop - ORCA_VERSION: ^4 ORCA_PACKAGES_CONFIG_ALTER: ../acquia_cms/tests/packages_alter.yml ORCA_FIXTURE_PROJECT_TEMPLATE: acquia/drupal-recommended-project ORCA_ENABLE_NIGHTWATCH: "FALSE" @@ -127,7 +128,8 @@ jobs: matrix: orca-job: - INTEGRATED_TEST_ON_LATEST_LTS - - ISOLATED_TEST_ON_CURRENT + - INTEGRATED_TEST_ON_PREVIOUS_MINOR +# - ISOLATED_TEST_ON_CURRENT acms_job: - integrated_php_unit_tests - integrated_existing_site_tests @@ -151,6 +153,7 @@ jobs: composer create-project --no-dev --ignore-platform-req=php acquia/orca ../orca "$ORCA_VERSION" -n curl https://gist.githubusercontent.com/rajeshreeputra/170586f217b422eb9cdfd9ca9457a2e3/raw/c2f277ba9005b91d7f662cacf37b3940a66a9b8c/sut-path-reposories.patch | git -C ../orca apply curl https://gist.githubusercontent.com/rajeshreeputra/efe6fd50fc839e0e05480a5eb58d1ba4/raw/c5e81aa3c0fba9f4abe42460f3d24c7ca976a527/remove-local-settings.patch | git -C ../orca apply + composer config extra."drupal-scaffold".file-mapping {} --json -d ${ORCA_SUT_DIR} # - name: Configure AWS Credentials # uses: aws-actions/configure-aws-credentials@v1 # with: @@ -223,7 +226,8 @@ jobs: matrix: orca-job: - INTEGRATED_TEST_ON_LATEST_LTS - - ISOLATED_TEST_ON_CURRENT + - INTEGRATED_TEST_ON_PREVIOUS_MINOR +# - ISOLATED_TEST_ON_CURRENT #php-version: [ "8.1" ] modules: - acquia_cms_article @@ -238,6 +242,7 @@ jobs: - acquia_cms_place - acquia_cms_search - acquia_cms_site_studio + - acquia_cms_toolbar - acquia_cms_tour - acquia_cms_video steps: @@ -255,6 +260,7 @@ jobs: composer self-update composer create-project --no-dev --ignore-platform-req=php acquia/orca ../orca "$ORCA_VERSION" -n curl https://gist.githubusercontent.com/rajeshreeputra/170586f217b422eb9cdfd9ca9457a2e3/raw/c2f277ba9005b91d7f662cacf37b3940a66a9b8c/sut-path-reposories.patch | git -C ../orca apply + composer config extra."drupal-scaffold".file-mapping {} --json -d ${ORCA_SUT_DIR} - name: Before Install run: | # Remove all ExistingSite test in CI. @@ -319,14 +325,16 @@ jobs: matrix: orca-job: - INTEGRATED_TEST_ON_LATEST_LTS - # - INTEGRATED_TEST_ON_PREVIOUS_MINOR - - ISOLATED_TEST_ON_CURRENT + - INTEGRATED_TEST_ON_PREVIOUS_MINOR +# - ISOLATED_TEST_ON_CURRENT php-version: - 8.1 - 8.3 exclude: - php-version: 8.1 - orca-job: ISOLATED_TEST_ON_CURRENT + orca-job: INTEGRATED_TEST_ON_PREVIOUS_MINOR +# - php-version: 8.1 +# orca-job: ISOLATED_TEST_ON_CURRENT steps: - uses: actions/checkout@v4 - name: Use Node.js 20.x @@ -346,6 +354,7 @@ jobs: composer self-update composer create-project --no-dev --ignore-platform-req=php acquia/orca ../orca "$ORCA_VERSION" -n curl https://gist.githubusercontent.com/rajeshreeputra/170586f217b422eb9cdfd9ca9457a2e3/raw/c2f277ba9005b91d7f662cacf37b3940a66a9b8c/sut-path-reposories.patch | git -C ../orca apply + composer config extra."drupal-scaffold".file-mapping {} --json -d ${ORCA_SUT_DIR} - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: diff --git a/.github/workflows/acquia_cms_cron.yml b/.github/workflows/acquia_cms_cron.yml index c405d6458..6f52ab32e 100644 --- a/.github/workflows/acquia_cms_cron.yml +++ b/.github/workflows/acquia_cms_cron.yml @@ -383,6 +383,7 @@ jobs: - acquia_cms_place - acquia_cms_search - acquia_cms_site_studio + - acquia_cms_toolbar - acquia_cms_tour - acquia_cms_video steps: diff --git a/.github/workflows/deployment.workflow.yml b/.github/workflows/deployment.workflow.yml new file mode 100644 index 000000000..02624a2f6 --- /dev/null +++ b/.github/workflows/deployment.workflow.yml @@ -0,0 +1,210 @@ +name: "Code Deployment (Acquia)" +on: + push: + branches: [ develop, main, ACMS-*, feature/* ] + workflow_dispatch: + inputs: + environment: + description: 'Choose environment' + type: choice + options: + - dev + - stage + - prod + - next + - ode1 + - ode2 + - ode3 + - ode4 + - ode5 + - ode6 + - ode7 + - ode8 + required: true + default: 'dev' + php-version: + description: 'Choose PHP Version' + type: choice + options: + - "8.1" + - "8.2" + - "8.3" + - "8.4" + required: true + default: '8.3' + drupal-core: + description: 'Choose Drupal Core Version.' + required: false + default: '^11' + download-latest-dependencies: + description: 'Download latest dependencies' + type: boolean + default: false + +concurrency: + group: "ci-${{ github.ref }}" + cancel-in-progress: true + +env: + GIT_AUTHOR_NAME: "CD" + GIT_COMMITTER_NAME: "CD" + GIT_COMMITTER_EMAIL: "no-reply@acquia.com" + GIT_AUTHOR_EMAIL: "no-reply@acquia.com" + PHP_VERSION: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.php-version || '8.3' }} + CORE_VERSION: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.drupal-core || '' }} + ACQUIA_CLOUD_ENVIRONMENT: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.environment || 'dev' }} + DOWNLOAD_LATEST_DEPENDENCIES: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.download-latest-dependencies || 'false' }} + +jobs: + acquia_code_deployment: + if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} + name: "Code Deployment" + runs-on: ubuntu-latest + environment: acquia_code_deployment + env: + ACQUIA_CLOUD_API_KEY: ${{ secrets.ACQUIA_CLOUD_API_KEY }} + ACQUIA_CLOUD_API_SECRET: ${{ secrets.ACQUIA_CLOUD_API_SECRET }} + ACQUIA_CLOUD_APPLICATION: ${{ secrets.ACQUIA_CLOUD_APPLICATION }} + steps: + - uses: actions/checkout@v4 + - uses: shivammathur/setup-php@v2 + with: + php-version: ${{ env.PHP_VERSION }} + - name: Setup Drupal Project + run: | + # Download specific version of Drupal Core, if requested. + [ -n "${CORE_VERSION}" ] && echo composer require drupal/core:${CORE_VERSION} drupal/core-composer-scaffold:${CORE_VERSION} drupal/core-recommended:${CORE_VERSION} --no-install --no-update -n || true + + # Move some of development dependencies to production dependencies or else acli push:artifact will fail. + composer require oomphinc/composer-installers-extender --no-install --no-update -n + + if [ "${DOWNLOAD_LATEST_DEPENDENCIES}" == "true" ]; then + rm composer.lock + composer install + else + # Update specific version of Drupal Core, if requested or else simply install all dependencies. + if [ -n "${CORE_VERSION}" ]; then + composer update "drupal/core-*" drush/drush "drupal/*" -W --with=drupal/core:${CORE_VERSION} --minimal-changes + else + # In CI, we don't need to run composer install again, as it's already will be done by below command. + composer update oomphinc/composer-installers-extender + fi + fi + + # Include MySQL 5.7 connection settings, before DRS require line is added. + echo "require DRUPAL_ROOT . '/modules/contrib/mysql57/settings.inc';" >> docroot/sites/default/settings.php + + # Download acquia/drupal-recommended-settings plugin & drupal/mysql57 library. + composer require acquia/drupal-recommended-settings:^1.1 drupal/mysql57 + + # Update .gitignore file, otherwise acli won't push any settings file. + sed -i 's/docroot\//docroot\/core/' .gitignore + cat .github/cd.gitignore >> .gitignore 2>/dev/null + + # Create symlink directory for multisite headless and community. + cd docroot/sites + ln -s default headless + ln -s default community + cd - + git add . && git commit -m "Update drupal core and it's dependencies." 2>/dev/null + - name: Setup Acquia CLI + run: | + curl -OL https://github.com/acquia/cli/releases/latest/download/acli.phar + chmod +x acli.phar + mv acli.phar /usr/local/bin/acli + acli --version + + acli auth:login --key=${ACQUIA_CLOUD_API_KEY} --secret=${ACQUIA_CLOUD_API_SECRET} -n + ACQUIA_APPLICATION_UUID=$(acli api:applications:find ${ACQUIA_CLOUD_APPLICATION} -n | jq -r '.uuid') + acli link ${ACQUIA_APPLICATION_UUID} -n + + acli remote:aliases:download -n + git add . && git commit -m "Added acli & drush alias configurations." 2>/dev/null + - name: Find & Switch PHP Version + run: | + # Find the PHP version. + ENV_PHP_VERSION=$(acli api:environments:find ${ACQUIA_CLOUD_APPLICATION}.${ACQUIA_CLOUD_ENVIRONMENT} -n | jq -r '.configuration.php.version') + echo "The CI php-version: ${PHP_VERSION}" + echo "The Acquia Cloud environment php-version: $ENV_PHP_VERSION" + # If PHP_VERSION is NOT the same as the one we want to switch to. Then switch PHP version. + if [ "${ENV_PHP_VERSION}" != "${PHP_VERSION}" ]; then + echo "Switching PHP version to ${PHP_VERSION}" + acli api:environments:update ${ACQUIA_CLOUD_APPLICATION}.${ACQUIA_CLOUD_ENVIRONMENT} --lang_version=${PHP_VERSION} -n + sleep 10 + fi + - name: Configure SSH keys + run: | + mkdir -p ~/.ssh + echo "${ACQUIA_CLOUD_SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + eval `ssh-agent -s` + ssh-add ~/.ssh/id_rsa + + SSH_URL=$(acli api:environments:find ${ACQUIA_CLOUD_APPLICATION}.${ACQUIA_CLOUD_ENVIRONMENT} -n | jq -r '.ssh_url' | awk -F'[@:]' '{print $2}') + GIT_URL=$(acli api:environments:find ${ACQUIA_CLOUD_APPLICATION}.${ACQUIA_CLOUD_ENVIRONMENT} -n | jq -r '.vcs.url' | awk -F'[@:]' '{print $2}') + + ssh-keyscan "${SSH_URL}" >> ~/.ssh/known_hosts && ssh-keyscan "${GIT_URL}" >> ~/.ssh/known_hosts + shell: bash + env: + ACQUIA_CLOUD_SSH_PRIVATE_KEY: ${{ secrets.ACQUIA_CLOUD_SSH_PRIVATE_KEY }} + - name: Deploy & Switch Code + shell: bash + run: | + BRANCH_TO_DEPLOY=acli-${GITHUB_REF_NAME} + + # Push changes on Acuia Cloud. + acli push:artifact ${ACQUIA_CLOUD_APPLICATION}.${ACQUIA_CLOUD_ENVIRONMENT} --destination-git-branch=${BRANCH_TO_DEPLOY} -n + + # If the event is push and branch is develop or if CI is triggered manually, then only switch code. + if [[ "${GITHUB_EVENT_NAME}" == "push" && "${GITHUB_REF_NAME}" == "develop" ]] || [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then + + DEPLOYED_BRANCH=$(acli api:environments:find ${ACQUIA_CLOUD_APPLICATION}.${ACQUIA_CLOUD_ENVIRONMENT} -n | jq -r '.vcs.path') + + # If BRANCH_TO_DEPLOY is NOT the same as DEPLOYED_BRANCH. Then switch code. + if [ "${BRANCH_TO_DEPLOY}" != "${DEPLOYED_BRANCH}" ]; then + # Step 1: Run the code:switch command and capture its output. + response=$(acli api:environments:code-switch ${ACQUIA_CLOUD_APPLICATION}.${ACQUIA_CLOUD_ENVIRONMENT} ${BRANCH_TO_DEPLOY} -n) + + # Step 2: Extract the notification ID from the JSON response + notification_id=$(echo "$response" | jq -r '.notification') + + # Step 3: Check if the notification ID was successfully extracted. + if [[ -z "$notification_id" ]]; then + echo "Error: Notification ID not found in the response." + exit 1 + fi + + progress=0 + timeout=1800 # Timeout in seconds (30 minutes). + start_time=$(date +%s) # Get the current time in seconds + + echo "Please wait while code is being switched..." + # Step 4: Poll the notification status until progress reaches 100. + while [[ "$progress" -lt 100 ]]; do + # Run the notification find command. + notification_response=$(acli api:notifications:find "$notification_id" -n) + + # Extract the progress value. + progress=$(echo "$notification_response" | jq -r '.progress') + + # Display current progress. + #echo "Current progress: $progress%" + + # Check if we've exceeded the timeout (5 minutes). + current_time=$(date +%s) + elapsed_time=$((current_time - start_time)) + + if [[ "$elapsed_time" -ge "$timeout" ]]; then + # Calculate minutes and seconds. + minutes=$((elapsed_time / 60)) + seconds=$((elapsed_time % 60)) + + echo "Error: Timeout reached after $minutes minute(s) and $seconds second(s). Progress did not reach 100%." + exit 1 + fi + + # Wait for 5 seconds before polling again. + sleep 5 + done + fi + fi diff --git a/acquia-pipelines.yml b/acquia-pipelines.yml deleted file mode 100644 index 5e065c520..000000000 --- a/acquia-pipelines.yml +++ /dev/null @@ -1,47 +0,0 @@ -# This file is used by Acquia Pipelines continuous integration. Upon success, an -# artifact is deployed to the `orionacms` subscription on Acquia Cloud. -version: 1.3.0 -services: - - composer: - version: 2 - - php: - version: 8.1 - -events: - build: - steps: - - setup: - type: script - script: - - composer validate --no-check-all --ansi --no-interaction - - composer install - - mkdir -p docroot/modules/acquia_cms - # Create symlink directory for multisite headless and community. - - cd docroot/sites - - ln -s default headless - - ln -s default community - - cd - - - composer archive --format zip --file acquia_cms - - unzip acquia_cms.zip -d docroot/modules/acquia_cms - # Commenting as it's no longer needed and this is failing deployment. - # - front-end: - # type: script - # script: - # - cd docroot/themes/contrib/acquia_claro - # - npm install - # - npm run build - # - cd - - - cleanup: - type: script - script: - - rm acquia_cms.zip - # Prepare settings.php with the minimum required for Cloud. - - chmod -R +w docroot/sites/default - - cp docroot/sites/default/default.settings.php docroot/sites/default/settings.php - # Clear any config directories that Cloud tries to set in the include file. - - echo "\$config_directories = [];" >> docroot/sites/default/settings.php - # Use the existing `config` directory we already have. Cloud gets confused - # because we already have a config directory above docroot and manipulating it - # in Pipelines doesn't seem to work. This deployment is ephemeral, so using - # the existing config directory isn't a problem. - - echo "\$config_directories['sync'] = '../config';" >> docroot/sites/default/settings.php diff --git a/composer.json b/composer.json index da7f4231b..dd70c2e6d 100644 --- a/composer.json +++ b/composer.json @@ -223,14 +223,6 @@ } } }, - "consumer_image_styles": { - "type": "vcs", - "url": "https://git.drupalcode.org/issue/consumer_image_styles-3429496.git" - }, - "config_filter": { - "type": "vcs", - "url": "https://git.drupalcode.org/issue/config_filter-3428542.git" - }, "drupal": { "type": "composer", "url": "https://packages.drupal.org/8" @@ -262,8 +254,7 @@ "phpstan/extension-installer": true, "tbachert/spi": true, "webdriver-binary/binary-chromedriver": true, - "wikimedia/composer-merge-plugin": true, - "tbachert/spi": true + "wikimedia/composer-merge-plugin": true }, "preferred-install": { "drupal/core": "dist" @@ -287,8 +278,10 @@ "[web-root]/profiles/README.txt": false, "[web-root]/robots.txt": false, "[web-root]/sites/README.txt": false, - "[web-root]/sites/default/default.settings.php": { - "append": "./patches/d9-acms-settings.patch" + "[web-root]/sites/default/settings.php": { + "mode": "replace", + "overwrite": false, + "path": "docroot/core/assets/scaffold/files/default.settings.php" }, "[web-root]/themes/README.txt": false, "[web-root]/themes/contrib/cohesion-theme/templates/maintenance-page.html.twig": "./patches/maintenance-page.patch", diff --git a/composer.lock b/composer.lock index 3247153fd..8f57c4670 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": "159f1bf0ea74b93f8d8588e5eec5bdcf", + "content-hash": "f7f9e623cf8da30e566ee0d0052fb980", "packages": [ { "name": "acquia/acquia-cms-starterkit", @@ -2921,10 +2921,10 @@ "dist": { "type": "path", "url": "./modules/acquia_cms_toolbar", - "reference": "0cc6f26997c253705d6d7087a8878f7e690a29a0" + "reference": "d6cd7d13ed41934d7654920ccb8a751972a28be6" }, "require": { - "drupal/acquia_cms_common": "^1.9 || ^2.1 || ^3.1", + "acquia/drupal-environment-detector": "^1.5", "drupal/admin_toolbar": "^3.3" }, "conflict": { @@ -2950,15 +2950,16 @@ "dist": { "type": "path", "url": "./modules/acquia_cms_tour", - "reference": "04e968e9b96a2b1fb974296aee91951ec849f6b9" + "reference": "f4cea1338093f3bd87095843583036f0bf289ecf" }, "require": { - "drupal/acquia_cms_common": "^1.9 || ^2.1 || ^3.1", "drupal/checklistapi": "^2.1" }, "require-dev": { - "drupal/acquia_cms_place": "^1", - "drupal/recaptcha": "^3" + "drupal/geocoder": "^3.35 || ^4.10", + "drupal/google_tag": "^2", + "drupal/recaptcha": "^3", + "geocoder-php/google-maps-provider": "^4.7" }, "type": "drupal-module", "extra": { @@ -4010,28 +4011,61 @@ }, { "name": "drupal/consumer_image_styles", - "version": "4.0.8", + "version": "4.0.10", "source": { "type": "git", - "url": "https://git.drupalcode.org/issue/consumer_image_styles-3429496.git", - "reference": "89263183da961c033eb05eb86c2f727df21de7ff" + "url": "https://git.drupalcode.org/project/consumer_image_styles.git", + "reference": "4.0.10" + }, + "dist": { + "type": "zip", + "url": "https://ftp.drupal.org/files/projects/consumer_image_styles-4.0.10.zip", + "reference": "4.0.10", + "shasum": "6894d5bde15984a4597e19e6ebab46f464a15b10" }, "require": { - "drupal/consumers": "^1.15", - "drupal/jsonapi_extras": "^3.23" + "drupal/consumers": "^1.19", + "drupal/core": "^9.5 || ^10 || ^11", + "php": ">=8.0" + }, + "require-dev": { + "drupal/jsonapi_extras": "^3.26" }, "type": "drupal-module", + "extra": { + "drupal": { + "version": "4.0.10", + "datestamp": "1729009525", + "security-coverage": { + "status": "covered", + "message": "Covered by Drupal's security advisory policy" + } + } + }, + "notification-url": "https://packages.drupal.org/8/downloads", "license": [ "GPL-2.0-or-later" ], "authors": [ { "name": "Mateu Aguiló Bosch", + "homepage": "https://www.drupal.org/user/405824", "email": "mateu.aguilo.bosch@gmail.com" + }, + { + "name": "e0ipso", + "homepage": "https://www.drupal.org/user/550110" + }, + { + "name": "japerry", + "homepage": "https://www.drupal.org/user/45640" } ], "description": "Consumer Image Styles integrates with JSON API to provide image styles to your images in your decoupled project.", - "time": "2022-12-09T06:06:46+00:00" + "homepage": "https://www.drupal.org/project/consumer_image_styles", + "support": { + "source": "https://git.drupalcode.org/project/consumer_image_styles" + } }, { "name": "drupal/consumers", @@ -5101,17 +5135,17 @@ }, { "name": "drupal/geocoder", - "version": "4.25.0", + "version": "4.26.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/geocoder.git", - "reference": "8.x-4.25" + "reference": "8.x-4.26" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/geocoder-8.x-4.25.zip", - "reference": "8.x-4.25", - "shasum": "f62dcbdb3c27a266aed92f78c6b861ffaa391ff0" + "url": "https://ftp.drupal.org/files/projects/geocoder-8.x-4.26.zip", + "reference": "8.x-4.26", + "shasum": "6681f565880da40341aa90b7e2df18bb1978fc96" }, "require": { "davedevelopment/stiphle": "^0.9.2", @@ -5155,8 +5189,8 @@ "type": "drupal-module", "extra": { "drupal": { - "version": "8.x-4.25", - "datestamp": "1722204762", + "version": "8.x-4.26", + "datestamp": "1733783003", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" @@ -13912,26 +13946,27 @@ }, { "name": "symfony/http-client", - "version": "v7.1.5", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4" + "reference": "955e43336aff03df1e8a8e17daefabb0127a313b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/abca35865118edf35a23f2f24978a1784c831cb4", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4", + "url": "https://api.github.com/repos/symfony/http-client/zipball/955e43336aff03df1e8a8e17daefabb0127a313b", + "reference": "955e43336aff03df1e8a8e17daefabb0127a313b", "shasum": "" }, "require": { "php": ">=8.2", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", + "symfony/http-client-contracts": "~3.4.3|^3.5.1", "symfony/service-contracts": "^2.5|^3" }, "conflict": { + "amphp/amp": "<2.5", "php-http/discovery": "<1.15", "symfony/http-foundation": "<6.4" }, @@ -13942,14 +13977,14 @@ "symfony/http-client-implementation": "3.0" }, "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", + "amphp/http-client": "^4.2.1|^5.0", + "amphp/http-tunnel": "^1.0|^2.0", "amphp/socket": "^1.1", "guzzlehttp/promises": "^1.4|^2.0", "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", + "symfony/amphp-http-client-meta": "^1.0|^2.0", "symfony/dependency-injection": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", "symfony/messenger": "^6.4|^7.0", @@ -13986,7 +14021,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.5" + "source": "https://github.com/symfony/http-client/tree/v7.2.0" }, "funding": [ { @@ -14002,20 +14037,20 @@ "type": "tidelift" } ], - "time": "2024-09-20T13:35:23+00:00" + "time": "2024-11-29T08:22:02+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/c2f3ad828596624ca39ea40f83617ef51ca8bbf9", + "reference": "c2f3ad828596624ca39ea40f83617ef51ca8bbf9", "shasum": "" }, "require": { @@ -14064,7 +14099,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.1" }, "funding": [ { @@ -14080,7 +14115,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-11-25T12:02:18+00:00" }, { "name": "symfony/http-foundation", diff --git a/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessApiKeys.php b/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessApiKeys.php index 5ca89eea2..9e29fc40e 100644 --- a/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessApiKeys.php +++ b/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessApiKeys.php @@ -25,34 +25,6 @@ * ) */ class HeadlessApiKeys extends AcquiaCmsDashboardBase { - /** - * The state interface. - * - * @var \Drupal\Core\State\StateInterface - */ - protected $state; - - - /** - * The module handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * The link generator. - * - * @var \Drupal\Core\Utility\LinkGeneratorInterface - */ - protected $linkGenerator; - - /** - * The info file parser. - * - * @var \Drupal\Core\Extension\InfoParserInterface - */ - protected $infoParser; /** * The EntityTypeManager service. @@ -75,27 +47,15 @@ class HeadlessApiKeys extends AcquiaCmsDashboardBase { */ protected $module = 'consumers'; - /** - * {@inheritdoc} - */ - public function __construct(StateInterface $state, ModuleHandlerInterface $module_handler, LinkGeneratorInterface $link_generator, InfoParserInterface $info_parser, EntityTypeManagerInterface $entity_type_manager, StarterkitNextjsService $starterkit_nextjs_service) { - parent::__construct($state, $module_handler, $link_generator, $info_parser); - $this->entityTypeManager = $entity_type_manager; - $this->starterKitNextjsService = $starterkit_nextjs_service; - } - /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { - return new static( - $container->get('state'), - $container->get('module_handler'), - $container->get('link_generator'), - $container->get('info_parser'), - $container->get('entity_type.manager'), - $container->get('acquia_cms_headless.starterkit_nextjs') - ); + $instance = parent::create($container); + $instance->entityTypeManager = $container->get('entity_type.manager'); + $instance->starterKitNextjsService = $container->get('acquia_cms_headless.starterkit_nextjs'); + + return $instance; } /** diff --git a/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessApiUsers.php b/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessApiUsers.php index 4c0ae9378..ca85797d1 100644 --- a/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessApiUsers.php +++ b/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessApiUsers.php @@ -24,34 +24,6 @@ * ) */ class HeadlessApiUsers extends AcquiaCmsDashboardBase { - /** - * The state interface. - * - * @var \Drupal\Core\State\StateInterface - */ - protected $state; - - - /** - * The module handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * The link generator. - * - * @var \Drupal\Core\Utility\LinkGeneratorInterface - */ - protected $linkGenerator; - - /** - * The info file parser. - * - * @var \Drupal\Core\Extension\InfoParserInterface - */ - protected $infoParser; /** * The EntityTypeManager service. @@ -81,28 +53,16 @@ class HeadlessApiUsers extends AcquiaCmsDashboardBase { */ protected $headlessRoleLabel; - /** - * {@inheritdoc} - */ - public function __construct(StateInterface $state, ModuleHandlerInterface $module_handler, LinkGeneratorInterface $link_generator, InfoParserInterface $info_parser, EntityTypeManagerInterface $entity_type_manager, StarterkitNextjsService $starterkit_nextjs_service) { - parent::__construct($state, $module_handler, $link_generator, $info_parser); - $this->entityTypeManager = $entity_type_manager; - $this->headlessRoleLabel = $entity_type_manager->getStorage('user_role')->load('headless')->label(); - $this->starterKitNextjsService = $starterkit_nextjs_service; - } - /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { - return new static( - $container->get('state'), - $container->get('module_handler'), - $container->get('link_generator'), - $container->get('info_parser'), - $container->get('entity_type.manager'), - $container->get('acquia_cms_headless.starterkit_nextjs') - ); + $instance = parent::create($container); + $instance->entityTypeManager = $container->get('entity_type.manager'); + $instance->starterKitNextjsService = $container->get('acquia_cms_headless.starterkit_nextjs'); + $instance->headlessRoleLabel = $instance->entityTypeManager->getStorage('user_role')->load('headless')->label(); + + return $instance; } /** diff --git a/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessNextEntityTypes.php b/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessNextEntityTypes.php index 5ab3decdf..e931a6788 100644 --- a/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessNextEntityTypes.php +++ b/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessNextEntityTypes.php @@ -24,34 +24,6 @@ * ) */ class HeadlessNextEntityTypes extends AcquiaCmsDashboardBase { - /** - * The state interface. - * - * @var \Drupal\Core\State\StateInterface - */ - protected $state; - - - /** - * The module handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * The link generator. - * - * @var \Drupal\Core\Utility\LinkGeneratorInterface - */ - protected $linkGenerator; - - /** - * The info file parser. - * - * @var \Drupal\Core\Extension\InfoParserInterface - */ - protected $infoParser; /** * The EntityTypeManager service. @@ -74,27 +46,15 @@ class HeadlessNextEntityTypes extends AcquiaCmsDashboardBase { */ protected $module = 'next'; - /** - * {@inheritdoc} - */ - public function __construct(StateInterface $state, ModuleHandlerInterface $module_handler, LinkGeneratorInterface $link_generator, InfoParserInterface $info_parser, EntityTypeManagerInterface $entity_type_manager, StarterkitNextjsService $starterKitNextjsService) { - parent::__construct($state, $module_handler, $link_generator, $info_parser); - $this->entityTypeManager = $entity_type_manager; - $this->starterKitNextjsService = $starterKitNextjsService; - } - /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { - return new static( - $container->get('state'), - $container->get('module_handler'), - $container->get('link_generator'), - $container->get('info_parser'), - $container->get('entity_type.manager'), - $container->get('acquia_cms_headless.starterkit_nextjs') - ); + $instance = parent::create($container); + $instance->entityTypeManager = $container->get('entity_type.manager'); + $instance->starterKitNextjsService = $container->get('acquia_cms_headless.starterkit_nextjs'); + + return $instance; } /** diff --git a/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessNextSites.php b/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessNextSites.php index 9085a23be..8cedd0870 100644 --- a/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessNextSites.php +++ b/modules/acquia_cms_headless/src/Plugin/AcquiaCmsHeadless/HeadlessNextSites.php @@ -26,41 +26,6 @@ * ) */ class HeadlessNextSites extends AcquiaCmsDashboardBase { - /** - * The state interface. - * - * @var \Drupal\Core\State\StateInterface - */ - protected $state; - - - /** - * The module handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - - /** - * The link generator. - * - * @var \Drupal\Core\Utility\LinkGeneratorInterface - */ - protected $linkGenerator; - - /** - * The info file parser. - * - * @var \Drupal\Core\Extension\InfoParserInterface - */ - protected $infoParser; - - /** - * Provides the database connection. - * - * @var \Drupal\Core\Database\Connection - */ - protected $connection; /** * The EntityTypeManager service. @@ -83,29 +48,15 @@ class HeadlessNextSites extends AcquiaCmsDashboardBase { */ protected $module = 'next'; - /** - * {@inheritdoc} - */ - public function __construct(StateInterface $state, ModuleHandlerInterface $module_handler, LinkGeneratorInterface $link_generator, InfoParserInterface $info_parser, Connection $connection, EntityTypeManagerInterface $entity_type_manager, StarterkitNextjsService $starterKitNextjsService) { - parent::__construct($state, $module_handler, $link_generator, $info_parser); - $this->connection = $connection; - $this->entityTypeManager = $entity_type_manager; - $this->starterKitNextjsService = $starterKitNextjsService; - } - /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { - return new static( - $container->get('state'), - $container->get('module_handler'), - $container->get('link_generator'), - $container->get('info_parser'), - $container->get('database'), - $container->get('entity_type.manager'), - $container->get('acquia_cms_headless.starterkit_nextjs') - ); + $instance = parent::create($container); + $instance->entityTypeManager = $container->get('entity_type.manager'); + $instance->starterKitNextjsService = $container->get('acquia_cms_headless.starterkit_nextjs'); + + return $instance; } /** diff --git a/modules/acquia_cms_toolbar/acquia_cms_toolbar.install b/modules/acquia_cms_toolbar/acquia_cms_toolbar.install index e00481b75..95817c314 100644 --- a/modules/acquia_cms_toolbar/acquia_cms_toolbar.install +++ b/modules/acquia_cms_toolbar/acquia_cms_toolbar.install @@ -5,25 +5,16 @@ * Contains hook code for the Acquia CMS Toolbar. */ -use Drupal\user\Entity\Role; +use Drupal\acquia_cms_toolbar\EntityOperations\PermissionManager; /** - * Update role permission handler. + * Implements hook_install(). */ -function update_toolbar_role_permission() { - $get_all_roles = Role::loadMultiple(); - $roles = [ - 'content_administrator', - 'content_author', - 'content_editor', - 'developer', - 'site_builder', - 'user_administrator', - ]; - foreach ($roles as $role) { - if (isset($get_all_roles[$role])) { - user_role_grant_permissions($role, ['access toolbar']); - } +function acquia_cms_toolbar_install($is_syncing) { + if (!$is_syncing) { + $class_resolver = \Drupal::service('class_resolver'); + $class_resolver->getInstanceFromDefinition(PermissionManager::class) + ->grantPermissionToRoles(); } } @@ -31,5 +22,7 @@ function update_toolbar_role_permission() { * Update role permissions. */ function acquia_cms_toolbar_update_8001() { - update_toolbar_role_permission(); + $class_resolver = \Drupal::service('class_resolver'); + $class_resolver->getInstanceFromDefinition(PermissionManager::class) + ->grantPermissionToRoles(); } diff --git a/modules/acquia_cms_toolbar/acquia_cms_toolbar.module b/modules/acquia_cms_toolbar/acquia_cms_toolbar.module index 391ce70da..970c456b1 100644 --- a/modules/acquia_cms_toolbar/acquia_cms_toolbar.module +++ b/modules/acquia_cms_toolbar/acquia_cms_toolbar.module @@ -6,6 +6,7 @@ */ use Acquia\DrupalEnvironmentDetector\AcquiaDrupalEnvironmentDetector as Environment; +use Drupal\acquia_cms_toolbar\EntityOperations\PermissionManager; use Drupal\Core\Url; use Drupal\user\RoleInterface; @@ -102,17 +103,12 @@ function _acquia_cms_toolbar_get_environment_indicator_color_config(): array { } /** - * Implements hook_content_model_role_presave_alter(). + * Implements hook_entity_insert(). */ -function acquia_cms_toolbar_content_model_role_presave_alter(RoleInterface &$role) { - switch ($role->id()) { - case 'content_administrator': - case 'content_author': - case 'content_editor': - case 'developer': - case 'site_builder': - case 'user_administrator': - $role->grantPermission('access toolbar'); - break; +function acquia_cms_toolbar_user_role_insert(RoleInterface $role) { + if (!$role->isSyncing()) { + $class_resolver = \Drupal::service('class_resolver'); + $class_resolver->getInstanceFromDefinition(PermissionManager::class) + ->grantPermissionToRoles([$role->id()]); } } diff --git a/modules/acquia_cms_toolbar/composer.json b/modules/acquia_cms_toolbar/composer.json index 9540e671d..8def6acf6 100644 --- a/modules/acquia_cms_toolbar/composer.json +++ b/modules/acquia_cms_toolbar/composer.json @@ -4,7 +4,7 @@ "license": "GPL-2.0-or-later", "type": "drupal-module", "require": { - "drupal/acquia_cms_common": "^1.9 || ^2.1 || ^3.1", + "acquia/drupal-environment-detector": "^1.5", "drupal/admin_toolbar": "^3.3" }, "conflict": { diff --git a/modules/acquia_cms_toolbar/src/EntityOperations/PermissionManager.php b/modules/acquia_cms_toolbar/src/EntityOperations/PermissionManager.php new file mode 100644 index 000000000..b0c3c3bc3 --- /dev/null +++ b/modules/acquia_cms_toolbar/src/EntityOperations/PermissionManager.php @@ -0,0 +1,57 @@ +get('entity_type.manager') + ); + } + + /** + * Update role permission handler. + * + * @param array|null $role_ids + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + */ + public function grantPermissionToRoles(?array $role_ids = NULL): void { + $roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple($role_ids ?? [ + 'content_administrator', + 'content_author', + 'content_editor', + 'developer', + 'site_builder', + 'user_administrator', + ]); + foreach ($roles as $role) { + $role->grantPermission('access toolbar')->trustData()->save(); + } + } + +} diff --git a/modules/acquia_cms_toolbar/tests/src/Functional/PermissionsTest.php b/modules/acquia_cms_toolbar/tests/src/Functional/PermissionsTest.php new file mode 100644 index 000000000..893cec8ad --- /dev/null +++ b/modules/acquia_cms_toolbar/tests/src/Functional/PermissionsTest.php @@ -0,0 +1,101 @@ +drupalCreateRole([], 'content_administrator'); + $this->entityTypeManager = $this->container->get("entity_type.manager"); + } + + /** + * Tests permissions are granted to content_administrator role. + */ + public function testGrantPermissionsOnInstall(): void { + // Load the role and check its permissions. + $role_permissions = $this->entityTypeManager->getStorage('user_role')->load('content_administrator')->getPermissions(); + $this->assertEquals(['access toolbar'], $role_permissions); + } + + /** + * Tests permissions are granted to role created after module install. + * + * @param string $role + * The role. + * @param array $permissions + * An array of permissions. + * + * @dataProvider rolePermissionDataProvider + */ + public function testGrantPermissionsOnRoleCreate(string $role, array $permissions): void { + // Create a new role. + $this->drupalCreateRole([], $role); + + // Load the role and check its permissions. + $role_permissions = $this->entityTypeManager->getStorage('user_role')->load('content_administrator')->getPermissions(); + $this->assertEquals($permissions, $role_permissions); + } + + /** + * Return an array of dataProvider for method grantPermissionToRoles. + */ + public static function rolePermissionDataProvider(): array { + return [ + [ + 'content_author', + ['access toolbar'], + ], + [ + 'content_editor', + ['access toolbar'], + ], + [ + 'developer', + ['access toolbar'], + ], + [ + 'site_builder', + ['access toolbar'], + ], + [ + 'user_administrator', + ['access toolbar'], + ], + ]; + } + +} diff --git a/modules/acquia_cms_tour/acquia_cms_tour.info.yml b/modules/acquia_cms_tour/acquia_cms_tour.info.yml index e7e199b20..90af15d5d 100644 --- a/modules/acquia_cms_tour/acquia_cms_tour.info.yml +++ b/modules/acquia_cms_tour/acquia_cms_tour.info.yml @@ -3,5 +3,3 @@ package: "Acquia CMS" description: "Provides a tour page for Acquia CMS." type: module core_version_requirement: ^9.4 || ^10 || ^11 -dependencies: - - acquia_cms_common:acquia_cms_common diff --git a/modules/acquia_cms_tour/acquia_cms_tour.install b/modules/acquia_cms_tour/acquia_cms_tour.install index 875a9b526..c17894737 100644 --- a/modules/acquia_cms_tour/acquia_cms_tour.install +++ b/modules/acquia_cms_tour/acquia_cms_tour.install @@ -7,6 +7,18 @@ use Drupal\user\Entity\Role; +/** + * Implements hook_install(). + */ +function acquia_cms_tour_install($is_syncing) { + if (!$is_syncing) { + $role = \Drupal::entityTypeManager()->getStorage('user_role')->load('content_administrator'); + if ($role) { + $role->grantPermission('access acquia cms tour dashboard')->trustData()->save(); + } + } +} + /** * Add state key for existing sites with Acquia CMS profile. */ diff --git a/modules/acquia_cms_tour/acquia_cms_tour.module b/modules/acquia_cms_tour/acquia_cms_tour.module index 3cd399189..ea24c3142 100644 --- a/modules/acquia_cms_tour/acquia_cms_tour.module +++ b/modules/acquia_cms_tour/acquia_cms_tour.module @@ -57,12 +57,13 @@ function acquia_cms_tour_modules_uninstalled(array $modules) { } /** - * Implements hook_content_model_role_presave_alter(). + * Implements hook_cms_tour_entity_insert(). */ -function acquia_cms_tour_content_model_role_presave_alter(RoleInterface &$role) { - switch ($role->id()) { - case 'content_administrator': - $role->grantPermission('access acquia cms tour dashboard'); - break; +function acquia_cms_tour_user_role_insert(RoleInterface $role) { + if (!$role->isSyncing() && + $role->id() == 'content_administrator' + ) { + $role = \Drupal::entityTypeManager()->getStorage('user_role')->load('content_administrator'); + $role->grantPermission('access acquia cms tour dashboard')->trustData()->save(); } } diff --git a/modules/acquia_cms_tour/composer.json b/modules/acquia_cms_tour/composer.json index ca400c78d..36f0f25ef 100644 --- a/modules/acquia_cms_tour/composer.json +++ b/modules/acquia_cms_tour/composer.json @@ -4,12 +4,13 @@ "license": "GPL-2.0-or-later", "type": "drupal-module", "require": { - "drupal/acquia_cms_common": "^1.9 || ^2.1 || ^3.1", "drupal/checklistapi": "^2.1" }, "require-dev": { - "drupal/acquia_cms_place": "^1", - "drupal/recaptcha": "^3" + "drupal/geocoder": "^3.35 || ^4.10", + "drupal/google_tag": "^2", + "drupal/recaptcha": "^3", + "geocoder-php/google-maps-provider": "^4.7" }, "config": { "allow-plugins": { diff --git a/modules/acquia_cms_tour/css/acquia_cms_tour_dashboard.css b/modules/acquia_cms_tour/css/acquia_cms_tour_dashboard.css index 3b4a75b22..f00ed69ef 100644 --- a/modules/acquia_cms_tour/css/acquia_cms_tour_dashboard.css +++ b/modules/acquia_cms_tour/css/acquia_cms_tour_dashboard.css @@ -78,7 +78,7 @@ padding: 0; margin: 0; } -.acms-dashboard-form-wrapper .js-form-wrapper .js-form-wrapper .fieldset__wrapper{ +.acms-dashboard-form-wrapper .js-form-wrapper .js-form-wrapper .fieldset__wrapper { margin-left: 0; } .section-top { diff --git a/modules/acquia_cms_tour/src/Form/AcquiaCmsDashboardBase.php b/modules/acquia_cms_tour/src/Form/AcquiaCmsDashboardBase.php index 4e18ec406..426901368 100644 --- a/modules/acquia_cms_tour/src/Form/AcquiaCmsDashboardBase.php +++ b/modules/acquia_cms_tour/src/Form/AcquiaCmsDashboardBase.php @@ -3,6 +3,7 @@ namespace Drupal\acquia_cms_tour\Form; use Drupal\Core\Extension\InfoParserInterface; +use Drupal\Core\Extension\ModuleExtensionList; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\State\StateInterface; @@ -50,6 +51,13 @@ abstract class AcquiaCmsDashboardBase extends ConfigFormBase implements AcquiaDa */ protected $infoParser; + /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleExtensionList + */ + protected $moduleList; + /** * Constructs a new AcquiaConnectorForm. * @@ -61,12 +69,15 @@ abstract class AcquiaCmsDashboardBase extends ConfigFormBase implements AcquiaDa * The link generator. * @param \Drupal\Core\Extension\InfoParserInterface $info_parser * The info file parser. + * @param \Drupal\Core\Extension\ModuleExtensionList $module_handler + * The module list. */ - public function __construct(StateInterface $state, ModuleHandlerInterface $module_handler, LinkGeneratorInterface $link_generator, InfoParserInterface $info_parser) { + public function __construct(StateInterface $state, ModuleHandlerInterface $module_handler, LinkGeneratorInterface $link_generator, InfoParserInterface $info_parser, ModuleExtensionList $module_list) { $this->state = $state; $this->moduleHandler = $module_handler; $this->linkGenerator = $link_generator; $this->infoParser = $info_parser; + $this->moduleList = $module_list; } /** @@ -77,7 +88,8 @@ public static function create(ContainerInterface $container) { $container->get('state'), $container->get('module_handler'), $container->get('link_generator'), - $container->get('info_parser') + $container->get('info_parser'), + $container->get('extension.list.module'), ); } @@ -101,7 +113,7 @@ public function getModule() { * Get human readable module name. */ public function getModuleName() { - return $this->moduleHandler->getName($this->module); + return $this->moduleList->getName($this->module); } /** diff --git a/modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GoogleMapsApiForm.php b/modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GeocoderGoogleMapsApiForm.php similarity index 90% rename from modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GoogleMapsApiForm.php rename to modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GeocoderGoogleMapsApiForm.php index 64425e91a..7cea2165a 100644 --- a/modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GoogleMapsApiForm.php +++ b/modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GeocoderGoogleMapsApiForm.php @@ -17,7 +17,7 @@ * weight = 2 * ) */ -class GoogleMapsApiForm extends AcquiaCmsDashboardBase { +class GeocoderGoogleMapsApiForm extends AcquiaCmsDashboardBase { /** * Provides module name. @@ -72,8 +72,12 @@ public function buildForm(array $form, FormStateInterface $form_state) { if ($this->isModuleEnabled()) { $module_path = $this->moduleHandler->getModule($module)->getPathname(); $module_info = $this->infoParser->parse($module_path); - $maps_api_key = $this->config('cohesion.settings') - ->get('google_map_api_key'); + + // Get Google Maps API Key from Site Studio config if available. + if ($this->moduleHandler->moduleExists('cohesion')) { + $maps_api_key = $this->config('cohesion.settings') + ->get('google_map_api_key'); + } $provider = $this->loadProvider(); if ($provider) { $configuration = $provider->get('configuration'); @@ -157,12 +161,14 @@ private function loadProvider() : ?GeocoderProviderInterface { public function submitForm(array &$form, FormStateInterface $form_state) { $maps_api_key = $form_state->getValue('maps_api_key'); - // Configure Google Maps API Key for both Site Studio and - // Geocoder module. - $this->config('cohesion.settings') - ->set('google_map_api_key', $maps_api_key) - ->save(TRUE); + // Configure Google Maps API Key for Site Studio module. + if ($this->moduleHandler->moduleExists('cohesion')) { + $this->config('cohesion.settings') + ->set('google_map_api_key', $maps_api_key) + ->save(TRUE); + } + // Configure Google Maps API Key for Geocoder module. $provider = $this->loadProvider(); if ($provider) { $configuration = $provider->get('configuration'); diff --git a/modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GoogleTagManagerForm.php b/modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GoogleTagManagerForm.php index e713f4f0d..5121d92ad 100644 --- a/modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GoogleTagManagerForm.php +++ b/modules/acquia_cms_tour/src/Plugin/AcquiaCmsTour/GoogleTagManagerForm.php @@ -92,7 +92,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { if ($accounts === []) { $config_name = 'google_tag.container.' . $account_default_value; $entity_accounts = $this->config($config_name)->get('tag_container_ids'); - if ($entity_accounts){ + if ($entity_accounts) { foreach ($entity_accounts as $index => $account) { $accounts[$index]['value'] = $account; $accounts[$index]['weight'] = $index; @@ -242,7 +242,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $config->set('tag_container_ids', array_values($tag_container_ids)); $config->save(); } - if($this->configFactory->getEditable('google_tag.settings')->get('default_google_tag_entity') !== NULL) { + if ($this->configFactory->getEditable('google_tag.settings')->get('default_google_tag_entity') !== NULL) { $this->configFactory->getEditable('google_tag.settings')->set('default_google_tag_entity', $config_id)->save(); } diff --git a/modules/acquia_cms_tour/src/Services/StarterKitService.php b/modules/acquia_cms_tour/src/Services/StarterKitService.php index a9bc889f1..ce3402ad7 100644 --- a/modules/acquia_cms_tour/src/Services/StarterKitService.php +++ b/modules/acquia_cms_tour/src/Services/StarterKitService.php @@ -77,7 +77,7 @@ public function __construct( * @param string $content_model * Variable holding the content model option selected. */ - public function enableModules(string $starter_kit, string $demo_question = NULL, string $content_model = NULL) { + public function enableModules(string $starter_kit, ?string $demo_question = NULL, ?string $content_model = NULL) { $starter_kits = [ 'acquia_cms_enterprise_low_code' => 'Acquia CMS Enterprise low-code', 'acquia_cms_community' => 'Acquia CMS Community', @@ -144,7 +144,7 @@ public static function enableSingleModule(string $module) { * @param string $content_model * Variable holding the content model option selected. */ - public function getModulesAndThemes(string $starter_kit, string $demo_question = NULL, string $content_model = NULL) { + public function getModulesAndThemes(string $starter_kit, ?string $demo_question = NULL, ?string $content_model = NULL) { $enableModules = $enableThemes = []; switch ($starter_kit) { case 'acquia_cms_enterprise_low_code': @@ -227,7 +227,7 @@ public function getModulesAndThemes(string $starter_kit, string $demo_question = * @param string $content_model * Variable holding the content model option selected. */ - public function getMissingModules(string $starter_kit, string $demo_question = NULL, string $content_model = NULL) { + public function getMissingModules(string $starter_kit, ?string $demo_question = NULL, ?string $content_model = NULL) { $modulesAndThemes = $this->getModulesAndThemes($starter_kit, $demo_question, $content_model); $modules = $modulesAndThemes['enableModules']; $moduleList = array_keys($this->moduleExtensionList->getList()); diff --git a/modules/acquia_cms_tour/tests/src/Functional/AcquiaGoogleMapsTest.php b/modules/acquia_cms_tour/tests/src/Functional/AcquiaGoogleMapsTest.php deleted file mode 100644 index f4eadac42..000000000 --- a/modules/acquia_cms_tour/tests/src/Functional/AcquiaGoogleMapsTest.php +++ /dev/null @@ -1,78 +0,0 @@ -assertSession(); - - $account = $this->drupalCreateUser(['access acquia cms tour dashboard']); - $this->drupalLogin($account); - - // Visit the tour page. - $this->drupalGet('/admin/tour/dashboard'); - $assert_session->statusCodeEquals(200); - - $container = $assert_session->elementExists('css', '[data-drupal-selector="edit-geocoder"]'); - // API key should be blank to start. - $assert_session->fieldValueEquals('maps_api_key', '', $container); - $container->pressButton('Save'); - $assert_session->pageTextContains('Maps API key field is required.'); - - // Save a dummmy API key. - $dummy_key = 'keykeykey123'; - $container->fillField('edit-maps-api-key', $dummy_key); - $container->pressButton('Save'); - $assert_session->pageTextContains('The Google Maps API key has been set.'); - - // Now test that the config values we expect are set correctly. - $cohesion_map_key = $this->config('cohesion.settings')->get('google_map_api_key'); - $this->assertSame($cohesion_map_key, $dummy_key); - - $configuration = GeocoderProvider::load('googlemaps')->get('configuration'); - $this->assertSame($configuration['apiKey'], $dummy_key); - } - -} diff --git a/modules/acquia_cms_tour/tests/src/Functional/GeocoderTest.php b/modules/acquia_cms_tour/tests/src/Functional/GeocoderTest.php new file mode 100644 index 000000000..f06d70b5f --- /dev/null +++ b/modules/acquia_cms_tour/tests/src/Functional/GeocoderTest.php @@ -0,0 +1,103 @@ +moduleHandler = $this->container->get("module_handler"); + } + + /** + * Tests that the Google Maps API key can be set on the tour page. + */ + public function testGeocoderGoogleMaps() { + $assert_session = $this->assertSession(); + + // Create an administrator account with all permissions. + $admin_user = $this->drupalCreateUser([], NULL, TRUE); + + // Log in the administrator account. + $this->drupalLogin($admin_user); + + $this->drupalGet('/admin/config/system/geocoder/geocoder-provider'); + $assert_session->statusCodeEquals(200); + + // Select googlemaps option from dropdown. + $assert_session->elementExists('css', '[data-drupal-selector="edit-geocoder-provider"]') + ->selectOption('googlemaps'); + $assert_session->buttonExists('Add')->press(); + $assert_session->pageTextContains('Add a Geocoder provider'); + + $container = $assert_session->elementExists('css', '[data-drupal-selector="geocoder-provider-add-form"]'); + $container->fillField('edit-label', 'GoogleMaps'); + $container->fillField('edit-id', 'googlemaps'); + $container->fillField('edit-apikey', 'oldkey12345'); + $container->pressButton('Save'); + $assert_session->pageTextContains('Created new geocoder provider'); + + // Create user account with 'access acquia cms tour dashboard' permission. + $account = $this->drupalCreateUser(['access acquia cms tour dashboard']); + $this->drupalLogin($account); + + // Visit the tour page. + $this->drupalGet('/admin/tour/dashboard'); + $assert_session->statusCodeEquals(200); + + $container = $assert_session->elementExists('css', '[data-drupal-selector="edit-geocoder"]'); + $assert_session->fieldValueEquals('maps_api_key', 'oldkey12345', $container); + $container->fillField('maps_api_key', ''); + $container->pressButton('Save'); + $assert_session->pageTextContains('Maps API key field is required.'); + + // Save a dummmy API key. + $dummy_key = 'keykeykey123'; + $container->fillField('edit-maps-api-key', $dummy_key); + $container->pressButton('Save'); + $assert_session->pageTextContains('The Google Maps API key has been set.'); + + // Test that the config values we expect are set correctly for Site Studio. + if ($this->moduleHandler->moduleExists('cohesion')) { + $cohesion_map_key = $this->config('cohesion.settings')->get('google_map_api_key'); + $this->assertSame($cohesion_map_key, $dummy_key); + } + + $configuration = GeocoderProvider::load('googlemaps')->get('configuration'); + $this->assertSame($configuration['apiKey'], $dummy_key); + } + +} diff --git a/modules/acquia_cms_tour/tests/src/Functional/GoogleTagManager.php b/modules/acquia_cms_tour/tests/src/Functional/GoogleTagManager.php index d7084745a..712218028 100644 --- a/modules/acquia_cms_tour/tests/src/Functional/GoogleTagManager.php +++ b/modules/acquia_cms_tour/tests/src/Functional/GoogleTagManager.php @@ -25,21 +25,6 @@ class GoogleTagManager extends BrowserTestBase { 'google_tag', ]; - /** - * Disable strict config schema checks in this test. - * - * Cohesion has a lot of config schema errors, and until they are all fixed, - * this test cannot pass unless we disable strict config schema checking - * altogether. Since strict config schema isn't critically important in - * testing this functionality, it's okay to disable it for now, but it should - * be re-enabled (i.e., this property should be removed) as soon as possible. - * - * @var bool - */ - // @codingStandardsIgnoreStart - protected $strictConfigSchema = FALSE; - // @codingStandardsIgnoreEnd - /** * Tests the Google Tag Manager Form. */ @@ -61,7 +46,8 @@ public function testGoogleTagManager() { $container->pressButton('Save'); $assert_session->pageTextContains('The configuration options have been saved.'); // Test that the config values we expect are set correctly. - $tag_id = $this->config($this->config('google_tag.settings')->get('default_google_tag_entity'))->get('tag_container_ids'); + $tag = $this->config('google_tag.settings')->get('default_google_tag_entity'); + $tag_id = $this->config('google_tag.container.' . $tag)->get('tag_container_ids'); $this->assertEquals($tag_id, [$dummy_tag]); } diff --git a/modules/acquia_cms_tour/tests/src/Functional/HelpIntegrationTest.php b/modules/acquia_cms_tour/tests/src/Functional/HelpIntegrationTest.php index 3866da06f..0060fc8f7 100644 --- a/modules/acquia_cms_tour/tests/src/Functional/HelpIntegrationTest.php +++ b/modules/acquia_cms_tour/tests/src/Functional/HelpIntegrationTest.php @@ -26,21 +26,6 @@ class HelpIntegrationTest extends BrowserTestBase { 'toolbar', ]; - /** - * Disable strict config schema checks in this test. - * - * Scheduler has a config schema errors, and until it's fixed, - * this test cannot pass unless we disable strict config schema checking - * altogether. Since strict config schema isn't critically important in - * testing this functionality, it's okay to disable it for now, but it should - * be re-enabled (i.e., this property should be removed) as soon as possible. - * - * @var bool - */ - // @codingStandardsIgnoreStart - protected $strictConfigSchema = FALSE; - // @codingStandardsIgnoreEnd - /** * Tests the Acquia CMS Tour module's integration with the core Help module. */ diff --git a/modules/acquia_cms_tour/tests/src/Functional/PermissionsTest.php b/modules/acquia_cms_tour/tests/src/Functional/PermissionsTest.php new file mode 100644 index 000000000..bd95e8579 --- /dev/null +++ b/modules/acquia_cms_tour/tests/src/Functional/PermissionsTest.php @@ -0,0 +1,53 @@ +drupalCreateRole([], 'content_administrator'); + $this->entityTypeManager = $this->container->get("entity_type.manager"); + } + + /** + * Tests permissions are granted to content_administrator role. + */ + public function testGrantPermissionsOnInstall(): void { + // Load the role and check its permissions. + $role_permissions = $this->entityTypeManager->getStorage('user_role')->load('content_administrator')->getPermissions(); + $this->assertEquals(['access acquia cms tour dashboard'], $role_permissions); + } + +} diff --git a/modules/acquia_cms_tour/tests/src/Functional/RecaptchaTest.php b/modules/acquia_cms_tour/tests/src/Functional/RecaptchaTest.php index d6a9d45fa..6f5c7c228 100644 --- a/modules/acquia_cms_tour/tests/src/Functional/RecaptchaTest.php +++ b/modules/acquia_cms_tour/tests/src/Functional/RecaptchaTest.php @@ -25,21 +25,6 @@ class RecaptchaTest extends BrowserTestBase { 'recaptcha', ]; - /** - * Disable strict config schema checks in this test. - * - * Cohesion has a lot of config schema errors, and until they are all fixed, - * this test cannot pass unless we disable strict config schema checking - * altogether. Since strict config schema isn't critically important in - * testing this functionality, it's okay to disable it for now, but it should - * be re-enabled (i.e., this property should be removed) as soon as possible. - * - * @var bool - */ - // @codingStandardsIgnoreStart - protected $strictConfigSchema = FALSE; - // @codingStandardsIgnoreEnd - /** * Tests the Recaptcha Form. */ diff --git a/modules/acquia_cms_tour/tests/src/Kernel/AcquiaTourDashboardTest.php b/modules/acquia_cms_tour/tests/src/Kernel/AcquiaTourDashboardTest.php index dd86497aa..5d6f4fc9e 100644 --- a/modules/acquia_cms_tour/tests/src/Kernel/AcquiaTourDashboardTest.php +++ b/modules/acquia_cms_tour/tests/src/Kernel/AcquiaTourDashboardTest.php @@ -22,21 +22,6 @@ class AcquiaTourDashboardTest extends KernelTestBase { 'acquia_cms_tour', ]; - /** - * Disable strict config schema checks in this test. - * - * Cohesion has a lot of config schema errors, and until they are all fixed, - * this test cannot pass unless we disable strict config schema checking - * altogether. Since strict config schema isn't critically important in - * testing this functionality, it's okay to disable it for now, but it should - * be re-enabled (i.e., this property should be removed) as soon as possible. - * - * @var bool - */ - // @codingStandardsIgnoreStart - protected $strictConfigSchema = FALSE; - // @codingStandardsIgnoreEnd - /** * Tests AcquiaCMSTour plugins and make sure they are sorted per weights. */