#412518 by catch, bangpound, and yched: Convert taxonomy_node_* to field API (with upgrade path). Say buh-bye to old, crusty code.

merge-requests/26/head
Angie Byron 2009-10-08 07:58:47 +00:00
parent f5b02199c7
commit c4e1242e92
13 changed files with 929 additions and 1343 deletions

View File

@ -20,7 +20,7 @@
* - $topic->message: If the topic has been moved, this contains an
* explanation and a link.
* - $topic->zebra: 'even' or 'odd' string used for row class.
* - $topic->num_comments: The number of replies on this topic.
* - $topic->comment_count: The number of replies on this topic.
* - $topic->new_replies: A flag to indicate whether there are unread comments.
* - $topic->new_url: If there are unread replies, this is a link to them.
* - $topic->new_text: Text containing the translated, properly pluralized count.
@ -53,7 +53,7 @@
<td colspan="3"><?php print $topic->message; ?></td>
<?php else: ?>
<td class="replies">
<?php print $topic->num_comments; ?>
<?php print $topic->comment_count; ?>
<?php if ($topic->new_replies): ?>
<br />
<a href="<?php print $topic->new_url; ?>"><?php print $topic->new_text; ?></a>

View File

@ -5,8 +5,8 @@
* @file
* Administrative page callbacks for the forum module.
*/
function forum_form_main($type, $edit = array()) {
$edit = (array) $edit;
if ((isset($_POST['op']) && $_POST['op'] == t('Delete')) || !empty($_POST['confirm'])) {
return drupal_get_form('forum_confirm_delete', $edit['tid']);
}

View File

@ -22,9 +22,7 @@ function forum_install() {
function forum_enable() {
if ($vocabulary = taxonomy_vocabulary_load(variable_get('forum_nav_vocabulary', 0))) {
// Existing install. Add back forum node type, if the forums
// vocabulary still exists. Keep all other node types intact there.
$vocabulary->nodes['forum'] = 1;
// Save the vocabulary to create the default field instance.
taxonomy_vocabulary_save($vocabulary);
}
else {
@ -33,17 +31,26 @@ function forum_enable() {
// forms.
$edit = array(
'name' => t('Forums'),
'multiple' => 0,
'required' => 0,
'machine_name' => 'forums',
'description' => t('Forum navigation vocabulary'),
'hierarchy' => 1,
'relations' => 0,
'module' => 'forum',
'weight' => -10,
'nodes' => array('forum' => 1),
);
$vocabulary = (object) $edit;
taxonomy_vocabulary_save($vocabulary);
$instance = array(
'field_name' => 'taxonomy_' . $vocabulary->machine_name,
'label' => $vocabulary->name,
'bundle' => 'forum',
'widget' => array(
'type' => 'options_select',
),
);
field_create_instance($instance);
variable_set('forum_nav_vocabulary', $vocabulary->vid);
}
}
@ -109,6 +116,68 @@ function forum_schema() {
),
);
$schema['forum_index'] = array(
'description' => 'Maintains denormalized information about node/term relationships.',
'fields' => array(
'nid' => array(
'description' => 'The {node}.nid this record tracks.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'title' => array(
'description' => 'The title of this node, always treated as non-markup plain text.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'tid' => array(
'description' => 'The term ID.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'sticky' => array(
'description' => 'Boolean indicating whether the node is sticky.',
'type' => 'int',
'not null' => FALSE,
'default' => 0,
'size' => 'tiny',
),
'created' => array(
'description' => 'The Unix timestamp when the node was created.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default'=> 0,
),
'last_comment_timestamp' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp of the last comment that was posted within this node, from {comment}.timestamp.',
),
'comment_count' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The total number of comments on this node.',
),
),
'indexes' => array(
'forum_topics' => array('tid', 'sticky', 'last_comment_timestamp'),
),
'foreign keys' => array(
'node' => 'nid',
'taxonomy_term_data' => 'tid',
),
);
return $schema;
}
@ -119,3 +188,74 @@ function forum_update_7000() {
db_drop_index('forum', 'nid');
db_add_index('forum', 'forum_topic', array('nid', 'tid'));
}
/**
* Create new {forum_index} table.
*/
function forum_update_7001() {
$forum_index = array(
'description' => 'Maintains denormalized information about node/term relationships.',
'fields' => array(
'nid' => array(
'description' => 'The {node}.nid this record tracks.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'title' => array(
'description' => 'The title of this node, always treated as non-markup plain text.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'tid' => array(
'description' => 'The term ID.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'sticky' => array(
'description' => 'Boolean indicating whether the node is sticky.',
'type' => 'int',
'not null' => FALSE,
'default' => 0,
'size' => 'tiny',
),
'created' => array(
'description' => 'The Unix timestamp when the node was created.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default'=> 0,
),
'last_comment_timestamp' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp of the last comment that was posted within this node, from {comment}.timestamp.',
),
'comment_count' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The total number of comments on this node.',
),
),
'indexes' => array(
'forum_topics' => array('tid', 'sticky', 'last_comment_timestamp'),
),
'foreign keys' => array(
'node' => 'nid',
'taxonomy_term_data' => 'tid',
),
);
db_create_table($ret, 'forum_index', $forum_index);
db_query('INSERT INTO {forum_index} (SELECT n.nid, n.title, f.tid, n.sticky, n.created, ncs.last_comment_timestamp, ncs.comment_count FROM {node} n INNER JOIN {forum} f on n.vid = f.vid INNER JOIN {node_comment_statistics} ncs ON n.nid = ncs.nid)');
return $ret;
}

View File

