Corrige erros de definição de biblioteca e esgotamento de memória no MSC 2020

Remove entrada de biblioteca vazia 'msc_term_select_widget' que causava
IncompleteLibraryDefinitionException. Otimiza buildTermData() para não
instanciar 597 entidades de taxonomia completas: usa loadTree() sem
entidades e busca field_msc_code diretamente na tabela do campo,
eliminando o fatal de memória esgotada (128 MB) ao abrir o modal
de configuração do campo.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-16 07:47:45 -03:00
parent d14aa22445
commit 1d4d676fa6
2 changed files with 35 additions and 21 deletions

View File

@@ -1,6 +1,3 @@
msc_term_select_widget:
version: VERSION
msc_term_list: msc_term_list:
version: VERSION version: VERSION
css: css:

View File

@@ -4,6 +4,7 @@ namespace Drupal\site_tools_msc_2020\Plugin\Field\FieldWidget;
use Drupal\Component\Utility\Html; use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray; use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\FieldItemListInterface;
@@ -42,6 +43,7 @@ class MscTermSelectWidget extends WidgetBase {
array $settings, array $settings,
array $third_party_settings, array $third_party_settings,
protected EntityTypeManagerInterface $entityTypeManager, protected EntityTypeManagerInterface $entityTypeManager,
protected Connection $database,
) { ) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
} }
@@ -54,6 +56,7 @@ class MscTermSelectWidget extends WidgetBase {
$configuration['settings'], $configuration['settings'],
$configuration['third_party_settings'], $configuration['third_party_settings'],
$container->get('entity_type.manager'), $container->get('entity_type.manager'),
$container->get('database'),
); );
} }
@@ -260,6 +263,9 @@ class MscTermSelectWidget extends WidgetBase {
/** /**
* Carrega todos os termos msc_2020 e retorna arrays por nível. * Carrega todos os termos msc_2020 e retorna arrays por nível.
* *
* Usa loadTree() sem entidades completas e busca field_msc_code direto na
* tabela do campo, evitando instanciar 597 objetos de entidade.
*
* @return array{ * @return array{
* l1: array<int,string>, * l1: array<int,string>,
* l2: array<int,array<int,string>>, * l2: array<int,array<int,string>>,
@@ -267,48 +273,59 @@ class MscTermSelectWidget extends WidgetBase {
* } * }
*/ */
protected function buildTermData(int $max_depth): array { protected function buildTermData(int $max_depth): array {
// Stubs leves: têm tid e name, sem carregar campos personalizados.
$tree = $this->entityTypeManager $tree = $this->entityTypeManager
->getStorage('taxonomy_term') ->getStorage('taxonomy_term')
->loadTree('msc_2020', 0, NULL, TRUE); ->loadTree('msc_2020', 0, NULL, FALSE);
// Busca todos os valores de field_msc_code em uma única query.
$codes = $this->database
->select('taxonomy_term__field_msc_code', 'c')
->fields('c', ['entity_id', 'field_msc_code_value'])
->execute()
->fetchAllKeyed();
// Indexa os stubs por tid.
$stubs = [];
foreach ($tree as $stub) {
$stubs[(int) $stub->tid] = $stub;
}
$code_to_tid = []; $code_to_tid = [];
$l1 = []; $l1 = [];
$l2 = []; $l2 = [];
$l3 = []; $l3 = [];
// Primeira passagem: monta mapa código→TID e coleta L1. foreach ($stubs as $tid => $stub) {
foreach ($tree as $term) { $code = $codes[$tid] ?? '';
$code = $term->get('field_msc_code')->value; if ($code === '') {
$tid = (int) $term->id(); continue;
}
$code_to_tid[$code] = $tid; $code_to_tid[$code] = $tid;
if (strlen($code) === 2) { if (strlen($code) === 2) {
$l1[$tid] = $code . ' — ' . $term->label(); $l1[$tid] = $code . ' — ' . $stub->name;
} }
} }
if ($max_depth >= 2) { if ($max_depth >= 2) {
foreach ($tree as $term) { foreach ($stubs as $tid => $stub) {
$code = $term->get('field_msc_code')->value; $code = $codes[$tid] ?? '';
if (strlen($code) === 3) { if (strlen($code) === 3) {
$parent_code = substr($code, 0, 2); $parent_tid = $code_to_tid[substr($code, 0, 2)] ?? NULL;
$parent_tid = $code_to_tid[$parent_code] ?? NULL;
if ($parent_tid !== NULL) { if ($parent_tid !== NULL) {
$tid = (int) $term->id(); $l2[$parent_tid][$tid] = $code . ' — ' . $stub->name;
$l2[$parent_tid][$tid] = $code . ' — ' . $term->label();
} }
} }
} }
} }
if ($max_depth >= 3) { if ($max_depth >= 3) {
foreach ($tree as $term) { foreach ($stubs as $tid => $stub) {
$code = $term->get('field_msc_code')->value; $code = $codes[$tid] ?? '';
if (strlen($code) === 5) { if (strlen($code) === 5) {
$parent_code = substr($code, 0, 3); $parent_tid = $code_to_tid[substr($code, 0, 3)] ?? NULL;
$parent_tid = $code_to_tid[$parent_code] ?? NULL;
if ($parent_tid !== NULL) { if ($parent_tid !== NULL) {
$tid = (int) $term->id(); $l3[$parent_tid][$tid] = $code . ' — ' . $stub->name;
$l3[$parent_tid][$tid] = $code . ' — ' . $term->label();
} }
} }
} }