diff --git a/taxonomy_access.admin.inc b/taxonomy_access.admin.inc index bd2ac47c61974401b6bfd20df855a0ae13c5a615..4a90e1dc254b23ac8d77efe86062557c6f1b0da4 100644 --- a/taxonomy_access.admin.inc +++ b/taxonomy_access.admin.inc @@ -21,10 +21,10 @@ function taxonomy_access_admin() { $roles = _taxonomy_access_user_roles(); $active_rids = db_query( 'SELECT rid FROM {taxonomy_access_default} WHERE vid = :vid', - array(':vid' => TAXONOMY_ACCESS_GLOBAL_DEFAULT)) - ->fetchCol(); + array(':vid' => TAXONOMY_ACCESS_GLOBAL_DEFAULT) + )->fetchCol(); - $header = array(t('Role'), t('Status'), array('data' => t('Operations'), 'colspan' => 2)); + $header = array(t('Role'), t('Status'), t('Operations')); $rows = array(); foreach ($roles as $rid => $name) { @@ -34,23 +34,16 @@ function taxonomy_access_admin() { if (in_array($rid, $active_rids)) { // Add edit operation link for active roles. $row[] = array('data' => t('Enabled')); - $row[] = array('data' => l(t("edit access rules"), TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit")); - // Add disable operation link for custom roles. - if ($rid != DRUPAL_ANONYMOUS_RID && $rid != DRUPAL_AUTHENTICATED_RID) { - $row[] = array('data' => l(t("disable access control"), TAXONOMY_ACCESS_CONFIG . "/role/$rid/delete")); - } - else { - $row[] = array('data' => ''); - } } else { // Add enable link for unconfigured roles. $row[] = array('data' => t('Disabled')); - $row[] = array('data' => ''); - $row[] = array('data' => l(t("enable access control"), TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit")); } - + $row[] = array('data' => l( + t("Configure"), + TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit", + array('attributes' => array('class' => array('module-link', 'module-link-configure'))))); $rows[] = $row; } @@ -71,26 +64,21 @@ function taxonomy_access_admin() { * @param int $rid * The role ID to disable. * - * @see taxonomy_access_admin_delete_role_submit() + * @see taxonomy_access_role_delete_confirm_submit() * @see taxonomy_access_menu() + * @ingroup forms */ -function taxonomy_access_admin_delete_role($form, &$form_state, $rid) { +function taxonomy_access_role_delete_confirm($form, &$form_state, $rid) { $roles = _taxonomy_access_user_roles(); - $role_global_default = db_query( - 'SELECT grant_view, grant_update, grant_delete - FROM {taxonomy_access_default} - WHERE vid = :vid AND rid = :rid', array(':vid' => TAXONOMY_ACCESS_GLOBAL_DEFAULT, ':rid' => $rid)) - ->fetchAssoc(); - if ($role_global_default) { + if (taxonomy_access_role_enabled($rid)) { $form['rid'] = array( '#type' => 'value', '#value' => $rid, ); - return confirm_form($form, - t('Are you sure you want to delete all taxonomy access rules for the role %role?', + t("Are you sure you want to delete all taxonomy access rules for the role %role?", array('%role' => $roles[$rid])), - TAXONOMY_ACCESS_CONFIG, + TAXONOMY_ACCESS_CONFIG . '/role/%/edit', t('This action cannot be undone.'), t('Delete all'), t('Cancel')); @@ -98,14 +86,9 @@ function taxonomy_access_admin_delete_role($form, &$form_state, $rid) { } /** - * Form submission handler for taxonomy_access_admin_delete_role. - * - * @param int $rid - * The role ID to disable. - * - * @see taxonomy_access_admin_delete_role() + * Form submission handler for taxonomy_role_delete_confirm(). */ -function taxonomy_access_admin_delete_role_submit($form, &$form_state) { +function taxonomy_access_role_delete_confirm_submit($form, &$form_state) { $roles = _taxonomy_access_user_roles(); $rid = $form_state['values']['rid']; if (is_numeric($rid) @@ -121,32 +104,55 @@ function taxonomy_access_admin_delete_role_submit($form, &$form_state) { } /** - * Assembles a row of grant options for a term or default on the admin form. + * Generates a URL to enable a role with a token for CSRF protection. * - * @param array $grants - * (optional) An array of grants to use as form defaults. Defaults to NULL. + * @param int $rid + * The role ID. + * + * @return string + * The full URL for the request path. */ -function taxonomy_access_admin_build_row(array $grants = NULL) { - $form['#tree'] = TRUE; - foreach (array('view', 'update', 'delete') as $grant) { - $form[$grant] = array( - '#type' => 'select', - '#options' => array( - TAXONOMY_ACCESS_NODE_ALLOW => 'Allow', - TAXONOMY_ACCESS_NODE_IGNORE => 'Ignore', - TAXONOMY_ACCESS_NODE_DENY => 'Deny'), - '#default_value' => is_string($grants['grant_' . $grant]) ? $grants['grant_' . $grant] : TAXONOMY_ACCESS_NODE_IGNORE, - '#required' => TRUE, - ); +function taxonomy_access_enable_role_url($rid) { + // Create a query array with a token to validate the sumbission. + $query = drupal_get_destination(); + $query['token'] = drupal_get_token($rid); + + // Build and return the URL with the token and destination. + return url( + TAXONOMY_ACCESS_CONFIG . "/role/$rid/enable", + array('query' => $query) + ); +} + +/** + * Page callback: Enables a role if the proper token is provided. + * + * @param int $rid + * The role ID. + */ +function taxonomy_access_enable_role_validate($rid) { + $rid = intval($rid); + // If a valid token is not provided, return a 403. + $query = drupal_get_query_parameters(); + if (empty($query['token']) || !drupal_valid_token($query['token'], $rid)) { + return MENU_ACCESS_DENIED; } - foreach (array('create', 'list') as $grant) { - $form[$grant] = array( - '#type' => 'select', - '#options' => array(TAXONOMY_ACCESS_TERM_ALLOW => 'Allow', TAXONOMY_ACCESS_TERM_DENY => 'Deny'), - '#default_value' => is_string($grants['grant_' . $grant]) ? $grants['grant_' . $grant] : TAXONOMY_ACCESS_TERM_DENY, - ); + // Return a 404 for the anonymous or authenticated roles. + if (in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { + return MENU_NOT_FOUND; } - return $form; + // Return a 404 for invalid role IDs. + $roles = _taxonomy_access_user_roles(); + if (empty($roles[$rid])) { + return MENU_NOT_FOUND; + } + + // If the parameters pass validation, enable the role and complete redirect. + if (taxonomy_access_enable_role($rid)) { + drupal_set_message(t('Role %name enabled successfully.', + array('%name' => $roles[$rid]))); + } + drupal_goto(); } /** @@ -159,308 +165,621 @@ function taxonomy_access_admin_build_row(array $grants = NULL) { * * @see taxonomy_access_admin_form_submit() * @see taxonomy_access_menu() + * @ingroup forms */ -function taxonomy_access_admin_form($form, $form_state, $rid) { - // Disable list filtering while preparing this form. - taxonomy_access_disable_list(); - - $roles = _taxonomy_access_user_roles(); - - // Fetch all default grants. - $default_grants = db_query('SELECT * FROM {taxonomy_access_default} WHERE rid = :rid', array(':rid' => $rid))->fetchAllAssoc('vid', PDO::FETCH_ASSOC); - - // If we are adding a role, no global default is set yet, so insert it now. - if (empty($default_grants[0]) && isset($rid)) { - // Assemble a $row object for Schema API. - $row = new stdClass(); - $row->vid = TAXONOMY_ACCESS_GLOBAL_DEFAULT; - $row->rid = $rid; - - // Insert the row with defaults for all grants. - drupal_write_record('taxonomy_access_default', $row); - - drupal_set_message(t('Access control for role %role enabled.', - array('%role' => $roles[$rid]))); - } - - // Fetch all grants. - $grants = db_query('SELECT * FROM {taxonomy_access_term} WHERE rid = :rid', array(':rid' => $rid))->fetchAllAssoc('tid', PDO::FETCH_ASSOC); - - $form['instructions'] = array( - '#markup' => _taxonomy_access_admin_instructions_html(), - '#weight' => '20', - ); +function taxonomy_access_admin_role($form, $form_state, $rid) { + // Always include the role ID in the form. + $rid = intval($rid); $form['rid'] = array('#type' => 'value', '#value' => $rid); - $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] = taxonomy_access_admin_build_row($global_defaults); - $form['selected_defaults'][0] = array( - '#type' => 'checkbox', - '#disabled' => TRUE, - '#title' => t('default'), - '#description' => t("can't be disabled without disabling TAC for this role"), - ); - foreach (taxonomy_get_vocabularies() as $vid => $vocabulary) { - $form['vocabs'][$vid]['#title'] = check_plain($vocabulary->name); - if (isset($default_grants[$vid])) { - $form['grants'][$vid][0] = taxonomy_access_admin_build_row($default_grants[$vid]); - $form['selected_defaults'][$vid] = array( - '#type' => 'checkbox', - '#title' => t('default'), + // For custom roles, allow the user to enable or disable grants for the role. + if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) { + $roles = _taxonomy_access_user_roles(); + + // If the role is not enabled, return only a link to enable it. + if (!taxonomy_access_role_enabled($rid)) { + $form['status'] = array( + '#markup' => '

' . t( + 'Access control for the %name role is disabled. Enable @name.', + array( + '%name' => $roles[$rid], + '@name' => $roles[$rid], + '@url' => taxonomy_access_enable_role_url($rid))) . '

' ); + return $form; } + // Otherwise, add a link to disable and build the rest of the form. else { - $add_items[$vocabulary->name]["default $vid"] = t('*default*'); + $disable_url = url( + TAXONOMY_ACCESS_CONFIG . "/role/$rid/delete", + array('query' => drupal_get_destination()) + ); + $form['status'] = array( + '#markup' => '

' . t( + 'Access control for the %name role is enabled. Disable @name.', + array('@name' => $roles[$rid], '%name' => $roles[$rid], '@url' => $disable_url)) . '

' + ); } + } - if ($tree = taxonomy_get_tree($vid)) { - foreach ($tree as $term) { - if (isset($grants[$term->tid])) { - $form['grants'][$vid][$term->tid] = taxonomy_access_admin_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); - } - } + // Retrieve role grants and display an administration form. + // Disable list filtering while preparing this form. + taxonomy_access_disable_list(); + + // Fetch all grants for the role. + $defaults = + db_query( + 'SELECT vid, grant_view, grant_update, grant_delete, grant_create, + grant_list + FROM {taxonomy_access_default} + WHERE rid = :rid', + array(':rid' => $rid)) + ->fetchAllAssoc('vid', PDO::FETCH_ASSOC); + + $records = + db_query( + 'SELECT ta.tid, td.vid, ta.grant_view, ta.grant_update, ta.grant_delete, + ta.grant_create, ta.grant_list + FROM {taxonomy_access_term} ta + INNER JOIN {taxonomy_term_data} td ON ta.tid = td.tid + WHERE rid = :rid', + array(':rid' => $rid)) + ->fetchAllAssoc('tid', PDO::FETCH_ASSOC); + $term_grants = array(); + foreach ($records as $record) { + $term_grants[$record['vid']][$record['tid']] = $record; + } + + // Add a fieldset for the global default. + $form['global_default'] = array( + '#type' => 'fieldset', + '#title' => t('Global default'), + '#description' => t('The global default controls access to untagged nodes. It is also used as the default for disabled vocabularies.'), + '#collapsible' => TRUE, + // Collapse if there are vocabularies configured. + '#collapsed' => (sizeof($defaults) > 1), + ); + // Print term grant table. + $form['global_default']['grants'] = taxonomy_access_grant_add_table($defaults[TAXONOMY_ACCESS_GLOBAL_DEFAULT], TAXONOMY_ACCESS_VOCABULARY_DEFAULT); + + // Fetch all vocabularies and determine which are enabled for the role. + $vocabs = array(); + $disabled = array(); + foreach (taxonomy_get_vocabularies() as $vocab) { + $vocabs[$vocab->vid] = $vocab; + if (!isset($defaults[$vocab->vid])) { + $disabled[$vocab->vid] = $vocab->name; } } - // New grant row. - if (isset($add_items)) { - $form['new']['grants'] = taxonomy_access_admin_build_row(); - $form['new']['#tree'] = TRUE; - $form['new']['item'] = array( - '#type' => 'select', - '#options' => $add_items, + + // Add a fieldset to enable vocabularies. + if (!empty($disabled)) { + $form['enable_vocabs'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Add vocabulary'), + '#attributes' => array('class' => array('container-inline', 'taxonomy-access-add')), ); - $form['new']['recursive'] = array( - '#type' => 'checkbox', - '#title' => t('with children'), - '#description' => t('Add child terms recursively with these values.'), + $form['enable_vocabs']['enable_vocab'] = array( + '#type' => 'select', + '#title' => t('Vocabulary'), + '#options' => $disabled, ); - $form['new']['add'] = array( + $form['enable_vocabs']['add'] = array( '#type' => 'submit', + '#submit' => array('taxonomy_access_enable_vocab_submit'), '#value' => t('Add'), ); } - $form['actions'] = array('#type' => 'actions'); - - $form['actions']['delete'] = array( - '#type' => 'submit', - '#value' => t('Delete selected'), - ); + // Add a fieldset for each enabled vocabulary. + foreach ($defaults as $vid => $vocab_default) { + if (!empty($vocabs[$vid])) { + $vocab = $vocabs[$vid]; + $name = $vocab->machine_name; + + // Fetch unconfigured terms and reorder term records by hierarchy. + $sort = array(); + $add_options = array(); + if ($tree = taxonomy_get_tree($vid)) { + foreach ($tree as $term) { + if (empty($term_grants[$vid][$term->tid])) { + $add_options["term $term->tid"] = str_repeat('-', $term->depth) . ' ' .check_plain($term->name); + } + else { + $sort[$term->tid] = $term_grants[$vid][$term->tid]; + $sort[$term->tid]['name'] = str_repeat('-', $term->depth) . ' ' . check_plain($term->name); + } + } + $term_grants[$vid] = $sort; + } + $grants = array(TAXONOMY_ACCESS_VOCABULARY_DEFAULT => $vocab_default); + $grants[TAXONOMY_ACCESS_VOCABULARY_DEFAULT]['name'] = t('Default'); + if (!empty($term_grants[$vid])) { + $grants += $term_grants[$vid]; + } + $form[$name] = array( + '#type' => 'fieldset', + '#title' => $vocab->name, + '#attributes' => array('class' => array('taxonomy-access-vocab')), + '#description' => t('The default settings apply to all terms in %vocab that do not have their own below.', array('%vocab' => $vocab->name)), + '#collapsible' => TRUE, + '#collapsed' => FALSE, + ); + // Term grant table. + $form[$name]['grants'] = + taxonomy_access_grant_table($grants, $vocab->vid, t('Term'), !empty($term_grants[$vid])); + // Fieldset to add a new term if there are any. + if (!empty($add_options)) { + $form[$name]['new'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#title' => t('Add term'), + '#tree' => TRUE, + '#attributes' => array('class' => array('container-inline', 'taxonomy-access-add')), + ); + $form[$name]['new'][$vid]['item'] = array( + '#type' => 'select', + '#title' => t('Term'), + '#options' => $add_options, + ); + $form[$name]['new'][$vid]['recursive'] = array( + '#type' => 'checkbox', + '#title' => t('with descendants'), + ); + $form[$name]['new'][$vid]['grants'] = + taxonomy_access_grant_add_table($vocab_default, $vid); + $form[$name]['new'][$vid]['add'] = array( + '#type' => 'submit', + '#name' => $vid, + '#submit' => array('taxonomy_access_add_term_submit'), + '#value' => t('Add'), + ); + } + $disable_url = url( + TAXONOMY_ACCESS_CONFIG . "/role/$rid/disable/$vid", + array('query' => drupal_get_destination()) + ); + $form[$name]['disable'] = array( + '#markup' => '

' . t( + 'To disable the %vocab vocabulary, delete all @vocab access rules.', + array('%vocab' => $vocab->name, '@vocab' => $vocab->name, '@url' => $disable_url)) . '

' + ); + } + } + $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array( '#type' => 'submit', '#value' => t('Save all'), + '#submit' => array('taxonomy_access_save_all_submit'), ); + if (!empty($term_grants)) { + $form['actions']['delete'] = array( + '#type' => 'submit', + '#value' => t('Delete selected'), + '#submit' => array('taxonomy_access_delete_selected_submit'), + ); + } return $form; } /** - * Renders the permission matrix user form for a given user role. + * Generates a grant table for multiple access rules. * - * @return string - * String containing rendered HTML form in table. + * @param array $rows + * An array of grant row data, keyed by an ID (term, vocab, role, etc.). Each + * row should include the following keys: + * - name: (optional) The label for the row (e.g., a term, vocabulary, or + * role name). + * - view: The View grant value select box for the element. + * - update: The Update grant value select box for the element. + * - delete: The Delete grant value select box for the element. + * - create: The Add tag grant value select box for the element. + * - list: The View tag grant value select box for the element. + * @param int $parent_vid + * The parent ID for the table in the form tree structure (typically a + * vocabulary id). + * @param string $first_col + * The header for the first column (in the 'name' key for each row). + * @param bool $delete + * (optional) Whether to add a deletion checkbox to each row along with a + * "Check all" box in the table header. The checbox is automatically disabled + * for TAXONOMY_ACCESS_VOCABULARY_DEFAULT. Defaults to TRUE. + * + * @return + * Renderable array containing the table. + * + * @see taxonomy_access_grant_table() */ -function theme_taxonomy_access_admin_form($variables) { - $form = $variables['form']; +function taxonomy_access_grant_table(array $rows, $parent_vid, $first_col, $delete = TRUE) { + $header = taxonomy_access_grant_table_header(); + if ($first_col) { + array_unshift( + $header, + array('data' => $first_col, 'class' => array('taxonomy-access-label')) + ); + } + if ($delete) { + drupal_add_js('misc/tableselect.js'); + array_unshift($header, array('class' => array('select-all'))); + } + $table = array( + '#type' => 'taxonomy_access_grant_table', + '#tree' => TRUE, + '#header' => $header, + ); + foreach ($rows as $id => $row) { + $table[$parent_vid][$id] = taxonomy_access_admin_build_row($row, 'name', $delete); + } + // Disable the delete checkbox for the default. + if ($delete && isset($table[$parent_vid][TAXONOMY_ACCESS_VOCABULARY_DEFAULT])) { + $table[$parent_vid][TAXONOMY_ACCESS_VOCABULARY_DEFAULT]['remove']['#disabled'] = TRUE; + } - $roles = _taxonomy_access_user_roles(); + return $table; +} + +/** + * Generates a grant table for adding access rules with one set of values. + * + * @param array $rows + * An associative array of access rule data, with the following keys: + * - view: The View grant value select box for the element. + * - update: The Update grant value select box for the element. + * - delete: The Delete grant value select box for the element. + * - create: The Add tag grant value select box for the element. + * - list: The View tag grant value select box for the element. + * @param int $id + * The ID for this set (e.g., a vocabulary ID). + * + * @return + * Renderable array containing the table. + * + * @see taxonomy_access_grant_table() + */ +function taxonomy_access_grant_add_table($row, $id) { + $header = taxonomy_access_grant_table_header(); + $table = array( + '#type' => 'taxonomy_access_grant_table', + '#tree' => TRUE, + '#header' => $header, + ); + $table[$id][TAXONOMY_ACCESS_VOCABULARY_DEFAULT] = taxonomy_access_admin_build_row($row); + + return $table; +} + +/** + * Returns a header array for grant form tables. + * + * @return array + * An array of header cell data for a grant table. + */ +function taxonomy_access_grant_table_header() { $header = array( - array( 'data' => t('Category'), 'colspan' => 2), - array( 'data' => t('View')), - array( 'data' => t('Update')), - array( 'data' => t('Delete')), - array( 'data' => t('Add Tag')), - array( 'data' => t('View Tag')), + array('data' => t('View')), + array('data' => t('Update')), + array('data' => t('Delete')), + array('data' => t('Add Tag')), + array('data' => t('View Tag')), ); - $grant_types = array('view', 'update', 'delete', 'create', 'list'); + foreach ($header as &$cell) { + $cell['class'] = array('taxonomy-access-grant'); + } + return $header; +} +/** + * Theme our grant table. + * + * @todo + * Use a separate theme function for taxonomy_access_grant_add_table() to get + * out of nesting hell? + * @todo + * I clearly have no idea what I'm doing here. + */ +function theme_taxonomy_access_grant_table($element_data) { + $table = array(); + $table['header'] = $element_data['elements']['#header']; + $table['attributes']['class'] = array('taxonomy-access-grant-table'); $rows = array(); - - foreach (array_keys($form['vocabs']) as $vid) { - if (is_numeric($vid) AND isset($form['grants'][$vid])) { - $row = array(array('data' => '

' . check_plain($form['vocabs'][$vid]['#title']) . '

', 'colspan' => 7)); - $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' => 2), - ); - foreach ($grant_types as $grant) { - $row[] = array( - 'data' => drupal_render($form['grants'][$vid][$tid][$grant]), - 'class' => $grant . '-' . $form['grants'][$vid][$tid][$grant]['#default_value'] - ); + foreach (element_children($element_data['elements']) as $element_key) { + $child = $element_data['elements'][$element_key]; + foreach (element_children($child) as $child_key) { + $record = $child[$child_key]; + $row = array(); + foreach (element_children($record) as $record_key) { + $data = array('data' => $record[$record_key]); + // If it's the default, add styling. + if ($record_key == 'name') { + $data['class'] = array('taxonomy-access-label'); + if ($child_key == TAXONOMY_ACCESS_VOCABULARY_DEFAULT) { + $data['class'][] = 'taxonomy-access-default'; } - $rows[] = $row; } + // Add grant classes to grant cells. + elseif (in_array($record_key, array('view', 'update', 'delete', 'create', 'list'))) { + $grant_class = $record_key . '-' . $data['data']['#default_value']; + $data['class'] = array('taxonomy-access-grant', $grant_class); + } + $row[] = $data; } + $rows[] = $row; } } - if (isset($form['new'])) { - $row = array(array('data' => '

' . t('New') . '

', 'colspan' => 7)); - $rows[] = $row; + $table['rows'] = $rows; + return theme('table', $table); +} - $row = array( - array( - 'data' => drupal_render($form['new']['item']) - . drupal_render($form['new']['recursive']), - ), - drupal_render($form['new']['add']), +/** + * Assembles a row of grant options for a term or default on the admin form. + * + * @param array $grants + * An array of grants to use as form defaults. + * @param $label_key + * (optional) Key of the column to use as a label in each grant row. Defaults + * to NULL. + */ +function taxonomy_access_admin_build_row(array $grants, $label_key = NULL, $delete = FALSE) { + $form['#tree'] = TRUE; + if ($delete) { + $form['remove'] = array( + '#type' => 'checkbox', + '#title' => t('Delete access rule for @name', array('@name' => $grants[$label_key])), + '#title_display' => 'invisible', ); - foreach ($grant_types as $grant) { - $row[] = array( - 'data' => drupal_render($form['new']['grants'][$grant]), - 'class' => $grant . '-' . $form['new']['grants'][$grant]['#default_value'] - ); - } - $rows[] = $row; - $row = array(); } + if ($label_key) { + $form[$label_key] = array( + '#type' => 'markup', + '#markup' => check_plain($grants[$label_key]), + ); + } + foreach (array('view', 'update', 'delete', 'create', 'list') as $grant) { + $for = $label_key ? $grants[$label_key] : NULL; + $form[$grant] = array( + '#type' => 'select', + '#title' => _taxonomy_access_grant_field_label($grant, $for), + '#title_display' => 'invisible', + '#default_value' => is_string($grants['grant_' . $grant]) ? $grants['grant_' . $grant] : TAXONOMY_ACCESS_NODE_IGNORE, + '#required' => TRUE, + ); + } + foreach (array('view', 'update', 'delete') as $grant) { + $form[$grant]['#options'] = array( + TAXONOMY_ACCESS_NODE_ALLOW => t('Allow'), + TAXONOMY_ACCESS_NODE_IGNORE => t('Ignore'), + TAXONOMY_ACCESS_NODE_DENY => t('Deny'), + ); + } + foreach (array('create', 'list') as $grant) { + $form[$grant]['#options'] = array( + TAXONOMY_ACCESS_TERM_ALLOW => t('Allow'), + TAXONOMY_ACCESS_TERM_DENY => t('Deny'), + ); + } + return $form; +} +/** + * Returns the proper invisible field label for each grant table element. + */ +function _taxonomy_access_grant_field_label($grant, $for = NULL) { + if ($for) { + $label = array('@label', $for); + $titles = array( + 'view' => t('View grant for @label', $label), + 'update' => t('Update grant for @label', $label), + 'delete' => t('Delete grant for @label', $label), + 'create' => t('Add tag grant for @label', $label), + 'list' => t('View tag grant for @label', $label), + ); + } + else { + $titles = array( + 'view' => t('View grant'), + 'update' => t('Update grant'), + 'delete' => t('Delete grant'), + 'create' => t('Add tag grant'), + 'list' => t('View tag grant'), + ); + } - $output = ''; - $output .= theme('table', array('header' => $header, 'rows' => $rows)); - $output .= drupal_render_children($form); - - return $output; + return $titles[$grant]; } /** - * Form submission handler for taxonomy_access_admin_form(). + * Form submission handler for taxonomy_access_admin_role(). + * + * Processes submissions for the vocabulary 'Add' button. */ -function taxonomy_access_admin_form_submit($form, &$form_state) { - // Save some typing. - $values = $form_state['values']; - - switch ($values['op']) { +function taxonomy_access_enable_vocab_submit($form, &$form_state) { + $rid = $form_state['values']['rid']; + $vid = $form_state['values']['enable_vocab']; + $roles = _taxonomy_access_user_roles(); + $vocab = taxonomy_vocabulary_load($vid); + if (taxonomy_access_enable_vocab($vid, $rid)) { + drupal_set_message(t( + 'Vocabulary %vocab enabled successfully for the %role role.', + array( + '%vocab' => $vocab->name, + '%role' => $roles[$rid]))); + } + else { + drupal_set_message(t('The vocabulary could not be enabled.'), 'error'); + } +} - case t('Delete selected'): - _taxonomy_access_admin_form_delete($values['rid'], $values); - break; +/** + * Form submission handler for taxonomy_access_admin_role(). + * + * Processes submissions for the term 'Add' button. + */ +function taxonomy_access_add_term_submit($form, &$form_state) { + $vid = $form_state['clicked_button']['#name']; + $new = $form_state['values']['new'][$vid]; + $rid = $form_state['values']['rid']; + list($type, $id) = explode(' ', $new['item']); + $rows = array(); - case t('Add'): - _taxonomy_access_admin_form_add($values['rid'], $values); - break; + $rows[$id] = + _taxonomy_access_format_grant_record($id, $rid, $new['grants'][$vid][TAXONOMY_ACCESS_VOCABULARY_DEFAULT]); - case t('Save all'): - _taxonomy_access_admin_form_save_all($values['rid'], $values, $form); - $form_state['redirect'] = TAXONOMY_ACCESS_CONFIG; - break; + // If we are adding children recursively, add those as well. + if ($new['recursive'] == 1) { + $children = _taxonomy_access_get_descendants($id); + foreach ($children as $tid) { + $rows[$tid] = + _taxonomy_access_format_grant_record($tid, $rid, $new['grants'][$vid][TAXONOMY_ACCESS_VOCABULARY_DEFAULT]); + } } + + // Set the grants for the row or rows. + taxonomy_access_set_term_grants($rows); } /** - * Helper to process the "Delete selected" button on the administration form. + * Page callback: Returns a confirmation form to disable a vocabulary. * - * @param $rid - * The role id for the submission. - * @param $values - * The $form_state['values'] from the form submission. + * @param int $rid + * The role ID. + * @param object $vocab + * The vocabulary object. + * + * @todo + * Check if vocab is enabled and return a 404 otherwise? + * + * @see taxonomy_access_menu() + * @see taxonomy_access_admin_role(). + * @see taxonomy_access_disable_vocab_confirm_page() */ -function _taxonomy_access_admin_form_delete($rid, $values) { - if (isset($values['selected_terms']) && is_array($values['selected_terms'])) { - $disable_tids = array(); - foreach ($values['selected_terms'] as $tid => $enabled) { - if ($enabled) { - $disable_tids[] = $tid; - } - } +function taxonomy_access_disable_vocab_confirm_page($rid, $vocab) { + $rid = intval($rid); - if (!empty($disable_tids)) { - taxonomy_access_delete_term_grants($disable_tids, $rid); - unset($disable_tids); - } + // Return a 404 on invalid vid or rid. + if (!$vocab->vid || !$rid) { + return MENU_NOT_FOUND; } - if (isset($values['selected_defaults']) && is_array($values['selected_defaults'])) { - $disable_vids = array(); - foreach ($values['selected_defaults'] as $vid => $enabled) { - if ($enabled) { - $disable_vids[] = $vid; - } - } + return drupal_get_form('taxonomy_access_disable_vocab_confirm', $rid, $vocab); +} - if (!empty($disable_vids)) { - taxonomy_access_delete_default_grants($disable_vids, $rid); - unset($disable_tids); - } +/** + * Returns a confirmation form for disabling a vocabulary for a role. + * + * @param int $rid + * The role ID. + * @param object $vocab + * The vocabulary object. + * + * @see taxonomy_access_disable_vocab_confirm_page() + * @see taxonomy_access_disable_vocab_confirm_submit() + * @ingroup forms + */ +function taxonomy_access_disable_vocab_confirm($form, &$form_state, $rid, $vocab) { + $roles = _taxonomy_access_user_roles(); + if (taxonomy_access_role_enabled($rid)) { + $form['rid'] = array( + '#type' => 'value', + '#value' => $rid, + ); + $form['vid'] = array( + '#type' => 'value', + '#value' => $vocab->vid, + ); + $form['vocab_name'] = array( + '#type' => 'value', + '#value' => $vocab->name, + ); + return confirm_form($form, + t("Are you sure you want to delete all Taxonomy access rules for %vocab in the %role role?", + array('%role' => $roles[$rid], '%vocab' => $vocab->name)), + TAXONOMY_ACCESS_CONFIG . '/role/%/edit', + t('This action cannot be undone.'), + t('Delete all'), + t('Cancel')); } } /** - * Helper to process the "Add" button on the administration form. + * Form submission handler for taxonomy_access_disable_vocab_confirm(). * - * @param $rid - * The role id for the submission. - * @param $values - * The $form_state['values'] from the form submission. + * @param int $rid + * The role ID to disable. + * + * @todo + * Set a message on invalid $rid or $vid? */ -function _taxonomy_access_admin_form_add($rid, $values) { - $new = $values['new']; - list($type, $id) = explode(' ', $new['item']); - $rows = array(); - - if ($type == 'term') { - $rows[$id] = - _taxonomy_access_format_grant_record($id, $rid, $new['grants']); +function taxonomy_access_disable_vocab_confirm_submit($form, &$form_state) { + $roles = _taxonomy_access_user_roles(); + $rid = intval($form_state['values']['rid']); + $vid = intval($form_state['values']['vid']); + // Do not proceed for invalid role IDs, and do not allow the global default + // to be deleted. + if (!$vid || !$rid || empty($roles[$rid])) { + return FALSE; + } - // If we are adding children recursively, add those as well. - if ($new['recursive'] == 1) { - $children = _taxonomy_access_get_descendants($id); - foreach ($children as $tid) { - $rows[$tid] = - _taxonomy_access_format_grant_record($tid, $rid, $new['grants']); - } + if ($form_state['values']['confirm']) { + $form_state['redirect'] = TAXONOMY_ACCESS_CONFIG; + if (taxonomy_access_disable_vocab($vid, $rid)) { + drupal_set_message( + t('All Taxonomy access rules deleted for %vocab in role %role.', + array( + '%vocab' => $form_state['values']['vocab_name'], + '%role' => $roles[$rid]) + )); + return TRUE; } - - // Set the grants for the row or rows. - taxonomy_access_set_term_grants($rows); } +} - elseif ($type == 'default') { - $default[$id] = - _taxonomy_access_format_grant_record($id, $rid, $new['grants'], TRUE); - - // For the vocabulary default, all terms in the vocabulary are children. - if ($new['recursive'] == 1) { - $children = _taxonomy_access_get_vocabulary_terms($id); - foreach ($children as $tid) { - $rows[$tid] = - _taxonomy_access_format_grant_record($tid, $rid, $new['grants']); +/** + * Form submission handler for taxonomy_access_admin_role(). + * + * Processes submissions for the "Delete selected" button. + * + * @todo + * The parent form could probably be refactored to make this more efficient + * (by putting these elements in a flat list) but that would require changing + * taxonomy_access_grant_table() and taxonomy_access_build_row(). + */ +function taxonomy_access_delete_selected_submit($form, &$form_state) { + $rid = intval($form_state['values']['rid']); + $delete_tids = array(); + foreach ($form_state['values']['grants'] as $vid => $tids) { + foreach ($tids as $tid => $record) { + if (!empty($record['remove'])) { + $delete_tids[] = $tid; } } - - // Set the grants for the row or rows. - taxonomy_access_set_default_grants($default); - taxonomy_access_set_term_grants($rows); + } + if ($rid) { + if (taxonomy_access_delete_term_grants($delete_tids, $rid)) { + drupal_set_message(format_plural( + sizeof($delete_tids), + '1 term access rule was deleted.', + '@count term access rules were deleted.')); + } + else { + drupal_set_message(t('The records could not be deleted.'), 'warning'); + } } } - /** - * Helper to process the "Save all" button on the administration form. + * Form submission handler for taxonomy_access_admin_form(). * - * @param int $rid - * The role id for the submission. - * @param array $values - * The $form_state['values'] from the form submission. - * @param array $form - * The $form array for the form. Used to compare default values. + * Processes submissions for the 'Save all' button. */ -function _taxonomy_access_admin_form_save_all($rid, $values, $form) { +function taxonomy_access_save_all_submit($form, &$form_state) { + $values = $form_state['values']; + $rid = $values['rid']; + $vocabs = taxonomy_get_vocabularies(); + // Create four lists of records to update. $update_terms = array(); $skip_terms = array(); @@ -468,12 +787,21 @@ function _taxonomy_access_admin_form_save_all($rid, $values, $form) { $skip_defaults = array(); foreach ($values['grants'] as $vid => $rows) { - foreach ($rows as $tid => $grants) { + if ($vid == TAXONOMY_ACCESS_GLOBAL_DEFAULT) { + $element = $form['global_default']; + } + else { + $vocab = $vocabs[$vid]; + $element = $form[$vocab->machine_name]; + } + foreach ($rows as $tid => $row) { // Check the default values for this row. $defaults = array(); - foreach ($grants as $grant_name => $value) { + $grants = array(); + foreach (array('view', 'update', 'delete', 'create', 'list') as $grant_name) { + $grants[$grant_name] = $row[$grant_name]; $defaults[$grant_name] = - $form['grants'][$vid][$tid][$grant_name]['#default_value']; + $element['grants'][$vid][$tid][$grant_name]['#default_value']; } // Proceed if the user changed the row (values differ from defaults). diff --git a/taxonomy_access.css b/taxonomy_access.css index 4a8693150489c458208d9d220b4696fa1eef358c..4eda7c19d9f98bcffc532f25d307085a5f3eacd2 100644 --- a/taxonomy_access.css +++ b/taxonomy_access.css @@ -1,11 +1,11 @@ table.grant_help th { vertical-align: top; -} +} table.grant_help td p { margin-top: 0px; margin-bottom: 8px; -} +} table.grant_help em.perm { font-weight: bold; @@ -33,4 +33,62 @@ label.disabled { .create-0, .list-0 { background-color: #fef5f1; -} \ No newline at end of file +} +.taxonomy-access-grant-table { + margin-top: 0.5em; + margin-bottom: 0.5em; + width: inherit; +} +.taxonomy-access-grant-table th.select-all { + width: 2em; +} +.taxonomy-access-grant-table td.taxonomy-access-label { + padding-right: 4em; + min-width: 12em; +} +.taxonomy-access-grant-table td.taxonomy-access-default { + font-style: italic; + font-weight: bold; +} +.taxonomy-access-grant-table td.taxonomy-access-grant { + width: 7em; +} +fieldset#edit-vocabs .fieldset-description { + display: block; +} + +/** + * I apologize, because what follows is a hodgepodge to override the default + * fieldset styling in both Seven and Bartik, and might not even work in some + * themes. + */ +#taxonomy-access-admin-role fieldset { + margin-bottom: 0.5em; + margin-top: 0.5em; +} + +#taxonomy-access-admin-role fieldset.taxonomy-access-add.collapsible, +#taxonomy-access-admin-role fieldset.taxonomy-access-add.collapsed { + margin-top: 0px; + margin-bottom: 1em; + border: none; + background: none; +} +fieldset.taxonomy-access-add > legend { + background: none; + border: none; + font-family: inherit; + position: static; +} +fieldset.taxonomy-access-add > legend a { + color: #0076bc; +} +fieldset.taxonomy-access-add .fieldset-wrapper { + margin-top: 0px; + padding-top: 0.5em; +} +html.js fieldset.collapsible.taxonomy-access-add > legend .fieldset-legend, +html.js fieldset.collapsed.taxonomy-access-add > legend .fieldset-legend { + background: transparent url(images/add.png) no-repeat 0 center; + text-transform: none; +} diff --git a/taxonomy_access.install b/taxonomy_access.install index a8dffc5e927b4f13e2015b3dacf23e2be6b04b9f..a91b330ec179ec00b7ece5235e3d04e4794c5936 100644 --- a/taxonomy_access.install +++ b/taxonomy_access.install @@ -178,6 +178,37 @@ function taxonomy_access_schema() { return $schema; } +/** + * Add vocabulary defaults for all configured vocabularies. + */ +function taxonomy_access_update_7002() { + // Get a list of all vocabularies with any term configurations for each role. + $ta_configs = db_query( + "SELECT td.vid, ta.rid + FROM {taxonomy_access_term} ta + INNER JOIN {taxonomy_term_data} td ON ta.tid = td.tid + GROUP BY td.vid, ta.rid" + )->fetchAll(); + + // Get a list of all configured vocabularies. + $td_configs = db_query( + "SELECT vid, rid + FROM {taxonomy_access_default}" + )->fetchAll(); + + $records = array(); + $global_defaults = taxonomy_access_global_defaults(); + + foreach ($ta_configs as $config) { + if (!in_array($config, $td_configs)) { + $record = (array) $global_defaults[$config->rid]; + $records[] = _taxonomy_access_format_grant_record($config->vid, $config->rid, $record, TRUE); + } + } + + return taxonomy_access_set_default_grants($records); +} + /** * Rename grant realm. */ diff --git a/taxonomy_access.module b/taxonomy_access.module index 64b48eefeb7124d352c0678989dc6ce65e936eb7..ddca41e3ec34518fcee85a1ebd66255b3e718ed3 100644 --- a/taxonomy_access.module +++ b/taxonomy_access.module @@ -94,8 +94,25 @@ function taxonomy_access_theme() { 'render element' => 'form', 'file' => 'taxonomy_access.admin.inc', ), + 'taxonomy_access_grant_table' => array( + 'render element' => 'elements', + 'file' => 'taxonomy_access.admin.inc', + ), ); } + +/** + * Implements hook_element_info(). + */ +function taxonomy_access_element_info() { + return array( + 'taxonomy_access_grant_table' => array( + '#theme' => 'taxonomy_access_grant_table', + '#regions' => array('' => array()), + ), + ); +} + /** * Implements hook_menu(). */ @@ -121,19 +138,32 @@ function taxonomy_access_menu() { 'title callback' => 'taxonomy_access_role_edit_title', 'title arguments' => array(5), 'page callback' => 'drupal_get_form', - 'page arguments' => array('taxonomy_access_admin_form', 5), + 'page arguments' => array('taxonomy_access_admin_role', 5), 'access callback' => 'taxonomy_access_role_edit_access', 'access arguments' => array(5), 'file' => 'taxonomy_access.admin.inc', ); + $items[TAXONOMY_ACCESS_CONFIG . '/role/%/enable'] = array( + 'page callback' => 'taxonomy_access_enable_role_validate', + 'page arguments' => array(5), + 'access arguments' => array('administer permissions'), + 'file' => 'taxonomy_access.admin.inc', + ); $items[TAXONOMY_ACCESS_CONFIG . '/role/%/delete'] = array( 'page callback' => 'drupal_get_form', - 'page arguments' => array('taxonomy_access_admin_delete_role', 5), + 'page arguments' => array('taxonomy_access_role_delete_confirm', 5), 'access callback' => 'taxonomy_access_role_delete_access', 'access arguments' => array(5), 'file' => 'taxonomy_access.admin.inc', 'type' => MENU_CALLBACK, ); + $items[TAXONOMY_ACCESS_CONFIG . '/role/%/disable/%taxonomy_vocabulary'] = array( + 'page callback' => 'taxonomy_access_disable_vocab_confirm_page', + 'page arguments' => array(5, 7), + 'access arguments' => array('administer permissions'), + 'file' => 'taxonomy_access.admin.inc', + 'type' => MENU_CALLBACK, + ); $items['taxonomy_access/autocomplete'] = array( 'title' => 'Autocomplete taxonomy', 'page callback' => 'taxonomy_access_autocomplete', diff --git a/taxonomy_access.test b/taxonomy_access.test index 45a147428aa0e1d928ab656fa3223264d186212a..481e5a4cb833b95aabacbb16bfc28dca88abf018 100644 --- a/taxonomy_access.test +++ b/taxonomy_access.test @@ -66,7 +66,7 @@ class TaxonomyAccessTestCase extends DrupalWebTestCase { 'update' => TAXONOMY_ACCESS_NODE_IGNORE, 'delete' => TAXONOMY_ACCESS_NODE_IGNORE, ); - $rows[] = _taxonomy_access_format_grant_record(TAXONOMY_ACCESS_NODE_IGNORE, $rid, $ignore, TRUE); + $rows[] = _taxonomy_access_format_grant_record(TAXONOMY_ACCESS_GLOBAL_DEFAULT, $rid, $ignore, TRUE); } taxonomy_access_set_default_grants($rows); @@ -74,12 +74,11 @@ class TaxonomyAccessTestCase extends DrupalWebTestCase { $r = db_query( 'SELECT grant_view FROM {taxonomy_access_default} - WHERE vid = :vid AND rid = :rid', + WHERE vid = :vid AND rid = :rid', array(':vid' => TAXONOMY_ACCESS_GLOBAL_DEFAULT, ':rid' => $rid) ) ->fetchField(); - $this->assertTrue(is_numeric($r) && $r == TAXONOMY_ACCESS_NODE_IGNORE, - t("Set global default for role %rid to Ignore", array('%rid' => $rid))); + $this->assertTrue(is_numeric($r) && $r == 0, t("Set global default for role %rid to Ignore", array('%rid' => $rid))); } } @@ -218,39 +217,84 @@ class TaxonomyAccessTestCase extends DrupalWebTestCase { } /** - * Asserts that an enable or edit link is found for the role. + * Asserts that a status column and "Configure" link is found for the role. + * + * @param array $statuses + * An associative array of role statuses, keyed by role ID. Each item + * should be TRUE if the role is enabled, and FALSE otherwise. + */ + function checkRoleConfig(array $statuses) { + $roles = _taxonomy_access_user_roles(); + + // Log in as the administrator. + $this->drupalLogout(); + $this->drupalLogin($this->users['site_admin']); + $this->drupalGet(TAXONOMY_ACCESS_CONFIG); + + foreach ($statuses as $rid => $status) { + // Assert that a "Configure" link is available for the role. + $this->assertLinkByHref( + TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit", + 0, + t('"Configure" link is available for role %rid.', array('%rid' => $rid))); + } + + // Retrieve the grant status table. + $shown = array(); + $table = $this->xpath('//table/tbody'); + $table = reset($table); + // SimpleXML has fake arrays so we have to do this to get the data out. + foreach ($table->tr as $row) { + $tds = array(); + foreach ($row->td as $value) { + $tds[] = (string) $value; + } + $shown[$tds[0]] = $tds[1]; + } + + foreach ($statuses as $rid => $status) { + // Assert that the form shows the passed status. + if ($status) { + $this->assertTrue( + $shown[$roles[$rid]] == t('Enabled'), + format_string('Role %role is enabled.', array('%role' => $rid))); + } + else { + $this->assertTrue( + $shown[$roles[$rid]] == t('Disabled'), + format_string('Role %role is disabled.', array('%role' => $rid))); + } + + // Assert that a "Configure" link is available for the role. + $this->assertLinkByHref( + TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit", + 0, + t('"Configure" link is available for role %rid.', + array('%rid' => $rid))); + } + + } + + /** + * Asserts that an enable link is or is not found for the role. * * @param int $rid * The role ID to check. - * @param bool $enable - * (optional) Whether the text should be 'edit' (TRUE) or 'enable' (FALSE). - * Defaults to FALSE. + * @param bool $found + * Whether the link should be found, or not. */ - function checkRoleEditEnable($rid, $enable = FALSE) { - $this->assertLinkByHref( - TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit", - 0, - t('Edit link is available for role %rid.', array('%rid' => $rid)) - ); - - if ($enable) { - $this->assertRaw( - TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit\">enable", - t('Link text is "enable" for role %rid.', array('%rid' => $rid)) - ); - $this->assertNoRaw( - TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit\">edit", - t('Link text is not "edit" for role %rid.', array('%rid' => $rid)) + function checkRoleEnableLink($rid, $found) { + if ($found) { + $this->assertLinkByHref( + TAXONOMY_ACCESS_CONFIG . "/role/$rid/enable", + 0, + t('Enable link is available for role %rid.', array('%rid' => $rid)) ); } else { - $this->assertRaw( - TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit\">edit", - t('Link text is "edit" for role %rid.', array('%rid' => $rid)) - ); - $this->assertNoRaw( - TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit\">enable", - t('Link text is not "enable" for role %rid.', array('%rid' => $rid)) + $this->assertNoLinkByHref( + TAXONOMY_ACCESS_CONFIG . "/role/$rid/enable", + t('Enable link is not available for role %rid.', array('%rid' => $rid)) ); } } @@ -261,60 +305,56 @@ class TaxonomyAccessTestCase extends DrupalWebTestCase { * @param int $rid * The role ID to check. * @param bool $found - * (optional) Whether the link should be found, or not. Defaults to TRUE. + * Whether the link should be found, or not. */ - function checkRoleDisable($rid, $found = TRUE) { + function checkRoleDisableLink($rid, $found) { if ($found) { $this->assertLinkByHref( TAXONOMY_ACCESS_CONFIG . "/role/$rid/delete", 0, t('Disable link is available for role %rid.', array('%rid' => $rid)) ); - $this->assertRaw( - TAXONOMY_ACCESS_CONFIG . "/role/$rid/delete\">disable", - t('Link text is "disable" for role %rid.', array('%rid' => $rid)) - ); } else { $this->assertNoLinkByHref( TAXONOMY_ACCESS_CONFIG . "/role/$rid/delete", t('Disable link is not available for role %rid.', array('%rid' => $rid)) ); - $this->assertNoRaw( - TAXONOMY_ACCESS_CONFIG . "/role/$rid/delete\">disable", - t('There is no link text "disable" for role %rid.', array('%rid' => $rid)) - ); } } /** - * Adds a row on the TAC configuration form. + * Adds a term row on the role configuration form. * * @param array &$edit * The form data to post. * @param int $vid - * (optional) The vocabulary ID. Defaults to global default. - * @param int $tid - * (optional) The term ID. Defaults to vocabulary default. + * (optional) The vocabulary ID. Defaults to + * TAXONOMY_ACCESS_GLOBAL_DEFAULT. + * @param $int tid + * (optional) The term ID. Defaults to TAXONOMY_ACCESS_VOCABULARY_DEFAULT. * @param int $view - * (optional) The view grant value. Defaults to ignore. + * (optional) The view grant value. Defaults to + * TAXONOMY_ACCESS_NODE_IGNORE. * @param int $update - * (optional) The update grant value. Defaults to ignore. + * (optional) The update grant value. Defaults to * @param int $delete - * (optional) The delete grant value. Defaults to ignore. + * (optional) The delete grant value. Defaults to + * TAXONOMY_ACCESS_NODE_IGNORE. * @param int $create - * (optional) The create grant value. Defaults to deny (unchecked). + * (optional) The create grant value. Defaults to + * TAXONOMY_ACCESS_TERM_DENY. * @param int $list - * (optional) The list grant value. Defaults to deny (unchecked). + * (optional) The list grant value. Defaults to TAXONOMY_ACCESS_TERM_DENY. */ - function addFormRow(&$edit, $vid = TAXONOMY_ACCESS_GLOBAL_DEFAULT, $tid = TAXONOMY_ACCESS_VOCABULARY_DEFAULT, $view = TAXONOMY_ACCESS_NODE_IGNORE, $update = TAXONOMY_ACCESS_NODE_IGNORE, $delete = TAXONOMY_ACCESS_NODE_IGNORE, $create = TAXONOMY_ACCESS_TERM_DENY, $list = TAXONOMY_ACCESS_TERM_DENY) { + function addFormRow(&$edit, $vid = TAXONOMY_ACCESS_GLOBAL_DEFAULT, $tid = TAXONOMY_ACCESS_VOCABULARY_DEFAULT, $view = TAXONOMY_ACCESS_NODE_IGNORE, $update = TAXONOMY_ACCESS_NODE_IGNORE, $delete = TAXONOMY_ACCESS_NODE_IGNORE, $create = TAXONOMY_ACCESS_TERM_DENY, $list = TAXONOMY_ACCESS_TERM_DENY) { $new_value = $tid ? "term $tid" : "default $vid"; - $edit["new[item]"] = $new_value; - $edit["new[grants][view]"] = $view; - $edit["new[grants][update]"] = $update; - $edit["new[grants][delete]"] = $delete; - $edit["new[grants][create]"] = $create; - $edit["new[grants][list]"] = $list; + $edit["new[$vid][item]"] = $new_value; + $edit["new[$vid][grants][$vid][0][view]"] = $view; + $edit["new[$vid][grants][$vid][0][update]"] = $update; + $edit["new[$vid][grants][$vid][0][delete]"] = $delete; + $edit["new[$vid][grants][$vid][0][create]"] = $create; + $edit["new[$vid][grants][$vid][0][list]"] = $list; } /** @@ -323,21 +363,25 @@ class TaxonomyAccessTestCase extends DrupalWebTestCase { * @param array &$edit * The form data to post. * @param int $vid - * (optional) The vocabulary ID. Defaults to TAXONOMY_ACCESS_GLOBAL_DEFAULT. - * @param int $tid + * (optional) The vocabulary ID. Defaults to + * TAXONOMY_ACCESS_GLOBAL_DEFAULT. + * @param $int tid * (optional) The term ID. Defaults to TAXONOMY_ACCESS_VOCABULARY_DEFAULT. * @param int $view - * (optional) The view grant value. Defaults to ignore. + * (optional) The view grant value. Defaults to + * TAXONOMY_ACCESS_NODE_IGNORE. * @param int $update - * (optional) The update grant value. Defaults to ignore. + * (optional) The update grant value. Defaults to * @param int $delete - * (optional) The delete grant value. Defaults to ignore. + * (optional) The delete grant value. Defaults to + * TAXONOMY_ACCESS_NODE_IGNORE. * @param int $create - * (optional) The create grant value. Defaults to deny (unchecked). + * (optional) The create grant value. Defaults to + * TAXONOMY_ACCESS_TERM_DENY. * @param int $list - * (optional) The list grant value. Defaults to deny (unchecked). + * (optional) The list grant value. Defaults to TAXONOMY_ACCESS_TERM_DENY. */ - function configureFormRow(&$edit, $vid = TAXONOMY_ACCESS_GLOBAL_DEFAULT, $tid = TAXONOMY_ACCESS_VOCABULARY_DEFAULT, $view = TAXONOMY_ACCESS_NODE_IGNORE, $update = TAXONOMY_ACCESS_NODE_IGNORE, $delete = TAXONOMY_ACCESS_NODE_IGNORE, $create = TAXONOMY_ACCESS_TERM_DENY, $list = TAXONOMY_ACCESS_TERM_DENY) { + function configureFormRow(&$edit, $vid = TAXONOMY_ACCESS_GLOBAL_DEFAULT, $tid = TAXONOMY_ACCESS_VOCABULARY_DEFAULT, $view = TAXONOMY_ACCESS_NODE_IGNORE, $update = TAXONOMY_ACCESS_NODE_IGNORE, $delete = TAXONOMY_ACCESS_NODE_IGNORE, $create = TAXONOMY_ACCESS_TERM_DENY, $list = TAXONOMY_ACCESS_TERM_DENY) { $edit["grants[$vid][$tid][view]"] = $view; $edit["grants[$vid][$tid][update]"] = $update; $edit["grants[$vid][$tid][delete]"] = $delete; @@ -458,28 +502,8 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { return $this->drupalCreateNode($settings); } - /** - * Checks for the proper display of admin links for anon. and auth. roles. - */ - function checkConfigAnonAuthLinks() { - $this->drupalGet(TAXONOMY_ACCESS_CONFIG); - $this->checkRoleEditEnable(DRUPAL_ANONYMOUS_RID); - $this->checkRoleEditEnable(DRUPAL_AUTHENTICATED_RID); - $this->checkRoleDisable(DRUPAL_ANONYMOUS_RID, FALSE); - $this->checkRoleDisable(DRUPAL_AUTHENTICATED_RID, FALSE); - } - - /** - * Checks for the proper display of admin links for custom roles. - */ - function checkConfigCustomRoleLinks() { - foreach ($this->user_roles as $role) { - $this->checkRoleEditEnable($role->rid, TRUE); - $this->checkRoleDisable($role->rid, FALSE); - } - } - /* +@todo - check anon and auth forms - add recursive for vocab and for term - change multiple @@ -498,11 +522,11 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Visit all nodes as anonymous and verify that access is denied. foreach ($this->articles as $key => $article) { $this->drupalGet('node/' . $article->nid); - $this->assertResponse(403, t("Access to %name article (nid %nid) is denied for anonymous users.", array('%name' => $key, '%nid' => $article->nid))); + $this->assertResponse(403, t("Access to %name article (nid %nid) is denied.", array('%name' => $key, '%nid' => $article->nid))); } foreach ($this->pages as $key => $page) { $this->drupalGet('node/' . $page->nid); - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); } // Log in as the regular_user. @@ -511,21 +535,21 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Visit all nodes and verify that access is denied. foreach ($this->articles as $key => $article) { $this->drupalGet('node/' . $article->nid); - $this->assertResponse(403, t("Access to %name article (nid %nid) is denied for a regular user.", array('%name' => $key, '%nid' => $article->nid))); + $this->assertResponse(403, t("Access to %name article (nid %nid) is denied.", array('%name' => $key, '%nid' => $article->nid))); } foreach ($this->pages as $key => $page) { $this->drupalGet('node/' . $page->nid); - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for a regular user.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); } // Log in as the administrator. $this->drupalLogin($this->users['site_admin']); // Confirm that only edit links are available for anon. and auth. - $this->checkConfigAnonAuthLinks(); - - // Confirm that only enable links are available for our four custom roles. - $this->checkConfigCustomRoleLinks(); + $this->checkRoleConfig(array( + DRUPAL_ANONYMOUS_RID => TRUE, + DRUPAL_AUTHENTICATED_RID => TRUE, + )); } /** @@ -543,8 +567,7 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Use the admin form to give anonymous view allow in the global default. $this->drupalGet(TAXONOMY_ACCESS_CONFIG . '/role/' . DRUPAL_ANONYMOUS_RID . '/edit'); $edit = array(); - $this->configureFormRow($edit, TAXONOMY_ACCESS_GLOBAL_DEFAULT, - TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_ALLOW); + $this->configureFormRow($edit, TAXONOMY_ACCESS_GLOBAL_DEFAULT, TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_ALLOW); $this->drupalPost(NULL, $edit, 'Save all'); // Log out. @@ -553,11 +576,11 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Visit each node and verify that access is allowed. foreach ($this->articles as $key => $article) { $this->drupalGet('node/' . $article->nid); - $this->assertResponse(200, t("Access to %name article (nid %nid) is allowed for anonymous when the global default is allow.", array('%name' => $key, '%nid' => $article->nid))); + $this->assertResponse(200, t("Access to %name article (nid %nid) is allowed.", array('%name' => $key, '%nid' => $article->nid))); } foreach ($this->pages as $key => $page) { $this->drupalGet('node/' . $page->nid); - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for anonymous when the global default is allow.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); } // Add some specific configurations programmatically. @@ -585,8 +608,7 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Use the admin form to give anonymous view deny in the global default. $this->drupalGet(TAXONOMY_ACCESS_CONFIG . '/role/' . DRUPAL_ANONYMOUS_RID . '/edit'); $edit = array(); - $this->configureFormRow($edit, TAXONOMY_ACCESS_GLOBAL_DEFAULT, - TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_DENY); + $this->configureFormRow($edit, TAXONOMY_ACCESS_GLOBAL_DEFAULT, TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_DENY); $this->drupalPost(NULL, $edit, 'Save all'); // Log out. @@ -595,7 +617,7 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Visit each artile and verify that access is denied. foreach ($this->articles as $key => $article) { $this->drupalGet('node/' . $article->nid); - $this->assertResponse(403, t("Access to %name article (nid %nid) is denied for anonymous after granting access to some terms and setting the global default to deny.", array('%name' => $key, '%nid' => $article->nid))); + $this->assertResponse(403, t("Access to %name article (nid %nid) is denied.", array('%name' => $key, '%nid' => $article->nid))); } // Visit each page. @@ -607,12 +629,12 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { case ($key == 'no_tags'): // If the page is tagged with v2t2, access should be denied. case (strpos($key, 'v2t2') !== FALSE): - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous after granting access to some terms and setting the global default to deny.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); break; // Otherwise, access should be allowed. default: - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for anonymous after granting access to some terms and setting the global default to deny.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); break; } } @@ -622,7 +644,8 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { * Tests configuring vocabulary defaults. * * Verifies that: - * - Access is updated correctly when the vocabulary default is added. + * - Access is updated correctly when the vocabulary default is added and + * configured. * - Access is updated correctly when there is a specific term configuration * in the vocabulary. * - Access is updated correctly when multiple defaults are changed. @@ -632,11 +655,23 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Log in as the administrator. $this->drupalLogin($this->users['site_admin']); - // Use the admin form to give anonymous view allow for the v1 default. + // Enable the vocabulary. $this->drupalGet(TAXONOMY_ACCESS_CONFIG . '/role/' . DRUPAL_ANONYMOUS_RID . '/edit'); + // @todo + // - Ensure that all vocabularies are options in the "Add" fieldset. $edit = array(); - $this->addFormRow($edit, $this->vocabs['v1']->vid, TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_ALLOW); - $this->drupalPost(NULL, $edit, 'Add'); + $edit['enable_vocab'] = $this->vocabs['v1']->vid; + $this->drupalPost(NULL, $edit, t('Add')); + + // @todo + // - Ensure that the vocabulary is removed from the "Add" fieldset. + // - Ensure that the fieldset for the vocabulary appears. + // - Ensure that no other fieldsets or rows appear. + + // Give anonymous view allow for the v1 default. + $edit = array(); + $this->configureFormRow($edit, $this->vocabs['v1']->vid, TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_ALLOW); + $this->drupalPost(NULL, $edit, 'Save all'); // Log out. $this->drupalLogout(); @@ -647,19 +682,19 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // If the page is tagged with a v1 term, access should be allowed. if (strpos($key, 'v1') !== FALSE) { - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for anonymous users after setting the v1 default to allow.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); } // Otherwise, access should be denied. else { - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after setting the v1 default to allow.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); } } - // Add a specific configuration for v2t1 programmatically. + // Programmatically enable v2 and add a specific configuration for v2t1. + taxonomy_access_enable_vocab($this->vocabs['v2']->vid, DRUPAL_ANONYMOUS_RID); $term_config = _taxonomy_access_format_grant_record( $this->terms['v2t1']->tid, DRUPAL_ANONYMOUS_RID, array('view' => TAXONOMY_ACCESS_NODE_IGNORE) ); - taxonomy_access_set_term_grants(array($term_config)); // Log in as the administrator. @@ -668,12 +703,13 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Use the admin form to give anonymous view deny for the v2 default. $this->drupalGet(TAXONOMY_ACCESS_CONFIG . '/role/' . DRUPAL_ANONYMOUS_RID . '/edit'); $edit = array(); - $this->addFormRow($edit, $this->vocabs['v2']->vid, TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_DENY); - $this->drupalPost(NULL, $edit, 'Add'); + $this->configureFormRow($edit, $this->vocabs['v2']->vid, TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_DENY); + $this->drupalPost(NULL, $edit, 'Save all'); + + $this->drupalGet(TAXONOMY_ACCESS_CONFIG . '/role/' . DRUPAL_ANONYMOUS_RID . '/edit'); // Log out. $this->drupalLogout(); - // Visit each page and verify whether access is allowed or denied. foreach ($this->pages as $key => $page) { $this->drupalGet('node/' . $page->nid); @@ -681,17 +717,17 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { switch (TRUE) { // If the page is tagged with v2t2, the v2 default is inherited: Deny. case (strpos($key, 'v2t2') !== FALSE): - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after setting the v2 default to deny.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); break; // Otherwise, if the page is tagged with v1, it's allowed. case (strpos($key, 'v1') !== FALSE): - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for anonymous users after setting the v2 default to deny.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); break; // Access should be denied by default. default: - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after setting the v2 default to deny.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); break; } } @@ -716,18 +752,18 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { switch (TRUE) { // If the page is tagged with a v1 term, access should be denied. case (strpos($key, 'v1') !== FALSE): - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after changing the default configuration for v1 and v2.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); break; // Otherwise, if the page is tagged with v2t2, the default is // inherited and access should be allowed. case (strpos($key, 'v2t2') !== FALSE): - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for anonymous users after changing the default configuration for v1 and v2.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); break; // Access should be denied by default. default: - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after changing the default configuration for v1 and v2.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); break; } } @@ -735,11 +771,11 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Log in as the administrator. $this->drupalLogin($this->users['site_admin']); - // Use the form to delete the v1 default. + // Use the admin form to disable v1. $this->drupalGet(TAXONOMY_ACCESS_CONFIG . '/role/' . DRUPAL_ANONYMOUS_RID . '/edit'); - $edit = array(); - $edit["selected_defaults[{$this->vocabs['v1']->vid}]"] = 1; - $this->drupalPost(NULL, $edit, 'Delete selected'); + $this->clickLink(t('delete all v1 access rules')); + $this->assertText("Are you sure you want to delete all Taxonomy access rules for v1", t('Disable form for vocabulary loaded.')); + $this->drupalPost(NULL, array(), 'Delete all'); // Log out. $this->drupalLogout(); @@ -750,11 +786,11 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // If the page is tagged with v2t2, access should be allowed. if (strpos($key, 'v2t2') !== FALSE) { - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for anonymous users after deleting the v1 default.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); } // Otherwise, access should be denied. else { - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after deleting the v1 default.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); } } } @@ -772,9 +808,12 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Log in as the administrator. $this->drupalLogin($this->users['site_admin']); - // Use the admin form to give anonymous view allow for v1t1. + // Use the admin form to enable v1 and give anonymous view allow for v1t1. $this->drupalGet(TAXONOMY_ACCESS_CONFIG . '/role/' . DRUPAL_ANONYMOUS_RID . '/edit'); $edit = array(); + $edit['enable_vocab'] = $this->vocabs['v1']->vid; + $this->drupalPost(NULL, $edit, t('Add')); + $edit = array(); $this->addFormRow($edit, $this->vocabs['v1']->vid, $this->terms['v1t1']->tid, TAXONOMY_ACCESS_NODE_ALLOW); $this->drupalPost(NULL, $edit, 'Add'); @@ -787,20 +826,16 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // If the page is tagged with v1t1, access should be allowed. if (strpos($key, 'v1t1') !== FALSE) { - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for anonymous users after granting allow for v1t1.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); } // Otherwise, access should be denied. else { - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after granting allow for v1t1.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); } } - // Add a vocabulary default for v2 programmatically. - $default_config = _taxonomy_access_format_grant_record( - $this->vocabs['v2']->vid, DRUPAL_ANONYMOUS_RID, array('view' => TAXONOMY_ACCESS_NODE_IGNORE), TRUE - ); - - taxonomy_access_set_default_grants(array($default_config)); + // Enable v2 programmatically. + taxonomy_access_enable_vocab($this->vocabs['v2']->vid, DRUPAL_ANONYMOUS_RID); // Log in as the administrator. $this->drupalLogin($this->users['site_admin']); @@ -821,17 +856,17 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { switch (TRUE) { // If the page is tagged with v2t1, access should be denied. case (strpos($key, 'v2t1') !== FALSE): - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after configuring v2t1 for deny.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); break; // Otherwise, if the page is tagged with v1t1, it's allowed. case (strpos($key, 'v1t1') !== FALSE): - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for anonymous users after configuring v2t1 for deny.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); break; // Access should be denied by default. default: - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after configuring v2t1 for deny.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); break; } } @@ -860,17 +895,17 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { switch (TRUE) { // If the page is tagged with v1t1, access should be denied. case (strpos($key, 'v1t1') !== FALSE): - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after reconfiguring v1t1 and v2t1.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); break; // Otherwise, if the page is tagged with v2t1, it's allowed. case (strpos($key, 'v2t1') !== FALSE): - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for anonymous users after reconfiguring v1t1 and v2t1.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); break; // Access should be denied by default. default: - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after reconfiguring v1t1 and v2t1.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); break; } } @@ -881,7 +916,7 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Use the form to delete the v2t1 configuration. $this->drupalGet(TAXONOMY_ACCESS_CONFIG . '/role/' . DRUPAL_ANONYMOUS_RID . '/edit'); $edit = array(); - $edit["selected_terms[{$this->terms['v2t1']->tid}]"] = 1; + $edit["grants[{$this->vocabs['v2']->vid}][{$this->terms['v2t1']->tid}][remove]"] = 1; $this->drupalPost(NULL, $edit, 'Delete selected'); // Log out. @@ -892,12 +927,15 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { $this->drupalGet('node/' . $page->nid); // Access to all pages should be denied. - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for anonymous users after deleting all term configurations.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); } } /** * Tests adding a term configuration with children. + * + * @todo + * Check that node access is updated for these as well. */ public function testTermWithChildren() { // Create some additional taxonomy terms in a hierarchy: @@ -938,10 +976,12 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Log in as the administrator. $this->drupalLogin($this->users['site_admin']); + // Enable v1 programmatically. + taxonomy_access_enable_vocab($this->vocabs['v1']->vid, DRUPAL_ANONYMOUS_RID); // Use the admin form to give anonymous view allow for v1t1 and children. $this->drupalGet(TAXONOMY_ACCESS_CONFIG . '/role/' . DRUPAL_ANONYMOUS_RID . '/edit'); $edit = array(); - $edit["new[recursive]"] = 1; + $edit["new[{$this->vocabs['v1']->vid}][recursive]"] = 1; $this->addFormRow($edit, $this->vocabs['v1']->vid, $this->terms['v1t1']->tid, TAXONOMY_ACCESS_NODE_ALLOW); $this->drupalPost(NULL, $edit, 'Add'); @@ -955,29 +995,46 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { $rid = $this->user_roles['regular_user']->rid; $name = $this->user_roles['regular_user']->name; - // Log in as the administrator. - $this->drupalLogout(); - $this->drupalLogin($this->users['site_admin']); + // Check that the role is disabled by default. + $this->checkRoleConfig(array( + DRUPAL_ANONYMOUS_RID => TRUE, + DRUPAL_AUTHENTICATED_RID => TRUE, + $rid => FALSE, + )); - // Enable TAC for the regular_user role. + // Test enabling the role. $this->drupalGet(TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit"); - $this->assertRaw("Access rules for $name", t('Role configuration for regular_user (%name) enabled successfully.', array('%name' => $name))); + + // Check that there is: + // - An enable link + // - No disable link + // @todo + // - No grant tables. + $this->checkRoleEnableLink($rid, TRUE); + $this->checkRoleDisableLink($rid, FALSE); + + // Enable the role and check that there is: + // - A disable link + // - No enable link + // @todo + // - A global default table (with correct values?) + // - An "Add vocabulary" fieldset. + // - No vocabulary fieldsets or term data. + $this->clickLink(format_string('Enable @name', array('@name' => $name))); + $this->checkRoleEnableLink($rid, FALSE); + $this->checkRoleDisableLink($rid, TRUE); // Update the global default to allow view. $edit = array(); - $this->configureFormRow($edit, TAXONOMY_ACCESS_GLOBAL_DEFAULT, - TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_ALLOW); + $this->configureFormRow($edit, TAXONOMY_ACCESS_GLOBAL_DEFAULT, TAXONOMY_ACCESS_VOCABULARY_DEFAULT, TAXONOMY_ACCESS_NODE_ALLOW); $this->drupalPost(NULL, $edit, 'Save all'); - // Confirm that the edit and disable links appear. - $this->checkRoleEditEnable($rid); - $this->checkRoleDisable($rid); - - // Confirm that the anon. and auth. links are unaffected. - $this->checkConfigAnonAuthLinks(); - - // Confirm that there is only one disable link. - $this->assertUniqueText('disable', t('There is only one disable link.')); + // Confirm that all three roles are enabled. + $this->checkRoleConfig(array( + DRUPAL_ANONYMOUS_RID => TRUE, + DRUPAL_AUTHENTICATED_RID => TRUE, + $rid => TRUE, + )); // Check that the role is configured. $r = @@ -996,40 +1053,54 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Visit each node and verify that access is allowed. foreach ($this->articles as $key => $article) { $this->drupalGet('node/' . $article->nid); - $this->assertResponse(200, t("Access to %name article (nid %nid) is allowed for a regular user after granting allow in the global default.", array('%name' => $key, '%nid' => $article->nid))); + $this->assertResponse(200, t("Access to %name article (nid %nid) is allowed.", array('%name' => $key, '%nid' => $article->nid))); } foreach ($this->pages as $key => $page) { $this->drupalGet('node/' . $page->nid); - $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed for a regular user after granting allow in the global default.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(200, t("Access to %name page (nid %nid) is allowed.", array('%name' => $key, '%nid' => $page->nid))); } // Log in as the administrator. $this->drupalLogout(); $this->drupalLogin($this->users['site_admin']); - // Disable the role. - $this->drupalGet(TAXONOMY_ACCESS_CONFIG); - $this->clickLink('disable access control'); + // Test disabling the role. + $this->drupalGet(TAXONOMY_ACCESS_CONFIG . "/role/$rid/edit"); + $this->clickLink(t('Disable @name', array('@name' => $name))); $this->assertText("Are you sure you want to delete all taxonomy access rules for the role $name", t('Disable form for role loaded.')); $this->drupalPost(NULL, array(), 'Delete all'); // Confirm that a confirmation message appears. $this->assertText("All taxonomy access rules deleted for role $name", t('Confirmation message found.')); + // Check that there is: + // - An enable link + // - No disable link + // @todo + // - No grant tables. + $this->checkRoleEnableLink($rid, TRUE); + $this->checkRoleDisableLink($rid, FALSE); + // Confirm edit/enable/disable links are in their original state. - $this->checkConfigAnonAuthLinks(); - $this->checkConfigCustomRoleLinks(); + $this->checkRoleConfig(array( + DRUPAL_ANONYMOUS_RID => TRUE, + DRUPAL_AUTHENTICATED_RID => TRUE, + $rid => FALSE, + )); // Check that the role is no longer configured. $r = db_query( 'SELECT grant_view FROM {taxonomy_access_default} - WHERE vid = :vid AND rid = :rid', - array(':vid' => TAXONOMY_ACCESS_GLOBAL_DEFAULT, ':rid' => $rid) + WHERE rid = :rid', + array(':rid' => $rid) ) - ->fetchField(); + ->fetchAll(); $this->assertTrue(empty($r), t('All records removed for role %role.', array('%role' => $name))); + // @todo + // - Add a term configuration and make sure that gets deleted too. + // Log in as the regular_user. $this->drupalLogout(); $this->drupalLogin($this->users['regular_user']); @@ -1037,11 +1108,11 @@ class TaxonomyAccessConfigTest extends TaxonomyAccessTestCase { // Visit all nodes and verify that access is again denied. foreach ($this->articles as $key => $article) { $this->drupalGet('node/' . $article->nid); - $this->assertResponse(403, t("Access to %name article (nid %nid) is denied for a regular user after disabling the role.", array('%name' => $key, '%nid' => $article->nid))); + $this->assertResponse(403, t("Access to %name article (nid %nid) is denied.", array('%name' => $key, '%nid' => $article->nid))); } foreach ($this->pages as $key => $page) { $this->drupalGet('node/' . $page->nid); - $this->assertResponse(403, t("Access to %name page (nid %nid) is denied for a regular user after disabling the role.", array('%name' => $key, '%nid' => $page->nid))); + $this->assertResponse(403, t("Access to %name page (nid %nid) is denied.", array('%name' => $key, '%nid' => $page->nid))); } } } @@ -1301,9 +1372,9 @@ class TaxonomyAccessTermGrantTest extends TaxonomyAccessTestCase { // Grant all rows view, update, and delete. foreach ($grant_combos as $combo) { - $combo['view'] = TAXONOMY_ACCESS_TERM_ALLOW; - $combo['update'] = TAXONOMY_ACCESS_TERM_ALLOW; - $combo['delete'] = TAXONOMY_ACCESS_TERM_ALLOW; + $combo['view'] = TAXONOMY_ACCESS_NODE_ALLOW; + $combo['update'] = TAXONOMY_ACCESS_NODE_ALLOW; + $combo['delete'] = TAXONOMY_ACCESS_NODE_ALLOW; } // Each vocabulary will have four parent terms in the same fashion: