' . t('About') . ''; $output .= '

' . 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 My Account 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()]) . '

'; $output .= '
'; $output .= '
' . t('Types of profiles') . '
'; $output .= '
' . 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 Profile types 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()]) . '
'; $output .= '
' . t('Creating profiles') . '
'; $output .= '
' . 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.') . '
'; $output .= '
'; 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; } }