<?php
// $Id: nodeaccess_userreference.module,v 1.1.2.6.2.11 2009/09/20 11:26:14 danielb Exp $

/**
 * Implementation of hook_menu().
 */
function nodeaccess_userreference_menu() {
  $items = array();

  $items['admin/settings/nodeaccess_userreference'] = array(
    'title' => 'Node access user reference settings',
    'description' => 'Configure Node Access User Reference.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('nodeaccess_userreference_admin_settings'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_NORMAL_ITEM,
  );
    
  return $items;
}

/**
 * System settings form for nodeaccess_userreference.
 */
function nodeaccess_userreference_admin_settings() {
  
  $form['nodeaccess_userreference_priority'] = array(
    '#type' => 'weight',
    '#title' => t('Set node grants priority for Node Access User Reference'),
    '#default_value' => variable_get('nodeaccess_userreference_priority', 0),
    '#description' => t('If you are only using this access control module, you can safely ignore this. 
    If you are using multiple access control modules you can adjust the priority of this module.'),
  );
  
  // Add additional submit processing
  $form['#submit'][] = 'nodeaccess_userreference_admin_settings_submit';

  return system_settings_form($form);
}

/**
 * Implementation of hook_node_grants().
 */
function nodeaccess_userreference_node_grants($account, $op) {
  $grants = array();
  $grants['nodeaccess_userreference'][] = $account->uid;
  if (!empty($grants)) {
    return $grants;
  }
  return NULL;
}

/**
 * Implementation of hook_form-FORM-ID_alter().
 */
function nodeaccess_userreference_form_content_field_edit_form_alter(&$form, $form_state) {
  if ($form['#field']['type'] == "userreference") {

    $data = nodeaccess_userreference_field_settings($form['#field']['type_name'],  $form['#field']['field_name']);

    $form['widget']['nodeaccess_userreference_view'] = array(
      '#type' => 'checkbox',
      '#title' => t('Grant "view" node access to user'),
      '#default_value' => $data['view'],
      '#description' => t('Give the referenced user access to view the node, if they cannot already do so.'),
      '#weight' => 42,
    );

    $form['widget']['nodeaccess_userreference_update'] = array(
      '#type' => 'checkbox',
      '#title' => t('Grant "edit" node access to user'),
      '#default_value' => $data['update'],
      '#description' => t('Give the referenced user access to edit the node, if they cannot already do so.'),
      '#weight' => 43,
    );

    $form['widget']['nodeaccess_userreference_delete'] = array(
      '#type' => 'checkbox',
      '#title' => t('Grant "delete" node access to user'),
      '#default_value' => $data['delete'],
      '#description' => t('Give the referenced user access to delete the node, if they cannot already do so.'),
      '#weight' => 44,
    );

    $form['#submit'][] = 'nodeaccess_userreference_content_field_edit_form_submit';
  }
}

/**
 * Extra submit function for User Reference field config.
 */
function nodeaccess_userreference_content_field_edit_form_submit($form, &$form_state) {
  $form_values = &$form_state['values'];
  $data = array(
    'view' => $form_values['nodeaccess_userreference_view'],
    'update' => $form_values['nodeaccess_userreference_update'],
    'delete' => $form_values['nodeaccess_userreference_delete'],
  );
  nodeaccess_userreference_field_settings($form_values['type_name'], $form_values['field_name'], $data);
  $nodes = node_load(array('type' => $form_values['type_name']));
  if ($nodes) {
    node_access_needs_rebuild(TRUE);
  }
}

/**
 * Implementation of hook_node_access_records().
 */
function nodeaccess_userreference_node_access_records($node) {
  $grants = array();
  $content_types = content_types($node->type);
  $info = &$content_types['fields'];
  $priority = variable_get('nodeaccess_userreference_priority', 0);
  if (is_array($info)) {
    foreach ($info as $field) {
      if ($field['type'] == 'userreference') {
        $data = nodeaccess_userreference_field_settings($field['type_name'], $field['field_name']);
        if (!empty($data) && !empty($node->$field['field_name'])) {
          foreach ((array)$node->$field['field_name'] as $userreference) {
            if ($userreference['uid']) {
              $uid = &$userreference['uid'];
              if (!isset($grants[$uid])) {
                $grants[$uid] = array(
                  'realm' => 'nodeaccess_userreference',
                  'gid' => $uid,
                  'priority' => $priority,
                );
              }
              if (isset($data['view']) && $data['view']) {
                $grants[$uid]['grant_view'] = 1;
              }
              if (isset($data['update']) && $data['update']) {
                $grants[$uid]['grant_update'] = 1;
              }
              if (isset($data['delete']) && $data['delete']) {
                $grants[$uid]['grant_delete'] = 1;
              }
            }
          }
        }
      }
    }
  }
  if (!empty($grants)) {
    // Allow other modules to change the grants.
    drupal_alter('nodeaccess_userreference_grants', $grants, $node);
    return $grants;
  }
  return NULL;
}

/**
 * Set and get nodeaccess userreference field settings.
 *
 * @param $type_name
 *   The node type.
 * @param $field_name
 *   The name of the field.
 * @param $variable
 *   If set will update the value of the settings for this field.
 * @return
 *   The stored or updated value of the settings for this field.
 */
function nodeaccess_userreference_field_settings($type_name, $field_name, $variable = NULL) {

  // 'get' the variable
  $data = variable_get('nodeaccess_userreference', NULL);
  if (!$data || !isset($data[$type_name][$field_name])) {
    // Attempt to get result from old variables.
    $old_varname = substr('nodeaccess_userreference_'. $field_name .'_'. $type_name, 0, 48);
    $old_data = variable_get($old_varname, NULL);
    if (is_array($old_data)) {
      variable_del($old_varname);
      nodeaccess_userreference_field_settings($type_name, $field_name, $old_data);
      $data[$type_name][$field_name] = $old_data;
    }
    else {
      // default
      $data[$type_name][$field_name] = array(
        'view' => 0, 
        'update' => 0, 
        'delete' => 0,
      );
    }
  }

  // change and 'set' the variable
  if (isset($variable)) {
    $data[$type_name][$field_name] = $variable;
    variable_set('nodeaccess_userreference', $data);
  }

  return $data[$type_name][$field_name];
}