You are here

og_vocab.module in OG Vocabulary 5

Same filename and directory in other branches
  1. 6 og_vocab.module
  2. 7 og_vocab.module

Give each group its own system controlled vocabularies

File

og_vocab.module
View source
<?php

/**
 * @file
 * Give each group its own system controlled vocabularies
 */

/**
 * If you already have a custom_url_rewrite function, please copy the contents of this one to your 
 * existing function and delete this one. See http://drupal.org/node/99927 and 
 * http://api.drupal.org/api/function/custom_url_rewrite/5.
 * 
 * @return void
 **/
function custom_url_rewrite($op, $result, $path) {
  if ($op == 'alias') {
    if (arg(0) == "node" && arg(2) == "og" && arg(4) == "terms") {

      // the system path to change or cloak
      $patterns[0] = '!^admin/content/taxonomy/edit/term/(\\d+)$!';

      // the new cloaked name
      $replacements[0] = 'node/' . arg(1) . '/og/vocab/edit/term/\\1';
      return preg_replace($patterns, $replacements, $path);
    }
  }
  if ($op == 'source') {

    // Do nothing.
  }

  // Do not forget to return $result!
  return $result;
}

/**
 * Implementation of hook_help().
 */
function og_vocab_help($section) {
  switch ($section) {
    case arg(2) == 'og' && arg(3) == 'vocab' && is_null(arg(4)):
      return t('Add or edit vocabularies that pertain only to this group. Each vocabulary will be shown on the post authoring form. Use categories to organize content within your group.');
  }
}

/**
 * Implementation of hook_menu().
 */
function og_vocab_menu($may_cache) {
  $items = array();
  global $user;
  if ($may_cache) {

    //
  }
  else {
    $gid = arg(1);
    if ($user->uid && arg(0) == 'node' && is_numeric($gid)) {
      $node = node_load($gid);
      if (og_is_group_type($node->type) && node_access('update', $node)) {
        $items[] = array(
          'path' => "node/{$gid}/og/vocab",
          'title' => t('Categories'),
          'callback' => 'og_vocab_overview_vocabularies',
          'callback arguments' => array(
            $gid,
          ),
          'weight' => 6,
          'type' => MENU_LOCAL_TASK,
        );
        $items[] = array(
          'path' => "node/{$gid}/og/vocab/add/vocabulary",
          'title' => t('Create vocabulary'),
          'callback' => 'drupal_get_form',
          'callback arguments' => array(
            'taxonomy_form_vocabulary',
          ),
          'type' => MENU_CALLBACK,
        );
        foreach ($node->og_vocabularies as $vid => $vocabulary) {
          $items[] = array(
            'path' => "node/{$gid}/og/vocab/terms/{$vid}",
            'title' => $vocabulary->name,
            'callback' => 'taxonomy_overview_terms',
            'callback arguments' => array(
              $vid,
            ),
            'type' => MENU_CALLBACK,
            'weight' => -10,
          );
          $items[] = array(
            'path' => "node/{$gid}/og/vocab/terms/{$vid}/list",
            'title' => t('List'),
            'type' => MENU_DEFAULT_LOCAL_TASK,
            'weight' => -10,
          );
          $items[] = array(
            'path' => "node/{$gid}/og/vocab/terms/{$vid}/add/term",
            'title' => t('Add term'),
            'callback' => 'drupal_get_form',
            'callback arguments' => array(
              'taxonomy_form_term',
              'vid' => $vid,
            ),
            'type' => MENU_LOCAL_TASK,
          );
          $items[] = array(
            'path' => "node/{$gid}/og/vocab/edit/vocabulary/{$vid}",
            'title' => t('Edit vocabulary'),
            'callback' => 'taxonomy_admin_vocabulary_edit',
            'callback arguments' => array(
              $vid,
            ),
            'type' => MENU_CALLBACK,
          );
          $terms = taxonomy_get_tree($vid);
          foreach ($terms as $key => $term) {
            $items[] = array(
              'path' => "node/{$gid}/og/vocab/edit/term/" . $term->tid,
              'title' => t('Edit term'),
              'callback' => 'taxonomy_admin_term_edit',
              'callback arguments' => $term->tid,
              'type' => MENU_CALLBACK,
            );
          }
        }
      }
    }
  }
  return $items;
}

