pcp.module in Profile Complete Percent 6.2
Same filename and directory in other branches
Allows users with valid permissions to tag profile fields created from the profile module as required fields for a users profile to be considered complete.
File
pcp.moduleView source
<?php
/**
* @file
* Allows users with valid permissions to tag profile fields created
* from the profile module as required fields for a
* users profile to be considered complete.
*/
/**
* Implementation of hook_perm()
*/
function pcp_perm() {
return array(
'administer pcp',
);
}
/**
* Implementation of hook_menu()
*/
function pcp_menu() {
$items = array();
$items['admin/user/pcp'] = array(
'title' => 'Profile Complete Percentages',
'description' => 'Tag profile fields as required for percent complete handling.',
'page callback' => 'pcp_admin_settings',
'access arguments' => array(
'administer pcp',
),
);
return $items;
}
/**
* Implementation of hook_block()
*/
function pcp_block($op = 'list', $delta = 0, $edit = array()) {
switch ($op) {
case 'list':
$blocks = array();
$blocks[0]['info'] = t('Profile Complete Percentage');
return $blocks;
break;
case 'view':
$block = array();
switch ($delta) {
case 0:
if (user_is_logged_in()) {
global $user;
$complete_data = pcp_get_complete_percentage_data($user);
$doHide = variable_get('pcp_hide_block_on_complete', 0);
if ($doHide && $complete_data['nextfield'] == '') {
$subject = '';
$content = '';
}
else {
$subject = t('Profile Complete');
$content = theme('pcp_profile_percent_complete', $complete_data);
}
$block['subject'] = $subject;
$block['content'] = $content;
}
break;
}
return $block;
break;
}
}
/**
* Implementation of hook_form_FORM_ID_alter().
*/
function pcp_form_user_admin_settings_alter(&$form, $form_state) {
if (user_access('administer pcp')) {
$form['pictures']['settings']['pcp_enable_user_picture'] = array(
'#title' => 'Make required for PCP module',
'#type' => 'checkbox',
'#default_value' => variable_get('pcp_enable_user_picture', 0),
'#description' => t('Checking this box will tag this field as a required field for completion of the users profile.'),
);
$form['#submit'][] = 'pcp_user_admin_settings_submit';
}
}
/**
* Implementation of hook_form_FORM_ID_alter().
*/
function pcp_form_profile_field_form_alter(&$form, $form_state) {
if (user_access('administer pcp')) {
$form['fields']['pcp_tag'] = array(
'#type' => 'checkbox',
'#title' => t('Make required for PCP module'),
'#description' => t('Checking this box will tag this field as a required field for completion of the users profile.'),
'#default_value' => _pcp_field_is_tagged($form['fid']['#value']),
);
$form['#submit'][] = 'pcp_profile_field_form_submit';
}
}
/**
* Implementation of hook_form_FORM_ID_alter().
*/
function pcp_form_user_profile_form_alter(&$form, $form_state) {
if (isset($_GET['fieldname']) && $_GET['fieldname'] != '') {
$fieldname = 'edit-' . preg_replace("/_/", "-", $_GET['fieldname']);
drupal_add_js("\n \$('#" . $fieldname . "').css({\n 'border' : '2px solid red'\n });\n ", 'inline', 'footer');
}
}
/**
* Implementation of hook_form_FORM_ID_alter().
*/
function pcp_form_profile_field_delete_alter(&$form, $form_state) {
$form['#submit'][] = 'pcp_delete_field_requireness';
}
/**
* Called when a user submits a profile field form from the
* profile module (when adding or editing a profile field).
*/
function pcp_profile_field_form_submit($form, &$form_state) {
$fid = $form_state['values']['fid'] ? $form_state['values']['fid'] : db_result(db_query("SELECT MAX(fid) FROM {profile_fields}"));
db_query("DELETE FROM {profile_pcp} WHERE fid = %d", $form_state['values']['fid']);
if ($form_state['values']['pcp_tag']) {
db_query("INSERT INTO {profile_pcp} (`fid`) VALUES (%d)", $fid);
}
}
/**
* Called when a user deletes a profile field
* We then need to delete the pcp value too
*/
function pcp_delete_field_requireness($form, &$form_state) {
db_query("DELETE FROM {profile_pcp} WHERE fid = %d", $form_state['values']['fid']);
}
/**
* Called when a user submits the admin user settings form.
*/
function pcp_user_admin_settings_submit($form, &$form_state) {
variable_set('pcp_enable_user_picture', $form_state['values']['pcp_enable_user_picture']);
}
/**
* Menu Callback Function
* Build output of the pcp module settings which allows the
* administrator to tag specific profile fields which will be
* used to determine the completion of a users profile.
*/
function pcp_admin_settings() {
return drupal_get_form('pcp_admin_settings_form');
}
/**
* Admin settings form
*/
function pcp_admin_settings_form() {
$form = array();
$form['general_settings'] = array(
'#type' => 'fieldset',
'#title' => 'General Settings',
);
$form['general_settings']['hide_block_on_complete'] = array(
'#type' => 'checkbox',
'#title' => 'Hide Block When Complete',
'#default_value' => variable_get('pcp_hide_block_on_complete', 0),
'#description' => t('When a user reaches 100% complete of their profile, do you want the profile complete percent block to go away? If so, check this box on.'),
);
$form['profile_field_settings'] = array(
'#type' => 'fieldset',
'#title' => 'Profile Fields',
'#description' => t('Checking a profile field below will add that field to the logic of the complete percentage.'),
);
// Add user picture support
if (variable_get('user_pictures', 0)) {
$form['profile_field_settings']['pcp_enable_user_picture'] = array(
'#title' => 'Enable User Picture Support',
'#type' => 'checkbox',
'#default_value' => variable_get('pcp_enable_user_picture', 0),
'#description' => t('Picture support has been turned on, do you want to make it required as part of Profile Complete Percent? Checking this box will make it required.'),
);
}
$options = pcp_admin_settings_form_data();
if ($options['profile_fields_options']) {
$form['profile_field_settings']['profile_fields'] = array(
'#title' => t('Profile Fields'),
'#type' => 'checkboxes',
'#options' => $options['profile_fields_options'],
'#default_value' => $options['default_values'],
);
}
// Add user terms support
if (module_exists('user_terms')) {
$vocabs = taxonomy_get_vocabularies();
$vocabs_enabled = variable_get('user_terms_vocabs', array());
$all_vocabs = array();
foreach ($vocabs_enabled as $vid) {
$all_vocabs[$vid] = $vocabs[$vid]->name;
}
if (!empty($vocabs_enabled)) {
$form['profile_field_settings']['pcp_enabled_user_terms_vocabs'] = array(
'#title' => t('User Terms Vocabularies'),
'#type' => 'checkboxes',
'#options' => $all_vocabs,
'#default_value' => variable_get('pcp_enabled_user_terms_vocabs', array()),
);
}
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
/**
* Admin settings form submit
*/
function pcp_admin_settings_form_submit($form, &$form_state) {
// Process the General Settings data
variable_set('pcp_hide_block_on_complete', $form_state['values']['hide_block_on_complete']);
variable_set('pcp_enable_user_picture', $form_state['values']['pcp_enable_user_picture']);
variable_set('pcp_enabled_user_terms_vocabs', $form_state['values']['pcp_enabled_user_terms_vocabs']);
// Process the profile fields that have been modified if available.
if (is_array($form_state['values']['profile_fields']) && !empty($form_state['values']['profile_fields'])) {
db_query("DELETE FROM {profile_pcp}");
foreach ($form_state['values']['profile_fields'] as $fid) {
if ($fid) {
db_query("INSERT INTO {profile_pcp} VALUES (%d)", $fid);
}
}
drupal_set_message("Your settings have been saved.");
}
}
/**
* Function that sets up parameters to be used
* when the pcp_admin_settings_form() function
* is executed.
*
* @return - assoc array
* ['profile_fields_options']
* - An associative array of all fields created from the profile module.
* ['default_values']
* - An indexed array of all (if any) default values for the form.
*/
function pcp_admin_settings_form_data() {
$profile_fields_options = array();
$default_values = array();
$profile_fields = pcp_get_profile_fields();
foreach ($profile_fields as $key => $value) {
$field_options[$value['fid']] = $value['title'];
}
$tagged_profile_fields = pcp_get_tagged_profile_fields();
foreach ($tagged_profile_fields as $key => $value) {
$default_values[] = $value['fid'];
}
$options = array();
$options['profile_fields_options'] = $field_options;
$options['default_values'] = $default_values;
return $options;
}
/**
* Return a users profile field values that have been saved
* for a given user.
*
* @param int $uid - The uid of the user we are returning data for.
*
* @return assoc array of all profile fields for the user.
*/
function pcp_get_user_profile_values($uid) {
$values = array();
if ($uid) {
$query = db_query("SELECT * FROM {profile_values} WHERE uid = %d", $uid);
while ($result = db_fetch_array($query)) {
$values[$result['fid']] = $result['value'];
}
}
return $values;
}
/**
* Return a users additional field values that have been saved
* for a given user.
*
* @param int $uid - The uid of the user we are returning data for.
*
* @return assoc array of all profile fields for the user.
*/
function pcp_get_user_additional_values($uid) {
$values = array();
if ($uid) {
$account = user_load($uid);
$values['user_picture'] = $account->picture;
if (module_exists('user_terms')) {
$user_terms_vocabs = variable_get('pcp_enabled_user_terms_vocabs', array());
foreach ($account->user_terms as $term) {
$vid = $term['vid'];
$values['user_terms_' . $vid][] = $term;
}
}
}
return $values;
}
/**
* Get the profile complete percentage data for a given user.
*
* @param obj $user
* - The user object to get data for.
*
* @return assoc array of all values needed at the theme layer.
* - Refer to comments in theme_pcp_profile_percent_complete() for specific values.
*/
function pcp_get_complete_percentage_data($user) {
$profile_fields = pcp_get_tagged_profile_fields();
$additional_fields = pcp_get_additional_tagged_fields();
$fields = $profile_fields + $additional_fields;
$user_profile_values = pcp_get_user_profile_values($user->uid);
$user_additional_values = pcp_get_user_additional_values($user->uid);
$user_values = $user_profile_values + $user_additional_values;
$percent = 0;
$complete = 0;
$nextfield_set = FALSE;
if (is_array($fields) && !empty($fields)) {
//Shuffle the fields to display a random field to fill in (issue #708382)
shuffle($fields);
foreach ($fields as $key => $value) {
if (isset($user_values[$value['fid']]) && ($user_values[$value['fid']] == '' || $user_values[$value['fid']] == '0' && $value['type'] == 'selection')) {
if ($nextfield_set === FALSE) {
$nextfield_set = TRUE;
$fid = $value['fid'];
$nextfield_fid = $fid;
if (is_numeric($fid)) {
$nextdata = db_fetch_array(db_query("SELECT title, name, category FROM {profile_fields} WHERE fid = %d", $fid));
$nextfield = $nextdata['title'];
$nextcategory = $nextdata['category'];
$nextname = $nextdata['name'];
}
elseif ($fid == 'user_picture') {
$nextfield = $value['title'];
$nextcategory = 'Default';
$nextname = $value['name'];
}
elseif (substr($fid, 0, 10) == 'user_terms' && variable_get('pcp_enabled_user_terms_vocabs', array())) {
$nextfield = $value['title'];
$nextcategory = $value['category'] == 'account' ? 'Default' : $value['category'];
$nextname = $value['name'];
}
}
continue;
}
$complete++;
}
$dec = number_format($complete / count($fields), 2);
$percent = $dec * 100;
if ($nextfield_set) {
$next = number_format(($complete + 1) / count($fields), 2);
$nextpercent = $next * 100;
}
}
$complete_data = array();
$complete_data['uid'] = $user->uid;
$complete_data['percent'] = $percent;
$complete_data['completed'] = $complete;
$complete_data['incomplete'] = count($fields) - $complete;
$complete_data['total'] = count($fields);
$complete_data['nextfield'] = $nextfield;
$complete_data['nextfield_fid'] = $nextfield_fid;
$complete_data['nextpercent'] = $nextpercent;
$complete_data['nextcategory'] = $nextcategory;
$complete_data['nextname'] = $nextname;
return $complete_data;
}
/**
* Get all the profile fields that have been tagged.
* If an $fid is passed in, only the data for that field will be returned.
*
* @param int $fid - The fid of the field data should be returned for. If 0, all fields are returned.
*
* @return indexed array - All fields and their information returned from the query.
*/
function pcp_get_tagged_profile_fields($fid = 0) {
$profile_role_used = module_exists('profile_role');
if ($fid > 0) {
$query = db_query("SELECT * FROM {profile_pcp} LEFT JOIN {profile_fields} USING(fid) WHERE fid = %d", $fid);
}
else {
$query = db_query("SELECT * FROM {profile_pcp} LEFT JOIN {profile_fields} USING(fid)");
}
$fields = array();
while ($result = db_fetch_array($query)) {
if ($profile_role_used) {
global $user;
if (profile_role_access_category($user, $result['category'])) {
$fields[] = $result;
}
}
else {
$fields[] = $result;
}
}
return $fields;
}
/**
* Get all the profile fields stored in the system, tagged or not tagged.
*/
function pcp_get_profile_fields() {
$query = db_query("SELECT * FROM {profile_fields}");
$fields = array();
while ($result = db_fetch_array($query)) {
$fields[] = $result;
}
return $fields;
}
/**
* Get all additional tagged fields that where not created
* using the profile module. This allows additional PCP
* support for other drupal features.
*/
function pcp_get_additional_tagged_fields() {
$fields = array();
// Enable user picture support.
if (variable_get('pcp_enable_user_picture', 0) && variable_get('user_pictures', 0)) {
$fields['user_picture'] = array(
'fid' => 'user_picture',
'title' => 'User Picture',
'name' => 'picture_upload',
);
}
if (module_exists('user_terms')) {
$vocabs = taxonomy_get_vocabularies();
$user_terms_vocabs = variable_get('pcp_enabled_user_terms_vocabs', array());
$vocabs_path = variable_get('user_terms_vocabs_path', array());
$all_vocabs = array();
foreach ($user_terms_vocabs as $vid) {
$all_vocabs[$vid] = $vocabs[$vid]->name;
}
foreach ($all_vocabs as $vid => $name) {
$fields['user_terms_' . $vid] = array(
'fid' => 'user_terms_' . $vid,
'title' => $name,
'name' => 'user_terms_' . $vid,
'category' => $vocabs_path[$vid],
);
}
}
return $fields;
}
function pcp_theme() {
return array(
'pcp_profile_percent_complete' => array(
'arguments' => array(
'complete_data' => NULL,
),
),
);
}
/**
* Block Theme function that displays the default output of a users
* profile complete percent. Use this theme function to override
* the output / display of this block.
*
* @param - assoc array $complete_data
* ['uid'] - int - The user ID of the user viewing the page.
* ['percent'] - int - A number that represents the total percent complete (ie 50).
* ['completed'] - int - How many fields total that have been completed (filled out) by $user.
* ['incomplete'] - int - How many fields still need to be filled out.
* ['total'] - int - The count of all tagged profile fields.
* ['nextfield'] - str - The next field to fill out that is currently empty.
* ['nextfield_fid'] - int or str - The fid identifier of the field being passed in.
* ['nextpercent'] - int - What the users total percent complete value will be when ['nextfield'] is complete.
* ['nextcategory] - str - The category the next field falls under for targeting with a link.
* ['nextname'] - str - The field name of the next field for field focus after linked to the profile field.
*/
function theme_pcp_profile_percent_complete($complete_data) {
$output = '<style type="text/css">';
$output .= '#pcp-percent-bar-wrapper {width: 100%; border: 1px solid #000; padding: 1px;}';
$output .= '#pcp-percent-bar { width: ' . $complete_data['percent'] . '%; height: 10px; background-color: #777777;}';
$output .= '</style>';
$output .= '<div id="pcp-wrapper">';
$output .= t('!complete% Complete', array(
'!complete' => $complete_data['percent'],
));
$output .= '<div id="pcp-percent-bar-wrapper">';
$output .= '<div id="pcp-percent-bar"></div>';
$output .= '</div>';
$output .= '</div>';
if ($complete_data['nextfield'] && $complete_data['nextpercent']) {
if ($complete_data['nextcategory'] == 'Default') {
$nextpath = 'user/' . $complete_data['uid'] . '/edit';
}
else {
$nextpath = 'user/' . $complete_data['uid'] . '/edit/' . $complete_data['nextcategory'];
}
$element_id = 'edit-' . str_replace('_', '-', $complete_data['nextname']);
$output .= t('Filling out <em>!empty-field</em> will bring your profile to !complete% Complete', array(
'!empty-field' => l($complete_data['nextfield'], $nextpath, array(
'query' => 'fieldname=' . $complete_data['nextname'],
'fragment' => $element_id,
)),
'!complete' => $complete_data['nextpercent'],
));
}
return $output;
}
/**
* Implementation of hook_rules_condition_info().
*
* @ingroup rules
* @see content_complete_completeness_percentage_form
*/
function pcp_rules_condition_info() {
return array(
'pcp_condition_check_profile_fields_completeness' => array(
'label' => t('Check profile fields completeness'),
'arguments' => array(
'user' => array(
'type' => 'user',
'label' => t('User'),
),
),
'help' => 'Evaluates to TRUE, if all the the selected user profile fields are filled in.',
'module' => 'Profile Complete Percent',
),
);
}
/**
* Rules Condition form configuration - select the profile fields to check
*
* @see pcp_rules_condition_info
*/
function pcp_condition_check_profile_fields_completeness_form($settings = array(), &$form) {
$options = pcp_admin_settings_form_data();
$form['settings']['profile_fields'] = array(
'#title' => t('Profile Fields'),
'#type' => 'checkboxes',
'#options' => $options['profile_fields_options'],
'#default_value' => isset($settings['profile_fields']) ? $settings['profile_fields'] : array(),
'#description' => t('Check which fields the user has to fill in'),
);
}
/**
* Rules Condition - Are the selected user profile fields filed in?
*
* @param $user
* The user for which the condition is checked.
* @param $settings
* The configured settings of the rule condition
*
* @see pcp_condition_check_profile_fields_completeness_form
* @see pcp_rules_condition_info
*
* @return TRUE or FALSE
*/
function pcp_condition_check_profile_fields_completeness($user, $settings) {
$edit_categories = array();
profile_load_profile($user);
if ($settings['profile_fields']) {
$result = db_query("SELECT fid, title, name, category FROM {profile_fields} WHERE fid IN (%d)", implode(', ', $settings['profile_fields']));
while ($field = db_fetch_object($result)) {
if (!$user->{$field->name}) {
return FALSE;
}
}
}
return TRUE;
}
/**
* Implementation of hook_rules_action_info
*/
function pcp_rules_action_info() {
return array(
'pcp_action_redirect_user_to_editform' => array(
'label' => t('Redirect the user to his own profile edit page'),
'arguments' => array(
'user' => array(
'type' => 'user',
'label' => t('User whos profile fields should be filled in'),
),
),
'module' => 'Profile Complete Percent',
),
);
}
/**
* Rules Action - Redirect the user to his profile edit page
*
* @param $user
* The user for which the action is performed.
* @param $settings
* The configured settings of the rule action
*
* @see pcp_rules_action_info
*
* @return Perform the redirection
*/
function pcp_action_redirect_user_to_editform($user, $settings) {
$settings = pcp_get_condition_settings('pcp_condition_check_profile_fields_completeness');
$edit_categories = array();
profile_load_profile($user);
if ($settings['profile_fields']) {
$result = db_query("SELECT fid, title, name, category FROM {profile_fields} WHERE fid IN (%d)", implode(', ', $settings['profile_fields']));
while ($field = db_fetch_object($result)) {
if (!$user->{$field->name}) {
drupal_set_message(t('Please fill in "<i>' . $field->category . '</i>".'), 'warning');
// Necessary to avoid redirect loop or malfunctioning
unset($_REQUEST['destination']);
unset($_REQUEST['edit']['destination']);
drupal_goto('user/' . $user->uid . '/edit/' . $field->category);
}
}
}
}
/**
* Check if a profile field is tagged as to be filled in.
* Returns TRUE or FALSE
*/
function _pcp_field_is_tagged($fid) {
$tag = TRUE;
$field_data = pcp_get_tagged_profile_fields($fid);
if (!$field_data[0]['fid']) {
$tag = FALSE;
}
return $tag;
}
/**
* Check if a profile category is tagged as to be filled in.
* Returns TRUE or FALSE
*/
function _pcp_category_status($category = '') {
return 'all';
}
/**
* Helper function to get the setting of a particular condition
*
* @param Condition name $name
* @return Array settings
*/
function pcp_get_condition_settings($name) {
$rules = rules_get_configured_items('rules');
foreach ($rules as $rule) {
if ($rule['#conditions']) {
foreach ($rule['#conditions'] as $condition) {
if ($condition['#name'] == $name) {
return $condition['#settings'];
}
}
}
}
}
Functions
Name | Description |
---|---|
pcp_action_redirect_user_to_editform | Rules Action - Redirect the user to his profile edit page |
pcp_admin_settings | Menu Callback Function Build output of the pcp module settings which allows the administrator to tag specific profile fields which will be used to determine the completion of a users profile. |
pcp_admin_settings_form | Admin settings form |
pcp_admin_settings_form_data | Function that sets up parameters to be used when the pcp_admin_settings_form() function is executed. |
pcp_admin_settings_form_submit | Admin settings form submit |
pcp_block | Implementation of hook_block() |
pcp_condition_check_profile_fields_completeness | Rules Condition - Are the selected user profile fields filed in? |
pcp_condition_check_profile_fields_completeness_form | Rules Condition form configuration - select the profile fields to check |
pcp_delete_field_requireness | Called when a user deletes a profile field We then need to delete the pcp value too |
pcp_form_profile_field_delete_alter | Implementation of hook_form_FORM_ID_alter(). |
pcp_form_profile_field_form_alter | Implementation of hook_form_FORM_ID_alter(). |
pcp_form_user_admin_settings_alter | Implementation of hook_form_FORM_ID_alter(). |
pcp_form_user_profile_form_alter | Implementation of hook_form_FORM_ID_alter(). |
pcp_get_additional_tagged_fields | Get all additional tagged fields that where not created using the profile module. This allows additional PCP support for other drupal features. |
pcp_get_complete_percentage_data | Get the profile complete percentage data for a given user. |
pcp_get_condition_settings | Helper function to get the setting of a particular condition |
pcp_get_profile_fields | Get all the profile fields stored in the system, tagged or not tagged. |
pcp_get_tagged_profile_fields | Get all the profile fields that have been tagged. If an $fid is passed in, only the data for that field will be returned. |
pcp_get_user_additional_values | Return a users additional field values that have been saved for a given user. |
pcp_get_user_profile_values | Return a users profile field values that have been saved for a given user. |
pcp_menu | Implementation of hook_menu() |
pcp_perm | Implementation of hook_perm() |
pcp_profile_field_form_submit | Called when a user submits a profile field form from the profile module (when adding or editing a profile field). |
pcp_rules_action_info | Implementation of hook_rules_action_info |
pcp_rules_condition_info | Implementation of hook_rules_condition_info(). |
pcp_theme | |
pcp_user_admin_settings_submit | Called when a user submits the admin user settings form. |
theme_pcp_profile_percent_complete | Block Theme function that displays the default output of a users profile complete percent. Use this theme function to override the output / display of this block. |
_pcp_category_status | Check if a profile category is tagged as to be filled in. Returns TRUE or FALSE |
_pcp_field_is_tagged | Check if a profile field is tagged as to be filled in. Returns TRUE or FALSE |