diff --git a/README.txt b/README.txt index 65a7446..8bbee03 100755 --- a/README.txt +++ b/README.txt @@ -13,7 +13,7 @@ to be "privileged" terms, such as marking a wiki page as stable or verified. To install the Taxonomy Term Permissions module, extract the module to your modules folder, such as sites/all/modules. After enabling the module, each term can be assigned permissions when adding or editing a term at Administer > -Content Management > Taxonomy. If no permissions are assigned, all users may +Structure > Taxonomy. If no permissions are assigned, all users may access the term. If a user may not access any terms in a required vocabulary, they will be denied access to the node form entirely. diff --git a/term_permissions.info b/term_permissions.info index 7f8ca95..88edcd1 100644 --- a/term_permissions.info +++ b/term_permissions.info @@ -1,4 +1,4 @@ name = Taxonomy Term Permissions description = Allows limiting the selection of specific taxonomy terms by user or role. -core=6.x +core = 7.x dependencies[] = taxonomy diff --git a/term_permissions.install b/term_permissions.install index 1e1b991..57ae761 100644 --- a/term_permissions.install +++ b/term_permissions.install @@ -1,33 +1,28 @@ error log may have more information about the error.', array('@watchdog-url' => url('admin/reports/dblog'))), 'error'); - } -} /** - * Implementation of hook_schema() + * Implements hook_schema(). */ function term_permissions_schema() { $schema = array(); $schema['term_permissions_user'] = array( 'fields' => array( - 'tid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE), - 'uid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE), + 'tid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'uid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), ), 'primary key' => array( 'tid', @@ -37,8 +32,16 @@ function term_permissions_schema() { $schema['term_permissions_role'] = array( 'fields' => array( - 'tid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE), - 'rid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => TRUE), + 'tid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), + 'rid' => array( + 'type' => 'int', + 'unsigned' => TRUE, + 'not null' => TRUE, + ), ), 'primary key' => array( 'tid', @@ -49,9 +52,3 @@ function term_permissions_schema() { return $schema; } -/** - * Implementation of hook_uninstall(). - */ -function term_permissions_uninstall() { - drupal_uninstall_schema('term_permissions'); -} diff --git a/term_permissions.module b/term_permissions.module index e6550b6..bd286e7 100644 --- a/term_permissions.module +++ b/term_permissions.module @@ -1,24 +1,28 @@ ' . t('This module allows taxonomy administrators the ability to restrict setting individual terms on nodes by user or role. If a user is unable to set any terms for a required vocabulary, they are blocked from adding or editing content with that vocabulary.') . '

'; - $output .= '

' . t('To add permissions for a term, go to Administer >> Content Management >> Taxonomy, and add or edit a term. If the permissions are left blank, the term is available to all users.') . '

'; + $output = '

' . t('This module allows taxonomy administrators the + ability to restrict setting individual terms on nodes by user or role. + If a user is unable to set any terms for a required vocabulary, they are + blocked from adding or editing content with that vocabulary.') . '

'; + $output .= '

' . t('To add permissions for a term, go to Administer >> + Content Management >> Taxonomy, and add or edit a term. If the + permissions are left blank, the term is available to all users.') . '

'; return $output; } } /** - * Implementation of hook_menu(). + * Implements hook_menu(). */ function term_permissions_menu() { $items = array(); @@ -32,39 +36,44 @@ function term_permissions_menu() { } /** - * Implementation of hook_form_alter() + * Implements hook_form_alter(). * - * @param $form + * @param array $form * The form to alter. - * @param $form_state + * @param array $form_state * The form state of the current form. - * @param $form_id + * @param array $form_id * The form id of the current form. */ function term_permissions_form_alter(&$form, $form_state, $form_id) { // This is the add / edit term form from the taxonomy page. if ($form_id == 'taxonomy_form_term') { - // Ensure that the Identification fieldset is at the top, as by default it - // has no weight specified. - $form['identification']['#weight'] = -15; - $form['advanced']['#weight'] = -10; + // Normally the term is an array, but when deleting terms it becomes an + // object. So, we cast it to an object so we can consistently reference it. + $term = (object)$form['#term']; + $form['access'] = array( '#type' => 'fieldset', '#title' => t('Permissions'), - '#description' => t('To limit selection of this term by user or roles, add users or roles to the following lists. Leave empty to allow selection by all users.'), + '#description' => t('To limit selection of this term by user or roles, + add users or roles to the following lists. Leave empty to allow + selection by all users.'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#attributes' => array('id' => 'fieldset_term_access'), - '#weight' => -5, '#tree' => TRUE, ); // Pull in any stored users in the database. $allowed_users = array(); if (!empty($form['tid']['#value'])) { - $result = db_query("SELECT uid FROM {term_permissions_user} WHERE tid = %d", $form['#term']['tid']); - while($uid = db_result($result)) { - $u = user_load($uid); + $result = db_select('term_permissions_user') + ->fields('term_permissions_user') + ->condition('tid', $term->tid) + ->execute(); + + foreach ($result as $row) { + $u = user_load($row->uid); $allowed_users[] = $u->name; } } @@ -75,18 +84,22 @@ function term_permissions_form_alter(&$form, $form_state, $form_id) { $form['access']['user'] = array( '#type' => 'textfield', '#title' => t('Allowed users'), - '#description' => t('Enter a comma-seperated list of user names to give them permission to use this term.'), + '#description' => t('Enter a comma-seperated list of user names to give + them permission to use this term.'), '#default_value' => $allowed_users, - '#size' => 40, + '#size' => 60, '#autocomplete_path' => 'term-permissions/autocomplete', '#weight' => -10, ); $allowed_roles = array(); if (!empty($form['tid']['#value'])) { - $result = db_query("SELECT rid FROM {term_permissions_role} WHERE tid = %d", array($form['tid']['#value'])); - while($rid = db_result($result)) { - $allowed_roles[] = $rid; + $result = db_select('term_permissions_role') + ->fields('term_permissions_role') + ->condition('tid', $term->tid) + ->execute(); + foreach ($result as $row) { + $allowed_roles[] = $row->rid; } } @@ -107,35 +120,56 @@ function term_permissions_form_alter(&$form, $form_state, $form_id) { // This is the node add / edit form. If a different selector is used from // another contributed module, we do nothing so as to not break the form. - if (isset($form['type']) && isset($form['#node']) && isset($form['taxonomy']) && (!variable_get('taxonomy_override_selector', FALSE)) && $form['type']['#value'] .'_node_form' == $form_id) { - foreach($form['taxonomy'] as $vid => $vocabulary) { - if (!is_array($vocabulary) || !isset($vocabulary['#options'])) { + if (isset($form['type']) && isset($form['#node']) && + (!variable_get('taxonomy_override_selector', FALSE)) && + $form['type']['#value'] . '_node_form' == $form_id) { + $types = array('taxonomy_term_reference'); // Field types we are looking for + + foreach ($form as $field_name => $field) { + if (!$field_info = field_info_field($field_name)) + continue; + + $options = &$form[$field_name][$form[$field_name]['#language']]['#options']; + if (!in_array($field_info['type'], $types) || !isset($options)) { continue; } - $total_terms = count($vocabulary['#options']); - foreach($vocabulary['#options'] as $terms) { - if (!isset($terms->option)) { + + foreach ($options as $tid => $name) { + if ($tid == "_none") { continue; } - foreach($terms->option as $tid => $term) { - // Now we have the term ID, check to see if the current user has - // access to the term. - global $user; - if (!term_permissions_allowed($tid, $user)) { - $total_terms--; - unset($terms->option[$tid]); - } - // If the user doesn't have access to any of the terms in the - // vocabulary, remove the form item entirely. - if ($total_terms <= 0) { - if ($vocabulary['#required']) { - drupal_set_message(t("Your account doesn't have permission to use any of the terms in the %vocabulary vocabulary. Your account must be given permission to use at least one term in the %vocabulary vocabulary to be able to add or edit the %content-type content type.", array('%vocabulary' => $vocabulary['#title'], '%content-type' => node_get_types('name', $form['type']['#value']))), 'warning'); - watchdog('term_permissions', '%user was blocked from accessing the %content-type form as they do not have permission to use any terms in the %vocabulary vocabulary.', array('%user' => isset($user->name) ? $user->name : variable_get('anonymous', 'Anonymous'), '%content-type' => node_get_types('name', $form['type']['#value']), '@vocabulary-url' => url('admin/content/taxonomy/' . $vid), '%vocabulary' => $vocabulary['#title']), WATCHDOG_WARNING, l(t('edit vocabulary'), 'admin/content/taxonomy/' . $vid)); - drupal_access_denied(); - exit(); - } - unset($form['taxonomy'][$vid]); + + // Now we have the term ID, check to see if the current user has + // access to the term. + global $user; + if (!term_permissions_allowed($tid, $user)) { + unset($options[$tid]); + } + // If the user doesn't have access to any of the terms in the + // vocabulary, remove the form item entirely. + if (count($options) <= 1) { + if ($vocabulary['#required']) { + drupal_set_message(t("Your account doesn't have permission to + use any of the terms in the %vocabulary vocabulary. Your + account must be given permission to use at least one term in + the %vocabulary vocabulary to be able to add or edit the + %content-type content type.", + array('%vocabulary' => $vocabulary['#title'], + '%content-type' => node_get_types('name', + $form['type']['#value']))), 'warning'); + watchdog('term_permissions', '%user was blocked from accessing + the %content-type form as they do not have permission to use + any terms in the %vocabulary + vocabulary.', array('%user' => isset($user->name) ? $user->name : variable_get('anonymous', 'Anonymous'), + '%content-type' => node_get_types('name', $form['type']['#value']), + '@vocabulary-url' => url('admin/content/taxonomy/' . $vid), + '%vocabulary' => $vocabulary['#title']), + WATCHDOG_WARNING, l(t('edit vocabulary'), + 'admin/content/taxonomy/' . $vid)); + drupal_access_denied(); + exit(); } + unset($form[$field_name]); } } } @@ -154,8 +188,9 @@ function term_permissions_validate($form, &$form_state) { if (!empty($form_state['values']['access']['user'])) { $allowed_users = drupal_explode_tags($form_state['values']['access']['user']); foreach ($allowed_users as $name) { - if (!(user_load(array('name' => $name)))) { - form_set_error('search_user', t('The user %name does not exist.', array('%user' => $name))); + if (!(array_shift(user_load_multiple(array(), array('name' => $name))))) { + form_set_error('search_user', t('The user %name does not exist.', + array('%user' => $name))); } } } @@ -171,21 +206,33 @@ function term_permissions_validate($form, &$form_state) { * The state of the current form. */ function term_permissions_submit($form, &$form_state) { + // First delete the values associated to the tid in the database. + db_delete('term_permissions_user')->condition('tid', $form_state['values']['tid'])->execute(); // For each user, save the term ID and the user ID. - db_query("DELETE FROM {term_permissions_user} WHERE tid = %d", $form_state['values']['tid']); - if (!empty($form_state['values']['access']['user'])) { + if (!empty($form_state['values']['access']['user']) && ($form_state['values']['op'] == 'Save')) { $allowed_users = drupal_explode_tags($form_state['values']['access']['user']); - foreach($allowed_users as $name) { - $u = user_load(array('name' => $name)); - db_query("INSERT INTO {term_permissions_user} (tid, uid) VALUES (%d, %d)", $form_state['values']['tid'], $u->uid); + foreach ($allowed_users as $name) { + $u = array_shift(user_load_multiple(array(), array('name' => $name))); + $id = db_insert('term_permissions_user') + ->fields(array( + 'tid' => $form_state['values']['tid'], + 'uid' => $u->uid, + )) + ->execute(); } } + // First delete the values associated to the tid in the database. + db_delete('term_permissions_user')->condition('tid', $form_state['values']['tid'])->execute(); // For each role, save the term ID and the role ID. - db_query("DELETE FROM {term_permissions_role} WHERE tid = %d", $form_state['values']['tid']); - if (!empty($form_state['values']['access']['role'])) { - foreach(array_keys(array_filter($form_state['values']['access']['role'])) as $rid) { - db_query("INSERT INTO {term_permissions_role} (tid, rid) VALUES (%d, %d)", $form_state['values']['tid'], $rid); + if (!empty($form_state['values']['access']['role']) && ($form_state['values']['op'] == 'Save')) { + foreach (array_keys(array_filter($form_state['values']['access']['role'])) as $rid) { + $id = db_insert('term_permissions_role') + ->fields(array( + 'tid' => $form_state['values']['tid'], + 'rid' => $rid, + )) + ->execute(); } } } @@ -193,7 +240,7 @@ function term_permissions_submit($form, &$form_state) { /** * Given a term ID, determine if a user has access to that term. UID 1 is * always allowed access. If no permissions are set on the term, allow - * access by default. + * acc ess by default. * * @param $tid * The term ID to look up. @@ -206,39 +253,48 @@ function term_permissions_allowed($tid, $user) { if ($user->uid == 1) { return TRUE; } + // Are permissions enabled on this term? - if (!(db_result(db_query("SELECT COUNT(1) FROM {term_permissions_user} WHERE tid = %d", $tid)) || db_result(db_query("SELECT COUNT(1) FROM {term_permissions_role} WHERE tid = %d", $tid)))) { - return TRUE; + if (!(db_query("SELECT COUNT(1) FROM {term_permissions_user} WHERE tid = :tid", + array(':tid' => $tid))->fetchField() || + db_query("SELECT COUNT(1) FROM {term_permissions_role} WHERE tid = :tid", + array(':tid' => $tid))->fetchField())) { + return TRUE; } + // We need to convert user->roles to be useful for us. + $users_uid = implode(', ', array_keys($user->roles)); // Permissions are enabled, check to see if this user or one of their roles // is allowed. - if (db_result(db_query("SELECT uid FROM {term_permissions_user} WHERE tid = %d AND uid = %d", $tid, $user->uid)) || db_result(db_query("SELECT rid FROM {term_permissions_role} WHERE tid = %d AND rid IN (" . implode(', ', array_keys($user->roles)) . ")", $tid))) { + + if (db_query("SELECT uid FROM {term_permissions_user} WHERE tid = :tid AND uid = :uid", + array(':tid' => $tid, ':uid' => $user->uid))->fetchField() || + db_query("SELECT rid FROM {term_permissions_role} WHERE tid = :tid AND rid IN (:user_roles)", + array(':tid' => $tid, ':user_roles' => $users_uid))->fetchField()) { return TRUE; } return FALSE; } /** - * Returns JS array for Taxonomy Term Permissions autocomplete fields. Supports + * Returns Json array for Taxonomy Term Permissions autocomplete fields. Supports * multiple entries separated by a comma. */ function term_permissions_autocomplete_multiple($string) { - // The user enters a comma-separated list of users. We only autocomplete the last user. + // The user enters a comma-separated list of users. + // We only autocomplete the last user. $array = drupal_explode_tags($string); - // Fetch last tag + // Fetch last user. $last_string = trim(array_pop($array)); $matches = array(); - $result = db_query_range("SELECT u.name FROM {users} u WHERE LOWER(u.name) LIKE LOWER('%s%%')", $last_string, 0, 10); + $result = db_select('users')->fields('users', array('name'))->condition('name', + db_like($last_string) . '%', 'LIKE')->range(0, 10)->execute(); - $prefix = count($array) ? implode(', ', $array) .', ' : ''; + $prefix = count($array) ? implode(', ', $array) . ', ' : ''; - while ($user = db_fetch_object($result)) { + foreach ($result as $user) { $matches[$prefix . $user->name] = check_plain($user->name); } - if (module_exists('devel')) { - $GLOBALS['devel_shutdown'] = FALSE; - } - exit(drupal_json($matches)); + exit(drupal_json_output($matches)); }