Exception when enabling 1.1.0 (dependency on purge)

Created on 19 January 2024, 10 months ago
Updated 6 February 2024, 9 months ago

It seems that the addition of the bunny_cdn_purger_settings config entity has introduced a dependency on the purge module.

If purge is not installed:

$ drush en bunny_cdn
 [error]  Error: Class "Drupal\purge\Plugin\Purge\Purger\PurgerSettingsBase" not found in include() (line 28 of /app/web/modules/contrib/bunny_cdn/src/Entity/BunnyCdnPurgerSettings.php) #0 /app/vendor/composer/ClassLoader.php(576): include()
#1 /app/vendor/composer/ClassLoader.php(427): Composer\Autoload\{closure}('/app/web/module...')
#2 [internal function]: Composer\Autoload\ClassLoader->loadClass('Drupal\\bunny_cd...')
#3 /app/web/core/lib/Drupal/Core/Entity/EntityType.php(439): is_subclass_of('Drupal\\bunny_cd...', 'Drupal\\Core\\Ent...')
#4 /app/web/core/lib/Drupal/Core/Entity/EntityType.php(323): Drupal\Core\Entity\EntityType->entityClassImplements('Drupal\\Core\\Ent...')
#5 /app/web/core/lib/Drupal/Core/Config/Entity/ConfigEntityType.php(65): Drupal\Core\Entity\EntityType->__construct(Array)
#6 /app/web/core/lib/Drupal/Core/Entity/Annotation/EntityType.php(60): Drupal\Core\Config\Entity\ConfigEntityType->__construct(Array)
#7 /app/web/core/lib/Drupal/Core/Entity/Annotation/ConfigEntityType.php(36): Drupal\Core\Entity\Annotation\EntityType->get()
#8 /app/web/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php(149): Drupal\Core\Entity\Annotation\ConfigEntityType->get()
#9 /app/web/core/lib/Drupal/Core/Entity/EntityTypeManager.php(116): Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery->getDefinitions()
#10 /app/web/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php(181): Drupal\Core\Entity\EntityTypeManager->findDefinitions()
#11 /app/web/core/lib/Drupal/Core/Extension/ModuleInstaller.php(289): Drupal\Core\Plugin\DefaultPluginManager->getDefinitions()
#12 /app/web/core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php(83): Drupal\Core\Extension\ModuleInstaller->install(Array, true)
#13 /app/vendor/drush/drush/src/Commands/pm/PmCommands.php(102): Drupal\Core\ProxyClass\Extension\ModuleInstaller->install(Array, true)
#14 [internal function]: Drush\Commands\pm\PmCommands->install(Array, Array)
#15 /app/vendor/consolidation/annotated-command/src/CommandProcessor.php(276): call_user_func_array(Array, Array)
#16 /app/vendor/consolidation/annotated-command/src/CommandProcessor.php(212): Consolidation\AnnotatedCommand\CommandProcessor->runCommandCallback(Array, Object(Consolidation\AnnotatedCommand\CommandData))
#17 /app/vendor/consolidation/annotated-command/src/CommandProcessor.php(176): Consolidation\AnnotatedCommand\CommandProcessor->validateRunAndAlter(Array, Array, Object(Consolidation\AnnotatedCommand\CommandData))
#18 /app/vendor/consolidation/annotated-command/src/AnnotatedCommand.php(391): Consolidation\AnnotatedCommand\CommandProcessor->process(Object(Symfony\Component\Console\Output\ConsoleOutput), Array, Array, Object(Consolidation\AnnotatedCommand\CommandData))
#19 /app/vendor/symfony/console/Command/Command.php(326): Consolidation\AnnotatedCommand\AnnotatedCommand->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#20 /app/vendor/symfony/console/Application.php(1081): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#21 /app/vendor/symfony/console/Application.php(320): Symfony\Component\Console\Application->doRunCommand(Object(Consolidation\AnnotatedCommand\AnnotatedCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#22 /app/vendor/symfony/console/Application.php(174): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#23 /app/vendor/drush/drush/src/Runtime/Runtime.php(110): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#24 /app/vendor/drush/drush/src/Runtime/Runtime.php(40): Drush\Runtime\Runtime->doRun(Array, Object(Symfony\Component\Console\Output\ConsoleOutput))
#25 /app/vendor/drush/drush/drush.php(139): Drush\Runtime\Runtime->run(Array)
#26 /app/vendor/drush/drush/drush(4): require('/app/vendor/dru...')
#27 /app/vendor/bin/drush(119): include('/app/vendor/dru...')
#28 {main}.

