forked from a64f7bb4-7358-4778-9fbe-3b882c34cc1d/v1
296 lines
11 KiB
PHP
296 lines
11 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @file
|
|
* Support for configurable user profiles.
|
|
*/
|
|
|
|
use Drupal\Core\Access\AccessResult;
|
|
use Drupal\Core\Entity\EntityTypeInterface;
|
|
use Drupal\Core\Field\BaseFieldDefinition;
|
|
use Drupal\Core\Field\FieldDefinitionInterface;
|
|
use Drupal\Core\Field\FieldItemListInterface;
|
|
use Drupal\Core\Render\Element;
|
|
use Drupal\Core\Session\AccountInterface;
|
|
use Drupal\profile\Plugin\Field\ProfileEntityFieldItemList;
|
|
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
|
use Drupal\Core\Entity\EntityInterface;
|
|
use Drupal\profile\Entity\ProfileType;
|
|
use Drupal\field\FieldConfigInterface;
|
|
use Drupal\Core\Routing\RouteMatchInterface;
|
|
use Drupal\Core\Form\FormStateInterface;
|
|
use Drupal\Core\Url;
|
|
|
|
/**
|
|
* Implements hook_help().
|
|
*/
|
|
function profile_help($route_name, RouteMatchInterface $route_match) {
|
|
switch ($route_name) {
|
|
case 'help.page.profile':
|
|
$output = '<h3>' . t('About') . '</h3>';
|
|
$output .= '<p>' . t('The Profile module provides a fieldable entity, that allows administrators to define different sets of fields for user profiles, which are then displayed in the <a href="@user">My Account</a> section. This permits users of a site to share more information about themselves, and can help community-based sites organize users around specific information.', ['@user' => Url::fromRoute('user.page')->toString()]) . '</p>';
|
|
$output .= '<dl>';
|
|
$output .= '<dt>' . t('Types of profiles') . '</dt>';
|
|
$output .= '<dd>' . t('Profile types provide a way of grouping similar data for user profiles e.g. Personal information, Work etc. A default "Personal information type is provided. You may create more types and manage fields for each type from the <a href="@profile-types">Profile types</a> admin page. When creating a new profile type, you will be able to specify whether a user may create multiple profiles or make the profile form available when registering a new user.', ['@profile-types' => Url::fromRoute('entity.profile_type.collection')->toString()]) . '</dd>';
|
|
$output .= '<dt>' . t('Creating profiles') . '</dt>';
|
|
$output .= '<dd>' . t('A user will see tabs they have access to, when editing their main user account e.g. "Add personal information profile". The visibility of a tab depends on whether they can create multiple profiles or if they haven\'t created a profile of the type that doesn\'t allow multiple instances.') . '</dd>';
|
|
$output .= '</dl>';
|
|
return $output;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_entity_bundle_info_alter().
|
|
*/
|
|
function profile_entity_bundle_info_alter(&$bundles) {
|
|
if (empty($bundles['profile'])) {
|
|
return;
|
|
}
|
|
|
|
$profile_type_ids = array_keys($bundles['profile']);
|
|
/** @var \Drupal\profile\Entity\ProfileTypeInterface[] $profile_types */
|
|
$profile_types = ProfileType::loadMultiple($profile_type_ids);
|
|
foreach ($bundles['profile'] as $bundle => $info) {
|
|
if (isset($profile_types[$bundle])) {
|
|
$profile_type = $profile_types[$bundle];
|
|
// Bundle info is loaded on most requests. Store the flags inside, so
|
|
// that modules can use them without needing to load the profile type.
|
|
if ($profile_type->allowsMultiple()) {
|
|
$bundles['profile'][$bundle]['multiple'] = TRUE;
|
|
}
|
|
if ($profile_type->showRevisionUi()) {
|
|
$bundles['profile'][$bundle]['revision_ui'] = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_entity_field_access().
|
|
*/
|
|
function profile_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
|
|
if ($operation == 'view' && $items && $field_definition->getTargetEntityTypeId() == 'profile') {
|
|
if ($field_definition instanceof FieldConfigInterface) {
|
|
$is_private = $field_definition->getThirdPartySetting('profile', 'profile_private', FALSE);
|
|
if ($is_private) {
|
|
// Users may see their own private profile fields by default, so this
|
|
// requires user granularity for caching.
|
|
/** @var \Drupal\profile\Entity\ProfileInterface $profile */
|
|
$profile = $items->getEntity();
|
|
if ($account->id() === $profile->getOwnerId()) {
|
|
return AccessResult::neutral();
|
|
}
|
|
|
|
return AccessResult::forbiddenIf(!$account->hasPermission('administer profile'));
|
|
}
|
|
}
|
|
}
|
|
return AccessResult::neutral();
|
|
}
|
|
|
|
/**
|
|
* Implements hook_jsonapi_entity_field_filter_access().
|
|
*/
|
|
function profile_jsonapi_entity_field_filter_access(FieldDefinitionInterface $field_definition, AccountInterface $account) {
|
|
if ($field_definition->getTargetEntityTypeId() == 'profile') {
|
|
if ($field_definition instanceof FieldConfigInterface) {
|
|
$is_private = $field_definition->getThirdPartySetting('profile', 'profile_private', FALSE);
|
|
if ($is_private) {
|
|
return AccessResult::forbiddenIf(!$account->hasPermission('administer profile'));
|
|
}
|
|
}
|
|
}
|
|
return AccessResult::neutral();
|
|
}
|
|
|
|
/**
|
|
* Implements hook_theme().
|
|
*/
|
|
function profile_theme() {
|
|
return [
|
|
'profile' => [
|
|
'render element' => 'elements',
|
|
],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Prepares variables for profile templates.
|
|
*
|
|
* Default template: profile.html.twig.
|
|
*
|
|
* @param array $variables
|
|
* An associative array containing:
|
|
* - elements: An associative array containing rendered fields.
|
|
* - attributes: HTML attributes for the containing element.
|
|
*/
|
|
function template_preprocess_profile(array &$variables) {
|
|
/** @var Drupal\profile\Entity\ProfileInterface $profile */
|
|
$profile = $variables['elements']['#profile'];
|
|
|
|
$variables['view_mode'] = $variables['elements']['#view_mode'];
|
|
$variables['profile'] = $profile;
|
|
$variables['url'] = $profile->id() ? $profile->toUrl() : FALSE;
|
|
// Helpful $content variable for templates.
|
|
$variables['content'] = [];
|
|
foreach (Element::children($variables['elements']) as $key) {
|
|
$variables['content'][$key] = $variables['elements'][$key];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_user_delete().
|
|
*/
|
|
function profile_user_delete(EntityInterface $entity) {
|
|
$list = \Drupal::entityTypeManager()
|
|
->getStorage('profile')
|
|
->loadByProperties([
|
|
'uid' => $entity->id(),
|
|
]);
|
|
|
|
foreach ($list as $profile) {
|
|
$profile->delete();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_form_FORM_ID_alter().
|
|
*/
|
|
function profile_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
|
|
$field = $form_state->getFormObject()->getEntity();
|
|
if ($field->getTargetEntityTypeId() != 'profile') {
|
|
return;
|
|
}
|
|
|
|
$form['field']['profile']['profile_private'] = [
|
|
'#type' => 'checkbox',
|
|
'#title' => t('This is a private field.'),
|
|
'#default_value' => $field->getThirdPartySetting('profile', 'profile_private', FALSE),
|
|
];
|
|
$form['actions']['submit']['#submit'][] = 'profile_form_field_config_edit_form_submit';
|
|
}
|
|
|
|
/**
|
|
* Form submission handler for profile_form_field_config_edit_form_alter.
|
|
*
|
|
* @param array $form
|
|
* The form array.
|
|
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
|
* The form state.
|
|
*/
|
|
function profile_form_field_config_edit_form_submit(array $form, FormStateInterface $form_state) {
|
|
$field = $form_state->getFormObject()->getEntity();
|
|
$form_fields = &$form_state->getValues();
|
|
|
|
// If the private option is checked, update settings.
|
|
if ($form_fields['profile_private']) {
|
|
$field->setThirdPartySetting('profile', 'profile_private', TRUE);
|
|
$field->save();
|
|
}
|
|
else {
|
|
$field->unsetThirdPartySetting('profile', 'profile_private');
|
|
$field->save();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_entity_form_display_alter().
|
|
*/
|
|
function profile_entity_form_display_alter(EntityFormDisplayInterface $form_display, array $context) {
|
|
if ($context['entity_type'] !== 'profile') {
|
|
return;
|
|
}
|
|
$profile_type_id = $context['bundle'];
|
|
$entity_type_bundle_info = \Drupal::service('entity_type.bundle.info');
|
|
$bundle_info = $entity_type_bundle_info->getBundleInfo('profile');
|
|
if (empty($bundle_info[$profile_type_id]['revision_ui'])) {
|
|
$form_display->removeComponent('revision_log_message');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Implements hook_views_data_alter().
|
|
*
|
|
* Adds a relationship from the user table to its' profile entity.
|
|
*/
|
|
function profile_views_data_alter(&$data) {
|
|
$data['users_field_data']['profile']['relationship'] = [
|
|
'title' => t('Profile'),
|
|
'label' => t('Profile'),
|
|
'group' => 'User',
|
|
'help' => t('Reference to the profile of a user.'),
|
|
'id' => 'standard',
|
|
'base' => 'profile',
|
|
'base field' => 'uid',
|
|
'field' => 'uid',
|
|
];
|
|
$data['users_field_data']['profile_type']['relationship'] = [
|
|
'title' => t('Profile Type'),
|
|
'label' => t('Profile Type'),
|
|
'group' => 'User',
|
|
'help' => t('Reference to a specific profile type of a user.'),
|
|
'id' => 'profile_relationship',
|
|
'base' => 'profile',
|
|
'base field' => 'uid',
|
|
'field' => 'uid',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Implements hook_theme_suggestions_HOOK().
|
|
*/
|
|
function profile_theme_suggestions_profile(array $variables) {
|
|
$original = $variables['theme_hook_original'];
|
|
$entity = $variables['elements']['#profile'];
|
|
$sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
|
|
|
|
$suggestions = [];
|
|
$suggestions[] = $original;
|
|
$suggestions[] = $original . '__' . $sanitized_view_mode;
|
|
$suggestions[] = $original . '__' . $entity->bundle();
|
|
$suggestions[] = $original . '__' . $entity->bundle() . '__' . $sanitized_view_mode;
|
|
$suggestions[] = $original . '__' . $entity->id();
|
|
$suggestions[] = $original . '__' . $entity->id() . '__' . $sanitized_view_mode;
|
|
|
|
return $suggestions;
|
|
}
|
|
|
|
/**
|
|
* Implements hook_entity_base_field_info().
|
|
*/
|
|
function profile_entity_base_field_info(EntityTypeInterface $entity_type) {
|
|
if ($entity_type->id() === 'user') {
|
|
$entity_type_manager = \Drupal::entityTypeManager();
|
|
$fields = [];
|
|
|
|
// In random cases, this hook is invoked before the profile_type entity
|
|
// definition is registered.
|
|
if (!$entity_type_manager->hasDefinition('profile_type')) {
|
|
return $fields;
|
|
}
|
|
|
|
/** @var Drupal\profile\Entity\ProfileType[] $profile_types */
|
|
$profile_types = $entity_type_manager->getStorage('profile_type')->loadMultiple();
|
|
foreach ($profile_types as $profile_type) {
|
|
$profile_type_id = $profile_type->id();
|
|
$fields[$profile_type_id . '_profiles'] = BaseFieldDefinition::create('entity_reference')
|
|
->setName(sprintf('%s profiles', $profile_type->label()))
|
|
->setLabel(t('@label profiles', ['@label' => $profile_type->label()]))
|
|
->setDescription(t('User profiles.'))
|
|
->setClass(ProfileEntityFieldItemList::class)
|
|
->setSetting('target_type', 'profile')
|
|
->setSetting('handler_settings', [
|
|
'target_bundles' => [
|
|
$profile_type_id => $profile_type_id,
|
|
],
|
|
])
|
|
->setSetting('profile_type', $profile_type_id)
|
|
->setDisplayConfigurable('view', TRUE)
|
|
->setDisplayConfigurable('form', TRUE)
|
|
->setCardinality($profile_type->allowsMultiple() ? BaseFieldDefinition::CARDINALITY_UNLIMITED : 1)
|
|
->setComputed(TRUE);
|
|
}
|
|
return $fields;
|
|
}
|
|
}
|