mirror of
https://gitlab.unicamp.br/infimecc_drupal11_modules/site_users.git
synced 2026-03-08 01:17:41 -03:00
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:
@@ -12,6 +12,7 @@ use Drupal\Core\Field\FieldDefinitionInterface;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
use Drupal\field\FieldConfigInterface;
|
||||
use Drupal\media\MediaInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
|
||||
@@ -51,31 +52,20 @@ function site_users_entity_field_access($operation, FieldDefinitionInterface $fi
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
// Lista de campos controlados pelo módulo.
|
||||
$profile_fields = [
|
||||
'field_user_name',
|
||||
'field_user_phone',
|
||||
'field_user_social_links',
|
||||
'field_user_bio',
|
||||
];
|
||||
|
||||
$photo_fields = [
|
||||
'field_user_photos',
|
||||
'field_user_default_photo',
|
||||
];
|
||||
$field_name = $field_definition->getName();
|
||||
|
||||
// Verificar se é um campo de perfil.
|
||||
if (in_array($field_name, $profile_fields)) {
|
||||
return site_users_check_profile_field_access($operation, $account, $items, $field_name);
|
||||
// Apenas campos configuráveis (não campos base como name, mail, status).
|
||||
if (!($field_definition instanceof FieldConfigInterface)) {
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
// Verificar se é um campo de fotos.
|
||||
if (in_array($field_name, $photo_fields)) {
|
||||
$field_name = $field_definition->getName();
|
||||
|
||||
// Campos de referência a mídia usam lógica de fotos.
|
||||
if ($field_definition->getType() === 'entity_reference'
|
||||
&& $field_definition->getSetting('target_type') === 'media') {
|
||||
return site_users_check_photo_field_access($operation, $account, $items, $field_name);
|
||||
}
|
||||
|
||||
return AccessResult::neutral();
|
||||
return site_users_check_profile_field_access($operation, $account, $items, $field_name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -132,8 +132,11 @@ msgstr "Links de perfil em redes sociais."
|
||||
msgid "User-editable profile fields"
|
||||
msgstr "Campos do perfil editáveis pelo usuário"
|
||||
|
||||
msgid "Select which fields users with the \"Edit own user profile fields\" or \"Manage own user photos\" permission can edit on their own profile."
|
||||
msgstr "Selecione quais campos os usuários com a permissão \"Editar campos do próprio perfil\" ou \"Gerenciar próprias fotos\" podem editar no próprio perfil."
|
||||
msgid "Select which fields users can edit on their own profile. Fields protected by other modules remain non-editable regardless of this setting."
|
||||
msgstr "Selecione quais campos os usuários podem editar no próprio perfil. Campos protegidos por outros módulos permanecem não editáveis independentemente desta configuração."
|
||||
|
||||
msgid "Protected by another module."
|
||||
msgstr "Protegido por outro módulo."
|
||||
|
||||
# Template
|
||||
msgid "Phone:"
|
||||
|
||||
Reference in New Issue
Block a user