| 1 |
<?php
|
| 2 |
// $Id: na_arbitrator.module,v 1.4 2006/03/23 19:25:57 merlinofchaos Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file na_arbitrator.module
|
| 6 |
*
|
| 7 |
* This module exists as a glue module between node_access and other modules
|
| 8 |
* that want to use node_access. It controls the writing of records and
|
| 9 |
* makes it possible for modules to work together by dealing with nodes
|
| 10 |
* that other modules don't want to deal with.
|
| 11 |
*
|
| 12 |
* This is a core patch effort, but will start out as a module with full
|
| 13 |
* intent of being moved into node.module as soon as this solution
|
| 14 |
* is accepted.
|
| 15 |
*/
|
| 16 |
|
| 17 |
/**
|
| 18 |
* Implementation of hook_help
|
| 19 |
*/
|
| 20 |
function na_arbitrator_help($section) {
|
| 21 |
switch($section) {
|
| 22 |
case 'admin/modules#description':
|
| 23 |
return t('The node access arbitrator module makes it possible for compliant node access modules to co-exist. This module contains no user-serviceable parts.');
|
| 24 |
}
|
| 25 |
}
|
| 26 |
|
| 27 |
/**
|
| 28 |
* Implementation of hook_node_grants
|
| 29 |
*
|
| 30 |
* The arbitrator controls only one grant, the 'arbitrator' grant. When
|
| 31 |
* moved to node.module, this will become the 'all' grant. By default,
|
| 32 |
* all users automatically get this grant of grant ID 1.
|
| 33 |
*/
|
| 34 |
function na_arbitrator_node_grants($user, $op) {
|
| 35 |
return array('arbitrator' => array(1));
|
| 36 |
}
|
| 37 |
|
| 38 |
/**
|
| 39 |
* Implementation of hook_nodeapi
|
| 40 |
*
|
| 41 |
* When a node is saved, the arbitrator will ask any other security modules
|
| 42 |
* for grants. If a grant list is returned, it will write that. If not,
|
| 43 |
* it will write its own grant which gives every user view access.
|
| 44 |
*/
|
| 45 |
function na_arbitrator_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
|
| 46 |
switch ($op) {
|
| 47 |
case 'insert':
|
| 48 |
case 'update':
|
| 49 |
na_arbitrator_acquire_grants($node);
|
| 50 |
break;
|
| 51 |
}
|
| 52 |
}
|
| 53 |
|
| 54 |
/**
|
| 55 |
* This function will call module invoke to get a list of grants and then
|
| 56 |
* write them to the database.
|
| 57 |
*
|
| 58 |
* @param $node
|
| 59 |
* The $node to acquire grants for.
|
| 60 |
*/
|
| 61 |
function na_arbitrator_acquire_grants($node) {
|
| 62 |
// Unfortunately hook_node_grants is misnamed. I think it should be
|
| 63 |
// hook_node_user_grants.
|
| 64 |
$grants = module_invoke_all('node_access_grants', $node);
|
| 65 |
if (!$grants) {
|
| 66 |
$grants[] = array('realm' => 'arbitrator', 'gid' => 1, 'grant_view' => 1, 'grant_update' => 0, 'grant_delete' => 0);
|
| 67 |
}
|
| 68 |
else {
|
| 69 |
// retain grants by highest priority
|
| 70 |
$grant_by_priority = array();
|
| 71 |
foreach ($grants as $g) {
|
| 72 |
$grant_by_priority[intval($g['priority'])][] = $g;
|
| 73 |
}
|
| 74 |
krsort($grant_by_priority);
|
| 75 |
$grants = current($grant_by_priority);
|
| 76 |
}
|
| 77 |
|
| 78 |
na_arbitrator_write_grants($node, $grants);
|
| 79 |
}
|
| 80 |
|
| 81 |
/**
|
| 82 |
* This function will write a list of grants to the database, deleting
|
| 83 |
* any pre-existing grants. If a realm is provided, it will only
|
| 84 |
* delete grants from that realm, but it will always delete a grant
|
| 85 |
* from the 'arbitrator' realm. Modules which utilize node_access can
|
| 86 |
* use this function when doing mass updates due to widespread permission
|
| 87 |
* changes.
|
| 88 |
*
|
| 89 |
* @param $node
|
| 90 |
* The $node being written to. All that is necessary is that it contain a nid.
|
| 91 |
* @param $grants
|
| 92 |
* A list of grants to write. Each grant is an array that must contain the
|
| 93 |
* following keys: realm, gid, grant_view, grant_update, grant_delete.
|
| 94 |
* The realm is specified by a particular module; the gid is as well, and
|
| 95 |
* is a module-defined id to define grant privileges. each grant_* field
|
| 96 |
* is a boolean value.
|
| 97 |
* @param $realm
|
| 98 |
* If provided, only read/write grants for that realm.
|
| 99 |
* @param $delete
|
| 100 |
* If false, do not delete records. This is only for optimization purposes,
|
| 101 |
* and assumes the caller has already performed a mass delete of some form.
|
| 102 |
*/
|
| 103 |
function na_arbitrator_write_grants($node, $grants, $realm = NULL, $delete = TRUE) {
|
| 104 |
if ($delete) {
|
| 105 |
$query = 'DELETE FROM {node_access} WHERE nid = %d';
|
| 106 |
if ($realm) {
|
| 107 |
$query .= " AND realm in ('%s', 'arbitrator')";
|
| 108 |
}
|
| 109 |
db_query($query, $node->nid, $realm);
|
| 110 |
}
|
| 111 |
|
| 112 |
// This optimization reduces the number of db inserts a little bit. We could
|
| 113 |
// optimize further for mass updates if we wanted.
|
| 114 |
$values = array();
|
| 115 |
|
| 116 |
$query = '';
|
| 117 |
foreach ($grants as $grant) {
|
| 118 |
if ($realm && $realm != $grant['realm']) {
|
| 119 |
continue;
|
| 120 |
}
|
| 121 |
$query .= ($query ? ', ' : '') . "(%d, '%s', %d, %d, %d, %d)";
|
| 122 |
// I'm not sure += works right here; if it does we should use that instead.
|
| 123 |
$values[] = $node->nid;
|
| 124 |
$values[] = $grant['realm'];
|
| 125 |
$values[] = $grant['gid'];
|
| 126 |
$values[] = $grant['grant_view'];
|
| 127 |
$values[] = $grant['grant_update'];
|
| 128 |
$values[] = $grant['grant_delete'];
|
| 129 |
}
|
| 130 |
|
| 131 |
$query = "INSERT INTO {node_access} (nid, realm, gid, grant_view, grant_update, grant_delete) VALUES " . $query;
|
| 132 |
|
| 133 |
db_query($query, $values);
|
| 134 |
}
|
| 135 |
|
| 136 |
/**
|
| 137 |
* implementation of hook_settings
|
| 138 |
*/
|
| 139 |
function na_arbitrator_settings() {
|
| 140 |
$form['markup'] = array(
|
| 141 |
'#value' => t('Click submit to reset your access database; this may be necessary right after installing na_arbitrator or a module that relies on na_arbitrator. NOTE: If you are using a node_access module that does not use the na_arbitrator API, its access control records will be destroyed! If you are even the slightest bit unsure, please back up your database BEFORE pressing submit here! YOU CANNOT UNDO THIS! This process may take some time to run.')
|
| 142 |
);
|
| 143 |
$form['#submit']['na_arbitrator_settings_submit'] = array('na_arbitrator_settings_submit' => array());
|
| 144 |
return $form;
|
| 145 |
}
|
| 146 |
|
| 147 |
/**
|
| 148 |
* reset the node access database
|
| 149 |
*/
|
| 150 |
function na_arbitrator_settings_submit() {
|
| 151 |
db_query("DELETE FROM {node_access}");
|
| 152 |
$result = db_query("SELECT nid FROM {node}");
|
| 153 |
while ($node = db_fetch_object($result)) {
|
| 154 |
na_arbitrator_acquire_grants(node_load($node->nid));
|
| 155 |
}
|
| 156 |
}
|