View source
<?php
define('LINEAGE_START_DEPTH', 3);
function lineage_taxonomy_term_delete($term) {
db_delete('taxonomy_term_lineage')
->condition('tid', $term->tid)
->execute();
}
function lineage_taxonomy_term_update($term) {
if (arg() != array(
'admin',
'structure',
'taxonomy',
$term->vocabulary_machine_name,
)) {
lineage_update_term($term);
}
}
function lineage_taxonomy_term_insert($term) {
if (arg() != array(
'admin',
'structure',
'taxonomy',
$term->vocabulary_machine_name,
)) {
lineage_update_term($term);
}
}
function lineage_form_taxonomy_overview_terms_alter(&$form, &$form_state) {
$form['#submit'] = array(
'lineage_taxonomy_overview_terms_submit',
);
}
function lineage_taxonomy_overview_terms_submit(&$form, &$form_state) {
if ($form_state['triggering_element']['#value'] == t('Reset to alphabetical')) {
if ($form_state['values']['reset_alphabetical'] === TRUE) {
taxonomy_vocabulary_confirm_reset_alphabetical_submit($form, $form_state);
lineage_update_all($form_state['values']['vid']);
return;
}
$form_state['rebuild'] = TRUE;
$form_state['confirm_reset_alphabetical'] = TRUE;
return;
}
uasort($form_state['values'], 'drupal_sort_weight');
$vocabulary = $form['#vocabulary'];
$hierarchy = 0;
$changed_terms = array();
$tree = taxonomy_get_tree($vocabulary->vid);
if (empty($tree)) {
return;
}
$weight = 0;
$term = (array) $tree[0];
while ($term['tid'] != $form['#first_tid']) {
if ($term['parents'][0] == 0 && $term['weight'] != $weight) {
$term['parent'] = $term['parents'][0];
$term['weight'] = $weight;
$changed_terms[$term['tid']] = $term;
}
$weight++;
$hierarchy = $term['parents'][0] != 0 ? 1 : $hierarchy;
$term = (array) $tree[$weight];
}
$level_weights = array();
foreach ($form_state['values'] as $tid => $values) {
if (isset($form[$tid]['#term'])) {
$term = $form[$tid]['#term'];
if ($values['parent'] == 0 && $term['weight'] != $weight) {
$term['weight'] = $weight;
$changed_terms[$term['tid']] = $term;
}
elseif ($values['parent'] > 0) {
$level_weights[$values['parent']] = isset($level_weights[$values['parent']]) ? $level_weights[$values['parent']] + 1 : 0;
if ($level_weights[$values['parent']] != $term['weight']) {
$term['weight'] = $level_weights[$values['parent']];
$changed_terms[$term['tid']] = $term;
}
}
if ($values['parent'] != $term['parent']) {
$term['parent'] = $values['parent'];
$changed_terms[$term['tid']] = $term;
}
$hierarchy = $term['parent'] != 0 ? 1 : $hierarchy;
$weight++;
}
}
for ($weight; $weight < count($tree); $weight++) {
$term = (array) $tree[$weight];
if ($term['parents'][0] == 0 && $term['weight'] != $weight) {
$term['parent'] = $term['parents'][0];
$term['weight'] = $weight;
$changed_terms[$term['tid']] = $term;
}
$hierarchy = $term['parents'][0] != 0 ? 1 : $hierarchy;
}
foreach ($changed_terms as $changed) {
$term = (object) $changed;
db_update('taxonomy_term_hierarchy')
->fields(array(
'parent' => $term->parent,
))
->condition('tid', $term->tid, '=')
->execute();
db_update('taxonomy_term_data')
->fields(array(
'weight' => $term->weight,
))
->condition('tid', $term->tid, '=')
->execute();
}
if ($vocabulary->hierarchy != $hierarchy) {
$vocabulary->hierarchy = $hierarchy;
taxonomy_vocabulary_save($vocabulary);
}
drupal_set_message(t('The configuration options have been saved.'));
lineage_update_all($vocabulary->vid);
}
function lineage_enable() {
drupal_set_message(t("Updated @number taxonomy lineages.", array(
'@number' => lineage_update_all(),
)));
}
function lineage_update_all($vid = FALSE) {
$query = db_select('taxonomy_term_data', 'td');
$query
->join('taxonomy_term_hierarchy', 'th', 'th.tid = td.tid');
$query
->fields('td', array(
'tid',
'name',
'weight',
'vid',
));
$query
->fields('th', array(
'parent',
));
$query
->condition('th.parent', 0);
if ($vid) {
$query
->condition('td.vid', $vid);
}
$result = $query
->execute();
$count = 0;
foreach ($result as $term) {
$count += lineage_update_term($term, TRUE);
}
return $count;
}
function lineage_update_term($term, $all = FALSE) {
if (!$all) {
$query = db_select('taxonomy_term_data', 'td');
$query
->join('taxonomy_term_lineage', 'tl', 'tl.tid = td.tid');
$query
->join('taxonomy_term_hierarchy', 'th', 'td.tid = th.tid');
$query
->fields('tl', array(
'lineage',
));
$query
->fields('td', array(
'tid',
'name',
'weight',
'vid',
));
$query
->fields('th', array(
'parent',
));
$query
->condition('td.vid', $term->vid, '=');
$query
->condition('td.tid', $term->tid, '<>');
$query
->range(0, 1);
$other_term = $query
->execute()
->fetchObject();
if ($other_term->lineage != lineage_string($other_term)) {
$count = lineage_update_all($term->vid);
return $count;
}
}
$base = _lineage_get_parent_lineage($term->parent);
return count(lineage_update_term_r($term, $base));
}
function lineage_update_term_r($term, $base, $tids = array()) {
$base['base'] .= lineage_string($term);
$base['depth'] = intval($base['depth']);
db_delete('taxonomy_term_lineage')
->condition('tid', $term->tid)
->execute();
db_insert('taxonomy_term_lineage')
->fields(array(
'tid' => $term->tid,
'lineage' => trim($base['base']),
'depth' => $base['depth'],
))
->execute();
$base['depth']++;
$tids[$term->tid] = TRUE;
$query = db_select('taxonomy_term_hierarchy', 'th');
$query
->join('taxonomy_term_data', 'td', 'td.tid = th.tid');
$query
->fields('td', array(
'tid',
'name',
'weight',
'vid',
));
$query
->condition('th.parent', $term->tid, '=');
$result = $query
->execute();
foreach ($result as $child) {
if (!isset($tids[$child->tid])) {
$tids = lineage_update_term_r($child, $base, $tids);
}
}
return $tids;
}
function lineage_string($term) {
$w = _lineage_weights($term->vid);
return sprintf("%0" . $w['digits'] . "d", $term->weight + $w['offset']) . "-" . $term->name . "\n";
}
function lineage_strip_weight($term_string) {
$term_name = preg_replace("([0-9]+-)", "", $term_string, 1);
if ($term_name != $term_string) {
return $term_name;
}
else {
_lineage_format_warning();
return FALSE;
}
}
function lineage_get_weight($term_string) {
$matches = array();
if (preg_match("([0-9]+-)", $term_string, $matches)) {
return substr($matches[0], 0, -1);
}
else {
_lineage_format_warning();
return FALSE;
}
}
function _lineage_get_parent_lineage($tid) {
$query = db_select('taxonomy_term_hierarchy', 'th');
$query
->join('taxonomy_term_data', 'td', 'td.tid = th.tid');
$query
->fields('td', array(
'tid',
'name',
'weight',
'vid',
));
$query
->fields('th', array(
'parent',
));
$query
->condition('td.tid', $tid, '=');
$result = $query
->execute();
foreach ($result as $term) {
$ret = _lineage_get_parent_lineage($term->parent);
$ret['base'] .= lineage_string($term);
$ret['depth'] += 1;
return $ret;
}
return array(
'base' => '',
'depth' => 0,
);
}
function lineage_views_api() {
return array(
'api' => 3,
);
}
function _lineage_weights($vid) {
static $weights = array();
if (!isset($weights[$vid])) {
$weights[$vid]['min'] = db_query('SELECT MIN(weight) FROM {taxonomy_term_data} WHERE vid = :vid', array(
':vid' => $vid,
))
->fetchField();
$weights[$vid]['offset'] = $weights[$vid]['min'] < 0 ? abs($weights[$vid]['min']) : 0;
$weights[$vid]['max'] = db_query('SELECT MAX(weight) FROM {taxonomy_term_data} WHERE vid = :vid', array(
':vid' => $vid,
))
->fetchField();
$weights[$vid]['digits'] = floor(log($weights[$vid]['max'] + $weights[$vid]['offset'] + 1));
if ($weights[$vid]['digits'] == 0) {
$weights[$vid]['digits']++;
}
}
return $weights[$vid];
}
function _lineage_format_warning() {
drupal_set_message(t('Warning: your lineage data appears to be in an old format. Try disabling and re-enabling the module, or run update.php.'), 'warning', FALSE);
}