drupal-contrib-mgmt

📁 grasmash/drupal-claude-skills 📅 Jan 26, 2026
0
总安装量
3
周安装量
安装命令
npx skills add https://github.com/grasmash/drupal-claude-skills --skill drupal-contrib-mgmt

Agent 安装分布

antigravity 3
cursor 2
claude-code 2
gemini-cli 2
neovate 1

Skill 文档

Drupal Contrib Module Management

Core Update Workflow

Standard Module Update

# Update a single module
composer require drupal/module_name --with-all-dependencies

# Update to specific version
composer require drupal/module_name:^3.0 --with-all-dependencies

# Update multiple modules
composer require drupal/module_a drupal/module_b --with-all-dependencies

# After any update, ALWAYS run database updates
drush updb -y

# Clear cache if needed
drush cr

# CRITICAL: Test by visiting pages to check for fatal errors
# Visit at least one page that uses the updated module

Major Version Upgrades

When upgrading to a new major version (e.g., 2.x → 3.x):

  1. Check compatibility: Ensure module supports your Drupal core version
  2. Search issue queue for patches: https://www.drupal.org/project/issues/MODULE_NAME?categories=All
  3. Use Drupal Lenient for version requirement issues (see below)
  4. Apply patches via composer.json (see Patch Management section)
  5. Run upgrade_status to check for deprecations

Checking Drupal 11 Compatibility

Three methods to check if a module is D11 compatible (in order of preference):

Method 1: Check .info.yml File (Fastest, Most Reliable)

# Check the module's .info.yml file for core_version_requirement
cat docroot/modules/contrib/MODULE_NAME/MODULE_NAME.info.yml | grep core_version_requirement

What to look for:

core_version_requirement: ^9.5 || ^10 || ^11     # ✅ D11 compatible
core_version_requirement: ^8 || ^9 || ^10 || ^11  # ✅ D11 compatible
core_version_requirement: ^9 || ^10                # ❌ Not D11 compatible yet

Example:

$ cat docroot/modules/contrib/admin_toolbar/admin_toolbar.info.yml | grep core_version
core_version_requirement: ^9.5 || ^10 || ^11
# ✅ This module declares D11 support!

Method 2: Use Composer Commands (Works Before Installing)

# Check what versions are available and their constraints
composer show drupal/MODULE_NAME --all | grep -A5 "^versions"

# Check currently installed version
composer show drupal/MODULE_NAME | grep versions

What to look for:

  • Version number (e.g., 3.6.2)
  • Check Drupal.org for release notes mentioning D11

Method 3: Check Drupal.org Project Page

Only use as fallback when above methods aren’t conclusive.

https://www.drupal.org/project/MODULE_NAME

Look for:

  • Latest release notes mentioning “Drupal 11”
  • Module page header showing D11 compatibility badge
  • Issue queue for D11 compatibility issues

Important Notes:

  • ⚠️ Module may declare D11 support but still have deprecation warnings
  • ⚠️ upgrade_status warnings don’t mean module is incompatible
  • ⚠️ “Check manually” status often means runtime version checks (false positive)
  • ✅ If .info.yml declares ^11 support, module maintainer says it works

Real-World Examples:

# admin_toolbar - Already D11 compatible
$ cat docroot/modules/contrib/admin_toolbar/admin_toolbar.info.yml | grep core_version
core_version_requirement: ^9.5 || ^10 || ^11

# But upgrade_status shows warnings about _drupal_flush_css_js()
# This is a FALSE POSITIVE - module handles it with version checks

# audiofield - Already D11 compatible
$ cat docroot/modules/contrib/audiofield/audiofield.info.yml | grep core_version
core_version_requirement: ^8 || ^9 || ^10 || ^11

# Has deprecation warnings but maintainer declares D11 support

Drupal Lenient Plugin

The mglaman/composer-drupal-lenient plugin allows installing modules that haven’t updated their version requirements yet.

Setup

{
  "require": {
    "mglaman/composer-drupal-lenient": "^1.0"
  },
  "config": {
    "allow-plugins": {
      "mglaman/composer-drupal-lenient": true
    }
  },
  "extra": {
    "drupal-lenient": {
      "allowed-list": [
        "drupal/module_name",
        "drupal/another_module"
      ]
    }
  }
}

Usage

# Add module to allowed-list, then install
composer require drupal/module_name --with-all-dependencies

Patch Management (cweagans/composer-patches)

Patch Configuration

{
  "require": {
    "cweagans/composer-patches": "^1.7"
  },
  "config": {
    "allow-plugins": {
      "cweagans/composer-patches": true
    }
  },
  "extra": {
    "patches": {
      "drupal/module_name": {
        "Description of patch": "https://www.drupal.org/files/issues/2024-01-15/module-issue-1234567-8.patch",
        "Local patch": "patches/custom-fix.patch"
      }
    },
    "enable-patching": true,
    "patchLevel": {
      "drupal/core": "-p2"
    }
  }
}

