/[drupal]/contributions/modules/pacs/pacs.module
ViewVC logotype

Contents of /contributions/modules/pacs/pacs.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.5 - (show annotations) (download) (as text)
Mon Jun 26 23:54:29 2006 UTC (3 years, 4 months ago) by peterone
Branch: MAIN
CVS Tags: HEAD
Changes since 1.4: +49 -16 lines
File MIME type: text/x-php
xml import/export
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 }

  ViewVC Help
Powered by ViewVC 1.1.2