Problem/Motivation

symfony_mailer alongside the eca_ui module produces a crash, because eca_ui defines a service which might has undefined use statements.

eca_ui defines the service webprofiler.eca_ui that is implemented by the class Drupal\eca_ui\DataCollector\EcaDataCollector which uses Drupal\webprofiler\DataCollector\DrupalDataCollectorTrait. eca_ui does not depend on webprofiler and afaiu the service in question should only ever be used if the webprofiler module is enabled, which, in my case, it is not. This worked fine so far, i.e. eca_ui worked fine without webprofiler.

Now with symfony_mailer the site crashes, because MailerPass is iterating through all service definitions calling class_exists() for every service, including webprofiler.eca_ui. This causes the definition of Drupal\eca_ui\DataCollector\EcaDataCollector to be evaluated which in turn causes PHP to crash, because Drupal\webprofiler\DataCollector\DrupalDataCollectorTrait is missing.

I'm not sure, if the correct place to fix the issue is symfony_mailer or if rather all service definitions should be assumed to be valid. There have been issues opened at eca in the past concerning the service (see https://www.drupal.org/project/eca/issues/3367660), but my understanding is, that Drupal somehow handles the case, if a service (class) cannot be loaded and that the eca_ui service is intended to only being used, if webprofiler is enabled and else it should be blissfully ignored.

Steps to reproduce

Install eca_ui alongside symfony_mailer and open /update.php.

Proposed resolution

