| 1 |
<?php
|
| 2 |
// $Id: pacs.module,v 1.3 2006/06/12 14:11:43 peterone Exp $
|
| 3 |
|
| 4 |
/**
|
| 5 |
* @file
|
| 6 |
* pacs - the tree access module.
|
| 7 |
*/
|
| 8 |
|
| 9 |
$_pacs_nodes = array();
|
| 10 |
|
| 11 |
// includes on demand
|
| 12 |
if (arg(0) == 'pacs') require_once 'pacs_xml.inc';
|
| 13 |
|
| 14 |
/**
|
| 15 |
* pacs_debug()
|
| 16 |
*/
|
| 17 |
function pacs_debug($msg, $pre = 0) {
|
| 18 |
if ($pre) {
|
| 19 |
watchdog('debug','<pre>'.date('(s) ').$msg.'</pre>',WATCHDOG_WARNING);
|
| 20 |
} else {
|
| 21 |
watchdog('debug',date('(s) ').$msg,WATCHDOG_WARNING);
|
| 22 |
}
|
| 23 |
}
|
| 24 |
|
| 25 |
/**
|
| 26 |
* pacs_node()
|
| 27 |
*/
|
| 28 |
function pacs_node($nid,$rid = 0) {
|
| 29 |
global $user, $_pacs_nodes;
|
| 30 |
|
| 31 |
if (!$nid) $nid = 0;
|
| 32 |
if ($_pacs_nodes[$nid][$rid]) return $_pacs_nodes[$nid][$rid];
|
| 33 |
|
| 34 |
if ($nid) {
|
| 35 |
// real node
|
| 36 |
if ($rid) {
|
| 37 |
// role grants
|
| 38 |
$sql = "SELECT n.nid, n.title, n.type, n.pid, n.stops, na.grant_view gv, na.grant_update gu, na.grant_delete gm FROM {node} n LEFT OUTER JOIN {node_access} na ON na.nid = n.nid AND na.realm = 'pacs' AND na.gid = %d WHERE n.nid = %d";
|
| 39 |
$res = db_query($sql,$rid,$nid);
|
| 40 |
} else {
|
| 41 |
// user grants (rid = 0)
|
| 42 |
$gids = implode(',',array_keys($user->roles));
|
| 43 |
$sql = "SELECT n.nid, n.title, n.type, n.pid, n.stops, MAX(na.grant_view) gv, MAX(na.grant_update) gu, MAX(na.grant_delete) gm FROM {node} n LEFT OUTER JOIN {node_access} na ON na.nid = n.nid AND na.realm = 'pacs' AND na.gid IN (%s) WHERE n.nid = %d GROUP BY nid";
|
| 44 |
$res = db_query($sql,$gids,$nid);
|
| 45 |
}
|
| 46 |
$nde = db_fetch_array($res);
|
| 47 |
$nde['stops'] = unserialize($nde['stops']);
|
| 48 |
if (!$nde['stops']) $nde['stops'] = array();
|
| 49 |
} else {
|
| 50 |
// root pseudo-node (nid = 0)
|
| 51 |
if ($rid) {
|
| 52 |
// role grants
|
| 53 |
$sql = "SELECT grant_view gv,grant_update gu,grant_delete gm FROM {node_access} WHERE realm = 'pacs' AND nid = %d AND gid = %d";
|
| 54 |
$res = db_query($sql,$nid,$rid);
|
| 55 |
} else {
|
| 56 |
//user grants (rid = 0)
|
| 57 |
$gids = implode(',',array_keys($user->roles));
|
| 58 |
$sql = "SELECT MAX(grant_view) gv, MAX(grant_update) gu, MAX(grant_delete) gm FROM {node_access} WHERE realm = 'pacs' AND nid = %d AND gid IN (%s)";
|
| 59 |
$res = db_query($sql,$nid,$gids);
|
| 60 |
}
|
| 61 |
$grs = db_fetch_array($res);
|
| 62 |
$nde = array('nid' => 0, 'pid' => NULL, 'type' => 'root', 'title' => t('root'), 'stops' => array());
|
| 63 |
if (isset($grs)) $nde = array_merge($nde,$grs);
|
| 64 |
}
|
| 65 |
$nde['rid'] = $rid;
|
| 66 |
if (($rid == 0) && ($user->uid == 1)) { $nde['gv'] = 1; $nde['gu'] = 1; $nde['gm'] = 1; }
|
| 67 |
$nde['grants'] = array($nde['gv'],$nde['gu'],$nde['gm']);
|
| 68 |
$_pacs_nodes[$nid][$rid] = $nde;
|
| 69 |
return $_pacs_nodes[$nid][$rid];
|
| 70 |
}
|
| 71 |
|
| 72 |
|
| 73 |
/**
|
| 74 |
* pacs_update_node()
|
| 75 |
*/
|
| 76 |
function pacs_update_node($node) {
|
| 77 |
global $_pacs_nodes;
|
| 78 |
|
| 79 |
$_pacs_nodes[$node['nid']][$node['rid']] = $node;
|
| 80 |
if ($node['nid']) {
|
| 81 |
$sql = "UPDATE {node} SET pid = %d, stops = '%s' WHERE nid = %d";
|
| 82 |
db_query($sql, $node['pid'], serialize($node['stops']), $node['nid']);
|
| 83 |
}
|
| 84 |
if ($node['rid']) {
|
| 85 |
$sql = "REPLACE {node_access} SET nid = %d, gid = %d, realm = 'pacs', grant_view = %d, grant_update = %d, grant_delete = %d";
|
| 86 |
db_query($sql, $node['nid'], $node['rid'], $node['grants'][0],$node['grants'][1],$node['grants'][2]);
|
| 87 |
}
|
| 88 |
}
|
| 89 |
|
| 90 |
/**
|
| 91 |
* pacs_loop()
|
| 92 |
*
|
| 93 |
* detects and breaks node loops
|
| 94 |
*/
|
| 95 |
function pacs_loop($fnc, $nid = -1) {
|
| 96 |
static $loop = array();
|
| 97 |
|
| 98 |
if ($nid < 0) {
|
| 99 |
unset($loop[$fnc]);
|
| 100 |
return FALSE;
|
| 101 |
}
|
| 102 |
if ($loop[$fnc][$nid]) {
|
| 103 |
// breaking the loop
|
| 104 |
db_query('UPDATE {node} SET pid = 0 WHERE nid = %d',$nid);
|
| 105 |
watchdog('pacs','LOOP detected and opened, function='.$fnc.', nid='.$nid,WATCHDOG_WARNING);
|
| 106 |
return TRUE;
|
| 107 |
} else {
|
| 108 |
$loop[$fnc][$nid] = 1;
|
| 109 |
}
|
| 110 |
return FALSE;
|
| 111 |
}
|
| 112 |
|
| 113 |
/**
|
| 114 |
* pacs_set_branch_grants()
|
| 115 |
*/
|
| 116 |
function pacs_set_branch_grants($nid,$rid,$grants,$reset_loop = TRUE) {
|
| 117 |
if ($reset_loop) pacs_loop('set_branch_grants');
|
| 118 |
pacs_loop('set_branch_grants',$nid);
|
| 119 |
db_query("REPLACE {node_access} SET nid = %d, gid = %d, realm = 'pacs', grant_view = %d, grant_update = %d, grant_delete = %d", $nid, $rid, $grants[0],$grants[1],$grants[2]);
|
| 120 |
$res = db_query("SELECT nid,stops FROM {node} WHERE pid = %d",$nid);
|
| 121 |
while ($row = db_fetch_array($res)) {
|
| 122 |
$stops = unserialize($row['stops']);
|
| 123 |
if (!$stops[$rid]) pacs_set_branch_grants($row['nid'],$rid,$grants,FALSE);
|
| 124 |
}
|
| 125 |
}
|
| 126 |
|
| 127 |
/**
|
| 128 |
* pacs_view_tree_perm()
|
| 129 |
*/
|
| 130 |
function pacs_view_tree_perm() {
|
| 131 |
global $user;
|
| 132 |
|
| 133 |
if ($user->uid == 1) return TRUE;
|
| 134 |
if (user_access('view tree')) return TRUE;
|
| 135 |
if (user_access('manage tree')) return TRUE;
|
| 136 |
return FALSE;
|
| 137 |
}
|
| 138 |
|
| 139 |
/**
|
| 140 |
* pacs_manage_tree_perm()
|
| 141 |
*/
|
| 142 |
function pacs_manage_tree_perm($nid) {
|
| 143 |
global $user;
|
| 144 |
|
| 145 |
if ($user->uid == 1) return TRUE;
|
| 146 |
$pnode = pacs_node($nid);
|
| 147 |
if ($pnode['grants'][2] && user_access('manage tree')) return TRUE;
|
| 148 |
return FALSE;
|
| 149 |
}
|
| 150 |
|
| 151 |
/**
|
| 152 |
* pacs_child_list()
|
| 153 |
*/
|
| 154 |
function pacs_child_list($nid) {
|
| 155 |
static $list = array();
|
| 156 |
|
| 157 |
if ($list[$nid]) return $list[$nid];
|
| 158 |
|
| 159 |
$res = db_query('SELECT nid FROM {node} WHERE pid = %d ORDER BY title',$nid);
|
| 160 |
while ($row = db_fetch_array($res)) $list[$nid][] = $row['nid'];
|
| 161 |
return $list[$nid];
|
| 162 |
}
|
| 163 |
|
| 164 |
/**
|
| 165 |
* pacs_move_node()
|
| 166 |
*/
|
| 167 |
function pacs_move_node($org_nid, $dst_nid, $check = 1) {
|
| 168 |
if ($org_nid == $dst_nid) return;
|
| 169 |
|
| 170 |
// check user permissions
|
| 171 |
if ($check && (!pacs_manage_tree_perm($org_nid) || !pacs_manage_tree_perm($dst_nid))) {
|
| 172 |
drupal_set_message(t('Insuficient permission to move nodes'),'error');
|
| 173 |
return;
|
| 174 |
}
|
| 175 |
// test for loop
|
| 176 |
if ($dst_nid != 0) {
|
| 177 |
$nid = $dst_nid;
|
| 178 |
$loop = FALSE;
|
| 179 |
while ($nid) {
|
| 180 |
$node = pacs_node($nid,1);
|
| 181 |
$nid = $node['pid'];
|
| 182 |
if ($nid == $org_nid) {
|
| 183 |
$loop = TRUE;
|
| 184 |
break;
|
| 185 |
}
|
| 186 |
}
|
| 187 |
if ($loop) {
|
| 188 |
drupal_set_message(t('Node loop detected, move aborted.'),'error');
|
| 189 |
return;
|
| 190 |
}
|
| 191 |
}
|
| 192 |
// move the node in the pacs tree
|
| 193 |
db_query('UPDATE {node} SET pid = %d WHERE nid = %d',$dst_nid,$org_nid);
|
| 194 |
if (variable_get('pacs_sync_book',0)) {
|
| 195 |
// if the node is a book page, update the book page hierarchy too
|
| 196 |
db_query("UPDATE {book} SET parent = %d WHERE nid = %d",$dst_nid,$org_nid);
|
| 197 |
}
|
| 198 |
// update the new branch grants
|
| 199 |
$roles = user_roles();
|
| 200 |
foreach ($roles as $rid => $role) {
|
| 201 |
$par = pacs_node($dst_nid,$rid);
|
| 202 |
pacs_set_branch_grants($org_nid,$rid,$par['grants']);
|
| 203 |
}
|
| 204 |
return;
|
| 205 |
}
|
| 206 |
|
| 207 |
/**
|
| 208 |
* pacs_sync_book()
|
| 209 |
*/
|
| 210 |
function pacs_sync_book() {
|
| 211 |
$res = db_query('SELECT nid,parent FROM {book}');
|
| 212 |
while ($row = db_fetch_array($res)) {
|
| 213 |
db_query("UPDATE {node} SET pid = %d WHERE nid = %d", $row['parent'], $row['nid']);
|
| 214 |
}
|
| 215 |
}
|
| 216 |
|
| 217 |
/**
|
| 218 |
* pacs_breadcrumb()
|
| 219 |
*/
|
| 220 |
function pacs_breadcrumb($nid) {
|
| 221 |
$bc = array();
|
| 222 |
|
| 223 |
$node = pacs_node($nid,1);
|
| 224 |
pacs_loop('breadcrumb');
|
| 225 |
while ($node['pid']) {
|
| 226 |
if (pacs_loop('breadcrumb',$node['pid'])) break;
|
| 227 |
$node = pacs_node($node['pid'],1);
|
| 228 |
$bc[] = l($node['title'],'node/'.$node['nid']);
|
| 229 |
}
|
| 230 |
$bc[] = l(t('Home'),'');
|
| 231 |
return array_reverse($bc);
|
| 232 |
}
|
| 233 |
|
| 234 |
/**
|
| 235 |
* pacs_grants_to_perm()
|
| 236 |
*/
|
| 237 |
function pacs_grants_to_perm($grants) {
|
| 238 |
// grants: 0 -> view, 1 -> update, 2 -> delete
|
| 239 |
if ($grants[2]) return 3;
|
| 240 |
if ($grants[1]) return 2;
|
| 241 |
if ($grants[0]) return 1;
|
| 242 |
return 0;
|
| 243 |
}
|
| 244 |
|
| 245 |
/**
|
| 246 |
* pacs_perm_to_grants()
|
| 247 |
*/
|
| 248 |
function pacs_perm_to_grants($perm) {
|
| 249 |
// grants: 0 -> view, 1 -> update, 2 -> delete
|
| 250 |
if ($perm == 3) return array(1,1,1);
|
| 251 |
if ($perm == 2) return array(1,1,0);
|
| 252 |
if ($perm == 1) return array(1,0,0);
|
| 253 |
return array(0,0,0);
|
| 254 |
}
|
| 255 |
|
| 256 |
/**
|
| 257 |
* pacs_get_tree_nodes()
|
| 258 |
*/
|
| 259 |
function pacs_get_tree_nodes($nid,$rid) {
|
| 260 |
$tree = array();
|
| 261 |
if ($nid) {
|
| 262 |
// current node is not root
|
| 263 |
$tree['cur'] = pacs_node($nid,$rid);
|
| 264 |
$tree['par'] = pacs_node($tree['cur']['pid'],$rid);
|
| 265 |
if ($list = pacs_child_list($tree['cur']['pid'])) {
|
| 266 |
foreach ($list as $n) $tree['sib'][] = pacs_node($n,$rid);
|
| 267 |
}
|
| 268 |
if ($list = pacs_child_list($tree['cur']['nid'])) {
|
| 269 |
foreach ($list as $n) $tree['chd'][] = pacs_node($n,$rid);
|
| 270 |
}
|
| 271 |
} else {
|
| 272 |
// current node is root
|
| 273 |
$tree['cur'] = $tree['sib'][] = pacs_node(0,$rid);
|
| 274 |
$tree['par'] = NULL;
|
| 275 |
if ($list = pacs_child_list(0,$rid)) {
|
| 276 |
foreach ($list as $n) $tree['chd'][] = pacs_node($n,$rid);
|
| 277 |
}
|
| 278 |
}
|
| 279 |
return $tree;
|
| 280 |
}
|
| 281 |
|
| 282 |
function pacs_display_tree_node($node,$rid,$class) {
|
| 283 |
$output = '';
|
| 284 |
$url = 'node/'.$node['nid'].'/tree';
|
| 285 |
$id = 'g'.pacs_grants_to_perm($node['grants']);
|
| 286 |
$output .= '<li class="'.$class.'">';
|
| 287 |
$output .= l($node['title'],$url,array('class' => $class, 'id' => $id));
|
| 288 |
if ($node['stops'][$rid]) $output .= '<b class="prm">*</b>';
|
| 289 |
return $output;
|
| 290 |
}
|
| 291 |
|
| 292 |
/**
|
| 293 |
* pacs_get_tree()
|
| 294 |
*/
|
| 295 |
function pacs_tree($nid) {
|
| 296 |
global $user;
|
| 297 |
|
| 298 |
$output = '';
|
| 299 |
$output .= '<div id="tree-page">';
|
| 300 |
|
| 301 |
// tree actions
|
| 302 |
|
| 303 |
if (isset($_SESSION['pacs_grants_undo']) && (isset($_GET['role']) || ($_SESSION['pacs_grants_undo']['nid'] != $nid))) unset($_SESSION['pacs_grants_undo']);
|
| 304 |
if (isset($_GET['role'])) $_SESSION['pacs_role'] = $_GET['role'];
|
| 305 |
if (!isset($_SESSION['pacs_role'])) $_SESSION['pacs_role'] = 1;
|
| 306 |
if (pacs_manage_tree_perm($nid)) {
|
| 307 |
if (isset($_GET['perm']) && ($_SESSION['pacs_role'] > 0)) {
|
| 308 |
$node = pacs_node($nid,$_SESSION['pacs_role']);
|
| 309 |
// make a grants undo button
|
| 310 |
$_SESSION['pacs_grants_undo'] = $node; // the original node
|
| 311 |
// set the new permission on the active role
|
| 312 |
if ($_GET['perm'] == -1) {
|
| 313 |
// inherit from parent
|
| 314 |
$par = pacs_node($node['pid'],$_SESSION['pacs_role']);
|
| 315 |
$node['grants'] = $par['grants'];
|
| 316 |
unset($node['stops'][$_SESSION['pacs_role']]);
|
| 317 |
} else {
|
| 318 |
// set local permission
|
| 319 |
$node['grants'] = pacs_perm_to_grants($_GET['perm']);
|
| 320 |
$node['stops'][$_SESSION['pacs_role']] = 1;
|
| 321 |
}
|
| 322 |
pacs_update_node($node);
|
| 323 |
pacs_set_branch_grants($nid,$_SESSION['pacs_role'],$node['grants']);
|
| 324 |
}
|
| 325 |
if ($_GET['op_cancel']) unset($_SESSION['pacs_orig']);
|
| 326 |
if ($_GET['op_move']) {
|
| 327 |
pacs_move_node($_SESSION['pacs_orig']['nid'],$nid);
|
| 328 |
unset($_SESSION['pacs_orig']);
|
| 329 |
}
|
| 330 |
}
|
| 331 |
if (isset($_GET['undo']) && isset($_SESSION['pacs_grants_undo'])) {
|
| 332 |
$node = $_SESSION['pacs_grants_undo'];
|
| 333 |
pacs_update_node($node);
|
| 334 |
pacs_set_branch_grants($node['nid'],$_SESSION['pacs_role'],$node['grants']);
|
| 335 |
unset($_SESSION['pacs_grants_undo']);
|
| 336 |
}
|
| 337 |
|
| 338 |
// displaying the tree
|
| 339 |
|
| 340 |
$trid = $_SESSION['pacs_role'];
|
| 341 |
$tree = pacs_get_tree_nodes($nid,$trid);
|
| 342 |
if ($_GET['op_set_orig']) $_SESSION['pacs_orig'] = $tree['cur'];
|
| 343 |
drupal_set_title($tree['cur']['title']);
|
| 344 |
|
| 345 |
////////////////////////////////////////////////////////////////////////
|
| 346 |
$output .= '<fieldset class="tree"><legend>'.t('Pacs Tree').'</legend>';
|
| 347 |
|
| 348 |
// the parent node
|
| 349 |
if ($par = $tree['par']) {
|
| 350 |
$output .= '<ul>'.pacs_display_tree_node($par,$trid,'parent');
|
| 351 |
}
|
| 352 |
$output .= '<ul>';
|
| 353 |
foreach ($tree['sib'] as $sib) {
|
| 354 |
if ($sib['nid'] == $tree['cur']['nid']) {
|
| 355 |
// current node
|
| 356 |
$output .= pacs_display_tree_node($sib,$trid,'current');
|
| 357 |
if (!$tree['chd']) continue;
|
| 358 |
// child nodes
|
| 359 |
$output .= '<ul>';
|
| 360 |
foreach ($tree['chd'] as $chd) {
|
| 361 |
$output .= pacs_display_tree_node($chd,$trid,'child').'</li>';
|
| 362 |
}
|
| 363 |
$output .= '</ul>';
|
| 364 |
} else {
|
| 365 |
// sibling nodes
|
| 366 |
$output .= pacs_display_tree_node($sib,$trid,'sibling');
|
| 367 |
}
|
| 368 |
$output .= '</li>';
|
| 369 |
}
|
| 370 |
$output .= '</ul>';
|
| 371 |
if ($tree['par']) $output .= '</li></ul>';
|
| 372 |
$output .= '</fieldset>';
|
| 373 |
|
| 374 |
/////////////////////////////////////////////////////////////////////////////
|
| 375 |
$output .= '<fieldset class="roles"><legend>'.t('Role Selector').'</legend>';
|
| 376 |
$url = "node/$nid/tree"; // default link url
|
| 377 |
$class = 'role';
|
| 378 |
if ($trid == 0) $class = 'sel-role';
|
| 379 |
$output .= l(t('me'),$url,
|
| 380 |
array('id' => 'own', 'class' => $class, 'title' => t('my own user grants')), 'role=0');
|
| 381 |
$roles = user_roles();
|
| 382 |
foreach ($roles as $rid => $role) {
|
| 383 |
$class = 'role';
|
| 384 |
if ($trid == $rid) $class = 'sel-role';
|
| 385 |
$output .= l($role,$url,array('class' => $class,'title' => t('role grants')),'role='.$rid);
|
| 386 |
}
|
| 387 |
$output .= '</fieldset>';
|
| 388 |
|
| 389 |
if (pacs_manage_tree_perm($nid)) {
|
| 390 |
if ($trid > 0) {
|
| 391 |
////////////////////////////////////////////////////////////////////////////////
|
| 392 |
$output .= '<fieldset class="perms"><legend>'.t('Set Branch Grants').'</legend>';
|
| 393 |
if ($nid) {
|
| 394 |
// no inherit for the root pseudo node
|
| 395 |
$output .= l('inherit',$url,array('id' => 'gi','class' => 'perm',
|
| 396 |
'title' => t('inherit from parent')),'perm=-1');
|
| 397 |
}
|
| 398 |
$output .= l(t('none'), $url,array('id' => 'g0','class' => 'perm',
|
| 399 |
'title' => t('no grants')),'perm=0');
|
| 400 |
$output .= l(t('view'), $url,array('id' => 'g1','class' => 'perm',
|
| 401 |
'title' => t('view')),'perm=1');
|
| 402 |
$output .= l(t('update'),$url,array('id' => 'g2','class' => 'perm',
|
| 403 |
'title' => t('view+update')),'perm=2');
|
| 404 |
$output .= l(t('manage'),$url,array('id' => 'g3','class' => 'perm',
|
| 405 |
'title' => t('view+update+manage')),'perm=3');
|
| 406 |
if (isset($_SESSION['pacs_grants_undo'])) {
|
| 407 |
$output .= l(t('undo'),$url,
|
| 408 |
array('id' => 'g'.pacs_grants_to_perm($_SESSION['pacs_grants_undo']['grants']),
|
| 409 |
'class' => 'undo','title' => t('undo the previous grant setting')),'undo=1');
|
| 410 |
}
|
| 411 |
$output .= '</fieldset>';
|
| 412 |
}
|
| 413 |
/////////////////////////////////////////////////////////////////////////////
|
| 414 |
$output .= '<fieldset class="move"><legend>'.t('Move Node').'</legend>';
|
| 415 |
if ($_SESSION['pacs_orig']) {
|
| 416 |
$output .= l(t('Cancel'),$url,array('class' => 'button'),'op_cancel=1').t(' or ');
|
| 417 |
$output .= l(t('Move'),$url,array('class' => 'button'),'op_move=1');
|
| 418 |
$output .= t(
|
| 419 |
'node <span class="sel">%o </span> under node <span class="sel">%d </span>',
|
| 420 |
array('%o' => $_SESSION['pacs_orig']['title'],'%d' => $tree['cur']['title'])
|
| 421 |
);
|
| 422 |
} else {
|
| 423 |
$output .= l(t('Select'),$url,array('class' => 'button'),'op_set_orig=1');
|
| 424 |
$output .= t('the <span class="sel">highlighted </span> node to move it in the tree.');
|
| 425 |
}
|
| 426 |
$output .= '</fieldset>';
|
| 427 |
///////////////////////////////////////////////////////////////////////////////////
|
| 428 |
$output .= '<fieldset class="move"><legend>'.t('Export/Import Branch').'</legend>';
|
| 429 |
$output .= l(t('export branch'),'pacs/export/'.$nid,array('class' => 'button'));
|
| 430 |
$output .= l(t('import branch'),'pacs/import/'.$nid,array('class' => 'button'));
|
| 431 |
$output .= l(t('delete branch'),'pacs/delete/'.$nid,array('class' => 'button'));
|
| 432 |
$output .= '</fieldset>';
|
| 433 |
} else {
|
| 434 |
if (isset($_SESSION['pacs_grants_undo'])) {
|
| 435 |
/////////////////////////////////////////////////////////////////////////////////
|
| 436 |
$output .= '<fieldset class="perms"><legend>'.t('Set Branch Grants').'</legend>';
|
| 437 |
$output .= l(t('undo'),$url,array('id' => 'g'.$_SESSION['pacs_grants_undo']['gid'],
|
| 438 |
'class' => 'undo','title' => t('undo the previous grant setting')),'undo=1');
|
| 439 |
$output .= '</fieldset>';
|
| 440 |
}
|
| 441 |
}
|
| 442 |
$output .= '<div class="help">'.l('help','admin/help/pacs').'</div>';
|
| 443 |
print theme('page',$output);
|
| 444 |
}
|
| 445 |
|
| 446 |
/**
|
| 447 |
* pacs_inc_help()
|
| 448 |
*/
|
| 449 |
function pacs_inc_help($section='') {
|
| 450 |
$output = '';
|
| 451 |
$output .= '<div class="pacs-help">';
|
| 452 |
switch ($section) {
|
| 453 |
case 'admin/help#pacs':
|
| 454 |
$output .= '<a name="intro"></a><h4>'.t('The Tree Access Module').'</h4>';
|
| 455 |
$output .= '<p>'.t('Under pacs, every drupal node turns in a <i>container</i> wich can hold normal content but also other nodes of any type, much like a directory in an apache web server.').'</p>';
|
| 456 |
$output .= '<p>'.t('You can control the access permissions to each of the nodes for each defined user role. Nodes with no explicit permission setting <i>inherit</i> them from its parent node, like in a directory tree.').'</p>';
|
| 457 |
$output .= '<p>'.t('This means that if you set permissions on one node you are actually setting these permissions on a whole branch, composed by this node and all of his descendants (child nodes), up to the next one with its own permission settings.').'</p>';
|
| 458 |
$output .= '<p>'.t('Pacs works with any type of nodes.').'</p>';
|
| 459 |
$output .= '<a name="node_view"></a><h4>'.t('The Node View').'</h4>';
|
| 460 |
$output .= '<p>'.t('Under pacs, when viewing a node, the page <i>breadcrumb</i> will show the position of the node in the pacs tree instead of the normal menu items sequence.').'</p>';
|
| 461 |
$output .= '<p>'.t('If you have the <i>view tree</i> system permission there will be a new <b>tree</b> tab. Clicking on this tab will open a nice representation of the tree structure.').'</p>';
|
| 462 |
$output .= '<p>'.t('If the current node has <i>child nodes</i>, their titles will show up as a list of page footer links. (not for book pages)').'</p>';
|
| 463 |
$output .= '<p>'.t('If you have the appropriate permissions, the page footer will also show a <i>new node</i> link that lets you create a new node of any type under the current node. (not for book pages)').'</p>';
|
| 464 |
$output .= '<p>'.t('Clicking on the standard <i>create content</i> menu item lets you create a new node under the tree root.').'</p>';
|
| 465 |
$output .= '<a name="tree_view"></a><h4>'.t('The Tree View').'</h4>';
|
| 466 |
$output .= '<p>'.t('Clicking on the <i>tree</i> tab will open a representation of the tree structure, where the permissions are represented by the color of each node.').'</p>';
|
| 467 |
$output .= '<ul>';
|
| 468 |
$output .= '<li>'.t('Click on a <i>node button</i> to make that node <i>current</i> and to see its <i>child nodes</i>.').'</li>';
|
| 469 |
$output .= '<li>'.t('Click on a <i>role button</i> to see the permissions for that role or click on the <i>me</i> button to see your own permissions (the combination of all your roles) in the tree').'</li>';
|
| 470 |
$output .= '</ul>';
|
| 471 |
$output .= '<p>'.t('If you have the <i>manage tree</i> system permission, there will also be command buttons to set permissions and to move the nodes inside the tree. But only if you also have the <i>manage</i> pacs permission on that branch.').'</p>';
|
| 472 |
$output .= '<ul>';
|
| 473 |
$output .= '<li>'.t('To move a node, make it the <i>current</i> node by clicking on it and then click on the <i>Select</i> button. Now chose the destination node by making it <i>current</i> and then click on the <i>Move</i> button. The permissions of the moved node and all his child nodes (the node branch) will be updated accordingly to its new position in the tree.').'</li>';
|
| 474 |
$output .= '<li>'.t('To change the permissions for a role on a branch, first chose the role (not <i>me</i>) and then click on the desired permission button. The permissions for that role will be updated on the whole branch. An <i>undo</i> button will appear and remain there until you use it or chose any other command. It can be used to revert the last permission change even if you mistakenly droped your own <i>manage</i> permission. (Don\'t miss the opportunity, it is a one shot gunn)').'</li>';
|
| 475 |
$output .= '</ul>';
|
| 476 |
$output .= '<a name="book_pages"></a><h4>'.t('Pacs and Book Pages').'</h4>';
|
| 477 |
$output .= '<p>'.t('Book pages, the nodes provided by the Book Module, have their own hierarchical structure. To avoid possible inconsistencies between the pacs and the book hierarchies, pacs maintains them both automatically synchronized. So, if you extend or update your book structure, pacs will update its tree accordingly. This feature is optional. See %sp',array('%sp' => l(t('The Settings Page'),'admin/help/pacs#settings'))).'</p>';
|
| 478 |
$output .= '<a name="system_permissions"></a><h4>'.t('Pacs Access Rights and System Permissions').'</h4>';
|
| 479 |
$output .= '<p>'.t('The pacs behavior is heavily affected by your system permissions settings, but there are a few easy rules: (See %ac)', array('%ac' => l(t('access control'),'admin/access'))).'</p>';
|
| 480 |
$output .= '<ul>';
|
| 481 |
$output .= '<li>'.t('To be able to create new nodes of some type one user <b>must</b> have the approppriate <i>create</i> system permission. Example: <i>create pages</i> to be able to create pages, or <i>create book pages</i> to be able to create book pages.').'</li>';
|
| 482 |
$output .= '<li>'.t('To let pacs assume full control over the <i>view</i>, <i>update</i> and <i>delete</i> permissions for one node type, you <b>must not</b> assign correspondent system permissions to any user role. Example: You must disable permissions such as <i>edit own pages</i>, <i>edit own stories</i> and <i>edit own book pages</i>, etc, for all user roles.').'</li>';
|
| 483 |
$output .= '<li>'.t('An user must have the <i>view tree</i> system permission to enable the <i>tree</i> tab in node views.').'</li>';
|
| 484 |
$output .= '<li>'.t('An user must have the <i>manage tree</i> system permission to be able to set permissions and move nodes (only in in the branches where he also has the <i>manage</i> pacs access permission).').'</li>';
|
| 485 |
$output .= '<li>'.t('To see <i>this help page</i>, a user must have the <i>access administration pages</i> system permission').'</li>';
|
| 486 |
$output .= '</ul>';
|
| 487 |
$output .= '<a name="perm"></a><h4>'.t('The Access Permissions').'</h4>';
|
| 488 |
$output .= '<p>'.t('You can set permissions for each user role on any node in the tree. If no access permission is set on a node, it inherits the permissions from the parent node. So, access permissions propagate downwards the tree up to the next node wich have its own permission definition for a particular role').'</p>';
|
| 489 |
$output .= '<p>'.t('If a user belongs to more than one role, pacs will grant him the permissions corresponding to the role with the highest permissions on each node. In other words, the user will have the <b>manage</b> permission (the highest possible access permission) if at least one of his roles has this permission. And his permission will only be <b>none</b> if all of his roles have this setting.').'</p>';
|
| 490 |
$output .= '<p>'.t('Pacs permissions are progressive, meaning that if you have the <i>update</i> permission you also have the <i>view</i> permission, and if you have the <i>manage</i> permission you also have <i>update</i> and <i>view</i> permissions.').'</p>';
|
| 491 |
$output .= '<p>'.t('Pacs provides 5 different levels of permissions:').'</p>';
|
| 492 |
$output .= '<p><b id="gi">'.t('inherit').'</b></p>';
|
| 493 |
$output .= '<p>'.t('The permissions for this node are <i>inherited</i> from its parent node. In fact, the inherit permission means that no permissions are set on this node for a given role.').'</p>';
|
| 494 |
$output .= '<p><b id="g0">'.t('none').'</b></p>';
|
| 495 |
$output .= t('None means <b>no</b> permissions. Users that have only roles with this permission on a branch can not see the branch.').'</p>';
|
| 496 |
$output .= '<p><b id="g1">'.t('view').'</b></p>';
|
| 497 |
$output .= '<p>'.t('Branches with this permission are visible to the users.').'</p>';
|
| 498 |
$output .= '<p><b id="g2">'.t('update').'</b></p>';
|
| 499 |
$output .= '<p>'.t('With the update permission the user can see and update the node, but not delete it or create new nodes.').'</p>';
|
| 500 |
$output .= '<p><b id="g3">'.t('manage').'</b></p>';
|
| 501 |
$output .= '<p>'.t('The manage access permission is a pacs extension for the standard drupal <i>delete</i> permission. With this permission, the user can <i>view</i>, <i>update</i> and <i>delete</i> nodes, but also <i>create</i> them, <i>move</i> them in the tree and set its access permissions').'</p>';
|
| 502 |
$output .= '<p>'.t('The <i>system administrator</i> (uid = 1) has all permissions inconditionally.').'</p>';
|
| 503 |
$output .= '<a name="settings"></a><h4>'.t('The Settings Page').'</h4>';
|
| 504 |
$output .= '<p>'.t('In the %url you can define if pacs should automatically keep itself in sync with the book page hierarchy.',array('%url' => l(t('pacs settings page'),'admin/settings/pacs'))).'</p>';
|
| 505 |
$output .= '<p>'.t('You can also syncronize a new pacs installation with a preexistent book structure or ressincronize a damaged structure.').'</p>';
|
| 506 |
$output .= '<p>'.t('Warning: The options above are available only if the <i>book module</i> is enabled.').'</p>';
|
| 507 |
break;
|
| 508 |
}
|
| 509 |
$output .= '</div>';
|
| 510 |
return $output;
|
| 511 |
}
|
| 512 |
|
| 513 |
function pacs_nodeadd($nid) {
|
| 514 |
$_SESSION['pacs_new_node_pid'] = $nid;
|
| 515 |
drupal_goto('node/add');
|
| 516 |
}
|
| 517 |
|
| 518 |
|
| 519 |
/****** DRUPAL HOOKS *************************************************/
|
| 520 |
|
| 521 |
|
| 522 |
/**
|
| 523 |
* Implementation of hook_perm().
|
| 524 |
*
|
| 525 |
* Valid permissions for this module
|
| 526 |
* @return array An array of valid permissions for the onthisdate module
|
| 527 |
*/
|
| 528 |
function pacs_perm() {
|
| 529 |
return array('view tree','manage tree');
|
| 530 |
}
|
| 531 |
|
| 532 |
/**
|
| 533 |
* Implementation of hook_help().
|
| 534 |
*/
|
| 535 |
function pacs_help($section='') {
|
| 536 |
switch ($section) {
|
| 537 |
case "admin/modules#description":
|
| 538 |
return t('Tree Access System. Lets you organize your content in a hierarchical tree and define the access rights to the branches for each user role.');
|
| 539 |
break;
|
| 540 |
case 'admin/help#pacs':
|
| 541 |
return pacs_inc_help($section);
|
| 542 |
break;
|
| 543 |
}
|
| 544 |
return NULL;
|
| 545 |
}
|
| 546 |
|
| 547 |
/**
|
| 548 |
* Implementation of hook_menu().
|
| 549 |
*/
|
| 550 |
function pacs_menu($may_cache) {
|
| 551 |
$items = array();
|
| 552 |
|
| 553 |
if (!$may_cache) {
|
| 554 |
|
| 555 |
$access = FALSE;
|
| 556 |
if (arg(0) == 'node') $access = pacs_view_tree_perm();
|
| 557 |
$items[] = array(
|
| 558 |
'path' => 'node/'.arg(1).'/tree',
|
| 559 |
'title' => t('tree'),
|
| 560 |
'callback' => 'pacs_tree',
|
| 561 |
'callback arguments' => array(arg(1)),
|
| 562 |
'access' => $access,
|
| 563 |
'weight' => 2,
|
| 564 |
'type' => MENU_LOCAL_TASK,
|
| 565 |
);
|
| 566 |
|
| 567 |
$access = FALSE;
|
| 568 |
if (arg(1) == 'nodeadd') $access = pacs_view_tree_perm();
|
| 569 |
$items[] = array(
|
| 570 |
'path' => 'pacs/nodeadd/'.arg(2),
|
| 571 |
'callback' => 'pacs_nodeadd',
|
| 572 |
'callback arguments' => array(arg(2)),
|
| 573 |
'access' => $access,
|
| 574 |
'type' => MENU_CALLBACK,
|
| 575 |
);
|
| 576 |
|
| 577 |
$access = FALSE;
|
| 578 |
if (arg(0) == 'pacs') $access = pacs_manage_tree_perm(arg(2));
|
| 579 |
$items[] = array(
|
| 580 |
'path' => 'pacs/export/'.arg(2),
|
| 581 |
'callback' => 'pacs_xml_export',
|
| 582 |
'callback arguments' => array(arg(2)),
|
| 583 |
'access' => $access,
|
| 584 |
'type' => MENU_CALLBACK,
|
| 585 |
);
|
| 586 |
$items[] = array(
|
| 587 |
'path' => 'pacs/import/'.arg(2),
|
| 588 |
'callback' => 'pacs_xml_import',
|
| 589 |
'callback arguments' => array(arg(2)),
|
| 590 |
'access' => $access,
|
| 591 |
'type' => MENU_CALLBACK,
|
| 592 |
);
|
| 593 |
$items[] = array(
|
| 594 |
'path' => 'pacs/delete/'.arg(2),
|
| 595 |
'callback' => 'pacs_delete_branch',
|
| 596 |
'callback arguments' => array(arg(2)),
|
| 597 |
'access' => $access,
|
| 598 |
'type' => MENU_CALLBACK,
|
| 599 |
);
|
| 600 |
|
| 601 |
}
|
| 602 |
|
| 603 |
// load style sheets on demand
|
| 604 |
if(strpos('.'.request_uri(),'/tree') > 0) {
|
| 605 |
theme('add_style','modules/pacs/pacs.css');
|
| 606 |
}
|
| 607 |
if(strpos('.'.request_uri(),'/help/pacs') > 0) {
|
| 608 |
theme('add_style','modules/pacs/help.css');
|
| 609 |
}
|
| 610 |
|
| 611 |
return $items;
|
| 612 |
}
|
| 613 |
|
| 614 |
/**
|
| 615 |
* Implementation of hook_settings().
|
| 616 |
*/
|
| 617 |
function pacs_settings() {
|
| 618 |
|
| 619 |
// action ////////////////////////
|
| 620 |
if ($_POST['op']) pacs_sync_book();
|
| 621 |
|
| 622 |
if (module_exist('book')) {
|
| 623 |
$form['book_sync'] = array(
|
| 624 |
'#type' => 'fieldset',
|
| 625 |
'#title' => t('pacs and book pages')
|
| 626 |
);
|
| 627 |
$form['book_sync']['pacs_sync_book'] = array(
|
| 628 |
'#type' => 'checkbox',
|
| 629 |
'#title' => t('synchronize the pacs tree with the book page hierarchies'),
|
| 630 |
'#default_value' => variable_get('pacs_sync_book',1),
|
| 631 |
'#description' => t('Enable this option to maintain your book page hierarchy automatically synchronized with the pacs tree.')
|
| 632 |
);
|
| 633 |
if (variable_get('pacs_sync_book',1)) {
|
| 634 |
$form['book_sync']['sync_now'] = array(
|
| 635 |
'#type' => 'button',
|
| 636 |
'#value' => t('synchronize now'),
|
| 637 |
'#suffix' => '<div>'.t('Click to synchronize your preexistent book page hierarchy or to resynchronize a damaged hierarchy. It will insert any existing book page hierarchy into the pacs tree.').'</div>'
|
| 638 |
);
|
| 639 |
}
|
| 640 |
} else {
|
| 641 |
variable_set('pacs_sync_book',0);
|
| 642 |
}
|
| 643 |
return $form;
|
| 644 |
}
|
| 645 |
|
| 646 |
/**
|
| 647 |
* Implementation of hook_db_rewrite_sql().
|
| 648 |
*/
|
| 649 |
function pacs_db_rewrite_sql($query, $table, $field, $args) {
|
| 650 |
global $user;
|
| 651 |
|
| 652 |
// no sql_rewrite for the administrator
|
| 653 |
if ($user->uid == 1) return NULL;
|
| 654 |
|
| 655 |
switch ($field) {
|
| 656 |
case 'nid':
|
| 657 |
$gids = implode(',',array_keys($user->roles));
|
| 658 |
return array(
|
| 659 |
'join' => "INNER JOIN {node_access} AS xna ON $table.nid = xna.nid AND xna.realm = 'pacs'",
|
| 660 |
'where' => "xna.gid IN ($gids) AND xna.grant_view >= 1",
|
| 661 |
'distinct' => 1,
|
| 662 |
);
|
| 663 |
break;
|
| 664 |
}
|
| 665 |
return NULL;
|
| 666 |
}
|
| 667 |
|
| 668 |
/**
|
| 669 |
* Implementation of hook_link().
|
| 670 |
*/
|
| 671 |
function pacs_link($type, $node = 0, $teaser = 0) {
|
| 672 |
$links = array();
|
| 673 |
|
| 674 |
if ($teaser || ($type != 'node') || ($node->type == 'book')) {
|
| 675 |
$_SESSION['pacs_new_node_pid'] = 0;
|
| 676 |
return $links;
|
| 677 |
}
|
| 678 |
|
| 679 |
// new node link
|
| 680 |
if ($node->pacs['grants'][2]) {
|
| 681 |
$attrs = array('title' => t('Create a new node, under this node'), 'class' => 'new-node');
|
| 682 |
$links[] = '<b class="new-node">'.l(t('new node'),'pacs/nodeadd/'.$node->nid,$attrs).'</b>';
|
| 683 |
}
|
| 684 |
|
| 685 |
// child nodes listing
|
| 686 |
$list = array();
|
| 687 |
if ($list = pacs_child_list($node->nid)) {
|
| 688 |
foreach ($list as $nid) {
|
| 689 |
$pnode = pacs_node($nid);
|
| 690 |
if ($pnode['grants'][0]) $links[] = l($pnode['title'],"node/$nid",array('class' => 'pacs-link'));
|
| 691 |
}
|
| 692 |
}
|
| 693 |
|
| 694 |
return $links;
|
| 695 |
}
|
| 696 |
|
| 697 |
/**
|
| 698 |
* Implementation of hook_nodeapi().
|
| 699 |
*/
|
| 700 |
function pacs_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
|
| 701 |
switch ($op) {
|
| 702 |
case 'load':
|
| 703 |
unset($_SESSION['pacs_new_node_pid']);
|
| 704 |
// book pages have their own breadcrumb
|
| 705 |
if ($node->type != 'book') drupal_set_breadcrumb(pacs_breadcrumb($node->nid));
|
| 706 |
// inserting pacs related data
|
| 707 |
$nde = pacs_node($node->nid);
|
| 708 |
unset($nde['title'],$nde['type']); // drop redundant data
|
| 709 |
return array('pacs' => $nde);
|
| 710 |
break;
|
| 711 |
case 'update':
|
| 712 |
if ($node->type == 'book' && variable_get('pacs_sync_book',0)) {
|
| 713 |
$pnode = pacs_node($node->nid);
|
| 714 |
if ($pnode['pid'] != $node->parent) pacs_move_node($node->nid,$node->parent,0);
|
| 715 |
}
|
| 716 |
break;
|
| 717 |
case 'insert':
|
| 718 |
if (isset($node->pacs_nid)) break;
|
| 719 |
$pnode = array('nid' => $node->nid, 'pid' => 0, 'rid' => 0, 'stops' => array());
|
| 720 |
pacs_update_node($pnode);
|
| 721 |
$pid = 0;
|
| 722 |
if ($node->type == 'book' && variable_get('pacs_sync_book',0) && $node->parent) {
|
| 723 |
$pid = $node->parent;
|
| 724 |
} else {
|
| 725 |
if ($_SESSION['pacs_new_node_pid']) $pid = $_SESSION['pacs_new_node_pid'];
|
| 726 |
}
|
| 727 |
pacs_move_node($node->nid,$pid,0);
|
| 728 |
unset($_SESSION['pacs_new_node_pid']);
|
| 729 |
break;
|
| 730 |
case 'delete':
|
| 731 |
// move all child nodes to the parent
|
| 732 |
if ($list = pacs_child_list($node->nid)) {
|
| 733 |
foreach ($list as $nid) pacs_move_node($nid,$node->pacs['pid'],0);
|
| 734 |
}
|
| 735 |
// delete all node_access entries
|
| 736 |
db_query("DELETE FROM {node_access} WHERE realm = 'pacs' AND nid = %d",$node->nid);
|
| 737 |
break;
|
| 738 |
}
|
| 739 |
}
|
| 740 |
|
| 741 |
/**
|
| 742 |
* Implementation of hook_node_grants().
|
| 743 |
*/
|
| 744 |
function pacs_node_grants($user, $op) {
|
| 745 |
if (isset($user->roles)) return array('pacs' => array_keys($user->roles));
|
| 746 |
return array();
|
| 747 |
}
|