Finding Patches

Issue Queue Search: https://www.drupal.org/project/issues/MODULE_NAME?categories=All

Patch Naming Convention:

  • Format: module-issue-NODEID-COMMENT.patch
  • Example: audiofield-d11-3432063-12.patch
  • Node ID is the issue number (visit drupal.org/node/NODEID)

When Existing Patches Fail After Update:

  1. Extract node ID from patch filename (e.g., 3432063 from above)
  2. Visit https://www.drupal.org/node/3432063
  3. Look for updated patch in latest comments
  4. Update composer.json with new patch URL

Creating Local Patches

# Method 1: Git diff
cd docroot/modules/contrib/module_name
# Make your changes
git diff > /path/to/project/patches/module-custom-fix.patch

# Method 2: diff command
diff -Naur original/file.php modified/file.php > patches/module-fix.patch

# Apply in composer.json
{
  "extra": {
    "patches": {
      "drupal/module_name": {
        "Custom fix description": "patches/module-custom-fix.patch"
      }
    }
  }
}

Patch Application

# Install with patches
composer install

# If patches fail, composer will error
# Update or remove failing patches, then retry
composer install

# Force re-patch
composer update drupal/module_name --with-all-dependencies

Drupal 11 Compatibility Workflow

Step 1: Analyze Readiness

# Scan all modules
drush upgrade_status:analyze --all

# Scan specific modules
drush upgrade_status:analyze module1 module2 module3

# Machine-readable output
drush upgrade_status:analyze --all --format=json > d11-report.json
drush upgrade_status:analyze --all --format=codeclimate > d11-report-ci.json

# Scan only custom code
drush upgrade_status:analyze --all --ignore-contrib

# Scan only contrib
drush upgrade_status:analyze --all --ignore-custom

Step 2: Identify Issues

Major Issues (blocking):

  • REQUEST_TIME constant → Use \Drupal::time()->getRequestTime()
  • user_roles() → Use \Drupal\user\Entity\Role::loadMultiple()
  • file_validate_extensions() → Use file.validator service
  • system_retrieve_file() → No replacement (refactor required)
  • _drupal_flush_css_js() → Use AssetQueryStringInterface::reset()

Info.yml Issues:

  • Update core_version_requirement to include ^11
  • Example: core_version_requirement: ^9 || ^10 || ^11

Step 3: Fix Custom Code

Example: Inject Time Service

use Drupal\Core\Datetime\TimeInterface;

class MyController extends ControllerBase {
  protected $time;

  public function __construct(TimeInterface $time) {
    $this->time = $time;
  }

  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('datetime.time')
    );
  }

  public function myMethod() {
    // OLD: $timestamp = REQUEST_TIME;
    $timestamp = $this->time->getRequestTime();
  }
}

Example: Replace user_roles()

// OLD:
$roles = user_roles(TRUE);

// NEW:
use Drupal\user\Entity\Role;

$roles = Role::loadMultiple();
$role_options = [];
foreach ($roles as $role_id => $role) {
  if ($role_id !== 'anonymous') {
    $role_options[$role_id] = $role->label();
  }
}

Step 4: Create .info.yml Patches

# Create patch for contrib module
cd docroot/modules/contrib/module_name
git diff module.info.yml > /path/to/patches/module-d11-info.patch

# Patch content:
--- a/module.info.yml
+++ b/module.info.yml
@@ -2,7 +2,7 @@
 name: Module Name
 type: module
 description: Module description
-core_version_requirement: ^9 || ^10
+core_version_requirement: ^9 || ^10 || ^11

Step 5: Apply Patches & Update Lenient List

{
  "extra": {
    "patches": {
      "drupal/module_name": {
        "Drupal 11 .info.yml support": "patches/module-d11-info.patch"
      }
    },
    "drupal-lenient": {
      "allowed-list": [
        "drupal/module_name"
      ]
    }
  }
}
composer install
drush updb -y
drush cr

Step 6: Verify Fixes

# Re-scan to confirm issues resolved
drush upgrade_status:analyze module_name

# Should show "No known issues found"

Complete Update Checklist

  • Check current module version: composer show drupal/module_name
  • Search issue queue for known issues
  • Check if module is D11 compatible
  • Update composer.json with new version
  • Add to drupal-lenient if needed
  • Search for and apply necessary patches
  • Run composer require drupal/module_name:^X.0 --with-all-dependencies
  • Run drush updb -y
  • Run drush cr
  • Run drush upgrade_status:analyze module_name
  • Test module functionality by visiting relevant pages
  • Check for PHP errors/warnings in logs
  • Commit changes with descriptive message