// since this module has to run after taxonomy and before og_menu(), we just set og context in hook_init()
function og_vocab_init() {
  if (function_exists('drupal_set_content')) {

    // set group context if we own this term
    if (arg(0) == 'taxonomy' && arg(1) == 'term' && is_numeric(arg(2))) {
      $sql = "SELECT ogv.nid FROM {term_data} td INNER JOIN {og_vocab} ogv ON td.vid = ogv.vid WHERE td.tid = %d";

      // arg(2) is known numeric. see 2 lines above
      if ($gid = db_result(db_query($sql, arg(2)))) {
        og_set_group_context(node_load($gid));

        // again, breadcrumb is not correct here but menu system hasn't built yet.
      }
    }
  }
}
function og_vocab_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks[0]['info'] = t('Group categories');
      return $blocks;
    case 'view':
      switch ($delta) {
        case 0:
          $block = og_vocab_block_view();
          break;
      }
      return $block;
  }
}
function og_vocab_block_view() {
  $group_node = og_get_group_context();
  if ($group_node && node_access('view', $group_node)) {
    foreach ((array) $group_node->og_vocabularies as $vid => $vocab) {
      $tree = taxonomy_get_tree($vid);

      // TODO. link to full page view. maybe views provides this?
      // only show first 20 terms. wary of huge vocabs. not ideal.
      $tree = array_slice($tree, 0, 20);
      $items = og_vocab_build_list_items($index = 0, $tree);
      if ($items) {
        $output .= theme('item_list', $items, $vocab->name);
      }
    }
    $block['content'] = $output;
    $block['subject'] = t('Group categories');
    return $block;
  }
}
function og_vocab_build_list_items(&$index, $tree) {
  $items = array();
  $current_depth = $tree[$index]->depth;
  while ($index < count($tree) && $tree[$index]->depth >= $current_depth) {
    $term = $tree[$index];
    $count = taxonomy_term_count_nodes($term->tid);
    if ($count) {
      $term_path = "taxonomy/term/{$term->tid}";
      $term_link = l($term->name, $term_path, array(
        'title' => t($term->description),
      ));
      $item = $term_link . " ({$count})";
      if ($tree[$index + 1]->depth > $current_depth) {
        $index++;
        $items[] = array(
          'data' => $item,
          'children' => og_vocab_build_list_items($index, $tree),
        );
      }
      else {
        $items[] = $item;
        $index++;
      }
    }
    else {
      $index++;
    }
  }
  return $items;
}

/**
 * Implementation of hook_form_alter().
 */
function og_vocab_form_alter($form_id, &$form) {
  switch ($form_id) {
    case 'taxonomy_form_vocabulary':
      if (arg(0) == 'node' && is_numeric(arg(1)) && arg(2) == 'og') {
        $form['module'] = array(
          '#type' => 'value',
          '#value' => 'og_vocab',
        );
        $form['og'] = array(
          '#type' => 'value',
          '#value' => arg(1),
        );
        $omit = array_merge(variable_get('og_node_types', array(
          'og',
        )), variable_get('og_omitted', array()));
        foreach ($omit as $type) {
          unset($form['nodes']['#options'][$type]);
        }
      }
      break;
    case 'taxonomy_form_term':
      $vocab = taxonomy_get_vocabulary($form['vid']['#value']);
      if ($vocab->module == 'og_vocab') {
        unset($form['synonyms']);
      }
      break;
    case isset($form['type']) && $form['type']['#value'] . '_node_form' == $form_id:
      if (isset($form['taxonomy'])) {

        // remove from node form those vocabs that belong to groups other than us (if we even have a group)
        $groupnode = og_get_group_context();
        $where = "(v.module = 'og_vocab' AND ov.nid != %d)";
        $sql = "SELECT v.vid, v.tags FROM {vocabulary} v LEFT JOIN {og_vocab} ov ON v.vid = ov.vid WHERE {$where}";
        $result = db_query($sql, $groupnode->nid);
        while ($row = db_fetch_object($result)) {
          if ($row->tags) {
            unset($form['taxonomy']['tags'][$row->vid]);
          }
          else {
            unset($form['taxonomy'][$row->vid]);
          }
        }

        // remove categories fieldset if no vocabularies remain
        // first, unset tags if needed
        if (!count($form['taxonomy']['tags'])) {
          unset($form['taxonomy']['tags']);
        }
        if (!count(element_children($form['taxonomy']))) {
          unset($form['taxonomy']);
        }

        // If there's only one element remove the fieldset but keep the children
        if (count(element_children($form['taxonomy'])) == 1) {
          unset($form['taxonomy']['#type']);
          unset($form['taxonomy']['#title']);
          unset($form['taxonomy']['#collapsible']);
          unset($form['taxonomy']['#collapsed']);
        }
      }
      break;
  }
}

