pmpermission.module in Drupal PM (Project Management) 7.2
Same filename and directory in other branches
Main module file for the pmpermission module.
File
pmpermission/pmpermission.moduleView source
<?php
/**
* @file
* Main module file for the pmpermission module.
*/
/**
* Implements hook_help().
*/
function pmpermission_help($path, $arg) {
switch ($path) {
case 'admin/help#pm-permission':
return '<p>' . t('PM Permission allows you to grant access to content based on interactions with Drupal PM.') . '</p>';
}
}
/**
* Implements hook_menu().
*/
function pmpermission_menu() {
$items['admin/config/pm/pmpermission'] = array(
'title' => 'Permissions',
'description' => 'Configure access controls based on PM fields.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'pmpermission_admin',
),
'access arguments' => array(
'administer pm permission',
),
);
return $items;
}
/**
* Admin settings form.
*/
function pmpermission_admin() {
$form = array();
$form['pmpermission_node'] = array(
'#type' => 'fieldset',
'#title' => t('Select node bundles where you want to enable PM permissions'),
);
$form['pmpermission_field'] = array(
'#type' => 'fieldset',
'#title' => t('Configure reference fields'),
);
$node_types = array();
foreach (node_type_get_types() as $type => $info) {
$name = node_type_get_name($type);
$node_types[$type] = $name;
$form['pmpermission_node']["pmpermission_node_{$type}_enabled"] = array(
'#type' => 'checkbox',
'#title' => $name,
'#default_value' => variable_get("pmpermission_node_{$type}_enabled", FALSE),
);
$options = _pmpermission_get_field_names_per_field_type('entityreference', 'node', $type);
if (count($options['node']) < 2) {
$form['pmpermission_field']["pmpermission_field_parent_reference_for_{$type}_message"] = array(
'#type' => 'item',
'#markup' => t('No configuration available for "@name"', array(
'@name' => $name,
)),
'#states' => array(
'visible' => array(
":input[name='pmpermission_node_{$type}_enabled']" => array(
'checked' => TRUE,
),
),
),
);
}
else {
$form['pmpermission_field']["pmpermission_field_parent_reference_for_{$type}"] = array(
'#type' => 'select',
'#title' => t('Select parent reference field for "@name"', array(
'@name' => $name,
)),
'#options' => $options['node'],
'#default_value' => variable_get("pmpermission_field_parent_reference_for_{$type}", ''),
'#states' => array(
'visible' => array(
":input[name='pmpermission_node_{$type}_enabled']" => array(
'checked' => TRUE,
),
),
),
);
}
}
$options = _pmpermission_get_field_names_per_field_type('entityreference');
$form['pmpermission_field']['pmpermission_field_assigned_reference'] = array(
'#type' => 'select',
'#title' => t('Assigned reference field'),
'#options' => $options['user'],
'#disabled' => TRUE,
'#default_value' => variable_get("pmpermission_field_assigned_reference", ''),
);
$form['pmpermission_field']['pmpermission_field_pm_reference'] = array(
'#type' => 'select',
'#title' => t('Project Manager reference field'),
'#options' => $options['user'],
'#disabled' => TRUE,
'#default_value' => variable_get("pmpermission_field_pm_reference", ''),
);
$form['pmpermission_field']['pmpermission_field_org_member_reference'] = array(
'#type' => 'select',
'#title' => t('Organization member reference field'),
'#options' => $options['user'],
'#disabled' => TRUE,
'#default_value' => variable_get("pmpermission_field_org_member_reference", ''),
);
$form['pmpermission_advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced Configuration'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['pmpermission_advanced']['pmpermission_override_core_permissions_agree'] = array(
'#type' => 'checkbox',
'#title' => t('I agree to override default core node permissions'),
'#description' => t("Drupal core doesn't provide a UI to alter these settings. So make sure you revert the settings before you uninstall this module."),
'#default_value' => FALSE,
);
$form['pmpermission_advanced']['pmpermission_override_core_permissions'] = array(
'#type' => 'checkboxes',
'#title' => t('Node default core permission override'),
'#default_value' => variable_get("pmpermission_override_core_permissions", array()),
'#options' => $node_types,
'#states' => array(
'enabled' => array(
':input[name="pmpermission_override_core_permissions_agree"]' => array(
'checked' => TRUE,
),
),
),
);
$form = system_settings_form($form);
$form['#submit'][] = 'pmpermission_admin_submit';
return $form;
}
/**
* Admin settings form submit handler.
*/
function pmpermission_admin_submit($form, $form_state) {
$values = $form_state['values'];
$agree = $values['pmpermission_override_core_permissions_agree'];
$overrides = $values['pmpermission_override_core_permissions'];
if ($agree and is_array($overrides)) {
foreach ($overrides as $type => $value) {
if ($value) {
variable_set('node_permissions_' . $type, 0);
}
else {
variable_set('node_permissions_' . $type, 1);
}
}
}
}
/**
* Get a list of field names matching a specific type.
*
* This function works reliably for "entityreference" only.
*
* @param string $type
* Type of field e.g. entityreference.
*
* @return array $field_names
* Field names categorized by target entity type.
*/
function _pmpermission_get_field_names_per_field_type($type, $entity_type = NULL, $bundle_name = NULL) {
$field_names = array(
'user' => array(
'' => t('- None -'),
),
'node' => array(
'' => t('- None -'),
),
);
// Get all entityreference field names.
$query = db_select('field_config', 'f');
$query
->fields('f', array(
'field_name',
));
$query
->condition('f.type', $type);
$query
->distinct();
$rows = $query
->execute();
foreach ($rows as $row) {
$field_name = $row->field_name;
if ($bundle_name and !field_info_instance($entity_type, $field_name, $bundle_name)) {
continue;
}
$field_info = field_info_field($field_name);
if (isset($field_info['settings']['target_type'])) {
// Code...
$field_names[$field_info['settings']['target_type']][$field_name] = $field_name;
}
}
return $field_names;
}
/**
* Returns a list of node bundles for which PM permission have been enabled.
*/
function pmpermission_get_enabled_types() {
$enabled = array();
foreach (node_type_get_types() as $type => $info) {
if (variable_get("pmpermission_node_{$type}_enabled", FALSE)) {
$enabled[] = $type;
}
}
return $enabled;
}
/**
* Implements hook_permission().
*/
function pmpermission_permission() {
$permissions = array(
'administer pm permission' => array(
'title' => t('Administer Project Management Permission'),
'restrict access' => TRUE,
),
);
// Generate override node permissions for all applicable node types.
foreach (pmpermission_get_enabled_types() as $bundle_name) {
$permissions += pmpermission_permission_per_bundle($bundle_name);
}
return $permissions;
}
/**
* Creates an array of permission name for the given node bundle.
*
* @param string $bundle_name
* Node bundle name.
*
* @return array
* Array equivalent to the return of hook_permission().
*/
function pmpermission_permission_per_bundle($bundle_name) {
$name = node_type_get_name($bundle_name);
$bundle_name = check_plain($bundle_name);
$permissions = array();
if (!variable_get('node_permissions_' . $bundle_name, 1)) {
$permissions += _pmpermission_permission_default($bundle_name, $name);
}
if (module_exists('pmorganization')) {
if (_pmpermission_get_field_name($bundle_name, 'parent') or $bundle_name == 'pmorganization') {
$permissions += _pmpermission_permission_belonged($bundle_name, $name, 'Organization');
}
}
if (module_exists('pmproject')) {
if (_pmpermission_get_field_name($bundle_name, 'pm')) {
$permissions += _pmpermission_permission_assigned($bundle_name, $name, 'Project Manager');
}
}
if (_pmpermission_get_field_name($bundle_name, 'assigned')) {
$permissions += _pmpermission_permission_assigned($bundle_name, $name, 'Assigned');
}
return $permissions;
}
/**
* Helper function to generate default permissions.
*
* @param string $type
* Node bundle machine name.
* @param string $name
* Node bundle name that could be used for display.
*
* @return array
* Array equivalent to the return of hook_permission().
*/
function _pmpermission_permission_default($type, $name) {
$permissions = array(
"PM permission {$type}: create" => array(
'title' => t('%type_name: Create new content', array(
'%type_name' => $name,
)),
),
"PM permission {$type}: view own" => array(
'title' => t('%type_name: View own content', array(
'%type_name' => $name,
)),
),
"PM permission {$type}: view all" => array(
'title' => t('%type_name: View any content', array(
'%type_name' => $name,
)),
),
"PM permission {$type}: update own" => array(
'title' => t('%type_name: Edit own content', array(
'%type_name' => $name,
)),
),
"PM permission {$type}: update all" => array(
'title' => t('%type_name: Edit any content', array(
'%type_name' => $name,
)),
),
"PM permission {$type}: delete own" => array(
'title' => t('%type_name: Delete own content', array(
'%type_name' => $name,
)),
),
"PM permission {$type}: delete all" => array(
'title' => t('%type_name: Delete any content', array(
'%type_name' => $name,
)),
),
);
return $permissions;
}
/**
* Helper function to generate belonged to permission set.
*
* @param string $type
* Node bundle machine name.
* @param string $name
* Node bundle name that could be used for display.
*
* @return array $permissions
* Array equivalent to the return of hook_permission().
*/
function _pmpermission_permission_belonged($type, $name, $belonged) {
$permissions["PM permission {$type}: view own {$belonged}"] = array(
'title' => t('%type_name: View content in own %belonged', array(
'%type_name' => $name,
'%belonged' => $belonged,
)),
'description' => t('For %type_name assigned to the same %belonged as a user, allows the user to view the %type_name and see the %type_name in lists or dropdowns elsewhere on the site.', array(
'%type_name' => $name,
'%belonged' => $belonged,
)),
);
$permissions["PM permission {$type}: update own {$belonged}"] = array(
'title' => t('%type_name: Edit content in own %belonged', array(
'%type_name' => $name,
'%belonged' => $belonged,
)),
'description' => t('For %type_name assigned to the same %belonged as a user, allows the user to edit the %type_name.', array(
'%type_name' => $name,
'%belonged' => $belonged,
)),
);
$permissions["PM permission {$type}: delete own {$belonged}"] = array(
'title' => t('%type_name: Delete in own %belonged', array(
'%type_name' => $name,
'%belonged' => $belonged,
)),
'description' => t('For %type_name assigned to the same %belonged as a user, allows the user to delete the %type_name.', array(
'%type_name' => $name,
'%belonged' => $belonged,
)),
);
return $permissions;
}
/**
* Helper function to generate assigned permissions set.
*
* @param string $type
* Node bundle machine name.
* @param string $name
* Node bundle name that could be used for display.
*
* @return array $permissions
* Equivalent to the return of hook_permission().
*/
function _pmpermission_permission_assigned($type, $name, $role) {
$permissions["PM permission {$type}: view if {$role}"] = array(
'title' => t('%type_name: View content if %role to %type_name', array(
'%type_name' => $name,
'%role' => $role,
)),
'description' => t('For %type_name with a user as %role, allows the user to view the %type_name.', array(
'%type_name' => $name,
'%role' => $role,
)),
);
$permissions["PM permission {$type}: update if {$role}"] = array(
'title' => t('%type_name: Edit content if %role to %type_name', array(
'%type_name' => $name,
'%role' => $role,
)),
'description' => t('For %type_name with a user as %role, allows the user to edit the %type_name.', array(
'%type_name' => $name,
'%role' => $role,
)),
);
$permissions["PM permission {$type}: delete if {$role}"] = array(
'title' => t('%type_name: Delete content if %role to %type_name', array(
'%type_name' => $name,
'%role' => $role,
)),
'description' => t('For %type_name with a user as %role, allows the user to delete the %type_name.', array(
'%type_name' => $name,
'%role' => $role,
)),
);
return $permissions;
}
/**
* A helper function to check if a field is present in a node.
*
* @param string $bundle_name
* Node bundle machine name.
* @param string $category
* Category of permission {pm, assigned, parent}.
*
* @return string
* The actual name of the field if present, false otherwise.
*/
function _pmpermission_get_field_name($bundle_name, $category) {
switch ($category) {
case 'parent':
$field_name = variable_get("pmpermission_field_parent_reference_for_{$bundle_name}", FALSE);
break;
case 'assigned':
$field_name = variable_get("pmpermission_field_assigned_reference", FALSE);
break;
case 'pm':
$field_name = variable_get("pmpermission_field_pm_reference", FALSE);
break;
default:
$field_name = FALSE;
break;
}
if ($field_name and field_info_instance('node', $field_name, $bundle_name)) {
return $field_name;
}
return FALSE;
}
/**
* Implements hook_node_access_records().
*/
function pmpermission_node_access_records($node) {
if (empty($node->status)) {
// Lets Drupal take care of permission to unpublished nodes.
return array();
}
$bundle_name = is_string($node) ? $node : $node->type;
$grants = array();
if (!variable_get('node_permissions_' . $bundle_name, 1)) {
$default_grants = _pmpermission_grants_default($node, $bundle_name);
$grants = array_merge($grants, $default_grants);
}
if (module_exists('pmorganization')) {
if ($bundle_name == 'pmorganization' or _pmpermission_get_field_name($bundle_name, 'parent')) {
$belonged_grants = _pmpermission_grants_belonged($node, $bundle_name, 'Organization');
if ($belonged_grants) {
$grants = array_merge($grants, $belonged_grants);
}
}
}
if (module_exists('pmproject')) {
if (_pmpermission_get_field_name($bundle_name, 'pm')) {
$assigned_grants_pm = _pmpermission_grants_assigned($node, $bundle_name, 'Project Manager');
if ($assigned_grants_pm) {
$grants = array_merge($grants, $assigned_grants_pm);
}
}
}
if (_pmpermission_get_field_name($bundle_name, 'assigned')) {
$assigned_grants_assigned = _pmpermission_grants_assigned($node, $bundle_name, 'Assigned');
if ($assigned_grants_assigned) {
$grants = array_merge($grants, $assigned_grants_assigned);
}
}
return $grants;
}
/**
* Generate default grants similar to drupal core.
*/
function _pmpermission_grants_default($node, $type) {
// PM permission $type: view all.
$grants[] = array(
'realm' => "pmpermission_{$type}_view_all",
'gid' => 0,
'grant_view' => 1,
'grant_update' => 0,
'grant_delete' => 0,
'priority' => 0,
);
// PM permission $type: view own.
$grants[] = array(
'realm' => "pmpermission_{$type}_view_own",
'gid' => $node->uid,
'grant_view' => 1,
'grant_update' => 0,
'grant_delete' => 0,
'priority' => 0,
);
// PM permission $type: update all.
$grants[] = array(
'realm' => "pmpermission_{$type}_update_all",
'gid' => 0,
'grant_view' => 0,
'grant_update' => 1,
'grant_delete' => 0,
'priority' => 0,
);
// PM permission $type: update own.
$grants[] = array(
'realm' => "pmpermission_{$type}_update_own",
'gid' => $node->uid,
'grant_view' => 0,
'grant_update' => 1,
'grant_delete' => 0,
'priority' => 0,
);
// PM permission $type: delete all.
$grants[] = array(
'realm' => "pmpermission_{$type}_delete_all",
'gid' => 0,
'grant_view' => 0,
'grant_update' => 0,
'grant_delete' => 1,
'priority' => 0,
);
// PM permission $type: delete own.
$grants[] = array(
'realm' => "pmpermission_{$type}_delete_own",
'gid' => $node->uid,
'grant_view' => 0,
'grant_update' => 0,
'grant_delete' => 1,
'priority' => 0,
);
return $grants;
}
/**
* Generate grants for belonged permission set.
*/
function _pmpermission_grants_belonged($node, $type, $belonged) {
// PM permission $type: view own %belonged.
$belonged_nid = _pmpermission_get_belonged_id($node, $type, $belonged);
$grants = array();
if ($belonged_nid) {
$grants[] = array(
'realm' => "pmpermission_{$type}_view_belonged_{$belonged}",
'gid' => $belonged_nid,
'grant_view' => 1,
'grant_update' => 0,
'grant_delete' => 0,
'priority' => 0,
);
$grants[] = array(
'realm' => "pmpermission_{$type}_update_belonged_{$belonged}",
'gid' => $belonged_nid,
'grant_view' => 0,
'grant_update' => 1,
'grant_delete' => 0,
'priority' => 0,
);
$grants[] = array(
'realm' => "pmpermission_{$type}_delete_belonged_{$belonged}",
'gid' => $belonged_nid,
'grant_view' => 0,
'grant_update' => 0,
'grant_delete' => 1,
'priority' => 0,
);
}
return $grants;
}
/**
* Generate grants for assigned permission set.
*/
function _pmpermission_grants_assigned($node, $type, $assigned) {
// PM permission $type: view own %assigned.
$assigned_nids = _pmpermission_get_assigned_id($node, $type, $assigned);
$grants = array();
if ($assigned_nids) {
foreach ($assigned_nids as $assigned_nid) {
if ($assigned_nid) {
$grants[] = array(
'realm' => "pmpermission_{$type}_view_assigned_{$assigned}",
'gid' => $assigned_nid,
'grant_view' => 1,
'grant_update' => 0,
'grant_delete' => 0,
'priority' => 0,
);
$grants[] = array(
'realm' => "pmpermission_{$type}_update_assigned_{$assigned}",
'gid' => $assigned_nid,
'grant_view' => 0,
'grant_update' => 1,
'grant_delete' => 0,
'priority' => 0,
);
$grants[] = array(
'realm' => "pmpermission_{$type}_delete_assigned_{$assigned}",
'gid' => $assigned_nid,
'grant_view' => 0,
'grant_update' => 0,
'grant_delete' => 1,
'priority' => 0,
);
}
}
}
return $grants;
}
/**
* Finds the nid of the organization attached to a node.
*/
function _pmpermission_get_organization_id($node, $max_depth) {
return pmpermission_get_parent_nid_of_node($node, 'pmorganization', $max_depth);
}
/**
* Recursively hunts and find out the first parent node of given type.
*
* @param object $node
* The node for which the parent to be found.
* @param string $parent_type
* The content type of parent node.
* @param int $max_depth
* How many levels up should the function traverse.
*
* @return mixed
* nid of the parent node if found, FALSE otherwise.
*/
function pmpermission_get_parent_nid_of_node($node, $parent_type, $max_depth = 10) {
if ($node->type == $parent_type) {
return $node->nid;
}
if ($max_depth) {
--$max_depth;
$bundle_name = $node->type;
$field_name = _pmpermission_get_field_name($bundle_name, 'parent');
if (empty($field_name)) {
return FALSE;
}
try {
$wrapper = entity_metadata_wrapper('node', $node);
$n = $wrapper->{$field_name}
->value();
if (empty($n)) {
return FALSE;
}
elseif ($n->type == $parent_type) {
return $n->nid;
}
else {
return pmpermission_get_parent_nid_of_node($n, $parent_type, $max_depth);
}
} catch (Exception $e) {
_pmpermission_watchdog_log($e);
}
}
else {
return FALSE;
}
}
/**
* Recursively hunt for a particular parent and get its id.
*/
function _pmpermission_get_belonged_id($node, $type, $belonged) {
$belonged_nid = FALSE;
switch ($belonged) {
case 'Organization':
$belonged_nid = _pmpermission_get_organization_id($node, 4);
break;
default:
break;
}
return $belonged_nid;
}
/**
* Should recursively hunt for a particular parent and get its id.
*/
function _pmpermission_get_assigned_id($node, $type, $assigned) {
$assigned_nids = FALSE;
switch ($assigned) {
case 'Project Manager':
$field_name = variable_get("pmpermission_field_pm_reference", FALSE);
break;
case 'Assigned':
$field_name = variable_get("pmpermission_field_assigned_reference", FALSE);
break;
default:
break;
}
if ($field_name) {
try {
$wrapper = entity_metadata_wrapper('node', $node);
$field_info = field_info_field($field_name);
if ($field_info['cardinality'] == 1) {
$account = $wrapper->{$field_name}
->value();
if ($account) {
$assigned_nids[] = $account->uid;
}
}
else {
foreach ($wrapper->{$field_name}
->getIterator() as $account_wrapper) {
$assigned_nids[] = $account_wrapper
->getIdentifier();
}
}
} catch (Exception $e) {
_pmpermission_watchdog_log($e);
}
}
return $assigned_nids;
}
/**
* Implements hook_node_grants().
*/
function pmpermission_node_grants($account, $op) {
$grants = array();
foreach (pmpermission_get_enabled_types() as $type) {
$grant_per_type = pmpermission_grants_list($account, $op, $type);
if ($grant_per_type) {
$grants += $grant_per_type;
}
}
return $grants;
}
/**
* Helper function for pmpermission_node_grants.
*/
function pmpermission_grants_list($account, $op, $type) {
$grants = array();
if (user_access("PM permission {$type}: {$op} all", $account)) {
$grants["pmpermission_{$type}_{$op}_all"] = array(
0,
);
}
if (user_access("PM permission {$type}: {$op} own", $account)) {
$grants["pmpermission_{$type}_{$op}_own"] = array(
$account->uid,
);
}
if (module_exists('pmorganization')) {
if (_pmpermission_get_field_name($type, 'parent') or $type == 'pmorganization') {
$field_name = variable_get("pmpermission_field_org_member_reference", '');
$pmorganization_nids = _pmpermission_get_entity_id_referenced_to_user('node', 'pmorganization', $field_name, $account->uid);
$belonged = 'Organization';
if (user_access("PM permission {$type}: {$op} own {$belonged}", $account) and !empty($pmorganization_nids)) {
$grants["pmpermission_{$type}_{$op}_belonged_{$belonged}"] = $pmorganization_nids;
}
}
}
if (module_exists('pmproject')) {
if (_pmpermission_get_field_name($type, 'pm')) {
$assigned = 'Project Manager';
if (user_access("PM permission {$type}: {$op} if {$assigned}", $account)) {
$grants["pmpermission_{$type}_{$op}_assigned_{$assigned}"] = array(
$account->uid,
);
}
}
}
if (_pmpermission_get_field_name($type, 'assigned')) {
$assigned = 'Assigned';
if (user_access("PM permission {$type}: {$op} if {$assigned}", $account)) {
$grants["pmpermission_{$type}_{$op}_assigned_{$assigned}"] = array(
$account->uid,
);
}
}
return $grants;
}
/**
* Get entity ids having a reference field pointing towards the user id.
*/
function _pmpermission_get_entity_id_referenced_to_user($entity_type, $bundle, $field_name, $uid) {
$ids = FALSE;
if ($entity_type and $bundle and $field_name and $uid) {
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', $entity_type)
->entityCondition('bundle', $bundle)
->propertyCondition('status', 1)
->fieldCondition($field_name, 'target_id', $uid)
->addMetaData('account', user_load(1));
$result = $query
->execute();
if (isset($result['node'])) {
$ids = array_keys($result['node']);
}
}
return $ids;
}
/**
* Implements hook_node_access().
*/
function pmpermission_node_access($node, $op, $account) {
$type = is_string($node) ? $node : $node->type;
if (variable_get("pmpermission_node_{$type}_enabled", FALSE) && $op == 'create') {
if (user_access("PM permission {$type}: create", $account)) {
return NODE_ACCESS_ALLOW;
}
}
// Returning nothing from this function would have the same effect.
return NODE_ACCESS_IGNORE;
}
/**
* Log and display the error.
*
* @param string $error
* Error to report.
* @param bool $backtrace
* TRUE if watchdog log should include full backtrace of the error.
*/
function _pmpermission_watchdog_log($error, $backtrace = TRUE) {
$err_msg = t("Error message: %error", array(
'%error' => $error,
));
watchdog('PHP', $err_msg, WATCHDOG_ERROR);
drupal_set_message($err_msg, 'error');
}
/**
* Implements hook_node_update().
*/
function pmpermission_node_update($node) {
$enabled = pmpermission_get_enabled_types();
$type = $node->type;
if (in_array($type, $enabled)) {
if (pmpermission_check_if_child_permission_needs_update($node)) {
pmpermission_hunt_and_update_all_child_permission($node);
}
}
}
/**
* Check and performs access update if supplied pmorganization.
*/
function pmpermission_hunt_and_update_all_child_permission($node) {
$nids = pmpermission_get_all_child_nids($node->nid);
if ($nids) {
$batch = array(
'title' => t('Rebuilding access permissions for the @type "@title"', array(
'@type' => $node->type,
'@title' => $node->title,
)),
'operations' => array(
array(
'_pmpermission_node_access_rebuild_batch_operation',
array(
$nids,
),
),
),
'finished' => '_pmpermission_node_access_rebuild_batch_finished',
);
batch_set($batch);
}
}
/**
* Check if current node is directly under pmorganization, and has changed.
*/
function pmpermission_check_if_child_permission_needs_update($node) {
$type = $node->type;
$wrapper = entity_metadata_wrapper('node', $node);
$parent_field = variable_get("pmpermission_field_parent_reference_for_{$type}", NULL);
// No update required if parent field is absent.
if (empty($parent_field)) {
return FALSE;
}
$parent_new = $wrapper->{$parent_field}
->value();
$new_id = isset($parent_new->nid) ? $parent_new->nid : NULL;
$wrapper = entity_metadata_wrapper('node', $node->original);
$parent_old = $wrapper->{$parent_field}
->value();
$old_id = isset($parent_old->nid) ? $parent_old->nid : NULL;
return $new_id != $old_id;
}
/**
* Helper function to get all child nids under current node.
*/
function pmpermission_get_all_child_nids($nid) {
$parents = array(
$nid,
);
$result = NULL;
_pmpermission_get_all_child_nids($parents, $result);
return $result;
}
/**
* Recursively hunt for child nodes of pmorganization.
*/
function _pmpermission_get_all_child_nids($nids, &$result = NULL) {
static $depth = 0;
$depth++;
if ($depth >= 10) {
return;
}
if ($result === NULL) {
$result = array();
$new_ids = $nids;
}
else {
$new_ids = array_diff($nids, $result);
$result = array_merge($result, $new_ids);
if (empty($new_ids)) {
return;
}
}
$ids = array();
foreach ($new_ids as $nid) {
$enabled = pmpermission_get_enabled_types();
if ($enabled) {
foreach ($enabled as $type) {
$parent_field = variable_get("pmpermission_field_parent_reference_for_{$type}", NULL);
if ($parent_field) {
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'node')
->entityCondition('bundle', array(
$type,
), 'IN')
->fieldCondition($parent_field, 'target_id', $nid)
->addMetaData('account', user_load(1));
$r = $query
->execute();
if (isset($r['node'])) {
$keys = array_keys($r['node']);
$ids = array_merge($ids, $keys);
}
}
}
}
}
_pmpermission_get_all_child_nids($ids, $result);
}
/**
* Custom batch operation for rebuilding permission.
*
* @see pmpermission_hunt_and_update_all_child_permission()
*/
function _pmpermission_node_access_rebuild_batch_operation($nids, &$context) {
if (empty($context['sandbox'])) {
// Initiate multistep processing.
$context['sandbox']['progress'] = 0;
$context['sandbox']['max'] = count($nids);
$context['sandbox']['nids'] = drupal_map_assoc($nids);
if (empty($nids)) {
$context['finished'] = 1;
return;
}
}
$nids = array_slice($context['sandbox']['nids'], 0, 20);
$nodes = node_load_multiple($nids, array(), TRUE);
foreach ($nodes as $nid => $node) {
// To preserve database integrity, only acquire grants if the node
// loads successfully.
if (!empty($node)) {
node_access_acquire_grants($node);
}
unset($context['sandbox']['nids'][$nid]);
$context['sandbox']['progress']++;
$context['message'] = t('Now processing %node', array(
'%node' => $node->title,
));
}
// Multistep processing : report progress.
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
/**
* Custom batch finish callback.
*
* @see pmpermission_hunt_and_update_all_child_permission()
*/
function _pmpermission_node_access_rebuild_batch_finished($success, $results, $operations) {
if ($success) {
drupal_set_message(t('The <em>Project Management</em> permissions have been rebuilt.'));
}
else {
drupal_set_message(t('The <em>Project Management</em> permissions have not been properly rebuilt.'), 'error');
}
cache_clear_all();
}
Functions
Name | Description |
---|---|
pmpermission_admin | Admin settings form. |
pmpermission_admin_submit | Admin settings form submit handler. |
pmpermission_check_if_child_permission_needs_update | Check if current node is directly under pmorganization, and has changed. |
pmpermission_get_all_child_nids | Helper function to get all child nids under current node. |
pmpermission_get_enabled_types | Returns a list of node bundles for which PM permission have been enabled. |
pmpermission_get_parent_nid_of_node | Recursively hunts and find out the first parent node of given type. |
pmpermission_grants_list | Helper function for pmpermission_node_grants. |
pmpermission_help | Implements hook_help(). |
pmpermission_hunt_and_update_all_child_permission | Check and performs access update if supplied pmorganization. |
pmpermission_menu | Implements hook_menu(). |
pmpermission_node_access | Implements hook_node_access(). |
pmpermission_node_access_records | Implements hook_node_access_records(). |
pmpermission_node_grants | Implements hook_node_grants(). |
pmpermission_node_update | Implements hook_node_update(). |
pmpermission_permission | Implements hook_permission(). |
pmpermission_permission_per_bundle | Creates an array of permission name for the given node bundle. |
_pmpermission_get_all_child_nids | Recursively hunt for child nodes of pmorganization. |
_pmpermission_get_assigned_id | Should recursively hunt for a particular parent and get its id. |
_pmpermission_get_belonged_id | Recursively hunt for a particular parent and get its id. |
_pmpermission_get_entity_id_referenced_to_user | Get entity ids having a reference field pointing towards the user id. |
_pmpermission_get_field_name | A helper function to check if a field is present in a node. |
_pmpermission_get_field_names_per_field_type | Get a list of field names matching a specific type. |
_pmpermission_get_organization_id | Finds the nid of the organization attached to a node. |
_pmpermission_grants_assigned | Generate grants for assigned permission set. |
_pmpermission_grants_belonged | Generate grants for belonged permission set. |
_pmpermission_grants_default | Generate default grants similar to drupal core. |
_pmpermission_node_access_rebuild_batch_finished | Custom batch finish callback. |
_pmpermission_node_access_rebuild_batch_operation | Custom batch operation for rebuilding permission. |
_pmpermission_permission_assigned | Helper function to generate assigned permissions set. |
_pmpermission_permission_belonged | Helper function to generate belonged to permission set. |
_pmpermission_permission_default | Helper function to generate default permissions. |
_pmpermission_watchdog_log | Log and display the error. |