123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735 |
- <?php
- function tac_lite_help($section) {
- switch ($section) {
- case 'admin/help#tac_lite':
-
- $output = '<p>' . t('Taxonomy Access Control Lite allows you to restrict access to site content. It uses a simple scheme based on Taxonomy, Users and Roles.') . '</p>';
- $output .= '<p>' . t('This module leverages Drupal\'s node_access table allows this module to grant permission to view, update, and delete nodes. To control which users can <em>create</em> new nodes, use Drupal\'s role based permissions.') . '</p>';
- $output .= '<p>' . t('It is important to understand that this module <em>grants</em> privileges, as opposed to <em>revoking</em> privileges. So, use Drupal\'s built-in permissions to hide content from certain roles, then use this module to show the content. This module cannot hide content that the user is allowed to see based on their existing privileges.') . '</p>';
- $output .= '<p>' . t('There are several steps required to set up Taxonomy Access Control Lite.') . '</p>';
- $output .= '<ol>';
- $output .= '<li>' . t('Define one or more vocabularies whose terms will control which users have access. For example, you could define a vocabulary called \'Privacy\' with terms \'Public\' and \'Private\'.') . '</li>';
- $output .= '<li>' . t('Tell this module which vocabularies control privacy. (!link)', array('!link' => l(t('administer -> people -> access control by taxonomy'), 'admin/people/access/tac_lite'))) . '</li>';
- $output .= '<li>' . t('Configure one or more <em>schemes</em>. simple site may need only one scheme which grants view permission. A more complex site might require additional schemes for update and delete. Each scheme associates roles and terms. Users will be granted priviliges based on their role and the terms with which nodes are tagged.') . '</li>';
- $output .= '<li>' . t('When settings are correct, <a href=!url>rebuild node_access permissions</a>.', array(
- '!url' => url('admin/reports/status/rebuild'),
- )) . '</li>';
- $output .= '<li>' . t('Optionally, grant access to individual users. (See the <em>access by taxonomy</em> tab, under user -> edit.)') . '</li>';
- $output .= '</ol>';
- $output .= '<p>' . t('Troubleshooting:.') . '<ul>';
- $output .= '<li>' . t('Try rebuilding node_access permissions.') . '</li>';
- $output .= '<li>' . t('Try disabling tac_lite.module, rebuilding permissions. With the module disabled, users should not have the privileges you are attempting to grant with this module.') . '</li>';
- $output .= '<li>' . t('The devel_node_access.module (part of <a href=!url>devel</a>) helps to see exactly what Drupal\'s node_access table is doing.', array(
- '!url' => 'http://drupal.org/project/devel',
- )) . '</li>';
- $output .= '</ul></p>';
- return $output;
- break;
- }
- }
- function tac_lite_permission() {
- return array(
- 'administer tac_lite' => array(
- 'title' => t('administer tac_lite'),
- 'description' => t('TODO Add a description for \'administer tac_lite\''),
- ),
- );
- }
- function tac_lite_menu() {
- global $user;
- $items = array();
- $items['admin/config/people/tac_lite'] = array(
- 'title' => 'Access by Taxonomy',
- 'description' => "taxonomy-based permissions by tac_lite",
- 'page callback' => 'drupal_get_form',
- 'page arguments' => array('tac_lite_admin_settings'),
- 'weight' => 1,
- 'access arguments' => array('administer tac_lite'),
- );
- $items['admin/config/people/tac_lite/settings'] = array(
- 'title' => 'Settings',
- 'type' => MENU_DEFAULT_LOCAL_TASK,
- 'weight' => -1,
- 'access arguments' => array('administer tac_lite'),
- );
- $schemes = variable_get('tac_lite_schemes', 1);
- for ($i = 1; $i <= $schemes; $i++) {
- $scheme = variable_get('tac_lite_config_scheme_'. $i, FALSE);
- if ($scheme) {
- $title = $scheme['name'];
- } else {
- $title = "Scheme $i";
- }
- $items['admin/config/people/tac_lite/scheme_' . $i] = array(
- 'title' => $title,
- 'page callback' => 'tac_lite_admin_settings_scheme',
- 'page arguments' => array((string)$i),
- 'type' => MENU_LOCAL_TASK,
- 'weight' => $i,
- 'access arguments' => array('administer tac_lite'),
- );
- }
- return $items;
- }
- function tac_lite_admin_settings($form, &$form_state) {
- $vocabularies = taxonomy_get_vocabularies();
- if (!count($vocabularies)) {
- $form['body'] = array(
- '#type' => 'markup',
- '#markup' => t('You must <a href="!url">create a vocabulary</a> before you can use tac_lite.',
- array('!url' => url('admin/structure/taxonomy/add/vocabulary'))),
- );
- return $form;
- }
- else {
- $options = array();
- foreach ($vocabularies as $vid => $vocab) {
- $options[$vid] = $vocab->name;
- }
- $form['tac_lite_categories'] = array(
- '#type' => 'select',
- '#title' => t('Vocabularies'),
- '#default_value' => variable_get('tac_lite_categories', NULL),
- '#options' => $options,
- '#description' => t('Select one or more vocabularies to control privacy. <br/>Use caution with hierarchical (nested) taxonomies as <em>visibility</em> settings may cause problems on node edit forms.<br/>Do not select free tagging vocabularies, they are not supported.'),
- '#multiple' => TRUE,
- '#required' => TRUE,
- );
- $scheme_options = array();
-
-
- for ($i = 1; $i < 8; $i++)
- $scheme_options[$i] = $i;
- $form['tac_lite_schemes'] = array(
- '#type' => 'select',
- '#title' => t('Number of Schemes'),
- '#description' => t('Each scheme allows for a different set of permissions. For example, use scheme 1 for read-only permission; scheme 2 for read and update; scheme 3 for delete; etc. Additional schemes increase the size of your node_access table, so use no more than you need.'),
- '#default_value' => variable_get('tac_lite_schemes', 1),
- '#options' => $scheme_options,
- '#required' => TRUE,
- );
- $form['tac_lite_rebuild'] = array(
- '#type' => 'checkbox',
- '#title' => t('Rebuild content permissions now'),
- '#default_value' => FALSE,
- '#description' => t('Do this once, after you have fully configured access by taxonomy.'),
- '#weight' => 9,
- );
- $ret = system_settings_form($form);
-
- $ret['#submit'][] = '_tac_lite_admin_settings_submit';
- return $ret;
- }
- }
- function _tac_lite_admin_settings_submit($form, &$form_state) {
- $rebuild = $form_state['values']['tac_lite_rebuild'];
-
- if ($rebuild) {
- node_access_rebuild(TRUE);
- }
- else {
- drupal_set_message(t('Do not forget to <a href=!url>rebuild node access permissions</a> after you have configured taxonomy-based access.', array(
- '!url' => url('admin/reports/status/rebuild'),
- )), 'warning');
- }
-
- menu_rebuild();
- variable_del('tac_lite_rebuild');
- }
- function tac_lite_admin_settings_scheme($i) {
- return drupal_get_form('tac_lite_admin_scheme_form', $i);
- }
- function _tac_lite_config($scheme) {
-
- if ($scheme === 1) {
- $config = variable_get('tac_lite_config_scheme_' . $scheme, array(
- 'name' => t('read'),
- 'perms' => array('grant_view'),
- ));
- }
- else {
- $config = variable_get('tac_lite_config_scheme_' . $scheme, array(
- 'name' => NULL,
- 'perms' => array(),
- ));
- }
-
- $config += array(
- 'term_visibility' => (isset($config['perms']['grant_view']) && $config['perms']['grant_view']),
- 'unpublished' => FALSE,
- );
-
- if ($scheme == 1) {
- $config['realm'] = 'tac_lite';
- }
- else {
- $config['realm'] = 'tac_lite_scheme_' . $scheme;
- }
- return $config;
- }
- function tac_lite_admin_scheme_form($form, $form_state, $i) {
- $vids = variable_get('tac_lite_categories', NULL);
- $roles = user_roles();
- $config = _tac_lite_config($i);
- $form['#tac_lite_config'] = $config;
- if (count($vids)) {
- $form['tac_lite_config_scheme_' . $i] = array('#tree' => TRUE);
- $form['tac_lite_config_scheme_' . $i]['name'] = array(
- '#type' => 'textfield',
- '#title' => t('Scheme name'),
- '#description' => t('A human-readable name for administrators to see. For example, \'read\' or \'read and write\'.'),
- '#default_value' => $config['name'],
- '#required' => TRUE,
- );
-
- $options = array(
- 'grant_view' => 'view',
- 'grant_update' => 'update',
- 'grant_delete' => 'delete',
- );
- $form['tac_lite_config_scheme_' . $i]['perms'] = array(
- '#type' => 'select',
- '#title' => t('Permissions'),
- '#multiple' => TRUE,
- '#options' => $options,
- '#default_value' => $config['perms'],
- '#description' => t('Select which permissions are granted by this scheme. <br/>Note when granting update, it is best to enable visibility on all terms. Otherwise a user may unknowingly remove invisible terms while editing a node.'),
- '#required' => FALSE,
- );
- $form['tac_lite_config_scheme_' . $i]['unpublished'] = array(
- '#type' => 'checkbox',
- '#title' => t('Apply to unpublished content'),
- '#description' => t('If checked, permissions in this scheme will apply to unpublished content. If this scheme includes the view permission, then <strong>unpublished nodes will be visible</strong> to users whose roles would grant them access to the published node.'),
- '#default_value' => $config['unpublished'],
- );
- $form['tac_lite_config_scheme_' . $i]['term_visibility'] = array(
- '#type' => 'checkbox',
- '#title' => t('Visibility'),
- '#description' => t('If checked, this scheme determines whether a user can view <strong>terms</strong>. Note the <em>view</em> permission in the select field above refers to <strong>node</strong> visibility. This checkbox refers to <strong>term</strong> visibility, for example in a content edit form or tag cloud.'),
- '#default_value' => $config['term_visibility'],
- );
- $form['helptext'] = array(
- '#type' => 'markup',
- '#markup' => t('To grant to an individual user, visit the <em>access by taxonomy</em> tab on the account edit page.'),
- '#prefix' => '<p>',
- '#suffix' => '</p>',
- );
- $form['helptext2'] = array(
- '#type' => 'markup',
- '#markup' => t('To grant by role, select the terms below.'),
- '#prefix' => '<p>',
- '#suffix' => '</p>',
- );
- $vocabularies = taxonomy_get_vocabularies();
- $all_defaults = variable_get('tac_lite_grants_scheme_' . $i, array());
- $form['tac_lite_grants_scheme_' . $i] = array('#tree' => TRUE);
- foreach ($roles as $rid => $role_name) {
- $form['tac_lite_grants_scheme_' . $i][$rid] = array(
- '#type' => 'fieldset',
- '#tree' => TRUE,
- '#title' => check_plain(t('Grant permission by role: !role', array('!role' => $role_name))),
- '#description' => t(''),
- '#collapsible' => TRUE,
- );
- $defaults = isset($all_defaults[$rid]) ? $all_defaults[$rid] : NULL;
- foreach ($vids as $vid) {
-
- $v = $vocabularies[$vid];
- $tree = taxonomy_get_tree($v->vid);
- $options = array(0 => '<' . t('none') . '>');
- if ($tree) {
- foreach ($tree as $term) {
- $choice = new stdClass();
- $choice->option = array($term->tid => str_repeat('-', $term->depth) . $term->name);
- $options[] = $choice;
- }
- }
- $default_values = isset($defaults[$vid]) ? $defaults[$vid] : NULL;
- $form['tac_lite_grants_scheme_' . $i][$rid][$vid] = _tac_lite_term_select($v, $default_values);
- }
- }
- $form['tac_lite_rebuild'] = array(
- '#type' => 'checkbox',
- '#title' => t('Rebuild content permissions now'),
- '#default_value' => FALSE,
- '#description' => t('Do this once, after you have fully configured access by taxonomy.'),
- '#weight' => 9,
- );
- $form['#submit'][] = 'tac_lite_admin_scheme_form_submit';
- return system_settings_form($form);
- }
- else {
- $form['tac_lite_help'] = array(
- '#type' => 'markup',
- '#prefix' => '<p>', '#suffix' => '</p>',
- '#markup' => t('First, select one or more vocabularies on the <a href=!url>settings tab</a>. Then, return to this page to complete configuration.', array('!url' => url('admin/config/people/tac_lite/settings'))));
- return $form;
- }
- }
- function tac_lite_admin_scheme_form_submit($form, &$form_state) {
- variable_set('menu_rebuild_needed', TRUE);
-
- if ($form_state['values']['tac_lite_rebuild']) {
- node_access_rebuild(TRUE);
- }
- else {
- drupal_set_message(t('Do not forget to <a href=!url>rebuild node access permissions</a> after you have configured taxonomy-based access.', array(
- '!url' => url('admin/reports/status/rebuild'),
- )), 'warning');
- }
- variable_del('tac_lite_rebuild');
- }
- function tac_lite_user_categories() {
- return array(
- array(
- 'name' => 'tac_lite',
- 'title' => t('Access by taxonomy'),
- 'weight' => 5,
- 'access callback' => 'user_access',
- 'access arguments' => array('administer users'),
- ),
- );
- }
- function tac_lite_form_alter(&$form, &$form_state, $form_id){
-
- if ($form_id == 'user_profile_form') {
- if ($form['#user_category'] == 'tac_lite') {
- $vocabularies = taxonomy_get_vocabularies();
- $vids = variable_get('tac_lite_categories', NULL);
- if (count($vids)) {
- for ($i = 1; $i <= variable_get('tac_lite_schemes', 1); $i++) {
- $config = _tac_lite_config($i);
- if ($config['name']) {
- $perms = $config['perms'];
- if ($config['term_visibility']) {
- $perms[] = t('term visibility');
- }
- $form['tac_lite'][$config['realm']] = array(
- '#type' => 'fieldset',
- '#title' => $config['name'],
- '#description' => t('This scheme controls %perms.', array('%perms' => implode(' and ', $perms))),
- '#tree' => TRUE,
- );
-
- foreach ($vids as $vid) {
- $v = $vocabularies[$vid];
-
-
- $default_values = array();
- if (!empty($form['#user']->data[$config['realm']])) {
- if (isset($form['#user']->data[$config['realm']][$vid])) {
- $default_values = $form['#user']->data[$config['realm']][$vid];
- }
- }
- $form['tac_lite'][$config['realm']][$vid] = _tac_lite_term_select($v, $default_values);
- $form['tac_lite'][$config['realm']][$vid]['#description'] =
- t('Grant permission to this user by selecting terms. Note that permissions are in addition to those granted based on user roles.');
- }
- }
- }
- $form['tac_lite'][0] = array(
- '#type' => 'markup',
- '#markup' => '<p>' . t('You may grant this user access based on the schemes and terms below. These permissions are in addition to <a href="!url">role based grants on scheme settings pages</a>.',
- array('!url' => url('admin/config/people/tac_lite/scheme_1'))) . "</p>\n",
- '#weight' => -1,
- );
- }
- else {
-
- }
- return $form;
- }
- }
- }
- function tac_lite_user_presave(&$edit, $account, $category) {
-
- if ($category == 'tac_lite'){
-
- for ($i = 1; $i <= variable_get('tac_lite_schemes', 1); $i++) {
- $config = _tac_lite_config($i);
- if ($config['name']) {
- $edit['data'][$config['realm']] = $edit[$config['realm']];
- }
- }
- }
- }
- function tac_lite_node_access_records($node) {
-
- $tids = _tac_lite_get_terms($node);
- if (!count($tids)) {
-
-
- }
- else {
-
-
- $grants = array();
- for ($i = 1; $i <= variable_get('tac_lite_schemes', 1); $i++) {
- $config = _tac_lite_config($i);
-
- if ($node->status || $config['unpublished']) {
- foreach ($tids as $tid) {
- $grant = array(
- 'realm' => $config['realm'],
- 'gid' => $tid,
- 'grant_view' => 0,
- 'grant_update' => 0,
- 'grant_delete' => 0,
- 'priority' => 0,
- );
- foreach ($config['perms'] as $perm) {
- $grant[$perm] = TRUE;
- }
- $grants[] = $grant;
- }
- }
- }
- return $grants;
- }
- }
- function _tac_lite_get_terms($node) {
- $tids = array();
-
- $vids = variable_get('tac_lite_categories', NULL);
- if ($vids) {
-
-
- $terms_by_vid = tac_lite_node_get_terms($node);
- if (!empty($terms_by_vid)) {
- foreach ($vids as $vid) {
- if (!empty($terms_by_vid[$vid])) {
- foreach ($terms_by_vid[$vid] as $tid => $term) {
- $tids[$tid] = $tid;
- }
- }
- }
- }
-
-
-
-
- $query = db_select('taxonomy_index', 'r');
- $t_alias = $query->join('taxonomy_term_data', 't', 'r.tid = t.tid');
- $v_alias = $query->join('taxonomy_vocabulary', 'v', 't.vid = v.vid');
- $query->fields( $t_alias );
- $query->condition("r.nid", $node->nid);
- $query->condition("t.vid", $vids, 'IN');
- $result = $query->execute();
- foreach ($result as $term) {
- if (empty($tids[$term->tid])) {
- watchdog('tac_lite', 'Unexpected term id %tid associated with !node. Please report this to !url.', array(
- '%tid' => $term->tid,
- '!node' => l($node->title, 'node/' . $node->nid),
- '!url' => 'https://drupal.org/node/1918272',
- ), WATCHDOG_DEBUG);
- }
- $tids[$term->tid] = $term->tid;
- }
- }
- elseif (user_access('administer tac_lite')) {
- drupal_set_message(t('tac_lite.module enabled, but not <a href=!admin_url>configured</a>. No tac_lite terms associated with %title.', array(
- '!admin_url' => url('admin/config/people/tac_lite'),
- '%title' => $node->title,
- )));
- }
- return $tids;
- }
- function tac_lite_node_get_terms($node) {
- $terms = &drupal_static(__FUNCTION__);
- if (!isset($terms[$node->nid])) {
-
- $fields = field_info_fields();
- foreach ($fields as $field_name => $field) {
-
- if ($field['type'] == 'taxonomy_term_reference' && field_info_instance('node', $field_name, $node->type)) {
- if (($items = field_get_items('node', $node, $field_name)) && is_array($items)) {
- foreach ($items as $item) {
-
-
- if (!empty($item['taxonomy_term'])) {
- $term = $item['taxonomy_term'];
- }
- else {
- $term = taxonomy_term_load($item['tid']);
- }
- if ($term) {
- $terms[$node->nid][$term->vid][$term->tid] = $term;
- }
- }
- }
- }
- }
- }
- return isset($terms[$node->nid]) ? $terms[$node->nid] : FALSE;
- }
- function _tac_lite_term_select($v, $default_values = array()) {
- $tree = taxonomy_get_tree($v->vid);
- $options = array(0 => '<' . t('none') . '>');
- if ($tree) {
- foreach ($tree as $term) {
- $choice = new stdClass();
- $choice->option = array($term->tid => str_repeat('-', $term->depth) . $term->name);
- $options[] = $choice;
- }
- }
- $field_array = array(
- '#type' => 'select',
- '#title' => $v->name,
- '#default_value' => $default_values,
- '#options' => $options,
- '#multiple' => TRUE,
- '#description' => $v->description,
- );
- return $field_array;
- }
- function _tac_lite_user_tids($account, $scheme) {
-
- $grants = array(0);
- $config = _tac_lite_config($scheme);
- $realm = $config['realm'];
- if (isset($account->data[$realm]) && count($account->data[$realm])) {
-
- foreach ($account->data[$realm] as $tids) {
- if (count($tids)) {
- $grants = array_merge($grants, $tids);
- }
- }
- }
-
- $defaults = variable_get('tac_lite_grants_scheme_' . $scheme, array());
- foreach ($account->roles as $rid => $role_name) {
- if (isset($defaults[$rid]) && count($defaults[$rid])) {
- foreach ($defaults[$rid] as $tids) {
- if (count($tids)) {
- $grants = array_merge($grants, $tids);
- }
- }
- }
- }
-
-
-
- unset($grants['']);
- return $grants;
- }
- function tac_lite_node_grants($account, $op) {
- $grants = array();
- for ($i = 1; $i <= variable_get('tac_lite_schemes', 1); $i++) {
- $config = _tac_lite_config($i);
- if (in_array('grant_' . $op, $config['perms'])) {
- $grants[$config['realm']] = _tac_lite_user_tids($account, $i);
- }
- }
- if (count($grants)) {
- return $grants;
- }
- }
- function tac_lite_query_term_access_alter(QueryAlterableInterface $query) {
- global $user;
-
- if (user_access('administer tac_lite')) {
- return;
- }
-
- $vids = variable_get('tac_lite_categories', NULL);
- $schemes = variable_get('tac_lite_schemes', 1);
- if (!$vids || !count($vids) || !$schemes) {
- return;
- }
-
- $term_visibility = FALSE;
- $tids = array();
- for ($i = 1; $i <= $schemes; $i++) {
- $config = _tac_lite_config($i);
- if ($config['term_visibility']) {
- $tids = array_merge($tids, _tac_lite_user_tids($user, $i));
- $term_visibility = TRUE;
- }
- }
- if ($term_visibility) {
-
- $primary_table = '';
- $t = $query->getTables();
- foreach($t as $key => $info) {
- if (!$info['join type']) {
- $primary_table = $info['alias'];
- }
- }
-
- $query->leftJoin('taxonomy_term_data', 'tac_td', $primary_table . '.tid = tac_td.tid');
- $or = db_or();
- $or->condition($primary_table . '.tid', $tids, 'IN');
- $or->condition('tac_td.vid', $vids, 'NOT IN');
- $query->condition($or);
- }
- }
|