Very rough initial commit of taxonomy for everyone's hacking pleasure. There be dragons. see #4189

git-svn-id: http://svn.automattic.com/wordpress/trunk@5510 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
ryan 2007-05-22 05:12:38 +00:00
parent 3ed5b0a01e
commit 634a33c206
8 changed files with 214 additions and 122 deletions

View File

@ -282,27 +282,14 @@ function category_exists($cat_name) {
}
function tag_exists($tag_name) {
global $wpdb;
if (! $tag_nicename = sanitize_title($tag_name))
return 0;
return (int) $wpdb->get_var("SELECT cat_ID FROM $wpdb->categories WHERE category_nicename = '$tag_nicename' AND ( type & " . TAXONOMY_TAG . " != 0 )");
return is_term($tag_name, 'post_tag');
}
function wp_create_tag($tag_name) {
if ( $id = tag_exists($tag_name) )
return $id;
$tag_array = array('cat_name' => $tag_name, 'type' => TAXONOMY_TAG);
if ( $id = category_object_exists($tag_name) ) {
$category = get_category($id);
$tag_array['type'] = $category->type | $tag_array['type'];
$tag_array['cat_ID'] = $id;
$id = wp_update_category($tag_array);
return $id;
} else {
return wp_insert_category($tag_array);
}
$tag_id = add_term($tag_name, 'post_tag');
}
function wp_delete_user($id, $reassign = 'novalue') {

View File

@ -664,16 +664,13 @@ function get_tags_to_edit( $post_id ) {
if ( !$post_id )
return false;
$tags = $wpdb->get_results( "
SELECT category_id, cat_name
FROM $wpdb->categories, $wpdb->post2cat
WHERE $wpdb->post2cat.category_id = cat_ID AND $wpdb->post2cat.post_id = '$post_id' AND rel_type = 'tag'
" );
$tags = wp_get_post_tags($post_id);
if ( !$tags )
return false;
foreach ( $tags as $tag )
$tag_names[] = $tag->cat_name;
$tag_names[] = $tag->name;
$tags_to_edit = join( ', ', $tag_names );
$tags_to_edit = attribute_escape( $tags_to_edit );
$tags_to_edit = apply_filters( 'tags_to_edit', $tags_to_edit );

View File

@ -10,20 +10,29 @@ if ( version_compare(mysql_get_server_info(), '4.1.0', '>=') ) {
$charset_collate .= " COLLATE $wpdb->collate";
}
$wp_queries="CREATE TABLE $wpdb->categories (
cat_ID bigint(20) NOT NULL auto_increment,
cat_name varchar(55) NOT NULL default '',
category_nicename varchar(200) NOT NULL default '',
category_description longtext NOT NULL,
category_parent bigint(20) NOT NULL default '0',
category_count bigint(20) NOT NULL default '0',
link_count bigint(20) NOT NULL default '0',
tag_count bigint(20) NOT NULL default '0',
posts_private tinyint(1) NOT NULL default '0',
links_private tinyint(1) NOT NULL default '0',
type tinyint NOT NULL default '1',
PRIMARY KEY (cat_ID),
KEY category_nicename (category_nicename)
$wp_queries="CREATE TABLE $wpdb->terms (
term_id bigint(20) NOT NULL auto_increment,
name varchar(55) NOT NULL default '',
slug varchar(200) NOT NULL default '',
term_group bigint(10) NOT NULL default 0,
PRIMARY KEY (term_id),
UNIQUE KEY slug (slug)
) $charset_collate;
CREATE TABLE $wpdb->term_taxonomy (
term_taxonomy_id bigint(20) NOT NULL auto_increment,
term_id bigint(20) NOT NULL default 0,
taxonomy varchar(32) NOT NULL default '',
description longtext NOT NULL,
parent bigint(20) NOT NULL default 0,
count bigint(20) NOT NULL default 0,
PRIMARY KEY (term_taxonomy_id),
UNIQUE KEY (term_id, taxonomy)
) $charset_collate;
CREATE TABLE $wpdb->term_relationships (
object_id bigint(20) NOT NULL default 0,
term_taxonomy_id bigint(20) NOT NULL default 0,
PRIMARY KEY (object_id),
KEY (term_taxonomy_id)
) $charset_collate;
CREATE TABLE $wpdb->comments (
comment_ID bigint(20) unsigned NOT NULL auto_increment,
@ -45,13 +54,6 @@ CREATE TABLE $wpdb->comments (
KEY comment_approved (comment_approved),
KEY comment_post_ID (comment_post_ID)
) $charset_collate;
CREATE TABLE $wpdb->link2cat (
rel_id bigint(20) NOT NULL auto_increment,
link_id bigint(20) NOT NULL default '0',
category_id bigint(20) NOT NULL default '0',
PRIMARY KEY (rel_id),
KEY link_id (link_id,category_id)
) $charset_collate;
CREATE TABLE $wpdb->links (
link_id bigint(20) NOT NULL auto_increment,
link_url varchar(255) NOT NULL default '',
@ -86,14 +88,6 @@ CREATE TABLE $wpdb->options (
PRIMARY KEY (option_id,blog_id,option_name),
KEY option_name (option_name)
) $charset_collate;
CREATE TABLE $wpdb->post2cat (
rel_id bigint(20) NOT NULL auto_increment,
post_id bigint(20) NOT NULL default '0',
category_id bigint(20) NOT NULL default '0',
rel_type varchar(64) NOT NULL default 'category',
PRIMARY KEY (rel_id),
KEY post_id (post_id,category_id)
) $charset_collate;
CREATE TABLE $wpdb->postmeta (
meta_id bigint(20) NOT NULL auto_increment,
post_id bigint(20) NOT NULL default '0',

View File

@ -459,10 +459,8 @@ function wp_get_post_tags( $post_id = 0 ) {
$post_id = (int) $post_id;
if ( !isset( $tag_cache[$blog_id][$post_id] ) )
update_post_category_cache( $post_id ); // loads $tag_cache
return $tag_cache[$blog_id][$post_id];
$tags = get_object_terms($post_id, 'post_tag');
return $tags;
}
function wp_get_recent_posts($num = 10) {
@ -793,75 +791,10 @@ function wp_set_post_tags( $post_id = 0, $tags = '', $append = false ) {
if ( !$post_id )
return false;
// prevent warnings for unintialized variables
$tag_ids = array();
if ( empty($tags) )
$tags = array();
$tags = (is_array($tags)) ? $tags : explode( ',', $tags );
foreach ( $tags as $tag ) {
$tag = trim( $tag );
if ( !$tag_slug = sanitize_title( $tag ) )
continue; // discard
if ( !$tag_id = tag_exists( $tag ) )
$tag_id = wp_create_tag( $tag );
$tag_ids[] = $tag_id;
}
if ( empty($tag_ids) && ( !empty($tags) || $append ) )
return false;
$tag_ids = array_unique( $tag_ids );
// First the old tags
$old_tags = $wpdb->get_col("
SELECT category_id
FROM $wpdb->post2cat
WHERE post_id = '$post_id' AND rel_type = 'tag'");
if ( !$old_tags ) {
$old_tags = array();
} else {
$old_tags = array_unique( $old_tags );
}
// Delete any?
$delete_tags = array_diff( $old_tags, $tag_ids);
if ( $delete_tags && !$append ) {
foreach ( $delete_tags as $del ) {
$wpdb->query("
DELETE FROM $wpdb->post2cat
WHERE category_id = '$del'
AND post_id = '$post_id'
AND rel_type = 'tag'
");
}
}
// Add any?
$add_tags = array_diff( $tag_ids, $old_tags );
if ( $add_tags ) {
foreach ( $add_tags as $new_tag ) {
$new_tag = (int) $new_tag;
if ( !empty($new_tag) )
$wpdb->query("
INSERT INTO $wpdb->post2cat (post_id, category_id, rel_type)
VALUES ('$post_id', '$new_tag', 'tag')");
}
}
// Update category counts.
$all_affected_tags = array_unique( array_merge( $tag_ids, $old_tags ) );
foreach ( $all_affected_tags as $tag_id ) {
$count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->post2cat, $wpdb->posts WHERE $wpdb->posts.ID=$wpdb->post2cat.post_id AND post_status = 'publish' AND post_type = 'post' AND category_id = '$tag_id' AND rel_type = 'tag'" );
$wpdb->query( "UPDATE $wpdb->categories SET tag_count = '$count', type = type | " . TAXONOMY_TAG . " WHERE cat_ID = '$tag_id'" );
if ( $count == 0 )
$wpdb->query( "UPDATE $wpdb->categories SET type = type & ~". TAXONOMY_TAG . " WHERE cat_ID = '$tag_id'" );
clean_category_cache( $tag_id );
do_action( 'edit_category', $tag_id );
do_action( 'edit_tag', $tag_id );
}
add_term_relationship($tags, $post_id, 'post_tag');
}
function wp_set_post_categories($post_ID = 0, $post_categories = array()) {

174
wp-includes/taxonomy.php Normal file
View File

@ -0,0 +1,174 @@
<?php
// TODO: add_term(), edit_term(), and remove_term() work with terms within context of
// taxonomies. insert_term(), update_term(), delete_term() work with just the terms table.
// insert_term_taxonomy(), update_term_taxonomy(), and delete_term_taxonomy() work
// with just the term taxonomy table. Right now we only have add_term().
/**
* Adds a new term to the database. Optionally marks it as an alias of an existing term.
* @param string $term The term to add.
* @param string $taxonomy The taxonomy to which to add the term
* @param int|string $alias_of The id or slug of the new term's alias.
*/
function add_term( $term, $taxonomy, $args = array() ) {
global $wpdb;
$slug = sanitize_title($term);
$defaults = array( 'alias_of' => '', 'description' => '', 'parent' => 0);
$args = wp_parse_args($args, $defaults);
extract($args);
$term_group = 0;
if ( $alias_of ) {
$alias = $wpdb->fetch_row("SELECT term_id, term_group FROM $wpdb->terms WHERE slug = '$alias_of'");
if ( $alias->term_group ) {
// The alias we want is already in a group, so let's use that one.
$term_group = $alias->term_group;
} else {
// The alias isn't in a group, so let's create a new one and firstly add the alias term to it.
$term_group = $wpdb->get_var("SELECT MAX() term_group FROM $wpdb->terms GROUP BY term_group") + 1;
$wpdb->query("UPDATE $wpdb->terms SET term_group = $term_group WHERE term_id = $alias->term_id");
}
}
if ( ! $term_id = is_term($slug) ) {
$wpdb->query("INSERT INTO $wpdb->terms (name, slug, term_group) VALUES ('$term', '$slug', '$term_group')");
$term_id = (int) $wpdb->insert_id;
}
$tt_id = $wpdb->get_var("SELECT tt.term_taxonomy_id FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = '$taxonomy' AND t.term_id = $term_id");
if ( !empty($tt_id) )
return $term_id;
$wpdb->query("INSERT INTO $wpdb->term_taxonomy (term_id, taxonomy, description, parent, count) VALUES ('$term_id', '$taxonomy', '$description', '$parent', '0')");
// TODO: Maybe return both term_id and tt_id.
return $term_id;
}
/**
* Removes a term from the database.
*/
function remove_term() {}
/**
* Returns the index of a defined term, or 0 (false) if the term doesn't exist.
*/
function is_term($term, $taxonomy = '') {
global $wpdb;
if ( ! $term = sanitize_title($term) )
return 0;
return $wpdb->get_var("SELECT term_id FROM $wpdb->terms WHERE slug = '$term'");
}
/**
* Given an array of terms, returns those that are defined term slugs. Ignores integers.
* @param array $terms The term slugs to check for a definition.
*/
function get_defined_terms($terms) {
global $wpdb;
foreach ( $terms as $term ) {
if ( !is_int($term) )
$searches[] = $term;
}
$terms = "'" . implode("', '", $searches) . "'";
return $wpdb->get_col("SELECT slug FROM $wpdb->terms WHERE slug IN ($terms)");
}
/**
* Relates an object (post, link etc) to a term and taxonomy type. Creates the term and taxonomy
* relationship if it doesn't already exist. Creates a term if it doesn't exist (using the slug).
* @param array|int|string $term The slug or id of the term.
* @param int $object_id The object to relate to.
* @param array|string $taxonomies The context(s) in which to relate the term to the object.
*/
function add_term_relationship($terms, $object_id, $taxonomies) {
global $wpdb;
if ( !is_array($taxonomies) )
$taxonomies = array($taxonomies);
if ( !is_array($terms) )
$terms = array($terms);
$defined_terms = get_defined_terms($terms);
foreach ( $terms as $term ) {
if ( !is_int($term) ) {
if ( !isset($defined_terms[$term]) )
$new_terms[] = $term;
$slugs[] = $term;
} else {
$term_ids[] = $term;
}
}
$term_clause = isset($term_ids) ? 'tt.term_id IN (' . implode(', ', $term_ids) . ')' : '';
if ( isset($slugs) ) {
if ($term_clause) {
$term_clause .= ' OR ';
}
$term_clause .= "t.slug IN ('" . implode("', '", $slugs) . "')";
$term_join = "INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id";
} else {
$term_join = '';
}
// Now add or increment the term taxonomy relationships. This is inefficient at the moment.
foreach ( $taxonomies as $taxonomy ) {
foreach ( $terms as $term ) {
add_term($term, $taxonomy);
}
}
$taxonomies = "'" . implode("', '", $taxonomies) . "'";
// Finally, relate the term and taxonomy to the object.
// Use IGNORE to avoid dupe warnings for now.
$wpdb->query("INSERT IGNORE INTO $wpdb->term_relationships(object_id, term_taxonomy_id) SELECT '$object_id', term_taxonomy_id FROM $wpdb->term_taxonomy AS tt $term_join WHERE ($term_clause) AND tt.taxonomy IN ($taxonomies)");
}
/**
* Returns the terms associated with the given object(s), in the supplied taxonomies.
* @param int|array $object_id The id of the object(s)) to retrieve for.
* @param string|array $taxonomies The taxonomies to retrieve terms from.
* @return array The requested term data.
*/
function get_object_terms($object_id, $taxonomy) {
global $wpdb;
$taxonomies = ($single_taxonomy = !is_array($taxonomy)) ? array($taxonomy) : $taxonomy;
$object_ids = ($single_object = !is_array($object_id)) ? array($object_id) : $object_id;
$taxonomies = "'" . implode("', '", $taxonomies) . "'";
$object_ids = implode(', ', $object_ids);
if ( $taxonomy_data = $wpdb->get_results("SELECT t.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON tt.term_id = t.term_id INNER JOIN $wpdb->term_relationships AS tr ON tr.term_taxonomy_id = tt.term_taxonomy_id WHERE tt.taxonomy IN ($taxonomies) AND tr.object_id IN ($object_ids)") ) {
if ($single_taxonomy && $single_object) {
// Just one kind of taxonomy for one object.
return $taxonomy_data;
} else {
foreach ($taxonomy_data as $data) {
if ($single_taxonomy) {
// Many objects, one taxonomy type.
$return[$data->object_id][] = $data;
} elseif ($single_object) {
// One object, many taxonomies.
$return[$data->taxonomy][] = $data;
} else {
// Many objects, many taxonomies.
$return[$data->object_id][$data->taxonomy][] = $data;
}
}
return $return;
}
} else {
return array();
}
}
?>

View File

@ -3,6 +3,6 @@
// This holds the version number in a separate file so we can bump it without cluttering the SVN
$wp_version = '2.3-alpha';
$wp_db_version = 5200;
$wp_db_version = 5495;
?>

View File

@ -34,6 +34,9 @@ class wpdb {
var $optiongroups;
var $optiongroup_options;
var $postmeta;
var $terms;
var $term_taxonomy;
var $term_relationships;
var $charset;
var $collate;

View File

@ -116,6 +116,9 @@ $wpdb->links = $wpdb->prefix . 'links';
$wpdb->options = $wpdb->prefix . 'options';
$wpdb->postmeta = $wpdb->prefix . 'postmeta';
$wpdb->usermeta = $wpdb->prefix . 'usermeta';
$wpdb->terms = $wpdb->prefix . 'terms';
$wpdb->term_taxonomy = $wpdb->prefix . 'term_taxonomy';
$wpdb->term_relationships = $wpdb->prefix . 'term_relationships';
if ( defined('CUSTOM_USER_TABLE') )
$wpdb->users = CUSTOM_USER_TABLE;
@ -168,6 +171,7 @@ require (ABSPATH . WPINC . '/cron.php');
require (ABSPATH . WPINC . '/version.php');
require (ABSPATH . WPINC . '/deprecated.php');
require (ABSPATH . WPINC . '/script-loader.php');
require (ABSPATH . WPINC . '/taxonomy.php');
if (strpos($_SERVER['PHP_SELF'], 'install.php') === false) {
// Used to guarantee unique hash cookies