tac_fields.admin.inc in Taxonomy Access Control 6
Administrative interface for TAC Fields.
File
tac_fields/tac_fields.admin.incView source
<?php
/**
* @file
* Administrative interface for TAC Fields.
*/
/**
* Menu callback for TAC Fields admin page (admin/user/tac_fields).
*/
function tac_fields_admin($op = NULL, $field = NULL, $rid = NULL, $arg = NULL) {
drupal_set_message("Warning: The TAC Fields module is experimental. Do not use on a production site.", 'warning', FALSE);
$roles = _taxonomy_access_user_roles();
$controlled_fields = _tac_fields_controlled_fields();
if ($field && in_array($field, $controlled_fields)) {
if (is_numeric($rid) and isset($roles[$rid])) {
switch ($op) {
case 'edit':
return drupal_get_form('tac_fields_admin_form', $field, $rid);
case 'delete':
return drupal_get_form('tac_fields_delete', $field, $rid);
}
}
elseif ($op == 'delete' and !isset($rid)) {
return drupal_get_form('tac_fields_delete', $field);
}
}
elseif (!isset($op) and !isset($rid)) {
return theme_tac_fields_admin();
}
// If we get here, page arguments were invalid.
return drupal_not_found();
}
/**
* Renders the main admin page (at admin/user/tac_fields).
*
* @return
* String containing rendered markup for the field's administration.
*/
function theme_tac_fields_admin() {
$output = '';
$add_form = tac_fields_add_form();
$output .= drupal_get_form('tac_fields_add_form');
// Get a list of all fields we control.
$fields = _tac_fields_controlled_fields();
foreach ($fields as $field) {
$output .= _tac_fields_admin_for_field($field);
}
return $output;
}
/**
* Renders admin table for each field, with links to configure each role.
*
* @param $field
* The machine name of the content field.
*
* @return
* String of HTML markup containing a header and table.
*
* @todo
* Return empty string if the field is not a controlled field?
*/
function _tac_fields_admin_for_field($field) {
$output = '';
$output .= "<h2>" . t("Configuration for %field", array(
'%field' => $field,
)) . "</h2>" . t('To delete all access rules below and return this field to its default behavior, you can <a href="@path">release control of %field</a>.', array(
'%field' => $field,
'@path' => url("admin/user/tac_fields/delete/{$field}"),
));
$roles = _taxonomy_access_user_roles();
// Render role/permission overview:
$header = array(
t('Role'),
array(
'data' => ' ',
),
);
$rows = array();
$result = db_query("SELECT rid FROM {term_field_access_defaults} WHERE vid=0 AND field='%s'", $field);
$active = array();
while ($role = db_fetch_array($result)) {
$active[$role['rid']] = TRUE;
}
foreach ($roles as $rid => $name) {
$ops = array();
if (!empty($active[$rid])) {
//only allow delete for "extra" roles
if ($rid > 2) {
$ops[] = l(t("disable"), "admin/user/tac_fields/delete/{$field}/{$rid}");
}
$ops[] = l(t("edit"), "admin/user/tac_fields/edit/{$field}/{$rid}");
}
else {
$ops = array(
l(t("enable"), "admin/user/tac_fields/edit/{$field}/{$rid}"),
);
}
$rows[] = array(
$name,
array(
'data' => implode(' | ', $ops),
'align' => 'right',
),
);
}
$output .= theme('table', $header, $rows);
return $output;
}
/**
* Form to choose a field to control with TAC.
*
* @todo
* Group select options by content type instead of field type?
*
* @return
* Form object.
*/
function tac_fields_add_form() {
$options = array();
$form = array();
$fields = content_fields();
$controlled_fields = _tac_fields_controlled_fields();
// Assemble a list of all CCK Fields, minus fields we already control.
foreach ($fields as $field) {
if (!in_array($field['field_name'], $controlled_fields)) {
$options[$field['type']][$field['field_name']] = t($field['widget']['label']) . ' (' . $field['field_name'] . ')';
}
}
if (!empty($options)) {
$form['add'] = array(
'#type' => 'select',
'#title' => t('Add field'),
'#required' => TRUE,
'#description' => t('Choose a field to control with TAC Fields.'),
'#options' => $options,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Add'),
);
}
else {
$form['no_choices'] = array(
'#value' => t('There are no fields available that are not already controlled by TAC Fields. See below to configure any fields that are already controlled, or add fields to one of your <a href="@content_types">content types</a>.', array(
'@content_types' => url("admin/content/types"),
)),
);
}
return $form;
}
/**
* Submit handler for tac_fields_add_form().
*/
function tac_fields_add_form_submit($form, &$form_state) {
$values = $form_state['values'];
if ($field = $values['add']) {
// Check to see whether it's a valid CCK field and not already controlled.
$fields = content_fields();
$controlled_fields = _tac_fields_controlled_fields();
if (in_array($field, array_keys($fields)) && !in_array($field, $controlled_fields)) {
// Add global defaults for anonymous & authenticated users to the db.
$row = new stdClass();
$row->vid = 0;
$row->field = $field;
for ($i = 1; $i <= 2; $i++) {
$row->rid = $i;
drupal_write_record('term_field_access_defaults', $row);
}
}
}
}
function tac_fields_delete($form, $field, $rid = NULL) {
$controlled_fields = _tac_fields_controlled_fields();
if (in_array($field, $controlled_fields)) {
if (isset($_POST['confirm'])) {
if (is_numeric($rid) && $rid > 2) {
return _tac_fields_disable_role($field, $rid);
}
elseif (is_null($rid)) {
return _tac_fields_disable_field($field);
}
}
else {
if (is_numeric($rid) && $rid > 2) {
$message = t("Are you sure you wish to delete all of the %field field's access rules for role %rid?", array(
'%field' => $field,
'%rid' => $rid,
));
}
elseif (is_null($rid)) {
$message = t("Are you sure you wish to release control of the %field field and delete <strong>all</strong> of its access rules?", array(
'%field' => $field,
'%rid' => $rid,
));
}
else {
return drupal_not_found();
}
return confirm_form($form, $message, 'admin/user/tac_fields', t('This action cannot be undone.'), t('Delete all'), t('Cancel'));
}
}
return drupal_not_found();
}
/**
* Helper function to delete all access rules for a field/row pair.
*
* @param $field
* The machine name of the field.
* @param $rid
* The role id for which to remove access rules for the field.
*/
function _tac_fields_disable_role($field, $rid) {
// Remove all records for the role/field pair from the database.
db_query("DELETE FROM {term_field_access} \n WHERE field = '%s' AND rid = %d", $field, $rid);
db_query("DELETE FROM {term_field_access_defaults} \n WHERE field = '%s' AND rid = %d", $field, $rid);
drupal_set_message(t('All term access rules for field %field and role %rid have been deleted.', array(
'%field' => $field,
'%rid' => $rid,
)));
drupal_goto('admin/user/tac_fields');
}
/**
* Helper function to delete all access rules for a field.
*
* @param $field
* The machine name of the field we are releasing.
*/
function _tac_fields_disable_field($field) {
// Remove all records for the field from the database.
db_query("DELETE FROM {term_field_access} \n WHERE field = '%s'", $field);
db_query("DELETE FROM {term_field_access_defaults} \n WHERE field = '%s'", $field);
drupal_set_message(t('All term access rules for field %field have been deleted.', array(
'%field' => $field,
)));
drupal_goto('admin/user/tac_fields');
}
/**
* Main administration form, with grid of permissions per term.
*
* @param $field
* The field to configure.
* @param $rid
* The role to configure.
*/
function tac_fields_admin_form($form_state, $field, $rid) {
// Fetch all default grants
$r = db_query("SELECT * FROM {term_field_access_defaults} \n WHERE field = '%s' AND rid = %d", $field, $rid);
while ($row = db_fetch_array($r)) {
$default_grants[$row['vid']] = $row;
}
// If we are adding a role, no global default is set yet, so insert it now.
if (empty($default_grants[0]) && isset($rid) && isset($field)) {
// Assemble a $row object for Schema API.
$row = new stdClass();
$row->vid = 0;
$row->field = $field;
$row->rid = $rid;
$row->grant_view = 1;
$row->grant_update = 0;
// Insert the default.
drupal_write_record('term_field_access_defaults', $row);
}
// Fetch all grants
$result = db_query("SELECT * FROM {term_field_access} \n WHERE field = '%s' AND rid = %d", $field, $rid);
while ($row = db_fetch_array($result)) {
$grants[$row['tid']] = $row;
}
$form['instructions'] = array(
'#value' => _tac_fields_admin_instructions_html(),
'#weight' => '20',
);
$form['rid'] = array(
'#type' => 'value',
'#value' => $rid,
);
$form['field'] = array(
'#type' => 'value',
'#value' => $field,
);
$form['grants'] = $form['selected_terms'] = $form['selected_defaults'] = array(
'#tree' => TRUE,
);
// Global default
$global_defaults = empty($default_grants[0]) ? NULL : $default_grants[0];
$form['vocabs'][0]['#title'] = 'Global';
$form['grants'][0][0] = tac_fields_build_row($global_defaults);
$form['selected_defaults'][0] = array(
'#type' => 'checkbox',
'#disabled' => TRUE,
'#title' => t('<em>default</em>'),
'#description' => t("can't be disabled without disabling this role or field"),
);
foreach (taxonomy_get_vocabularies() as $vid => $vocabulary) {
$form['vocabs'][$vid]['#title'] = check_plain($vocabulary->name);
if (isset($default_grants[$vid])) {
$form['grants'][$vid][0] = tac_fields_build_row($default_grants[$vid]);
$form['selected_defaults'][$vid] = array(
'#type' => 'checkbox',
'#title' => t('<em>default</em>'),
);
}
else {
$add_items[$vocabulary->name]["default {$vid}"] = t('*default*');
}
if ($tree = taxonomy_get_tree($vid)) {
foreach ($tree as $term) {
if (isset($grants[$term->tid])) {
$form['grants'][$vid][$term->tid] = tac_fields_build_row($grants[$term->tid]);
$form['selected_terms'][$term->tid] = array(
'#type' => 'checkbox',
'#title' => str_repeat(' ', $term->depth) . check_plain($term->name),
);
}
else {
$add_items[$vocabulary->name]["term {$term->tid}"] = str_repeat('-', $term->depth) . check_plain($term->name);
}
}
}
}
//New grant row
if (isset($add_items)) {
$form['new']['grants'] = tac_fields_build_row();
$form['new']['#tree'] = TRUE;
$form['new']['item'] = array(
'#type' => 'select',
'#options' => $add_items,
);
$form['new']['recursive'] = array(
'#type' => 'checkbox',
'#title' => t('with children'),
'#description' => t('Add child terms recursively with these values.'),
);
$form['new']['add'] = array(
'#type' => 'submit',
'#value' => t('Add'),
);
}
$form['delete'] = array(
'#type' => 'submit',
'#value' => t('Delete selected'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save all'),
);
return $form;
}
/**
* Assembles an admin form row with the appropriate radio buttons.
*
* @param $grants
* Default grants to set, if any.
*
* @return
* Form array for the row.
*/
function tac_fields_build_row($grants = NULL) {
$form['#title'] = '';
$form['#tree'] = TRUE;
foreach (array(
'view',
'update',
) as $grant) {
$form[$grant] = array(
'#type' => 'radios',
'#options' => array(
'1' => '',
'0' => '',
'2' => '',
),
//1: Allow, 0: Ignore, 2: Deny
'#default_value' => is_string($grants['grant_' . $grant]) ? $grants['grant_' . $grant] : '0',
'#required' => TRUE,
);
}
return $form;
}
/**
* Renders the admin form in an HTML table.
*/
function theme_tac_fields_admin_form($form) {
$roles = _taxonomy_access_user_roles();
$header = array(
array(
'data' => t('Category'),
'colspan' => 3,
),
array(
'data' => t('View'),
'colspan' => 4,
),
array(
'data' => t('Update'),
'colspan' => 4,
),
);
$sub_header = array(
' <strong>' . t('<acronym title="Allow">A</acronym>') . '</strong>',
' <strong>' . t('<acronym title="Ignore">I</acronym>') . '</strong>',
' <strong>' . t('<acronym title="Deny">D</acronym>') . '</strong>',
' ',
);
$sub_header = array_merge(array(
' ',
), $sub_header, $sub_header);
$node_grant_types = array(
'view',
'update',
);
$radios = array(
'1' => t('Allow'),
'0' => t('Ignore'),
'2' => t('Deny'),
);
drupal_set_title(t('%field: Grants for %role', array(
'%field' => $form['field']['#value'],
'%role' => $roles[$form['rid']['#value']],
)));
$rows = array();
foreach (array_keys($form['vocabs']) as $vid) {
if (is_numeric($vid) and isset($form['grants'][$vid])) {
$row = $sub_header;
$row[0] = array(
'data' => '<h3>' . check_plain($form['vocabs'][$vid]['#title']) . '</h3>',
'colspan' => 3,
);
$rows[] = $row;
foreach (array_keys($form['grants'][$vid]) as $tid) {
if (is_numeric($tid)) {
$select_key = $tid ? 'selected_terms' : 'selected_defaults';
$select_id = $tid ? $tid : $vid;
$row = array(
array(
'data' => drupal_render($form[$select_key][$select_id]),
'colspan' => 3,
),
);
foreach ($node_grant_types as $grant) {
foreach (array_keys($radios) as $key) {
// I need this hack to display radio buttons horizontally (instead of standard form 'radios')
$row[] = array(
'data' => drupal_render($form['grants'][$vid][$tid][$grant][$key]),
);
}
$row[] = ' ';
}
$rows[] = $row;
}
}
}
}
if (isset($form['new'])) {
$row = $sub_header;
$row[0] = array(
'data' => '<h3>' . t('New') . '</h3>',
'colspan' => 3,
);
$rows[] = $row;
$row = array(
array(
'data' => drupal_render($form['new']['item']) . drupal_render($form['new']['recursive']),
'colspan' => '2',
),
drupal_render($form['new']['add']),
);
foreach ($node_grant_types as $grant) {
foreach (array_keys($radios) as $key) {
// I need this hack to display radio buttons horizontally (instead of standard form 'radios')
$row[] = array(
'data' => drupal_render($form['new']['grants'][$grant][$key]),
);
}
$row[] = ' ';
}
$rows[] = $row;
$row = array();
}
$output = '';
$output .= theme('table', $header, $rows);
$output .= drupal_render($form);
return $output;
}
/**
* Submit handler for permission administration form.
*
* @todo
* This is cloned from TAC; finish.
*/
function tac_fields_admin_form_submit($form, &$form_state) {
$values = $form_state['values'];
$field = $values['field'];
$rid = $values['rid'];
switch ($values['op']) {
case t('Delete selected'):
if (is_array($values['selected_terms'])) {
foreach ($values['selected_terms'] as $tid => $enabled) {
if ($enabled) {
db_query("DELETE FROM {term_field_access} \n WHERE field = '%s' AND rid = %d AND tid = %d", $field, $rid, $tid);
}
}
}
if (is_array($values['selected_defaults'])) {
foreach ($values['selected_defaults'] as $vid => $enabled) {
if ($enabled) {
db_query("DELETE FROM {term_field_access_defaults} \n WHERE field = '%s' AND rid = %d AND vid = %d", $field, $rid, $vid);
}
}
}
break;
case t('Add'):
$new = $values['new'];
list($type, $id) = explode(' ', $new['item']);
if ($type == 'term') {
if ($new['recursive'] == 1) {
tac_fields_recursive_update($id, $field, $rid, $new['grants']);
}
else {
tac_fields_update_grants($id, $field, $rid, $new['grants']);
}
}
elseif ($type == 'default') {
tac_fields_update_defaults($id, $field, $rid, $new['grants']);
}
break;
case t('Save all'):
foreach ($values['grants'] as $vid => $rows) {
foreach ($rows as $tid => $grants) {
// Check the default values for this row.
$defaults = array();
foreach ($grants as $grant_name => $value) {
$defaults[$grant_name] = $form['grants'][$vid][$tid][$grant_name]['#default_value'];
}
// Proceed if the user changed the row (values differ from defaults).
if ($defaults != $grants) {
if ($tid == 0) {
tac_fields_update_defaults($vid, $field, $rid, $grants);
}
else {
tac_fields_update_grants($tid, $field, $rid, $grants);
}
}
}
}
drupal_goto('admin/user/tac_fields');
break;
}
}
function _tac_fields_admin_instructions_html() {
return "hi";
}
function tac_fields_update_grants($tid, $field, $rid, $grants) {
// Assemble a $row object for Schema API.
$row = new stdClass();
$row->tid = $tid;
$row->field = $field;
$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;
}
}
}
// Delete old entry.
db_query("DELETE FROM {term_field_access} \n WHERE field = '%s' AND tid = %d AND rid = %d", $field, $tid, $rid);
// Insert new entry.
drupal_write_record('term_field_access', $row);
}
function tac_fields_update_defaults($vid, $field, $rid, $grants) {
// Assemble a $row object for Schema API.
$row = new stdClass();
$row->vid = $vid;
$row->field = $field;
$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;
}
}
}
// Delete old entry.
db_query("DELETE FROM {term_field_access_defaults} \n WHERE field = '%s' AND vid = %d AND rid = %d", $field, $vid, $rid);
// Insert new entry.
drupal_write_record('term_field_access_defaults', $row);
}
function tac_fields_recursive_update($tid, $field, $rid, $grants) {
// First, process the original.
tac_fields_update_grants($tid, $field, $rid, $grants);
// Process the children.
$ran_tids = array();
// tids that have been processed.
$run_tids = array(
$tid,
);
// tids that are in the queue to be processed.
while (count($run_tids) > 0) {
foreach ($run_tids as $run_key => $run_tid) {
// Some basic loop protection.
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();
// stop the execution
}
else {
$result = db_query('SELECT th.tid FROM {term_hierarchy} th WHERE th.parent = %d', $run_tid);
// If this tid has children, update grants and queue the children
while ($row = db_fetch_array($result)) {
tac_fields_update_grants($row['tid'], $field, $rid, $grants);
$run_tids[] = $row['tid'];
}
// Remove this tid from the queue and mark as processed,
unset($run_tids[$run_key]);
$ran_tids[] = $run_tid;
}
}
}
}
Functions
Name | Description |
---|---|
tac_fields_add_form | Form to choose a field to control with TAC. |
tac_fields_add_form_submit | Submit handler for tac_fields_add_form(). |
tac_fields_admin | Menu callback for TAC Fields admin page (admin/user/tac_fields). |
tac_fields_admin_form | Main administration form, with grid of permissions per term. |
tac_fields_admin_form_submit | Submit handler for permission administration form. |
tac_fields_build_row | Assembles an admin form row with the appropriate radio buttons. |
tac_fields_delete | |
tac_fields_recursive_update | |
tac_fields_update_defaults | |
tac_fields_update_grants | |
theme_tac_fields_admin | Renders the main admin page (at admin/user/tac_fields). |
theme_tac_fields_admin_form | Renders the admin form in an HTML table. |
_tac_fields_admin_for_field | Renders admin table for each field, with links to configure each role. |
_tac_fields_admin_instructions_html | |
_tac_fields_disable_field | Helper function to delete all access rules for a field. |
_tac_fields_disable_role | Helper function to delete all access rules for a field/row pair. |