Or, in other words, as far as I can make out:

  • Really any code can invoke DefaultPluginManager->getDefinitions() for whatever reason , which always(?) loops through all definitions found including yours
  • Annotation\EntityType->get() does a `new ConfigEntityType(DEFINITION)`
  • ConfigEntityType::_construct() -> EntityType::construct() does if ($this->entityClassImplements(EntityChangedInterface::class)) {
  • which does is_subclass_of('Drupal\bunny_cdn\Entity\BunnyCdnPurgerSettings, something)
  • which triggers the class autoloader
  • which completely breaks because PurgerSettingsBase does not exist.

I don't know enough about config entities and annotations and stuff to be sure, but this looks pretty inescapable to me. Unless there's magic config somewhere that says "annotation system, please do not process this annotated entity class".

After this happens, all drush commands (en purge, pm-uninstall bunny_cdn, cr, ...) crash so you're stuck.

Looks like this really needs to be in a submodule.

🐛 Bug report
Status

Fixed

Version

1.1

Component

Code

Created by

🇳🇱Netherlands roderik Amsterdam,NL / Budapest,HU

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @roderik
  • 🇳🇱Netherlands roderik Amsterdam,NL / Budapest,HU

    (By the way we haven't been using your code yet in a way that can't be undone/changed. So... given your current reported install base... Feel free to solve in any way you see fit.)

  • 🇳🇱Netherlands roderik Amsterdam,NL / Budapest,HU
  • 🇧🇪Belgium dieterholvoet Brussels

    You're right, I don't think there's any way around it except adding the Purge module as a dependency as you suggested before, or creating a submodule as you suggested in this issue. But since such a big part of the module depends on Purge, the first option is probably a better idea. I'll try to work on this in the coming days, we'll need to define the dependency in info.yml and add an update hook enabling the new dependency if it isn't enabled yet.

  • Merge request !4Add purge dependency → (Merged) created by dieterholvoet
  • Status changed to Needs review 10 months ago
  • Status changed to Needs work 10 months ago
  • 🇳🇱Netherlands roderik Amsterdam,NL / Budapest,HU

    The dependency looks fine. (I agree with your earlier assessment that it ideally shouldn't be necessary, but hey -- people will want purge anyway.)

    Tested. The update hook won't help:

    composer require drupal/bunny_cdn:1.0.1 # problem free version
    
    composer require drupal/bunny_cdn:1.1.1 
    # just imagine 1.1.1. I did "require 1.1.0" immediately followed by patching .info and .install
    
    # NO OTHER commands executed, no HTTP requests done. Immediately:
    drush updb 
    PHP Fatal error:  Uncaught Error: Class "Drupal\purge\Plugin\Purge\Purger\PurgerSettingsBase" not found in /app/web/modules/contrib/bunny_cdn/src/Entity/BunnyCdnPurgerSettings.php:28
    Stack trace: (...)
    

    I'm setting NW for possibly removing the update hook, but feel free to interpret this as RTBC if you want to keep the hook to serve as... e.g. some 'documentation' about the evolution of the module...

  • 🇳🇱Netherlands roderik Amsterdam,NL / Budapest,HU

    For the user who would ever encounter this issue in theory: you need CLI / composer access to get out of it, and then:

    composer require drupal/bunny_cdn:1.0.1
    drush en purge
    composer require drupal/bunny_cdn:^1.1.1
    drusn updb # this will execute the update hook which does essentially nothing. But it proves that it runs fine, at least.
    
  • 🇧🇪Belgium dieterholvoet Brussels

    Hmm okay, I'll remove the update hook and add your instructions to the release page. But I don't think anyone else is using this module, so should be fine.

  • Pipeline finished with Skipped
    10 months ago
    #81258
  • Status changed to Fixed 10 months ago
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024