feat: Descoberta dinâmica de campos de usuário editáveis

hook_entity_field_access() passa a cobrir todos os FieldConfigInterface
do usuário, sem lista hardcoded. Campos de referência a mídia usam
lógica de fotos; demais usam lógica de perfil.

SiteUsersSettingsForm descobre campos dinamicamente via
entity_field.manager, listando todos os campos configuráveis do usuário
independente do módulo que os define.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 07:43:41 -03:00
parent 06e5bae039
commit 120d7b1858
3 changed files with 72 additions and 32 deletions

View File

@@ -4,6 +4,7 @@ namespace Drupal\site_users\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\field\FieldConfigInterface;
/**
* Formulário de configuração do módulo Site Users.
@@ -11,19 +12,51 @@ use Drupal\Core\Form\FormStateInterface;
class SiteUsersSettingsForm extends ConfigFormBase {
/**
* Returns the list of fields controllable by the admin.
* Returns all configurable user fields, discovered dynamically.
*
* @return array
* Associative array of field_name => label.
*/
protected function getEditableFields(): array {
return [
'field_user_name' => $this->t('Full Name'),
'field_user_phone' => $this->t('Phone'),
'field_user_bio' => $this->t('Biography'),
'field_user_social_links' => $this->t('Social Links'),
'field_user_photos' => $this->t('Photos'),
];
$definitions = \Drupal::service('entity_field.manager')
->getFieldDefinitions('user', 'user');
$fields = [];
foreach ($definitions as $field_name => $definition) {
if ($definition instanceof FieldConfigInterface) {
$provider = $this->getFieldStorageProvider($field_name);
$fields[$field_name] = $this->t('@label [@module]', [
'@label' => $definition->getLabel(),
'@module' => $provider,
]);
}
}
ksort($fields);
return $fields;
}
/**
* Finds which module provides the field storage config file.
*
* @param string $field_name
* The field name.
*
* @return string
* The module name, or 'unknown' if not found.
*/
protected function getFieldStorageProvider(string $field_name): string {
$config_file = 'field.storage.user.' . $field_name . '.yml';
$module_handler = \Drupal::moduleHandler();
foreach ($module_handler->getModuleList() as $module_name => $module) {
foreach (['config/install', 'config/optional'] as $dir) {
if (file_exists($module->getPath() . '/' . $dir . '/' . $config_file)) {
return $module_name;
}
}
}
return 'unknown';
}
/**
@@ -75,15 +108,26 @@ class SiteUsersSettingsForm extends ConfigFormBase {
$form['user_editable_fields'] = [
'#type' => 'fieldset',
'#title' => $this->t('User-editable profile fields'),
'#description' => $this->t('Select which fields users with the "Edit own user profile fields" or "Manage own user photos" permission can edit on their own profile.'),
'#description' => $this->t('Select which fields users can edit on their own profile. Fields protected by other modules remain non-editable regardless of this setting.'),
'#tree' => TRUE,
];
$definitions = \Drupal::service('entity_field.manager')
->getFieldDefinitions('user', 'user');
$access_handler = \Drupal::entityTypeManager()
->getAccessControlHandler('user');
foreach ($this->getEditableFields() as $field_name => $label) {
$is_protected = $access_handler
->fieldAccess('edit', $definitions[$field_name], NULL, NULL, TRUE)
->isForbidden();
$form['user_editable_fields'][$field_name] = [
'#type' => 'checkbox',
'#title' => $label,
'#default_value' => $config->get('user_editable_fields.' . $field_name) ?? TRUE,
'#disabled' => $is_protected,
'#description' => $is_protected ? $this->t('Protected by another module.') : '',
];
}
@@ -102,7 +146,10 @@ class SiteUsersSettingsForm extends ConfigFormBase {
$editable = $form_state->getValue('user_editable_fields');
foreach (array_keys($this->getEditableFields()) as $field_name) {
$config->set('user_editable_fields.' . $field_name, (bool) ($editable[$field_name] ?? FALSE));
// Disabled fields are not submitted; skip them to preserve current value.
if (isset($editable[$field_name])) {
$config->set('user_editable_fields.' . $field_name, (bool) $editable[$field_name]);
}
}
$config->save();