updated webform, webform_localization, profile2, term_merge, search_api_saved_pages, rules, redirect, overide_node_options
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
Maintainers:
|
||||
* Wolfgang Ziegler (fago), nuppla@zites.net
|
||||
* Joachim Noreiko (joachim), joachim.n+drupal@gmail.com
|
||||
* Rick Jones (RickJ), rick@activeservice.co.uk
|
||||
|
||||
|
||||
This modules is designed to be the successor of the core profile module. In
|
||||
@@ -24,8 +25,26 @@ Usage
|
||||
-----
|
||||
|
||||
* Go to /admin/structure/profiles for managing profile types.
|
||||
* By default users may view their profile at /user and edit them at
|
||||
'user/X/edit'.
|
||||
* By default users' profile information is displayed on the
|
||||
account view page (/user/X). The relative positioning can be
|
||||
controlled using Account Settings -> Manage Display
|
||||
(/admin/config/people/accounts/display)
|
||||
|
||||
Profile titles
|
||||
--------------
|
||||
|
||||
A new feature in 7.x-1.6 gives each profile an unambiguous title.
|
||||
Previously, profile titles defaulted to the profile type, which was
|
||||
ambiguous, and contained other bugs. In this release the default
|
||||
profile title is "<type> profile for <user>".
|
||||
|
||||
This format is a translatable string, so can be easily customised.
|
||||
If you have locales installed you can use that, otherwise the
|
||||
String Overrides module provides a simple way to replace text in
|
||||
the current language.
|
||||
|
||||
The string to override is "@type profile for @user". To simulate
|
||||
the previous behaviour (without the bugs), just use "@type".
|
||||
|
||||
|
||||
|
||||
@@ -34,31 +53,30 @@ Usage
|
||||
--------------------------------------------------------------------------------
|
||||
Maintainers:
|
||||
* Wolfgang Ziegler (fago), nuppla@zites.net
|
||||
|
||||
This module provides an alternative way for your users to edit their profiles.
|
||||
Instead of integrating with the user account page, it generates a separate page
|
||||
allowing your users to view and edit their profile.
|
||||
* Rick Jones (RickJ), rick@activeservice.co.uk
|
||||
|
||||
This module provides alternative ways for users to view and edit their profiles.
|
||||
There are two options, instead of integrating with the user account page.
|
||||
|
||||
1. Generate a separate page for users to view and edit their profiles.
|
||||
|
||||
2. Display the profile in a separate sub-tab of the account page.
|
||||
In this case the editing mode of the profile is unchanged.
|
||||
|
||||
These options are mutually exclusive, but are set per profile type, so different
|
||||
profiles can display in different ways.
|
||||
|
||||
|
||||
Installation
|
||||
-------------
|
||||
|
||||
* Once profile2 is installed, just active the profile pages module.
|
||||
* Once profile2 is installed, just active the Profile2-pages module.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
* The module may be enabled per profile-type by checking the checkbox
|
||||
"Provide a separate page for editing profiles." in the profile type's
|
||||
settings.
|
||||
* Users with sufficient permissions (check user permissions) receive a menu
|
||||
item in their user menu, just beside the "My account" menu item.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
General notes
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
* Automatic profile labels can be easily generated based upon a pre-configured
|
||||
pattern using the Rules module. See http://drupal.org/node/1392716 for more
|
||||
details.
|
||||
* The module's options may be enabled per profile-type by checking one of the
|
||||
checkboxes "Provide a separate page for editing profiles." or
|
||||
"Provide a separate tab for viewing profiles." in the profile type's settings.
|
||||
* In the first case, users with sufficient permissions (check user permissions)
|
||||
receive a menu item in their user menu, next to the "My account" menu item.
|
||||
|
@@ -5,9 +5,8 @@ dependencies[] = i18n_string
|
||||
package = Multilingual - Internationalization
|
||||
core = 7.x
|
||||
|
||||
; Information added by drupal.org packaging script on 2012-12-26
|
||||
version = "7.x-1.3"
|
||||
; Information added by Drupal.org packaging script on 2019-01-01
|
||||
version = "7.x-1.6"
|
||||
core = "7.x"
|
||||
project = "profile2"
|
||||
datestamp = "1356482021"
|
||||
|
||||
datestamp = "1546363384"
|
||||
|
@@ -4,9 +4,8 @@ core = 7.x
|
||||
dependencies[] = profile2
|
||||
dependencies[] = og
|
||||
package = "Organic groups"
|
||||
; Information added by drupal.org packaging script on 2012-12-26
|
||||
version = "7.x-1.3"
|
||||
; Information added by Drupal.org packaging script on 2019-01-01
|
||||
version = "7.x-1.6"
|
||||
core = "7.x"
|
||||
project = "profile2"
|
||||
datestamp = "1356482021"
|
||||
|
||||
datestamp = "1546363384"
|
||||
|
@@ -25,13 +25,14 @@ function profile2_page_own($base_path) {
|
||||
* Profile view page.
|
||||
*/
|
||||
function profile2_page_view($profile) {
|
||||
return $profile->view('page');
|
||||
return $profile->view('page', NULL, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* The profile edit form.
|
||||
*/
|
||||
function profile2_form($form, &$form_state, $profile) {
|
||||
global $user;
|
||||
if (empty($form_state['profiles'])) {
|
||||
$form_state['profiles'][$profile->type] = $profile;
|
||||
}
|
||||
@@ -46,10 +47,16 @@ function profile2_form($form, &$form_state, $profile) {
|
||||
'#value' => t('Save'),
|
||||
'#weight' => 40,
|
||||
);
|
||||
if (empty($profile->is_new) && user_access('administer profiles')) {
|
||||
if (user_access('administer profiles') && $user->uid != $profile->uid) {
|
||||
$delete_button_label = t('Delete profile');
|
||||
}
|
||||
elseif (user_access("delete own $profile->type profile") && $user->uid === $profile->uid) {
|
||||
$delete_button_label = t('Delete this profile');
|
||||
}
|
||||
if (empty($profile->is_new) && !empty($delete_button_label)) {
|
||||
$form['actions']['delete'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Delete profile'),
|
||||
'#value' => $delete_button_label,
|
||||
'#weight' => 45,
|
||||
'#limit_validation_errors' => array(),
|
||||
'#submit' => array('profile2_form_submit_delete')
|
||||
@@ -79,14 +86,27 @@ function profile2_form_submit_delete($form, &$form_state) {
|
||||
* Confirm form for deleting a profile.
|
||||
*/
|
||||
function profile2_page_delete_confirm_form($form, &$form_state, $profile) {
|
||||
global $user;
|
||||
$form_state += array('profile2' => $profile);
|
||||
$confirm_question = t('Are you sure you want to delete profile %label?', array('%label' => $profile->label()));
|
||||
$type = profile2_get_types($profile->type);
|
||||
if (isset($profile->uid) && $profile->uid === $user->uid) {
|
||||
$confirm_question = t('Are you sure you want to delete your own %label profile ?',
|
||||
array('%label' => $type->getTranslation('label')));
|
||||
}
|
||||
elseif (user_access('administer profiles')) {
|
||||
$user_account = user_load($profile->uid);
|
||||
if (!empty($user_account)) {
|
||||
$confirm_question = t("Are you sure you want to delete profile %label of user %user?",
|
||||
array('%label' => $type->getTranslation('label'), '%user' => $user_account->name));
|
||||
}
|
||||
}
|
||||
return confirm_form($form, $confirm_question, $profile->path());
|
||||
}
|
||||
|
||||
function profile2_page_delete_confirm_form_submit($form, &$form_state) {
|
||||
$profile = $form_state['profile2'];
|
||||
$type = profile2_get_types($profile->type);
|
||||
$profile->delete();
|
||||
drupal_set_message(t('Deleted %label.', array('%label' => $profile->label)));
|
||||
drupal_set_message(t('Deleted %label.', array('%label' => $type->getTranslation('label'))));
|
||||
$form_state['redirect'] = 'user/' . $profile->uid;
|
||||
}
|
||||
|
@@ -2,9 +2,8 @@ name = Profile2 pages
|
||||
description = Adds separate pages for viewing and editing profiles.
|
||||
core = 7.x
|
||||
dependencies[] = profile2
|
||||
; Information added by drupal.org packaging script on 2012-12-26
|
||||
version = "7.x-1.3"
|
||||
; Information added by Drupal.org packaging script on 2019-01-01
|
||||
version = "7.x-1.6"
|
||||
core = "7.x"
|
||||
project = "profile2"
|
||||
datestamp = "1356482021"
|
||||
|
||||
datestamp = "1546363384"
|
||||
|
@@ -16,41 +16,34 @@ function profile2_page_menu() {
|
||||
return;
|
||||
}
|
||||
|
||||
$profile2_view_tab_count = 0;
|
||||
foreach (profile2_get_types() as $type_name => $type) {
|
||||
if (!empty($type->data['use_page'])) {
|
||||
$path = profile2_page_get_base_path($type);
|
||||
$count = count(explode('/', $path));
|
||||
|
||||
// This is the menu item for opening the user's own profile page.
|
||||
$items[$path] = array(
|
||||
'title callback' => 'profile2_page_title',
|
||||
'title arguments' => array($type_name),
|
||||
'title arguments' => array($type_name, TRUE),
|
||||
'page callback' => 'profile2_page_own',
|
||||
'page arguments' => array($path),
|
||||
'access callback' => 'user_access',
|
||||
'access arguments' => array("edit own $type_name profile"),
|
||||
'access arguments' => array("view own $type_name profile"),
|
||||
'file' => 'profile2_page.inc',
|
||||
'menu_name' => 'user-menu',
|
||||
);
|
||||
|
||||
// This is the router item that opens the page view.
|
||||
$items[$path . '/%profile2_by_uid'] = array(
|
||||
'title callback' => 'profile2_page_title',
|
||||
'title arguments' => array($type_name, $count),
|
||||
// Title is added in profile2_page_preprocess_page().
|
||||
'page callback' => 'profile2_page_view',
|
||||
'page arguments' => array($count),
|
||||
'load arguments' => array($type_name),
|
||||
'access callback' => 'profile2_access',
|
||||
'access arguments' => array('view', $count),
|
||||
'file' => 'profile2_page.inc',
|
||||
// Copied over the following hack from user_menu() to avoid $path
|
||||
// appearing in the breadcrumb:
|
||||
//
|
||||
// By assigning a different menu name, this item (and all registered
|
||||
// child paths) are no longer considered as children of 'user'. When
|
||||
// accessing the user account pages, the preferred menu link that is
|
||||
// used to build the active trail (breadcrumb) will be found in this
|
||||
// menu (unless there is more specific link), so the link to 'user' will
|
||||
// not be in the breadcrumb.
|
||||
'menu_name' => 'navigation',
|
||||
'type' => MENU_CALLBACK,
|
||||
);
|
||||
$items[$path . '/%profile2_by_uid/view'] = array(
|
||||
'title' => 'View',
|
||||
@@ -109,27 +102,57 @@ function profile2_page_menu() {
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (!empty($type->data['use_tab'])) {
|
||||
// Make tab(s) under user profile page.
|
||||
$items['user/%profile2_by_uid/view/' . $type_name] = array(
|
||||
'title callback' => 'profile2_page_title',
|
||||
'title arguments' => array($type_name),
|
||||
'page callback' => 'profile2_page_view',
|
||||
'page arguments' => array(1),
|
||||
'load arguments' => array($type_name),
|
||||
'access callback' => 'profile2_access',
|
||||
'access arguments' => array('view', 1),
|
||||
'type' => MENU_LOCAL_TASK,
|
||||
'file' => 'profile2_page.inc',
|
||||
);
|
||||
}
|
||||
$profile2_view_tab_count++;
|
||||
}
|
||||
// If there exists at least one tab for profile2 type,
|
||||
// then we need to create default tab for user account page.
|
||||
if ($profile2_view_tab_count) {
|
||||
$items['user/%user/view/account'] = array(
|
||||
'title' => 'Account',
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
'weight' => -10,
|
||||
);
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu load callback.
|
||||
* Implements hook_menu_local_tasks_alter().
|
||||
*
|
||||
* Returns the profile object for the given user. If there is none yet, a new
|
||||
* object is created.
|
||||
* If viewing a profile sub-tab, change the URL of the edit tab (if present)
|
||||
* so it edits the profile, not the main account page.
|
||||
* Subject to edit permissions.
|
||||
*/
|
||||
function profile2_by_uid_load($uid, $type_name) {
|
||||
if ($uid && is_numeric($uid) && ($account = user_load($uid))) {
|
||||
$profile = profile2_load_by_user($account, $type_name);
|
||||
if (!$profile) {
|
||||
$profile = profile2_create(array('type' => $type_name));
|
||||
$profile->setUser($account);
|
||||
$profile->is_new = TRUE;
|
||||
function profile2_page_menu_local_tasks_alter(&$data, $router_item, $root_path) {
|
||||
if (strpos($root_path, 'user/%/view/') === 0) {
|
||||
// Get the part of the URL containing "user/<uid>".
|
||||
$href = $router_item['tab_root_href'] . '/edit';
|
||||
// Get the uid & profile type name.
|
||||
$uid = $router_item['original_map'][1];
|
||||
$ptype = $router_item['original_map'][3];
|
||||
if (profile2_access('edit', profile2_by_uid_load($uid, $ptype))) {
|
||||
//Walk the menu tree to find the account-edit link, and append the profile type.
|
||||
array_walk_recursive($data, function (&$item) use ($href, $ptype) {
|
||||
if ($item == $href) {
|
||||
$item .= "/$ptype";
|
||||
}
|
||||
});
|
||||
}
|
||||
return $profile;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +178,12 @@ function profile2_page_forms($form_id, $args) {
|
||||
$forms['profile2_edit_' . $bundle . '_form']['callback'] = 'profile2_form';
|
||||
$forms['profile2_edit_' . $bundle . '_form']['wrapper callback'] = 'entity_ui_form_defaults';
|
||||
}
|
||||
return $forms;
|
||||
if (!empty($forms)) {
|
||||
// Include the file with profile2_form() callback. This needed when the
|
||||
// form is loaded from the outside, for example, from the ajax callback.
|
||||
form_load_include($form_state, 'inc', 'profile2_page');
|
||||
return $forms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +197,9 @@ function profile2_page_profile2_type_load($types) {
|
||||
$type->userCategory = FALSE;
|
||||
$type->userView = FALSE;
|
||||
}
|
||||
elseif (!empty($type->data['use_tab'])) {
|
||||
$type->userView = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +218,12 @@ function profile2_page_entity_info_alter(&$entity_info) {
|
||||
);
|
||||
$entity_info['profile2']['uri callback'] = 'profile2_page_uri_callback';
|
||||
$entity_info['profile2']['form callback'] = 'profile2_page_form_callback';
|
||||
|
||||
// Integrate with Metatag module to enable metatags support for separate
|
||||
// profile pages.
|
||||
if (module_exists('metatag')) {
|
||||
$entity_info['profile2']['metatags'] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,16 +251,14 @@ function profile2_page_form_callback($profile) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu title callback.
|
||||
* Menu title callbacks.
|
||||
*/
|
||||
function profile2_page_title($type_name, $profile2 = NULL) {
|
||||
$type = profile2_get_types($type_name);
|
||||
// If no profile is given, we are at the general path pointing to the own
|
||||
// profile.
|
||||
if (!isset($profile2)) {
|
||||
return t('My @profile-label', array('@profile-label' => drupal_strtolower($type->getTranslation('label'))));
|
||||
function profile2_page_title($type_name, $my = FALSE) {
|
||||
$label = profile2_get_types($type_name)->getTranslation('label');
|
||||
if ($my) {
|
||||
$label = t('My @title', array('@title' => $label));
|
||||
}
|
||||
return drupal_ucfirst($profile2->label());
|
||||
return $label;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,41 +269,44 @@ function profile2_page_form_profile2_type_form_alter(&$form, &$form_state) {
|
||||
$form['data']['use_page'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Provide a separate page for editing profiles.'),
|
||||
'#description' => t('If enabled, a separate menu item for editing the profile is generated and the profile is hidden from the user account page.'),
|
||||
'#default_value' => !empty($type->is_new) || !empty($type->data['use_page']),
|
||||
'#description' => t('If enabled, a separate menu item for viewing and editing the profile is generated, and the profile is hidden from the user account page.'),
|
||||
'#default_value' => empty($type->is_new) && !empty($type->data['use_page']),
|
||||
'#states' => array(
|
||||
'invisible' => array(
|
||||
':input[name="data[use_tab]"]' => array('checked' => TRUE),
|
||||
),
|
||||
),
|
||||
);
|
||||
$form['data']['use_tab'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Provide a separate tab for viewing profiles.'),
|
||||
'#description' => t('If enabled, the profile is shown under a separate tab on the user account page.'),
|
||||
'#default_value' => empty($type->is_new) && !empty($type->data['use_tab']),
|
||||
'#states' => array(
|
||||
'invisible' => array(
|
||||
':input[name="data[use_page]"]' => array('checked' => TRUE),
|
||||
),
|
||||
),
|
||||
);
|
||||
$form['data']['#tree'] = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_profile2_type_insert().
|
||||
* Implements hook_preprocess_page().
|
||||
*
|
||||
* Fix the page titles on the profile view pages.
|
||||
* We want the titles to be the full profile label, giving the user name & profile name.
|
||||
*
|
||||
* Note: the title for the separate edit page is already correct.
|
||||
*/
|
||||
function profile2_page_profile2_type_insert(ProfileType $type) {
|
||||
// Do not directly issue menu rebuilds here to avoid potentially multiple
|
||||
// rebuilds. Instead, let menu_get_item() issue the rebuild on the next page.
|
||||
if (!empty($type->data['use_page'])) {
|
||||
variable_set('menu_rebuild_needed', TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_profile2_type_update().
|
||||
*/
|
||||
function profile2_page_profile2_type_update(ProfileType $type) {
|
||||
// Rebuild the menu if use_page or the type name has been changed.
|
||||
// @see profile2_page_profile2_type_insert()
|
||||
if (empty($type->data['use_page']) != empty($type->original->data['use_page']) || ($type->data['use_page'] && $type->type != $type->original->type)) {
|
||||
variable_set('menu_rebuild_needed', TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_profile2_type_delete()
|
||||
*/
|
||||
function profile2_page_profile2_type_delete($type) {
|
||||
// Do not directly issue menu rebuilds here to avoid potentially multiple
|
||||
// rebuilds. Instead, let menu_get_item() issue the rebuild on the next page.
|
||||
if (!empty($type->data['use_page'])) {
|
||||
variable_set('menu_rebuild_needed', TRUE);
|
||||
function profile2_page_preprocess_page(&$vars) {
|
||||
// This is true for profile2 view pages, both as a tab and a separate page.
|
||||
if (!empty($vars['page']['content']['system_main']['profile2'])) {
|
||||
// Get the one item, index is unknown..
|
||||
$item = reset($vars['page']['content']['system_main']['profile2']);
|
||||
// If we've found an item, and it has a profile2 entity, display the title.
|
||||
if (!empty($item['#entity'])) {
|
||||
$vars['title'] = $item['#entity']->label();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Plugin to provide an relationship handler for profile2 from user.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Plugins are described by creating a $plugin array which will be used
|
||||
* by the system that includes this file.
|
||||
*/
|
||||
$plugin = array(
|
||||
'title' => t('Profile2 from user'),
|
||||
'keyword' => 'profile2',
|
||||
'description' => t('Adds a profile2 type from a user context.'),
|
||||
'required context' => new ctools_context_required(t('User'), 'entity:user'),
|
||||
'context' => 'profile2_from_user_context',
|
||||
'edit form' => 'profile2_from_user_settings_form',
|
||||
'defaults' => array('type' => 'main'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Return a new context based on an existing context.
|
||||
*/
|
||||
function profile2_from_user_context($context, $conf) {
|
||||
// If unset it wants a generic, unfilled context, which is just NULL.
|
||||
if (empty($context->data) || !isset($context->data->uid)) {
|
||||
return ctools_context_create_empty('entity:profile2', NULL);
|
||||
}
|
||||
|
||||
// Load user's profile and return a ctools context from it.
|
||||
if ($profile = profile2_load_by_user($context->data, $conf['type'])) {
|
||||
return ctools_context_create('entity:profile2', $profile);
|
||||
}
|
||||
|
||||
// In case when we can't load a profile, just return an empty context.
|
||||
return ctools_context_create_empty('entity:profile2', NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings form for the relationship.
|
||||
*/
|
||||
function profile2_from_user_settings_form($form, &$form_state) {
|
||||
$conf = $form_state['conf'];
|
||||
|
||||
$options = array();
|
||||
foreach (profile2_get_types() as $type => $info) {
|
||||
$options[$type] = $info->label;
|
||||
}
|
||||
|
||||
$form['type'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Select Profile2 Type'),
|
||||
'#options' => $options,
|
||||
'#default_value' => $conf['type'],
|
||||
'#prefix' => '<div class="clearfix">',
|
||||
'#suffix' => '</div>',
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
@@ -58,6 +58,17 @@ function profile2_type_form($form, &$form_state, $profile_type, $op = 'edit') {
|
||||
'#default_value' => !empty($profile_type->data['registration']),
|
||||
);
|
||||
|
||||
$user_roles = user_roles();
|
||||
// Exclude anonymous user role.
|
||||
unset($user_roles[DRUPAL_ANONYMOUS_RID]);
|
||||
$form['data']['roles'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => t('Roles'),
|
||||
'#description' => t('Check user roles that should have this profile.'),
|
||||
'#options' => $user_roles,
|
||||
'#default_value' => !empty($profile_type->data['roles']) ? $profile_type->data['roles'] : array_keys($user_roles)
|
||||
);
|
||||
|
||||
$form['actions'] = array('#type' => 'actions');
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
@@ -88,6 +99,7 @@ function profile2_type_form($form, &$form_state, $profile_type, $op = 'edit') {
|
||||
* Form API submit callback for the type form.
|
||||
*/
|
||||
function profile2_type_form_submit(&$form, &$form_state) {
|
||||
$form_state['values']['data']['roles'] = array_filter($form_state['values']['data']['roles']);
|
||||
$profile_type = entity_ui_form_submit_build_entity($form, $form_state);
|
||||
// Save and go back.
|
||||
$profile_type->save();
|
||||
|
@@ -138,7 +138,7 @@ function hook_profile2_view($profile, $view_mode, $langcode) {
|
||||
*
|
||||
* @see hook_entity_view_alter()
|
||||
*/
|
||||
function hook_profile2_view_alter($build) {
|
||||
function hook_profile2_view_alter(&$build) {
|
||||
if ($build['#view_mode'] == 'full' && isset($build['an_additional_field'])) {
|
||||
// Change its weight.
|
||||
$build['an_additional_field']['#weight'] = -10;
|
||||
|
38
sites/all/modules/contrib/users/profile2/profile2.delete.inc
Normal file
38
sites/all/modules/contrib/users/profile2/profile2.delete.inc
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains functions for Profile Delete.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Confirm form for deleting own profile.
|
||||
*/
|
||||
function profile2_delete_confirm_form($form, &$form_state, $profile) {
|
||||
global $user;
|
||||
if (isset($profile) && is_object($profile)) {
|
||||
$form_state += array('profile2' => $profile);
|
||||
if ($user->uid === $profile->uid) {
|
||||
$confirm_question = t('Are you sure you want to delete your own %label profile ?', array('%label' => $profile->label));
|
||||
}
|
||||
elseif (user_access('administer profiles')) {
|
||||
$user_account = user_load($profile->uid);
|
||||
if (!empty($user_account)) {
|
||||
$confirm_question = t("Are you sure you want to delete profile %label of user %user?", array('%label' => $profile->label, '%user' => $user_account->name));
|
||||
}
|
||||
}
|
||||
return confirm_form($form, $confirm_question, 'user/' . $profile->uid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Confirm form submit for deleting own profile.
|
||||
*/
|
||||
function profile2_delete_confirm_form_submit($form, &$form_state) {
|
||||
$profile = isset($form_state['profile2']) ? $form_state['profile2'] : '';
|
||||
if (isset($profile) && is_object($profile)) {
|
||||
$profile->delete();
|
||||
drupal_set_message(t('Deleted %label.', array('%label' => $profile->label)));
|
||||
}
|
||||
$form_state['redirect'] = 'user/' . $profile->uid;
|
||||
}
|
145
sites/all/modules/contrib/users/profile2/profile2.devel.inc
Normal file
145
sites/all/modules/contrib/users/profile2/profile2.devel.inc
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains integration with Devel generate modules.
|
||||
* Provides possibility to generate dummy profiles for users.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Form that allows to generate a user profiles with dummy data.
|
||||
*/
|
||||
function profile2_generate_form($form, &$form_state) {
|
||||
|
||||
// Generate a list with available profile types.
|
||||
$profile_types = profile2_get_types();
|
||||
foreach ($profile_types as $id => $type) {
|
||||
$profile_types[$id] = $type->label;
|
||||
}
|
||||
|
||||
$form['profile2_types'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => t('Generate profiles of the following types'),
|
||||
'#description' => t('Select profile type(s) to create profile. If no types are selected, profiles of all types will be generated.'),
|
||||
'#options' => $profile_types,
|
||||
);
|
||||
|
||||
$roles_list = user_roles(TRUE);
|
||||
|
||||
// Don't show authorized role.
|
||||
unset($roles_list[DRUPAL_AUTHENTICATED_RID]);
|
||||
|
||||
$form['profile2_roles'] = array(
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => t('Generate profiles for following user roles'),
|
||||
'#options' => $roles_list,
|
||||
);
|
||||
|
||||
$form['profile2_generate_limit'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Maximum number of profiles per type'),
|
||||
'#element_validate' => array('element_validate_integer_positive'),
|
||||
'#default_value' => 50,
|
||||
'#size' => 10,
|
||||
);
|
||||
|
||||
$form['profile2_delete'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Delete existing profiles'),
|
||||
);
|
||||
|
||||
$form['actions'] = array(
|
||||
'#type' => 'actions',
|
||||
);
|
||||
|
||||
$form['actions']['submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Generate'),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback for profile2_generate_form().
|
||||
* Generates profiles for users.
|
||||
*/
|
||||
function profile2_generate_form_submit($form, &$form_state) {
|
||||
|
||||
$values = $form_state['values'];
|
||||
|
||||
// Initial database query that allows to fetch all user ids except anonymous.
|
||||
$query = db_select('users', 'u');
|
||||
$query->fields('u', array('uid'));
|
||||
$query->condition('u.uid', 0, '<>');
|
||||
|
||||
// If user selected certain user roles - we need to filter by them.
|
||||
$roles_selected = array_filter($values['profile2_roles']);
|
||||
if (!empty($roles_selected)) {
|
||||
$query->innerJoin('users_roles', 'ur', 'ur.uid = u.uid');
|
||||
$query->condition('ur.rid', $roles_selected);
|
||||
}
|
||||
|
||||
// Fetch uids for which profiles should be generated.
|
||||
$uids = $query->execute()->fetchCol('uid');
|
||||
|
||||
// Delete all profiles before generation.
|
||||
if (!empty($values['profile2_delete'])) {
|
||||
|
||||
$profile_ids = db_select('profile')
|
||||
->fields('profile', array('pid'))
|
||||
->execute()
|
||||
->fetchCol('pid');
|
||||
|
||||
profile2_delete_multiple($profile_ids);
|
||||
|
||||
// Set message that indicates how much profiles were deleted.
|
||||
$message = format_plural(count($profile_ids), t('1 profile was deleted.'), t('@count profiles were deleted.'));
|
||||
drupal_set_message($message);
|
||||
}
|
||||
|
||||
$new_pids = array();
|
||||
if (!empty($uids)) {
|
||||
|
||||
// Get selected profile types. Load them all if no profile type was chosen.
|
||||
$profile_types = array_filter($values['profile2_types']);
|
||||
if (empty($profile_types)) {
|
||||
$profile_types = profile2_get_types();
|
||||
}
|
||||
|
||||
// Generate user-defined amount of certain profile types.
|
||||
foreach ($profile_types as $profile_type_name => $profile_type) {
|
||||
$counter = 0;
|
||||
$uids_to_generate = $uids;
|
||||
while ($counter < $values['profile2_generate_limit'] && !empty($uids_to_generate)) {
|
||||
$uid = array_shift($uids_to_generate);
|
||||
|
||||
// If user already has profile of certain type - skip the generation for it.
|
||||
if (profile2_load_by_user($uid, $profile_type_name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$profile2 = entity_create('profile2', array('type' => $profile_type_name, 'uid' => $uid));
|
||||
|
||||
// Populate all core fields on behalf of field.module.
|
||||
module_load_include('fields.inc', 'devel_generate');
|
||||
module_load_include('inc', 'devel_generate');
|
||||
devel_generate_fields($profile2, 'profile2', $profile2->type);
|
||||
|
||||
// Set profile language.
|
||||
$profile2->language = LANGUAGE_NONE;
|
||||
|
||||
// Create new profile of the certain type.
|
||||
$new_pids[] = entity_save('profile2', $profile2);
|
||||
|
||||
// Increase counter of generated profiles of certain type.
|
||||
$counter++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Show message that indicates how much profiles were created.
|
||||
$message = format_plural(count($new_pids), '1 profile were generated', '@count profiles were generated.');
|
||||
drupal_set_message($message);
|
||||
}
|
@@ -6,9 +6,8 @@ files[] = profile2.info.inc
|
||||
files[] = profile2.test
|
||||
dependencies[] = entity
|
||||
configure = admin/structure/profiles
|
||||
; Information added by drupal.org packaging script on 2012-12-26
|
||||
version = "7.x-1.3"
|
||||
; Information added by Drupal.org packaging script on 2019-01-01
|
||||
version = "7.x-1.6"
|
||||
core = "7.x"
|
||||
project = "profile2"
|
||||
datestamp = "1356482021"
|
||||
|
||||
datestamp = "1546363384"
|
||||
|
@@ -16,7 +16,7 @@ function profile2_install() {
|
||||
'type' => 'main',
|
||||
'label' => t('Main profile'),
|
||||
'weight' => 0,
|
||||
'data' => array('registration' => TRUE, 'use_page' => TRUE),
|
||||
'data' => array('registration' => TRUE),
|
||||
));
|
||||
$type->save();
|
||||
user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('edit own main profile', 'view own main profile'));
|
||||
@@ -81,6 +81,9 @@ function profile2_schema() {
|
||||
'columns' => array('type' => 'type'),
|
||||
),
|
||||
),
|
||||
'unique keys' => array(
|
||||
'user_profile_type' => array('type', 'uid'),
|
||||
),
|
||||
'primary key' => array('pid'),
|
||||
);
|
||||
|
||||
@@ -143,6 +146,22 @@ function profile2_schema() {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_uninstall()
|
||||
*/
|
||||
function profile2_uninstall() {
|
||||
// Select all available profile2 bundles from the database directly, instead
|
||||
// of entity_load() call. See https://drupal.org/node/1330598 for details.
|
||||
$types = db_select('profile_type', 'p')
|
||||
->fields('p')
|
||||
->execute()
|
||||
->fetchAllAssoc('type');
|
||||
|
||||
foreach ($types as $name => $type) {
|
||||
field_attach_delete_bundle('profile2', $name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add in the exportable entity db columns as required by the entity API.
|
||||
*/
|
||||
@@ -204,3 +223,46 @@ function profile2_update_7102() {
|
||||
'not null' => FALSE,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove duplicate profile records in batches of 50.
|
||||
*/
|
||||
function profile2_update_7103(&$sandbox) {
|
||||
// Query to get duplicate profiles.
|
||||
$query = db_select('profile', 'p1');
|
||||
$query->distinct();
|
||||
$query->fields('p1', array('pid'));
|
||||
$query->join('profile', 'p2', 'p1.type = p2.type AND p1.uid = p2.uid AND p1.label = p2.label AND p1.pid < p2.pid');
|
||||
|
||||
// Setup initial batch variables.
|
||||
if (!isset($sandbox['progress'])) {
|
||||
// The number of duplicate profiles deleted so far.
|
||||
$sandbox['progress'] = 0;
|
||||
// Total number of duplicate profiles that will be deleted.
|
||||
$sandbox['total'] = $query->execute()->rowCount();
|
||||
}
|
||||
|
||||
// Query the next 50 profiles to be deleted.
|
||||
$query->range(0, 50);
|
||||
$result = $query->execute();
|
||||
|
||||
// Update progress of removing duplicate profiles.
|
||||
$sandbox['progress'] = $sandbox['progress'] + $result->rowCount();
|
||||
|
||||
// Delete duplicate profiles.
|
||||
profile2_delete_multiple($result->fetchCol());
|
||||
|
||||
// Update batch status.
|
||||
$sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['total']) ? TRUE : ($sandbox['progress'] / $sandbox['total']);
|
||||
|
||||
if ($sandbox['#finished']) {
|
||||
return t('@total duplicate profiles were removed from the system.', array('@total' => $sandbox['progress']));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The combination of profile type and uid should be unique.
|
||||
*/
|
||||
function profile2_update_7104() {
|
||||
db_add_unique_key('profile', 'user_profile_type', array('type', 'uid'));
|
||||
}
|
||||
|
@@ -105,6 +105,39 @@ function profile2_type_load($type) {
|
||||
return profile2_get_types($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function profile2_menu() {
|
||||
$items = array();
|
||||
|
||||
// Define page which provides form to generate profiles using
|
||||
// Devel generate module.
|
||||
if (module_exists('devel_generate')) {
|
||||
$items['admin/config/development/generate/profile2'] = array(
|
||||
'title' => 'Generate profiles',
|
||||
'description' => 'Generate a given number of profiles for users. Optionally override current user profiles.',
|
||||
'access arguments' => array('administer profiles'),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('profile2_generate_form'),
|
||||
'file' => 'profile2.devel.inc',
|
||||
);
|
||||
}
|
||||
|
||||
$items['user/%profile2_by_uid/%/delete'] = array(
|
||||
'title' => 'Delete',
|
||||
'description' => 'Delete Profile of User.',
|
||||
'type' => MENU_NORMAL_ITEM,
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('profile2_delete_confirm_form', 1),
|
||||
'load arguments' => array(2),
|
||||
'access callback' => 'profile2_access',
|
||||
'access arguments' => array('delete', 1),
|
||||
'file' => 'profile2.delete.inc',
|
||||
);
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
@@ -135,6 +168,9 @@ function profile2_permission() {
|
||||
"view any $type_name profile" => array(
|
||||
'title' => t('%type_name: View any profile', array('%type_name' => $type->getTranslation('label'))),
|
||||
),
|
||||
"delete own $type_name profile" => array(
|
||||
'title' => t('%type_name: Delete own profile', array('%type_name' => $type->getTranslation('label'))),
|
||||
),
|
||||
);
|
||||
}
|
||||
return $permissions;
|
||||
@@ -212,24 +248,17 @@ function profile2_load_by_user($account, $type_name = NULL) {
|
||||
$uid = is_object($account) ? $account->uid : $account;
|
||||
|
||||
if (!isset($cache[$uid])) {
|
||||
if (empty($type_name)) {
|
||||
$profiles = profile2_load_multiple(FALSE, array('uid' => $uid));
|
||||
// Cache ids for further lookups.
|
||||
$cache[$uid] = array();
|
||||
foreach ($profiles as $pid => $profile) {
|
||||
$cache[$uid][$profile->type] = $pid;
|
||||
}
|
||||
return $profiles ? array_combine(array_keys($cache[$uid]), $profiles) : array();
|
||||
}
|
||||
$cache[$uid] = db_select('profile', 'p')
|
||||
->fields('p', array('type', 'pid'))
|
||||
->condition('uid', $uid)
|
||||
->execute()
|
||||
->fetchAllKeyed();
|
||||
}
|
||||
|
||||
if (isset($type_name)) {
|
||||
return isset($cache[$uid][$type_name]) ? profile2_load($cache[$uid][$type_name]) : FALSE;
|
||||
}
|
||||
|
||||
// Return an array containing profiles keyed by profile type.
|
||||
return $cache[$uid] ? array_combine(array_keys($cache[$uid]), profile2_load_multiple($cache[$uid])) : $cache[$uid];
|
||||
}
|
||||
@@ -308,8 +337,25 @@ function profile2_type_delete(ProfileType $type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_profile2_type_delete()
|
||||
*/
|
||||
* Implements hook_profile2_type_insert().
|
||||
*/
|
||||
function profile2_profile2_type_insert(ProfileType $type) {
|
||||
// Do not directly issue menu rebuilds here to avoid potentially multiple
|
||||
// rebuilds. Instead, let menu_get_item() issue the rebuild on the next page.
|
||||
variable_set('menu_rebuild_needed', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_profile2_type_update().
|
||||
*/
|
||||
function profile2_profile2_type_update(ProfileType $type) {
|
||||
// @see profile2_profile2_type_insert()
|
||||
variable_set('menu_rebuild_needed', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_profile2_type_delete()
|
||||
*/
|
||||
function profile2_profile2_type_delete(ProfileType $type) {
|
||||
// Delete all profiles of this type but only if this is not a revert.
|
||||
if (!$type->hasStatus(ENTITY_IN_CODE)) {
|
||||
@@ -317,6 +363,8 @@ function profile2_profile2_type_delete(ProfileType $type) {
|
||||
if ($pids) {
|
||||
profile2_delete_multiple($pids);
|
||||
}
|
||||
// @see profile2_profile2_type_insert()
|
||||
variable_set('menu_rebuild_needed', TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,10 +377,10 @@ function profile2_user_view($account, $view_mode, $langcode) {
|
||||
if (profile2_access('view', $profile)) {
|
||||
$account->content['profile_' . $type] = array(
|
||||
'#type' => 'user_profile_category',
|
||||
'#title' => $profile->label,
|
||||
'#title' => $profile_type->getTranslation('label'),
|
||||
'#prefix' => '<a id="profile-' . $profile->type . '"></a>',
|
||||
);
|
||||
$account->content['profile_' . $type]['view'] = $profile->view('account');
|
||||
$account->content['profile_' . $type]['view'] = $profile->view($view_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,18 +393,46 @@ function profile2_user_view($account, $view_mode, $langcode) {
|
||||
* @see profile2_form_submit_handler
|
||||
*/
|
||||
function profile2_form_user_profile_form_alter(&$form, &$form_state) {
|
||||
global $user;
|
||||
if (($type = profile2_get_types($form['#user_category'])) && $type->userCategory) {
|
||||
if (empty($form_state['profiles'])) {
|
||||
$profile = profile2_load_by_user($form['#user'], $form['#user_category']);
|
||||
if (empty($profile)) {
|
||||
$profile = profile2_create(array('type' => $form['#user_category'], 'uid' => $form['#user']->uid));
|
||||
$profile->is_new = TRUE;
|
||||
}
|
||||
$form_state['profiles'][$profile->type] = $profile;
|
||||
|
||||
if (user_access('administer profiles') && $user->uid != $profile->uid) {
|
||||
$str_button_value = t('Delete profile');
|
||||
}
|
||||
elseif (user_access("delete own $profile->type profile") && $user->uid === $profile->uid) {
|
||||
$str_button_value = t('Delete this profile');
|
||||
}
|
||||
}
|
||||
if (empty($profile->is_new) && !empty($str_button_value)) {
|
||||
$form['actions']['delete'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => $str_button_value,
|
||||
'#weight' => 45,
|
||||
'#limit_validation_errors' => array(),
|
||||
'#submit' => array('profile2_form_submit_own_delete')
|
||||
);
|
||||
}
|
||||
profile2_attach_form($form, $form_state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Profile form submit handler for the delete button.
|
||||
*/
|
||||
function profile2_form_submit_own_delete($form, &$form_state) {
|
||||
$profile = $form_state['profiles'][$form['#user_category']];
|
||||
if (isset($profile) && is_object($profile)) {
|
||||
$form_state['redirect'] = 'user/' . $profile->uid . '/' . $form['#user_category'] . '/delete';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_FORM_ID_alter() for the registration form.
|
||||
*/
|
||||
@@ -366,8 +442,15 @@ function profile2_form_user_register_form_alter(&$form, &$form_state) {
|
||||
if (empty($form_state['profiles'][$type_name])) {
|
||||
$form_state['profiles'][$type_name] = profile2_create(array('type' => $type_name));
|
||||
}
|
||||
profile2_attach_form($form, $form_state);
|
||||
// Wrap each profile form in a fieldset.
|
||||
}
|
||||
}
|
||||
|
||||
// If we have profiles to attach to the registration form - then do it.
|
||||
if (!empty($form_state['profiles'])) {
|
||||
profile2_attach_form($form, $form_state);
|
||||
|
||||
// Wrap each profile form in a fieldset.
|
||||
foreach ($form_state['profiles'] as $type_name => $profile_type) {
|
||||
$form['profile_' . $type_name] += array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => check_plain($profile_type->getTranslation('label')),
|
||||
@@ -399,13 +482,17 @@ function profile2_attach_form(&$form, &$form_state) {
|
||||
$form['profile_' . $profile->type]['#parents'] = array('profile_' . $profile->type);
|
||||
field_attach_form('profile2', $profile, $form['profile_' . $profile->type], $form_state);
|
||||
|
||||
if (count(field_info_instances('profile2', $profile->type)) == 0) {
|
||||
$form['profile_' . $profile->type]['message'] = array(
|
||||
'#access' => user_access('administer profile types'),
|
||||
'#markup' => t('No fields have been associated with this profile type. Go to the <a href="!url">Profile types</a> page to add some fields.', array('!url' => url('admin/structure/profiles'))),
|
||||
);
|
||||
if (user_access('administer profile types')) {
|
||||
if (count(field_info_instances('profile2', $profile->type)) == 0) {
|
||||
$form['profile_' . $profile->type]['message'] = array(
|
||||
'#markup' => t('No fields have been associated with this profile type. Go to the <a href="!url">Profile types</a> page to add some fields.', array('!url' => url('admin/structure/profiles'))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we don't have duplicate pre render callbacks.
|
||||
$form['profile_' . $profile->type]['#pre_render'] = array_unique($form['profile_' . $profile->type]['#pre_render']);
|
||||
|
||||
// Provide a central place for modules to alter the profile forms, but
|
||||
// skip that in case the caller cares about invoking the hooks.
|
||||
// @see profile2_form().
|
||||
@@ -416,7 +503,42 @@ function profile2_attach_form(&$form, &$form_state) {
|
||||
}
|
||||
}
|
||||
$form['#validate'][] = 'profile2_form_validate_handler';
|
||||
$form['#submit'][] = 'profile2_form_submit_handler';
|
||||
|
||||
// Default name of user registry form callback.
|
||||
$register_submit_callback = 'user_register_submit';
|
||||
|
||||
// LoginToBoggan module replaces default user_register_submit() callback
|
||||
// with his own. So if this module enabled we need to track his callback
|
||||
// instead one that comes from the User module.
|
||||
if (module_exists('logintoboggan')) {
|
||||
$register_submit_callback = 'logintoboggan_user_register_submit';
|
||||
}
|
||||
|
||||
// Search for key of user register submit callback.
|
||||
if (!empty($form['#submit']) && is_array($form['#submit'])) {
|
||||
$submit_key = array_search($register_submit_callback, $form['#submit']);
|
||||
}
|
||||
|
||||
// Add these hooks only when needed, and ensure they are not added twice.
|
||||
if (isset($submit_key) && $submit_key !== FALSE && !in_array('profile2_form_before_user_register_submit_handler', $form['#submit'])) {
|
||||
|
||||
// Insert submit callback right before the user register submit callback.
|
||||
// Needs for disabling email notification during user registration.
|
||||
array_splice($form['#submit'], $submit_key, 0, array('profile2_form_before_user_register_submit_handler'));
|
||||
|
||||
// Add a submit callback right after the user register submit callback.
|
||||
// This is needed for creation of a new user profile.
|
||||
array_splice($form['#submit'], $submit_key + 2, 0, array('profile2_form_submit_handler'));
|
||||
|
||||
// Insert submit handler right after the creation of new user profile.
|
||||
// This is needed for sending email which was blocked during registration.
|
||||
array_splice($form['#submit'], $submit_key + 3, 0, array('profile2_form_after_user_register_submit_handler'));
|
||||
}
|
||||
else {
|
||||
// Fallback if some contrib module removes user register submit callback
|
||||
// from form submit functions.
|
||||
$form['#submit'][] = 'profile2_form_submit_handler';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,6 +557,99 @@ function profile2_form_validate_handler(&$form, &$form_state) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User registration form submit handler
|
||||
* that executes right before user_register_submit().
|
||||
*
|
||||
* In generally, this callback disables the notification emails
|
||||
* during the execution of user_register_submit() callback.
|
||||
* The reason for this - we want to support profile2 tokens
|
||||
* in emails during registration, and there is no another
|
||||
* proper way to do this. See https://drupal.org/node/1097684.
|
||||
*
|
||||
* @see profile2_form_after_user_register_submit_handler()
|
||||
* @see user_register_submit()
|
||||
* @see profile2_attach_form()
|
||||
*/
|
||||
function profile2_form_before_user_register_submit_handler(&$form, &$form_state) {
|
||||
global $conf;
|
||||
|
||||
// List of available operations during the registration.
|
||||
$register_ops = array('register_admin_created', 'register_no_approval_required', 'register_pending_approval');
|
||||
|
||||
// We also have to track if we change a variables, because
|
||||
// later we have to restore them.
|
||||
$changed_ops = &drupal_static('profile2_register_changed_operations', array());
|
||||
foreach ($register_ops as $op) {
|
||||
|
||||
// Save variable value.
|
||||
if (isset($conf['user_mail_' . $op . '_notify'])) {
|
||||
$changed_ops['user_mail_' . $op . '_notify'] = $conf['user_mail_' . $op . '_notify'];
|
||||
}
|
||||
|
||||
// Temporary disable the notification about registration.
|
||||
$conf['user_mail_' . $op . '_notify'] = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User registration form submit handler
|
||||
* that executes right after user_register_submit().
|
||||
*
|
||||
* This callback sends delayed email notification to a user
|
||||
* about his registration. See https://drupal.org/node/1097684.
|
||||
*
|
||||
* @see profile2_form_prepare_user_register_submit_handler()
|
||||
* @see user_register_submit()
|
||||
* @see profile2_attach_form()
|
||||
*/
|
||||
function profile2_form_after_user_register_submit_handler(&$form, &$form_state) {
|
||||
global $conf;
|
||||
|
||||
// List of registration operations that where
|
||||
// notification values were changed.
|
||||
$changed_ops = &drupal_static('profile2_register_changed_operations', array());
|
||||
|
||||
// List of available operations during the registration.
|
||||
$register_ops = array('register_admin_created', 'register_no_approval_required', 'register_pending_approval');
|
||||
foreach ($register_ops as $op) {
|
||||
|
||||
// If we changed the notification value in
|
||||
// profile2_form_before_user_register_submit_handler() then change it back.
|
||||
if (isset($changed_ops['user_mail_' . $op . '_notify'])) {
|
||||
$conf['user_mail_' . $op . '_notify'] = $changed_ops['user_mail_' . $op . '_notify'];
|
||||
}
|
||||
// Otherwise just remove this value from a global variables array.
|
||||
else {
|
||||
unset($conf['user_mail_' . $op . '_notify']);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the values that we need to define which notification
|
||||
// should be sent to the user. Generally this is a trimmed version
|
||||
// of user_register_submit() callback.
|
||||
$admin = !empty($form_state['values']['administer_users']);
|
||||
$account = $form_state['user'];
|
||||
$notify = !empty($form_state['values']['notify']);
|
||||
|
||||
if ($admin && !$notify) {
|
||||
// If admin has created a new account and decided to don't notify a user -
|
||||
// then just do nothing.
|
||||
}
|
||||
elseif (!$admin && !variable_get('user_email_verification', TRUE) && $account->status) {
|
||||
_user_mail_notify('register_no_approval_required', $account);
|
||||
}
|
||||
// No administrator approval required.
|
||||
elseif ($account->status || $notify) {
|
||||
$op = $notify ? 'register_admin_created' : 'register_no_approval_required';
|
||||
_user_mail_notify($op, $account);
|
||||
}
|
||||
// Administrator approval required.
|
||||
elseif (!$admin) {
|
||||
_user_mail_notify('register_pending_approval', $account);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler that builds and saves all profiles in the form.
|
||||
*
|
||||
@@ -531,9 +746,26 @@ function profile2_category_access($account, $type_name) {
|
||||
* @see profile2_profile2_access()
|
||||
*/
|
||||
function profile2_access($op, $profile = NULL, $account = NULL) {
|
||||
|
||||
// Check if profile user has current profile available by role.
|
||||
if (isset($profile->type)) {
|
||||
$profile_type = profile2_type_load($profile->type);
|
||||
if (!empty($profile_type) && !empty($profile_type->data['roles']) && isset($profile->uid)) {
|
||||
$profile_user = user_load($profile->uid);
|
||||
$profile_roles = array_keys($profile_type->data['roles']);
|
||||
$user_roles = array_keys($profile_user->roles);
|
||||
$matches = array_intersect($profile_roles, $user_roles);
|
||||
if (empty($matches)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// With access to all profiles there is no need to check further.
|
||||
if (user_access('administer profiles', $account)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ($op == 'create' || $op == 'update') {
|
||||
$op = 'edit';
|
||||
}
|
||||
@@ -555,8 +787,7 @@ function profile2_access($op, $profile = NULL, $account = NULL) {
|
||||
* Implements hook_profile2_access().
|
||||
*/
|
||||
function profile2_profile2_access($op, $profile = NULL, $account = NULL) {
|
||||
// Don't grant access for users to delete their profile.
|
||||
if (isset($profile) && ($type_name = $profile->type) && $op != 'delete') {
|
||||
if (isset($profile) && ($type_name = $profile->type)) {
|
||||
if (user_access("$op any $type_name profile", $account)) {
|
||||
return TRUE;
|
||||
}
|
||||
@@ -701,12 +932,11 @@ class Profile extends Entity {
|
||||
}
|
||||
|
||||
public function defaultLabel() {
|
||||
if (module_exists('profile2_i18n')) {
|
||||
// Run the label through i18n_string() using the profile2_type label
|
||||
// context, so the default label (= the type's label) gets translated.
|
||||
return entity_i18n_string('profile2:profile2_type:' . $this->type . ':label', $this->label);
|
||||
}
|
||||
return $this->label;
|
||||
// Return a label that combines the type name and user name, translatable.
|
||||
return t('@type profile for @user', array(
|
||||
'@type' => profile2_get_types($this->type)->getTranslation('label'),
|
||||
'@user' => format_username($this->user()),
|
||||
));
|
||||
}
|
||||
|
||||
public function buildContent($view_mode = 'full', $langcode = NULL) {
|
||||
@@ -719,6 +949,19 @@ class Profile extends Entity {
|
||||
}
|
||||
|
||||
public function save() {
|
||||
// Don't create a new profile if the user already have one of the same type.
|
||||
$existing_profile = profile2_load_by_user($this->uid, $this->type);
|
||||
if (empty($this->pid) && !empty($existing_profile)) {
|
||||
watchdog('profile2_create', serialize(array(
|
||||
'message' => 'Profile already exists',
|
||||
'uid' => $this->uid,
|
||||
'type' => $this->type,
|
||||
'path' => current_path(),
|
||||
'logged_in_user' => $GLOBALS['user']->uid,
|
||||
)), array(), WATCHDOG_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
// Care about setting created and changed values. But do not automatically
|
||||
// set a created values for already existing profiles.
|
||||
if (empty($this->created) && (!empty($this->is_new) || !$this->pid)) {
|
||||
@@ -726,12 +969,12 @@ class Profile extends Entity {
|
||||
}
|
||||
$this->changed = REQUEST_TIME;
|
||||
|
||||
parent::save();
|
||||
// Update the static cache from profile2_load_by_user().
|
||||
// Clear the static cache from profile2_load_by_user() before saving, so
|
||||
// that profiles are correctly loaded in insert/update hooks.
|
||||
$cache = &drupal_static('profile2_load_by_user', array());
|
||||
if (isset($cache[$this->uid])) {
|
||||
$cache[$this->uid][$this->type] = $this->pid;
|
||||
}
|
||||
unset($cache[$this->uid]);
|
||||
|
||||
return parent::save();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,7 +1051,7 @@ function profile2_view($profile, $view_mode = 'full', $langcode = NULL, $page =
|
||||
* profiles.
|
||||
*/
|
||||
function profile2_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
|
||||
if ($form['instance']['entity_type']['#value'] == 'profile2') {
|
||||
if (!empty($form['instance']['entity_type']['#value']) && $form['instance']['entity_type']['#value'] == 'profile2') {
|
||||
$form['field']['settings']['profile2_private'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Make the content of this field private.'),
|
||||
@@ -829,15 +1072,17 @@ function profile2_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
|
||||
* Implements hook_field_access().
|
||||
*/
|
||||
function profile2_field_access($op, $field, $entity_type, $profile = NULL, $account = NULL) {
|
||||
if ($entity_type == 'profile2' && $op == 'view' && !empty($field['settings']['profile2_private']) && !user_access('administer profiles', $account)) {
|
||||
// For profiles, deny general view access for private fields.
|
||||
if (!isset($profile)) {
|
||||
if ($entity_type == 'profile2' && $op == 'view' && isset($profile)) {
|
||||
// Check if the profile type is accessible (e.g. applicable to the role).
|
||||
if (!profile2_access($op, $profile, $account)) {
|
||||
return FALSE;
|
||||
}
|
||||
// Also deny view access, if someone else views a private field.
|
||||
$account = isset($account) ? $account : $GLOBALS['user'];
|
||||
if ($account->uid != $profile->uid) {
|
||||
return FALSE;
|
||||
// Deny view access, if someone else views a private field.
|
||||
if (!empty($field['settings']['profile2_private']) && !user_access('administer profiles', $account)) {
|
||||
$account = isset($account) ? $account : $GLOBALS['user'];
|
||||
if ($account->uid != $profile->uid) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -879,3 +1124,72 @@ function profile2_user_get_properties($account, array $options, $name) {
|
||||
return $profile ? $profile : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_ctools_plugin_directory().
|
||||
*/
|
||||
function profile2_ctools_plugin_directory($owner, $plugin_type) {
|
||||
if ($owner == 'ctools' && !empty($plugin_type)) {
|
||||
return 'plugins/' . $plugin_type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_ctools_context_item_form().
|
||||
*
|
||||
* When the User context is added, CTools will update the relationship dropdown
|
||||
* with ajax. The dropdown is passed through theme_ctools_context_item_form
|
||||
* before being passed to ajax_render, so that is our best opportunity to
|
||||
* alter it.
|
||||
*
|
||||
* @see ctools_context_ajax_item_add
|
||||
*/
|
||||
function profile2_preprocess_ctools_context_item_form(&$vars) {
|
||||
unset($vars['form']['buttons']['relationship']['item']['#options']['entity_from_schema:uid-user-profile2']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the given user has access to delete a profile.
|
||||
*/
|
||||
function profile2_delete_access($uid, $type_name) {
|
||||
$profile = profile2_by_uid_load($uid, $type_name);
|
||||
return is_object($profile) ? profile2_access('edit', $profile) : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu load callback.
|
||||
*
|
||||
* Returns the profile object for the given user. If there is none yet, a new
|
||||
* object is created.
|
||||
*/
|
||||
function profile2_by_uid_load($uid, $type_name) {
|
||||
if ($uid && is_numeric($uid) && ($account = user_load($uid))) {
|
||||
$profile = profile2_load_by_user($account, $type_name);
|
||||
if (!$profile) {
|
||||
$profile = profile2_create(array('type' => $type_name));
|
||||
$profile->setUser($account);
|
||||
$profile->is_new = TRUE;
|
||||
}
|
||||
return $profile;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_preprocess_page().
|
||||
*
|
||||
* Fix the page titles on the profile2 edit tabs.
|
||||
* We want the titles to be the full profile label, giving the user name & profile name.
|
||||
*/
|
||||
function profile2_preprocess_page(&$vars) {
|
||||
// This is true when editing a profile in a tab.
|
||||
if (!empty($vars['page']['content']['system_main']['#user_category'])) {
|
||||
$ptype = $vars['page']['content']['system_main']['#user_category'];
|
||||
if (!empty($vars['page']['content']['system_main']["profile_$ptype"])) {
|
||||
$item = $vars['page']['content']['system_main']["profile_$ptype"];
|
||||
// If we've found an item, and it has a profile2 entity, display the title.
|
||||
if (!empty($item['#entity'])) {
|
||||
$vars['title'] = $item['#entity']->label();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -62,8 +62,10 @@ class Profile2CRUDTestCase extends DrupalWebTestCase {
|
||||
profile2_save($profile);
|
||||
|
||||
$profiles = profile2_load_by_user($user1);
|
||||
$this->assertEqual($profiles['test']->label(), 'label', 'Created and loaded profile 1.');
|
||||
$this->assertEqual($profiles['test2']->label(), 'label2', 'Created and loaded profile 2.');
|
||||
$label = t('@type profile for @user', array('@type' => 'label', '@user' => format_username($user1)));
|
||||
$label2 = t('@type profile for @user', array('@type' => 'label2', '@user' => format_username($user1)));
|
||||
$this->assertEqual($profiles['test']->label(), $label, 'Created and loaded profile 1.');
|
||||
$this->assertEqual($profiles['test2']->label(), $label2, 'Created and loaded profile 2.');
|
||||
|
||||
// Test looking up from static cache works also.
|
||||
$profiles = profile2_load_by_user($user1);
|
||||
@@ -134,4 +136,30 @@ class Profile2CRUDTestCase extends DrupalWebTestCase {
|
||||
$this->assertText(check_plain($edit['profile_main[profile_fullname][und][0][value]']), 'Profile displayed.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests optional access parameters.
|
||||
*/
|
||||
function testAccess() {
|
||||
global $user;
|
||||
$admin_user = $this->drupalCreateUser(array('administer profiles'));
|
||||
$user2 = $this->drupalCreateUser();
|
||||
// Create profiles for the admin user.
|
||||
$profile = profile2_create(array('type' => 'test', 'uid' => $admin_user->uid));
|
||||
profile2_save($profile);
|
||||
|
||||
// Make sure access is denied to the profile.
|
||||
$this->drupalLogin($user2);
|
||||
$this->drupalGet('user/' . $admin_user->uid . '/edit/main');
|
||||
$this->assertText(t('Access denied'), 'Access has been denied.');
|
||||
|
||||
// Set the global user to ensure the defaults are respected.
|
||||
$user = $user2;
|
||||
|
||||
// Ensure optional parameters check access for the current logged in user.
|
||||
$this->assertFalse(profile2_access('edit'), 'No edit access for user 2');
|
||||
|
||||
// Ensure optional parameters check access for the admin user.
|
||||
$this->assertTrue(profile2_access('edit', NULL, $admin_user), 'No edit access for user 1');
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user