You are here

profile.module in Profile 2 8

Support for configurable user profiles.

File

profile.module
View source
<?php

/**
 * @file
 * Support for configurable user profiles.
 */
use Drupal\user\UserInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Component\Utility\String;
use Drupal\Core\Url;
use Drupal\Core\Access\AccessResult;
use Drupal\profile\Entity\ProfileType;
use Drupal\profile\ProfileInterface;
use Drupal\field\FieldConfigInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Form\FormStateInterface;

/**
 * Denotes that the profile is not active.
 */
const PROFILE_NOT_ACTIVE = 0;

/**
 * Denotes that the profile is active.
 */
const PROFILE_ACTIVE = 1;

/**
 * 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.', array(
        '!user' => \Drupal::url('user.page'),
      )) . '</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-overview-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.', array(
        '!profile-overview-types' => \Drupal::url('profile.overview_types'),
      )) . '</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_profile_access().
 */
function profile_profile_access(ProfileInterface $profile, $op, $account) {
  $type = $profile
    ->bundle();
  switch ($op) {
    case 'view':
      if ($account
        ->hasPermission('view any ' . $type . ' profile', $account)) {
        return AccessResult::allowed()
          ->cachePerRole();
      }
      else {
        return AccessResult::allowedIfHasPermission($account, 'view own ' . $type . ' profile');
      }
    case 'create':
      if ($account
        ->hasPermission('add any ' . $type . ' profile', $account)) {
        return AccessResult::allowed()
          ->cachePerRole();
      }
      else {
        return AccessResult::allowedIfHasPermission($account, 'add own ' . $type . ' profile');
      }
    case 'update':
      if ($account
        ->hasPermission('edit any ' . $type . ' profile', $account)) {
        return AccessResult::allowed()
          ->cachePerRole();
      }
      else {
        return AccessResult::allowedIf($account
          ->hasPermission('edit own ' . $type . ' profile', $account) && $account
          ->id() == $profile
          ->getOwnerId())
          ->cachePerRole()
          ->cachePerUser()
          ->cacheUntilEntityChanges($profile);
      }
    case 'delete':
      if ($account
        ->hasPermission('delete any ' . $type . ' profile', $account)) {
        return AccessResult::allowed()
          ->cachePerRole();
      }
      else {
        return AccessResult::allowedIf($account
          ->hasPermission('delete own ' . $type . ' profile', $account) && $account
          ->id() == $profile
          ->getOwnerId())
          ->cachePerRole()
          ->cachePerUser()
          ->cacheUntilEntityChanges($profile);
      }
    default:

      // No opinion.
      return AccessResult::neutral();
  }
}

/**
 * Implements hook_user_view().
 */
function profile_user_view(array &$build, UserInterface $account, EntityViewDisplayInterface $display, $view_mode, $langcode) {

  // Only attach profiles for the full account view.
  if ($view_mode != 'full') {
    return;
  }

  // Position profiles at the bottom of account page.
  $weight = 100;
  foreach (\Drupal::configFactory()
    ->listAll('profile.type.') as $config_name) {
    $config = \Drupal::config($config_name);
    $profiles = \Drupal::entityManager()
      ->getStorage('profile')
      ->loadByProperties(array(
      'uid' => $account
        ->id(),
      'type' => $config
        ->get('id'),
      'status' => PROFILE_ACTIVE,
    ));
    if (count($profiles)) {

      // Only display profiles user has access.
      foreach ($profiles as $key => $profile) {
        if (!$profile
          ->access('view')) {
          unset($profiles[$key]);
        }
      }
      if (count($profiles)) {
        $build['profiles']['#weight'] = $weight + $config
          ->get('weight');
        $build['profiles'][$config
          ->get('id')] = array(
          '#theme' => 'profile_items',
          '#profile_items' => $profiles,
          '#type' => $config
            ->get('label'),
        );
      }
    }
  }
  $build['#attached']['library'][] = 'profile/drupal.profile-items';
}

/**
 * Implements hook_user_delete().
 */
