Hi all!

This morning I've realized that Taxonomy Super Select and Taxonomy Access Control Lite (http://drupal.org/project/tac_lite) aren't compatible. Well, this is 'cause both of these modules implements hook_form_alter in a different way.

Let's see deeper... As I've found, the execution sequence of the different implementations is:

  • tac_lite_create_form_alter
  • taxonomy_super_select_form_alter

Well, the first simply make an unset of the elements of the ['taxonomy'] select element of the $form variable when a user has not the proper permission to set these tags. BTW, with this solution if a user make a content with some tags and after that another user with less permission modify the content, there's the possibility of data lossing.

The latter, instead, as you know, wipes out the select element of the form and creates a new form element. This operation does not takes in account Taxonomy Access Control Lite permissions.

Well, I've modified Taxonomy Super Select module to take these permissions in account, adding a new recursive function and modifying the taxonomy_super_select_form_alter in the taxonomy_super_select.module file.

Here is the added function:

function _tss_taxonomy_fetch(&$taxonomy_form_node,$valid_tids){
  foreach($taxonomy_form_node as $key => $value ){   
        if(is_numeric($key)){
           if(!in_array($key, $valid_tids)){
              $taxonomy_form_node[$key]['#disabled'] = 'TRUE';
           }      
           foreach($value as $k => $v){
              if(is_numeric($k)){
                if(!in_array($k, $valid_tids)){
                $taxonomy_form_node[$key][$k]['#disabled'] = 'TRUE';
                }
                 _tss_taxonomy_fetch($taxonomy_form_node[$key][$k],$valid_tids);      
              }
           } 
        }  
  }
}

And this is the new code for taxonomy_super_select_form_alter :

