- Issue created by @eduardo morales alberti
After execute the PHUnit test we got an error.
If we comment the code from \Drupal\Core\Cache\CacheTagsChecksumTrait::invalidateTags the error is gone.
$in_transaction = $this->getDatabaseConnection()->inTransaction();
if ($in_transaction) {
if (empty($this->delayedTags)) {
// @todo in drupal:11.0.0, remove the conditional and only call the
// TransactionManager().
if ($this->getDatabaseConnection()->transactionManager()) {
$this->getDatabaseConnection()->transactionManager()->addPostTransactionCallback([$this, 'rootTransactionEndCallback']);
}
else {
$this->getDatabaseConnection()->addRootTransactionEndCallback([$this, 'rootTransactionEndCallback']);
}
}
$this->delayedTags = Cache::mergeTags($this->delayedTags, $tags);
}
The problem is that the transaction is destroyed when the PHPUnit tables are removed, and then gives the error.
Error:
PHP Fatal error: Uncaught TypeError: Drupal\Core\Database\StatementWrapperIterator::__construct(): Argument #2 ($clientConnection) must be of type object, null given, called in /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php on line 582 and defined in /var/www/html/docroot/core/lib/Drupal/Core/Database/StatementWrapperIterator.php:55
Stack trace:
#0 /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php(582): Drupal\Core\Database\StatementWrapperIterator->__construct()
#1 /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php(848): Drupal\Core\Database\Connection->prepareStatement()
#2 /var/www/html/docroot/core/lib/Drupal/Core/Database/Query/Select.php(524): Drupal\Core\Database\Connection->query()
#3 /var/www/html/docroot/core/lib/Drupal/Core/Database/Query/Merge.php(379): Drupal\Core\Database\Query\Select->execute()
#4 /var/www/html/docroot/core/lib/Drupal/Core/Cache/DatabaseCacheTagsChecksum.php(42): Drupal\Core\Database\Query\Merge->execute()
#5 /var/www/html/docroot/core/lib/Drupal/Core/Cache/CacheTagsChecksumTrait.php(45): Drupal\Core\Cache\DatabaseCacheTagsChecksum->doInvalidateTags()
#6 [internal function]: Drupal\Core\Cache\DatabaseCacheTagsChecksum->rootTransactionEndCallback()
#7 /var/www/html/docroot/core/lib/Drupal/Core/Database/Transaction/TransactionManagerBase.php(488): call_user_func()
#8 /var/www/html/docroot/core/lib/Drupal/Core/Database/Transaction/TransactionManagerBase.php(296): Drupal\Core\Database\Transaction\TransactionManagerBase->processPostTransactionCallbacks()
#9 /var/www/html/docroot/core/lib/Drupal/Core/Database/Transaction.php(93): Drupal\Core\Database\Transaction\TransactionManagerBase->unpile()
#10 [internal function]: Drupal\Core\Database\Transaction->__destruct()
#11 {main}
thrown in /var/www/html/docroot/core/lib/Drupal/Core/Database/StatementWrapperIterator.php on line 55
PHP Stack trace:
PHP 1. newrelic_exception_handler($exception = class TypeError { protected $message = 'Drupal\\Core\\Database\\StatementWrapperIterator::__construct(): Argument #2 ($clientConnection) must be of type object, null given, called in /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php on line 582'; private string ${Error}string = 'TypeError: Drupal\\Core\\Database\\StatementWrapperIterator::__construct(): Argument #2 ($clientConnection) must be of type object, null given, called in /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php on line 582 and defined in /var/www/html/docroot/core/lib/Drupal/Core/Database/StatementWrapperIterator.php:55\nStack trace:\n#0 /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php(582): Drupal\\Core\\Database\\StatementWrapperIterator->__construct()\n#1 /var/www/html/docroot/core/lib'...; protected $code = 0; protected string $file = '/var/www/html/docroot/core/lib/Drupal/Core/Database/StatementWrapperIterator.php'; protected int $line = 55; private array ${Error}trace = [0 => [...], 1 => [...], 2 => [...], 3 => [...], 4 => [...], 5 => [...], 6 => [...], 7 => [...], 8 => [...], 9 => [...], 10 => [...]]; private ?Throwable ${Error}previous = NULL }) Unknown:0
Fatal error: Uncaught TypeError: Drupal\Core\Database\StatementWrapperIterator::__construct(): Argument #2 ($clientConnection) must be of type object, null given, called in /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php on line 582 and defined in /var/www/html/docroot/core/lib/Drupal/Core/Database/StatementWrapperIterator.php on line 55
Call Stack:
2.8847 20329880 1. newrelic_exception_handler($exception = class TypeError { protected $message = 'Drupal\\Core\\Database\\StatementWrapperIterator::__construct(): Argument #2 ($clientConnection) must be of type object, null given, called in /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php on line 582'; private string ${Error}string = 'TypeError: Drupal\\Core\\Database\\StatementWrapperIterator::__construct(): Argument #2 ($clientConnection) must be of type object, null given, called in /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php on line 582 and defined in /var/www/html/docroot/core/lib/Drupal/Core/Database/StatementWrapperIterator.php:55\nStack trace:\n#0 /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php(582): Drupal\\Core\\Database\\StatementWrapperIterator->__construct()\n#1 /var/www/html/docroot/core/lib'...; protected $code = 0; protected string $file = '/var/www/html/docroot/core/lib/Drupal/Core/Database/StatementWrapperIterator.php'; protected int $line = 55; private array ${Error}trace = [0 => [...], 1 => [...], 2 => [...], 3 => [...], 4 => [...], 5 => [...], 6 => [...], 7 => [...], 8 => [...], 9 => [...], 10 => [...]]; private ?Throwable ${Error}previous = NULL }) Unknown:0
TypeError: Drupal\Core\Database\StatementWrapperIterator::__construct(): Argument #2 ($clientConnection) must be of type object, null given, called in /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php on line 582 in /var/www/html/docroot/core/lib/Drupal/Core/Database/StatementWrapperIterator.php on line 55
Call Stack:
2.8844 20394696 1. Drupal\Core\Database\Transaction->__destruct() /var/www/html/docroot/core/lib/Drupal/Core/Database/Transaction.php:0
2.8844 20394696 2. Drupal\Core\Database\Transaction\TransactionManagerBase->unpile($name = 'drupal_transaction', $id = '67b7189e476c66.98966785') /var/www/html/docroot/core/lib/Drupal/Core/Database/Transaction.php:93
2.8844 20394696 3. Drupal\Core\Database\Transaction\TransactionManagerBase->processPostTransactionCallbacks() /var/www/html/docroot/core/lib/Drupal/Core/Database/Transaction/TransactionManagerBase.php:296
2.8844 20394696 4. call_user_func:{/var/www/html/docroot/core/lib/Drupal/Core/Database/Transaction/TransactionManagerBase.php:488}($callback = [0 => class Drupal\Core\Cache\DatabaseCacheTagsChecksum { protected $connection = class Drupal\mysql\Driver\Database\mysql\Connection { ... }; protected $invalidatedTags = [...]; protected $delayedTags = [...]; protected $tagCache = [...] }, 1 => 'rootTransactionEndCallback'], $args = TRUE) /var/www/html/docroot/core/lib/Drupal/Core/Database/Transaction/TransactionManagerBase.php:488
2.8844 20394928 5. Drupal\Core\Cache\DatabaseCacheTagsChecksum->rootTransactionEndCallback($success = TRUE) /var/www/html/docroot/core/lib/Drupal/Core/Database/Transaction/TransactionManagerBase.php:488
2.8844 20394928 6. Drupal\Core\Cache\DatabaseCacheTagsChecksum->doInvalidateTags($tags = [0 => 'node_list', 1 => 'node_list:page', 2 => 'http_response']) /var/www/html/docroot/core/lib/Drupal/Core/Cache/CacheTagsChecksumTrait.php:45
2.8845 20397680 7. Drupal\Core\Database\Query\Merge->execute() /var/www/html/docroot/core/lib/Drupal/Core/Cache/DatabaseCacheTagsChecksum.php:42
2.8845 20401376 8. Drupal\Core\Database\Query\Select->execute() /var/www/html/docroot/core/lib/Drupal/Core/Database/Query/Merge.php:379
2.8846 20402832 9. Drupal\Core\Database\Connection->query($query = 'SELECT 1 AS "expression"\nFROM\n{cachetags} "cachetags"\nWHERE "tag" = :db_condition_placeholder_0', $args = [':db_condition_placeholder_0' => 'node_list'], $options = []) /var/www/html/docroot/core/lib/Drupal/Core/Database/Query/Select.php:524
2.8846 20403272 10. Drupal\Core\Database\Connection->prepareStatement($query = 'SELECT 1 AS "expression"\nFROM\n{cachetags} "cachetags"\nWHERE "tag" = :db_condition_placeholder_0', $options = ['fetch' => 5, 'allow_delimiter_in_query' => FALSE, 'allow_square_brackets' => FALSE, 'pdo' => []], $allow_row_count = ???) /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php:848
2.8846 20403624 11. Drupal\Core\Database\StatementWrapperIterator->__construct($connection = class Drupal\mysql\Driver\Database\mysql\Connection { protected $target = 'default'; protected $key = 'default'; protected $logger = NULL; protected $transactionLayers = []; protected $driverClasses = []; protected $statementWrapperClass = 'Drupal\\Core\\Database\\StatementWrapperIterator'; protected $transactionalDDLSupport = FALSE; protected $connection = NULL; protected $connectionOptions = ['driver' => 'mysql', 'username' => 'db', 'password' => 'db', 'host' => 'db', 'database' => 'db', 'namespace' => 'Drupal\\mysql\\Driver\\Database\\mysql', 'port' => 3306, 'autoload' => 'core/modules/mysql/src/Driver/Database/mysql/', 'prefix' => 'test84046328', 'pdo' => [...], 'init_commands' => [...]]; protected $schema = class Drupal\mysql\Driver\Database\mysql\Schema { protected $connection = ...; protected $placeholder = 136; protected $defaultSchema = 'public'; protected $uniqueIdentifier = '67b7189c994d92.36549461'; protected $mysqlStringTypes = [...] }; protected string $prefix = 'test84046328'; protected array $tablePlaceholderReplacements = [0 => '"test84046328', 1 => '"']; protected $prefixes = []; protected $prefixSearch = []; protected $prefixReplace = []; protected $unprefixedTablesMap = []; protected $escapedTables = ['config' => 'config', 'cachetags' => 'cachetags', 'cache_container' => 'cache_container', 'node_field_data' => 'node_field_data', 'node_field_revision' => 'node_field_revision', 'users' => 'users', 'node' => 'node', 'router' => 'router', 'menu_tree' => 'menu_tree', 'node_revision' => 'node_revision', 'node__body' => 'node__body', 'entity_mesh' => 'entity_mesh']; protected $escapedFields = ['' => '', 'table_schema' => '"table_schema"', 'table_name' => '"table_name"', 'collection' => '"collection"', 'name' => '"name"', 'config.name' => '"config"."name"', 'data' => '"data"', 'tag' => '"tag"', 'invalidations' => '"invalidations"', 'column_name' => '"column_name"', 'content_translation_source' => '"content_translation_source"', 'content_translation_outdated' => '"content_translation_outdated"', 'base.uid' => '"base"."uid"', 'base.uuid' => '"base"."uuid"', 'base.langcode' => '"base"."langcode"', 'vid' => '"vid"', 'type' => '"type"', 'uuid' => '"uuid"', 'langcode' => '"langcode"', 'nid' => '"nid"', 'revision_uid' => '"revision_uid"', 'revision_timestamp' => '"revision_timestamp"', 'revision_log' => '"revision_log"', 'revision_default' => '"revision_default"', 'status' => '"status"', 'uid' => '"uid"', 'title' => '"title"', 'created' => '"created"', 'changed' => '"changed"', 'promote' => '"promote"', 'sticky' => '"sticky"', 'default_langcode' => '"default_langcode"', 'revision_translation_affected' => '"revision_translation_affected"', 'entity_id' => '"entity_id"', 'revision_id' => '"revision_id"', 'bundle' => '"bundle"', 'delta' => '"delta"', 'body_value' => '"body_value"', 'body_summary' => '"body_summary"', 'body_format' => '"body_format"', 'fit' => '"fit"', 'path' => '"path"', 'pattern_outline' => '"pattern_outline"', 'number_parts' => '"number_parts"', 'route' => '"route"', 'menu_tree.menu_name' => '"menu_tree"."menu_name"', 'id' => '"id"', 'menu_name' => '"menu_name"', 'mlid' => '"mlid"', 'route_name' => '"route_name"', 'route_parameters' => '"route_parameters"', 'url' => '"url"', 'description' => '"description"', 'parent' => '"parent"', 'weight' => '"weight"', 'options' => '"options"', 'expanded' => '"expanded"', 'enabled' => '"enabled"', 'provider' => '"provider"', 'metadata' => '"metadata"', 'class' => '"class"', 'form_class' => '"form_class"', 'discovered' => '"discovered"', 'has_children' => '"has_children"', 'depth' => '"depth"', 'p1' => '"p1"', 'p2' => '"p2"', 'p3' => '"p3"', 'p4' => '"p4"', 'p5' => '"p5"', 'p6' => '"p6"', 'p7' => '"p7"', 'p8' => '"p8"', 'p9' => '"p9"', 'route_param_key' => '"route_param_key"', 'menu_tree.id' => '"menu_tree"."id"', 'base.nid' => '"base"."nid"', 'revision.vid' => '"revision"."vid"', 'revision.langcode' => '"revision"."langcode"', 'revision.revision_uid' => '"revision"."revision_uid"', 'revision.revision_timestamp' => '"revision"."revision_timestamp"', 'revision.revision_log' => '"revision"."revision_log"', 'revision.revision_default' => '"revision"."revision_default"', 'base.type' => '"base"."type"', 'revision.nid' => '"revision"."nid"', 'deleted' => '"deleted"', 'source_entity_type' => '"source_entity_type"', 'source_entity_id' => '"source_entity_id"', 'source_entity_langcode' => '"source_entity_langcode"', 'source_hash_id' => '"source_hash_id"', 'source_entity_bundle' => '"source_entity_bundle"', 'source_title' => '"source_title"', 'category' => '"category"', 'subcategory' => '"subcategory"', 'target_link_type' => '"target_link_type"', 'target_href' => '"target_href"', 'target_path' => '"target_path"', 'target_scheme' => '"target_scheme"', 'target_entity_type' => '"target_entity_type"', 'target_entity_id' => '"target_entity_id"', 'target_entity_langcode' => '"target_entity_langcode"', 'target_hash_id' => '"target_hash_id"', 'target_entity_bundle' => '"target_entity_bundle"', 'target_title' => '"target_title"']; protected $escapedAliases = ['name' => '"name"', 'config' => '"config"', 'expression' => '"expression"', 'cachetags' => '"cachetags"', 'uid' => '"uid"', 'uuid' => '"uuid"', 'langcode' => '"langcode"', 'base' => '"base"', 'menu_name' => '"menu_name"', 'menu_tree' => '"menu_tree"', 'id' => '"id"', 'vid' => '"vid"', 'revision_uid' => '"revision_uid"', 'revision_timestamp' => '"revision_timestamp"', 'revision_log' => '"revision_log"', 'revision_default' => '"revision_default"', 'nid' => '"nid"', 'type' => '"type"', 'isDefaultRevision' => '"isDefaultRevision"', 'revision' => '"revision"', 't' => '"t"']; protected $rootTransactionEndCallbacks = []; protected $identifierQuotes = [0 => '"', 1 => '"']; private array ${Drupal\Core\Database\Connection}enabledEvents = []; protected Drupal\Core\Database\Transaction\TransactionManagerInterface|false $transactionManager = class Drupal\mysql\Driver\Database\mysql\TransactionManager { private ?string ${Drupal\Core\Database\Transaction\TransactionManagerBase}rootId = '67b7189e476c66.98966785'; private array ${Drupal\Core\Database\Transaction\TransactionManagerBase}stack = [...]; private array ${Drupal\Core\Database\Transaction\TransactionManagerBase}voidedItems = [...]; private array ${Drupal\Core\Database\Transaction\TransactionManagerBase}postTransactionCallbacks = [...]; private Drupal\Core\Database\Transaction\ClientConnectionTransactionState ${Drupal\Core\Database\Transaction\TransactionManagerBase}connectionTransactionState = enum Drupal\Core\Database\Transaction\ClientConnectionTransactionState::Committed; protected readonly Drupal\Core\Database\Connection $connection = ... }; protected $needsCleanup = FALSE; private $serverVersion = '10.11.10-MariaDB-ubu2204-log' }, $clientConnection = NULL, $query = 'SELECT 1 AS "expression"\nFROM\n"test84046328cachetags" "cachetags"\nWHERE "tag" = :db_condition_placeholder_0', $options = [], $rowCountEnabled = FALSE) /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php:582
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php:685
/var/www/html/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:651
/var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php:146
/var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php:99
--
There was 1 risky test:
1) Drupal\Tests\entity_mesh\Kernel\EntityMeshEntityRenderTest::testProcessEntity
This test did not perform any assertions
/var/www/html/docroot/core/tests/Drupal/Tests/Listeners/DrupalListener.php:62
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestResult.php:453
/var/www/html/vendor/phpunit/phpunit/src/Framework/TestSuite.php:685
/var/www/html/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:651
/var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php:146
/var/www/html/vendor/phpunit/phpunit/src/TextUI/Command.php:99
Code from PHPUnit:
<?php
namespace Drupal\Tests\entity_mesh\Kernel;
use Drupal\KernelTests\KernelTestBase;
use Drupal\language\Entity\ContentLanguageSettings;
use Drupal\node\Entity\Node;
use Drupal\language\Entity\ConfigurableLanguage;
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
/**
* Tests the Entity Mesh link auditing with multilingual support.
*
* @group entity_mesh
*/
class EntityMeshEntityRenderTest extends KernelTestBase {
use ContentTypeCreationTrait;
/**
* Modules to enable.
*
* @var array
*/
protected static $modules = [
'system',
'node',
'user',
'field',
'filter',
'text',
'language',
'content_translation',
'entity_mesh',
];
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
// Install the necessary schemas.
$this->installConfig(['filter']);
$this->installEntitySchema('node');
$this->installEntitySchema('user');
$this->installSchema('entity_mesh', ['entity_mesh']);
$this->installConfig(['node', 'system', 'language', 'content_translation', 'entity_mesh']);
// Enable the French language.
ConfigurableLanguage::createFromLangcode('fr')->save();
$this->createContentType(['type' => 'page', 'name' => 'Page']);
ContentLanguageSettings::loadByEntityTypeBundle('node', 'page')->setLanguageAlterable(TRUE)->save();
// Enable content translation for nodes.
$this->container->get('content_translation.manager')->setEnabled('node', 'page', TRUE);
// Enable the body field in the default view mode.
$this->container->get('entity_display.repository')
->getViewDisplay('node', 'page', 'full')
->setComponent('body', [
'label' => 'above', // Show label above the body content
'type' => 'text_default', // Render as basic text
])
->save();
$filter_format = \Drupal\filter\Entity\FilterFormat::load('basic_html');
if (!$filter_format) {
$filter_format = \Drupal\filter\Entity\FilterFormat::create([
'format' => 'basic_html',
'name' => 'Basic HTML',
'filters' => [],
]);
$filter_format->save();
}
}
/**
* Tests the processing of an entity with multiple link scenarios.
*/
public function testProcessEntity() {
// Create HTML content containing various link scenarios.
$html = '
<p>External link: <a href="https://example.com">Example</a></p>
<p>Internal valid link: <a href="/node/1">Internal Node</a></p>
<p>Broken link: <a href="/non-existent">Broken</a></p>
<p>Iframe content: <iframe src="https://example.com/iframe"></iframe></p>
';
// Create a node entity in English.
$node_en = Node::create([
'type' => 'page',
'title' => 'Test Node EN',
'body' => [
'value' => $html,
'format' => 'basic_html',
],
'langcode' => 'en',
]);
$node_en->save();
// Create a node entity in French.
$node_fr = Node::create([
'type' => 'page',
'title' => 'Test Node FR',
'body' => [
'value' => $html,
'format' => 'basic_html',
],
'langcode' => 'fr',
]);
$node_fr->save();
// Get the entity_mesh render service and process both nodes.
// $entity_mesh_service = $this->container->get('entity_mesh.entity_render');
// $entity_mesh_service->processEntity($node_en);
// $entity_mesh_service->processEntity($node_fr);
//
// // Retrieve records from the 'entity_mesh' table.
// $connection = $this->container->get('database');
// $query = $connection->select('entity_mesh', 'em')
// ->fields('em', ['source_entity_langcode', 'target_link_type', 'target_href']);
// $results = $query->execute()->fetchAll();
//
// // Organize records by their target link type.
// $records = [];
// foreach ($results as $record) {
// $records[$record->target_link_type][] = $record;
// }
//
// // Assert that a record exists for each link type.
// $this->assertNotEmpty($records['iframe'], 'An iframe record exists.');
// $this->assertNotEmpty($records['external'], 'An external link record exists.');
// $this->assertNotEmpty($records['internal'], 'An internal link record exists.');
// $this->assertNotEmpty($records['broken'], 'A broken link record exists.');
//
// // Check multilingual support: verify that records exist with both language codes.
// $languages = array_column($results, 'source_entity_langcode');
// $this->assertContains('en', $languages, 'An English language record is found.');
// $this->assertContains('fr', $languages, 'A French language record is found.');
//
// // (Optional) Further assertions could check the exact values of fields,
// // e.g., verifying that the external link's href is 'https://example.com'.
// foreach ($records['external'] as $external) {
// $this->assertEquals('https://example.com', $external->target_href, 'The external link href is correct.');
// }
}
}
Active
10.4 ✨
phpunit