diff --git a/core/modules/block/block.install b/core/modules/block/block.install
index 56b91c3..6687838 100644
--- a/core/modules/block/block.install
+++ b/core/modules/block/block.install
@@ -163,7 +163,7 @@ function block_schema() {
         'type' => 'varchar',
         'length' => 255,
         'not null' => FALSE,
-        'description' => 'The {filter_format}.format of the block body.',
+        'description' => 'The format id of the block body.',
       ),
     ),
     'unique keys' => array(
diff --git a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php
index b09f2d4..bb2aacb 100644
--- a/core/modules/block/lib/Drupal/block/Tests/BlockTest.php
+++ b/core/modules/block/lib/Drupal/block/Tests/BlockTest.php
@@ -36,12 +36,12 @@ function setUp() {
     config('system.site')->set('page.front', 'test-page')->save();
 
     // Create Full HTML text format.
-    $full_html_format = array(
+    $full_html_format_config = array(
       'format' => 'full_html',
       'name' => 'Full HTML',
     );
-    $full_html_format = (object) $full_html_format;
-    filter_format_save($full_html_format);
+    $full_html_format = entity_create('filter_format', $full_html_format_config);
+    $full_html_format->save();
     $this->checkPermissions(array(), TRUE);
 
     // Create and log in an administrative user having access to the Full HTML
diff --git a/core/modules/filter/config/filter.format.plain_text.yml b/core/modules/filter/config/filter.format.plain_text.yml
new file mode 100644
index 0000000..ceff5d2
--- /dev/null
+++ b/core/modules/filter/config/filter.format.plain_text.yml
@@ -0,0 +1,13 @@
+format: plain_text
+name: Plain text
+weight: 10
+filters:
+  filter_html_escape:
+    weight: 0
+    status: 1
+  filter_url:
+    weight: 1
+    status: 1
+  filter_autop:
+    weight: 2
+    status: 1
diff --git a/core/modules/filter/filter.admin.inc b/core/modules/filter/filter.admin.inc
index 4f56856..1d0864e 100644
--- a/core/modules/filter/filter.admin.inc
+++ b/core/modules/filter/filter.admin.inc
@@ -61,13 +61,12 @@ function filter_admin_overview($form) {
  * Form submission handler for filter_admin_overview().
  */
 function filter_admin_overview_submit($form, &$form_state) {
+  $filter_formats = filter_formats();
   foreach ($form_state['values']['formats'] as $id => $data) {
     if (is_array($data) && isset($data['weight'])) {
       // Only update if this is a form element with weight.
-      db_update('filter_format')
-        ->fields(array('weight' => $data['weight']))
-        ->condition('format', $id)
-        ->execute();
+      $filter_formats[$id]->weight = $data['weight'];
+      $filter_formats[$id]->save();
     }
   }
   filter_formats_reset();
@@ -133,10 +132,8 @@ function theme_filter_admin_overview($variables) {
 function filter_admin_format_page($format = NULL) {
   if (!isset($format->name)) {
     drupal_set_title(t('Add text format'));
-    $format = (object) array(
-      'format' => NULL,
-      'name' => '',
-    );
+
+    $format = entity_create('filter_format', array());
   }
   return drupal_get_form('filter_admin_format_form', $format);
 }
@@ -345,9 +342,12 @@ function filter_admin_format_form_validate($form, &$form_state) {
   form_set_value($form['format'], $format_format, $form_state);
   form_set_value($form['name'], $format_name, $form_state);
 
-  $result = db_query("SELECT format FROM {filter_format} WHERE name = :name AND format <> :format", array(':name' => $format_name, ':format' => $format_format))->fetchField();
-  if ($result) {
-    form_set_error('name', t('Text format names must be unique. A format named %name already exists.', array('%name' => $format_name)));
+  $filter_formats = entity_load_multiple('filter_format');
+  foreach ($filter_formats as $format) {
+    if ($format->name == $format_name && $format->format != $format_format) {
+      form_set_error('name', t('Text format names must be unique. A format named %name already exists.', array('%name' => $format_name)));
+      break;
+    }
   }
 }
 
@@ -365,7 +365,7 @@ function filter_admin_format_form_submit($form, &$form_state) {
   foreach ($form_state['values'] as $key => $value) {
     $format->$key = $value;
   }
-  $status = filter_format_save($format);
+  $status = $format-save();
 
   // Save user permissions.
   if ($permission = filter_permission_name($format)) {
diff --git a/core/modules/filter/filter.install b/core/modules/filter/filter.install
index 9237ad1..76ddc00 100644
--- a/core/modules/filter/filter.install
+++ b/core/modules/filter/filter.install
@@ -9,101 +9,6 @@
  * Implements hook_schema().
  */
 function filter_schema() {
-  $schema['filter'] = array(
-    'description' => 'Table that maps filters (HTML corrector) to text formats (Filtered HTML).',
-    'fields' => array(
-      'format' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'description' => 'Foreign key: The {filter_format}.format to which this filter is assigned.',
-      ),
-      'module' => array(
-        'type' => 'varchar',
-        'length' => 64,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'The origin module of the filter.',
-      ),
-      'name' => array(
-        'type' => 'varchar',
-        'length' => 32,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Name of the filter being referenced.',
-      ),
-      'weight' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Weight of filter within format.',
-      ),
-      'status' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Filter enabled status. (1 = enabled, 0 = disabled)',
-      ),
-      'settings' => array(
-        'type' => 'blob',
-        'not null' => FALSE,
-        'size' => 'big',
-        'serialize' => TRUE,
-        'description' => 'A serialized array of name value pairs that store the filter settings for the specific format.',
-      ),
-    ),
-    'primary key' => array('format', 'name'),
-    'indexes' => array(
-      'list' => array('weight', 'module', 'name'),
-    ),
-  );
-  $schema['filter_format'] = array(
-    'description' => 'Stores text formats: custom groupings of filters, such as Filtered HTML.',
-    'fields' => array(
-      'format' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'description' => 'Primary Key: Unique machine name of the format.',
-      ),
-      'name' => array(
-        'type' => 'varchar',
-        'length' => 255,
-        'not null' => TRUE,
-        'default' => '',
-        'description' => 'Name of the text format (Filtered HTML).',
-        'translatable' => TRUE,
-      ),
-      'cache' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'size' => 'tiny',
-        'description' => 'Flag to indicate whether format is cacheable. (1 = cacheable, 0 = not cacheable)',
-      ),
-      'status' => array(
-        'type' => 'int',
-        'unsigned' => TRUE,
-        'not null' => TRUE,
-        'default' => 1,
-        'size' => 'tiny',
-        'description' => 'The status of the text format. (1 = enabled, 0 = disabled)',
-      ),
-      'weight' => array(
-        'type' => 'int',
-        'not null' => TRUE,
-        'default' => 0,
-        'description' => 'Weight of text format to use when listing.',
-      ),
-    ),
-    'primary key' => array('format'),
-    'unique keys' => array(
-      'name' => array('name'),
-    ),
-    'indexes' => array(
-      'status_weight' => array('status', 'weight'),
-    ),
-  );
 
   $schema['cache_filter'] = drupal_get_schema_unprocessed('system', 'cache');
   $schema['cache_filter']['description'] = 'Cache table for the Filter module to store already filtered pieces of text, identified by text format and hash of the text.';
@@ -119,31 +24,57 @@ function filter_install() {
   // users have access to, so add it here. We initialize it as a simple, safe
   // plain text format with very basic formatting, but it can be modified by
   // installation profiles to have other properties.
-  $plain_text_format = array(
-    'format' => 'plain_text',
-    'name' => 'Plain text',
-    'weight' => 10,
-    'filters' => array(
-      // Escape all HTML.
-      'filter_html_escape' => array(
-        'weight' => 0,
-        'status' => 1,
-      ),
-      // URL filter.
-      'filter_url' => array(
-        'weight' => 1,
-        'status' => 1,
-      ),
-      // Line break filter.
-      'filter_autop' => array(
-        'weight' => 2,
-        'status' => 1,
-      ),
-    ),
-  );
-  $plain_text_format = (object) $plain_text_format;
-  filter_format_save($plain_text_format);
+  //
+  // See core/modules/filter/config/filter.format.plain_text.yml.
 
   // Set the fallback format to plain text.
-  variable_set('filter_fallback_format', $plain_text_format->format);
+  variable_set('filter_fallback_format', 'plain_text');
 }
+
+/**
+ * @addtogroup updates-7.x-to-8.x
+ * @{
+ */
+
+/**
+ * Migrate filter formats into configuration.
+ *
+ * @ingroup config_upgrade
+ */
+function filter_update_8000() {
+  $result = db_query('SELECT * FROM {filter_format}');
+  foreach ($result as $filter_format) {
+    // Find the settings for this format.
+    $filters = array();
+    $settings = db_query('SELECT * FROM {filter} WHERE format = :format', array(':format' => $filter_format->format));
+    foreach($settings as $setting) {
+      $filters[$setting->name] = array(
+        'weight' => $setting->weight,
+        'settings' => unserialize($setting->settings),
+        'status' => $setting->status,
+      );
+    }
+
+    // Save the config object.
+    config('filter.format.' . $filter_format->format)
+      ->set('format', $filter_format->format)
+      ->set('name', $filter_format->name)
+      ->set('status', $filter_format->status)
+      ->set('weight', $filter_format->weight)
+      ->set('filters', $filters)
+      ->save();
+  }
+}
+
+/**
+ * Drop the {filter} and {filter_format} tables.
+ */
+function filter_update_8001() {
+  db_drop_table('filter');
+  db_drop_table('filter_format');
+}
+
+/**
+ * @} End of "defgroup updates-7.x-to-8.x".
+ * The next series of updates should start at 9000.
+ */
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index b55066f..615a7a4 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -7,6 +7,7 @@
 
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Template\Attribute;
+use Drupal\filter\Plugin\Core\Entity\FilterFormat;
 
 /**
  * Non-HTML markup language filters that generate HTML.
@@ -174,6 +175,56 @@ function filter_menu() {
 }
 
 /**
+ * Implements MODULE_config_import_create().
+ */
+function filter_config_import_create($name, $new_config, $old_config) {
+  if (strpos($name, 'filter.format.') !== 0) {
+    return FALSE;
+  }
+
+  $filter_format = entity_create('filter_format', $new_config->get());
+  $filter_format->save();
+  return TRUE;
+}
+
+/**
+ * Implements MODULE_config_import_change().
+ */
+function filter_config_import_change($name, $new_config, $old_config) {
+  if (strpos($name, 'filter.format.') !== 0) {
+    return FALSE;
+  }
+
+  list(, , $id) = explode('.', $name);
+  $filter_format = entity_load('filter_format', $id);
+
+  $filter_format->original = clone $filter_format;
+  foreach ($old_config->get() as $property => $value) {
+    $filter_format->original->$property = $value;
+  }
+
+  foreach ($new_config->get() as $property => $value) {
+    $filter_format->$property = $value;
+  }
+
+  $filter_format->save();
+  return TRUE;
+}
+
+/**
+ * Implements MODULE_config_import_delete().
+ */
+function filter_config_import_delete($name, $new_config, $old_config) {
+  if (strpos($name, 'filter.format.') !== 0) {
+    return FALSE;
+  }
+
+  list(, , $id) = explode('.', $name);
+  entity_delete_multiple('filter_format', array($id));
+  return TRUE;
+}
+
+/**
  * Access callback: Checks access for disabling text formats.
  *
  * @param $format
@@ -209,116 +260,6 @@ function filter_format_load($format_id) {
 }
 
 /**
- * Saves a text format object to the database.
- *
- * @param $format
- *   A format object having the properties:
- *   - format: A machine-readable name representing the ID of the text format
- *     to save. If this corresponds to an existing text format, that format
- *     will be updated; otherwise, a new format will be created.
- *   - name: The title of the text format.
- *   - status: (optional) An integer indicating whether the text format is
- *     enabled (1) or not (0). Defaults to 1.
- *   - weight: (optional) The weight of the text format, which controls its
- *     placement in text format lists. If omitted, the weight is set to 0.
- *   - filters: (optional) An associative, multi-dimensional array of filters
- *     assigned to the text format, keyed by the name of each filter and using
- *     the properties:
- *     - weight: (optional) The weight of the filter in the text format. If
- *       omitted, either the currently stored weight is retained (if there is
- *       one), or the filter is assigned a weight of 10, which will usually
- *       put it at the bottom of the list.
- *     - status: (optional) A Boolean indicating whether the filter is
- *       enabled in the text format. If omitted, the filter will be disabled.
- *     - settings: (optional) An array of configured settings for the filter.
- *       See hook_filter_info() for details.
- *
- * @return
- *   SAVED_NEW or SAVED_UPDATED.
- */
-function filter_format_save($format) {
-  $format->name = trim($format->name);
-  $format->cache = _filter_format_is_cacheable($format);
-  if (!isset($format->status)) {
-    $format->status = 1;
-  }
-  if (!isset($format->weight)) {
-    $format->weight = 0;
-  }
-
-  // Insert or update the text format.
-  $return = db_merge('filter_format')
-    ->key(array('format' => $format->format))
-    ->fields(array(
-      'name' => $format->name,
-      'cache' => (int) $format->cache,
-      'status' => (int) $format->status,
-      'weight' => (int) $format->weight,
-    ))
-    ->execute();
-
-  // Programmatic saves may not contain any filters.
-  if (!isset($format->filters)) {
-    $format->filters = array();
-  }
-  $filter_info = filter_get_filters();
-  foreach ($filter_info as $name => $filter) {
-    // If the format does not specify an explicit weight for a filter, assign
-    // a default weight, either defined in hook_filter_info(), or the default of
-    // 0 by filter_get_filters().
-    if (!isset($format->filters[$name]['weight'])) {
-      $format->filters[$name]['weight'] = $filter['weight'];
-    }
-    $format->filters[$name]['status'] = isset($format->filters[$name]['status']) ? $format->filters[$name]['status'] : 0;
-    $format->filters[$name]['module'] = $filter['module'];
-
-    // If settings were passed, only ensure default settings.
-    if (isset($format->filters[$name]['settings'])) {
-      if (isset($filter['default settings'])) {
-        $format->filters[$name]['settings'] = array_merge($filter['default settings'], $format->filters[$name]['settings']);
-      }
-    }
-    // Otherwise, use default settings or fall back to an empty array.
-    else {
-      $format->filters[$name]['settings'] = isset($filter['default settings']) ? $filter['default settings'] : array();
-    }
-
-    $fields = array();
-    $fields['weight'] = $format->filters[$name]['weight'];
-    $fields['status'] = $format->filters[$name]['status'];
-    $fields['module'] = $format->filters[$name]['module'];
-    $fields['settings'] = serialize($format->filters[$name]['settings']);
-
-    db_merge('filter')
-      ->key(array(
-        'format' => $format->format,
-        'name' => $name,
-      ))
-      ->fields($fields)
-      ->execute();
-  }
-
-  if ($return == SAVED_NEW) {
-    module_invoke_all('filter_format_insert', $format);
-  }
-  else {
-    module_invoke_all('filter_format_update', $format);
-    // Explicitly indicate that the format was updated. We need to do this
-    // since if the filters were updated but the format object itself was not,
-    // the merge query above would not return an indication that anything had
-    // changed.
-    $return = SAVED_UPDATED;
-
-    // Clear the filter cache whenever a text format is updated.
-    cache('filter')->invalidateTags(array('filter_format' => $format->format));
-  }
-
-  filter_formats_reset();
-
-  return $return;
-}
-
-/**
  * Disables a text format.
  *
  * There is no core facility to re-enable a disabled format. It is not deleted
@@ -330,10 +271,8 @@ function filter_format_save($format) {
  *   The text format object to be disabled.
  */
 function filter_format_disable($format) {
-  db_update('filter_format')
-    ->fields(array('status' => 0))
-    ->condition('format', $format->format)
-    ->execute();
+  $format->status = 0;
+  $format-save();
 
   // Allow modules to react on text format deletion.
   module_invoke_all('filter_format_disable', $format);
@@ -357,7 +296,8 @@ function filter_format_disable($format) {
  * @see filter_format_load()
  */
 function filter_format_exists($format_id) {
-  return (bool) db_query_range('SELECT 1 FROM {filter_format} WHERE format = :format', 0, 1, array(':format' => $format_id))->fetchField();
+  $formats = entity_load_multiple('filter_format');
+  return !empty($formats[$format_id]);
 }
 
 /**
@@ -456,13 +396,14 @@ function filter_formats($account = NULL) {
       $formats['all'] = $cache->data;
     }
     else {
-      $formats['all'] = db_select('filter_format', 'ff')
-        ->addTag('translatable')
-        ->fields('ff')
-        ->condition('status', 1)
-        ->orderBy('weight')
-        ->execute()
-        ->fetchAllAssoc('format');
+      $filter_formats = entity_load_multiple('filter_format');
+      $formats['all'] = array();
+      foreach ($filter_formats as $format_name => $filter_format) {
+        if (!empty($filter_format->status)) {
+          $formats['all'][$format_name] = $filter_format;
+        }
+      }
+      @uasort($formats['all'], 'Drupal\Core\Config\Entity\ConfigEntityBase::sort');
 
       cache()->set("filter_formats:{$language_interface->langcode}", $formats['all'], CacheBackendInterface::CACHE_PERMANENT, array('filter_formats' => TRUE));
     }
@@ -691,6 +632,21 @@ function _filter_list_cmp($a, $b) {
 }
 
 /**
+ * Sorts an array of filters by filter weight, module, name.
+ *
+ * Callback for uasort() within filter_list_format().
+ */
+function _filter_format_filter_cmp($a, $b) {
+  if ($a->weight != $b->weight) {
+    return ($a->weight < $b->weight) ? -1 : 1;
+  }
+  elseif ($a->module != $b->module) {
+    return strcmp($a->module, $b->module);
+  }
+  return strcmp($a->name, $b->name);
+}
+
+/**
  * Checks if the text in a certain text format is allowed to be cached.
  *
  * This function can be used to check whether the result of the filtering
@@ -721,7 +677,7 @@ function filter_format_allowcache($format_id) {
  *   TRUE if all the filters enabled in the given text format allow caching,
  *   FALSE otherwise.
  *
- * @see filter_format_save()
+ * @see Drupal\filter\Plugin\Core\Entity\FilterFormat::save()
  */
 function _filter_format_is_cacheable($format) {
   if (empty($format->filters)) {
@@ -761,9 +717,13 @@ function filter_list_format($format_id) {
       $filters['all'] = $cache->data;
     }
     else {
-      $result = db_query('SELECT * FROM {filter} ORDER BY weight, module, name');
-      foreach ($result as $record) {
-        $filters['all'][$record->format][$record->name] = $record;
+      $filter_formats = filter_formats();
+      foreach ($filter_formats as $filter_format) {
+        foreach ($filter_format->filters as $filter_name => $filter) {
+          $filter['name'] = $filter_name;
+          $filters['all'][$filter_format->format][$filter_name] = (object)$filter;
+        }
+        @uasort($filters['all'][$filter_format->format], '_filter_format_filter_cmp');
       }
       cache()->set('filter_list_format', $filters['all']);
     }
@@ -775,8 +735,9 @@ function filter_list_format($format_id) {
     foreach ($filter_map as $name => $filter) {
       if (isset($filter_info[$name])) {
         $filter->title = $filter_info[$name]['title'];
-        // Unpack stored filter settings.
-        $filter->settings = (isset($filter->settings) ? unserialize($filter->settings) : array());
+
+        $filter->settings = isset($filter->settings) ? $filter->settings : array();
+
         // Merge in default settings.
         if (isset($filter_info[$name]['default settings'])) {
           $filter->settings += $filter_info[$name]['default settings'];
@@ -889,7 +850,7 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE,
   // Cache the filtered text. This cache is infinitely valid. It becomes
   // obsolete when $text changes (which leads to a new $cache_id). It is
   // automatically flushed when the text format is updated.
-  // @see filter_format_save()
+  // @see Drupal\filter\Plugin\Core\Entity\FilterFormat::save()
   if ($cache) {
     cache('filter')->set($cache_id, $text, CacheBackendInterface::CACHE_PERMANENT, array('filter_format' => $format->format));
   }
diff --git a/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php b/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php
new file mode 100644
index 0000000..587f12a
--- /dev/null
+++ b/core/modules/filter/lib/Drupal/filter/Plugin/Core/Entity/FilterFormat.php
@@ -0,0 +1,158 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\filter\Plugin\Core\Entity\FilterFormat.
+ */
+
+namespace Drupal\filter\Plugin\Core\Entity;
+
+use Drupal\Core\Config\Entity\ConfigEntityBase;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Defines the Filter Format entity.
+ *
+ * @Plugin(
+ *   id = "filter_format",
+ *   label = @Translation("Filter Format"),
+ *   module = "filter",
+ *   controller_class = "Drupal\Core\Config\Entity\ConfigStorageController",
+ *   config_prefix = "filter.format",
+ *   entity_keys = {
+ *     "id" = "format",
+ *     "label" = "name",
+ *     "uuid" = "uuid"
+ *   }
+ * )
+ */
+class FilterFormat extends ConfigEntityBase {
+
+  /**
+   * Unique machine name of the format.
+   *
+   * @var string
+   */
+  public $format;
+
+  /**
+   * Name of the text format (Filtered HTML).
+   *
+   * @var string
+   */
+  public $name;
+
+  /**
+   * Flag to indicate whether format is cacheable. (1 = cacheable, 0 = not
+   * cacheable).
+   *
+   * @var int
+   */
+  public $cache = 0;
+
+  /**
+   * The status of the text format. (1 = enabled, 0 = disabled)
+   *
+   * @var int
+   */
+  public $status = 1;
+
+  /**
+   * Weight of text format to use when listing.
+   *
+   * @var int
+   */
+  public $weight = 0;
+
+  /**
+   * An array of name value pairs of the roles that can use this format.
+   *
+   * @var array
+   */
+  public $roles = array();
+
+  /**
+   * An array of name value pairs of the enabled filters for this text format.
+   *
+   * Each element of this array must contain at least the following values:
+   *   - weight: Weight of filter within format.
+   *   - settings: An array of name value pairs that store the filter settings
+   *     for the specific format.
+   *
+   * @var array
+   */
+  public $filters = array();
+
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::id().
+   */
+  public function id() {
+    return $this->format;
+  }
+
+  /**
+   * Saves a text format object to the database.
+   *
+   * @return
+   *   SAVED_NEW or SAVED_UPDATED.
+   */
+  function save() {
+    $this->name = trim($this->name);
+    $this->cache = _filter_format_is_cacheable($this);
+    if (!isset($this->status)) {
+      $this->status = 1;
+    }
+    if (!isset($this->weight)) {
+      $this->weight = 0;
+    }
+
+    // Programmatic saves may not contain any filters.
+    if (!isset($this->filters)) {
+      $this->filters = array();
+    }
+    $filter_info = filter_get_filters();
+    foreach ($filter_info as $name => $filter) {
+      // If the format does not specify an explicit weight for a filter, assign
+      // a default weight, either defined in hook_filter_info(), or the default of
+      // 0 by filter_get_filters().
+      if (!isset($this->filters[$name]['weight'])) {
+        $this->filters[$name]['weight'] = $filter['weight'];
+      }
+      $this->filters[$name]['status'] = isset($this->filters[$name]['status']) ? $this->filters[$name]['status'] : 0;
+      $this->filters[$name]['module'] = $filter['module'];
+
+      // If settings were passed, only ensure default settings.
+      if (isset($this->filters[$name]['settings'])) {
+        if (isset($filter['default settings'])) {
+          $this->filters[$name]['settings'] = array_merge($filter['default settings'], $this->filters[$name]['settings']);
+        }
+      }
+      // Otherwise, use default settings or fall back to an empty array.
+      else {
+        $this->filters[$name]['settings'] = isset($filter['default settings']) ? $filter['default settings'] : array();
+      }
+    }
+
+    $return = $this->save();
+
+    if ($return == SAVED_NEW) {
+      module_invoke_all('filter_format_insert', $this);
+    }
+    else {
+      module_invoke_all('filter_format_update', $this);
+      // Explicitly indicate that the format was updated. We need to do this
+      // since if the filters were updated but the format object itself was not,
+      // the merge query above would not return an indication that anything had
+      // changed.
+      $return = SAVED_UPDATED;
+
+      // Clear the filter cache whenever a text format is updated.
+      cache('filter')->invalidateTags(array('filter_format' => $this->format));
+    }
+
+    filter_formats_reset();
+
+    return $return;
+  }
+}
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php
index e355f2d..754cd1c 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAPITest.php
@@ -26,7 +26,7 @@ function setUp() {
     parent::setUp();
 
     // Create Filtered HTML format.
-    $filtered_html_format = array(
+    $filtered_html_format_config = array(
       'format' => 'filtered_html',
       'name' => 'Filtered HTML',
       'filters' => array(
@@ -41,11 +41,11 @@ function setUp() {
         ),
       )
     );
-    $filtered_html_format = (object) $filtered_html_format;
-    filter_format_save($filtered_html_format);
+    $filtered_html_format = entity_create('filter_format', $filtered_html_format_config);
+    $filtered_html_format->save();
 
     // Create Full HTML format.
-    $full_html_format = array(
+    $full_html_format_config = array(
       'format' => 'full_html',
       'name' => 'Full HTML',
       'weight' => 1,
@@ -56,8 +56,8 @@ function setUp() {
         ),
       ),
     );
-    $full_html_format = (object) $full_html_format;
-    filter_format_save($full_html_format);
+    $full_html_format = entity_create('filter_format', $full_html_format_config);
+    $full_html_format->save();
   }
 
   /**
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php
index 9a09a76..893394b 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterAdminTest.php
@@ -152,14 +152,19 @@ function testFilterAdmin() {
     ));
     $this->assertTrue(!empty($elements), 'Reorder confirmed in admin interface.');
 
-    $result = db_query('SELECT * FROM {filter} WHERE format = :format ORDER BY weight ASC', array(':format' => $filtered));
-    $filters = array();
-    foreach ($result as $filter) {
-      if ($filter->name == $second_filter || $filter->name == $first_filter) {
-        $filters[] = $filter;
+    $filter_format = filter_format_load($filtered);
+
+    // The filter format is not saved in 'order', but the order is defined
+    // in the filter array. So, check if after ordering the filter, the
+    // expected order is correct.
+    $filter_format_filters = $filter_format->filters;
+    @uasort($filter_format_filters, '_filter_format_filter_cmp');
+    foreach ($filter_format_filters as $filter_name => $filter) {
+      if ($filter_name == $second_filter || $filter_name == $first_filter) {
+        $filters[] = $filter_name;
       }
     }
-    $this->assertTrue(($filters[0]->name == $second_filter && $filters[1]->name == $first_filter), 'Order confirmed in database.');
+    $this->assertTrue(($filters[0] == $second_filter && $filters[1] == $first_filter), t('Order confirmed in database.'));
 
     // Add format.
     $edit = array();
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php
index 766736f..f34376d 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.php
@@ -35,15 +35,15 @@ public static function getInfo() {
    */
   function testTextFormatCrud() {
     // Add a text format with minimum data only.
-    $format = new stdClass();
+    $format = entity_create('filter_format', array());
     $format->format = 'empty_format';
     $format->name = 'Empty format';
-    filter_format_save($format);
+    $format-save();
     $this->verifyTextFormat($format);
     $this->verifyFilters($format);
 
     // Add another text format specifying all possible properties.
-    $format = new stdClass();
+    $format = entity_create('filter_format', array());
     $format->format = 'custom_format';
     $format->name = 'Custom format';
     $format->filters = array(
@@ -54,7 +54,7 @@ function testTextFormatCrud() {
         ),
       ),
     );
-    filter_format_save($format);
+    $format-save();
     $this->verifyTextFormat($format);
     $this->verifyFilters($format);
 
@@ -62,21 +62,19 @@ function testTextFormatCrud() {
     $format->name = 'Altered format';
     $format->filters['filter_url']['status'] = 0;
     $format->filters['filter_autop']['status'] = 1;
-    filter_format_save($format);
+    $format-save();
     $this->verifyTextFormat($format);
     $this->verifyFilters($format);
 
     // Add a uncacheable filter and save again.
     $format->filters['filter_test_uncacheable']['status'] = 1;
-    filter_format_save($format);
+    $format-save();
     $this->verifyTextFormat($format);
     $this->verifyFilters($format);
 
     // Disable the text format.
     filter_format_disable($format);
 
-    $db_format = db_query("SELECT * FROM {filter_format} WHERE format = :format", array(':format' => $format->format))->fetchObject();
-    $this->assertFalse($db_format->status, 'Database: Disabled text format is marked as disabled.');
     $formats = filter_formats();
     $this->assertTrue(!isset($formats[$format->format]), 'filter_formats: Disabled text format no longer exists.');
   }
@@ -86,16 +84,6 @@ function testTextFormatCrud() {
    */
   function verifyTextFormat($format) {
     $t_args = array('%format' => $format->name);
-    // Verify text format database record.
-    $db_format = db_select('filter_format', 'ff')
-      ->fields('ff')
-      ->condition('format', $format->format)
-      ->execute()
-      ->fetchObject();
-    $this->assertEqual($db_format->format, $format->format, format_string('Database: Proper format id for text format %format.', $t_args));
-    $this->assertEqual($db_format->name, $format->name, format_string('Database: Proper title for text format %format.', $t_args));
-    $this->assertEqual($db_format->cache, $format->cache, format_string('Database: Proper cache indicator for text format %format.', $t_args));
-    $this->assertEqual($db_format->weight, $format->weight, format_string('Database: Proper weight for text format %format.', $t_args));
 
     // Verify filter_format_load().
     $filter_format = filter_format_load($format->format);
@@ -123,27 +111,7 @@ function verifyTextFormat($format) {
    * Verify that filters are properly stored for a text format.
    */
   function verifyFilters($format) {
-    // Verify filter database records.
-    $filters = db_query("SELECT * FROM {filter} WHERE format = :format", array(':format' => $format->format))->fetchAllAssoc('name');
     $format_filters = $format->filters;
-    foreach ($filters as $name => $filter) {
-      $t_args = array('%format' => $format->name, '%filter' => $name);
-
-      // Verify that filter status is properly stored.
-      $this->assertEqual($filter->status, $format_filters[$name]['status'], format_string('Database: Proper status for %filter in text format %format.', $t_args));
-
-      // Verify that filter settings were properly stored.
-      $this->assertEqual(unserialize($filter->settings), isset($format_filters[$name]['settings']) ? $format_filters[$name]['settings'] : array(), format_string('Database: Proper filter settings for %filter in text format %format.', $t_args));
-
-      // Verify that each filter has a module name assigned.
-      $this->assertTrue(!empty($filter->module), format_string('Database: Proper module name for %filter in text format %format.', $t_args));
-
-      // Remove the filter from the copy of saved $format to check whether all
-      // filters have been processed later.
-      unset($format_filters[$name]);
-    }
-    // Verify that all filters have been processed.
-    $this->assertTrue(empty($format_filters), 'Database contains values for all filters in the saved format.');
 
     // Verify filter_list_format().
     $filters = filter_list_format($format->format);
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultFormatTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultFormatTest.php
index 04fa520..02031e3 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultFormatTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterDefaultFormatTest.php
@@ -42,7 +42,17 @@ function testDefaultTextFormats() {
 
     // Adjust the weights so that the first and second formats (in that order)
     // are the two lowest weighted formats available to any user.
-    $minimum_weight = db_query("SELECT MIN(weight) FROM {filter_format}")->fetchField();
+    $minimum_weight = NULL;
+    foreach (entity_load_multiple('filter_format') as $format) {
+      if (is_null($minimum_weight)) {
+        $minimum_weight = $format->weight;
+      }
+      else {
+        if ($minimum_weight > $format->weight) {
+          $minimum_weight = $format->weight;
+        }
+      }
+    }
     $edit = array();
     $edit['formats[' . $first_format->format . '][weight]'] = $minimum_weight - 2;
     $edit['formats[' . $second_format->format . '][weight]'] = $minimum_weight - 1;
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php
index a7e38ac..4d664a8 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterHtmlImageSecureTest.php
@@ -33,7 +33,7 @@ function setUp() {
     parent::setUp();
 
     // Setup Filtered HTML text format.
-    $filtered_html_format = array(
+    $filtered_html_format_config = array(
       'format' => 'filtered_html',
       'name' => 'Filtered HTML',
       'filters' => array(
@@ -51,8 +51,8 @@ function setUp() {
         ),
       ),
     );
-    $filtered_html_format = (object) $filtered_html_format;
-    filter_format_save($filtered_html_format);
+    $filtered_html_format = entity_create('filter_format', $filtered_html_format_config);
+    $filtered_html_format->save();
 
     // Setup users.
     $this->checkPermissions(array(), TRUE);
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php
index 813d717..c99a1ce 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterSecurityTest.php
@@ -36,7 +36,7 @@ function setUp() {
     $this->drupalCreateContentType(array('type' => 'page', 'name' => 'Basic page'));
 
     // Create Filtered HTML format.
-    $filtered_html_format = array(
+    $filtered_html_format_config = array(
       'format' => 'filtered_html',
       'name' => 'Filtered HTML',
       'filters' => array(
@@ -46,8 +46,8 @@ function setUp() {
         ),
       )
     );
-    $filtered_html_format = (object) $filtered_html_format;
-    filter_format_save($filtered_html_format);
+    $filtered_html_format = entity_create('filter_format', $filtered_html_format_config);
+    $filtered_html_format->save();
 
     $filtered_html_permission = filter_permission_name($filtered_html_format);
     user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array($filtered_html_permission));
diff --git a/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php b/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php
index 0a6c00c..1aa7909 100644
--- a/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php
+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterSettingsTest.php
@@ -31,12 +31,13 @@ function testFilterDefaults() {
     $filters = array_fill_keys(array_keys($filter_info), array());
 
     // Create text format using filter default settings.
-    $filter_defaults_format = (object) array(
+    $filter_defaults_format_config = array(
       'format' => 'filter_defaults',
       'name' => 'Filter defaults',
       'filters' => $filters,
     );
-    filter_format_save($filter_defaults_format);
+    $filter_defaults_format = entity_create('filter_format', $filter_defaults_format_config);
+    $filter_defaults_format->save();
 
     // Verify that default weights defined in hook_filter_info() were applied.
     $saved_settings = array();
@@ -51,7 +52,7 @@ function testFilterDefaults() {
     }
 
     // Re-save the text format.
-    filter_format_save($filter_defaults_format);
+    $filter_defaults_format->save();
     // Reload it from scratch.
     filter_formats_reset();
     $filter_defaults_format = filter_format_load($filter_defaults_format->format);
diff --git a/core/modules/php/php.install b/core/modules/php/php.install
index 12944dd..f2281f2 100644
--- a/core/modules/php/php.install
+++ b/core/modules/php/php.install
@@ -9,13 +9,20 @@
  * Implements hook_enable().
  */
 function php_enable() {
-  $format_exists = (bool) db_query_range('SELECT 1 FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'PHP code'))->fetchField();
   // Add a PHP code text format, if it does not exist. Do this only for the
   // first install (or if the format has been manually deleted) as there is no
   // reliable method to identify the format in an uninstall hook or in
   // subsequent clean installs.
+  $format_exists = FALSE;
+  $filter_formats = entity_load_multiple('filter_format');
+  foreach ($filter_formats as $format) {
+    if ($format->name == 'PHP code') {
+      $format_exists = TRUE;
+      break;
+    }
+  }
   if (!$format_exists) {
-    $php_format = array(
+    $php_format_config = array(
       'format' => 'php_code',
       'name' => 'PHP code',
       // 'Plain text' format is installed with a weight of 10 by default. Use a
@@ -30,8 +37,8 @@ function php_enable() {
         ),
       ),
     );
-    $php_format = (object) $php_format;
-    filter_format_save($php_format);
+    $php_format = entity_create('filter_format', $php_format_config);
+    $php_format->save();
 
     drupal_set_message(t('A <a href="@php-code">PHP code</a> text format has been created.', array('@php-code' => url('admin/config/content/formats/' . $php_format->format))));
   }
diff --git a/core/modules/search/lib/Drupal/search/Tests/SearchRankingTest.php b/core/modules/search/lib/Drupal/search/Tests/SearchRankingTest.php
index a57e483..72c2431 100644
--- a/core/modules/search/lib/Drupal/search/Tests/SearchRankingTest.php
+++ b/core/modules/search/lib/Drupal/search/Tests/SearchRankingTest.php
@@ -106,12 +106,12 @@ function testRankings() {
    * Test rankings of HTML tags.
    */
   function testHTMLRankings() {
-    $full_html_format = array(
+    $full_html_format_config = array(
       'format' => 'full_html',
       'name' => 'Full HTML',
     );
-    $full_html_format = (object) $full_html_format;
-    filter_format_save($full_html_format);
+    $full_html_format = entity_create('filter_format', $full_html_format_config);
+    $full_html_format->save();
 
     // Login with sufficient privileges.
     $this->drupalLogin($this->drupalCreateUser(array('create page content')));
diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
index 15d12d8..5defe91 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php
@@ -29,12 +29,12 @@ public static function getInfo() {
   function setUp() {
     parent::setUp();
 
-    $filtered_html_format = array(
+    $filtered_html_format_config = array(
       'format' => 'filtered_html',
       'name' => 'Filtered HTML',
     );
-    $filtered_html_format = (object) $filtered_html_format;
-    filter_format_save($filtered_html_format);
+    $filtered_html_format = entity_create('filter_format', $filtered_html_format_config);
+    $filtered_html_format->save();
 
     $filtered_html_permission = filter_permission_name($filtered_html_format);
     user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array($filtered_html_permission));
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
index e4ecbfc..1b558fa 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/BreadcrumbTest.php
@@ -147,7 +147,8 @@ function testBreadCrumbs() {
     $this->assertBreadcrumb("admin/structure/types/manage/$type/fields/body/widget-type", $trail);
 
     // Verify Filter text format administration breadcrumbs.
-    $format = db_query_range("SELECT format, name FROM {filter_format}", 1, 1)->fetch();
+    $filter_formats = filter_formats();
+    $format = reset($filter_formats);
     $format_id = $format->format;
     $trail = $config + array(
       'admin/config/content' => t('Content authoring'),
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTestBase.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTestBase.php
index 6f4dcb2..aebbb61 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTestBase.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TaxonomyTestBase.php
@@ -52,11 +52,13 @@ function createVocabulary() {
    * Returns a new term with random properties in vocabulary $vid.
    */
   function createTerm($vocabulary) {
+    $filter_formats = filter_formats();
+    $format = array_pop($filter_formats);
     $term = entity_create('taxonomy_term', array(
       'name' => $this->randomName(),
       'description' => $this->randomName(),
       // Use the first available text format.
-      'format' => db_query_range('SELECT format FROM {filter_format}', 0, 1)->fetchField(),
+      'format' => $format->format,
       'vid' => $vocabulary->vid,
       'langcode' => LANGUAGE_NOT_SPECIFIED,
     ));
diff --git a/core/modules/taxonomy/taxonomy.install b/core/modules/taxonomy/taxonomy.install
index 25d2c06..7def3bc 100644
--- a/core/modules/taxonomy/taxonomy.install
+++ b/core/modules/taxonomy/taxonomy.install
@@ -133,7 +133,7 @@ function taxonomy_schema() {
         'type' => 'varchar',
         'length' => 255,
         'not null' => FALSE,
-        'description' => 'The {filter_format}.format of the description.',
+        'description' => 'The Filter Format id of the description.',
       ),
       'weight' => array(
         'type' => 'int',
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserSignatureTest.php b/core/modules/user/lib/Drupal/user/Tests/UserSignatureTest.php
index 9ed88ca..3712eba 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserSignatureTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserSignatureTest.php
@@ -41,19 +41,19 @@ function setUp() {
     // Prefetch and create text formats.
     $this->plain_text_format = filter_format_load('plain_text');
 
-    $filtered_html_format = array(
+    $filtered_html_format_config = array(
       'format' => 'filtered_html',
       'name' => 'Filtered HTML',
     );
-    $this->filtered_html_format = (object) $filtered_html_format;
-    filter_format_save($this->filtered_html_format);
+    $this->filtered_html_format = entity_create('filter_format', $filtered_html_format_config);
+    $this->filtered_html_format->save();
 
-    $full_html_format = array(
+    $full_html_format_config = array(
       'format' => 'full_html',
       'name' => 'Full HTML',
     );
-    $this->full_html_format = (object) $full_html_format;
-    filter_format_save($this->full_html_format);
+    $this->full_html_format = entity_create('filter_format', $full_html_format_config);
+    $this->full_html_format->save();
 
     user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array(filter_permission_name($this->filtered_html_format)));
     $this->checkPermissions(array(), TRUE);
diff --git a/core/modules/user/user.install b/core/modules/user/user.install
index 3bc837f..e5bb9f3 100644
--- a/core/modules/user/user.install
+++ b/core/modules/user/user.install
@@ -73,7 +73,7 @@ function user_schema() {
         'type' => 'varchar',
         'length' => 255,
         'not null' => FALSE,
-        'description' => 'The {filter_format}.format of the signature.',
+        'description' => 'The Filter Format id of the signature.',
       ),
       'created' => array(
         'type' => 'int',
diff --git a/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php b/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php
index 7e37452..4129332 100644
--- a/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php
+++ b/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php
@@ -149,11 +149,13 @@ public function testDefaultViews() {
    * Returns a new term with random properties in vocabulary $vid.
    */
   function createTerm($vocabulary) {
+    $filter_formats = filter_formats();
+    $format = array_pop($filter_formats);
     $term = entity_create('taxonomy_term', array(
       'name' => $this->randomName(),
       'description' => $this->randomName(),
       // Use the first available text format.
-      'format' => db_query_range('SELECT format FROM {filter_format}', 0, 1)->fetchField(),
+      'format' => $format->format,
       'vid' => $vocabulary->vid,
       'langcode' => LANGUAGE_NOT_SPECIFIED,
     ));
diff --git a/core/modules/views/lib/Drupal/views/Tests/Taxonomy/TaxonomyTestBase.php b/core/modules/views/lib/Drupal/views/Tests/Taxonomy/TaxonomyTestBase.php
index 9c2835a..f6defe4 100644
--- a/core/modules/views/lib/Drupal/views/Tests/Taxonomy/TaxonomyTestBase.php
+++ b/core/modules/views/lib/Drupal/views/Tests/Taxonomy/TaxonomyTestBase.php
@@ -122,11 +122,13 @@ protected function mockStandardInstall() {
    *   The created taxonomy term.
    */
   protected function createTerm() {
+    $filter_formats = filter_formats();
+    $format = array_pop($filter_formats);
     $term = entity_create('taxonomy_term', array(
       'name' => $this->randomName(),
       'description' => $this->randomName(),
       // Use the first available text format.
-      'format' => db_query_range('SELECT format FROM {filter_format}', 0, 1)->fetchField(),
+      'format' => $format->format,
       'vid' => $this->vocabulary->vid,
       'langcode' => LANGUAGE_NOT_SPECIFIED,
     ));
diff --git a/core/profiles/standard/config/filter.format.filtered_html.yml b/core/profiles/standard/config/filter.format.filtered_html.yml
new file mode 100644
index 0000000..1b905c6
--- /dev/null
+++ b/core/profiles/standard/config/filter.format.filtered_html.yml
@@ -0,0 +1,16 @@
+format: filtered_html
+name: Filtered HTML
+weight: 0
+filters:
+  filter_url:
+    weight: 0
+    status: 1
+  filter_html:
+    weight: 1
+    status: 1
+  filter_autop:
+    weight: 2
+    status: 1
+  filter_htmlcorrector:
+    weight: 10
+    status: 1
diff --git a/core/profiles/standard/config/filter.format.full_html.yml b/core/profiles/standard/config/filter.format.full_html.yml
new file mode 100644
index 0000000..bc01d83
--- /dev/null
+++ b/core/profiles/standard/config/filter.format.full_html.yml
@@ -0,0 +1,13 @@
+format: full_html
+name: Full HTML
+weight: 1
+filters:
+  filter_url:
+    weight: 0
+    status: 1
+  filter_autop:
+    weight: 1
+    status: 1
+  filter_htmlcorrector:
+    weight: 10
+    status: 1
diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install
index b4dc761..c9a641d 100644
--- a/core/profiles/standard/standard.install
+++ b/core/profiles/standard/standard.install
@@ -12,62 +12,6 @@
  * @see system_install()
  */
 function standard_install() {
-  // Add text formats.
-  $filtered_html_format = array(
-    'format' => 'filtered_html',
-    'name' => 'Filtered HTML',
-    'weight' => 0,
-    'filters' => array(
-      // URL filter.
-      'filter_url' => array(
-        'weight' => 0,
-        'status' => 1,
-      ),
-      // HTML filter.
-      'filter_html' => array(
-        'weight' => 1,
-        'status' => 1,
-      ),
-      // Line break filter.
-      'filter_autop' => array(
-        'weight' => 2,
-        'status' => 1,
-      ),
-      // HTML corrector filter.
-      'filter_htmlcorrector' => array(
-        'weight' => 10,
-        'status' => 1,
-      ),
-    ),
-  );
-  $filtered_html_format = (object) $filtered_html_format;
-  filter_format_save($filtered_html_format);
-
-  $full_html_format = array(
-    'format' => 'full_html',
-    'name' => 'Full HTML',
-    'weight' => 1,
-    'filters' => array(
-      // URL filter.
-      'filter_url' => array(
-        'weight' => 0,
-        'status' => 1,
-      ),
-      // Line break filter.
-      'filter_autop' => array(
-        'weight' => 1,
-        'status' => 1,
-      ),
-      // HTML corrector filter.
-      'filter_htmlcorrector' => array(
-        'weight' => 10,
-        'status' => 1,
-      ),
-    ),
-  );
-  $full_html_format = (object) $full_html_format;
-  filter_format_save($full_html_format);
-
   // Enable Bartik theme and set it as default theme instead of Stark.
   // @see system_install()
   $default_theme = 'bartik';
@@ -374,6 +318,7 @@ function standard_install() {
   field_create_instance($instance);
 
   // Enable default permissions for system roles.
+  $filtered_html_format = filter_format_load('filtered_html');
   $filtered_html_permission = filter_permission_name($filtered_html_format);
   user_role_grant_permissions(DRUPAL_ANONYMOUS_RID, array('access content', 'access comments', $filtered_html_permission));
   user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID, array('access content', 'access comments', 'post comments', 'skip comment approval', $filtered_html_permission));
