0

I'm using Drupal 7, and a Bootstrap sub-theme. I am using the following code to add a new CSS class (taxonomy-[vocabulary-name]) to the classes_array array.

template.php

function bootstrap_gstt_preprocess_html(&$variables) {
  if (arg(0) == 'node' && is_numeric(arg(1))) {
    $node = node_load(arg(1));  
    $results = _bootstrap_gstt_taxonomy_node_get_terms($node); 
    $taxonomy_vocab = $results->name;
    if (is_array($results)) {
      foreach ($results as $item) {
        $taxonomy_vocab = "taxonomy-".strtolower(drupal_clean_css_identifier($item->name)); 
        $variables['classes_array'][] = $taxonomy_vocab;

        $variables['classes'] = implode(' ', $variables['classes_array']);
        dpm($variables['classes_array']); 
      }
    }
  }
}

function _bootstrap_gstt_taxonomy_node_get_terms($node, $key = 'tid') {
  static $terms;
  if (!isset($terms[$node->vid][$key])) {
    $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);
    $result = $query->execute();
    $terms[$node->vid][$key] = array();
    foreach ($result as $term) {
      $terms[$node->vid][$key][$term->$key] = $term;
    }
  }
  return $terms[$node->vid][$key];
}

html.tpl.php

<!DOCTYPE html>
<html<?php print $html_attributes;?><?php print $rdf_namespaces;?>>
<head>
  <link rel="profile" href="<?php print $grddl_profile; ?>" />
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <?php print $head; ?>
  <title><?php print $head_title; ?></title>
  <?php print $styles; ?>
  <!-- HTML5 element support for IE6-8 -->
  <!--[if lt IE 9]>
    <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->
  <?php print $scripts; ?>
</head>
<body<?php print $body_attributes; ?>>
  <div id="skip-link">
    <a href="#main-content" class="element-invisible element-focusable"><?php print t('Skip to main content'); ?></a>
  </div>
  <?php print $page_top; ?>
  <?php print $page; ?>
  <?php print $page_bottom; ?>
</body>
</html>

With dpm($variables['classes_array']);, the new CSS classes I added appear in the array, but they aren't output as body CSS classes.

Is there anything I need to change in my code?

  • what's code in file html.tpl.php ? – MrD Sep 5 '16 at 15:37
  • I'm voting to close this question as off-topic because it's been cross-posted on Stack Overflow. Please post a question to one site in the network only. – Clive Sep 5 '16 at 15:38
  • Clive - I'll remove it from the other stack overflow as this site is more relevant – wotney Sep 5 '16 at 16:20
  • Sounds good - while you're there, probably a good idea to add some more details. It isn't answerable at the moment, but probably will be if you edit the post and include the full preprocessing function (including signature), and details of what theme/base theme you're using – Clive Sep 5 '16 at 16:25
  • Clive - I can't seem to be able to delete my question on the other network :/ – wotney Sep 5 '16 at 16:58
1

You simply do as Drupal does in its html.tpl.php file. Instead of using <body<?php print $body_attributes; ?>>, you use the following code.

<body class="<?php print $classes; ?>" <?php print $attributes;?>>

$attributes is set from template_preprocess() with the following code.

  // Flatten out attributes, title_attributes, and content_attributes.
  // Because this function can be called very often, and often with empty
  // attributes, optimize performance by only calling drupal_attributes() if
  // necessary.
  $variables['attributes'] = $variables['attributes_array'] ? drupal_attributes($variables['attributes_array']) : '';
  $variables['title_attributes'] = $variables['title_attributes_array'] ? drupal_attributes($variables['title_attributes_array']) : '';
  $variables['content_attributes'] = $variables['content_attributes_array'] ? drupal_attributes($variables['content_attributes_array']) : '';

Also, you don't need the following line in bootstrap_gstt_preprocess_html().

$variables['classes'] = implode(' ', $variables['classes_array']);

template_process(), which is executed after bootstrap_gstt_preprocess_html(), contains the following code.

  // Flatten out classes.
  $variables['classes'] = implode(' ', $variables['classes_array']); 

So, what your code is doing is already done from Drupal.

As side note, this what I would change in the code you shown.

$results = _bootstrap_gstt_taxonomy_node_get_terms($node); 
$taxonomy_vocab = $results->name;
if (is_array($results)) {
  // Omissis.
}

Since _bootstrap_gstt_taxonomy_node_get_terms() is surely returning an array, you cannot access an object property as you do with $results->name.

$t_alias = $query->join('taxonomy_term_data', 't', 'r.tid = t.tid');
$v_alias = $query->join('taxonomy_vocabulary', 'v', 't.vid = v.vid');

If you are going to use the value returned from $query->join(), then you should use the following code.

$t_alias = $query->join('taxonomy_term_data', 't', 'r.tid = %alias.tid');
$query->join('taxonomy_vocabulary', 'v', "$t_alias.vid = %alias.vid");

Also, since you are using $key (whose default value is 'tid') in the rest of the code, you should probably use the following code.

$t_alias = $query->join('taxonomy_term_data', 't', "r.$key = %alias.$key");
$query->join('taxonomy_vocabulary', 'v', "$t_alias.vid = %alias.vid");

To understand what %alias means, see SelectQuery::join().

$condition: The condition on which to join this table. If the join requires values, this clause should use a named placeholder and the value or values to insert should be passed in the 4th parameter. For the first table joined on a query, this value is ignored as the first table is taken as the base table. The token %alias can be used in this string to be replaced with the actual alias. This is useful when $alias is modified by the database system, for example, when joining the same table more than once.

If you are sure the same table is not joined more than once, you can simply ignore the value returned from $query->join() and use the following code.

$query->join('taxonomy_term_data', 't', "r.$key = t.$key");
$query->join('taxonomy_vocabulary', 'v', 't.vid = v.vid');
  • A fantastic, detailed reply - thanks for your time and effort. It really is appreciated – wotney Sep 6 '16 at 9:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.