diff --git a/modules/block/block.module b/modules/block/block.module index 6227927cd73..0361a8b474d 100644 --- a/modules/block/block.module +++ b/modules/block/block.module @@ -855,3 +855,14 @@ function template_preprocess_block(&$variables) { $variables['template_files'][] = 'block-' . $variables['block']->module; $variables['template_files'][] = 'block-' . $variables['block']->module . '-' . $variables['block']->delta; } + +/** + * Implement hook_filter_format_delete(). + */ +function block_filter_format_delete($format, $default) { + db_update('box') + ->fields(array('format' => $default->format)) + ->condition('format', $format->format) + ->execute(); +} + diff --git a/modules/comment/comment.module b/modules/comment/comment.module index d63fd3c2911..afdc87d624e 100644 --- a/modules/comment/comment.module +++ b/modules/comment/comment.module @@ -2442,3 +2442,14 @@ function comment_menu_alter(&$items) { // Add comments to the description for admin/content. $items['admin/content']['description'] = "View, edit, and delete your site's content and comments."; } + +/** + * Implement hook_filter_format_delete(). + */ +function comment_filter_format_delete($format, $default) { + db_update('comment') + ->fields(array('format' => $default->format)) + ->condition('format', $format->format) + ->execute(); +} + diff --git a/modules/filter/filter.admin.inc b/modules/filter/filter.admin.inc index ad6570c1356..0d7b6de86a8 100644 --- a/modules/filter/filter.admin.inc +++ b/modules/filter/filter.admin.inc @@ -225,16 +225,18 @@ function filter_admin_format_form_submit($form, &$form_state) { * @ingroup forms * @see filter_admin_delete_submit() */ -function filter_admin_delete() { - $format = arg(4); - $format = db_query('SELECT * FROM {filter_format} WHERE format = :format', array(':format' => $format))->fetchObject(); - +function filter_admin_delete(&$form_state, $format) { if ($format) { if ($format->format != variable_get('filter_default_format', 1)) { - $form['format'] = array('#type' => 'hidden', '#value' => $format->format); - $form['name'] = array('#type' => 'hidden', '#value' => $format->name); + $form['#format'] = $format; - return confirm_form($form, t('Are you sure you want to delete the text format %format?', array('%format' => $format->name)), 'admin/settings/formats', t('If you have any content left in this text format, it will be switched to the default text format. This action cannot be undone.'), t('Delete'), t('Cancel')); + return confirm_form($form, + t('Are you sure you want to delete the text format %format?', array('%format' => $format->name)), + 'admin/settings/formats', + t('If you have any content left in this text format, it will be switched to the default text format. This action cannot be undone.'), + t('Delete'), + t('Cancel') + ); } else { drupal_set_message(t('The default format cannot be deleted.')); @@ -250,11 +252,11 @@ function filter_admin_delete() { * Process filter delete form submission. */ function filter_admin_delete_submit($form, &$form_state) { - filter_format_delete($form_state['values']['format']); - drupal_set_message(t('Deleted text format %format.', array('%format' => $form_state['values']['name']))); + $format = $form['#format']; + filter_format_delete($format); + drupal_set_message(t('Deleted text format %format.', array('%format' => $format->name))); $form_state['redirect'] = 'admin/settings/formats'; - return; } diff --git a/modules/filter/filter.api.php b/modules/filter/filter.api.php index f78824212b4..fea6178b0a4 100644 --- a/modules/filter/filter.api.php +++ b/modules/filter/filter.api.php @@ -117,6 +117,59 @@ function hook_filter_info_alter(&$info) { $info['php_code']['process callback'] = 'my_module_php_evaluator'; } +/** + * Perform actions when a new text format has been created. + * + * @param $format + * The format object of the format being updated. + * + * @see hook_filter_format_update(). + * @see hook_filter_format_delete(). + */ +function hook_filter_format_insert($format) { + mymodule_cache_rebuild(); +} + +/** + * Perform actions when a text format has been updated. + * + * This hook allows modules to act when a text format has been updated in any + * way. For example, when filters have been reconfigured, disabled, or + * re-arranged in the text format. + * + * @param $format + * The format object of the format being updated. + * + * @see hook_filter_format_insert(). + * @see hook_filter_format_delete(). + */ +function hook_filter_format_update($format) { + mymodule_cache_rebuild(); +} + +/** + * Perform actions when a text format has been deleted. + * + * It is recommended for modules to implement this hook, when they store + * references to text formats to replace existing references to the deleted + * text format with the default format. + * + * @param $format + * The format object of the format being deleted. + * @param $default + * The format object of the site's default format. + * + * @see hook_filter_format_update(). + * @see hook_filter_format_delete(). + */ +function hook_filter_format_delete($format, $default) { + // Replace the deleted format with the default format. + db_update('my_module_table') + ->fields(array('format' => $default->format)) + ->condition('format', $format->format) + ->execute(); +} + /** * @} End of "addtogroup hooks". */ diff --git a/modules/filter/filter.module b/modules/filter/filter.module index 8331c7c85ed..ccc7bb101da 100644 --- a/modules/filter/filter.module +++ b/modules/filter/filter.module @@ -90,14 +90,6 @@ function filter_menu() { 'weight' => 1, 'file' => 'filter.admin.inc', ); - $items['admin/settings/formats/delete'] = array( - 'title' => 'Delete text format', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('filter_admin_delete'), - 'access arguments' => array('administer filters'), - 'type' => MENU_CALLBACK, - 'file' => 'filter.admin.inc', - ); $items['filter/tips'] = array( 'title' => 'Compose tips', 'page callback' => 'filter_tips_long', @@ -137,6 +129,14 @@ function filter_menu() { 'weight' => 2, 'file' => 'filter.admin.inc', ); + $items['admin/settings/formats/%filter_format/delete'] = array( + 'title' => 'Delete text format', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('filter_admin_delete', 3), + 'access arguments' => array('administer filters'), + 'type' => MENU_CALLBACK, + 'file' => 'filter.admin.inc', + ); return $items; } @@ -193,6 +193,13 @@ function filter_format_save($format) { } $query->execute(); + if ($status == SAVED_NEW) { + module_invoke_all('filter_format_insert', $format); + } + else { + module_invoke_all('filter_format_update', $format); + } + cache_clear_all($format->format . ':', 'cache_filter', TRUE); return $status; @@ -206,28 +213,17 @@ function filter_format_save($format) { */ function filter_format_delete($format) { db_delete('filter_format') - ->condition('format', $format) + ->condition('format', $format->format) ->execute(); db_delete('filter') - ->condition('format', $format) + ->condition('format', $format->format) ->execute(); - $default = variable_get('filter_default_format', 1); - // Replace existing instances of the deleted format with the default format. - if (db_table_exists('comment')) { - db_update('comment') - ->fields(array('format' => $default)) - ->condition('format', $format) - ->execute(); - } - if (db_table_exists('box')) { - db_update('box') - ->fields(array('format' => $default)) - ->condition('format', $format) - ->execute(); - } + // Allow modules to react on text format deletion. + $default = filter_format_load(variable_get('filter_default_format', 1)); + module_invoke_all('filter_format_delete', $format, $default); - cache_clear_all($format . ':', 'cache_filter', TRUE); + cache_clear_all($format->format . ':', 'cache_filter', TRUE); } /** diff --git a/modules/filter/filter.test b/modules/filter/filter.test index 6a2c7ada279..2b49a32c47f 100644 --- a/modules/filter/filter.test +++ b/modules/filter/filter.test @@ -32,7 +32,7 @@ class FilterAdminTestCase extends DrupalWebTestCase { $this->drupalPost('admin/settings/formats', $edit, t('Save changes')); $this->assertText(t('Default format updated.'), t('Default filter updated successfully.')); - $this->assertNoRaw('admin/settings/formats/delete/' . $full, t('Delete link not found.')); + $this->assertNoRaw('admin/settings/formats/' . $full . '/delete', t('Delete link not found.')); // Add an additional tag. $edit = array(); @@ -79,7 +79,7 @@ class FilterAdminTestCase extends DrupalWebTestCase { $this->assertFieldByName('filters[' . $first_filter . ']', '', t('Url filter found.')); // Delete new filter. - $this->drupalPost('admin/settings/formats/delete/' . $format->format, array(), t('Delete')); + $this->drupalPost('admin/settings/formats/' . $format->format . '/delete', array(), t('Delete')); $this->assertRaw(t('Deleted text format %format.', array('%format' => $edit['name'])), t('Format successfully deleted.')); } @@ -89,7 +89,7 @@ class FilterAdminTestCase extends DrupalWebTestCase { $this->drupalPost('admin/settings/formats', $edit, t('Save changes')); $this->assertText(t('Default format updated.'), t('Default filter updated successfully.')); - $this->assertNoRaw('admin/settings/formats/delete/' . $filtered, t('Delete link not found.')); + $this->assertNoRaw('admin/settings/formats/' . $filtered . '/delete', t('Delete link not found.')); // Allow authenticated users on full HTML. $edit = array(); @@ -694,7 +694,7 @@ class FilterUnitTest extends DrupalWebTestCase { function deleteFormat($format) { if ($format !== NULL) { - $this->drupalPost('admin/settings/formats/delete/' . $format->format, array(), t('Delete')); + $this->drupalPost('admin/settings/formats/' . $format->format . '/delete', array(), t('Delete')); } } @@ -746,3 +746,74 @@ class FilterUnitTest extends DrupalWebTestCase { return $this->assertTrue(strpos(strtolower(decode_entities($haystack)), $needle) === FALSE, $message, $group); } } + +/** + * Tests for filter hook invocation. + */ +class FilterHooksTestCase extends DrupalWebTestCase { + function getInfo() { + return array( + 'name' => 'Filter format hooks', + 'description' => 'Test hooks for text formats insert/update/delete.', + 'group' => 'Filter', + ); + } + + function setUp() { + parent::setUp('block', 'filter_test'); + $admin_user = $this->drupalCreateUser(array('administer filters', 'administer blocks')); + $this->drupalLogin($admin_user); + } + + /** + * Test that hooks run correctly on creating, editing, and deleting a text format. + */ + function testFilterHooks() { + // Add a text format. + $name = $this->randomName(); + $edit = array(); + $edit['name'] = $name; + $edit['roles[1]'] = 1; + $this->drupalPost('admin/settings/formats/add', $edit, t('Save configuration')); + $this->assertRaw(t('Added text format %format.', array('%format' => $name)), t('New format created.')); + $this->assertText(t('hook_filter_format_insert invoked.'), t('hook_filter_format_insert invoked.')); + + $format = db_query("SELECT format FROM {filter_format} WHERE name = :name", array(':name' => $name))->fetchField(); + + // Update text format. + $edit = array(); + $edit['roles[2]'] = 1; + $this->drupalPost('admin/settings/formats/' . $format, $edit, t('Save configuration')); + $this->assertRaw(t('The text format settings have been updated.'), t('Full HTML format successfully updated.')); + $this->assertText(t('hook_filter_format_update invoked.'), t('hook_filter_format_update() was invoked.')); + + // Add a new custom block. + $box = array(); + $box['info'] = $this->randomName(8); + $box['title'] = $this->randomName(8); + $box['body'] = $this->randomName(32); + // Use the format created. + $box['body_format'] = $format; + $this->drupalPost('admin/structure/block/add', $box, t('Save block')); + $this->assertText(t('The block has been created.'), t('New block successfully created.')); + + // Verify the new block is in the database. + $bid = db_query("SELECT bid FROM {box} WHERE info = :info", array(':info' => $box['info']))->fetchField(); + $this->assertNotNull($bid, t('New block found in database')); + + // Delete the text format. + $this->drupalPost('admin/settings/formats/' . $format . '/delete', array(), t('Delete')); + $this->assertRaw(t('Deleted text format %format.', array('%format' => $name)), t('Format successfully deleted.')); + $this->assertText(t('hook_filter_format_delete invoked.'), t('hook_filter_format_delete() was invoked.')); + + // Verify that the deleted format was replaced with the default format. + $current_format = db_select('box', 'b') + ->fields('b', array('format')) + ->condition('bid', $bid) + ->execute() + ->fetchField(); + $default = variable_get('filter_default_format', 1); + $this->assertEqual($current_format, $default, t('Deleted text format replaced with the default format.')); + } +} + diff --git a/modules/simpletest/tests/filter_test.info b/modules/simpletest/tests/filter_test.info new file mode 100644 index 00000000000..b379267495a --- /dev/null +++ b/modules/simpletest/tests/filter_test.info @@ -0,0 +1,8 @@ +; $Id$ +name = Filter test module +description = Tests filter hooks and functions. +package = Testing +version = VERSION +core = 7.x +files[] = filter_test.module +hidden = TRUE diff --git a/modules/simpletest/tests/filter_test.module b/modules/simpletest/tests/filter_test.module new file mode 100644 index 00000000000..4adba88b9e0 --- /dev/null +++ b/modules/simpletest/tests/filter_test.module @@ -0,0 +1,29 @@ +