Skip to content
Snippets Groups Projects
Commit 48d5cd75 authored by catch's avatar catch
Browse files

Issue #3231503 by mdupont, kiseleva.t, donquixote, akalam, larowlan, joachim,...

Issue #3231503 by mdupont, kiseleva.t, donquixote, akalam, larowlan, joachim, longwave, mglaman: hook_entity_extra_field_info() is called unnecessarily often, hurting performance

(cherry picked from commit 525dcd84)
parent 74fcd731
No related branches found
No related tags found
20 merge requests!11628Update file MediaLibraryWidget.php,!7564Revert "Issue #3364773 by roshnichordiya, Chris Matthews, thakurnishant_06,...,!5752Issue #3275828 by joachim, quietone, bradjones1, Berdir: document the reason...,!5627Issue #3261805: Field not saved when change of 0 on string start,!5427Issue #3338518: send credentials in ajax if configured in CORS settings.,!5395Issue #3387916 by fjgarlin, Spokje: Each GitLab job exposes user email,!5217Issue #3386607 by alexpott: Improve spell checking in commit-code-check.sh,!5064Issue #3379522 by finnsky, Gauravvvv, kostyashupenko, smustgrave, Chi: Revert...,!5040SDC ComponentElement: Transform slots scalar values to #plain_text instead of throwing an exception,!4958Issue #3392147: Whitelist IP for a Ban module.,!4894Issue #3280279: Add API to allow sites to opt in to upload SVG images in CKEditor 5,!4857Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!4856Issue #3336994: StringFormatter always displays links to entity even if the user in context does not have access,!4788Issue #3272985: RSS Feed header reverts to text/html when cached,!4716Issue #3362929: Improve 400 responses for broken/invalid image style routes,!4553Draft: Issue #2980951: Permission to see own unpublished comments in comment thread,!3679Issue #115801: Allow password on registration without disabling e-mail verification,!3106Issue #3017548: "Filtered HTML" text format does not support manual teaser break (<!--break-->),!925Issue #2339235: Remove taxonomy hard dependency on node module,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links
...@@ -25,11 +25,14 @@ class EntityFieldManager implements EntityFieldManagerInterface { ...@@ -25,11 +25,14 @@ class EntityFieldManager implements EntityFieldManagerInterface {
use StringTranslationTrait; use StringTranslationTrait;
/** /**
* Extra fields by bundle. * Extra fields info, if initialized.
* *
* @var array * The fields are keyed by entity type, bundle, type ('form' or 'display'),
* and the extra field name.
*
* @var array[][][][]|null
*/ */
protected $extraFields = []; protected ?array $extraFields = NULL;
/** /**
* Static cache of base field definitions. * Static cache of base field definitions.
...@@ -619,7 +622,7 @@ public function clearCachedFieldDefinitions() { ...@@ -619,7 +622,7 @@ public function clearCachedFieldDefinitions() {
$this->fieldMap = []; $this->fieldMap = [];
$this->fieldMapByFieldType = []; $this->fieldMapByFieldType = [];
$this->entityDisplayRepository->clearDisplayModeInfo(); $this->entityDisplayRepository->clearDisplayModeInfo();
$this->extraFields = []; $this->extraFields = NULL;
Cache::invalidateTags(['entity_field_info']); Cache::invalidateTags(['entity_field_info']);
// The typed data manager statically caches prototype objects with injected // The typed data manager statically caches prototype objects with injected
// definitions, clear those as well. // definitions, clear those as well.
...@@ -643,36 +646,51 @@ public function useCaches($use_caches = FALSE) { ...@@ -643,36 +646,51 @@ public function useCaches($use_caches = FALSE) {
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getExtraFields($entity_type_id, $bundle) { public function getExtraFields($entity_type_id, $bundle) {
$this->extraFields ??= $this->loadExtraFields();
// Read from the "static" cache. // Read from the "static" cache.
if (isset($this->extraFields[$entity_type_id][$bundle])) { // Return an empty fallback if the bundle has no extra fields.
return $this->extraFields[$entity_type_id][$bundle]; return $this->extraFields[$entity_type_id][$bundle] ?? [
} 'form' => [],
'display' => [],
];
}
/**
* Loads extra fields from cache, or rebuilds them.
*
* @return array[][][][]
* Extra fields by entity type, bundle name, type (form/display) and
* extra field name.
*/
protected function loadExtraFields(): array {
// Read from the persistent cache. Since hook_entity_extra_field_info() and // Read from the persistent cache. Since hook_entity_extra_field_info() and
// hook_entity_extra_field_info_alter() might contain t() calls, we cache // hook_entity_extra_field_info_alter() might contain t() calls, we cache
// per language. // per language.
$cache_id = 'entity_bundle_extra_fields:' . $entity_type_id . ':' . $bundle . ':' . $this->languageManager->getCurrentLanguage()->getId(); $cache_id = 'entity_extra_field_info:' . $this->languageManager->getCurrentLanguage()->getId();
$cached = $this->cacheGet($cache_id); $cached = $this->cacheGet($cache_id);
if ($cached) { if ($cached) {
$this->extraFields[$entity_type_id][$bundle] = $cached->data; return $cached->data;
return $this->extraFields[$entity_type_id][$bundle];
} }
$extra = $this->moduleHandler->invokeAll('entity_extra_field_info'); $extra = $this->moduleHandler->invokeAll('entity_extra_field_info');
$this->moduleHandler->alter('entity_extra_field_info', $extra); $this->moduleHandler->alter('entity_extra_field_info', $extra);
$info = $extra[$entity_type_id][$bundle] ?? [];
$info += [
'form' => [],
'display' => [],
];
// Store in the 'static' and persistent caches. // Apply default values to each bundle.
$this->extraFields[$entity_type_id][$bundle] = $info; foreach ($extra as $entity_type_id => $extra_fields_by_bundle) {
$this->cacheSet($cache_id, $info, Cache::PERMANENT, [ foreach ($extra_fields_by_bundle as $bundle => $bundle_extra_fields) {
$extra[$entity_type_id][$bundle] += [
'form' => [],
'display' => [],
];
}
}
$this->cacheSet($cache_id, $extra, Cache::PERMANENT, [
'entity_field_info', 'entity_field_info',
]); ]);
return $this->extraFields[$entity_type_id][$bundle]; return $extra;
} }
} }
...@@ -684,7 +684,7 @@ public function testGetExtraFields() { ...@@ -684,7 +684,7 @@ public function testGetExtraFields() {
$processed_hook_bundle_extra_fields[$entity_type_id][$bundle] += [ $processed_hook_bundle_extra_fields[$entity_type_id][$bundle] += [
'display' => [], 'display' => [],
]; ];
$cache_id = 'entity_bundle_extra_fields:' . $entity_type_id . ':' . $bundle . ':' . $language_code; $cache_id = 'entity_extra_field_info:' . $language_code;
$language = new Language(['id' => $language_code]); $language = new Language(['id' => $language_code]);
$this->languageManager->getCurrentLanguage() $this->languageManager->getCurrentLanguage()
...@@ -696,7 +696,7 @@ public function testGetExtraFields() { ...@@ -696,7 +696,7 @@ public function testGetExtraFields() {
$this->moduleHandler->invokeAll('entity_extra_field_info')->willReturn($hook_bundle_extra_fields); $this->moduleHandler->invokeAll('entity_extra_field_info')->willReturn($hook_bundle_extra_fields);
$this->moduleHandler->alter('entity_extra_field_info', $hook_bundle_extra_fields)->shouldBeCalled(); $this->moduleHandler->alter('entity_extra_field_info', $hook_bundle_extra_fields)->shouldBeCalled();
$this->cacheBackend->set($cache_id, $processed_hook_bundle_extra_fields[$entity_type_id][$bundle], Cache::PERMANENT, ['entity_field_info'])->shouldBeCalled(); $this->cacheBackend->set($cache_id, $processed_hook_bundle_extra_fields, Cache::PERMANENT, ['entity_field_info'])->shouldBeCalled();
$this->assertSame($processed_hook_bundle_extra_fields[$entity_type_id][$bundle], $this->entityFieldManager->getExtraFields($entity_type_id, $bundle)); $this->assertSame($processed_hook_bundle_extra_fields[$entity_type_id][$bundle], $this->entityFieldManager->getExtraFields($entity_type_id, $bundle));
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment