View source
<?php
define('TAXONOMY_ACCESS_MAX_UPDATE', 500);
function _taxonomy_access_user_roles() {
static $roles;
if (!is_array($roles)) {
$roles = user_roles();
}
return $roles;
}
function taxonomy_access_enable() {
global $db_type;
switch ($db_type) {
case 'mysql':
case 'mysqli':
db_query('DELETE ta FROM {term_access} ta LEFT JOIN {term_data} td ON ta.tid = td.tid WHERE ta.tid <> 0 AND ISNULL(td.tid)');
db_query('DELETE tad FROM {term_access_defaults} tad LEFT JOIN {vocabulary} v ON tad.vid = v.vid WHERE tad.vid <> 0 AND ISNULL(v.vid)');
db_query('DELETE ta FROM {term_access} ta LEFT JOIN {role} r ON ta.rid = r.rid WHERE ISNULL(r.rid)');
db_query('DELETE tad FROM {term_access_defaults} tad LEFT JOIN {role} r ON tad.rid = r.rid WHERE ISNULL(r.rid)');
break;
case 'pgsql':
$queries = array(
'tax' => "SELECT ta.tid,ta.rid FROM {term_access} ta LEFT JOIN {term_data} td ON ta.tid = td.tid WHERE ta.tid <> 0 AND td.tid IS NULL",
'tadx' => "SELECT tad.vid,tad.rid FROM {term_access_defaults} tad LEFT JOIN {vocabulary} v ON tad.vid = v.vid WHERE tad.vid <> 0 AND v.vid IS NULL",
'tar' => "SELECT ta.tid,ta.rid FROM {term_access} ta LEFT JOIN {role} r ON ta.rid = r.rid WHERE r.rid IS NULL",
'tadr' => "SELECT tad.vid,tad.rid FROM {term_access_defaults} tad LEFT JOIN {role} r ON tad.rid = r.rid WHERE r.rid IS NULL",
);
foreach ($queries as $type => $sql) {
$result = db_query($sql);
while ($args = db_fetch_array($result)) {
if ($args) {
if ($type == 'tax' || $type == 'tar') {
db_query("DELETE FROM {term_access} WHERE tid = %d AND rid = %d", $args);
}
else {
db_query("DELETE FROM {term_access_defaults} WHERE vid = %d AND rid = %d", $args);
}
}
}
}
break;
}
}
function taxonomy_access_init() {
if (arg(0) == 'admin') {
$path = drupal_get_path('module', 'taxonomy_access');
include_once $path . '/taxonomy_access.admin.inc';
drupal_add_css($path . '/admin.css');
}
}
function taxonomy_access_theme() {
return array(
'taxonomy_access_admin_form' => array(
'arguments' => array(
'form' => NULL,
),
),
);
}
function taxonomy_access_menu() {
$items = array();
$items['admin/user/taxonomy_access'] = array(
'title' => 'Taxonomy access permissions',
'description' => 'Taxonomy-based access control for content',
'page callback' => 'taxonomy_access_admin',
'access arguments' => array(
'administer permissions',
),
);
$items['admin/user/taxonomy_access/delete'] = array(
'type' => MENU_CALLBACK,
'page callback' => 'drupal_get_form',
'page arguments' => array(
'taxonomy_access_admin_delete_role',
),
'access arguments' => array(
'administer permissions',
),
);
$items['admin/user/taxonomy_access/edit'] = array(
'type' => MENU_CALLBACK,
'page callback' => 'drupal_get_form',
'page arguments' => array(
'taxonomy_access_admin_form',
),
'access arguments' => array(
'administer permissions',
),
);
return $items;
}
function taxonomy_access_taxonomy($op, $type, $array = NULL) {
switch ($op) {
case 'delete':
static $del_vocab;
static $del_term;
static $affected_nodes;
static $descendants;
if (!isset($del_vocab)) {
$del_vocab = _taxonomy_access_del_vocabulary();
}
if (!isset($del_term)) {
$del_term = _taxonomy_access_del_term();
}
if (!isset($affected_nodes)) {
$affected_nodes = _taxonomy_access_cache_affected_nodes();
}
if (!isset($descendants) && $del_term) {
$descendants = _taxonomy_access_get_descendants($del_term);
}
if ($type == 'term') {
db_query("DELETE FROM {term_access} WHERE tid = '%d'", $array['tid']);
}
if ($type == 'vocabulary') {
db_query("DELETE FROM {term_access_defaults} WHERE vid = '%d'", $array['vid']);
}
if ($del_vocab) {
if ($type == 'vocabulary') {
_taxonomy_access_node_access_update($affected_nodes);
}
}
elseif ($del_term) {
$key = array_search($array['tid'], $descendants);
if (!($key === FALSE)) {
unset($descendants[$key]);
}
if (sizeof($descendants) == 0) {
_taxonomy_access_node_access_update($affected_nodes);
}
}
else {
node_access_needs_rebuild(TRUE);
}
break;
}
return;
}
function taxonomy_access_form_alter(&$form, $form_state, $form_id) {
if ($form['#id'] == 'node-form' && is_numeric($form['nid']['#value'])) {
$form['tac_protected_terms'] = array(
'#type' => 'value',
'#value' => taxonomy_access_preserve_terms($form['#node']),
);
}
}
function taxonomy_access_form_taxonomy_form_term_alter(&$form, &$form_state) {
$form['#submit'] = array(
'taxonomy_access_term_submit',
);
}
function taxonomy_access_form_taxonomy_vocabulary_confirm_delete_alter(&$form, &$form_state) {
$form['#submit'] = array(
'taxonomy_access_vocabulary_delete_submit',
);
}
function taxonomy_access_term_submit(&$form, &$form_state) {
if ($form_state['clicked_button']['#value'] == t('Delete')) {
if ($form_state['values']['delete'] === TRUE) {
$tid = $form_state['values']['tid'];
_taxonomy_access_del_term($tid);
$affected_nodes = _taxonomy_access_get_nodes_for_term($tid, TRUE);
_taxonomy_access_cache_affected_nodes($affected_nodes);
return taxonomy_term_confirm_delete_submit($form, $form_state);
}
$form_state['rebuild'] = TRUE;
$form_state['confirm_delete'] = TRUE;
return;
}
else {
taxonomy_form_term_submit($form, $form_state);
}
}
function taxonomy_access_vocabulary_delete_submit(&$form, &$form_state) {
$vid = $form_state['values']['vid'];
_taxonomy_access_del_vocabulary($vid);
$affected_nodes = _taxonomy_access_get_nodes_for_vocabulary($vid);
_taxonomy_access_cache_affected_nodes($affected_nodes);
return taxonomy_vocabulary_confirm_delete_submit($form, $form_state);
}
function taxonomy_access_node_grants($user, $op) {
return array(
'term_access' => array_keys(is_array($user->roles) ? $user->roles : array(
1 => 'anonymous user',
)),
);
}
function taxonomy_access_node_access_records($node) {
$grants = array();
$result = db_query('SELECT tadg.rid,
BIT_OR(COALESCE( ta.grant_view, tad.grant_view, tadg.grant_view )) AS grant_view,
BIT_OR(COALESCE( ta.grant_update, tad.grant_update, tadg.grant_update )) AS grant_update,
BIT_OR(COALESCE( ta.grant_delete, tad.grant_delete, tadg.grant_delete )) AS grant_delete
FROM {term_node} tn
INNER JOIN {term_data} t ON t.tid = tn.tid
INNER JOIN {term_access_defaults} tadg ON tadg.vid = 0
LEFT JOIN {term_access_defaults} tad ON tad.vid = t.vid AND tad.rid = tadg.rid
LEFT JOIN {term_access} ta ON ta.tid = t.tid AND ta.rid = tadg.rid
WHERE tn.vid = %d
GROUP BY tadg.rid', $node->vid);
if (!db_affected_rows($result)) {
$result = db_query('SELECT n.nid, tadg.rid AS rid, tadg.grant_view AS grant_view, tadg.grant_update AS grant_update, tadg.grant_delete AS grant_delete
FROM {node} n INNER JOIN {term_access_defaults} tadg ON tadg.vid = 0
WHERE n.nid = %d', $node->nid);
}
while ($row = db_fetch_array($result)) {
$grants[] = array(
'realm' => 'term_access',
'gid' => $row['rid'],
'grant_view' => $row['grant_view'] == 1 ? 1 : 0,
'grant_update' => $row['grant_update'] == 1 ? 1 : 0,
'grant_delete' => $row['grant_delete'] == 1 ? 1 : 0,
'priority' => 0,
);
}
return $grants;
}
function taxonomy_access_nodeapi(&$node, $op, $arg = 0) {
switch ($op) {
case 'presave':
break;
case 'update':
taxonomy_access_restore_terms($node->nid, $node->vid, $node->tac_protected_terms);
break;
case 'delete':
node_access_write_grants($node, array(), 'term_access');
break;
}
}
function taxonomy_access_db_rewrite_sql($query, $table, $field) {
if (!user_access('administer taxonomy') && ($field == 'vid' || $field == 'tid')) {
if ($table == 'node_revisions') {
return array();
}
global $user;
if (arg(0) == "admin") {
$op = arg(1) == 'node' && (arg(2) == 'add' || arg(3) == 'edit') ? 'create' : 'list';
}
else {
$op = arg(0) == 'node' && (arg(1) == 'add' || arg(2) == 'edit') ? 'create' : 'list';
}
static $taxonomy_access_sql_clause;
$clause = array();
if (!isset($taxonomy_access_sql_clause)) {
$taxonomy_access_sql_clause = array();
}
if (!isset($taxonomy_access_sql_clause[$op][$field])) {
if (isset($user) && is_array($user->roles)) {
$rids = array_keys($user->roles);
}
else {
$rids[] = 1;
}
$sql = db_query('SELECT t.tid AS tid, t.vid AS vid FROM {term_data} t
INNER JOIN {term_access_defaults} tdg ON tdg.vid=0
LEFT JOIN {term_access_defaults} td ON td.vid=t.vid AND td.rid=tdg.rid
LEFT JOIN {term_access} ta ON ta.tid=t.tid AND ta.rid=tdg.rid
WHERE tdg.rid IN (' . db_placeholders($rids, 'int') . ')
GROUP BY t.tid, t.vid
HAVING BIT_OR(COALESCE(
ta.' . db_escape_table("grant_{$op}") . ',
td.' . db_escape_table("grant_{$op}") . ',
tdg.' . db_escape_table("grant_{$op}") . '
)) > 0', $rids);
$tids = array();
$vids = array();
while ($result = db_fetch_object($sql)) {
$tids[] = $result->tid;
$vids[$result->vid] = $result->vid;
}
if ($op == 'create') {
$sql = db_query('SELECT vid FROM {vocabulary} WHERE required = 1 OR tags = 1');
while ($row = db_fetch_array($sql)) {
$vids[$row['vid']] = $row['vid'];
}
}
foreach ($tids as $key => $tid) {
$tids[$key] = (int) $tid;
}
foreach ($vids as $key => $vid) {
$vids[$key] = (int) $vid;
}
$clause[$op]['tid'] = isset($tids) ? implode("','", $tids) : '';
$clause[$op]['vid'] = isset($vids) ? implode("','", $vids) : '';
$taxonomy_access_sql_clause = $clause;
}
else {
$clause[$op][$field] = $taxonomy_access_sql_clause[$op][$field];
}
$return = array();
if ($clause[$op][$field]) {
$return['where'] = db_escape_table($table) . "." . db_escape_table($field) . " IN ('" . $clause[$op][$field] . "')";
}
else {
$return['where'] = db_escape_table($table) . "." . db_escape_table($field) . " IS NULL";
}
return $return;
}
else {
return array();
}
}
function taxonomy_access_views_api() {
return array(
'api' => 2,
'path' => drupal_get_path('module', 'taxonomy_access') . '/includes',
);
}
function _taxonomy_access_node_access_update($nids) {
if (!node_access_needs_rebuild()) {
node_access_needs_rebuild(TRUE);
$nids = array_unique($nids);
if (sizeof($nids) < TAXONOMY_ACCESS_MAX_UPDATE) {
foreach ($nids as $node) {
$loaded_node = node_load($node, NULL, TRUE);
if (!empty($loaded_node)) {
node_access_acquire_grants($loaded_node);
}
}
node_access_needs_rebuild(FALSE);
}
}
return TRUE;
}
function _taxonomy_access_cache_affected_nodes($affected_nodes = NULL) {
static $nodes = array();
if (isset($affected_nodes)) {
$nodes = array_merge($nodes, $affected_nodes);
}
else {
return $nodes;
}
}
function _taxonomy_access_get_nodes_for_role($rid) {
$nids = array();
$result = db_query('SELECT n.nid
FROM {term_node} n
LEFT JOIN {term_data} d ON n.tid = d.tid
LEFT JOIN {term_access} a ON n.tid = a.tid
LEFT JOIN {term_access_defaults} ad on ad.vid = d.vid
WHERE a.rid = %d OR ad.rid = %d', $rid, $rid);
while ($node = db_fetch_object($result)) {
$nids[] = $node->nid;
}
return $nids;
}
function _taxonomy_access_get_nodes_for_vocabulary($vid, $rid = NULL) {
$nids = array();
$query = "SELECT n.nid FROM {term_node} n\n LEFT JOIN {term_data} d ON n.tid = d.tid\n WHERE d.vid = %d ";
$args = array(
$vid,
);
if (!is_null($rid)) {
$r = db_query("SELECT a.tid FROM {term_access} a\n INNER JOIN {term_data} d ON d.tid = a.tid\n WHERE a.rid = %d AND d.vid = %d", $rid, $vid);
$tids = array();
while ($row = db_fetch_object($r)) {
$tids[] = $row->tid;
}
if (!empty($tids)) {
$query .= " AND n.tid NOT IN (" . db_placeholders($tids, 'int') . ")";
$args = array_merge($args, $tids);
}
}
$result = db_query($query, $args);
while ($node = db_fetch_object($result)) {
$nids[] = $node->nid;
}
return $nids;
}
function _taxonomy_access_get_nodes_for_term($tid, $get_children = FALSE) {
$nids = array();
$result = db_query("SELECT nid FROM {term_node} WHERE tid = %d", $tid);
while ($node = db_fetch_object($result)) {
$nids[] = $node->nid;
}
if ($get_children) {
$child_tids = _taxonomy_access_get_descendants($tid);
if (sizeof($child_tids) > 0) {
$child_r = db_query('SELECT nid FROM {term_node} WHERE tid IN ' . '(' . db_placeholders($child_tids, 'int') . ')', $child_tids);
while ($node = db_fetch_object($child_r)) {
$nids[] = $node->nid;
}
}
}
return $nids;
}
function _taxonomy_access_get_descendants($tid) {
static $descendants = array();
if (!isset($descendants[$tid])) {
$descendants[$tid] = array();
$term = taxonomy_get_term($tid);
$tree = taxonomy_get_tree($term->vid, $tid);
foreach ($tree as $term) {
$descendants[$tid][] = $term->tid;
}
}
return $descendants[$tid];
}
function _taxonomy_access_del_vocabulary($vid = NULL) {
static $deleted_vid = FALSE;
if (isset($vid)) {
$deleted_vid = $vid;
}
else {
return $deleted_vid;
}
}
function _taxonomy_access_del_term($tid = NULL) {
static $deleted_tid = FALSE;
if (isset($tid)) {
$deleted_tid = $tid;
}
else {
return $deleted_tid;
}
}
function taxonomy_access_set_term_grants($tid, $rid = NULL, $grants = NULL, $skip_nodes = FALSE) {
if (!isset($tid) or !is_numeric($rid)) {
return FALSE;
}
$row = new stdClass();
$row->tid = $tid;
if (isset($rid)) {
$row->rid = $rid;
}
if (isset($grants) && is_array($grants)) {
foreach ($grants as $op => $value) {
if (is_numeric($value)) {
$grant_name = "grant_{$op}";
$row->{$grant_name} = $value;
}
}
}
if (!$skip_nodes) {
$affected_nodes = _taxonomy_access_get_nodes_for_term($tid);
}
db_query("DELETE FROM {term_access} WHERE tid=%d AND rid=%d", $tid, $rid);
drupal_write_record('term_access', $row);
if (!empty($affected_nodes)) {
_taxonomy_access_cache_affected_nodes($affected_nodes);
}
}
function taxonomy_access_set_recursive_grants($tid, $rid = NULL, $grants = NULL) {
taxonomy_access_set_term_grants($tid, $rid, $grants);
$ran_tids = array();
$run_tids = array(
$tid,
);
while (count($run_tids) > 0) {
foreach ($run_tids as $run_key => $run_tid) {
if (!(array_search($run_tid, $ran_tids) === FALSE)) {
drupal_set_message(t("Loop detected for tid %run_tid. Stopping.", array(
'%run_tid' => $run_tid,
)));
$run_tids = array();
}
else {
$result = db_query('SELECT th.tid FROM {term_hierarchy} th WHERE th.parent = %d', $run_tid);
while ($row = db_fetch_array($result)) {
taxonomy_access_set_term_grants($row['tid'], $rid, $grants);
$run_tids[] = $row['tid'];
}
unset($run_tids[$run_key]);
$ran_tids[] = $run_tid;
}
}
}
}
function taxonomy_access_set_default_grants($vid, $rid = NULL, $grants = NULL, $skip_nodes = FALSE) {
if (!is_numeric($vid) || isset($rid) && !is_numeric($rid)) {
return FALSE;
}
$row = new stdClass();
$row->vid = $vid;
$row->rid = $rid;
if (isset($grants) && is_array($grants)) {
foreach ($grants as $op => $value) {
if (is_numeric($value)) {
$grant_name = "grant_{$op}";
$row->{$grant_name} = $value;
}
}
}
if (!$skip_nodes) {
if ($vid === 0) {
drupal_set_message(t("You have modified a global default, so you should see a message indicating that content access permissions need to be rebuilt. However, you can wait to do this until you have finished any other changes you wish to make to the Taxonomy Access Permissions."), 'warning');
node_access_needs_rebuild(TRUE);
}
else {
$affected_nodes = _taxonomy_access_get_nodes_for_vocabulary($vid, $rid);
}
}
db_query("DELETE FROM {term_access_defaults} WHERE vid = %d AND rid = %d", $vid, $rid);
drupal_write_record('term_access_defaults', $row);
if (!empty($affected_nodes)) {
_taxonomy_access_cache_affected_nodes($affected_nodes);
}
}
function taxonomy_access_preserve_terms($node) {
$nid = $node->nid;
static $tids = array();
if (!is_numeric($nid)) {
return array();
}
if (isset($tids[$nid])) {
return $tids[$nid];
}
$user_terms = taxonomy_node_get_terms($node);
$result = db_query('SELECT tid FROM {term_node} WHERE vid = %d', $node->vid);
$tids[$nid] = array();
while ($row = db_fetch_array($result)) {
if (!isset($user_terms[$row['tid']])) {
$tids[$nid][$row['tid']] = $row['tid'];
}
}
return $tids[$nid];
}
function taxonomy_access_restore_terms($nid, $vid, $protected_terms) {
if (isset($protected_terms)) {
$terms = $protected_terms;
if (count($terms)) {
$args = array(
$nid,
$vid,
);
$args = array_merge($args, $terms);
db_query('DELETE FROM {term_node} WHERE nid = %d AND vid = %d
AND tid IN (' . db_placeholders($terms, 'int') . ')', $args);
foreach ($terms as $tid) {
$row = new stdClass();
$row->nid = $nid;
$row->vid = $vid;
$row->tid = $tid;
drupal_write_record('term_node', $row);
}
}
}
}
function taxonomy_access_get_grants($rid) {
if (!isset($rid)) {
return FALSE;
}
if (isset($rid) && !is_numeric($rid)) {
$rid = db_result(db_query("SELECT rid FROM {role} WHERE name='%s'", $rid));
}
$result = db_query("SELECT * FROM {term_access} WHERE rid=%d", $rid);
$grants = array();
while ($grant = db_fetch_array($result)) {
$tid = $grant['tid'];
foreach ($grant as $key => $grant_val) {
if (strpos($key, 'grant_') !== FALSE) {
$grant_name = '';
$grant_name = str_replace('grant_', '', $key);
if (!isset($grants[$tid][$grant_name]) || !$grants[$tid][$grant_name]) {
$grants[$tid][$grant_name] = $grant_val;
}
}
}
}
return $grants;
}
function taxonomy_access_get_default_grants($rid) {
if (!is_numeric($rid)) {
return FALSE;
}
$result = db_query("SELECT * FROM {term_access_defaults} WHERE rid=%d", $rid);
$grants = array();
while ($grant = db_fetch_array($result)) {
$vid = $grant['vid'];
foreach ($grant as $key => $grant_val) {
if (strpos($key, 'grant_') !== FALSE) {
$grant_name = '';
$grant_name = str_replace('grant_', '', $key);
if (!isset($grants[$vid][$grant_name]) || !$grants[$vid][$grant_name]) {
$grants[$vid][$grant_name] = $grant_val;
}
}
}
}
return $grants;
}
function taxonomy_access_help($path, $arg) {
switch ($path) {
case 'admin/help#taxonomy_access':
$message = '';
$message .= '' . '<p>' . t('The Taxonomy Access Control module allows users to specify how each category can be used by various roles.') . '</p>' . '<p>' . t('Permissions can be set differently for each user role. Be aware that setting Taxonomy Access permissions works <em>only within one user role</em>.') . '</p>' . '<p>' . t('(For users with multiple user roles, see section <a href="#good-to-know">Good to know</a> below.)') . '</p><hr /><br />' . "<h3>" . t("On this page") . "</h3>" . "<ol>" . '<li><a href="#grant">' . t("Grant types") . '</a></li>' . '<li><a href="#perm">' . t("Permission options") . '</a></li>' . '<li><a href="#defaults">' . t("Global and vocabulary defaults") . '</a></li>' . '<li><a href="#good-to-know">' . t("Good to know") . '</a></li>' . "</ol><hr /><br />" . '<h3 id="grant">' . t("Grant types") . '</h3>' . '<p>' . t('On the category permissions page for each role, administrators can configure five types of permission for each term: <em>View, Update, Delete, Add tag</em> (formerly <em>Create</em>), and <em>View tag</em> (formerly <em>List</em>):') . '</p>' . _taxonomy_access_grant_help_table() . '<p>' . t('<em>View</em>, <em>Update</em>, and <em>Delete</em> control the node access system. <em>View Tag</em> and <em>Add Tag</em> control the terms themselves. (Note: In previous versions of Taxonomy Access Control, there was no <em>View Tag</em> permission its functionality was controlled by the <em>View</em> permission.)') . '</p><hr /><br />' . '<h3 id="perm">' . t("Permission options") . "</h3>" . '<p>' . t('<strong><em>View</em>, <em>Update</em>, and <em>Delete</em> have three options for each term:</strong> <em>Allow</em> (<acronym title="Allow">A</acronym>), <em>Ignore</em> (<acronym title="Ignore">I</acronym>), and <em>Deny</em> (<acronym title="Deny">D</acronym>). Indicate which rights each role should have for each term. If a node is tagged with multiple terms:') . '</p>' . "<ul>\n" . "<li>" . t('<em>Deny</em> (<acronym title="Deny">D</acronym>) overrides <em>Allow</em> (<acronym title="Allow">A</acronym>) within a role.') . "</li>" . "<li>" . t('Both <em>Allow</em> (<acronym title="Allow">A</acronym>) and <em>Deny</em> (<acronym title="Deny">D</acronym>) override <em>Ignore</em> (<acronym title="Ignore">I</acronym>) within a role.') . "</li>" . "<li>" . t('If a user has <strong>multiple roles</strong>, an <em>Allow</em> (<acronym title="Allow">A</acronym>) from one role <strong>will</strong> override a <em>Deny</em> (<acronym title="Deny">D</acronym>) in another. (For more information, see section <a href="#good-to-know">Good to know</a> below.)') . "</li>" . "</ul>\n\n" . '<p>' . t('<strong><em>Add Tag</em> and <em>View Tag</em> have only two options for each term:</strong> <em>Yes</em> (selected) or <em>No</em> (deselected). Indicate what each role should be allowed to do with each term.') . '</p>' . "<h4>" . t("Important notes") . "</h4>" . "<ol>" . "<li>" . t('Custom roles <strong>will</strong> inherit permissions from the <em>authenticated user</em> role. Be sure to <a href="@url">configure
the authenticated user</a> properly.', array(
"@url" => url("admin/user/taxonomy_access/edit/2"),
)) . "</li>\n" . '<li>' . "<p>" . t('The <em>Deny</em> directives are processed after the <em>Allow</em> directives. (<strong><em>Deny</em> overrides <em>Allow</em></strong>.)</em> So, if a multicategory node is in Categories "A" and "B" and a user has <em>Allow</em> permissions for <em>View</em> in Category "A" and <em>Deny</em> permissions for <em>View</em> in Category "B", then the user will NOT be permitted to <em>View</em> the node.') . '</p>' . '<p>' . t('<em>Access is denied by default.</em> So, if a multicategory node is in Categories "C" and "D" and a user has <em>Ignore</em> permissions for <em>View</em> in both Category "C" and "D", then the user will <strong>not</strong> be permitted to view the node.') . '</p>' . '<p>' . t('(If you are familiar with Apache mod_access, this permission system works similar to directive: <em>ORDER ALLOW, DENY</em>)') . '</p>' . "</li>" . "</ol>" . "<hr /><br />" . '<h3 id="defaults">' . t("Global and vocabulary defaults") . "</h3>" . '<p>' . t('This option, just underneath the vocabulary title, <em>sets the permission that will automatically be given</em> to the role, <em>for any new terms</em> that are added within the vocabulary. This includes terms that are added via free tagging.') . '</p><hr /><br />' . '<h3 id="good-to-know">' . t('Good to know') . '</h3>' . '<ol>' . '<li>' . '<p>' . t('<strong>Users with multiple user roles:</strong> Allow/Ignore/Deny options are interpreted <em>only within one user role</em>. When a user belongs to multiple user roles, then <strong>the user gets access if <em>any</em> of his/her user roles have the access granted.</strong>') . '</p>' . '<p>' . t('In this case, permissions for the given user are calculated so that the <em>permissions of ALL of his user roles are "OR-ed" together</em>, which means that <em>Allow</em> in one role will take precedence over <em>Deny</em> in the other. This is different from how node access permissions (for multi-category nodes) are handled <em>within one user role</em>, as noted above.') . '</p>' . '</li>' . '<li>' . '<p>' . t('<strong>Input formats:</strong> <em>Node editing/deleting is blocked</em>, even when the user has <em>Update</em> or <em>Delete</em> permission to the node, <em>when the user is not allowed to use a filter format</em> that the node was saved at.') . '</p>' . '</li>' . '</ol>' . '<hr /><br />';
return $message;
break;
}
}
function _taxonomy_access_grant_help_table() {
$header = array();
$rows = array();
$rows[] = array(
array(
'header' => TRUE,
'data' => t("View"),
),
"<p>" . t('Grants this role the ability to view nodes with the term. (Users must also have this permission to see <em class="perm">nodes</em> with the term listed in Views.)') . "</p>" . "<p>" . t('The role must <strong>have</strong> <em class="perm">access content</em> permission on the <a href="@path">permissions administration form</a>.', array(
'@path' => url('admin/user/permissions', array(
'fragment' => 'module-node',
)),
)),
);
$rows[] = array(
array(
'header' => TRUE,
'data' => t("Update") . ", " . t("Delete"),
),
"<p>" . t("Grants this role the ability to edit or delete nodes with the term, respectively.") . "</p>" . "<p>" . t('The role must <strong>not</strong> have <em class="perm">edit any [type] content</em> or <em class="perm">delete any [type] content</em> permission on the <a href="@path">permissions administration form</a> if you wish to control them here.', array(
'@path' => url('admin/user/permissions', array(
'fragment' => 'module-node',
)),
)) . "</p>",
);
$rows[] = array(
array(
'header' => TRUE,
'data' => t("Add Tag"),
),
"<p>" . t("Grants this role the ability to add the term to a node when creating or updating it.") . "</p>" . "<p>" . t('(Formerly <em>Create</em>.) This does <strong>not</strong> give the role the ability to create nodes by itself; the role must <strong>have</strong> <em class="perm">create [type] content</em> permission on the <a href="@path">permissions administration form</a> in order to create new nodes.', array(
'@path' => url('admin/user/permissions', array(
'fragment' => 'module-node',
)),
)) . "</p>",
);
$rows[] = array(
array(
'header' => TRUE,
'data' => t("View Tag"),
),
"<p>" . t("(Formerly <em>List</em>). Whether this role can see the term listed on node pages and in lists, and whether the user can view the %taxonomy-term-page page for the term.", array(
'%taxonomy-term-page' => "taxonomy/term/x",
)) . "</p>" . "<p>" . t("This does <strong>not</strong> control whether the role can see the <em>nodes</em> listed in Views, only the <em>term</em>.") . "</p>",
);
return theme('table', $header, $rows, array(
'class' => 'grant_help',
));
}