Commit 234b98d8 authored by Dries's avatar Dries

Merge branch '8.x' of git.drupal.org:project/drupal into 8.x

parents 4cd50477 7d712bea
...@@ -186,7 +186,7 @@ Filter module ...@@ -186,7 +186,7 @@ Filter module
- Daniel F. Kudwien 'sun' <http://drupal.org/user/54136> - Daniel F. Kudwien 'sun' <http://drupal.org/user/54136>
Forum module Forum module
- ? - Lee Rowlands 'larowlan' <http://drupal.org/user/395439>
Help module Help module
- ? - ?
......
...@@ -5041,7 +5041,15 @@ function drupal_cron_run() { ...@@ -5041,7 +5041,15 @@ function drupal_cron_run() {
drupal_register_shutdown_function('drupal_cron_cleanup'); drupal_register_shutdown_function('drupal_cron_cleanup');
// Iterate through the modules calling their cron handlers (if any): // Iterate through the modules calling their cron handlers (if any):
module_invoke_all('cron'); foreach (module_implements('cron') as $module) {
// Do not let an exception thrown by one module disturb another.
try {
module_invoke($module, 'cron');
}
catch (Exception $e) {
watchdog_exception('cron', $e);
}
}
// Record cron time // Record cron time
variable_set('cron_last', REQUEST_TIME); variable_set('cron_last', REQUEST_TIME);
......
...@@ -1539,7 +1539,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE, ...@@ -1539,7 +1539,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
// directory. This overcomes open_basedir restrictions for future file // directory. This overcomes open_basedir restrictions for future file
// operations. // operations.
$file->uri = $file->destination; $file->uri = $file->destination;
if (!move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->uri)) { if (!drupal_move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->uri)) {
form_set_error($source, t('File upload error. Could not move uploaded file.')); form_set_error($source, t('File upload error. Could not move uploaded file.'));
watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->uri)); watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->uri));
return FALSE; return FALSE;
...@@ -1566,6 +1566,42 @@ function file_save_upload($source, $validators = array(), $destination = FALSE, ...@@ -1566,6 +1566,42 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
return FALSE; return FALSE;
} }
/**
* Moves an uploaded file to a new location.
*
* PHP's move_uploaded_file() does not properly support streams if safe_mode
* or open_basedir are enabled, so this function fills that gap.
*
* Compatibility: normal paths and stream wrappers.
* @see http://drupal.org/node/515192
*
* @param $filename
* The filename of the uploaded file.
* @param $uri
* A string containing the destination URI of the file.
*
* @return
* TRUE on success, or FALSE on failure.
*
* @see move_uploaded_file()
* @ingroup php_wrappers
*/
function drupal_move_uploaded_file($filename, $uri) {
$result = @move_uploaded_file($filename, $uri);
// PHP's move_uploaded_file() does not properly support streams if safe_mode
// or open_basedir are enabled so if the move failed, try finding a real path
// and retry the move operation.
if (!$result) {
if ($realpath = drupal_realpath($uri)) {
$result = move_uploaded_file($filename, $realpath);
}
else {
$result = move_uploaded_file($filename, $uri);
}
}
return $result;
}
/** /**
* Check that a file meets the criteria specified by the validators. * Check that a file meets the criteria specified by the validators.
......
...@@ -675,10 +675,6 @@ function hook_field_is_empty($item, $field) { ...@@ -675,10 +675,6 @@ function hook_field_is_empty($item, $field) {
* Widget hooks are typically called by the Field Attach API during the * Widget hooks are typically called by the Field Attach API during the
* creation of the field form structure with field_attach_form(). * creation of the field form structure with field_attach_form().
* *
* @see hook_field_widget_info_alter()
* @see hook_field_widget_form()
* @see hook_field_widget_error()
*
* @return * @return
* An array describing the widget types implemented by the module. * An array describing the widget types implemented by the module.
* The keys are widget type names. To avoid name clashes, widget type * The keys are widget type names. To avoid name clashes, widget type
...@@ -704,6 +700,12 @@ function hook_field_is_empty($item, $field) { ...@@ -704,6 +700,12 @@ function hook_field_is_empty($item, $field) {
* - FIELD_BEHAVIOR_DEFAULT: (default) If the widget accepts default * - FIELD_BEHAVIOR_DEFAULT: (default) If the widget accepts default
* values. * values.
* - FIELD_BEHAVIOR_NONE: if the widget does not support default values. * - FIELD_BEHAVIOR_NONE: if the widget does not support default values.
*
* @see hook_field_widget_info_alter()
* @see hook_field_widget_form()
* @see hook_field_widget_form_alter()
* @see hook_field_widget_WIDGET_TYPE_form_alter()
* @see hook_field_widget_error()
*/ */
function hook_field_widget_info() { function hook_field_widget_info() {
return array( return array(
...@@ -783,8 +785,8 @@ function hook_field_widget_info_alter(&$info) { ...@@ -783,8 +785,8 @@ function hook_field_widget_info_alter(&$info) {
* properties from $field and $instance and set them as ad-hoc * properties from $field and $instance and set them as ad-hoc
* $element['#custom'] properties, for later use by its element callbacks. * $element['#custom'] properties, for later use by its element callbacks.
* *
* @see field_widget_field() * Other modules may alter the form element provided by this function using
* @see field_widget_instance() * hook_field_widget_form_alter().
* *
* @param $form * @param $form
* The form structure where widgets are being attached to. This might be a * The form structure where widgets are being attached to. This might be a
...@@ -826,6 +828,11 @@ function hook_field_widget_info_alter(&$info) { ...@@ -826,6 +828,11 @@ function hook_field_widget_info_alter(&$info) {
* *
* @return * @return
* The form elements for a single widget for this field. * The form elements for a single widget for this field.
*
* @see field_widget_field()
* @see field_widget_instance()
* @see hook_field_widget_form_alter()
* @see hook_field_widget_WIDGET_TYPE_form_alter()
*/ */
function hook_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { function hook_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$element += array( $element += array(
...@@ -835,6 +842,69 @@ function hook_field_widget_form(&$form, &$form_state, $field, $instance, $langco ...@@ -835,6 +842,69 @@ function hook_field_widget_form(&$form, &$form_state, $field, $instance, $langco
return $element; return $element;
} }
/**
* Alter forms for field widgets provided by other modules.
*
* @param $element
* The field widget form element as constructed by hook_field_widget_form().
* @param $form_state
* An associative array containing the current state of the form.
* @param $context
* An associative array containing the following key-value pairs, matching the
* arguments received by hook_field_widget_form():
* - "form": The form structure where widgets are being attached to. This
* might be a full form structure, or a sub-element of a larger form.
* - "field": The field structure.
* - "instance": The field instance structure.
* - "langcode": The language associated with $items.
* - "items": Array of default values for this field.
* - "delta": The order of this item in the array of subelements (0, 1, 2,
* etc).
*
* @see hook_field_widget_form()
* @see hook_field_widget_WIDGET_TYPE_form_alter
*/
function hook_field_widget_form_alter(&$element, &$form_state, $context) {
// Add a css class to widget form elements for all fields of type mytype.
if ($context['field']['type'] == 'mytype') {
// Be sure not to overwrite existing attributes.
$element['#attributes']['class'][] = 'myclass';
}
}
/**
* Alter widget forms for a specific widget provided by another module.
*
* Modules can implement hook_field_widget_WIDGET_TYPE_form_alter() to modify a
* specific widget form, rather than using hook_field_widget_form_alter() and
* checking the widget type.
*
* @param $element
* The field widget form element as constructed by hook_field_widget_form().
* @param $form_state
* An associative array containing the current state of the form.
* @param $context
* An associative array containing the following key-value pairs, matching the
* arguments received by hook_field_widget_form():
* - "form": The form structure where widgets are being attached to. This
* might be a full form structure, or a sub-element of a larger form.
* - "field": The field structure.
* - "instance": The field instance structure.
* - "langcode": The language associated with $items.
* - "items": Array of default values for this field.
* - "delta": The order of this item in the array of subelements (0, 1, 2,
* etc).
*
* @see hook_field_widget_form()
* @see hook_field_widget_form_alter()
*/
function hook_field_widget_WIDGET_TYPE_form_alter(&$element, &$form_state, $context) {
// Code here will only act on widgets of type WIDGET_TYPE. For example,
// hook_field_widget_mymodule_autocomplete_form_alter() will only act on
// widgets of type 'mymodule_autocomplete'.
$element['#autocomplete_path'] = 'mymodule/autocomplete_path';
}
/** /**
* Flag a field-level validation error. * Flag a field-level validation error.
* *
......
...@@ -76,6 +76,17 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode, ...@@ -76,6 +76,17 @@ function field_default_form($entity_type, $entity, $field, $instance, $langcode,
'#delta' => $delta, '#delta' => $delta,
); );
if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) { if ($element = $function($form, $form_state, $field, $instance, $langcode, $items, $delta, $element)) {
// Allow modules to alter the field widget form element.
$context = array(
'form' => $form,
'field' => $field,
'instance' => $instance,
'langcode' => $langcode,
'items' => $items,
'delta' => $delta,
);
drupal_alter(array('field_widget_form', 'field_widget_' . $instance['widget']['type'] . '_form'), $element, $form_state, $context);
// If we're processing a specific delta value for a field where the // If we're processing a specific delta value for a field where the
// field module handles multiples, set the delta in the result. // field module handles multiples, set the delta in the result.
// For fields that handle their own processing, we can't make // For fields that handle their own processing, we can't make
...@@ -193,6 +204,18 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form, ...@@ -193,6 +204,18 @@ function field_multiple_value_form($field, $instance, $langcode, $items, &$form,
'#weight' => 100, '#weight' => 100,
); );
} }
// Allow modules to alter the field widget form element.
$context = array(
'form' => $form,
'field' => $field,
'instance' => $instance,
'langcode' => $langcode,
'items' => $items,
'delta' => $delta,
);
drupal_alter(array('field_widget_form', 'field_widget_' . $instance['widget']['type'] . '_form'), $element, $form_state, $context);
$field_elements[$delta] = $element; $field_elements[$delta] = $element;
} }
} }
......
...@@ -305,13 +305,6 @@ class FieldException extends Exception {} ...@@ -305,13 +305,6 @@ class FieldException extends Exception {}
*/ */
class FieldUpdateForbiddenException extends FieldException {} class FieldUpdateForbiddenException extends FieldException {}
/**
* Implements hook_flush_caches().
*/
function field_flush_caches() {
return array('cache_field');
}
/** /**
* Implements hook_help(). * Implements hook_help().
*/ */
...@@ -370,6 +363,7 @@ function field_theme() { ...@@ -370,6 +363,7 @@ function field_theme() {
* Purges some deleted Field API data, if any exists. * Purges some deleted Field API data, if any exists.
*/ */
function field_cron() { function field_cron() {
field_sync_field_status();
$limit = variable_get('field_purge_batch_size', 10); $limit = variable_get('field_purge_batch_size', 10);
field_purge_batch($limit); field_purge_batch($limit);
} }
...@@ -386,45 +380,84 @@ function field_modules_uninstalled($modules) { ...@@ -386,45 +380,84 @@ function field_modules_uninstalled($modules) {
} }
/** /**
* Implements hook_modules_enabled(). * Implements hook_system_info_alter().
*
* Goes through a list of all modules that provide a field type, and makes them
* required if there are any active fields of that type.
*/ */
function field_modules_enabled($modules) { function field_system_info_alter(&$info, $file, $type) {
foreach ($modules as $module) { if ($type == 'module' && module_hook($file->name, 'field_info')) {
field_associate_fields($module); $fields = field_read_fields(array('module' => $file->name), array('include_deleted' => TRUE));
if ($fields) {
$info['required'] = TRUE;
// Provide an explanation message (only mention pending deletions if there
// remains no actual, non-deleted fields)
$non_deleted = FALSE;
foreach ($fields as $field) {
if (empty($field['deleted'])) {
$non_deleted = TRUE;
break;
}
}
if ($non_deleted) {
if (module_exists('field_ui')) {
$explanation = t('Field type(s) in use - see !link', array('!link' => l(t('Field list'), 'admin/reports/fields')));
}
else {
$explanation = t('Fields type(s) in use');
}
}
else {
$explanation = t('Fields pending deletion');
}
$info['explanation'] = $explanation;
}
} }
field_cache_clear();
} }
/** /**
* Implements hook_modules_disabled(). * Implements hook_flush_caches().
*/
function field_flush_caches() {
field_sync_field_status();
return array('cache_field');
}
/**
* Refreshes the 'active' and 'storage_active' columns for fields.
*/ */
function field_modules_disabled($modules) { function field_sync_field_status() {
// Track fields whose field type is being disabled. // Refresh the 'active' and 'storage_active' columns according to the current
// set of enabled modules.
$all_modules = system_rebuild_module_data();
$modules = array();
foreach ($all_modules as $module_name => $module) {
if ($module->status) {
$modules[] = $module_name;
field_associate_fields($module_name);
}
}
db_update('field_config') db_update('field_config')
->fields(array('active' => 0)) ->fields(array('active' => 0))
->condition('module', $modules, 'IN') ->condition('module', $modules, 'NOT IN')
->execute(); ->execute();
// Track fields whose storage backend is being disabled.
db_update('field_config') db_update('field_config')
->fields(array('storage_active' => 0)) ->fields(array('storage_active' => 0))
->condition('storage_module', $modules, 'IN') ->condition('storage_module', $modules, 'NOT IN')
->execute(); ->execute();
field_cache_clear();
} }
/** /**
* Allows a module to update the database for fields and columns it controls. * Allows a module to update the database for fields and columns it controls.
* *
* @param string $module * @param $module
* The name of the module to update on. * The name of the module to update on.
*/ */
function field_associate_fields($module) { function field_associate_fields($module) {
// Associate field types. // Associate field types.
$field_types =(array) module_invoke($module, 'field_info'); $field_types = (array) module_invoke($module, 'field_info');
foreach ($field_types as $name => $field_info) { foreach ($field_types as $name => $field_info) {
watchdog('field', 'Updating field type %type with module %module.', array('%type' => $name, '%module' => $module));
db_update('field_config') db_update('field_config')
->fields(array('module' => $module, 'active' => 1)) ->fields(array('module' => $module, 'active' => 1))
->condition('type', $name) ->condition('type', $name)
...@@ -433,7 +466,6 @@ function field_associate_fields($module) { ...@@ -433,7 +466,6 @@ function field_associate_fields($module) {
// Associate storage backends. // Associate storage backends.
$storage_types = (array) module_invoke($module, 'field_storage_info'); $storage_types = (array) module_invoke($module, 'field_storage_info');
foreach ($storage_types as $name => $storage_info) { foreach ($storage_types as $name => $storage_info) {
watchdog('field', 'Updating field storage %type with module %module.', array('%type' => $name, '%module' => $module));
db_update('field_config') db_update('field_config')
->fields(array('storage_module' => $module, 'storage_active' => 1)) ->fields(array('storage_module' => $module, 'storage_active' => 1))
->condition('storage_type', $name) ->condition('storage_type', $name)
......
...@@ -2356,6 +2356,7 @@ class FieldCrudTestCase extends FieldTestCase { ...@@ -2356,6 +2356,7 @@ class FieldCrudTestCase extends FieldTestCase {
$this->assertTrue($field_definition <= $field, t('The field was properly read.')); $this->assertTrue($field_definition <= $field, t('The field was properly read.'));
module_disable($modules, FALSE); module_disable($modules, FALSE);
drupal_flush_all_caches();
$fields = field_read_fields(array('field_name' => $field_name), array('include_inactive' => TRUE)); $fields = field_read_fields(array('field_name' => $field_name), array('include_inactive' => TRUE));
$this->assertTrue(isset($fields[$field_name]) && $field_definition < $field, t('The field is properly read when explicitly fetching inactive fields.')); $this->assertTrue(isset($fields[$field_name]) && $field_definition < $field, t('The field is properly read when explicitly fetching inactive fields.'));
...@@ -2368,6 +2369,7 @@ class FieldCrudTestCase extends FieldTestCase { ...@@ -2368,6 +2369,7 @@ class FieldCrudTestCase extends FieldTestCase {
$module = array_shift($modules); $module = array_shift($modules);
module_enable(array($module), FALSE); module_enable(array($module), FALSE);
drupal_flush_all_caches();
} }
// Check that the field is active again after all modules have been // Check that the field is active again after all modules have been
......
...@@ -12,17 +12,27 @@ function field_ui_fields_list() { ...@@ -12,17 +12,27 @@ function field_ui_fields_list() {
$instances = field_info_instances(); $instances = field_info_instances();
$field_types = field_info_field_types(); $field_types = field_info_field_types();
$bundles = field_info_bundles(); $bundles = field_info_bundles();
$modules = system_rebuild_module_data();
$header = array(t('Field name'), t('Field type'), t('Used in')); $header = array(t('Field name'), t('Field type'), t('Used in'));
$rows = array(); $rows = array();
foreach ($instances as $entity_type => $type_bundles) { foreach ($instances as $entity_type => $type_bundles) {
foreach ($type_bundles as $bundle => $bundle_instances) { foreach ($type_bundles as $bundle => $bundle_instances) {
foreach ($bundle_instances as $field_name => $instance) { foreach ($bundle_instances as $field_name => $instance) {
$field = field_info_field($field_name); $field = field_info_field($field_name);
// Initialize the row if we encounter the field for the first time.
if (!isset($rows[$field_name])) {
$rows[$field_name]['class'] = $field['locked'] ? array('menu-disabled') : array('');
$rows[$field_name]['data'][0] = $field['locked'] ? t('@field_name (Locked)', array('@field_name' => $field_name)) : $field_name;
$module_name = $field_types[$field['type']]['module'];
$rows[$field_name]['data'][1] = $field_types[$field['type']]['label'] . ' ' . t('(module: !module)', array('!module' => $modules[$module_name]->info['name']));
}
// Add the current instance.
$admin_path = _field_ui_bundle_admin_path($entity_type, $bundle); $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
$rows[$field_name]['data'][0] = $field['locked'] ? t('@field_name (Locked)', array('@field_name' => $field_name)) : $field_name;
$rows[$field_name]['data'][1] = $field_types[$field['type']]['label'];
$rows[$field_name]['data'][2][] = $admin_path ? l($bundles[$entity_type][$bundle]['label'], $admin_path . '/fields') : $bundles[$entity_type][$bundle]['label']; $rows[$field_name]['data'][2][] = $admin_path ? l($bundles[$entity_type][$bundle]['label'], $admin_path . '/fields') : $bundles[$entity_type][$bundle]['label'];
$rows[$field_name]['class'] = $field['locked'] ? array('menu-disabled') : array('');
} }
} }
} }
...@@ -1717,6 +1727,14 @@ function field_ui_field_delete_form_submit($form, &$form_state) { ...@@ -1717,6 +1727,14 @@ function field_ui_field_delete_form_submit($form, &$form_state) {
$admin_path = _field_ui_bundle_admin_path($entity_type, $bundle); $admin_path = _field_ui_bundle_admin_path($entity_type, $bundle);
$form_state['redirect'] = field_ui_get_destinations(array($admin_path . '/fields')); $form_state['redirect'] = field_ui_get_destinations(array($admin_path . '/fields'));
// Fields are purged on cron. However field module prevents disabling modules
// when field types they provided are used in a field until it is fully
// purged. In the case that a field has minimal or no content, a single call
// to field_purge_batch() will remove it from the system. Call this with a
// low batch limit to avoid administrators having to wait for cron runs when
// removing instances that meet this criteria.
field_purge_batch(10);
} }
/** /**
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
* FALSE if the forum can contain only topics. * FALSE if the forum can contain only topics.
* - $forum->depth: How deep the forum is in the current hierarchy. * - $forum->depth: How deep the forum is in the current hierarchy.
* - $forum->zebra: 'even' or 'odd' string used for row class. * - $forum->zebra: 'even' or 'odd' string used for row class.
* - $forum->icon_class: 'default' or 'new' string used for forum icon class.
* - $forum->icon_title: Text alternative for the forum icon.
* - $forum->name: The name of the forum. * - $forum->name: The name of the forum.
* - $forum->link: The URL to link to this forum. * - $forum->link: The URL to link to this forum.
* - $forum->description: The description of this forum. * - $forum->description: The description of this forum.
...@@ -48,6 +50,9 @@ ...@@ -48,6 +50,9 @@
* left-margin for indenting. * left-margin for indenting.
*/ ?> */ ?>
<?php print str_repeat('<div class="indent">', $forum->depth); ?> <?php print str_repeat('<div class="indent">', $forum->depth); ?>
<div class="icon forum-status-<?php print $forum->icon_class; ?>" title="<?php print $forum->icon_title; ?>">
<span class="element-invisible"><?php print $forum->icon_title; ?></span>
</div>
<div class="name"><a href="<?php print $forum->link; ?>"><?php print $forum->name; ?></a></div> <div class="name"><a href="<?php print $forum->link; ?>"><?php print $forum->name; ?></a></div>
<?php if ($forum->description): ?> <?php if ($forum->description): ?>
<div class="description"><?php print $forum->description; ?></div> <div class="description"><?php print $forum->description; ?></div>
......
#forum tr td.forum { #forum td.forum .icon {
padding-left: 0.5em; float: right;
padding-right: 25px; margin: 0 0 0 9px;
background-position: 98% 2px;
} }
.forum-topic-navigation { .forum-topic-navigation {
padding: 1em 3em 0 0; padding: 1em 3em 0 0;
......
...@@ -11,15 +11,19 @@ ...@@ -11,15 +11,19 @@
#forum td.pager { #forum td.pager {
white-space: nowrap; white-space: nowrap;
} }
#forum tr td.forum {
padding-left: 25px; /* LTR */ #forum td.forum .icon {
background-position: 2px 2px; /* LTR */ background-image: url(../../misc/forum-icons.png);
background-image: url(../../misc/forum-default.png);
background-repeat: no-repeat; background-repeat: no-repeat;
float: left; /* LTR */
height: 24px;
margin: 0 9px 0 0; /* LTR */
width: 24px;
} }
#forum tr.new-topics td.forum { #forum td.forum .forum-status-new {
background-image: url(../../misc/forum-new.png); background-position: -24px 0;
} }
#forum div.indent { #forum div.indent {
margin-left: 20px; margin-left: 20px;
} }
......
...@@ -113,6 +113,11 @@ function forum_uninstall() { ...@@ -113,6 +113,11 @@ function forum_uninstall() {
variable_del('forum_block_num_active'); variable_del('forum_block_num_active');
variable_del('forum_block_num_new'); variable_del('forum_block_num_new');
variable_del('node_options_forum'); variable_del('node_options_forum');
field_delete_field('taxonomy_forums');
// Purge field data now to allow taxonomy module to be uninstalled
// if this is the only field remaining.
field_purge_batch(10);
} }
/** /**
......
...@@ -1064,11 +1064,15 @@ function template_preprocess_forum_list(&$variables) { ...@@ -1064,11 +1064,15 @@ function template_preprocess_forum_list(&$variables) {
$variables['forums'][$id]->new_url = ''; $variables['forums'][$id]->new_url = '';
$variables['forums'][$id]->new_topics = 0; $variables['forums'][$id]->new_topics = 0;
$variables['forums'][$id]->old_topics = $forum->num_topics; $variables['forums'][$id]->old_topics = $forum->num_topics;
$variables['forums'][$id]->icon_class = 'default';
$variables['forums'][$id]->icon_title = t('No new posts');
if ($user->uid) { if ($user->uid) {
$variables['forums'][$id]->new_topics = _forum_topics_unread($forum->tid, $user->uid); $variables['forums'][$id]->new_topics = _forum_topics_unread($forum->tid, $user->uid);
if ($variables['forums'][$id]->new_topics) { if ($variables['forums'][$id]->new_topics) {
$variables['forums'][$id]->new_text = format_plural($variables['forums'][$id]->new_topics, '1 new', '@count new'); $variables['forums'][$id]->new_text = format_plural($variables['forums'][$id]->new_topics, '1 new', '@count new');
$variables['forums'][$id]->new_url = url("forum/$forum->tid", array('fragment' => 'new')); $variables['forums'][$id]->new_url = url("forum/$forum->tid", array('fragment' => 'new'));
$variables['forums'][$id]->icon_class = 'new';
$variables['forums'][$id]->icon_title = t('New posts');
} }
$variables['forums'][$id]->old_topics = $forum->num_topics - $variables['forums'][$id]->new_topics; $variables['forums'][$id]->old_topics = $forum->num_topics - $variables['forums'][$id]->new_topics;
} }
......
...@@ -31,6 +31,7 @@ class ForumTestCase extends DrupalWebTestCase { ...@@ -31,6 +31,7 @@ class ForumTestCase extends DrupalWebTestCase {
// Create users. // Create users.
$this->admin_user = $this->drupalCreateUser(array( $this->admin_user = $this->drupalCreateUser(array(
'access administration pages', 'access administration pages',
'administer modules',
'administer blocks', 'administer blocks',
'administer forums', 'administer forums',
'administer menu', 'administer menu',
...@@ -51,6 +52,30 @@ class ForumTestCase extends DrupalWebTestCase { ...@@ -51,6 +52,30 @@ class ForumTestCase extends DrupalWebTestCase {
$this->web_user = $this->drupalCreateUser(array()); $this->web_user = $this->drupalCreateUser(array());
} }
/**
* Tests disabling and re-enabling forum.
*/
function testEnableForumField() {
$this->drupalLogin($this->admin_user);
// Disable the forum module.
$edit = array();
$edit['modules[Core][forum][enable]'] = FALSE;
$this->drupalPost('admin/modules', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
module_list(TRUE);
$this->assertFalse(module_exists('forum'), t('Forum module is not enabled.'));
// Attempt to re-enable the forum module and ensure it does not try to
// recreate the taxonomy_forums field.
$edit = array();
$edit['modules[Core][forum][enable]'] = 'forum';
$this->drupalPost('admin/modules', $edit, t('Save configuration'));
$this->assertText(t('The configuration options have been saved.'), t('Modules status has been updated.'));
module_list(TRUE);
$this->assertTrue(module_exists('forum'), t('Forum module is enabled.'));
}
/** /**
* Login users, create forum nodes, and test forum functionality through the admin and user interfaces. * Login users, create forum nodes, and test forum functionality through the admin and user interfaces.
*/ */
......
...@@ -594,6 +594,10 @@ function poll_update($node) { ...@@ -594,6 +594,10 @@ function poll_update($node) {
->condition('nid', $node->nid) ->condition('nid', $node->nid)
->condition('chid', $key) ->condition('chid', $key)
->execute(); ->execute();
db_delete('poll_choice')
->condition('nid', $node->nid)
->condition('chid', $choice['chid'])
->execute();
} }
} }
} }
......
...@@ -746,3 +746,39 @@ class PollExpirationTestCase extends PollTestCase { ...@@ -746,3 +746,39 @@ class PollExpirationTestCase extends PollTestCase {
$this->assertTrue(isset($elements[0]) && !empty($elements[0]['checked']), t('Poll has expired.')); $this->assertTrue(isset($elements[0]) && !empty($elements[0]['checked']), t('Poll has expired.'));
} }
} }