symfony_mailer should not crash, if a service class cannot be loaded. (Although I don't know if and how this would be possible.)

Comments

lukas_w created an issue. See original summary.

adamps’s picture

Thanks. I feel that the ECA code is correct - the code will only be loaded when the webprofiler module exists, and so the use will be valid.

In Symony library ContainerBuilder::getReflectionClass() the call to class_exists() is inside try/catch (\ReflectionException $e) {, so we can do the same. Please can you post the full text of your error message?

lukas_w’s picture

The error message I get is this one:

Got error 'PHP message: PHP Fatal error: Trait "Drupal\\webprofiler\\DataCollector\\DrupalDataCollectorTrait" not found in /home/lukas/sites/nextworkplace3/web/modules/contrib/eca/modules/ui/src/DataCollector/EcaDataCollector.php on line 15; PHP message: PHP Stack trace:; PHP message: PHP 1. {main}() /home/lukas/sites/nextworkplace3/web/update.php:0; PHP message: PHP 2. Drupal\\Core\\Update\\UpdateKernel->handle($request = class Symfony\\Component\\HttpFoundation\\Request { public $attributes = class Symfony\\Component\\HttpFoundation\\ParameterBag { protected $parameters = [...] }; public $request = class Symfony\\Component\\HttpFoundation\\InputBag { protected $parameters = [...] }; public $query = class Symfony\\Component\\HttpFoundation\\InputBag { protected $parameters = [...] }; public $server = class Symfony\\Component\\HttpFoundation\\ServerBag { protected $parameters = [...] }; public $files = class Symfony\\Component\\HttpFoundation\\FileBag { protected $parameters = [...] }; public $cookies = class Symfony\\Component\\HttpFoundation\\InputBag { protected $parameters = [...] }; public $headers = class Symfony\\Component\\HttpFoundation\\HeaderBag { protected $headers = [...]; protected $cacheControl = [...] }; protected $content = NULL; protected $languages = NULL; protected $charsets = NULL; protected $encodings = NULL; protected $acceptableContentTypes = N...; PHP message: PHP 3. Drupal\\Core\\DrupalKernel->boot() /home/lukas/sites/nextworkplace3/web/core/lib/Drupal/Core/Update/UpdateKernel.php:65; PHP message: PHP 4. Drupal\\Core\\Update\\UpdateKernel->initializeContainer() /home/lukas/sites/nextworkplace3/web/core/lib/Drupal/Core/DrupalKernel.php:515; PHP message: PHP 5. Drupal\\Core\\DrupalKernel->initializeContainer() /home/lukas/sites/nextworkplace3/web/core/lib/Drupal/Core/Update/UpdateKernel.php:42; PHP message: PHP 6. Drupal\\Core\\DrupalKernel->compileContainer() /home/lukas/sites/nextworkplace3/web/core/lib/Drupal/Core/DrupalKernel.php:972; PHP message: PHP 7. Symfony\\Component\\DependencyInjection\\ContainerBuilder->compile($resolveEnvPlaceholders = *uninitialized*) /home/lukas/sites/nextworkplace3/web/core/lib/Drupal/Core/DrupalKernel.php:1449; PHP message: PHP 8. Symfony\\Component\\DependencyInjection\\Compiler\\Compiler->compile($container = class Drupal\\Core\\DependencyInjection\\ContainerBuilder { protected $parameterBag = class Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag { protected $parameters = [...]; protected $resolved = FALSE; protected array $deprecatedParameters = [...] }; protected $services = ['kernel' => class Drupal\\Core\\Update\\UpdateKernel { ... }, 'keyvalue' => class Drupal\\Core\\KeyValueStore\\KeyValueFactory { ... }, 'serialization.phpserialize' => class Drupal\\Component\\Serialization\\PhpSerialize { ... }, 'keyvalue.database' => class Drupal\\Core\\KeyValueStore\\KeyValueDatabaseFactory { ... }]; protected $privates = []; protected $fileMap = []; protected $methodMap = []; protected $factories = []; protected $aliases = []; protected $loading = []; protected $resolving = []; protected $syntheticIds = []; private array ${Symfony\\Component\\DependencyInjection\\Container}envCache = []; private bool ${Symfony\\C...; PHP message: PHP 9. Drupal\\symfony_mailer\\MailerPass->process($container = class Drupal\\Core\\DependencyInjection\\ContainerBuilder { protected $parameterBag = class Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag { protected $parameters = [...]; protected $resolved = FALSE; protected array $deprecatedParameters = [...] }; protected $services = ['kernel' => class Drupal\\Core\\Update\\UpdateKernel { ... }, 'keyvalue' => class Drupal\\Core\\KeyValueStore\\KeyValueFactory { ... }, 'serialization.phpserialize' => class Drupal\\Component\\Serialization\\PhpSerialize { ... }, 'keyvalue.database' => class Drupal\\Core\\KeyValueStore\\KeyValueDatabaseFactory { ... }]; protected $privates = []; protected $fileMap = []; protected $methodMap = []; protected $factories = []; protected $aliases = []; protected $loading = []; protected $resolving = []; protected $syntheticIds = []; private array ${Symfony\\Component\\DependencyInjection\\Container}envCache = []; private bool ${Symfony\\Component\\DependencyInje...; PHP message: PHP 10. class_exists($class = 'Drupal\\\\eca_ui\\\\DataCollector\\\\EcaDataCollector') /home/lukas/sites/nextworkplace3/web/modules/contrib/symfony_mailer/src/MailerPass.php:22; PHP message: PHP 11. Composer\\Autoload\\ClassLoader->loadClass($class = 'Drupal\\\\eca_ui\\\\DataCollector\\\\EcaDataCollector') /home/lukas/sites/nextworkplace3/web/modules/contrib/symfony_mailer/src/MailerPass.php:22; PHP message: PHP 12. {closure:/home/lukas/sites/nextworkplace3/vendor/composer/ClassLoader.php:575-577}($file = '/home/lukas/sites/nextworkplace3/web/modules/contrib/eca/modules/ui/src/DataCollector/EcaDataCollector.php') /home/lukas/sites/nextworkplace3/vendor/composer/ClassLoader.php:427; PHP message: PHP 13. include() /home/lukas/sites/nextworkplace3/vendor/composer/ClassLoader.php:576'

adamps’s picture

Status: Active » Postponed (maintainer needs more info)

Strange, I can see EcaDataCollector only in the 1.x series https://git.drupalcode.org/project/eca/-/blob/1.1.x/modules/ui/src/DataC..., which is no longer supported.

Anyway I edited a Core service to use a non-existent trait and it generates an error that I cannot catch. Then I commented out the code from this module, and still got an error, presumably from one of the Core service passes, which contain calls to registerForAutoconfiguration() or new \ReflectionMethod. Strange again, how it generates an error now, but it didn't at first.

So I no longer agree that the ECA code is good (and anyway the code seems to have been removed now?). It's common to have a plug-in definition that wouldn't compile, because the code will only be loaded if the module containing the plug-in manager exists anyway. However for a service it's much less common, and can easily trigger an error in a compiler pass.

In summary, I'm not yet convinced that this is a bug here (rather than ECA), and I'm not yet aware of anything that I can do about it.

lukas_w’s picture

Indeed, the site in question stills uses eca 1.x, I hadn't checked that. I will then update eca and there is nothing to be done here.

Sorry for the noise and thanks for looking into it!

adamps’s picture

Status: Postponed (maintainer needs more info) » Closed (outdated)

Thanks for the update

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.