Troubleshooting

Patch Won’t Apply

# Error: "Cannot apply patch..."
# 1. Check if module version changed
composer show drupal/module_name

# 2. Search issue queue for updated patch
# Visit drupal.org/node/NODEID (from patch filename)

# 3. Update composer.json with new patch URL
# 4. Or remove patch if merged upstream

Version Conflict

# Error: "drupal/module_name requires drupal/core ^9"
# Add to drupal-lenient allowed-list

Patch Already Applied

# Error: "patch ... has already been applied"
# Module maintainer merged the patch - remove from composer.json

Database Update Fails

# Error during drush updb
# 1. Check error message carefully
# 2. May need to disable module, update, re-enable
drush pm:uninstall module_name
composer require drupal/module_name --with-all-dependencies
drush pm:enable module_name
drush updb -y

Best Practices

  1. Always use --with-all-dependencies for module updates
  2. Always run drush updb after composer updates
  3. Test immediately after updates (visit pages, check logs)
  4. Keep patches organized in a patches/ directory
  5. Document patches with descriptive names and comments
  6. Check issue queues first before creating custom patches
  7. Use upgrade_status to validate D11 compatibility
  8. Commit atomically: one module update per commit
  9. Use descriptive commit messages with patch references
  10. Keep drupal-lenient list minimal (only when necessary)

Developing Contrib Modules Locally

When actively developing a contrib module for drupal.org, use this workflow to avoid constantly updating via composer:

Symlink Development Workflow

# 1. Set up module repository in temp location
cd /tmp
git clone git@git.drupal.org:project/module_name.git
cd module_name
# Make your changes...

# 2. Remove composer-installed version and symlink your dev copy
cd /path/to/project
rm -rf docroot/modules/contrib/module_name
ln -s /tmp/module_name docroot/modules/contrib/module_name

# 3. Develop and test
# Make changes in /tmp/module_name
# Test immediately in your Drupal site
drush cr  # Clear cache as needed

# 4. When ready to publish
cd /tmp/module_name
git add -A
git commit -m "Your changes"
git push origin 1.0.x

# 5. Clean up: remove symlink and reinstall from composer
cd /path/to/project
rm docroot/modules/contrib/module_name
composer install  # Reinstalls from drupal.org

Benefits:

  • Test changes immediately without composer update cycles
  • Keep git history in the module’s own repo
  • Easy to commit and push changes
  • No risk of accidentally committing module code to main project

Important Notes:

  • Don’t forget to remove the symlink before committing project changes
  • Clear Drupal cache after changes: drush cr
  • When done developing, always reinstall via composer to ensure clean state
  • Useful for fixing autoloader issues, adding features, or troubleshooting

Example: Fixing recurly_commerce_api autoloader issue

# Module needed composer.json autoload section
cd /tmp/recurly_commerce_api
# Edit composer.json to add autoload section
git commit -m "Add PSR-4 autoload configuration"
git push origin 1.0.x

# Back in main project
rm docroot/modules/contrib/recurly_commerce_api
composer install  # Gets latest with fix
drush cr

Common Patterns

Pattern: Update Module with Known Patch

# 1. Find patch in issue queue
# 2. Add to composer.json patches section
# 3. Update module
composer require drupal/module_name:^3.0 --with-all-dependencies
drush updb -y
drush cr
# 4. Test
# 5. Commit
git add composer.json composer.lock patches/
git commit -m "Update module_name to 3.0 with D11 compatibility patch"

Pattern: Fix Contrib D11 Issue

# 1. Scan for issues
drush upgrade_status:analyze module_name

# 2. Create info.yml patch if needed
cd docroot/modules/contrib/module_name
# Edit module.info.yml to add ^11
git diff module.info.yml > ../../../patches/module-d11-info.patch

# 3. Add patch to composer.json
# 4. Apply
composer install
drush cr

# 5. Verify
drush upgrade_status:analyze module_name

Pattern: Major Version Upgrade with Breaking Changes

# 1. Read CHANGELOG/UPDATE.md for breaking changes
# 2. Check issue queue for upgrade path documentation
# 3. Backup database before upgrade
drush sql:dump > backup-before-update.sql

# 4. Update module
composer require drupal/module_name:^3.0 --with-all-dependencies

# 5. Run updates
drush updb -y

# 6. Check for errors
drush watchdog:show --severity=Error --count=20

# 7. Test thoroughly
# 8. If issues, can rollback:
# git checkout composer.json composer.lock
# composer install
# drush sql:cli < backup-before-update.sql

Reference Links