Newer
Older
/**
* @file
* Enables the organization of content into categories.
*/
* Implement hook_permission().
function taxonomy_permission() {
return array(
Angie Byron
committed
'administer taxonomy' => array(
'title' => t('Administer taxonomy'),
'description' => t('Manage taxonomy vocabularies and terms.'),
),
);
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implement hook_entity_info().
Dries Buytaert
committed
*/
Dries Buytaert
committed
function taxonomy_entity_info() {
Dries Buytaert
committed
$return = array(
'taxonomy_term' => array(
'label' => t('Taxonomy term'),
Dries Buytaert
committed
'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(),
Dries Buytaert
committed
),
);
Dries Buytaert
committed
foreach (taxonomy_vocabulary_get_names() as $machine_name => $vocabulary) {
$return['taxonomy_term']['bundles'][$machine_name] = array(
'label' => $vocabulary->name,
'admin' => array(
Dries Buytaert
committed
'path' => 'admin/structure/taxonomy/%taxonomy_vocabulary',
'real path' => 'admin/structure/taxonomy/' . $vocabulary->vid,
'bundle argument' => 3,
'access arguments' => array('administer taxonomy'),
),
);
}
Dries Buytaert
committed
$return['taxonomy_vocabulary'] = array(
'label' => t('Taxonomy vocabulary'),
'controller class' => 'TaxonomyVocabularyController',
'base table' => 'taxonomy_vocabulary',
'object keys' => array(
'id' => 'vid',
),
'fieldable' => FALSE,
);
Dries Buytaert
committed
return $return;
}
/**
* Implement hook_field_build_modes();
*
* @TODO: build mode for display as a field (when attached to nodes etc.).
*/
function taxonomy_field_build_modes($obj_type) {
$modes = array();
if ($obj_type == 'term') {
$modes = array(
'full' => t('Taxonomy term page'),
);
}
return $modes;
}
Dries Buytaert
committed
/**
Dries Buytaert
committed
* Implement hook_theme().
Dries Buytaert
committed
*/
function taxonomy_theme() {
return array(
'taxonomy_term_select' => array(
'arguments' => array('element' => NULL),
Gábor Hojtsy
committed
),
'taxonomy_overview_vocabularies' => array(
'arguments' => array('form' => array()),
),
'taxonomy_overview_terms' => array(
'arguments' => array('form' => array()),
),
Dries Buytaert
committed
'field_formatter_taxonomy_term_link' => array(
'arguments' => array('element' => NULL),
),
'field_formatter_taxonomy_term_plain' => array(
'arguments' => array('element' => NULL),
),
Angie Byron
committed
'taxonomy_autocomplete' => array(
'arguments' => array('element' => NULL),
),
Dries Buytaert
committed
);
}
* Implement hook_node_view().
function taxonomy_node_view($node, $build_mode) {
Dries Buytaert
committed
if (empty($node->taxonomy)) {
return;
Dries Buytaert
committed
if ($build_mode == 'rss') {
Dries Buytaert
committed
// Provide category information for RSS feeds.
foreach ($node->taxonomy as $term) {
$node->rss_elements[] = array(
'key' => 'category',
'value' => $term->name,
'attributes' => array('domain' => url(taxonomy_term_path($term), array('absolute' => TRUE))),
);
}
}
else {
$links = array();
// If previewing, the terms must be converted to objects first.
if (!empty($node->in_preview)) {
Dries Buytaert
committed
$node->taxonomy = taxonomy_preview_terms($node);
}
foreach ($node->taxonomy as $term) {
// During preview the free tagging terms are in an array unlike the
// other terms which are objects. So we have to check if a $term
// is an object or not.
if (is_object($term)) {
$links['taxonomy_term_' . $term->tid] = array(
'title' => $term->name,
'href' => taxonomy_term_path($term),
'attributes' => array('rel' => 'tag', 'title' => strip_tags($term->description))
);
}
// Previewing free tagging terms; we don't link them because the
// term-page might not exist yet.
else {
foreach ($term as $free_typed) {
$typed_terms = drupal_explode_tags($free_typed);
foreach ($typed_terms as $typed_term) {
$links['taxonomy_preview_term_' . $typed_term] = array(
'title' => $typed_term,
);
}
Steven Wittens
committed
}
Dries Buytaert
committed
$node->content['links']['terms'] = array(
'#theme' => 'links',
'#links' => $links,
'#attributes' => array('class' => array('links', 'inline')),
Dries Buytaert
committed
'#sorted' => TRUE,
);
}
Steven Wittens
committed
}
/**
* For vocabularies not maintained by taxonomy.module, give the maintaining
* module a chance to provide a path for terms in that vocabulary.
*
* @param $term
* A term object.
* @return
* An internal Drupal path.
*/
function taxonomy_term_path($term) {
$vocabulary = taxonomy_vocabulary_load($term->vid);
if ($vocabulary->module != 'taxonomy' && $path = module_invoke($vocabulary->module, 'term_path', $term)) {
return $path;
}
return 'taxonomy/term/' . $term->tid;
Dries Buytaert
committed
* Implement hook_menu().
Dries Buytaert
committed
function taxonomy_menu() {
Dries Buytaert
committed
$items['admin/structure/taxonomy'] = array(
Gábor Hojtsy
committed
'title' => 'Taxonomy',
'description' => 'Manage tagging, categorization, and classification of your content.',
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_overview_vocabularies'),
Dries Buytaert
committed
'access arguments' => array('administer taxonomy'),
'file' => 'taxonomy.admin.inc',
Dries Buytaert
committed
);
Dries Buytaert
committed
$items['admin/structure/taxonomy/list'] = array(
'title' => 'List',
Dries Buytaert
committed
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
Dries Buytaert
committed
$items['admin/structure/taxonomy/add'] = array(
'title' => 'Add vocabulary',
Dries Buytaert
committed
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_form_vocabulary'),
Dries Buytaert
committed
'access arguments' => array('administer taxonomy'),
Angie Byron
committed
'type' => MENU_LOCAL_ACTION,
'file' => 'taxonomy.admin.inc',
Dries Buytaert
committed
);
Dries Buytaert
committed
$items['taxonomy/term/%taxonomy_term'] = array(
Dries Buytaert
committed
'title' => 'Taxonomy term',
Dries Buytaert
committed
'title callback' => 'taxonomy_term_title',
'title arguments' => array(2),
Dries Buytaert
committed
'page callback' => 'taxonomy_term_page',
'page arguments' => array(2),
'access arguments' => array('access content'),
Dries Buytaert
committed
'type' => MENU_CALLBACK,
'file' => 'taxonomy.pages.inc',
Dries Buytaert
committed
);
Dries Buytaert
committed
$items['taxonomy/term/%taxonomy_term/view'] = array(
Dries Buytaert
committed
'title' => 'View',
'type' => MENU_DEFAULT_LOCAL_TASK,
Dries Buytaert
committed
);
Dries Buytaert
committed
$items['taxonomy/term/%taxonomy_term/edit'] = array(
'title' => 'Edit term',
'page callback' => 'taxonomy_term_edit',
Gábor Hojtsy
committed
'page arguments' => array(2),
Dries Buytaert
committed
'access arguments' => array('administer taxonomy'),
'type' => MENU_LOCAL_TASK,
'weight' => 10,
'file' => 'taxonomy.pages.inc',
Dries Buytaert
committed
);
Dries Buytaert
committed
$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.feeds.inc',
Dries Buytaert
committed
);
Dries Buytaert
committed
$items['taxonomy/autocomplete'] = array(
'title' => 'Autocomplete taxonomy',
Dries Buytaert
committed
'page callback' => 'taxonomy_autocomplete',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'taxonomy.pages.inc',
Dries Buytaert
committed
);
Angie Byron
committed
// TODO: remove with taxonomy_term_node_*
$items['taxonomy/autocomplete/legacy'] = array(
'title' => 'Autocomplete taxonomy',
'page callback' => 'taxonomy_autocomplete_legacy',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'taxonomy.pages.inc',
Angie Byron
committed
);
Dries Buytaert
committed
Dries Buytaert
committed
$items['admin/structure/taxonomy/%taxonomy_vocabulary'] = array(
Dries Buytaert
committed
'title' => 'Vocabulary', // this is replaced by callback
'page callback' => 'drupal_get_form',
Dries Buytaert
committed
'page arguments' => array('taxonomy_form_vocabulary', 3),
'title callback' => 'taxonomy_admin_vocabulary_title_callback',
'title arguments' => array(3),
Dries Buytaert
committed
'access arguments' => array('administer taxonomy'),
'type' => MENU_CALLBACK,
'file' => 'taxonomy.admin.inc',
Dries Buytaert
committed
);
Dries Buytaert
committed
$items['admin/structure/taxonomy/%taxonomy_vocabulary/edit'] = array(
Dries Buytaert
committed
'title' => 'Edit vocabulary',
Dries Buytaert
committed
'type' => MENU_DEFAULT_LOCAL_TASK,
Dries Buytaert
committed
'weight' => -20,
);
Dries Buytaert
committed
$items['admin/structure/taxonomy/%taxonomy_vocabulary/list'] = array(
Dries Buytaert
committed
'title' => 'List terms',
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_overview_terms', 3),
'access arguments' => array('administer taxonomy'),
'type' => MENU_LOCAL_TASK,
Dries Buytaert
committed
'weight' => -10,
'file' => 'taxonomy.admin.inc',
Dries Buytaert
committed
);
Angie Byron
committed
$items['admin/structure/taxonomy/%taxonomy_vocabulary/list/add'] = array(
'title' => 'Add term',
Dries Buytaert
committed
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_form_term', 3),
Dries Buytaert
committed
'access arguments' => array('administer taxonomy'),
Angie Byron
committed
'type' => MENU_LOCAL_ACTION,
'file' => 'taxonomy.admin.inc',
Dries Buytaert
committed
);
Dries Buytaert
committed
/**
* Return the vocabulary name given the vocabulary object.
*/
function taxonomy_admin_vocabulary_title_callback($vocabulary) {
return check_plain($vocabulary->name);
}
/**
Dries Buytaert
committed
* Save a vocabulary given a vocabulary object.
Dries Buytaert
committed
*/
Dries Buytaert
committed
function taxonomy_vocabulary_save($vocabulary) {
if (empty($vocabulary->nodes)) {
$vocabulary->nodes = array();
}
Dries Buytaert
committed
if (!empty($vocabulary->name)) {
// Prevent leading and trailing spaces in vocabulary names.
$vocabulary->name = trim($vocabulary->name);
}
Dries Buytaert
committed
if (!isset($vocabulary->module)) {
$vocabulary->module = 'taxonomy';
Dries Buytaert
committed
}
Dries Buytaert
committed
if (!empty($vocabulary->vid) && !empty($vocabulary->name)) {
Dries Buytaert
committed
$status = drupal_write_record('taxonomy_vocabulary', $vocabulary, 'vid');
Dries Buytaert
committed
db_delete('taxonomy_vocabulary_node_type')
->condition('vid', $vocabulary->vid)
->execute();
if (!empty($vocabulary->nodes)) {
$query = db_insert('taxonomy_vocabulary_node_type')
->fields(array('vid', 'type'));
foreach ($vocabulary->nodes as $type => $selected) {
$query->values(array(
'vid' => $vocabulary->vid,
'type' => $type,
));
}
$query->execute();
Dries Buytaert
committed
module_invoke_all('taxonomy_vocabulary_update', $vocabulary);
Dries Buytaert
committed
elseif (empty($vocabulary->vid)) {
Dries Buytaert
committed
$status = drupal_write_record('taxonomy_vocabulary', $vocabulary);
Dries Buytaert
committed
if (!empty($vocabulary->nodes)) {
$query = db_insert('taxonomy_vocabulary_node_type')
->fields(array('vid', 'type'));
foreach ($vocabulary->nodes as $type => $selected) {
$query->values(array(
'vid' => $vocabulary->vid,
'type' => $type,
));
}
$query->execute();
Dries Buytaert
committed
field_attach_create_bundle($vocabulary->machine_name);
Dries Buytaert
committed
module_invoke_all('taxonomy_vocabulary_insert', $vocabulary);
Dries Buytaert
committed
entity_get_controller('taxonomy_vocabulary')->resetCache();
Dries Buytaert
committed
return $status;
/**
* Delete a vocabulary.
*
* @param $vid
* A vocabulary ID.
* @return
* Constant indicating items were deleted.
*/
Dries Buytaert
committed
function taxonomy_vocabulary_delete($vid) {
$vocabulary = (array) taxonomy_vocabulary_load($vid);
Dries Buytaert
committed
db_delete('taxonomy_vocabulary')
->condition('vid', $vid)
->execute();
db_delete('taxonomy_vocabulary_node_type')
->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);
Dries Buytaert
committed
field_attach_delete_bundle($vocabulary['machine_name']);
Dries Buytaert
committed
entity_get_controller('taxonomy_vocabulary')->resetCache();
Steven Wittens
committed
return SAVED_DELETED;
* Dynamically check and update the hierarchy flag of a vocabulary.
* Checks the current parents of all terms in a vocabulary and updates the
* vocabularies hierarchy setting to the lowest possible level. A hierarchy with
* no parents in any of its terms will be given a hierarchy of 0. If terms
* contain at most a single parent, the vocabulary will be given a hierarchy of
* 1. If any term contain multiple parents, the vocabulary will be given a
* hierarchy of 2.
* @param $vocabulary
Dries Buytaert
committed
* A vocabulary object.
* @param $changed_term
* An array of the term structure that was updated.
*/
function taxonomy_check_vocabulary_hierarchy($vocabulary, $changed_term) {
Dries Buytaert
committed
$tree = taxonomy_get_tree($vocabulary->vid);
$hierarchy = 0;
foreach ($tree as $term) {
// Update the changed term with the new parent value before comparison.
if ($term->tid == $changed_term['tid']) {
$term = (object)$changed_term;
$term->parents = $term->parent;
}
// Check this term's parent count.
if (count($term->parents) > 1) {
$hierarchy = 2;
break;
}
elseif (count($term->parents) == 1 && 0 !== array_shift($term->parents)) {
$hierarchy = 1;
}
}
Dries Buytaert
committed
if ($hierarchy != $vocabulary->hierarchy) {
$vocabulary->hierarchy = $hierarchy;
taxonomy_vocabulary_save($vocabulary);
}
return $hierarchy;
}
* Save a term object to the database.
* @param $term
* A term object.
* @return
* Status constant indicating if term was inserted or updated.
*/
function taxonomy_term_save($term) {
Dries Buytaert
committed
if ($term->name) {
// Prevent leading and trailing spaces in term names.
$term->name = trim($term->name);
}
Dries Buytaert
committed
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) {
Dries Buytaert
committed
$status = drupal_write_record('taxonomy_term_data', $term, 'tid');
Dries Buytaert
committed
field_attach_update('taxonomy_term', $term);
module_invoke_all('taxonomy_term_update', $term);
Dries Buytaert
committed
$status = drupal_write_record('taxonomy_term_data', $term);
Dries Buytaert
committed
_taxonomy_clean_field_cache($term);
Dries Buytaert
committed
field_attach_insert('taxonomy_term', $term);
module_invoke_all('taxonomy_term_insert', $term);
Dries Buytaert
committed
db_delete('taxonomy_term_hierarchy')
->condition('tid', $term->tid)
->execute();
if (!isset($term->parent) || empty($term->parent)) {
$term->parent = array(0);
Dries Buytaert
committed
$query = db_insert('taxonomy_term_hierarchy')
->fields(array('tid', 'parent'));
if (is_array($term->parent)) {
foreach ($term->parent as $parent) {
Dries Buytaert
committed
if (is_array($parent)) {
foreach ($parent as $tid) {
Dries Buytaert
committed
$query->values(array(
'tid' => $term->tid,
'parent' => $tid
));
Dries Buytaert
committed
}
}
else {
Dries Buytaert
committed
$query->values(array(
'tid' => $term->tid,
'parent' => $parent
));
Dries Buytaert
committed
}
Dries Buytaert
committed
else {
$query->values(array(
'tid' => $term->tid,
'parent' => $parent
));
Dries Buytaert
committed
}
Dries Buytaert
committed
$query->execute();
Dries Buytaert
committed
db_delete('taxonomy_term_synonym')
->condition('tid', $term->tid)
->execute();
if (!empty($term->synonyms)) {
Dries Buytaert
committed
$query = db_insert('taxonomy_term_synonym')
->fields(array('tid', 'name'));
foreach (explode ("\n", str_replace("\r", '', $term->synonyms)) as $synonym) {
Dries Buytaert
committed
$query->values(array(
'tid' => $term->tid,
'name' => rtrim($synonym)
));
Dries Buytaert
committed
$query->execute();
Dries Buytaert
committed
taxonomy_terms_static_reset();
Dries Buytaert
committed
return $status;
/**
* Delete a term.
*
* @param $tid
* The term ID.
* @return
* Status constant indicating deletion.
*/
function taxonomy_term_delete($tid) {
Dries Buytaert
committed
$tids = array($tid);
while ($tids) {
$children_tids = $orphans = array();
foreach ($tids as $tid) {
// See if any of the term's children are about to be become orphans:
if ($children = taxonomy_get_children($tid)) {
foreach ($children as $child) {
// If the term has multiple parents, we don't delete it.
$parents = taxonomy_get_parents($child->tid);
if (count($parents) == 1) {
$orphans[] = $child->tid;
}
}
}
$term = taxonomy_term_load($tid);
Dries Buytaert
committed
db_delete('taxonomy_term_data')
->condition('tid', $tid)
->execute();
db_delete('taxonomy_term_hierarchy')
->condition('tid', $tid)
->execute();
db_delete('taxonomy_term_synonym')
->condition('tid', $tid)
->execute();
db_delete('taxonomy_term_node')
->condition('tid', $tid)
->execute();
Dries Buytaert
committed
field_attach_delete('taxonomy_term', $term);
Dries Buytaert
committed
_taxonomy_clean_field_cache($term);
module_invoke_all('taxonomy_term_delete', $term);
Dries Buytaert
committed
}
Dries Buytaert
committed
$tids = $orphans;
}
Dries Buytaert
committed
taxonomy_terms_static_reset();
Gerhard Killesreiter
committed
return SAVED_DELETED;
Dries Buytaert
committed
/**
* Clear all static cache variables for terms..
*/
function taxonomy_terms_static_reset() {
drupal_static_reset('taxonomy_term_count_nodes');
drupal_static_reset('taxonomy_get_tree');
drupal_static_reset('taxonomy_get_synonym_root');
Dries Buytaert
committed
entity_get_controller('taxonomy_term')->resetCache();
Dries Buytaert
committed
}
/**
* Generate a form element for selecting terms from a vocabulary.
Angie Byron
committed
*
* @param $vid
* The vocabulary ID to generate a form element for
* @param $value
* The existing value of the term(s) in this vocabulary to use by default.
* @param $help
* Optional help text to use for the form element. If specified, this value
* MUST be properly sanitized and filtered (e.g. with filter_xss_admin() or
* check_plain() if it is user-supplied) to prevent XSS vulnerabilities. If
* omitted, the help text stored with the vocaulary (if any) will be used.
* @return
* An array describing a form element to select terms for a vocabulary.
*
* @see _taxonomy_term_select()
* @see filter_xss_admin()
Dries Buytaert
committed
function taxonomy_form($vid, $value = 0, $help = NULL) {
$vocabulary = taxonomy_vocabulary_load($vid);
Angie Byron
committed
$help = ($help) ? $help : filter_xss_admin($vocabulary->help);
Dries Buytaert
committed
Gábor Hojtsy
committed
if (!$vocabulary->multiple) {
$blank = ($vocabulary->required) ? t('- Please choose -') : t('- None selected -');
else {
$blank = ($vocabulary->required) ? 0 : t('- None -');
}
Dries Buytaert
committed
return _taxonomy_term_select(check_plain($vocabulary->name), $value, $vid, $help, intval($vocabulary->multiple), $blank);
Neil Drumm
committed
/**
* Generate a set of options for selecting a term from all vocabularies.
Neil Drumm
committed
*/
function taxonomy_form_all($free_tags = 0) {
$vocabularies = taxonomy_get_vocabularies();
$options = array();
foreach ($vocabularies as $vid => $vocabulary) {
if ($vocabulary->tags && !$free_tags) {
continue;
}
Neil Drumm
committed
$tree = taxonomy_get_tree($vid);
Dries Buytaert
committed
if ($tree && (count($tree) > 0)) {
Neil Drumm
committed
$options[$vocabulary->name] = array();
Neil Drumm
committed
foreach ($tree as $term) {
Dries Buytaert
committed
$options[$vocabulary->name][$term->tid] = str_repeat('-', $term->depth) . $term->name;
Neil Drumm
committed
}
}
}
return $options;
}
/**
* Return an array of all vocabulary objects.
*
* @param $type
* If set, return only those vocabularies associated with this node type.
*/
Dries Buytaert
committed
function taxonomy_get_vocabularies($type = NULL) {
$conditions = !empty($type) ? array('type' => $type) : NULL;
Dries Buytaert
committed
return taxonomy_vocabulary_load_multiple(FALSE, $conditions);
Dries Buytaert
committed
/**
* Get names for all taxonomy vocabularies.
*
* @return
Dries Buytaert
committed
* An array of vocabulary ids, names, machine names, keyed by machine name.
Dries Buytaert
committed
*/
function taxonomy_vocabulary_get_names() {
Dries Buytaert
committed
$names = db_query('SELECT name, machine_name, vid FROM {taxonomy_vocabulary}')->fetchAllAssoc('machine_name');
Dries Buytaert
committed
return $names;
}
Dries Buytaert
committed
* Implement hook_form_alter().
* We check for taxonomy_override_selector before loading the full
Gábor Hojtsy
committed
* vocabulary, so contrib modules can intercept before hook_form_alter
* and provide scalable alternatives.
Dries Buytaert
committed
function taxonomy_form_alter(&$form, $form_state, $form_id) {
Dries Buytaert
committed
if (!variable_get('taxonomy_override_selector', FALSE) && !empty($form['#node_edit_form'])) {
Dries Buytaert
committed
$node = $form['#node'];
Dries Buytaert
committed
if (!isset($node->taxonomy)) {
$terms = empty($node->nid) ? array() : taxonomy_node_get_terms($node);
// After preview the terms must be converted to objects.
if (isset($form_state['node_preview'])) {
$node->taxonomy = taxonomy_preview_terms($node);
}
Dries Buytaert
committed
$terms = $node->taxonomy;
Dries Buytaert
committed
$query = db_select('taxonomy_vocabulary', 'v');
$query->join('taxonomy_vocabulary_node_type', 'n', 'v.vid = n.vid');
$query->addTag('term_access');
Dries Buytaert
committed
$result = $query
->fields('v')
->condition('n.type', $node->type)
->orderBy('v.weight')
->orderBy('v.name')
->execute();
Dries Buytaert
committed
foreach ($result as $vocabulary) {
Dries Buytaert
committed
if ($vocabulary->tags) {
if (isset($form_state['node_preview'])) {
Dries Buytaert
committed
// Typed string can be changed by the user before preview,
// so we just insert the tags directly as provided in the form.
$typed_string = $node->taxonomy['tags'][$vocabulary->vid];
}
else {
$typed_string = taxonomy_implode_tags($terms, $vocabulary->vid) . (array_key_exists('tags', $terms) ? $terms['tags'][$vocabulary->vid] : NULL);
}
Dries Buytaert
committed
if ($vocabulary->help) {
Angie Byron
committed
$help = filter_xss_admin($vocabulary->help);
Dries Buytaert
committed
}
else {
Angie Byron
committed
$help = t('A comma-separated list of terms describing this content. Example: funny, bungee jumping, "Company, Inc."');
Dries Buytaert
committed
}
$form['taxonomy']['tags'][$vocabulary->vid] = array('#type' => 'textfield',
'#title' => $vocabulary->name,
'#description' => $help,
'#required' => $vocabulary->required,
'#default_value' => $typed_string,
Angie Byron
committed
'#autocomplete_path' => 'taxonomy/autocomplete/legacy/' . $vocabulary->vid,
'#weight' => $vocabulary->weight,
'#maxlength' => 1024,
);
Dries Buytaert
committed
}
else {
// Extract terms belonging to the vocabulary in question.
$default_terms = array();
Dries Buytaert
committed
foreach ($terms as $term) {
// Free tagging has no default terms and also no vid after preview.
if (isset($term->vid) && $term->vid == $vocabulary->vid) {
$default_terms[$term->tid] = $term;
}
}
Angie Byron
committed
$form['taxonomy'][$vocabulary->vid] = taxonomy_form($vocabulary->vid, array_keys($default_terms), filter_xss_admin($vocabulary->help));
$form['taxonomy'][$vocabulary->vid]['#weight'] = $vocabulary->weight;
$form['taxonomy'][$vocabulary->vid]['#required'] = $vocabulary->required;
Dries Buytaert
committed
}
Dries Buytaert
committed
if (!empty($form['taxonomy']) && is_array($form['taxonomy'])) {
Dries Buytaert
committed
if (count($form['taxonomy']) > 1) {
// Add fieldset only if form has more than 1 element.
$form['taxonomy'] += array(
'#type' => 'fieldset',
Gábor Hojtsy
committed
'#title' => t('Vocabularies'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
}
$form['taxonomy']['#weight'] = -3;
$form['taxonomy']['#tree'] = TRUE;
Dries Buytaert
committed
}
}
}
/**
* Helper function to convert terms after a preview.
*
* After preview the tags are an array instead of proper objects. This function
* converts them back to objects with the exception of 'free tagging' terms,
Dries Buytaert
committed
* because new tags can be added by the user before preview and those do not
* yet exist in the database. We therefore save those tags as a string so
* we can fill the form again after the preview.
*/
function taxonomy_preview_terms($node) {
$taxonomy = array();
Gábor Hojtsy
committed
if (isset($node->taxonomy)) {
foreach ($node->taxonomy as $key => $term) {
unset($node->taxonomy[$key]);
// A 'Multiple select' and a 'Free tagging' field returns an array.
if (is_array($term)) {
foreach ($term as $tid) {
if ($key == 'tags') {
// Free tagging; the values will be saved for later as strings
// instead of objects to fill the form again.
$taxonomy['tags'] = $term;
}
else {
Dries Buytaert
committed
$taxonomy[$tid] = taxonomy_term_load($tid);
Gábor Hojtsy
committed
}
}
}
Gábor Hojtsy
committed
// A 'Single select' field returns the term id.
elseif ($term) {
Dries Buytaert
committed
$taxonomy[$term] = taxonomy_term_load($term);
Gábor Hojtsy
committed
}
return $taxonomy;
* Find all terms associated with the given node, within one vocabulary.
function taxonomy_node_get_terms_by_vocabulary($node, $vid, $key = 'tid') {
Dries Buytaert
committed
$query = db_select('taxonomy_term_data', 't');
$query->join('taxonomy_term_node', 'r', 'r.tid = t.tid');
$query->addTag('term_access');
$result = $query
->fields('t')
->condition('t.vid', $vid)
->condition('r.vid', $node->vid)
->orderBy('weight')
->execute();
Dries Buytaert
committed
foreach ($result as $term) {
/**
* Find all term IDs associated with a set of nodes.
*
* @param $nodes
* An array of node objects.
*
* @return
* An array of term and node IDs ordered by vocabulary and term weight.
*/
function taxonomy_get_tids_from_nodes($nodes) {
$node_vids = array();
foreach ($nodes as $node) {
$node_vids[] = $node->vid;
}
Dries Buytaert
committed
$query = db_select('taxonomy_term_node', 'r');
$query->join('taxonomy_term_data', 't', 'r.tid = t.tid');
$query->join('taxonomy_vocabulary', 'v', 't.vid = v.vid');
$query->addTag('term_access');
Dries Buytaert
committed
return $query
->fields('r', array('tid', 'nid', 'vid'))
->condition('r.vid', $node_vids, 'IN')
->orderBy('v.weight')
->orderBy('t.weight')
->orderBy('t.name')
->execute()
->fetchAll();
}
* Find all terms associated with the given node, ordered by vocabulary and term weight.
function taxonomy_node_get_terms($node, $key = 'tid') {
Dries Buytaert
committed
$terms = &drupal_static(__FUNCTION__);
Dries Buytaert
committed
if (!isset($terms[$node->vid][$key])) {
Dries Buytaert
committed
$query = db_select('taxonomy_term_node', 'r');
$query->join('taxonomy_term_data', 't', 'r.tid = t.tid');
$query->join('taxonomy_vocabulary', 'v', 't.vid = v.vid');
$query->addTag('term_access');
$result = $query
->fields('r', array('tid', 'nid', 'vid'))
->condition('r.vid', $node->vid)
->orderBy('v.weight')
->orderBy('t.weight')
->orderBy('t.name')
->execute();
Dries Buytaert
committed
$terms[$node->vid][$key] = array();
Dries Buytaert
committed
foreach ($result as $term) {
Dries Buytaert
committed
$terms[$node->vid][$key][$term->$key] = $term;
Dries Buytaert
committed
return $terms[$node->vid][$key];
function taxonomy_node_save($node, $terms) {
taxonomy_node_delete_revision($node);
// Free tagging vocabularies do not send their tids in the form,
// so we'll detect them here and process them independently.
Dries Buytaert
committed
if (isset($terms['tags'])) {
$typed_input = $terms['tags'];
unset($terms['tags']);
foreach ($typed_input as $vid => $vid_value) {
Dries Buytaert
committed
$vocabulary = taxonomy_vocabulary_load($vid);
$typed_terms = drupal_explode_tags($vid_value);
$inserted = array();
foreach ($typed_terms as $typed_term) {
// See if the term exists in the chosen vocabulary
// and return the tid; otherwise, add a new record.
$possibilities = taxonomy_get_term_by_name($typed_term);
$typed_term_tid = NULL; // tid match, if any.
foreach ($possibilities as $possibility) {
if ($possibility->vid == $vid) {
$typed_term_tid = $possibility->tid;
}
}
if (!$typed_term_tid) {
Dries Buytaert
committed
$edit = array(
'vid' => $vid,
'name' => $typed_term,
'vocabulary_machine_name' => $vocabulary->machine_name,
);
$term = (object)$edit;
$status = taxonomy_term_save($term);
$typed_term_tid = $term->tid;
// Defend against duplicate, differently cased tags
if (!isset($inserted[$typed_term_tid])) {
Dries Buytaert
committed
db_insert('taxonomy_term_node')
->fields(array(
'nid' => $node->nid,
'vid' => $node->vid,
'tid' => $typed_term_tid
))
->execute();
$inserted[$typed_term_tid] = TRUE;
}
Dries Buytaert
committed
if (is_array($terms) && !empty($terms)) {
$query = db_insert('taxonomy_term_node')
->fields(array('nid', 'vid', 'tid'));
Dries Buytaert
committed
foreach ($terms as $term) {
Dries Buytaert
committed
if (is_array($term)) {
foreach ($term as $tid) {
if ($tid) {
Dries Buytaert
committed
$query->values(array(
'nid' => $node->nid,
'vid' => $node->vid,
'tid' => $tid,
));
Dries Buytaert
committed
}
}
}
Angie Byron
committed
elseif (is_object($term)) {
Dries Buytaert
committed
$query->values(array(
'nid' => $node->nid,
'vid' => $node->vid,
'tid' => $term->tid,
));
Angie Byron
committed
elseif ($term) {
Dries Buytaert
committed
$query->values(array(
'nid' => $node->nid,
'vid' => $node->vid,
'tid' => $term,
));
Dries Buytaert
committed
$query->execute();
Neil Drumm
committed
/**
* Implement hook_node_type_insert().
Neil Drumm
committed
*/
function taxonomy_node_type_insert($info) {
drupal_static_reset('taxonomy_term_count_nodes');
}
/**
* Implement hook_node_type_update().
*/
function taxonomy_node_type_update($info) {
if (!empty($info->old_type) && $info->type != $info->old_type) {
Dries Buytaert
committed
db_update('taxonomy_vocabulary_node_type')
->fields(array(
'type' => $info->type,
))
->condition('type', $info->old_type)
->execute();
}
drupal_static_reset('taxonomy_term_count_nodes');
}
/**
* Implement hook_node_type_delete().
*/
function taxonomy_node_type_delete($info) {
db_delete('taxonomy_vocabulary_node_type')
->condition('type', $info->type)
->execute();
Dries Buytaert
committed
drupal_static_reset('taxonomy_term_count_nodes');
Neil Drumm
committed
}
/**
* Find all parents of a given term ID.
*/
function taxonomy_get_parents($tid, $key = 'tid') {
Dries Buytaert
committed
$query = db_select('taxonomy_term_data', 't');
$query->join('taxonomy_term_hierarchy', 'h', 'h.parent = t.tid');
$query->addTag('term_access');