From f58c8f90f489cf35a8f52b6a15a0cbb937e6f802 Mon Sep 17 00:00:00 2001 From: "Quintino A. G. Souza" Date: Wed, 25 Feb 2026 16:29:41 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20Perfis=20p=C3=BAblicos=20de=20usu=C3=A1?= =?UTF-8?q?rio=20via=20view=20mode=20'public'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adiciona hook_entity_view_mode_alter() para redirecionar visitantes não-proprietários e não-admins para o view mode 'public' ao acessar /user/{uid}, exibindo apenas foto padrão, bio e redes sociais - Simplifica hook_entity_field_access(): operação 'view' retorna neutral para não-proprietários (visibilidade controlada pelo view mode) - Cria update_10005() que provisiona o view mode 'public', seu display e concede a permissão 'access user profiles' ao papel anonymous - Replica a concessão de permissão em hook_install() para novas instalações - Corrige TypeError em hook_entity_view_mode_alter(): $context aceita null - Amplia hook_media_access() para permitir visualização de mídia publicada também para usuários anônimos Co-Authored-By: Claude Sonnet 4.6 --- site_users.install | 71 ++++++++++++++++++++++++++++++++++++++++++++++ site_users.module | 25 +++++++++++----- 2 files changed, 89 insertions(+), 7 deletions(-) diff --git a/site_users.install b/site_users.install index 13f795f..59180d8 100644 --- a/site_users.install +++ b/site_users.install @@ -164,6 +164,13 @@ function site_users_install() { $view_display->save(); } + + // Conceder permissão "access user profiles" ao papel anonymous. + $anonymous_role = \Drupal\user\Entity\Role::load('anonymous'); + if ($anonymous_role && !$anonymous_role->hasPermission('access user profiles')) { + $anonymous_role->grantPermission('access user profiles'); + $anonymous_role->save(); + } } /** @@ -288,6 +295,70 @@ function site_users_update_10002() { return t('Social links field created successfully.'); } +/** + * Cria o view mode 'public' e seu display para perfis de usuário. + */ +function site_users_update_10005() { + // Criar o view mode 'public' se não existir. + $view_mode_storage = \Drupal::entityTypeManager()->getStorage('entity_view_mode'); + if (!$view_mode_storage->load('user.public')) { + \Drupal\Core\Entity\Entity\EntityViewMode::create([ + 'id' => 'user.public', + 'label' => 'Public', + 'targetEntityType' => 'user', + ])->save(); + } + + // Criar o view display 'public' se não existir. + $display_storage = \Drupal::entityTypeManager()->getStorage('entity_view_display'); + if (!$display_storage->load('user.user.public')) { + $display = \Drupal\Core\Entity\Entity\EntityViewDisplay::create([ + 'targetEntityType' => 'user', + 'bundle' => 'user', + 'mode' => 'public', + 'status' => TRUE, + ]); + + $display->setComponent('field_user_default_photo', [ + 'type' => 'entity_reference_entity_view', + 'weight' => 5, + 'label' => 'hidden', + 'settings' => [ + 'view_mode' => 'default', + 'link' => FALSE, + ], + 'region' => 'content', + ]); + + $display->setComponent('field_user_bio', [ + 'type' => 'text_default', + 'weight' => 10, + 'label' => 'hidden', + 'settings' => [], + 'region' => 'content', + ]); + + $display->setComponent('field_user_social_links', [ + 'type' => 'social_link_formatter', + 'weight' => 15, + 'label' => 'hidden', + 'settings' => [], + 'region' => 'content', + ]); + + $display->save(); + } + + // Conceder permissão "access user profiles" ao papel anonymous. + $anonymous_role = \Drupal\user\Entity\Role::load('anonymous'); + if ($anonymous_role && !$anonymous_role->hasPermission('access user profiles')) { + $anonymous_role->grantPermission('access user profiles'); + $anonymous_role->save(); + } + + return t("View mode 'public' para usuário criado com foto padrão, bio e redes sociais."); +} + /** * Corrige mapeamentos LDAP com prov_events nulo na config ativa. */ diff --git a/site_users.module b/site_users.module index b3af6e1..795e61d 100644 --- a/site_users.module +++ b/site_users.module @@ -98,9 +98,7 @@ function site_users_check_profile_field_access($operation, AccountInterface $acc if ($is_own && $account->hasPermission('view own user profile fields')) { return AccessResult::allowed()->cachePerPermissions()->cachePerUser(); } - if (!$is_own) { - return AccessResult::forbidden()->cachePerPermissions()->cachePerUser(); - } + // Visibilidade pública controlada pelo view mode — não bloquear aqui. return AccessResult::neutral()->cachePerUser(); } @@ -153,9 +151,7 @@ function site_users_check_photo_field_access($operation, AccountInterface $accou if ($is_own && $account->hasPermission('view own user profile fields')) { return AccessResult::allowed()->cachePerPermissions()->cachePerUser(); } - if (!$is_own) { - return AccessResult::forbidden()->cachePerPermissions()->cachePerUser(); - } + // Visibilidade pública controlada pelo view mode — não bloquear aqui. return AccessResult::neutral()->cachePerUser(); } @@ -332,11 +328,26 @@ function site_users_user_presave(UserInterface $user) { } } +/** + * Implements hook_entity_view_mode_alter(). + */ +function site_users_entity_view_mode_alter(string &$view_mode, EntityInterface $entity, ?array $context): void { + if ($entity->getEntityTypeId() !== 'user' || $view_mode !== 'full') { + return; + } + $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'; + } +} + /** * Implements hook_ENTITY_TYPE_access() for media entities. */ function site_users_media_access(\Drupal\media\MediaInterface $entity, string $operation, AccountInterface $account): AccessResult { - if ($operation === 'view' && $entity->isPublished() && $account->isAuthenticated()) { + if ($operation === 'view' && $entity->isPublished()) { return AccessResult::allowed() ->cachePerUser() ->addCacheableDependency($entity);