taxonomy.module
<?php
function taxonomy_help($path, $arg) {
switch ($path) {
case 'admin/help#taxonomy':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('The Taxonomy module allows you to classify the content of your website. To classify content, you define <em>vocabularies</em> that contain related <em>terms</em>, and then assign the vocabularies to content types. For more information, see the online handbook entry for the <a href="@taxonomy">Taxonomy module</a>.', array('@taxonomy' => 'http://drupal.org/handbook/modules/taxonomy/')) . '</p>';
$output .= '<h3>' . t('Uses') . '</h3>';
$output .= '<dl>';
$output .= '<dt>' . t('Creating vocabularies') . '</dt>';
$output .= '<dd>' . t('Users with sufficient <a href="@perm">permissions</a> can create <em>vocabularies</em> and <em>terms</em> through the <a href="@taxo">Taxonomy page</a>. The page listing the terms provides a drag-and-drop interface for controlling the order of the terms and sub-terms within a vocabulary, in a hierarchical fashion. A <em>controlled vocabulary</em> classifying music by genre with terms and sub-terms could look as follows:', array('@taxo' => url('admin/structure/taxonomy'), '@perm' => url('admin/config/people/permissions', array('fragment'=>'module-taxonomy'))));
$output .= '<ul><li>' . t ('<em>vocabulary</em>: Music'); '</li>';
$output .= '<ul><li>' . t('<em>term</em>: Jazz') . '</li>';
$output .= '<ul><li>' . t('<em>sub-term</em>: Swing') . '</li>';
$output .= '<li>' . t('<em>sub-term</em>: Fusion') . '</li></ul></ul>';
$output .= '<ul><li>' . t('<em>term</em>: Rock') . '</li>';
$output .= '<ul><li>' . t('<em>sub-term</em>: Country rock') . '</li>';
$output .= '<li>' . t('<em>sub-term</em>: Hard rock') . '</li></ul></ul></ul>';
$output .= t('You can assign a sub-term to multiple parent terms. For example, <em>fusion</em> can be assigned to both <em>rock</em> and <em>jazz</em>.') . '</dd>';
$output .= '<dd>' . t('Terms in a <em>free-tagging vocabulary</em> can be built gradually as you create or edit content. This is often done used for blogs or photo management applications.') . '</dd>';
$output .= '<dt>' . t('Assigning vocabularies to content types') . '</dt>';
$output .= '<dd>' . t('Before you can use a new vocabulary to classify your content, a new Taxonomy term field must be added to a <a href="@ctedit">content type</a> on its <em>manage fields</em> page. When adding a taxonomy field, you choose a <em>widget</em> to use to enter the taxonomy information on the conent editing page: a select list, checkboxes, radio buttons, or an auto-complete field (to build a free-tagging vocabulary). After choosing the field type and widget, on the subsequent <em>field settings</em> page you can choose the desired vocabulary, whether one or multiple terms can be chosen from the vocabulary, and other settings. The same vocabulary can be added to multiple content types, by using the "Add existing field" section on the manage fields page.', array('@ctedit' => url('admin/structure/types'))) . '</dd>';
$output .= '<dt>' . t('Classifying content') . '</dt>';
$output .= '<dd>' . t('After the vocabulary is assigned to the content type, you can start classifying content. The field with terms will appear on the content editing screen when you edit or <a href="@addnode">create content</a>.', array('@addnode' => url('node/add'))) . '</dd>';
$output .= '<dt>' . t('Viewing listings and RSS feeds by term') . '</dt>';
$output .= '<dd>' . t("Each taxonomy term automatically provides a page listing content that has its classification, and a corresponding RSS feed. For example, if the taxonomy term <em>country rock</em> has the ID 123 (you can see this by looking at the URL when hovering on the linked term, which you can click to navigate to the listing page), then you will find this list at the path <em>taxonomy/term/123</em>. The RSS feed will use the path <em>taxonomy/term/123/feed</em> (the RSS icon for this term's listing will automatically display in your browser's address bar when viewing the listing page).") . '</dd>';
$output .= '<dt>' . t('Extending Taxonomy module') . '</dt>';
$output .= '<dd>' . t('There are <a href="@taxcontrib">many contributed modules</a> that extend the behavior of the Taxonomy module for both display and organization of terms.', array('@taxcontrib' => 'http://drupal.org/project/modules?filters=tid:71&solrsort=sis_project_release_usage%20desc'));
$output .= '</dl>';
return $output;
case 'admin/structure/taxonomy':
$output = '<p>' . t('Configure the vocabularies and terms for your site.') . '</p>';
return $output;
case 'admin/structure/taxonomy/%':
$vocabulary = taxonomy_vocabulary_load($arg[3]);
switch ($vocabulary->hierarchy) {
case 0:
return '<p>' . t('You can reorganize the terms in %capital_name using their drag and drop handles, and group terms under a parent term by sliding them under and to the right of the parent.', array('%capital_name' => drupal_ucfirst($vocabulary->name), '%name' => $vocabulary->name)) . '</p>';
case 1:
return '<p>' . t('%capital_name contains terms grouped with parent terms. You can reorganize the terms in %capital_name using their drag and drop handles.', array('%capital_name' => drupal_ucfirst($vocabulary->name), '%name' => $vocabulary->name)) . '</p>';
case 2:
return '<p>' . t('%capital_name contains terms with multiple parents. Drag and drop of terms with multiple parents is not supported, but you can re-enable drag and drop support by editing each term to include only a single parent.', array('%capital_name' => drupal_ucfirst($vocabulary->name))) . '</p>';
}
case 'admin/structure/taxonomy/add':
return '<p>' . t('To create a new taxonomy vocabulary, type in a name and a description.') . '</p>';
}
}
function taxonomy_permission() {
$permissions = array(
'administer taxonomy' => array(
'title' => t('Administer vocabularies and terms'),
),
);
foreach (taxonomy_get_vocabularies() as $vocabulary) {
$permissions += array(
'edit terms in ' . $vocabulary->vid => array(
'title' => t('Edit terms in %vocabulary', array('%vocabulary' => $vocabulary->name)),
),
);
$permissions += array(
'delete terms in ' . $vocabulary->vid => array(
'title' => t('Delete terms from %vocabulary', array('%vocabulary' => $vocabulary->name)),
),
);
}
return $permissions;
}
function taxonomy_entity_info() {
$return = array(
'taxonomy_term' => array(
'label' => t('Taxonomy term'),
'controller class' => 'TaxonomyTermController',
'base table' => 'taxonomy_term_data',
'fieldable' => TRUE,
'object keys' => array(
'id' => 'tid',
'bundle' => 'vocabulary_machine_name',
),
'bundle keys' => array(
'bundle' => 'machine_name',
),
'bundles' => array(),
),
);
foreach (taxonomy_vocabulary_get_names() as $machine_name => $vocabulary) {
$return['taxonomy_term']['bundles'][$machine_name] = array(
'label' => $vocabulary->name,
'admin' => array(
'path' => 'admin/structure/taxonomy/%taxonomy_vocabulary',
'real path' => 'admin/structure/taxonomy/' . $vocabulary->vid,
'bundle argument' => 3,
'access arguments' => array('administer taxonomy'),
),
);
}
$return['taxonomy_vocabulary'] = array(
'label' => t('Taxonomy vocabulary'),
'controller class' => 'TaxonomyVocabularyController',
'base table' => 'taxonomy_vocabulary',
'object keys' => array(
'id' => 'vid',
),
'fieldable' => FALSE,
);
return $return;
}
function taxonomy_select_nodes($tid, $pager = TRUE, $limit = FALSE, $order = array('t.sticky' => 'DESC', 't.created' => 'DESC')) {
if (!variable_get('taxonomy_maintain_index_table', TRUE)) {
return array();
}
$query = db_select('taxonomy_index', 't');
$query->addTag('node_access');
if ($pager) {
$count_query = clone $query;
$count_query->addExpression('COUNT(t.nid)');
$query = $query->extend('PagerDefault');
if ($limit !== FALSE) {
$query = $query->limit($limit);
}
$query->setCountQuery($count_query);
}
else {
if ($limit !== FALSE) {
$query->range(0, $limit);
}
}
$query->condition('tid', $tid);
$query->addField('t', 'nid');
$query->addField('t', 'tid');
foreach ($order as $field => $direction) {
$query->orderBy($field, $direction);
list($table_alias, $name) = explode('.', $field);
$query->addField($table_alias, $name);
}
return $query->execute()->fetchCol();
}
function taxonomy_field_build_modes($obj_type) {
$modes = array();
if ($obj_type == 'term') {
$modes = array(
'full' => t('Taxonomy term page'),
);
}
return $modes;
}
function taxonomy_theme() {
return array(
'taxonomy_overview_vocabularies' => array(
'render element' => 'form',
),
'taxonomy_overview_terms' => array(
'render element' => 'form',
),
);
}
function taxonomy_menu() {
$items['admin/structure/taxonomy'] = array(
'title' => 'Taxonomy',
'description' => 'Manage tagging, categorization, and classification of your content.',
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_overview_vocabularies'),
'access arguments' => array('administer taxonomy'),
'file' => 'taxonomy.admin.inc',
);
$items['admin/structure/taxonomy/list'] = array(
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items['admin/structure/taxonomy/add'] = array(
'title' => 'Add vocabulary',
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_form_vocabulary'),
'access arguments' => array('administer taxonomy'),
'type' => MENU_LOCAL_ACTION,
'file' => 'taxonomy.admin.inc',
);
$items['taxonomy/term/%taxonomy_term'] = array(
'title' => 'Taxonomy term',
'title callback' => 'taxonomy_term_title',
'title arguments' => array(2),
'page callback' => 'taxonomy_term_page',
'page arguments' => array(2),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'taxonomy.pages.inc',
);
$items['taxonomy/term/%taxonomy_term/view'] = array(
'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['taxonomy/term/%taxonomy_term/edit'] = array(
'title' => 'Edit term',
'title callback' => 'taxonomy_term_title',
'title arguments' => array(2),
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_form_term', 2),
'access callback' => 'taxonomy_term_edit_access',
'access arguments' => array(2),
'type' => MENU_LOCAL_TASK,
'weight' => 10,
'file' => 'taxonomy.admin.inc',
);
$items['taxonomy/term/%taxonomy_term/feed'] = array(
'title' => 'Taxonomy term',
'title callback' => 'taxonomy_term_title',
'title arguments' => array(2),
'page callback' => 'taxonomy_term_feed',
'page arguments' => array(2),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'taxonomy.pages.inc',
);
$items['taxonomy/autocomplete'] = array(
'title' => 'Autocomplete taxonomy',
'page callback' => 'taxonomy_autocomplete',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'taxonomy.pages.inc',
);
$items['admin/structure/taxonomy/%taxonomy_vocabulary'] = array(
'title callback' => 'taxonomy_admin_vocabulary_title_callback',
'title arguments' => array(3),
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_overview_terms', 3),
'access arguments' => array('administer taxonomy'),
'file' => 'taxonomy.admin.inc',
);
$items['admin/structure/taxonomy/%taxonomy_vocabulary/list'] = array(
'title' => 'List',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -20,
);
$items['admin/structure/taxonomy/%taxonomy_vocabulary/edit'] = array(
'title' => 'Edit',
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_form_vocabulary', 3),
'access arguments' => array('administer taxonomy'),
'type' => MENU_LOCAL_TASK,
'weight' => -10,
'file' => 'taxonomy.admin.inc',
);
$items['admin/structure/taxonomy/%taxonomy_vocabulary/add'] = array(
'title' => 'Add term',
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_form_term', array(), 3),
'access arguments' => array('administer taxonomy'),
'type' => MENU_LOCAL_ACTION,
'file' => 'taxonomy.admin.inc',
);
return $items;
}
function taxonomy_term_edit_access($term) {
return user_access("edit terms in $term->vid") || user_access('administer taxonomy');
}
function taxonomy_admin_vocabulary_title_callback($vocabulary) {
return check_plain($vocabulary->name);
}
function taxonomy_vocabulary_save($vocabulary) {
if (!empty($vocabulary->name)) {
$vocabulary->name = trim($vocabulary->name);
}
if (!isset($vocabulary->module)) {
$vocabulary->module = 'taxonomy';
}
if (!empty($vocabulary->vid) && !empty($vocabulary->name)) {
$status = drupal_write_record('taxonomy_vocabulary', $vocabulary, 'vid');
module_invoke_all('taxonomy_vocabulary_update', $vocabulary);
}
elseif (empty($vocabulary->vid)) {
$status = drupal_write_record('taxonomy_vocabulary', $vocabulary);
field_attach_create_bundle('taxonomy_term', $vocabulary->machine_name);
taxonomy_vocabulary_create_field($vocabulary);
module_invoke_all('taxonomy_vocabulary_insert', $vocabulary);
}
cache_clear_all();
entity_get_controller('taxonomy_vocabulary')->resetCache();
return $status;
}
function taxonomy_vocabulary_delete($vid) {
$vocabulary = (array) taxonomy_vocabulary_load($vid);
db_delete('taxonomy_vocabulary')
->condition('vid', $vid)
->execute();
$result = db_query('SELECT tid FROM {taxonomy_term_data} WHERE vid = :vid', array(':vid' => $vid))->fetchCol();
foreach ($result as $tid) {
taxonomy_term_delete($tid);
}
field_attach_delete_bundle('taxonomy_term', $vocabulary['machine_name']);
module_invoke_all('taxonomy', 'delete', 'vocabulary', $vocabulary);
cache_clear_all();
entity_get_controller('taxonomy_vocabulary')->resetCache();
return SAVED_DELETED;
}
function taxonomy_check_vocabulary_hierarchy($vocabulary, $changed_term) {
$tree = taxonomy_get_tree($vocabulary->vid);
$hierarchy = 0;
foreach ($tree as $term) {
if ($term->tid == $changed_term['tid']) {
$term = (object)$changed_term;
$term->parents = $term->parent;
}
if (count($term->parents) > 1) {
$hierarchy = 2;
break;
}
elseif (count($term->parents) == 1 && 0 !== array_shift($term->parents)) {
$hierarchy = 1;
}
}
if ($hierarchy != $vocabulary->hierarchy) {
$vocabulary->hierarchy = $hierarchy;
taxonomy_vocabulary_save($vocabulary);
}
return $hierarchy;
}
function taxonomy_vocabulary_create_field($vocabulary) {
$field = array(
'field_name' => 'taxonomy_' . $vocabulary->machine_name,
'type' => 'taxonomy_term',
'cardinality' => FIELD_CARDINALITY_UNLIMITED,
'settings' => array(
'allowed_values' => array(
array(
'vid' => $vocabulary->vid,
'parent' => 0,
),
),
),
);
field_create_field($field);
}
function taxonomy_term_save($term) {
if ($term->name) {
$term->name = trim($term->name);
}
if (!isset($term->vocabulary_machine_name)) {
$vocabulary = taxonomy_vocabulary_load($term->vid);
$term->vocabulary_machine_name = $vocabulary->machine_name;
}
field_attach_presave('taxonomy_term', $term);
if (!empty($term->tid) && $term->name) {
$status = drupal_write_record('taxonomy_term_data', $term, 'tid');
field_attach_update('taxonomy_term', $term);
module_invoke_all('taxonomy_term_update', $term);
}
else {
$status = drupal_write_record('taxonomy_term_data', $term);
_taxonomy_clean_field_cache($term);
field_attach_insert('taxonomy_term', $term);
module_invoke_all('taxonomy_term_insert', $term);
}
db_delete('taxonomy_term_hierarchy')
->condition('tid', $term->tid)
->execute();
if (!isset($term->parent) || empty($term->parent)) {
$term->parent = array(0);
}
if (!is_array($term->parent)) {
$term->parent = array($term->parent);
}
$query = db_insert('taxonomy_term_hierarchy')
->fields(array('tid', 'parent'));
if (is_array($term->parent)) {
foreach ($term->parent as $parent) {
if (is_array($parent)) {
foreach ($parent as $tid) {
$query->values(array(
'tid' => $term->tid,
'parent' => $tid
));
}
}
else {
$query->values(array(
'tid' => $term->tid,
'parent' => $parent
));
}
}
}
$query->execute();
cache_clear_all();
taxonomy_terms_static_reset();
return $status;
}
function taxonomy_term_delete($tid) {
$tids = array($tid);
while ($tids) {
$children_tids = $orphans = array();
foreach ($tids as $tid) {
if ($children = taxonomy_get_children($tid)) {
foreach ($children as $child) {
$parents = taxonomy_get_parents($child->tid);
if (count($parents) == 1) {
$orphans[] = $child->tid;
}
}
}
$term = taxonomy_term_load($tid);
db_delete('taxonomy_term_data')
->condition('tid', $tid)
->execute();
db_delete('taxonomy_term_hierarchy')
->condition('tid', $tid)
->execute();
field_attach_delete('taxonomy_term', $term);
_taxonomy_clean_field_cache($term);
module_invoke_all('taxonomy_term_delete', $term);
}
$tids = $orphans;
}
cache_clear_all();
taxonomy_terms_static_reset();
return SAVED_DELETED;
}
function taxonomy_terms_static_reset() {
drupal_static_reset('taxonomy_term_count_nodes');
drupal_static_reset('taxonomy_get_tree');
entity_get_controller('taxonomy_term')->resetCache();
}
function taxonomy_form_all() {
$vocabularies = taxonomy_get_vocabularies();
$options = array();
foreach ($vocabularies as $vid => $vocabulary) {
$tree = taxonomy_get_tree($vid);
if ($tree && (count($tree) > 0)) {
$options[$vocabulary->name] = array();
foreach ($tree as $term) {
$options[$vocabulary->name][$term->tid] = str_repeat('-', $term->depth) . $term->name;
}
}
}
return $options;
}
function taxonomy_get_vocabularies() {
return taxonomy_vocabulary_load_multiple(FALSE, array());
}
function taxonomy_vocabulary_get_names() {
$names = db_query('SELECT name, machine_name, vid FROM {taxonomy_vocabulary}')->fetchAllAssoc('machine_name');
return $names;
}
function taxonomy_get_parents($tid, $key = 'tid') {
if ($tid) {
$query = db_select('taxonomy_term_data', 't');
$query->join('taxonomy_term_hierarchy', 'h', 'h.parent = t.tid');
$result = $query
->addTag('translatable')
->addTag('term_access')
->fields('t')
->condition('h.tid', $tid)
->orderBy('weight')
->orderBy('name')
->execute();
$parents = array();
foreach ($result as $parent) {
$parents[$parent->$key] = $parent;
}
return $parents;
}
else {
return array();
}
}
function taxonomy_get_parents_all($tid) {
$cache = &drupal_static(__FUNCTION__, array());
if (isset($cache[$tid])) {
return $cache[$tid];
}
$parents = array();
if ($term = taxonomy_term_load($tid)) {
$parents[] = $term;
$n = 0;
while ($parent = taxonomy_get_parents($parents[$n]->tid)) {
$parents = array_merge($parents, $parent);
$n++;
}
}
$cache[$tid] = $parents;
return $parents;
}
function taxonomy_get_children($tid, $vid = 0, $key = 'tid') {
$query = db_select('taxonomy_term_data', 't');
$query->join('taxonomy_term_hierarchy', 'h', 'h.tid = t.tid');
$query
->addTag('translatable')
->addTag('term_access')
->fields('t')
->condition('parent', $tid)
->orderBy('weight')
->orderBy('name');
if ($vid) {
$query->condition('t.vid', $vid);
}
$result = $query->execute();
$children = array();
foreach ($result as $term) {
$children[$term->$key] = $term;
}
return $children;
}
function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $depth = -1) {
$children = &drupal_static(__FUNCTION__, array());
$parents = &drupal_static(__FUNCTION__ . 'parents', array());
$terms = &drupal_static(__FUNCTION__ . 'terms', array());
$depth++;
if (!isset($children[$vid])) {
$children[$vid] = array();
$parents[$vid] = array();
$terms[$vid] = array();
$query = db_select('taxonomy_term_data', 't');
$query->join('taxonomy_term_hierarchy', 'h', 'h.tid = t.tid');
$result = $query
->addTag('translatable')
->addTag('term_access')
->fields('t')
->fields('h', array('parent'))
->condition('t.vid', $vid)
->orderBy('weight')
->orderBy('name')
->execute();
foreach ($result as $term) {
$children[$vid][$term->parent][] = $term->tid;
$parents[$vid][$term->tid][] = $term->parent;
$terms[$vid][$term->tid] = $term;
}
}
$max_depth = (is_null($max_depth)) ? count($children[$vid]) : $max_depth;
$tree = array();
if ($max_depth > $depth && !empty($children[$vid][$parent])) {
foreach ($children[$vid][$parent] as $child) {
$term = clone $terms[$vid][$child];
$term->depth = $depth;
unset($term->parent);
$term->parents = $parents[$vid][$child];
$tree[] = $term;
if (!empty($children[$vid][$child])) {
$tree = array_merge($tree, taxonomy_get_tree($vid, $child, $max_depth, $depth));
}
}
}
return $tree;
}
function taxonomy_get_term_by_name($name) {
return taxonomy_term_load_multiple(array(), array('name' => trim($name)));
}
class TaxonomyTermController extends DrupalDefaultEntityController {
protected $type;
public function load($ids = array(), $conditions = array()) {
if (isset($conditions['type'])) {
$this->type = $conditions['type'];
unset($conditions['type']);
}
return parent::load($ids, $conditions);
}
protected function buildQuery() {
parent::buildQuery();
$this->query->addTag('translatable');
$this->query->addTag('term_access');
if (isset($this->conditions['name'])) {
$conditions = &$this->query->conditions();
foreach ($conditions as $key => $condition) {
if ($condition['field'] == 'base.name') {
$conditions[$key]['operator'] = 'LIKE';
}
}
}
$this->query->innerJoin('taxonomy_vocabulary', 'v', 'base.vid = v.vid');
$this->query->addField('v', 'machine_name', 'vocabulary_machine_name');
}
protected function cacheGet($ids, $conditions = array()) {
$terms = parent::cacheGet($ids, $conditions);
foreach ($terms as $term) {
$term_values = (array) $term;
if (isset($this->conditions['name']) && drupal_strtolower($this->conditions['name'] != drupal_strtolower($term_values['name']))) {
unset($terms[$term->tid]);
}
}
return $terms;
}
}
class TaxonomyVocabularyController extends DrupalDefaultEntityController {
protected function buildQuery() {
parent::buildQuery();
$this->query->addTag('translatable');
$this->query->orderBy('base.weight');
$this->query->orderBy('base.name');
}
protected function attachLoad(&$records) {
foreach ($records as $record) {
$queried_vocabularies[$record->vid] = $record;
}
$records = $queried_vocabularies;
parent::attachLoad($records);
}
}
function taxonomy_term_load_multiple($tids = array(), $conditions = array()) {
return entity_load('taxonomy_term', $tids, $conditions);
}
function taxonomy_vocabulary_load_multiple($vids = array(), $conditions = array()) {
return entity_load('taxonomy_vocabulary', $vids, $conditions);
}
function taxonomy_vocabulary_load($vid) {
$vocabularies = taxonomy_vocabulary_load_multiple(array($vid));
return reset($vocabularies);
}
function taxonomy_term_load($tid) {
if (!is_numeric($tid)) {
return FALSE;
}
$term = taxonomy_term_load_multiple(array($tid), array());
return $term ? $term[$tid] : FALSE;
}
function _taxonomy_get_tid_from_term($term) {
return $term->tid;
}
function taxonomy_implode_tags($tags, $vid = NULL) {
$typed_tags = array();
foreach ($tags as $tag) {
if (is_null($vid) || $tag->vid == $vid) {
if (strpos($tag->name, ',') !== FALSE || strpos($tag->name, '"') !== FALSE) {
$tag->name = '"' . str_replace('"', '""', $tag->name) . '"';
}
$typed_tags[] = $tag->name;
}
}
return implode(', ', $typed_tags);
}
function taxonomy_field_info() {
return array(
'taxonomy_term' => array(
'label' => t('Taxonomy term'),
'description' => t('This field stores a reference to a taxonomy term.'),
'default_widget' => 'options_select',
'default_formatter' => 'taxonomy_term_link',
'settings' => array(
'allowed_values' => array(
array(
'vid' => '0',
'parent' => '0',
),
),
),
),
);
}
function taxonomy_field_widget_info() {
return array(
'taxonomy_autocomplete' => array(
'label' => t('Autocomplete term widget (tagging)'),
'field types' => array('taxonomy_term'),
'settings' => array(
'size' => 60,
'autocomplete_path' => 'taxonomy/autocomplete',
),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM,
),
),
);
}
function taxonomy_field_widget_info_alter(&$info) {
$info['options_select']['field types'][] = 'taxonomy_term';
$info['options_buttons']['field types'][] = 'taxonomy_term';
}
function taxonomy_field_schema($field) {
return array(
'columns' => array(
'tid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => FALSE,
),
),
'indexes' => array(
'tid' => array('tid'),
),
);
}
function taxonomy_field_validate($obj_type, $object, $field, $instance, $langcode, $items, &$errors) {
$allowed_values = taxonomy_allowed_values($field);
$widget = field_info_widget_types($instance['widget']['type']);
if ($widget['behaviors']['multiple values'] == FIELD_BEHAVIOR_CUSTOM && $field['cardinality'] >= 2) {
if (count($items) > $field['cardinality']) {
$errors[$field['field_name']][$langcode][0][] = array(
'error' => 'taxonomy_term_illegal_value',
'message' => t('%name: this field cannot hold more that @count values.', array('%name' => t($instance['label']), '@count' => $field['cardinality'])),
);
}
}
foreach ($items as $delta => $item) {
if (!empty($item['tid'])) {
if (!isset($allowed_values[$item['tid']])) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'taxonomy_term_illegal_value',
'message' => t('%name: illegal value.', array('%name' => t($instance['label']))),
);
}
}
}
}
function taxonomy_field_is_empty($item, $field) {
if (!is_array($item) || (empty($item['tid']) && (string) $item['tid'] !== '0')) {
return TRUE;
}
return FALSE;
}
function taxonomy_field_formatter_info() {
return array(
'taxonomy_term_link' => array(
'label' => t('Link'),
'field types' => array('taxonomy_term'),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
),
'taxonomy_term_plain' => array(
'label' => t('Plain text'),
'field types' => array('taxonomy_term'),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
),
),
);
}
function taxonomy_field_formatter($object_type, $object, $field, $instance, $langcode, $display, $items, $delta) {
$item = $items[$delta];
switch ($display['type']) {
case 'taxonomy_term_link':
if (!isset($item['taxonomy_term'])) {
$item['taxonomy_term'] = taxonomy_term_load($item['tid']);
}
$term = $item['taxonomy_term'];
$result = array(
'#type' => 'link',
'#title' => $term->name,
'#href' => 'taxonomy/term/' . $term->tid,
);
break;
case 'taxonomy_term_plain':
$term = $item['taxonomy_term'];
$result = array(
'#markup' => check_plain($term->name),
);
break;
}
return $result;
}
function taxonomy_allowed_values($field) {
$options = array();
foreach ($field['settings']['allowed_values'] as $tree) {
$terms = taxonomy_get_tree($tree['vid'], $tree['parent']);
if ($terms) {
foreach ($terms as $term) {
$options[$term->tid] = str_repeat('-', $term->depth) . $term->name;
}
}
}
return $options;
}
function taxonomy_field_formatter_prepare_view($obj_type, $objects, $field, $instances, $langcode, &$items, $displays) {
$tids = array();
foreach ($objects as $id => $object) {
foreach ($items[$id] as $delta => $item) {
$tids[$item['tid']] = $item['tid'];
}
}
if ($tids) {
$terms = taxonomy_term_load_multiple($tids);
foreach ($objects as $id => $object) {
foreach ($items[$id] as $delta => $item) {
if (isset($terms[$item['tid']])) {
$items[$id][$delta]['taxonomy_term'] = $terms[$item['tid']];
}
else {
unset($items[$id][$delta]);
}
}
}
}
}
function _taxonomy_clean_field_cache($term) {
$cids = array();
$obj_types = array();
foreach (entity_get_info() as $obj_type => $info) {
if (isset($info['cacheable']) && !$info['cacheable']) {
$obj_types[] = $obj_type;
}
}
$fields = field_read_fields(array('type' => 'taxonomy_term'));
foreach ($fields as $field_name => $field) {
foreach ($field['settings']['allowed_values'] as $tree) {
$vids[$tree['vid']] = $tree['vid'];
}
if (in_array($term->vid, $vids)) {
$conditions = array(array('tid', $term->tid));
if ($obj_types) {
$conditions[] = array('type', $obj_types, 'NOT IN');
}
$results = field_attach_query($field['id'], $conditions, array('limit' => FIELD_QUERY_NO_LIMIT));
foreach ($results as $obj_type => $objects) {
foreach (array_keys($objects) as $id) {
$cids[] = "field:$obj_type:$id";
}
}
}
}
if ($cids) {
cache_clear_all($cids, 'cache_field');
}
}
function taxonomy_term_title($term) {
return check_plain($term->name);
}
function taxonomy_field_widget(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$tags = array();
foreach ($items as $item) {
$tags[$item['tid']] = isset($item['taxonomy_term']) ? $item['taxonomy_term'] : taxonomy_term_load($item['tid']);
}
$element += array(
'#type' => 'textfield',
'#default_value' => taxonomy_implode_tags($tags),
'#autocomplete_path' => $instance['widget']['settings']['autocomplete_path'] . '/' . $field['field_name'],
'#size' => $instance['widget']['settings']['size'],
'#element_validate' => array('taxonomy_autocomplete_validate'),
);
return $element;
}
function taxonomy_autocomplete_validate($element, &$form_state) {
if ($tags = $element['#value']) {
$field = $form_state['complete form']['#fields'][$element['#field_name']]['field'];
$vids = array();
foreach ($field['settings']['allowed_values'] as $tree) {
$vids[] = $tree['vid'];
}
$typed_terms = drupal_explode_tags($tags);
$values = array();
foreach ($typed_terms as $typed_term) {
if ($possibilities = taxonomy_term_load_multiple(array(), array('name' => trim($typed_term), 'vid' => $vids))) {
$term = array_pop($possibilities);
}
else {
$vocabulary = taxonomy_vocabulary_load($vids[0]);
$term = (object) array(
'vid' => $vids[0],
'name' => $typed_term,
'vocabulary_machine_name' => $vocabulary->machine_name,
);
taxonomy_term_save($term);
}
$values[] = $term->tid;
}
$value = options_array_transpose(array('tid' => $values));
}
else {
$value = array();
}
form_set_value($element, $value, $form_state);
}
function taxonomy_field_widget_error($element, $error) {
form_error($element, $error['message']);
}
function taxonomy_field_settings_form($field, $instance, $has_data) {
$vocabularies = taxonomy_get_vocabularies();
$options = array();
foreach ($vocabularies as $vocabulary) {
$options[$vocabulary->vid] = $vocabulary->name;
}
$form['allowed_values'] = array(
'#tree' => TRUE,
);
foreach ($field['settings']['allowed_values'] as $delta => $tree) {
$form['allowed_values'][$delta]['vid'] = array(
'#type' => 'select',
'#title' => t('Vocabulary'),
'#default_value' => $tree['vid'],
'#options' => $options,
'#required' => TRUE,
'#description' => t('The vocabulary which supplies the options for this field.'),
'#disabled' => $has_data,
);
$form['allowed_values'][$delta]['parent'] = array(
'#type' => 'value',
'#value' => $tree['parent'],
);
}
return $form;
}
function taxonomy_rdf_mapping() {
return array(
array(
'type' => 'taxonomy_term',
'bundle' => RDF_DEFAULT_BUNDLE,
'mapping' => array(
'rdftype' => array('skos:Concept'),
'name' => array(
'predicates' => array('skos:prefLabel'),
),
'description' => array(
'predicates' => array('skos:definition'),
),
'vid' => array(
'predicates' => array('skos:member'),
),
),
),
array(
'type' => 'taxonomy_vocabulary',
'bundle' => RDF_DEFAULT_BUNDLE,
'mapping' => array(
'rdftype' => array('skos:Collection'),
'name' => array(
'predicates' => array('rdfs:label'),
),
'description' => array(
'predicates' => array('rdfs:comment'),
),
),
),
);
}
function taxonomy_field_insert($obj_type, $object, $field, $instance, $langcode, &$items) {
if (variable_get('taxonomy_maintain_index_table', TRUE) && $field['storage']['type'] == 'field_sql_storage' && $obj_type == 'node' && $object->status) {
$query = db_insert('taxonomy_index')->fields(array('nid', 'tid', 'sticky', 'created', ));
foreach ($items as $item) {
$query->values(array(
'nid' => $object->nid,
'tid' => $item['tid'],
'sticky' => $object->sticky,
'created' => $object->created,
));
}
$query->execute();
}
}
function taxonomy_field_update($obj_type, $object, $field, $instance, $langcode, &$items) {
if (variable_get('taxonomy_maintain_index_table', TRUE) && $field['storage']['type'] == 'field_sql_storage' && $obj_type = 'node') {
$first_call = &drupal_static(__FUNCTION__, array());
if (!isset($first_call[$object->nid])) {
$first_call[$object->nid] = FALSE;
db_delete('taxonomy_index')->condition('nid', $object->nid)->execute();
}
if ($object->status) {
$query = db_insert('taxonomy_index')->fields(array('nid', 'tid', 'sticky', 'created'));
foreach ($items as $item) {
$query->values(array(
'nid' => $object->nid,
'tid' => $item['tid'],
'sticky' => $object->sticky,
'created' => $object->created,
));
}
$query->execute();
}
}
}
function taxonomy_node_delete($node) {
if (variable_get('taxonomy_maintain_index_table', TRUE)) {
db_delete('taxonomy_index')->condition('nid', $node->nid)->execute();
}
}
function taxonomy_taxonomy_term_delete($term) {
if (variable_get('taxonomy_maintain_index_table', TRUE)) {
db_delete('taxonomy_index')->condition('tid', $term->tid)->execute();
}
}