function taxonomy_super_select_form_alter(&$form, $form_state, $form_id) {

  drupal_add_css(drupal_get_path('module', 'taxonomy_super_select') .'/taxonomy_super_select.css');
  // Taxonomy Edit Form
  if ($form_id == 'taxonomy_form_vocabulary') {
    $vid = $form['vid']['#value'];
    $vocab = taxonomy_vocabulary_load($vid);
    if ($vocab) {
      $tss = variable_get('taxonomy_super_select_vid_'. $vid, 0);
      // Position the name field higher
      // Add our own submit handler
      $form['#submit'][] = 'taxonomy_super_select_submit';
      // Create fieldset and form elements
      $form['settings']['tss'] = array(
        '#type'         => 'fieldset',
        '#title'        => t('Taxonomy Super Select'),
        '#collapsed'    => !$tss,
        '#collapsible'  => TRUE,
        '#tree'         => TRUE,
        '#weight'       => 3,
      );
      // Get list of all content types
      $types = node_get_types('names');
      // Loop through all types that are enabled for this vocab
      foreach ($vocab->nodes as $index => $type) {
        $options[$type] = $types[$type];
      }
      $options['-all-'] = t('All content types');
      $form['settings']['tss']['taxonomy_super_select_vid_'. $vid]['types'] = array(
        '#type'          => 'checkboxes',
        '#title'         => t('Enable Taxonomy Select for the Vocabulary Content Types Below'),
        '#options'       => $options,
        '#default_value' => $tss ? $tss['types'] : array(),
        '#weight'        => -1,
      );
      $form['settings']['tss']['taxonomy_super_select_vid_'. $vid]['parents'] = array(
        '#type'           => 'checkbox',
        '#title'          => t('Display parent terms as form items'),
        '#default_value'  => $tss ? $tss['parents'] : array(),
        '#return_value'   => 1,
        '#weight'         => 0,
        '#description'    => t('Leaving this disabled forces users to select dangling child terms. Useful for grouping terms with descriptive parent terms that are not themselves needed for display.'),
      );
      $form['settings']['tss']['taxonomy_super_select_vid_'. $vid]['collapsible'] = array(
        '#type'           => 'checkbox',
        '#title'          => t('Make this vocabulary collapsible'),
        '#default_value'  => $tss ? $tss['collapsible'] : TRUE,
        '#return_value'   => 1,
        '#weight'         => 0,
        '#description'    => t('Display this vocabulary in a fieldset (collapsible).'),
      );
      $form['settings']['tss']['taxonomy_super_select_vid_'. $vid]['terms_expanded'] = array(
        '#type'          => 'checkbox',
        '#title'         => t('Make all terms expanded by default'),
        '#default_value' => $tss ? $tss['terms_expanded'] : FALSE,
        '#description'   => t('Make all terms expanded by default. If unchecked, only parens who have at least a term selected are expanded.'),
        '#weight'         => 0,
      );
      $form['settings']['tss']['taxonomy_super_select_vid_'. $vid]['compact'] = array(
        '#type'          => 'checkbox',
        '#title'         => t('Compact presentation'),
        '#default_value' => $tss ? $tss['compact'] : FALSE,
        '#description'   => t('Make the presentation compact (no padding space, no description...)'),
        '#weight'         => 0,
      );

      if (module_exists('taxonomy_image')) {
        $form['settings']['tss']['taxonomy_super_select_vid_'. $vid]['image'] = array(
          '#type' => 'checkbox',
          '#title' => t('Allow Taxonomy Image to provide images with the terms'),
          '#default_value'  => ($tss ? $tss['image'] : array()),
          '#weight' => 2,
          );
      }
    }
  }

  // Node Edit Form
  if (strstr($form_id, '_node_form') && strstr($form['form_id']['#value'], '_node_form')) {       
    
    $content_type = $form['type']['#value'];
    // Get all vocabs for this content type
    $vocabularies = taxonomy_get_vocabularies($content_type);
    $valid_vocabs = array();
    foreach ($vocabularies as $vid => $vocabulary) {
      $tss[$vid] = variable_get('taxonomy_super_select_vid_'. $vid, 0);
      // Only operate on types for a vocabulary that are enabled
      if (isset($tss[$vid]['types'][$content_type]) || isset($tss[$vid]['types']['-all-'])) {
        // Show radio or checkbox based on the selection type
        $valid_vocabs[$vid] = $vocabulary->multiple ? 'checkbox' : 'radio';
        if ($vocabulary->tags) {
          // Remove any tags from the autocomplete form item (prevent duplicates)
          $tags[$vid] = $form['taxonomy']['tags'][$vid];
          $tags[$vid]['#required'] = FALSE;
          $tags[$vid]['#parents'] = array('taxonomy', 'tags', $vid);
          $tags[$vid]['#weight'] = -12;
          $tags[$vid]['#title'] = t('Enter New Tags');
          $tags[$vid]['#default_value'] = @$form_state['values']['taxonomy']['tags'][$vid];
          unset($form['taxonomy']['tags'][$vid]);
        }
        else{
          // Remove the default form rendering except for freetagging vocabs
          unset($form['taxonomy'][$vid]);
        }
      }
    }
    $form['#validate'][] = 'taxonomy_super_select_node_form_validate';

    // Go through each enabled vocab and create taxonomy super select
    foreach ($valid_vocabs as $vid => $input) {
      // Get root terms for vocabulary only
      if (!$terms = taxonomy_get_tree($vid, 0, -1, 1)) {
        continue;
      }
      if (module_exists('i18ntaxonomy')) {
        $terms = i18ntaxonomy_localize_terms($terms);
      }
      $form['taxonomy'][$vid] = _tss_branch($vid, $vocabularies[$vid]);
      if (isset($tags[$vid])) {
        $form['taxonomy'][$vid]['tags'] = $tags[$vid];
      }
      _tss_next_nested($terms, $vid, $input, $tss, $form['#node'], $form['taxonomy'][$vid]);
      
      if(module_exists('tac_lite')){
        
        global $user;   
        
        if (user_access('administer tac_lite')) {
          // no need to restrict based on update permission in this cases
          return;
        }
        
        // the terms this user is allowed to edit
        $tids = array();
        for ($i = 1; $i <= variable_get('tac_lite_schemes', 1); $i++) {
          $config = _tac_lite_config($i);
          if ((isset($config['tac_lite_create']) && $config['tac_lite_create']) ||
            in_array('grant_update', $config['perms'])) {
            $tids = array_merge($tids, _tac_lite_user_tids($user, $i));
          }
        }
        _tss_taxonomy_fetch($form['taxonomy'][$vid],$tids);
      }              
    }
  }
}

Interesting part of this code is after the _tss_next_nested call in the Node Edit Form branch, where I've recicled part of the Taxonomy Access Control Lite code to retrieve the allowed tags and after, with the new function, the form element created by Taxonomy Super Select is fetched and the not allowed tags are disabled.

Well, that's all...I hope this helps someone...
Could a patch be useful?

Antonio

Comments

jcisio’s picture

Could a patch be useful?

Naturally, for easier review.

andou’s picture

yep... tomorrow at work I'll do this patch...

jcisio’s picture

Status: Needs review » Active

Always waiting for a patch ;)

And I've just committed a patch for another issue #703020-6: Compatibility with term-level permission control modules where a module modifies the taxonomy element of node-edit form. I don't know if they are related, as I haven't reviewed this "patch".

gooddesignusa’s picture

Does this also happen when using TAC, not TAC lite?

cassio’s picture

I would really appreciate some sense of if this was fixed by the other patch, if it's still an issue.

Also, I don't really understand what is meant by the collapsible option?

--Sam