@ -60,25 +60,6 @@ function forum_theme() {
);
}
/**
* Fetch a forum term.
*
* @param $tid
* The ID of the term which should be loaded.
*
* @return
* An associative array containing the term data or FALSE if the term cannot be loaded, or is not part of the forum vocabulary.
*/
function forum_term_load($tid) {
return db_select('taxonomy_term_data', 't')
->fields('t', array('tid', 'vid', 'name', 'description', 'weight'))
->condition('tid', $tid)
->condition('vid', variable_get('forum_nav_vocabulary', 0))
->addTag('term_access')
->execute()
->fetchAssoc();
}
/**
* Implement hook_menu().
*/
@ -130,13 +111,13 @@ function forum_menu() {
'parent' => 'admin/structure/forum',
'file' => 'forum.admin.inc',
);
$items['admin/structure/forum/edit/%forum_term'] = array(
$items['admin/structure/forum/edit/%taxonomy_term'] = array(
'page callback' => 'forum_form_main',
'access arguments' => array('administer forums'),
'type' => MENU_CALLBACK,
'file' => 'forum.admin.inc',
);
$items['admin/structure/forum/edit/container/%forum_term'] = array(
$items['admin/structure/forum/edit/container/%taxonomy_term'] = array(
'title' => 'Edit container',
'page callback' => 'forum_form_main',
'page arguments' => array('container', 5),
@ -144,7 +125,7 @@ function forum_menu() {
'type' => MENU_CALLBACK,
'file' => 'forum.admin.inc',
);
$items['admin/structure/forum/edit/forum/%forum_term'] = array(
$items['admin/structure/forum/edit/forum/%taxonomy_term'] = array(
'title' => 'Edit forum',
'page callback' => 'forum_form_main',
'page arguments' => array('forum', 5),
@ -164,28 +145,19 @@ function forum_init() {
}
/**
* _forum_node_check_node_type
* Check whether a content type can be used in a forum.
*
* @param mixed $node
* @param mixed $vocabulary
* @access protected
* @return bool
* @param $node
* A node object.
*
* @return
* Boolean indicating if the node can be assigned to a forum.
*/
function _forum_node_check_node_type($node, $vocabulary) {
// We are going to return if $node->type is not one of the node
// types assigned to the forum vocabulary. If forum_nav_vocabulary
// is undefined or the vocabulary does not exist, it clearly cannot
// be assigned to $node->type, so return to avoid E_ALL warnings.
if (empty($vocabulary)) {
return FALSE;
}
function _forum_node_check_node_type($node) {
// Fetch information about the forum field.
$field = field_info_instance('taxonomy_forums', $node->type);
// Operate only on node types assigned for the forum vocabulary.
if (!in_array($node->type, $vocabulary->nodes)) {
return FALSE;
}
return TRUE;
return is_array($field);
}
/**
@ -194,24 +166,15 @@ function _forum_node_check_node_type($node, $vocabulary) {
function forum_node_view($node, $build_mode) {
$vid = variable_get('forum_nav_vocabulary', 0);
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_node_check_node_type($node, $vocabulary)) {
if ((bool)menu_get_object() && taxonomy_node_get_terms_by_vocabulary($node, $vid) && $tree = taxonomy_get_tree($vid)) {
// Get the forum terms from the (cached) tree
foreach ($tree as $term) {
$forum_terms[] = $term->tid;
}
foreach ($node->taxonomy as $term_id => $term) {
if (in_array($term_id, $forum_terms)) {
$node->tid = $term_id;
}
}
if (_forum_node_check_node_type($node)) {
if ((bool)menu_get_object()) {
// Breadcrumb navigation
$breadcrumb[] = l(t('Home'), NULL);
$breadcrumb[] = l($vocabulary->name, 'forum');
if ($parents = taxonomy_get_parents_all($node->tid)) {
if ($parents = taxonomy_get_parents_all($node->forum_tid)) {
$parents = array_reverse($parents);
foreach ($parents as $p) {
$breadcrumb[] = l($p->name, 'forum/' . $p->tid);
foreach ($parents as $parent) {
$breadcrumb[] = l($parent->name, 'forum/' . $parent->tid);
}
}
drupal_set_breadcrumb($breadcrumb);
@ -224,15 +187,10 @@ function forum_node_view($node, $build_mode) {
* Implement hook_node_prepare().
*/
function forum_node_prepare($node) {
$vid = variable_get('forum_nav_vocabulary', 0);
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_node_check_node_type($node, $vocabulary)) {
if (_forum_node_check_node_type($node)) {
if (empty($node->nid)) {
// New topic
$node->taxonomy[arg(3)] = (object) array(
'vid' => $vid,
'tid' => arg(3),
);
$node->taxonomy_forums[0]['value'] = arg(3);
}
}
}
@ -243,22 +201,20 @@ function forum_node_prepare($node) {
* Check in particular that only a "leaf" term in the associated taxonomy.
*/
function forum_node_validate($node, $form) {
$vid = variable_get('forum_nav_vocabulary', 0);
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_node_check_node_type($node, $vocabulary)) {
if (_forum_node_check_node_type($node)) {
$langcode = $form['taxonomy_forums']['#language'];
// vocabulary is selected, not a "container" term.
if ($node->taxonomy) {
if (!empty($node->taxonomy_forums[$langcode])) {
// Extract the node's proper topic ID.
$vocabulary = $vid;
$containers = variable_get('forum_containers', array());
foreach ($node->taxonomy as $term) {
$used = db_query_range('SELECT 1 FROM {taxonomy_term_data} WHERE tid = :tid AND vid = :vid', 0, 1, array(
':tid' => $term,
':vid' => $vocabulary,
foreach ($node->taxonomy_forums[$langcode] as $tid) {
$term = taxonomy_term_load($tid['value']);
$used = db_query_range('SELECT 1 FROM {taxonomy_term_data} WHERE tid = :tid AND vid = :vid',0 , 1, array(
':tid' => $term->tid,
':vid' => $term->vid,
))->fetchField();
if ($used && in_array($term, $containers)) {
$term = taxonomy_term_load($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)));
if ($used && in_array($term->tid, $containers)) {
form_set_error('taxonomy_forums', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => $term->name)));
}
}
}
@ -271,26 +227,16 @@ function forum_node_validate($node, $form) {
* Assign forum taxonomy when adding a topic from within a forum.
*/
function forum_node_presave($node) {
$vid = variable_get('forum_nav_vocabulary', 0);
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_node_check_node_type($node, $vocabulary)) {
if (_forum_node_check_node_type($node)) {
// Make sure all fields are set properly:
$node->icon = !empty($node->icon) ? $node->icon : '';
if ($node->taxonomy && $tree = taxonomy_get_tree($vid)) {
// Get the forum terms from the (cached) tree if we have a taxonomy.
foreach ($tree as $term) {
$forum_terms[] = $term->tid;
}
foreach ($node->taxonomy as $term_id) {
if (in_array($term_id, $forum_terms)) {
$node->tid = $term_id;
}
}
$langcode = array_shift(array_keys($node->taxonomy_forums));
if (!empty($node->taxonomy_forums[$langcode])) {
$node->forum_tid = $node->taxonomy_forums[$langcode][0]['value'];
$old_tid = db_query_range("SELECT f.tid FROM {forum} f INNER JOIN {node} n ON f.vid = n.vid WHERE n.nid = :nid ORDER BY f.vid DESC", 0, 1, array(':nid' => $node->nid))->fetchField();
if ($old_tid && isset($node->tid) && ($node->tid != $old_tid) && !empty($node->shadow)) {
if ($old_tid && isset($node->forum_tid) && ($node->forum_tid != $old_tid) && !empty($node->shadow)) {
// A shadow copy needs to be created. Retain new term and add old term.
$node->taxonomy[] = $old_tid;
$node->taxonomy_forums[$langcode][] = array('value' => $old_tid);
}
}
}
@ -300,13 +246,11 @@ function forum_node_presave($node) {
* Implement hook_node_update().
*/
function forum_node_update($node) {
$vid = variable_get('forum_nav_vocabulary', 0);
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_node_check_node_type($node, $vocabulary)) {
if (_forum_node_check_node_type($node)) {
if (empty($node->revision) && db_query('SELECT tid FROM {forum} WHERE nid=:nid', array(':nid' => $node->nid))->fetchField()) {
if (!empty($node->tid)) {
if (!empty($node->forum_tid)) {
db_update('forum')
->fields(array('tid' => $node->tid))
->fields(array('tid' => $node->forum_tid))
->condition('vid', $node->vid)
->execute();
}
@ -318,16 +262,31 @@ function forum_node_update($node) {
}
}
else {
if (!empty($node->tid)) {
if (!empty($node->forum_tid)) {
db_insert('forum')
->fields(array(
'tid' => $node->tid,
'tid' => $node->forum_tid,
'vid' => $node->vid,
'nid' => $node->nid,
))
->execute();
}
}
// If the node has a shadow forum topic, update the record for this
// revision.
if ($node->shadow) {
db_delete('forum')
->condition('nid', $node->nid)
->condition('vid', $node->vid)
->execute();
db_insert('forum')
->fields(array(
'nid' => $node->nid,
'vid' => $node->vid,
'tid' => $node->forum_tid,
))
->execute();
}
}
}
@ -335,13 +294,11 @@ function forum_node_update($node) {
* Implement hook_node_insert().
*/
function forum_node_insert($node) {
$vid = variable_get('forum_nav_vocabulary', 0);
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_node_check_node_type($node, $vocabulary)) {
if (!empty($node->tid)) {
if (_forum_node_check_node_type($node)) {
if (!empty($node->forum_tid)) {
$nid = db_insert('forum')
->fields(array(
'tid' => $node->tid,
'tid' => $node->forum_tid,
'vid' => $node->vid,
'nid' => $node->nid,
))
@ -354,34 +311,32 @@ function forum_node_insert($node) {
* Implement hook_node_delete().
*/
function forum_node_delete($node) {
$vid = variable_get('forum_nav_vocabulary', 0);
$vocabulary = taxonomy_vocabulary_load($vid);
if (_forum_node_check_node_type($node, $vocabulary)) {
if (_forum_node_check_node_type($node)) {
db_delete('forum')
->condition('nid', $node->nid)
->execute();
db_delete('forum_index')
->condition('nid', $node->nid)
->execute();
}
}
/**
* Implement hook_node_load().
*/
function forum_node_load($nodes, $types) {
$vid = variable_get('forum_nav_vocabulary', 0);
// If no forum vocabulary is set up, return.
if ($vid == '') {
return;
}
$vocabulary = taxonomy_vocabulary_load($vid);
function forum_node_load($nodes) {
$node_vids = array();
foreach ($nodes as $node) {
if (isset($vocabulary->nodes[$node->type])) {
if (_forum_node_check_node_type($node)) {
$node_vids[] = $node->vid;
}
}
if (!empty($node_vids)) {
$result = db_query('SELECT nid, tid FROM {forum} WHERE vid IN(:node_vids)', array(':node_vids' => $node_vids));
$query = db_select('forum', 'f');
$query
->fields('f', array('nid', 'tid'))
->condition('f.vid', $node_vids);
$result = $query->execute();
foreach ($result as $record) {
$nodes[$record->nid]->forum_tid = $record->tid;
}
@ -418,26 +373,111 @@ function forum_permission() {
/**
* Implement hook_taxonomy().
*/
function forum_taxonomy($op, $type, $term = NULL) {
if ($op == 'delete' && $term['vid'] == variable_get('forum_nav_vocabulary', 0)) {
switch ($type) {
case 'term':
$result = db_query('SELECT f.nid FROM {forum} f WHERE f.tid = :tid', array(':tid' => $term['tid']));
foreach ($result as $node) {
// node_delete will also remove any association with non-forum vocabularies.
node_delete($node->nid);
}
function forum_taxonomy_term_delete($tid) {
// For containers, remove the tid from the forum_containers variable.
$containers = variable_get('forum_containers', array());
$key = array_search($tid, $containers);
if ($key !== FALSE) {
unset($containers[$key]);
}
variable_set('forum_containers', $containers);
}
// For containers, remove the tid from the forum_containers variable.
$containers = variable_get('forum_containers', array());
$key = array_search($term['tid'], $containers);
if ($key !== FALSE) {
unset($containers[$key]);
/**
* Implement hook_comment_publish().
*
* This actually handles the insert and update of published nodes since
* comment_save() calls hook_comment_publish() for all published comments.
*/
function forum_comment_publish($comment) {
_forum_update_forum_index($comment->nid);
}
/**
* Implement forum_comment_update().
*
* Comment module doesn't call hook_comment_unpublish() when saving individual
* comments so we need to check for those here.
*/
function forum_comment_update($comment) {
// comment_save() calls hook_comment_publish() for all published comments
// so we to handle all other values here.
if (!$comment->status) {
_forum_update_forum_index($comment->nid);
}
}
/**
* Implement forum_comment_unpublish() {
*/
function forum_comment_unpublish($comment) {
_forum_update_forum_index($comment->nid);
}
/**
* Implement forum_comment_delete().
*/
function forum_comment_delete($comment) {
_forum_update_forum_index($comment->nid);
}
/**
* Implement hook_field_attach_pre_insert().
*/
function forum_field_attach_pre_insert($obj_type, $object, $skip_fields) {
if ($obj_type == 'node' && $object->status && _forum_node_check_node_type($object)) {
$query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp'));
foreach ($object->taxonomy_forums as $language) {
foreach ($language as $delta) {
$query->values(array(
'nid' => $object->nid,
'title' => $object->title,
'tid' => $delta['value'],
'sticky' => $object->sticky,
'created' => $object->created,
'comment_count' => 0,
'last_comment_timestamp' => $object->created,
));
}
}
$query->execute();
}
}
/**
* Implement hook_field_attach_pre_update().
*/
function forum_field_attach_pre_update($obj_type, $object, $skip_fields) {
$first_call = &drupal_static(__FUNCTION__, array());
if ($obj_type == 'node' && $object->status && _forum_node_check_node_type($object)) {
// We don't maintain data for old revisions, so clear all previous values
// from the table. Since this hook runs once per field, per object, make
// sure we only wipe values once.
if (!isset($first_call[$object->nid])) {
$first_call[$object->nid] = FALSE;
db_delete('forum_index')->condition('nid', $object->nid)->execute();
}
// Only save data to the table if the node is published.
if ($object->status) {
$query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp'));
foreach ($object->taxonomy_forums as $language) {
foreach ($language as $delta) {
$query->values(array(
'nid' => $object->nid,
'title' => $object->title,
'tid' => $delta['value'],
'sticky' => $object->sticky,
'created' => $object->created,
'comment_count' => 0,
'last_comment_timestamp' => $object->created,
));
}
variable_set('forum_containers', $containers);
break;
case 'vocabulary':
variable_del('forum_nav_vocabulary');
}
$query->execute();
// The logic for determining last_comment_count is fairly complex, so
// call _forum_update_forum_index() too.
_forum_update_forum_index($object->nid);
}
}
}
@ -454,13 +494,8 @@ function forum_form_alter(&$form, $form_state, $form_id) {
'#markup' => t('This is the designated forum vocabulary. Some of the normal vocabulary options have been removed.'),
'#weight' => -1,
);
$form['content_types']['nodes']['#required'] = TRUE;
$form['hierarchy'] = array('#type' => 'value', '#value' => 1);
$form['settings']['required'] = array('#type' => 'value', '#value' => FALSE);
$form['settings']['relations'] = array('#type' => 'value', '#value' => FALSE);
$form['settings']['tags'] = array('#type' => 'value', '#value' => FALSE);
$form['settings']['multiple'] = array('#type' => 'value', '#value' => FALSE);
unset($form['delete']);
$form['delete']['#access'] = FALSE;
}
// Hide multiple parents select from forum terms.
elseif ($form_id == 'taxonomy_form_term') {
@ -468,10 +503,10 @@ function forum_form_alter(&$form, $form_state, $form_id) {
}
}
if ($form_id == 'forum_node_form') {
$langcode = $form['taxonomy_forums']['#language'];
// Make the vocabulary required for 'real' forum-nodes.
$vid = variable_get('forum_nav_vocabulary', 0);
$form['taxonomy'][$vid]['#required'] = TRUE;
$form['taxonomy'][$vid]['#options'][''] = t('- Please choose -');
$form['taxonomy_forums'][$langcode]['#required'] = TRUE;
$form['taxonomy_forums'][$langcode]['#multiple'] = FALSE;
}
}
@ -512,28 +547,21 @@ function forum_block_save($delta = '', $edit = array()) {
* most recently added forum topics.
*/
function forum_block_view($delta = '') {
$query = db_select('node', 'n');
$query->join('forum', 'f', 'f.vid = n.vid');
$query->join('taxonomy_term_data', 'td', 'td.tid = f.tid');
$query->join('node_comment_statistics', 'ncs', 'n.nid = ncs.nid');
$query
->fields('n', array('nid', 'title'))
->fields('ncs', array('comment_count', 'last_comment_timestamp'))
->condition('n.status', 1)
->condition('td.vid', variable_get('forum_nav_vocabulary', 0))
$query = db_select('forum_index', 'f')
->fields('f')
->addTag('node_access');
switch ($delta) {
case 'active':
$title = t('Active forum topics');
$query
->orderBy('ncs.last_comment_timestamp', 'DESC')
->orderBy('f.last_comment_timestamp', 'DESC')
->range(0, variable_get('forum_block_num_active', '5'));
break;
case 'new':
$title = t('New forum topics');
$query
->orderBy('n.nid', 'DESC')
->orderBy('f.created', 'DESC')
->range(0, variable_get('forum_block_num_new', '5'));
break;
}
@ -581,11 +609,11 @@ function forum_form($node, $form_state) {
$form['title'] = array('#type' => 'textfield', '#title' => check_plain($type->title_label), '#default_value' => !empty($node->title) ? $node->title : '', '#required' => TRUE, '#weight' => -5);
if (!empty($node->nid)) {
$vid = variable_get('forum_nav_vocabulary', 0);
$forum_terms = taxonomy_node_get_terms_by_vocabulary($node, $vid);
// if editing, give option to leave shadows
$forum_terms = $node->taxonomy_forums;
// If editing, give option to leave shadows
$shadow = (count($forum_terms) > 1);
$form['shadow'] = array('#type' => 'checkbox', '#title' => t('Leave shadow copy'), '#default_value' => $shadow, '#description' => t('If you move this topic, you can leave a link in the old forum to the new forum.'));
$form['forum_tid'] = array('#type' => 'value', '#value' => $node->forum_tid);
}
$form['#submit'][] = 'forum_submit';
@ -667,7 +695,7 @@ function forum_get_forums($tid = 0) {
$last_post = new stdClass();
if (!empty($topic->last_comment_timestamp)) {
$last_post->timestamp = $topic->last_comment_timestamp;
$last_post->created = $topic->last_comment_timestamp;
$last_post->name = $topic->last_comment_name;
$last_post->uid = $topic->last_comment_uid;
}
@ -702,9 +730,9 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
$forum_topic_list_header = array(
NULL,
array('data' => t('Topic'), 'field' => 'n.title'),
array('data' => t('Replies'), 'field' => 'ncs.comment_count'),
array('data' => t('Last reply'), 'field' => 'ncs.last_comment_timestamp'),
array('data' => t('Topic'), 'field' => 'f.title'),
array('data' => t('Replies'), 'field' => 'f.comment_count'),
array('data' => t('Last reply'), 'field' => 'f.last_comment_timestamp'),
);
$order = _forum_get_topic_order($sortby);
@ -714,48 +742,45 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
}
}
$query = db_select('node_comment_statistics', 'ncs')->extend('PagerDefault')->extend('TableSort');
$query->join('node', 'n', 'n.nid = ncs.nid');
$query->join('users', 'cu', 'ncs.last_comment_uid = cu.uid');
$query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $tid));
$query->join('users', 'u', 'n.uid = u.uid');
$query->addExpression('IF(ncs.last_comment_uid != 0, cu.name, ncs.last_comment_name)', 'last_comment_name');
$query->addField('n', 'created', 'timestamp');
$query->addField('n', 'comment', 'comment_mode');
$query->addField('ncs', 'comment_count', 'num_comments');
$query->addField('f', 'tid', 'forum_tid');
$query = db_select('forum_index', 'f')->extend('PagerDefault')->extend('TableSort');
$query->fields('f');
$query
->condition('f.tid', $tid)
->addTag('node_access')
->fields('n', array('nid', 'title', 'type', 'sticky'))
->fields('f', array('tid'))
->fields('u', array('name', 'uid'))
->fields('ncs', array('last_comment_timestamp', 'last_comment_uid'))
->condition('n.status', 1)
->orderBy('n.sticky', 'DESC')
->orderBy('f.sticky', 'DESC')
->orderByHeader($forum_topic_list_header)
->orderBy('n.created', 'DESC')
->orderBy('f.last_comment_timestamp', 'DESC')
->limit($forum_per_page);
$count_query = db_select('node', 'n');
$count_query->join('forum', 'f', 'n.vid = f.vid AND f.tid = :tid', array(':tid' => $tid));
$count_query = db_select('forum_index', 'f');
$count_query->condition('f.tid', $tid);
$count_query->addExpression('COUNT(*)');
$count_query
->condition('n.status', 1)
->addTag('node_access');
$count_query->addTag('node_access');
$query->setCountQuery($count_query);
$result = $query->execute();
$nids = array();
foreach ($result as $record) {
$nids[] = $record->nid;
}
if ($nids) {
$result = db_query("SELECT n.title, n.nid, n.sticky, n.created, n.uid, n.comment AS comment_mode, ncs.*, f.tid AS forum_tid, u.name, IF (ncs.last_comment_uid != 0, u2.name, ncs.last_comment_name) AS last_comment_name FROM {node} n INNER JOIN {node_comment_statistics} ncs ON n.nid = ncs.nid INNER JOIN {forum} f ON n.vid = f.vid INNER JOIN {users} u ON n.uid = u.uid INNER JOIN {users} u2 ON ncs.last_comment_uid = u2.uid WHERE n.nid IN (:nids)", array(':nids' => $nids));
}
else {
$result = array();
}
$topics = array();
foreach ($result as $topic) {
if ($user->uid) {
// folder is new if topic is new or there are new comments since last visit
if ($topic->tid != $tid) {
if ($topic->forum_tid != $tid) {
$topic->new = 0;
}
else {
$history = _forum_user_last_visit($topic->nid);
$topic->new_replies = comment_num_new($topic->nid, $history);
$topic->new = $topic->new_replies || ($topic->timestamp > $history);
$topic->new = $topic->new_replies || ($topic->last_comment_timestamp > $history);
}
}
else {
@ -764,9 +789,9 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
$topic->new = 0;
}
if ($topic->num_comments > 0) {
if ($topic->comment_count > 0) {
$last_reply = new stdClass();
$last_reply->timestamp = $topic->last_comment_timestamp;
$last_reply->created = $topic->last_comment_timestamp;
$last_reply->name = $topic->last_comment_name;
$last_reply->uid = $topic->last_comment_uid;
$topic->last_reply = $last_reply;
@ -820,8 +845,9 @@ function template_preprocess_forums(&$variables) {
// Format the "post new content" links listing.
$forum_types = array();
// Loop through all node types for forum vocabulary.
foreach ($vocabulary->nodes as $type) {
// Loop through all bundles for forum taxonomy vocabulary field.
$field = field_info_field('taxonomy_' . $vocabulary->machine_name);
foreach ($field['bundles'] as $type) {
// Check if the current user has the 'create' permission for this node type.
if (node_access('create', $type)) {
// Fetch the "General" name of the content type;
@ -951,14 +977,14 @@ function template_preprocess_forum_topic_list(&$variables) {
if (!empty($variables['topics'])) {
$row = 0;
foreach ($variables['topics'] as $id => $topic) {
$variables['topics'][$id]->icon = theme('forum_icon', $topic->new, $topic->num_comments, $topic->comment_mode, $topic->sticky);
$variables['topics'][$id]->icon = theme('forum_icon', $topic->new, $topic->comment_count, $topic->comment_mode, $topic->sticky);
$variables['topics'][$id]->zebra = $row % 2 == 0 ? 'odd' : 'even';
$row++;
// We keep the actual tid in forum table, if it's different from the
// current tid then it means the topic appears in two forums, one of
// them is a shadow copy.
if ($topic->forum_tid != $variables['tid']) {
if ($variables['tid'] != $topic->forum_tid) {
$variables['topics'][$id]->moved = TRUE;
$variables['topics'][$id]->title = check_plain($topic->title);
$variables['topics'][$id]->message = l(t('This topic has been moved'), "forum/$topic->forum_tid");
@ -968,6 +994,7 @@ function template_preprocess_forum_topic_list(&$variables) {
$variables['topics'][$id]->title = l($topic->title, "node/$topic->nid");
$variables['topics'][$id]->message = '';
}
$topic->uid = $topic->last_comment_uid ? $topic->last_comment_uid : $topic->uid;
$variables['topics'][$id]->created = theme('forum_submitted', $topic);
$variables['topics'][$id]->last_reply = theme('forum_submitted', isset($topic->last_reply) ? $topic->last_reply : NULL);
@ -1031,7 +1058,7 @@ function template_preprocess_forum_icon(&$variables) {
*/
function template_preprocess_forum_submitted(&$variables) {
$variables['author'] = isset($variables['topic']->uid) ? theme('username', $variables['topic']) : '';
$variables['time'] = isset($variables['topic']->timestamp) ? format_interval(REQUEST_TIME - $variables['topic']->timestamp) : '';
$variables['time'] = isset($variables['topic']->created) ? format_interval(REQUEST_TIME - $variables['topic']->created) : '';
}
function _forum_user_last_visit($nid) {
@ -1063,3 +1090,42 @@ function _forum_get_topic_order($sortby) {
break;
}
}
/**
* Updates the taxonomy index for a given node.
*
* @param $nid
* The ID of the node to update.
*/
function _forum_update_forum_index($nid) {
$count = db_query('SELECT COUNT(cid) FROM {comment} WHERE nid = :nid AND status = :status', array(
':nid' => $nid,
':status' => COMMENT_PUBLISHED,
))->fetchField();
if ($count > 0) {
// Comments exist.
$last_reply = db_query_range('SELECT cid, name, timestamp, uid FROM {comment} WHERE nid = :nid AND status = :status ORDER BY cid DESC', array(
':nid' => $nid,
':status' => COMMENT_PUBLISHED,
), 0, 1)->fetchObject();
db_update('forum_index')
->fields( array(
'comment_count' => $count,
'last_comment_timestamp' => $last_reply->timestamp,
))
->condition('nid', $nid)
->execute();
}
else {
// Comments do not exist.
$node = db_query('SELECT uid, created FROM {node} WHERE nid = :nid', array(':nid' => $nid))->fetchObject();
db_update('forum_index')
->fields( array(
'comment_count' => 0,
'last_comment_timestamp' => $node->created,
))
->condition('nid', $nid)
->execute();
}
}

View File

@ -131,8 +131,7 @@ class ForumTestCase extends DrupalWebTestCase {
$edit = array(
'name' => $title,
'description' => $description,
'machine_name' => drupal_strtolower($this->randomName()),
'help' => '',
'machine_name' => drupal_strtolower(drupal_substr($this->randomName(), 3, 9)),
);
// Edit the vocabulary.
@ -251,7 +250,7 @@ class ForumTestCase extends DrupalWebTestCase {
$edit = array(
'title' => $title,
"body[$langcode][0][value]" => $body,
'taxonomy[1]' => $tid
"taxonomy_forums[$langcode][value]" => $tid,
);
// TODO The taxonomy select value is set by drupal code when the tid is part
@ -341,7 +340,7 @@ class ForumTestCase extends DrupalWebTestCase {
$langcode = FIELD_LANGUAGE_NONE;
$edit["body[$langcode][0][value]"] = $this->randomName(256);
// Assume the topic is initially associated with $forum.
$edit['taxonomy[1]'] = $this->root_forum['tid'];
$edit["taxonomy_forums[$langcode][value]"] = $this->root_forum['tid'];
$edit['shadow'] = TRUE;
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
$this->assertRaw(t('Forum topic %title has been updated.', array('%title' => $edit['title'])), t('Forum node was edited'));

View File

@ -85,7 +85,7 @@ function node_object_prepare($node) {
// If this is a new node, fill in the default values.
if (!isset($node->nid)) {
foreach (array('status', 'promote', 'sticky') as $key) {
$node->$key = in_array($key, $node_options);
$node->$key = (int) in_array($key, $node_options);
}
global $user;
$node->uid = $user->uid;
@ -543,9 +543,6 @@ function node_revision_revert_confirm_submit($form, &$form_state) {
$node_revision = $form['#node_revision'];
$node_revision->revision = 1;
$node_revision->log = t('Copy of the revision from %date.', array('%date' => format_date($node_revision->revision_timestamp)));
if (module_exists('taxonomy')) {
$node_revision->taxonomy = array_keys($node_revision->taxonomy);
}
node_save($node_revision);

View File

@ -1355,14 +1355,15 @@ class DrupalDataApiTest extends DrupalWebTestCase {
$this->assertTrue($update_result == SAVED_UPDATED, t('Correct value returned when a record updated with drupal_write_record() for table with single-field primary key.'));
// Insert an object record for a table with a multi-field primary key.
$vocabulary_node_type = new stdClass();
$vocabulary_node_type->vid = $vocabulary->vid;
$vocabulary_node_type->type = 'page';
$insert_result = drupal_write_record('taxonomy_vocabulary_node_type', $vocabulary_node_type);
$node_access = new stdClass();
$node_access->nid = mt_rand();
$node_access->gid = mt_rand();
$node_access->realm = $this->randomName();
$insert_result = drupal_write_record('node_access', $node_access);
$this->assertTrue($insert_result == SAVED_NEW, t('Correct value returned when a record is inserted with drupal_write_record() for a table with a multi-field primary key.'));
// Update the record.
$update_result = drupal_write_record('taxonomy_vocabulary_node_type', $vocabulary_node_type, array('vid', 'type'));
$update_result = drupal_write_record('node_access', $node_access, array('nid', 'gid', 'realm'));
$this->assertTrue($update_result == SAVED_UPDATED, t('Correct value returned when a record is updated with drupal_write_record() for a table with a multi-field primary key.'));
}

View File

@ -17,14 +17,8 @@ function taxonomy_overview_vocabularies($form) {
$vocabularies = taxonomy_get_vocabularies();
$form['#tree'] = TRUE;
foreach ($vocabularies as $vocabulary) {
$types = array();
foreach ($vocabulary->nodes as $type) {
$node_type = node_type_get_name($type);
$types[] = $node_type ? check_plain($node_type) : check_plain($type);
}
$form[$vocabulary->vid]['#vocabulary'] = $vocabulary;
$form[$vocabulary->vid]['name'] = array('#markup' => check_plain($vocabulary->name));
$form[$vocabulary->vid]['types'] = array('#markup' => implode(', ', $types));
$form[$vocabulary->vid]['weight'] = array('#type' => 'weight', '#delta' => 10, '#default_value' => $vocabulary->weight);
$form[$vocabulary->vid]['edit'] = array('#markup' => l(t('edit vocabulary'), "admin/structure/taxonomy/$vocabulary->vid"));
$form[$vocabulary->vid]['list'] = array('#markup' => l(t('list terms'), "admin/structure/taxonomy/$vocabulary->vid/list"));
@ -71,7 +65,6 @@ function theme_taxonomy_overview_vocabularies($form) {
$row = array();
$row[] = drupal_render($vocabulary['name']);
$row[] = drupal_render($vocabulary['types']);
if (isset($vocabulary['weight'])) {
$vocabulary['weight']['#attributes']['class'] = array('vocabulary-weight');
$row[] = drupal_render($vocabulary['weight']);
@ -87,7 +80,7 @@ function theme_taxonomy_overview_vocabularies($form) {
$rows[] = array(array('data' => t('No vocabularies available. <a href="@link">Add vocabulary</a>.', array('@link' => url('admin/structure/taxonomy/add'))), 'colspan' => '5'));
}
$header = array(t('Vocabulary name'), t('Content types'));
$header = array(t('Vocabulary name'));
if (isset($form['submit'])) {
$header[] = t('Weight');
drupal_add_tabledrag('taxonomy', 'order', 'sibling', 'vocabulary-weight');
@ -110,12 +103,7 @@ function taxonomy_form_vocabulary($form, &$form_state, $edit = array()) {
'name' => '',
'machine_name' => '',
'description' => '',
'help' => '',
'nodes' => array(),
'hierarchy' => 0,
'tags' => 0,
'multiple' => 0,
'required' => 0,
'weight' => 0,
);
$form['#vocabulary'] = (object) $edit;
@ -155,47 +143,11 @@ function taxonomy_form_vocabulary($form, &$form_state, $edit = array()) {
'js' => array(drupal_get_path('module', 'system') . '/system.js', $js_settings),
),
);
$form['help'] = array(
'#type' => 'textfield',
'#title' => t('Help text'),
'#maxlength' => 255,
'#default_value' => $edit['help'],
'#description' => t('Instructions to present to the user when selecting terms, e.g., <em>"Enter a comma separated list of words"</em>.'),
);
$form['description'] = array(
'#type' => 'textfield',
'#title' => t('Description'),
'#default_value' => $edit['description'],
);
$form['nodes'] = array(
'#type' => 'checkboxes',
'#title' => t('Apply to content types'),
'#default_value' => $edit['nodes'],
'#options' => array_map('check_plain', node_type_get_names()),
);
$form['settings'] = array(
'#type' => 'fieldset',
'#title' => t('Settings'),
'#collapsible' => TRUE,
);
$form['settings']['tags'] = array(
'#type' => 'checkbox',
'#title' => t('Tags'),
'#default_value' => $edit['tags'],
'#description' => t('Terms are created by users when submitting posts by typing a comma separated list.'),
);
$form['settings']['multiple'] = array(
'#type' => 'checkbox',
'#title' => t('Multiple select'),
'#default_value' => $edit['multiple'],
'#description' => t('Allows posts to have more than one term from this vocabulary (always true for tags).'),
);
$form['settings']['required'] = array(
'#type' => 'checkbox',
'#title' => t('Required'),
'#default_value' => $edit['required'],
'#description' => t('At least one term in this vocabulary must be selected when submitting a post.'),
);
// Set the hierarchy to "multiple parents" by default. This simplifies the
// vocabulary form and standardizes the term form.
$form['hierarchy'] = array(
@ -225,6 +177,11 @@ function taxonomy_form_vocabulary_validate($form, &$form_state) {
if (!preg_match('!^[a-z0-9_]+$!', $form_state['values']['machine_name'])) {
form_set_error('machine_name', t('The machine-readable name must contain only lowercase letters, numbers, and underscores.'));
}
// Restrict machine names to 21 characters to avoid exceeding the limit
// for field names.
if (drupal_strlen($machine_name) > 21) {
form_set_error('machine_name', t('The machine-readable name must not exceed 21 characters.'));
}
// Do not allow duplicate machine names.
$vocabularies = taxonomy_get_vocabularies();
@ -246,8 +203,6 @@ function taxonomy_form_vocabulary_submit($form, &$form_state) {
$form_state['confirm_delete'] = TRUE;
return;
}
// Fix up the nodes array to remove unchecked nodes.
$form_state['values']['nodes'] = array_filter($form_state['values']['nodes']);
$vocabulary = (object) $form_state['values'];
if ($vocabulary->machine_name != $old_vocabulary->machine_name) {
field_attach_rename_bundle($old_vocabulary->machine_name, $vocabulary->machine_name);
@ -306,106 +261,71 @@ function taxonomy_overview_terms($form, &$form_state, $vocabulary) {
// An array of the terms to be displayed on this page.
$current_page = array();
// Case for free tagging.
if ($vocabulary->tags) {
// We are not calling taxonomy_get_tree because that might fail with a big
// number of tags in the freetagging vocabulary.
$query = db_select('taxonomy_term_data', 't')->extend('PagerDefault');
$query->join('taxonomy_term_hierarchy', 'h', 't.tid = h.tid');
$query->addTag('term_access');
$query->condition('t.vid', $vocabulary->vid);
// Store count in total entries and use this as count query.
$count_query = db_select('taxonomy_term_data', 't');
$count_query->join('taxonomy_term_hierarchy', 'h', 't.tid = h.tid');
$count_query->addTag('term_access');
$count_query->condition('t.vid', $vocabulary->vid);
$count_query->addExpression('COUNT(t.tid)');
$total_entries = $count_query->execute();
$query->setCountQuery($count_query);
$result = $query
->fields('t')
->fields('h', array('parent'))
->orderBy('weight')
->orderBy('name')
->limit($page_increment)
->execute();
foreach ($result as $term) {
$key = 'tid:' . $term->tid . ':0';
$current_page[$key] = $term;
$page_entries++;
$term_deltas = array();
$tree = taxonomy_get_tree($vocabulary->vid);
$term = current($tree);
do {
// In case this tree is completely empty.
if (empty($term)) {
break;
}
// Count entries before the current page.
if ($page && ($page * $page_increment) > $before_entries && !isset($back_peddle)) {
$before_entries++;
continue;
}
// Count entries after the current page.
elseif ($page_entries > $page_increment && isset($complete_tree)) {
$after_entries++;
continue;
}
}
// Case for restricted vocabulary.
else {
$term_deltas = array();
$tree = taxonomy_get_tree($vocabulary->vid);
$term = current($tree);
do {
// In case this tree is completely empty.
if (empty($term)) {
break;
}
// Count entries before the current page.
if ($page && ($page * $page_increment) > $before_entries && !isset($back_peddle)) {
$before_entries++;
continue;
}
// Count entries after the current page.
elseif ($page_entries > $page_increment && isset($complete_tree)) {
$after_entries++;
continue;
}
// Do not let a term start the page that is not at the root.
if (isset($term->depth) && ($term->depth > 0) && !isset($back_peddle)) {
$back_peddle = 0;
while ($pterm = prev($tree)) {
$before_entries--;
$back_peddle++;
if ($pterm->depth == 0) {
prev($tree);
continue 2; // Jump back to the start of the root level parent.
}
}
// Do not let a term start the page that is not at the root.
if (isset($term->depth) && ($term->depth > 0) && !isset($back_peddle)) {
$back_peddle = 0;
while ($pterm = prev($tree)) {
$before_entries--;
$back_peddle++;
if ($pterm->depth == 0) {
prev($tree);
continue 2; // Jump back to the start of the root level parent.
}
}
$back_peddle = isset($back_peddle) ? $back_peddle : 0;
}
$back_peddle = isset($back_peddle) ? $back_peddle : 0;
// Continue rendering the tree until we reach the a new root item.
if ($page_entries >= $page_increment + $back_peddle + 1 && $term->depth == 0 && $root_entries > 1) {
$complete_tree = TRUE;
// This new item at the root level is the first item on the next page.
$after_entries++;
continue;
}
if ($page_entries >= $page_increment + $back_peddle) {
$forward_peddle++;
}
// Continue rendering the tree until we reach the a new root item.
if ($page_entries >= $page_increment + $back_peddle + 1 && $term->depth == 0 && $root_entries > 1) {
$complete_tree = TRUE;
// This new item at the root level is the first item on the next page.
$after_entries++;
continue;
}
if ($page_entries >= $page_increment + $back_peddle) {
$forward_peddle++;
}
// Finally, if we've gotten down this far, we're rendering a term on this page.
$page_entries++;
$term_deltas[$term->tid] = isset($term_deltas[$term->tid]) ? $term_deltas[$term->tid] + 1 : 0;
$key = 'tid:' . $term->tid . ':' . $term_deltas[$term->tid];
// Finally, if we've gotten down this far, we're rendering a term on this page.
$page_entries++;
$term_deltas[$term->tid] = isset($term_deltas[$term->tid]) ? $term_deltas[$term->tid] + 1 : 0;
$key = 'tid:' . $term->tid . ':' . $term_deltas[$term->tid];
// Keep track of the first term displayed on this page.
if ($page_entries == 1) {
$form['#first_tid'] = $term->tid;
}
// Keep a variable to make sure at least 2 root elements are displayed.
if ($term->parents[0] == 0) {
$root_entries++;
}
$current_page[$key] = $term;
} while ($term = next($tree));
// Keep track of the first term displayed on this page.
if ($page_entries == 1) {
$form['#first_tid'] = $term->tid;
}
// Keep a variable to make sure at least 2 root elements are displayed.
if ($term->parents[0] == 0) {
$root_entries++;
}
$current_page[$key] = $term;
} while ($term = next($tree));
// Because we didn't use a pager query, set the necessary pager variables.
$total_entries = $before_entries + $page_entries + $after_entries;
$pager_total_items[0] = $total_entries;
$pager_page_array[0] = $page;
$pager_total[0] = ceil($total_entries / $page_increment);
}
// Because we didn't use a pager query, set the necessary pager variables.
$total_entries = $before_entries + $page_entries + $after_entries;
$pager_total_items[0] = $total_entries;
$pager_page_array[0] = $page;
$pager_total[0] = ceil($total_entries / $page_increment);
// If this form was already submitted once, it's probably hit a validation
// error. Ensure the form is rebuilt in the same order as the user submitted.
@ -433,7 +353,7 @@ function taxonomy_overview_terms($form, &$form_state, $vocabulary) {
}
$form[$key]['view'] = array('#markup' => l($term->name, "taxonomy/term/$term->tid"));
if (!$vocabulary->tags && $vocabulary->hierarchy < 2 && count($tree) > 1) {
if ($vocabulary->hierarchy < 2 && count($tree) > 1) {
$form['#parent_fields'] = TRUE;
$form[$key]['tid'] = array(
'#type' => 'hidden',
@ -460,7 +380,7 @@ function taxonomy_overview_terms($form, &$form_state, $vocabulary) {
$form['#forward_peddle'] = $forward_peddle;
$form['#empty_text'] = t('No terms available. <a href="@link">Add term</a>.', array('@link' => url('admin/structure/taxonomy/' . $vocabulary->vid . '/list/add')));
if (!$vocabulary->tags && $vocabulary->hierarchy < 2 && count($tree) > 1) {
if ($vocabulary->hierarchy < 2 && count($tree) > 1) {
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save')
@ -690,7 +610,6 @@ function taxonomy_form_term($form, &$form_state, $vocabulary, $edit = array()) {
$form['#term'] = $edit;
$form['#term']['parent'] = $parent;
$form['#vocabulary'] = $vocabulary;
$form['#vocabulary']->nodes = drupal_map_assoc($vocabulary->nodes);
$form['#builder_function'] = 'taxonomy_form_term_submit_builder';
// Check for confirmation forms.
@ -747,7 +666,7 @@ function taxonomy_form_term($form, &$form_state, $vocabulary, $edit = array()) {
}
$exclude[] = $edit['tid'];
$form['advanced']['parent'] = _taxonomy_term_select(t('Parents'), $parent, $vocabulary->vid, t('Parent terms') . '.', 1, '<' . t('root') . '>', $exclude);
$form['advanced']['parent'] = _taxonomy_term_select(t('Parents'), $parent, $vocabulary->vid, t('Parent terms') . '.', '<' . t('root') . '>', $exclude);
}
$form['advanced']['synonyms'] = array(
'#type' => 'textarea',
@ -814,7 +733,7 @@ function taxonomy_form_term_submit($form, &$form_state) {
return;
}
// Rebuild the form to confirm enabling multiple parents.
elseif ($form_state['clicked_button']['#value'] == t('Save') && !$form['#vocabulary']->tags && count($form_state['values']['parent']) > 1 && $form['#vocabulary']->hierarchy < 2) {
elseif ($form_state['clicked_button']['#value'] == t('Save') && count($form_state['values']['parent']) > 1 && $form['#vocabulary']->hierarchy < 2) {
$form_state['rebuild'] = TRUE;
$form_state['confirm_parents'] = TRUE;
return;
@ -834,26 +753,24 @@ function taxonomy_form_term_submit($form, &$form_state) {
break;
}
if (!$form['#vocabulary']->tags) {
$current_parent_count = count($form_state['values']['parent']);
$previous_parent_count = count($form['#term']['parent']);
// Root doesn't count if it's the only parent.
if ($current_parent_count == 1 && isset($form_state['values']['parent'][0])) {
$current_parent_count = 0;
$form_state['values']['parent'] = array();
}
$current_parent_count = count($form_state['values']['parent']);
$previous_parent_count = count($form['#term']['parent']);
// Root doesn't count if it's the only parent.
if ($current_parent_count == 1 && isset($form_state['values']['parent'][0])) {
$current_parent_count = 0;
$form_state['values']['parent'] = array();
}
// If the number of parents has been reduced to one or none, do a check on the
// parents of every term in the vocabulary value.
if ($current_parent_count < $previous_parent_count && $current_parent_count < 2) {
taxonomy_check_vocabulary_hierarchy($form['#vocabulary'], $form_state['values']);
}
// If we've increased the number of parents and this is a single or flat
// hierarchy, update the vocabulary immediately.
elseif ($current_parent_count > $previous_parent_count && $form['#vocabulary']->hierarchy < 2) {
$form['#vocabulary']->hierarchy = $current_parent_count == 1 ? 1 : 2;
taxonomy_vocabulary_save($form['#vocabulary']);
}
// If the number of parents has been reduced to one or none, do a check on the
// parents of every term in the vocabulary value.
if ($current_parent_count < $previous_parent_count && $current_parent_count < 2) {
taxonomy_check_vocabulary_hierarchy($form['#vocabulary'], $form_state['values']);
}
// If we've increased the number of parents and this is a single or flat
// hierarchy, update the vocabulary immediately.
elseif ($current_parent_count > $previous_parent_count && $form['#vocabulary']->hierarchy < 2) {
$form['#vocabulary']->hierarchy = $current_parent_count == 1 ? 1 : 2;
taxonomy_vocabulary_save($form['#vocabulary']);
}
$form_state['tid'] = $term->tid;

View File

@ -93,42 +93,6 @@ function taxonomy_schema() {
'primary key' => array('tid', 'parent'),
);
$schema['taxonomy_term_node'] = array(
'description' => 'Stores the relationship of terms to nodes.',
'fields' => array(
'nid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'Primary Key: The {node}.nid of the node.',
),
'vid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'Primary Key: The {node}.vid of the node.',
),
'tid' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'Primary Key: The {taxonomy_term_data}.tid of a term assigned to the node.',
),
),
'indexes' => array(
'vid' => array('vid'),
'nid' => array('nid'),
),
'foreign keys' => array(
'nid' => array('node' => 'nid'),
'vid' => array('node' => 'vid'),
'tid' => array('taxonomy_term_data' => 'tid'),
),
'primary key' => array('tid', 'vid'),
);
$schema['taxonomy_term_synonym'] = array(
'description' => 'Stores term synonyms.',
'fields' => array(
@ -191,13 +155,6 @@ function taxonomy_schema() {
'size' => 'big',
'description' => 'Description of the vocabulary.',
),
'help' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => 'Help text to display for the vocabulary.',
),
'relations' => array(
'type' => 'int',
'unsigned' => TRUE,
@ -214,30 +171,6 @@ function taxonomy_schema() {
'size' => 'tiny',
'description' => 'The type of hierarchy allowed within the vocabulary. (0 = disabled, 1 = single, 2 = multiple)',
),
'multiple' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
'description' => 'Whether or not multiple terms from this vocabulary may be assigned to a node. (0 = disabled, 1 = enabled)',
),
'required' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
'description' => 'Whether or not terms are required for nodes using this vocabulary. (0 = disabled, 1 = enabled)',
),
'tags' => array(
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
'description' => 'Whether or not free tagging is enabled for the vocabulary. (0 = disabled, 1 = enabled)',
),
'module' => array(
'type' => 'varchar',
'length' => 255,
@ -250,7 +183,7 @@ function taxonomy_schema() {
'not null' => TRUE,
'default' => 0,
'size' => 'tiny',
'description' => 'The weight of the vocabulary in relation to other vocabularies.',
'description' => 'The weight of this vocabulary in relation to other vocabularies.',
),
),
'primary key' => array('vid'),
@ -259,30 +192,44 @@ function taxonomy_schema() {
),
);
$schema['taxonomy_vocabulary_node_type'] = array(
'description' => 'Stores which node types vocabularies may be used with.',
$schema['taxonomy_index'] = array(
'description' => 'Maintains denormalized information about node/term relationships.',
'fields' => array(
'vid' => array(
'nid' => array(
'description' => 'The {node}.nid this record tracks.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'Primary Key: the {taxonomy_vocabulary}.vid of the vocabulary.',
),
'type' => array(
'type' => 'varchar',
'length' => 32,
'tid' => array(
'description' => 'The term ID.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'sticky' => array(
'description' => 'Boolean indicating whether the node is sticky.',
'type' => 'int',
'not null' => FALSE,
'default' => 0,
'size' => 'tiny',
),
'created' => array(
'description' => 'The Unix timestamp when the node was created.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => '',
'description' => 'The {node}.type of the node type for which the vocabulary may be used.',
'default'=> 0,
),
),
'primary key' => array('type', 'vid'),
'indexes' => array(
'vid' => array('vid'),
'term_node' => array('tid', 'sticky', 'created'),
),
'foreign keys' => array(
'vid' => array('taxonomy_vocabulary' => 'vid'),
'node' => 'nid',
'taxonomy_term_data' => 'tid',
),
);
@ -322,3 +269,170 @@ function taxonomy_update_7002() {
function taxonomy_update_7003() {
db_drop_field('taxonomy_vocabulary', 'relations');
}
/**
* Move taxonomy vocabulary associations for nodes to fields and field instances.
*/
function taxonomy_update_7004() {
$taxonomy_index = array(
'description' => 'Maintains denormalized information about node/term relationships.',
'fields' => array(
'nid' => array(
'description' => 'The {node}.nid this record tracks.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'tid' => array(
'description' => 'The term ID.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
),
'sticky' => array(
'description' => 'Boolean indicating whether the node is sticky.',
'type' => 'int',
'not null' => FALSE,
'default' => 0,
'size' => 'tiny',
),
'created' => array(
'description' => 'The Unix timestamp when the node was created.',
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default'=> 0,
),
),
'indexes' => array(
'term_node' => array('tid', 'sticky', 'created'),
),
'foreign keys' => array(
'node' => 'nid',
'taxonomy_term_data' => 'tid',
),
);
db_create_table('taxonomy_index', $taxonomy_index);
// Use an inline version of Drupal 6 taxonomy_get_vocabularies() here since
// we can no longer rely on $vocabulary->nodes from the API function.
$result = db_query('SELECT v.*, n.type FROM {taxonomy_vocabulary} v LEFT JOIN {taxonomy_vocabulary_node_type} n ON v.vid = n.vid ORDER BY v.weight, v.name');
$vocabularies = array();
foreach ($result as $record) {
// If no node types are associated with a vocabulary, the LEFT JOIN will
// return a NULL value for type.
if (isset($record->type)) {
$node_types[$record->vid][$record->type] = $record->type;
unset($record->type);
$record->nodes = $node_types[$record->vid];
}
elseif (!isset($record->nodes)) {
$record->nodes = array();
}
$vocabularies[$record->vid] = $record;
}
foreach ($vocabularies as $vocabulary) {
$field_name = 'taxonomy_' . $vocabulary->machine_name;
$field = array(
'field_name' => $field_name,
'type' => 'taxonomy_term',
'cardinality' => $vocabulary->multiple || $vocabulary->tags ? FIELD_CARDINALITY_UNLIMITED : 1,
'settings' => array(
'required' => $vocabulary->required ? TRUE : FALSE,
'allowed_values' => array(
array(
'vid' => $vocabulary->vid,
'parent' => 0,
),
),
),
);
field_create_field($field);
foreach ($vocabulary->nodes as $bundle) {
$instance = array(
'label' => $vocabulary->name,
'field_name' => $field_name,
'bundle' => $bundle,
'description' => $vocabulary->help,
'widget' => array(
'type' => $vocabulary->tags ? 'taxonomy_autocomplete' : 'select',
),
);
field_create_instance($instance);
}
}
db_drop_table('taxonomy_vocabulary_node_type');
$fields = array('help', 'multiple', 'required', 'tags');
foreach ($fields as $field) {
db_drop_field('taxonomy_vocabulary', $field);
}
}
/**
* Migrate {taxonomy_term_node} table to field storage.
*/
function taxonomy_update_7005(&$sandbox) {
// Since we are upgrading from Drupal 6, we know that only
// field_sql_storage.module will be enabled.
$field = field_info_field($field['field_name']);
$data_table = _field_sql_storage_tablename($field);
$revision_table = _field_sql_storage_revision_tablename($field);
$etid = _field_sql_storage_etid('node');
$value_column = $field['field_name'] . '_value';
$columns = array('etid', 'entity_id', 'revision_id', 'bundle', 'delta', $value_column);
// This is a multi-pass update. On the first call we need to initialize some
// variables.
if (!isset($sandbox['total'])) {
$sandbox['last'] = 0;
$sandbox['count'] = 0;
$query = db_select('taxonomy_term_node', 't');
$sandbox['total'] = $query->countQuery()->execute()->fetchField();
$found = (bool) $sandbox['total'];
}
else {
// We do each pass in batches of 1000, this should result in a
// maximum of 2000 insert queries each operation.
$batch = 1000 + $sandbox['last'];
// Query and save data for the current revision.
$result = db_query_range('SELECT td.tid, tn.nid, td.weight, tn.vid, n2.type, n2.created, n2.sticky FROM {taxonomy_term_data} td INNER JOIN {taxonomy_term_node} tn ON td.tid = tn.tid INNER JOIN {node} n2 ON tn.nid = n2.nid INNER JOIN {node} n ON tn.vid = n.vid AND td.vid = :vocabulary_id ORDER BY td.weight ASC', array(':vocabulary_id' => $vocabulary->vid), $sandbox['last'], $batch);
$deltas = array();
foreach ($result as $record) {
$found = TRUE;
$sandbox['count'] += 1;
// Start deltas from 0, and increment by one for each
// term attached to a node.
$deltas[$record->nid] = isset($deltas[$record->nid]) ? ++$deltas[$record->nid] : 0;
$values = array($etid, $record->nid, $record->vid, $record->type, $deltas[$record->nid], $record->tid);
db_insert($data_table)->fields($columns)->values($values)->execute();
// Update the {taxonomy_index} table.
db_insert('taxonomy_index')
->fields(array('nid', 'tid', 'sticky', 'created',))
->values(array($record->nid, $record->tid, $record->sticky, $record->created))
->execute();
}
// Query and save data for all revisions.
$result = db_query('SELECT td.tid, tn.nid, td.weight, tn.vid, n.type FROM {taxonomy_term_data} td INNER JOIN {taxonomy_term_node} tn ON td.tid = tn.tid AND td.vid = :vocabulary_id INNER JOIN {node} n ON tn.nid = n.nid ORDER BY td.weight ASC', array(':vocabulary_id' => $vocabulary->vid), $sandbox['last'][$batch]);
$deltas = array();
foreach ($result as $record) {
$found = TRUE;
$sandbox['count'] += 1;
// Start deltas at 0, and increment by one for each term attached to a revision.
$deltas[$record->vid] = isset($deltas[$record->vid]) ? ++$deltas[$record->vid] : 0;
$values = array($etid, $record->nid, $record->vid, $record->type, $deltas[$record->vid], $record->tid);
db_insert($revision_table)->fields($columns)->values($values)->execute();
}
$sandbox['last'] = $batch;
}
if (!$found) {
db_drop_table('taxonomy_term_node');
}
}

File diff suppressed because it is too large Load Diff

View File

@ -40,8 +40,7 @@ function taxonomy_term_page($term) {
'#suffix' => '</div>',
);
}
if ($nids = taxonomy_select_nodes(array($term->tid), NULL, TRUE)) {
if ($nids = taxonomy_select_nodes($term)) {
$nodes = node_load_multiple($nids);
$build += node_build_multiple($nodes);
$build['pager'] = array(
@ -71,7 +70,7 @@ function taxonomy_term_feed($term) {
// Only display the description if we have a single term, to avoid clutter and confusion.
// HTML will be removed from feed description, so no need to filter here.
$channel['description'] = $term->description;
$nids = taxonomy_select_nodes(array($term->tid, NULL, NULL, FALSE));
$nids = taxonomy_select_nodes(array($term->tid, FALSE));
node_feed($nids, $channel);
}
@ -88,56 +87,6 @@ function taxonomy_term_edit($term) {
return drupal_not_found();
}
/**
* Helper function for autocompletion
*/
function taxonomy_autocomplete_legacy($vid = 0, $tags_typed = '') {
// The user enters a comma-separated list of tags. We only autocomplete the last tag.
$tags_typed = drupal_explode_tags($tags_typed);
$tag_last = drupal_strtolower(array_pop($tags_typed));
$matches = array();
if ($tag_last != '') {
$query = db_select('taxonomy_term_data', 't');
$query->addTag('term_access');
$query->leftJoin('taxonomy_term_synonym', 'ts', 't.tid = ts.tid');
// Don't select already entered terms.
if (count($tags_typed)) {
$query->condition('t.name', $tags_typed, 'NOT IN');
}
$tags_return = $query
->fields('t', array('tid', 'name'))
->condition('t.vid', $vid)
// Select rows that either match by term or synonym name.
->condition(db_or()
->where("LOWER(t.name) LIKE :last_string", array(':last_string' => '%' . $tag_last . '%'))
->where("LOWER(ts.name) LIKE :last_string", array(':last_string' => '%' . $tag_last . '%'))
)
->range(0, 10)
->execute()
->fetchAllKeyed();
$prefix = count($tags_typed) ? implode(', ', $tags_typed) . ', ' : '';
// We use two arrays to make sure synonym suggestions appear last.
$term_matches = $synonym_matches = array();
foreach ($tags_return as $tid => $name) {
$n = $name;
// Commas and quotes in terms are special cases, so encode 'em.
if (strpos($name, ',') !== FALSE || strpos($name, '"') !== FALSE) {
$n = '"' . str_replace('"', '""', $name) . '"';
}
// Inform the user his query matched a synonym rather than a term.
if (strpos(drupal_strtolower($name), $tag_last) === FALSE) {
$name = t('Did you mean %suggestion', array('%suggestion' => $name));
$synonym_matches[$prefix . $n] = filter_xss($name);
}
}
}
drupal_json_output(array_merge($term_matches, $synonym_matches));
}
/**
* Helper function for autocompletion
*/

View File

@ -73,11 +73,6 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
$edit['name'] = $this->randomName();
$edit['description'] = $this->randomName();
$edit['machine_name'] = $machine_name;
$edit['help'] = $this->randomName();
$edit['nodes[article]'] = 'article';
$edit['tags'] = 1;
$edit['multiple'] = 1;
$edit['required'] = 1;
$this->drupalPost(NULL, $edit, t('Save'));
$this->assertRaw(t('Created new vocabulary %name.', array('%name' => $edit['name'])), t('Vocabulary created successfully'));
@ -154,7 +149,6 @@ class TaxonomyVocabularyFunctionalTest extends TaxonomyWebTestCase {
$edit = array(
'name' => $this->randomName(),
'machine_name' => drupal_strtolower($this->randomName()),
'nodes[article]' => 'article',
);
$this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save'));
$this->assertText(t('Created new vocabulary'), t('New vocabulary was created.'));
@ -276,27 +270,23 @@ class TaxonomyVocabularyUnitTest extends TaxonomyWebTestCase {
// Fetch all of the vocabularies using taxonomy_get_vocabularies().
// Confirm that the vocabularies are ordered by weight.
$vocabularies = taxonomy_get_vocabularies();
$this->assertEqual(array_shift($vocabularies), $vocabulary1, t('Vocabulary was found in the vocabularies array.'));
$this->assertEqual(array_shift($vocabularies), $vocabulary2, t('Vocabulary was found in the vocabularies array.'));
$this->assertEqual(array_shift($vocabularies), $vocabulary3, t('Vocabulary was found in the vocabularies array.'));
$this->assertEqual(array_shift($vocabularies)->vid, $vocabulary1->vid, t('Vocabulary was found in the vocabularies array.'));
$this->assertEqual(array_shift($vocabularies)->vid, $vocabulary2->vid, t('Vocabulary was found in the vocabularies array.'));
$this->assertEqual(array_shift($vocabularies)->vid, $vocabulary3->vid, t('Vocabulary was found in the vocabularies array.'));
// Fetch the vocabularies with taxonomy_vocabulary_load_multiple(), specifying IDs.
// Ensure they are returned in the same order as the original array.
$vocabularies = taxonomy_vocabulary_load_multiple(array($vocabulary3->vid, $vocabulary2->vid, $vocabulary1->vid));
$this->assertEqual(array_shift($vocabularies), $vocabulary3, t('Vocabulary loaded successfully by ID.'));
$this->assertEqual(array_shift($vocabularies), $vocabulary2, t('Vocabulary loaded successfully by ID.'));
$this->assertEqual(array_shift($vocabularies), $vocabulary1, t('Vocabulary loaded successfully by ID.'));
$this->assertEqual(array_shift($vocabularies)->vid, $vocabulary3->vid, t('Vocabulary loaded successfully by ID.'));
$this->assertEqual(array_shift($vocabularies)->vid, $vocabulary2->vid, t('Vocabulary loaded successfully by ID.'));
$this->assertEqual(array_shift($vocabularies)->vid, $vocabulary1->vid, t('Vocabulary loaded successfully by ID.'));
// Fetch vocabulary 1 by name.
$this->assertTrue(current(taxonomy_vocabulary_load_multiple(array(), array('name' => $vocabulary1->name))) == $vocabulary1, t('Vocabulary loaded successfully by name.'));
$vocabulary = current(taxonomy_vocabulary_load_multiple(array(), array('name' => $vocabulary1->name)));
$this->assertTrue($vocabulary->vid == $vocabulary1->vid, t('Vocabulary loaded successfully by name.'));
// Fetch vocabulary 1 by name and ID.
$this->assertTrue(current(taxonomy_vocabulary_load_multiple(array($vocabulary1->vid), array('name' => $vocabulary1->name))) == $vocabulary1, t('Vocabulary loaded successfully by name and ID.'));
// Fetch vocabulary 1 with specified node type.
entity_get_controller('taxonomy_vocabulary')->resetCache();
$vocabulary_node_type = current(taxonomy_vocabulary_load_multiple(array($vocabulary1->vid), array('type' => 'article')));
$this->assertEqual($vocabulary_node_type, $vocabulary1, t('Vocabulary with specified node type loaded successfully.'));
$this->assertTrue(current(taxonomy_vocabulary_load_multiple(array($vocabulary1->vid), array('name' => $vocabulary1->name)))->vid == $vocabulary1->vid, t('Vocabulary loaded successfully by name and ID.'));
}
}
@ -312,65 +302,6 @@ class TaxonomyTermUnitTest extends TaxonomyWebTestCase {
'group' => 'Taxonomy',
);
}
/**
* Tests for taxonomy_term_count_nodes().
*
* Attach nodes to a hierarchical vocabulary and check they are counted
* correctly.
*/
function testTaxonomyTermCountNodes() {
// Create a vocabulary with three terms.
$vocabulary = $this->createVocabulary();
$term1 = $this->createTerm($vocabulary);
$term2 = $this->createTerm($vocabulary);
$term3 = $this->createTerm($vocabulary);
// Attach term1 to a node.
$node1 = $this->drupalCreateNode(array('type' => 'page'));
$node1->taxonomy = array($term1->tid);
node_save($node1);
$this->assertEqual(taxonomy_term_count_nodes($term1->tid), 1, t('Term has one valid node association.'));
// Attach term2 to a node.
$node2 = $this->drupalCreateNode(array('type' => 'article'));
$node2->taxonomy = array($term2->tid);
node_save($node2);
$this->assertEqual(taxonomy_term_count_nodes($term2->tid), 1, t('Term has one valid node association.'));
// Confirm that term3 is not associated with any nodes.
$this->assertEqual(taxonomy_term_count_nodes($term3->tid), 0, t('Term is not associated with any nodes'));
// Set term3 as the parent of term1.
$term1->parent = array($term3->tid);
taxonomy_term_save($term1);
// Confirm that the term hierarchy is altered correctly.
$children = taxonomy_get_children($term3->tid);
$this->assertTrue(isset($children[$term1->tid]), t('Term 3 saved as parent of term 1'));
$this->assertEqual(count(taxonomy_get_tree($term3->vid, $term3->tid)), 1, t('Term 3 has one child term'));
// Confirm that term3's parental relationship with term1 leads to a
// node assocation being counted.
$this->assertEqual(taxonomy_term_count_nodes($term3->tid, NULL), 1, t('Term has one valid node association due to child term.'));
// Set term3 as the parent of term2.
$term2->parent = array($term3->tid);
taxonomy_term_save($term2);
// term3 should now have two node associations counted.
$this->assertEqual(taxonomy_term_count_nodes($term3->tid, NULL), 2, t('Term has two valid node associations due to child terms.'));
// Save node1 with both child taxonomy terms, this should still result
// in term3 having two node associations.
$node1->taxonomy = array($term1->tid, $term2->tid);
node_save($node1);
$this->assertEqual(taxonomy_term_count_nodes($term3->tid, NULL), 2, t('Term has two valid node associations.'));
// Confirm that the node type argument returns a single node association.
$this->assertEqual(taxonomy_term_count_nodes($term3->tid, 'page'), 1, t("Term is associated with one node of type 'page'."));
}
}
/**
@ -391,6 +322,20 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
$this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'bypass node access'));
$this->drupalLogin($this->admin_user);
$this->vocabulary = $this->createVocabulary();
$this->instance = array(
'field_name' => 'taxonomy_' . $this->vocabulary->machine_name,
'bundle' => 'article',
'widget' => array(
'type' => 'options_select',
),
'display' => array(
'full' => array(
'type' => 'taxonomy_term_link',
),
),
);
field_create_instance($this->instance);
}
/**
@ -422,7 +367,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
// Edit $term2, setting $term1 as parent.
$edit = array();
$edit['parent[]'] = $term1->tid;
$edit['parent'] = $term1->tid;
$this->drupalPost('taxonomy/term/' . $term2->tid . '/edit', $edit, t('Save'));
// Check the hierarchy.
@ -454,7 +399,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
$edit['title'] = $this->randomName();
$langcode = FIELD_LANGUAGE_NONE;
$edit["body[$langcode][0][value]"] = $this->randomName();
$edit['taxonomy[' . $this->vocabulary->vid . ']'] = $term1->tid;
$edit[$this->instance['field_name'] . '[' . $langcode .'][value][]'] = $term1->tid;
$this->drupalPost('node/add/article', $edit, t('Save'));
// Check that the term is displayed when the node is viewed.
@ -463,19 +408,11 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
$this->assertText($term1->name, t('Term is displayed when viewing the node.'));
// Edit the node with a different term.
$edit['taxonomy[' . $this->vocabulary->vid . ']'] = $term2->tid;
$edit[$this->instance['field_name'] . '[' . $langcode . '][value][]'] = $term2->tid;
$this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
$this->drupalGet('node/' . $node->nid);
$this->assertText($term2->name, t('Term is displayed when viewing the node.'));
// Delete node through browser.
$this->drupalPost('node/' . $node->nid . '/delete', array(), t('Delete'));
$this->drupalGet('node/' . $node->nid);
$this->assertNoText($term2->name, t('Checking if node exists'));
// Checking database fields.
$result = db_query('SELECT * FROM {taxonomy_term_node} WHERE nid = :nid', array(':nid' => $node->nid))->fetch();
$this->assertTrue(empty($result), t('Term/node relationships are no longer in the database table.'));
}
/**
@ -483,22 +420,25 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
*/
function testNodeTermCreation() {
// Enable tags in the vocabulary.
$this->vocabulary->tags = 1;
taxonomy_vocabulary_save($this->vocabulary);
$instance = $this->instance;
$instance['widget'] = array('type' => 'taxonomy_autocomplete');
$instance['bundle'] = 'page';
field_create_instance($instance);
$terms = array(
$this->randomName(),
$this->randomName(),
$this->randomName(),
);
$edit = array();
$edit['title'] = $this->randomName();
// Insert the terms in a comma separated list. Vocabulary 1 is a
// free-tagging field created by the default profile.
$edit['taxonomy[tags][' . $this->vocabulary->vid . ']'] = implode(', ', $terms);
$langcode = FIELD_LANGUAGE_NONE;
$edit["body[$langcode][0][value]"] = $this->randomName();
$this->drupalPost('node/add/article', $edit, t('Save'));
$this->assertRaw(t('@type %title has been created.', array('@type' => t('Article'), '%title' => $edit['title'])), t('The node was created successfully'));
// Insert the terms in a comma separated list. Vocabulary 1 is a
// free-tagging field created by the default profile.
$edit[$instance['field_name'] . "[$langcode][value]"] = implode(', ', $terms);
$this->drupalPost('node/add/page', $edit, t('Save'));
$this->assertRaw(t('@type %title has been created.', array('@type' => t('Page'), '%title' => $edit['title'])), t('The node was created successfully'));
foreach ($terms as $term) {
$this->assertText($term, t('The term was saved and appears on the node page'));
}
@ -514,7 +454,7 @@ class TaxonomyTermTestCase extends TaxonomyWebTestCase {
);
// Explicitly set the parents field to 'root', to ensure that
// taxonomy_form_term_submit() handles the invalid term ID correctly.
$edit['parent[]'] = 0;
$edit['parent'] = 0;
// Create the term to edit.
$this->drupalPost('admin/structure/taxonomy/' . $this->vocabulary->vid . '/list/add', $edit, t('Save'));

View File

@ -175,20 +175,26 @@ function default_install() {
variable_set('theme_settings', $theme_settings);
// Create a default vocabulary named "Tags", enabled for the 'article' content type.
$vocabulary = new stdClass;
$vocabulary->name = 'Tags';
$vocabulary->description = st('Use tags to group articles on similar topics into categories.');
$vocabulary->machine_name = 'tags';
$vocabulary->help = st('Enter a comma-separated list of words to describe your content.');
$vocabulary->relations = 0;
$vocabulary->hierarchy = 0;
$vocabulary->multiple = 0;
$vocabulary->required = 0;
$vocabulary->tags = 1;
$vocabulary->module = 'taxonomy';
$vocabulary->weight = 0;
$vocabulary->nodes = array('article' => 'article');
$description = st('Use tags to group articles on similar topics into categories.');
$help = st('Enter a comma-separated list of words to describe your content.');
$vocabulary = (object) array(
'name' => 'Tags',
'description' => $description,
'machine_name' => 'tags',
'help' => $help,
'weight' => 0,
);
taxonomy_vocabulary_save($vocabulary);
$instance = array(
'field_name' => 'taxonomy_' . $vocabulary->machine_name,
'label' => $vocabulary->name,
'bundle' => 'article',
'description' => $vocabulary->help,
'widget' => array(
'type' => 'taxonomy_autocomplete',
),
);
field_create_instance($instance);
// Enable default permissions for system roles.
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content', 'use text format 1'));