// TODO: this could be a submit handler if I had a way to know the inserted vid
function og_vocab_taxonomy($op, $type, $edit = NULL) {
  if ($type == 'vocabulary') {
    switch ($op) {
      case 'update':
        if ($edit['og']) {
          $sql = "UPDATE {og_vocab} SET nid=%d WHERE vid=%d";
          db_query($sql, $edit['og'], $edit['vid']);
        }
        break;
      case 'insert':
        if ($edit['og']) {
          $sql = "INSERT {og_vocab} (nid, vid) VALUES (%d, %d)";
          db_query($sql, $edit['og'], $edit['vid']);
        }
        break;
      case 'delete':
        $sql = "DELETE FROM {og_vocab} WHERE vid = %d";
        db_query($sql, $edit['vid']);
    }
  }
}

/**
 * List and manage vocabularies for a given group.
 */
function og_vocab_overview_vocabularies($gid) {
  $groupnode = node_load((int) $gid);
  drupal_set_title(check_plain($groupnode->title));

  // i tried fixing breadcrumb here with drupal_set_breadcrumb() and menu_set_location() but neither is satisfactory
  $links[] = l(t('add vocabulary'), "node/{$gid}/og/vocab/add/vocabulary", array(), drupal_get_destination());
  $output = theme('item_list', $links);
  $vocabularies = og_vocab_load_vocabularies($gid);
  foreach ($vocabularies as $vid => $vocabulary) {
    $types = array();
    foreach ($vocabulary->nodes as $type) {
      $node_type = node_get_types('name', $type);
      $types[] = $node_type ? $node_type : $type;
    }
    $rows[] = array(
      check_plain($vocabulary->name),
      implode(', ', $types),
      l(t('edit vocabulary'), "node/{$gid}/og/vocab/edit/vocabulary/{$vocabulary->vid}", array(), drupal_get_destination()),
      l(t('list terms'), "node/{$gid}/og/vocab/terms/{$vocabulary->vid}"),
      l(t('add terms'), "node/{$gid}/og/vocab/terms/{$vocabulary->vid}/add/term"),
    );
  }
  if (!$rows) {
    $rows[] = array(
      array(
        'data' => t('No categories'),
        'colspan' => 5,
      ),
    );
  }
  $header = array(
    t('Name'),
    t('Type'),
    array(
      'data' => 'Operations',
      'colspan' => 3,
    ),
  );
  return $output . theme('table', $header, $rows);
}

/**
 * Implementation of hook_nodeapi().
 */
function og_vocab_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'load':
      if (og_is_group_type($node->type)) {
        $node->og_vocabularies = og_vocab_load_vocabularies($node->nid);
      }
      break;
    case 'delete':
      if (og_is_group_type($node->type)) {
        $sql = "DELETE FROM {og_vocab} WHERE nid = %d";
        db_query($sql, $node->nid);
        foreach ($node->og_vocabularies as $vocabulary) {
          taxonomy_del_vocabulary($vocabulary->vid);
        }
      }
      break;
  }
}

// helper function for nodeapi('load')
function og_vocab_load_vocabularies($nid) {
  $sql = "SELECT * FROM {og_vocab} WHERE nid = %d";
  $result = db_query($sql, $nid);
  while ($row = db_fetch_object($result)) {
    $vocabs[$row->vid] = taxonomy_get_vocabulary($row->vid);
  }
  return $vocabs ? $vocabs : array();
}

// contributed by http://drupal.org/node/70462
// pathauto.module integration
function og_vocab_pathauto_taxonomy($op, $category = NULL) {
  switch ($op) {
    case 'placeholders':
      $placeholders = array();
      $placeholders[t('[ogname]')] = t('The name of the organic group this category belongs to.');
      return $placeholders;
    case 'values':
      $results = array();
      $results[t('[ogname]')] = '';
      $where = ' ov.vid = %d';
      $sql = "SELECT n.title FROM {node} n INNER JOIN {og_vocab} ov ON ov.nid = n.nid WHERE {$where}";
      $result = db_query($sql, $category->vid);
      while ($row = db_fetch_object($result)) {
        $name = $row->title;
        $results[t('[ogname]')] = pathauto_cleanstring($name);
      }
      return $results;
    default:
      break;
  }
}

Functions

Namesort descending Description
custom_url_rewrite If you already have a custom_url_rewrite function, please copy the contents of this one to your existing function and delete this one. See http://drupal.org/node/99927 and http://api.drupal.org/api/function/custom_url_rewrite/5.
og_vocab_block
og_vocab_block_view
og_vocab_build_list_items
og_vocab_form_alter Implementation of hook_form_alter().
og_vocab_help Implementation of hook_help().
og_vocab_init
og_vocab_load_vocabularies
og_vocab_menu Implementation of hook_menu().
og_vocab_nodeapi Implementation of hook_nodeapi().
og_vocab_overview_vocabularies List and manage vocabularies for a given group.
og_vocab_pathauto_taxonomy
og_vocab_taxonomy