? 302440-2.patch ? hook_taxonomy_term_load.patch ? taxonomy_list_plus_admin_and_edit_term_tests_1.patch ? taxonomy_list_plus_admin_and_edit_term_tests_2.patch ? taxonomy_list_plus_test.patch ? taxonomy_refactor.patch ? taxonomy_refactor_2.patch ? taxonomy_term_load.patch ? term.patch ? term_edit.patch ? unappaproved.patch ? modules/taxonomy/taxonomy_refactor.patch ? modules/taxonomy/taxonomyrelation ? modules/taxonomy/taxonomyrelation.tar.gz.txt ? modules/taxonomy/taxonomysynonym ? modules/taxonomy/taxonomysynonym.tar.gz.txt ? sites/default/files ? sites/default/settings.php Index: modules/forum/forum.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.admin.inc,v retrieving revision 1.12 diff -u -p -r1.12 forum.admin.inc --- modules/forum/forum.admin.inc 16 Jul 2008 21:59:26 -0000 1.12 +++ modules/forum/forum.admin.inc 11 Sep 2008 17:22:52 -0000 @@ -160,7 +160,7 @@ function forum_form_container(&$form_sta * @param $tid ID of the term to be deleted */ function forum_confirm_delete(&$form_state, $tid) { - $term = taxonomy_get_term($tid); + $term = taxonomy_term_load($tid); $form['tid'] = array('#type' => 'value', '#value' => $tid); $form['name'] = array('#type' => 'value', '#value' => $term->name); Index: modules/forum/forum.module =================================================================== RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v retrieving revision 1.462 diff -u -p -r1.462 forum.module --- modules/forum/forum.module 6 Sep 2008 08:36:20 -0000 1.462 +++ modules/forum/forum.module 11 Sep 2008 17:22:53 -0000 @@ -224,7 +224,7 @@ function forum_nodeapi(&$node, $op, $tea foreach ($node->taxonomy as $term) { if (db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) { if (in_array($term, $containers)) { - $term = taxonomy_get_term($term); + $term = taxonomy_get_term_data($term); form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => $term->name))); } } @@ -565,7 +565,7 @@ function forum_get_topics($tid, $sortby, } } - $term = taxonomy_get_term($tid); + $term = taxonomy_get_term_data($tid); $sql = db_rewrite_sql("SELECT n.nid, r.tid, n.title, n.type, n.sticky, u.name, u.uid, n.created AS timestamp, n.comment AS comment_mode, l.last_comment_timestamp, IF(l.last_comment_uid != 0, cu.name, l.last_comment_name) AS last_comment_name, l.last_comment_uid, l.comment_count AS num_comments, f.tid AS forum_tid FROM {node_comment_statistics} l INNER JOIN {node} n ON n.nid = l.nid INNER JOIN {users} cu ON l.last_comment_uid = cu.uid INNER JOIN {term_node} r ON n.vid = r.vid INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {forum} f ON n.vid = f.vid WHERE n.status = 1 AND r.tid = %d"); $sql .= tablesort_sql($forum_topic_list_header, 'n.sticky DESC,'); Index: modules/taxonomy/taxonomy.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.admin.inc,v retrieving revision 1.27 diff -u -p -r1.27 taxonomy.admin.inc --- modules/taxonomy/taxonomy.admin.inc 16 Jul 2008 21:59:28 -0000 1.27 +++ modules/taxonomy/taxonomy.admin.inc 11 Sep 2008 17:22:53 -0000 @@ -233,9 +233,9 @@ function taxonomy_admin_vocabulary_edit( /** * Page to edit a vocabulary term. */ -function taxonomy_admin_term_edit($tid) { - if ($term = (array)taxonomy_get_term($tid)) { - return drupal_get_form('taxonomy_form_term', taxonomy_vocabulary_load($term['vid']), $term); +function taxonomy_admin_term_edit($term) { + if (isset($term)) { + return drupal_get_form('taxonomy_form_term', taxonomy_vocabulary_load($term->vid), (array)$term); } return drupal_not_found(); } @@ -700,13 +700,7 @@ function taxonomy_form_term(&$form_state $exclude[] = $edit['tid']; $form['advanced']['parent'] = _taxonomy_term_select(t('Parents'), 'parent', $parent, $vocabulary->vid, t('Parent terms') . '.', 1, '<' . t('root') . '>', $exclude); - $form['advanced']['relations'] = _taxonomy_term_select(t('Related terms'), 'relations', array_keys(taxonomy_get_related($edit['tid'])), $vocabulary->vid, NULL, 1, '<' . t('none') . '>', array($edit['tid'])); } - $form['advanced']['synonyms'] = array( - '#type' => 'textarea', - '#title' => t('Synonyms'), - '#default_value' => implode("\n", taxonomy_get_synonyms($edit['tid'])), - '#description' => t('Synonyms of this term, one synonym per line.')); $form['advanced']['weight'] = array( '#type' => 'textfield', '#title' => t('Weight'), @@ -770,7 +764,9 @@ function taxonomy_form_term_submit($form return; } - switch (taxonomy_save_term($form_state['values'])) { + $status = taxonomy_save_term($form_state['values']); + + switch($status) { case SAVED_NEW: drupal_set_message(t('Created new term %term.', array('%term' => $form_state['values']['name']))); watchdog('taxonomy', 'Created new term %term.', array('%term' => $form_state['values']['name']), WATCHDOG_NOTICE, l(t('edit'), 'admin/content/taxonomy/edit/term/' . $form_state['values']['tid'])); @@ -804,7 +800,6 @@ function taxonomy_form_term_submit($form } $form_state['tid'] = $form_state['values']['tid']; - $form_state['redirect'] = 'admin/content/taxonomy'; return; } @@ -835,7 +830,7 @@ function taxonomy_term_confirm_parents(& * @see taxonomy_term_confirm_delete_submit() */ function taxonomy_term_confirm_delete(&$form_state, $tid) { - $term = taxonomy_get_term($tid); + $term = taxonomy_term_load($tid); $form['type'] = array('#type' => 'value', '#value' => 'term'); $form['name'] = array('#type' => 'value', '#value' => $term->name); Index: modules/taxonomy/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v retrieving revision 1.425 diff -u -p -r1.425 taxonomy.module --- modules/taxonomy/taxonomy.module 24 Jul 2008 16:25:19 -0000 1.425 +++ modules/taxonomy/taxonomy.module 11 Sep 2008 17:22:53 -0000 @@ -142,9 +142,10 @@ function taxonomy_menu() { 'type' => MENU_CALLBACK, ); - $items['admin/content/taxonomy/edit/term'] = array( + $items['admin/content/taxonomy/edit/term/%taxonomy_term'] = array( 'title' => 'Edit term', 'page callback' => 'taxonomy_admin_term_edit', + 'page arguments' => array(5), 'access arguments' => array('administer taxonomy'), 'type' => MENU_CALLBACK, ); @@ -156,6 +157,18 @@ function taxonomy_menu() { 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, ); + $items['taxonomy/term/%/view'] = array( + 'title' => 'View', + 'type' => MENU_DEFAULT_LOCAL_TASK, + ); + $items['taxonomy/term/%taxonomy_term/edit'] = array( + 'title' => 'Edit term', + 'page callback' => 'taxonomy_admin_term_edit', + 'page arguments' => array(2), + 'access arguments' => array('administer taxonomy'), + 'type' => MENU_LOCAL_TASK, + 'weight' => 10, + ); $items['taxonomy/autocomplete'] = array( 'title' => 'Autocomplete taxonomy', @@ -291,7 +304,7 @@ function taxonomy_check_vocabulary_hiera /** * Helper function for taxonomy_form_term_submit(). * - * @param $form_state['values'] + * @param $form_values * @return * Status constant indicating if term was inserted or updated. */ @@ -302,26 +315,19 @@ function taxonomy_save_term(&$form_value ); if (!empty($form_values['tid']) && $form_values['name']) { - drupal_write_record('term_data', $form_values, 'tid'); - $hook = 'update'; - $status = SAVED_UPDATED; + $status = drupal_write_record('term_data', $form_values, 'tid'); + $term = taxonomy_term_load($form_values['tid']); + module_invoke_all('taxonomy_term_save', $term, $form_values); } else if (!empty($form_values['tid'])) { + $term = taxonomy_term_load($form_values['tid']); + module_invoke_all('taxonomy_term_delete', $term); return taxonomy_del_term($form_values['tid']); } else { - drupal_write_record('term_data', $form_values); - $hook = 'insert'; - $status = SAVED_NEW; - } - - db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $form_values['tid'], $form_values['tid']); - if (!empty($form_values['relations'])) { - foreach ($form_values['relations'] as $related_id) { - if ($related_id != 0) { - db_query('INSERT INTO {term_relation} (tid1, tid2) VALUES (%d, %d)', $form_values['tid'], $related_id); - } - } + $status = drupal_write_record('term_data', $form_values); + $term = taxonomy_term_load($form_values['tid']); + module_invoke_all('taxonomy_term_save', $term, $form_values); } db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $form_values['tid']); @@ -344,15 +350,6 @@ function taxonomy_save_term(&$form_value db_query('INSERT INTO {term_hierarchy} (tid, parent) VALUES (%d, %d)', $form_values['tid'], $form_values['parent']); } - db_query('DELETE FROM {term_synonym} WHERE tid = %d', $form_values['tid']); - if (!empty($form_values['synonyms'])) { - foreach (explode ("\n", str_replace("\r", '', $form_values['synonyms'])) as $synonym) { - if ($synonym) { - db_query("INSERT INTO {term_synonym} (tid, name) VALUES (%d, '%s')", $form_values['tid'], chop($synonym)); - } - } - } - if (isset($hook)) { module_invoke_all('taxonomy', $hook, 'term', $form_values); } @@ -379,22 +376,20 @@ function taxonomy_del_term($tid) { 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); + $parents = taxonomy_get_parent_tids($child->tid); if (count($parents) == 1) { $orphans[] = $child->tid; } } } - $term = (array) taxonomy_get_term($tid); + $term = (array) taxonomy_term_load($tid); - db_query('DELETE FROM {term_data} WHERE tid = %d', $tid); - db_query('DELETE FROM {term_hierarchy} WHERE tid = %d', $tid); - db_query('DELETE FROM {term_relation} WHERE tid1 = %d OR tid2 = %d', $tid, $tid); - db_query('DELETE FROM {term_synonym} WHERE tid = %d', $tid); - db_query('DELETE FROM {term_node} WHERE tid = %d', $tid); + db_query('DELETE FROM {term_data} WHERE tid = :tid', array(':tid' => $tid)); + db_query('DELETE FROM {term_hierarchy} WHERE tid = :tid', array(':tid' => $tid)); + db_query('DELETE FROM {term_node} WHERE tid = :tid', array(':tid' => $tid)); - module_invoke_all('taxonomy', 'delete', 'term', $term); + module_invoke_all('taxonomy_term_delete', $term); } $tids = $orphans; @@ -579,13 +574,13 @@ function taxonomy_preview_terms($node) { $taxonomy['tags'] = $term; } else { - $taxonomy[$tid] = taxonomy_get_term($tid); + $taxonomy[$tid] = taxonomy_get_term_data($tid); } } } // A 'Single select' field returns the term id. elseif ($term) { - $taxonomy[$term] = taxonomy_get_term($term); + $taxonomy[$term] = taxonomy_get_term_term($term); } } } @@ -728,20 +723,19 @@ function taxonomy_node_type($op, $info) } /** - * Find all term objects related to a given term ID. + * Find all parent tids of a given term ID. */ -function taxonomy_get_related($tid, $key = 'tid') { +function taxonomy_get_parent_tids($tid) { if ($tid) { - $result = db_query('SELECT t.*, tid1, tid2 FROM {term_relation}, {term_data} t WHERE (t.tid = tid1 OR t.tid = tid2) AND (tid1 = %d OR tid2 = %d) AND t.tid != %d ORDER BY weight, name', $tid, $tid, $tid); - $related = array(); - while ($term = db_fetch_object($result)) { - $related[$term->$key] = $term; + $result = db_query(db_rewrite_sql("SELECT t.tid FROM {term_data} t INNER JOIN {term_hierarchy} h ON h.parent = t.tid WHERE h.tid = :tid ORDER BY weight, name", 't', 'tid'), array(':tid' => $tid)); + $parents = array(); + foreach ($result AS $tid) { + drupal_set_message('
' . var_dump($tid->tid) . '
'); + + $parents[] = $tid->tid; } - return $related; - } - else { - return array(); } + return $parents; } /** @@ -767,7 +761,7 @@ function taxonomy_get_parents($tid, $key function taxonomy_get_parents_all($tid) { $parents = array(); if ($tid) { - $parents[] = taxonomy_get_term($tid); + $parents[] = taxonomy_get_term_data($tid); $n = 0; while ($parent = taxonomy_get_parents($parents[$n]->tid)) { $parents = array_merge($parents, $parent); @@ -997,7 +991,7 @@ function taxonomy_vocabulary_load($vid) } /** - * Return the term object matching a term ID. + * Return a fully loaded term object. * * @param $tid * A term's ID @@ -1005,11 +999,42 @@ function taxonomy_vocabulary_load($vid) * @return Object * A term object. Results are statically cached. */ -function taxonomy_get_term($tid) { +function taxonomy_term_load($tid) { + static $terms = array(); + + // Ensure numeric tid to avoid loading the first term on 1+2 URLs. + // The db layer casts '1 2' to '1', so doesn't help here. + if (!is_numeric($tid)) { + return FALSE; + } + + if (!isset($terms[$tid])) { + $terms[$tid] = taxonomy_get_term_data($tid); + + $term = $terms[$tid]; + $vocabulary = taxonomy_vocabulary_load($term->vid); + if ($vocabulary->hierarchy) { + $term->parents = taxonomy_get_parent_tids($term->tid); + } + // Allow other modules to act on the term object. + module_invoke_all('taxonomy_term_load', $term); + $terms[$tid] = $term; + } + return $terms[$tid]; +} + +/** + * Return a term object from the term_data table. + * @param $tid + * A term's ID + * @return Object + * A term object. Results are statically cached. + */ +function taxonomy_get_term_data($tid) { static $terms = array(); if (!isset($terms[$tid])) { - $terms[$tid] = db_fetch_object(db_query('SELECT * FROM {term_data} WHERE tid = %d', $tid)); + $terms[$tid] = db_fetch_object(db_query('SELECT * FROM {term_data} WHERE tid = :tid', array(':tid' => $tid))); } return $terms[$tid]; @@ -1046,7 +1071,7 @@ function _taxonomy_term_select($title, $ /** * Format the selection field for choosing terms - * (by deafult the default selection field is used). + * (by default the default selection field is used). * * @ingroup themeable */ @@ -1080,7 +1105,7 @@ function taxonomy_select_nodes($tids = a $depth = NULL; } foreach ($tids as $index => $tid) { - $term = taxonomy_get_term($tid); + $term = taxonomy_get_term_data($tid); $tree = taxonomy_get_tree($term->vid, $tid, -1, $depth); $descendant_tids[] = array_merge(array($tid), array_map('_taxonomy_get_tid_from_term', $tree)); } @@ -1123,7 +1148,7 @@ function taxonomy_select_nodes($tids = a function taxonomy_render_nodes($result) { $output = ''; $has_rows = FALSE; - while ($node = db_fetch_object($result)) { + foreach ($result AS $node) { $output .= node_view(node_load($node->nid), 1); $has_rows = TRUE; } @@ -1240,7 +1265,6 @@ function taxonomy_help($path, $arg) { $output .= '

' . t('Preparation Time: 0-30mins, 30-60mins, 1-2 hrs, 2hrs+') . '

'; $output .= '

' . t("Each taxonomy term (often called a 'category' or 'tag' in other systems) automatically provides lists of posts and a corresponding RSS feed. These taxonomy/term URLs can be manipulated to generate AND and OR lists of posts classified with terms. In our recipe site example, it then becomes easy to create pages displaying 'Main courses', '30 minute recipes', or '30 minute main courses and appetizers' by using terms on their own or in combination with others. There are a significant number of contributed modules which you to alter and extend the behavior of the core module for both display and organization of terms.") . '

'; $output .= '

' . t("Terms can also be organized in parent/child relationships from the admin interface. An example would be a vocabulary grouping countries under their parent geo-political regions. The taxonomy module also enables advanced implementations of hierarchy, for example placing Turkey in both the 'Middle East' and 'Europe'.") . '

'; - $output .= '

' . t('The taxonomy module supports the use of both synonyms and related terms, but does not directly use this functionality. However, optional contributed or custom modules may make full use of these advanced features.') . '

'; $output .= '

' . t('For more information, see the online handbook entry for Taxonomy module.', array('@taxonomy' => 'http://drupal.org/handbook/modules/taxonomy/')) . '

'; return $output; case 'admin/content/taxonomy': Index: modules/taxonomy/taxonomy.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.pages.inc,v retrieving revision 1.12 diff -u -p -r1.12 taxonomy.pages.inc --- modules/taxonomy/taxonomy.pages.inc 21 Aug 2008 19:36:38 -0000 1.12 +++ modules/taxonomy/taxonomy.pages.inc 11 Sep 2008 17:22:53 -0000 @@ -51,7 +51,7 @@ function taxonomy_term_page($str_tids = $channel['title'] = variable_get('site_name', 'Drupal') . ' - ' . $title; // Only display the description if we have a single term, to avoid clutter and confusion. if (count($tids) == 1) { - $term = taxonomy_get_term($tids[0]); + $term = taxonomy_term_load($tids[0]); // HTML will be removed from feed description, so no need to filter here. $channel['description'] = $term->description; } @@ -92,7 +92,7 @@ function theme_taxonomy_term_page($tids, // Only display the description if we have a single term, to avoid clutter and confusion. if (count($tids) == 1) { - $term = taxonomy_get_term($tids[0]); + $term = taxonomy_term_load($tids[0]); $description = $term->description; // Check that a description is set. Index: modules/taxonomy/taxonomy.test =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v retrieving revision 1.3 diff -u -p -r1.3 taxonomy.test --- modules/taxonomy/taxonomy.test 8 Sep 2008 21:37:21 -0000 1.3 +++ modules/taxonomy/taxonomy.test 11 Sep 2008 17:22:53 -0000 @@ -114,13 +114,7 @@ class TaxonomyTermFunctionsTestCase exte $termname = $this->randomName(20); $termdesc = $this->randomName(200); $termweight = rand(-9, 9); - $randSyn = rand(0, 9); - $synonyms = array(); - for($i = 0; $i < $randSyn; $i++) { - $synonyms[] = $this->randomName(20); - } - $termsyn = implode("\n", $synonyms); - $data = array('name' => $termname, 'description' => $termdesc, 'weight' => $termweight, 'synonyms' => $termsyn, 'vid' => $edit['vid'], 'tid' => 0, 'relations' => 0); + $data = array('name' => $termname, 'description' => $termdesc, 'weight' => $termweight, 'vid' => $edit['vid'], 'tid' => 0); taxonomy_save_term($data); // Retrieve term and check all fields. @@ -130,32 +124,6 @@ class TaxonomyTermFunctionsTestCase exte foreach($checkField as $v) { $this->assertEqual($data[$v], $getTerm->$v, t('Checking value of the term (@v).', array('@v' => $v))); } - $getSynonyms = taxonomy_get_synonyms($getTerm->tid); - $this->assertEqual(sort($synonyms), sort($getSynonyms), 'Checking synonyms'); - - // Creating related terms. - $relations = array(); - $staryTid = $getTerm->tid; - $relations[] = $staryTid; - $termname = $this->randomName(20); - $data = array('name' => $termname, 'description' => '', 'weight' => 0, 'synonyms' => 0, 'vid' => $edit['vid'], 'tid' => 0, 'relations' => array($staryTid)); - taxonomy_save_term($data); - $_tArray = taxonomy_get_term_by_name($termname); - $getTerm = $_tArray[0]; - $relations[] = $getTerm->tid; - - // Creating another term related to 2 terms above. - $termname = $this->randomName(20); - $data = array('name' => $termname, 'description' => '', 'weight' => 0, 'synonyms' => 0, 'vid' => $edit['vid'], 'tid' => 0, 'relations' => array($staryTid, $getTerm->tid)); - taxonomy_save_term($data); - $_tArray = taxonomy_get_term_by_name($termname); - $getTerm = $_tArray[0]; - - // Check related terms. - $related = taxonomy_get_related($getTerm->tid); - foreach($relations as $rTid) { - $this->assertTrue(array_key_exists($rTid, $related), t('Checking relations (@rTid).', array('@rTid' => $rTid))); - } // Delete vocabulary. $edit['name'] = 0;