mirror of
https://gitlab.unicamp.br/infimecc_drupal11_modules/site_users.git
synced 2026-03-10 10:17:41 -03:00
feat: Módulo Site Users para customização de perfis de usuário
Módulo Drupal para gerenciamento de campos e fotos de perfil de usuários: - Campos customizados: nome, telefone, categoria, departamento, biografia - Suporte a múltiplas fotos com seleção de foto padrão - Controle de permissões granular para visualização e edição - Bloco de informações do usuário para exibição em páginas - Configurações administrativas para limite de fotos e integração LDAP Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
73
src/Form/SiteUsersSettingsForm.php
Normal file
73
src/Form/SiteUsersSettingsForm.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\site_users\Form;
|
||||
|
||||
use Drupal\Core\Form\ConfigFormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
||||
/**
|
||||
* Formulário de configuração do módulo Site Users.
|
||||
*/
|
||||
class SiteUsersSettingsForm extends ConfigFormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFormId() {
|
||||
return 'site_users_settings_form';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getEditableConfigNames() {
|
||||
return ['site_users.settings'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(array $form, FormStateInterface $form_state) {
|
||||
$config = $this->config('site_users.settings');
|
||||
|
||||
// Fieldset para configurações de fotos.
|
||||
$form['photos'] = [
|
||||
'#type' => 'fieldset',
|
||||
'#title' => $this->t('Configurações de Fotos'),
|
||||
'#collapsible' => FALSE,
|
||||
];
|
||||
|
||||
$form['photos']['photos_max_count'] = [
|
||||
'#type' => 'number',
|
||||
'#title' => $this->t('Quantidade de fotos permitidas'),
|
||||
'#description' => $this->t('Número máximo de fotos que um usuário pode adicionar ao perfil.'),
|
||||
'#default_value' => $config->get('photos.max_count') ?? 5,
|
||||
'#min' => 1,
|
||||
'#max' => 100,
|
||||
'#required' => TRUE,
|
||||
];
|
||||
|
||||
$form['photos']['photos_ldap_attribute'] = [
|
||||
'#type' => 'textfield',
|
||||
'#title' => $this->t('Atributo LDAP da foto'),
|
||||
'#description' => $this->t('Se LDAP estiver habilitado, informe o nome do atributo que contém a foto do usuário (ex: thumbnailPhoto, jpegPhoto).'),
|
||||
'#default_value' => $config->get('photos.ldap_attribute') ?? 'jpegPhoto',
|
||||
'#maxlength' => 255,
|
||||
];
|
||||
|
||||
return parent::buildForm($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitForm(array &$form, FormStateInterface $form_state) {
|
||||
$this->config('site_users.settings')
|
||||
->set('photos.max_count', $form_state->getValue('photos_max_count'))
|
||||
->set('photos.ldap_attribute', $form_state->getValue('photos_ldap_attribute'))
|
||||
->save();
|
||||
|
||||
parent::submitForm($form, $form_state);
|
||||
}
|
||||
|
||||
}
|
||||
192
src/Plugin/Block/UserInfoBlock.php
Normal file
192
src/Plugin/Block/UserInfoBlock.php
Normal file
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\site_users\Plugin\Block;
|
||||
|
||||
use Drupal\Core\Block\BlockBase;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\user\UserInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Bloco com informações básicas do usuário.
|
||||
*
|
||||
* Exibe automaticamente as informações do usuário da rota /user/{id}.
|
||||
*
|
||||
* @Block(
|
||||
* id = "site_users_info_block",
|
||||
* admin_label = @Translation("Informações do Usuário"),
|
||||
* category = @Translation("Site Users")
|
||||
* )
|
||||
*/
|
||||
class UserInfoBlock extends BlockBase implements ContainerFactoryPluginInterface {
|
||||
|
||||
/**
|
||||
* The current route match.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteMatchInterface
|
||||
*/
|
||||
protected $routeMatch;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* Constructs a new UserInfoBlock instance.
|
||||
*
|
||||
* @param array $configuration
|
||||
* The plugin configuration.
|
||||
* @param string $plugin_id
|
||||
* The plugin ID.
|
||||
* @param mixed $plugin_definition
|
||||
* The plugin definition.
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The current route match.
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager.
|
||||
*/
|
||||
public function __construct(
|
||||
array $configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
RouteMatchInterface $route_match,
|
||||
EntityTypeManagerInterface $entity_type_manager
|
||||
) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
$this->routeMatch = $route_match;
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
||||
return new static(
|
||||
$configuration,
|
||||
$plugin_id,
|
||||
$plugin_definition,
|
||||
$container->get('current_route_match'),
|
||||
$container->get('entity_type.manager')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function build() {
|
||||
$user = $this->getUserFromContext();
|
||||
|
||||
if (!$user instanceof UserInterface) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Obter foto padrão.
|
||||
$default_photo = NULL;
|
||||
$default_photo_url = NULL;
|
||||
if (function_exists('site_users_get_default_photo')) {
|
||||
$default_photo = site_users_get_default_photo($user);
|
||||
if ($default_photo) {
|
||||
// Usar o source field do media (forma padrão do Drupal).
|
||||
$source_field = $default_photo->getSource()->getConfiguration()['source_field'];
|
||||
if ($default_photo->hasField($source_field) && !$default_photo->get($source_field)->isEmpty()) {
|
||||
$file = $default_photo->get($source_field)->entity;
|
||||
if ($file) {
|
||||
$default_photo_url = \Drupal::service('file_url_generator')->generateAbsoluteString($file->getFileUri());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Coletar informações do usuário.
|
||||
$user_info = [
|
||||
'uid' => $user->id(),
|
||||
'username' => $user->getDisplayName(),
|
||||
'name' => $this->getFieldValue($user, 'field_user_name'),
|
||||
'phone' => $this->getFieldValue($user, 'field_user_phone'),
|
||||
'category' => $this->getFieldValue($user, 'field_user_category'),
|
||||
'dept_code' => $this->getFieldValue($user, 'field_user_dept_code'),
|
||||
'bio' => $this->getFieldValue($user, 'field_user_bio'),
|
||||
'photo_url' => $default_photo_url,
|
||||
'photo_alt' => $default_photo ? $default_photo->label() : '',
|
||||
];
|
||||
|
||||
return [
|
||||
'#theme' => 'site_users_info_block',
|
||||
'#user_info' => $user_info,
|
||||
'#user' => $user,
|
||||
'#attached' => [
|
||||
'library' => [
|
||||
'site_users/user-info-block',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtém o usuário da rota atual.
|
||||
*
|
||||
* @return \Drupal\user\UserInterface|null
|
||||
* O usuário ou NULL se não estiver em uma página de usuário.
|
||||
*/
|
||||
protected function getUserFromContext(): ?UserInterface {
|
||||
// Obter da rota /user/{user}.
|
||||
$user = $this->routeMatch->getParameter('user');
|
||||
|
||||
if ($user instanceof UserInterface) {
|
||||
return $user;
|
||||
}
|
||||
|
||||
// Se for apenas o ID, carregar o usuário.
|
||||
if (is_numeric($user)) {
|
||||
return $this->entityTypeManager->getStorage('user')->load($user);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtém o valor de um campo do usuário.
|
||||
*
|
||||
* @param \Drupal\user\UserInterface $user
|
||||
* O usuário.
|
||||
* @param string $field_name
|
||||
* O nome do campo.
|
||||
*
|
||||
* @return string|null
|
||||
* O valor do campo ou NULL.
|
||||
*/
|
||||
protected function getFieldValue(UserInterface $user, string $field_name): ?string {
|
||||
if ($user->hasField($field_name) && !$user->get($field_name)->isEmpty()) {
|
||||
return $user->get($field_name)->value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheTags() {
|
||||
$tags = parent::getCacheTags();
|
||||
|
||||
$user = $this->getUserFromContext();
|
||||
if ($user instanceof UserInterface) {
|
||||
$tags = Cache::mergeTags($tags, $user->getCacheTags());
|
||||
}
|
||||
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getCacheContexts() {
|
||||
return Cache::mergeContexts(parent::getCacheContexts(), ['route', 'user']);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user