feat: View mode por role/usuário com seletor de visibilidade no perfil

- Cria view mode e display 'restricted' (template mostra só username + mensagem)
- Adiciona campo field_user_selected_view_mode (string, default: restricted)
- update_10006: provisiona view mode, display e campo; inicializa role_view_modes
- Seletor de visibilidade no form de edição do perfil (owner e admin)
- hook_entity_view_mode_alter lê o campo e valida existência do display
- Formulário de admin: checkboxes de view modes por role (exceto anonymous e authenticated)
- Schema YAML completo para site_users.settings incluindo role_view_modes
- Tradução pt-BR de todas as novas strings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-26 08:06:10 -03:00
parent f58c8f90f4
commit bd24e6eb6b
9 changed files with 431 additions and 2 deletions

View File

@@ -28,6 +28,10 @@ function site_users_theme($existing, $type, $theme, $path) {
'template' => 'user--full',
'base hook' => 'user',
],
'user__restricted' => [
'template' => 'user--restricted',
'base hook' => 'user',
],
'site_users_info_block' => [
'template' => 'site-user-info-block',
'variables' => [
@@ -184,6 +188,131 @@ function site_users_form_user_form_alter(&$form, FormStateInterface $form_state,
$form['#validate'][] = 'site_users_validate_photos_count';
_site_users_add_default_photo_selector($form, $form_state);
}
_site_users_add_visibility_selector($form, $form_state);
}
/**
* Adiciona o seletor de visibilidade do perfil ao formulário de usuário.
*/
function _site_users_add_visibility_selector(&$form, FormStateInterface $form_state) {
/** @var \Drupal\user\UserInterface $user */
$user = $form_state->getFormObject()->getEntity();
$current_user = \Drupal::currentUser();
$is_own = (int) $user->id() === (int) $current_user->id();
$is_admin = $current_user->hasPermission('administer users');
if (!$is_own && !$is_admin) {
return;
}
$options = _site_users_get_allowed_view_modes($user);
// Always include 'restricted'.
$options = ['restricted' => t('Restricted (username only)')] + $options;
$current_value = 'restricted';
if ($user->hasField('field_user_selected_view_mode') && !$user->get('field_user_selected_view_mode')->isEmpty()) {
$current_value = $user->get('field_user_selected_view_mode')->value;
}
// Fallback to restricted if stored value is no longer allowed.
if (!isset($options[$current_value])) {
$current_value = 'restricted';
}
$form['profile_visibility'] = [
'#type' => 'fieldset',
'#title' => t('Profile visibility'),
'#weight' => 20,
];
$form['profile_visibility']['profile_view_mode'] = [
'#type' => 'radios',
'#title' => t('How should my profile appear to other visitors?'),
'#description' => t('Choose the information displayed on your public profile page.'),
'#options' => $options,
'#default_value' => $current_value,
];
// Prepend validate handler.
array_unshift($form['#validate'], '_site_users_validate_visibility_selector');
// Prepend submit handler before the default submit.
array_unshift($form['actions']['submit']['#submit'], '_site_users_presave_visibility_selector');
}
/**
* Retorna os view modes permitidos para os roles do usuário.
*
* @param \Drupal\user\UserInterface $user
* O usuário cujo perfil está sendo editado.
*
* @return array
* Associative array of machine_name => label.
*/
function _site_users_get_allowed_view_modes(UserInterface $user): array {
$config = \Drupal::config('site_users.settings');
$role_view_modes = $config->get('role_view_modes') ?? [];
$allowed = [];
foreach ($user->getRoles() as $role_id) {
if (!empty($role_view_modes[$role_id]) && is_array($role_view_modes[$role_id])) {
foreach ($role_view_modes[$role_id] as $vm) {
$allowed[$vm] = $vm;
}
}
}
if (empty($allowed)) {
return [];
}
// Load labels for the allowed view modes.
$view_mode_storage = \Drupal::entityTypeManager()->getStorage('entity_view_mode');
$options = [];
foreach (array_keys($allowed) as $machine_name) {
$view_mode = $view_mode_storage->load('user.' . $machine_name);
$options[$machine_name] = $view_mode ? $view_mode->label() : $machine_name;
}
return $options;
}
/**
* Validate handler: confirma que o valor escolhido está na lista permitida.
*/
function _site_users_validate_visibility_selector(&$form, FormStateInterface $form_state) {
$chosen = $form_state->getValue('profile_view_mode');
if ($chosen === NULL) {
return;
}
/** @var \Drupal\user\UserInterface $user */
$user = $form_state->getFormObject()->getEntity();
$allowed = _site_users_get_allowed_view_modes($user);
$allowed['restricted'] = 'restricted';
if (!isset($allowed[$chosen])) {
$form_state->setErrorByName('profile_view_mode', t('Invalid profile visibility option selected.'));
}
}
/**
* Submit handler (prepended): seta field_user_selected_view_mode no entity antes do save.
*/
function _site_users_presave_visibility_selector(&$form, FormStateInterface $form_state) {
$chosen = $form_state->getValue('profile_view_mode');
if ($chosen === NULL) {
return;
}
/** @var \Drupal\user\UserInterface $user */
$user = $form_state->getFormObject()->getEntity();
if ($user->hasField('field_user_selected_view_mode')) {
$user->set('field_user_selected_view_mode', $chosen);
// Do not save here — the standard submit handler saves the entity.
}
}
/**
@@ -338,9 +467,31 @@ function site_users_entity_view_mode_alter(string &$view_mode, EntityInterface $
$current_user = \Drupal::currentUser();
$is_own = (int) $entity->id() === (int) $current_user->id();
$is_admin = $current_user->hasPermission('administer users');
if (!$is_own && !$is_admin) {
$view_mode = 'public';
if ($is_own || $is_admin) {
// Owner and admin always see the full view mode.
return;
}
// Read the chosen view mode from the profile being visited.
$chosen = 'restricted';
if ($entity instanceof UserInterface
&& $entity->hasField('field_user_selected_view_mode')
&& !$entity->get('field_user_selected_view_mode')->isEmpty()
) {
$chosen = $entity->get('field_user_selected_view_mode')->value;
}
// Validate that a view display exists for the chosen value.
if ($chosen !== 'restricted') {
$display_id = 'user.user.' . $chosen;
$display_storage = \Drupal::entityTypeManager()->getStorage('entity_view_display');
if (!$display_storage->load($display_id)) {
$chosen = 'restricted';
}
}
$view_mode = $chosen;
}
/**