function profile_user_delete(EntityInterface $entity) {
  $list = entity_load_multiple_by_properties('profile', array(
    'uid' => $entity
      ->id(),
  ));
  foreach ($list as $profile) {
    $profile
      ->delete();
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Add available profile forms to the user registration form.
 *
 */
function profile_form_user_register_form_alter(&$form, FormStateInterface $form_state) {
  $attached_profile_form = FALSE;
  $weight = 90;
  foreach (\Drupal::configFactory()
    ->listAll('profile.type.') as $config_name) {
    $config = \Drupal::config($config_name);
    $profile_type = ProfileType::load($config
      ->get('id'));
    $instances = array_filter(\Drupal::entityManager()
      ->getFieldDefinitions('profile', $config
      ->get('id')), function ($field_definition) {
      return $field_definition instanceof FieldConfigInterface;
    });
    if ($profile_type->registration === TRUE && count($instances)) {
      $id = $profile_type
        ->id();
      $property = [
        'profiles',
        $id,
      ];
      $profile = $form_state
        ->get($property);
      if (empty($profile)) {
        $entity = entity_create('profile', array(
          'type' => $id,
          'langcode' => $profile_type
            ->language() ? $profile_type
            ->language() : \Drupal::languageManager()
            ->getDefaultLanguage()->id,
        ));

        // Attach profile entity form.
        $form_state
          ->set($property, $entity);
        $form_state
          ->set('form_display_' . $id, EntityFormDisplay::collectRenderDisplay($entity, 'default'));
        $form['entity_' . $id] = array(
          '#type' => 'details',
          '#title' => $profile_type
            ->label(),
          '#tree' => TRUE,
          '#parents' => array(
            'entity_' . $id,
          ),
          '#weight' => ++$weight,
          '#open' => TRUE,
        );
        $form_state
          ->get('form_display_' . $id)
          ->buildForm($entity, $form['entity_' . $id], $form_state);
        $attached_profile_form = TRUE;
      }
    }
  }
  if ($attached_profile_form) {
    $form['actions']['submit']['#validate'][] = 'profile_form_user_register_form_validate';
    $form['actions']['submit']['#submit'][] = 'profile_form_user_register_form_submit';
  }
}

/**
 * Extra form validation handler for the user registration form.
 */
function profile_form_user_register_form_validate(array &$form, FormStateInterface $form_state) {
  $profiles = $form_state
    ->get('profiles');
  if (!empty($profiles)) {
    foreach ($profiles as $bundle => $entity) {
      $form_display = $form_state
        ->get('form_display_' . $bundle);
      $form_display
        ->extractFormValues($entity, $form['entity_' . $bundle], $form_state);
      $form_display
        ->validateFormValues($entity, $form['entity_' . $bundle], $form_state);
    }
  }
}

/**
 * Extra form submission handler for the user registration form.
 */
function profile_form_user_register_form_submit(array &$form, FormStateInterface $form_state) {
  $account = $form_state
    ->getFormObject()
    ->getEntity();
  $profiles = $form_state
    ->get('profiles');
  if (!empty($profiles)) {
    foreach ($profiles as $bundle => $entity) {
      $entity
        ->setOwnerId($account
        ->id());
      $entity
        ->setActive(TRUE);
      $entity
        ->save();
    }
  }
}

/**
 * Implements hook_theme().
 */
function profile_theme() {
  return array(
    'profile_items' => array(
      'variables' => array(
        'profile_items' => NULL,
        'type' => NULL,
      ),
      'template' => 'profile-items',
    ),
  );
}

/**
 * Implements hook_preprocess_HOOK() for profile templates.
 */
function template_preprocess_profile_items(&$variables) {
  if (count($variables['profile_items'])) {
    $variables['title'] = String::checkPlain($variables['type']);
    foreach ($variables['profile_items'] as $profile_item) {
      $variables['items'][] = entity_view($profile_item, 'default');
      if ($profile_item
        ->access('update')) {
        $variables['edit_links'][] = \Drupal::l(t('Edit'), new Url("entity.profile.edit_form", array(
          'user' => \Drupal::currentUser()
            ->id(),
          'profile_type' => $profile_item
            ->bundle(),
          'profile' => $profile_item
            ->id(),
        )));
      }
      if ($profile_item
        ->access('delete')) {
        $variables['delete_links'][] = \Drupal::l(t('Delete'), new Url("entity.profile.delete_form", array(
          'user' => \Drupal::currentUser()
            ->id(),
          'profile_type' => $profile_item
            ->bundle(),
          'profile' => $profile_item
            ->id(),
        )));
      }
    }
  }
}

Functions

Namesort descending Description
profile_form_user_register_form_alter Implements hook_form_FORM_ID_alter().
profile_form_user_register_form_submit Extra form submission handler for the user registration form.
profile_form_user_register_form_validate Extra form validation handler for the user registration form.
profile_help Implements hook_help().
profile_profile_access Implements hook_profile_access().
profile_theme Implements hook_theme().
profile_user_delete Implements hook_user_delete().
profile_user_view Implements hook_user_view().
template_preprocess_profile_items Implements hook_preprocess_HOOK() for profile templates.

Constants

Namesort descending Description
PROFILE_ACTIVE Denotes that the profile is active.
PROFILE_NOT_ACTIVE Denotes that the profile is not active.