Index: block_api.admin.inc
===================================================================
RCS file: block_api.admin.inc
diff -N block_api.admin.inc
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ block_api.admin.inc	12 Dec 2010 17:18:13 -0000
@@ -0,0 +1,122 @@
+<?php
+// $Id: block_api.module,v 1.7 2010/12/12 17:12:52 sun Exp $
+
+/**
+ * @file
+ * Block API administration pages.
+ */
+
+/**
+ * Form constructor to create a new block instance.
+ */
+function block_api_create_form($form, &$form_state) {
+  $form['admin_title'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Administrative block description'),
+    '#required' => TRUE,
+  );
+  $form['delta'] = array(
+    '#type' => 'machine_name',
+    '#required' => TRUE,
+    '#machine_name' => array(
+      'source' => array('admin_title'),
+      'exists' => 'block_api_load',
+    ),
+  );
+  $form['type'] = array(
+    '#type' => 'radios',
+    '#title' => t('Block type'),
+    '#required' => TRUE,
+    '#options' => array(),
+  );
+  foreach (block_api_get_info() as $type => $info) {
+    // Add the option.
+    $form['type']['#options'][$type] = $info['title'];
+    // Add the block type description and entire block info to the about to be
+    // expanded sub-element for the option.
+    $form['type'][$type]['#description'] = $info['description'];
+    $form['type'][$type]['#block_api'] = $info;
+  }
+
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Add block'),
+  );
+  return $form;
+}
+
+/**
+ * Form submission handler for block_api_create_form().
+ */
+function block_api_create_form_submit($form, &$form_state) {
+  form_state_values_clean($form_state);
+
+  $type = $form_state['values']['type'];
+  $block_info = $form['type'][$type]['#block_api'];
+  $delta = $form_state['values']['delta'];
+
+  // Save the block instance.
+  $instance = $form_state['values'];
+  $instance += $block_info;
+  $instance = (object) $instance;
+  block_api_save($instance);
+
+  // @see block_add_block_form_submit()
+  $query = db_insert('block')->fields(array(
+    'visibility', 'pages', 'custom', 'title', 'module', 'theme', 'status', 'weight', 'delta', 'cache',
+  ));
+  foreach (list_themes() as $key => $theme) {
+    if ($theme->status) {
+      $query->values(array(
+        'visibility' => 0,
+        'pages' => '',
+        'custom' => 0,
+        'title' => '',
+        'module' => 'block_api',
+        'theme' => $theme->name,
+        'status' => 0,
+        'weight' => 0,
+        'delta' => $delta,
+        'cache' => DRUPAL_NO_CACHE,
+      ));
+    }
+  }
+  $query->execute();
+
+  drupal_set_message(t('The block has been created.'));
+
+  $form_state['redirect'] = 'admin/structure/block/manage/block_api/' . $delta;
+}
+
+/**
+ * Form constructor to confirm the deletion of a block instance.
+ */
+function block_api_delete_form($form, &$form_state, $module, $delta) {
+  $instance = block_api_load($delta);
+  $form['#block_api'] = $instance;
+  $form['type'] = array('#type' => 'value', '#value' => $instance->type);
+  $form['module'] = array('#type' => 'value', '#value' => $instance->module);
+  $form['delta'] = array('#type' => 'value', '#value' => $instance->delta);
+
+  return confirm_form($form,
+    t('Are you sure you want to delete the block %name?', array('%name' => $instance->admin_title)),
+    'admin/structure/block',
+    NULL,
+    t('Delete')
+  );
+}
+
+/**
+ * Form submission handler for block_api_delete_form().
+ */
+function block_api_delete_form_submit($form, &$form_state) {
+  $instance = $form['#block_api'];
+
+  block_api_delete($instance->delta);
+
+  drupal_set_message(t('The block %name has been removed.', array('%name' => $instance->admin_title)));
+  cache_clear_all();
+
+  $form_state['redirect'] = 'admin/structure/block';
+}
Index: block_api.api.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/block_api/block_api.api.php,v
retrieving revision 1.2
diff -u -p -r1.2 block_api.api.php
--- block_api.api.php	12 Dec 2010 17:12:52 -0000	1.2
+++ block_api.api.php	12 Dec 2010 17:25:52 -0000
@@ -40,6 +40,18 @@ function hook_block_api_info() {
 }
 
 /**
+ * Act on block instances being loaded from the database.
+ *
+ * This hook is invoked during block loading, which is handled by entity_load(),
+ * via DrupalDefaultEntityController.
+ *
+ * @param $instances
+ *   An array of block type instances being loaded, keyed by delta.
+ */
+function hook_block_api_load($instances) {
+}
+
+/**
  * Respond to creation of a new block instance.
  *
  * This hook is invoked from block_api_save() after the block instance has been
Index: block_api.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/block_api/block_api.info,v
retrieving revision 1.5
diff -u -p -r1.5 block_api.info
--- block_api.info	12 Dec 2010 17:12:52 -0000	1.5
+++ block_api.info	12 Dec 2010 17:55:55 -0000
@@ -3,4 +3,5 @@ name = Block API
 description = Allows to create block instances of predefined block types.
 core = 7.x
 dependencies[] = block
+files[] = block_api.module
 files[] = tests/block_api.test
Index: block_api.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/block_api/block_api.module,v
retrieving revision 1.7
diff -u -p -r1.7 block_api.module
--- block_api.module	12 Dec 2010 17:12:52 -0000	1.7
+++ block_api.module	12 Dec 2010 18:22:05 -0000
@@ -4,9 +4,6 @@
 /**
  * @file
  * Allows to create block instances of predefined block types.
- *
- * @todo Implement hook_entity_info() to treat "block types" as entity bundles
- *   and block instances as entities. Opens the doors for fieldable blocks.
  */
 
 /**
@@ -55,7 +52,7 @@ function block_api_get_info() {
  */
 function block_api_block_info() {
   $blocks = array();
-  foreach (block_api_load_multiple() as $instance) {
+  foreach (block_api_load_multiple(FALSE) as $instance) {
     $blocks[$instance->delta] = array(
       'info' => $instance->admin_title,
     );
@@ -130,6 +127,7 @@ function block_api_menu() {
     'page arguments' => array('block_api_create_form'),
     'access arguments' => array('administer blocks'),
     'type' => MENU_LOCAL_ACTION,
+    'file' => 'block_api.admin.inc',
   );
   $items['admin/structure/block/delete-module-block/%/%'] = array(
     'title' => 'Delete module block',
@@ -137,11 +135,53 @@ function block_api_menu() {
     'page callback' => 'drupal_get_form',
     'page arguments' => array('block_api_delete_form', 4, 5),
     'type' => MENU_CALLBACK,
+    'file' => 'block_api.admin.inc',
   );
   return $items;
 }
 
 /**
+ * Implements hook_entity_info().
+ */
+function block_api_entity_info() {
+  $types['block_api'] = array(
+    'label' => t('Block'),
+    'controller class' => 'BlockApiController',
+    'base table' => 'block_api',
+    'entity keys' => array(
+      'id' => 'delta',
+      'bundle' => 'type',
+      'label' => 'admin_title',
+    ),
+    'bundle keys' => array(
+      'bundle' => 'type',
+    ),
+    // @todo Invoke block_api_get_info() and register block types as bundles.
+    'bundles' => array(),
+  );
+  return $types;
+}
+
+/**
+ * Controller class for block instances.
+ *
+ * This extends the DrupalDefaultEntityController class, adding required
+ * special handling for block instances.
+ */
+class BlockApiController extends DrupalDefaultEntityController {
+
+  function attachLoad(&$queried_entities, $revision_id = FALSE) {
+    foreach ($queried_entities as $delta => $instance) {
+      $queried_entities[$delta]->settings = unserialize($instance->settings);
+    }
+
+    // Call the default attachLoad() method to add fields and invoke
+    // hook_ENTITY_load().
+    parent::attachLoad($queried_entities, $revision_id);
+  }
+}
+
+/**
  * Loads multiple block instances from the database.
  *
  * @param $delta
@@ -158,29 +198,16 @@ function block_api_load($delta) {
  * @param $deltas
  *   A list of block instance deltas to load.
  * @param $conditions
- *   (deprecated)
+ *   An associative array of conditions on the base table, where the keys are
+ *   the database fields and the values are the values those fields must have.
  * @param $reset
  *   Whether to reset the internal static cache.
  *
- * @todo Use entity_load() instead.
+ * @return
+ *   An array of loaded block instances, keyed by delta.
  */
-function block_api_load_multiple(array $deltas = array(), array $conditions = array(), $reset = FALSE) {
-  $query = db_select('block_api', 'ba')
-    ->fields('ba');
-  if ($deltas) {
-    $query->condition('delta', $deltas, 'IN');
-  }
-  if ($conditions) {
-    foreach ($conditions as $column => $value) {
-      $query->condition($column, $value);
-    }
-  }
-  $blocks = $query->execute()->fetchAllAssoc('delta');
-  foreach ($blocks as &$block) {
-    $block->settings = unserialize($block->settings);
-  }
-
-  return $blocks;
+function block_api_load_multiple($deltas = array(), array $conditions = array(), $reset = FALSE) {
+  return entity_load('block_api', $deltas, $conditions, $reset);
 }
 
 /**
@@ -232,10 +259,6 @@ function block_api_delete($delta) {
  *   A list of machine names of block instances to delete.
  */
 function block_api_delete_multiple(array $deltas) {
-  // block_api_load_multiple() is supposed to load all blocks by default.
-  if (empty($deltas)) {
-    return;
-  }
   $instances = block_api_load_multiple($deltas);
   foreach ($instances as $delta => $instance) {
     // Remove the configuration settings
@@ -268,9 +291,9 @@ function block_api_delete_multiple(array
  * Alters the blocks page to show a delete link to delete blocks
  */
 function block_api_form_block_admin_display_form_alter(&$form, $form_state) {
-  $blocks = block_api_load_multiple();
+  $blocks = block_api_load_multiple(FALSE);
   foreach ($blocks as $delta => $block) {
-    // Block module's block overview form uses MODULE_DELTA as form array keys.
+    // block_admin_display_form() uses MODULE_DELTA as form array keys.
     $form['blocks']['block_api_' . $delta]['delete'] = array(
       '#type' => 'link',
       '#title' => t('delete'),
@@ -278,118 +301,3 @@ function block_api_form_block_admin_disp
     );
   }
 }
-
-/**
- * Form constructor to confirm the deletion of a block instance.
- */
-function block_api_delete_form($form, &$form_state, $module, $delta) {
-  $instance = block_api_load($delta);
-  $form['#block_api'] = $instance;
-  $form['type'] = array('#type' => 'value', '#value' => $instance->type);
-  $form['module'] = array('#type' => 'value', '#value' => $instance->module);
-  $form['delta'] = array('#type' => 'value', '#value' => $instance->delta);
-
-  return confirm_form($form,
-    t('Are you sure you want to delete the block %name?', array('%name' => $instance->admin_title)),
-    'admin/structure/block',
-    NULL,
-    t('Delete')
-  );
-}
-
-/**
- * Form submission handler for block_api_delete_form().
- */
-function block_api_delete_form_submit($form, &$form_state) {
-  $instance = $form['#block_api'];
-
-  block_api_delete($instance->delta);
-
-  drupal_set_message(t('The block %name has been removed.', array('%name' => $instance->admin_title)));
-  cache_clear_all();
-
-  $form_state['redirect'] = 'admin/structure/block';
-}
-
-/**
- * Form constructor to create a new block instance.
- */
-function block_api_create_form($form, &$form_state) {
-  $form['admin_title'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Administrative block description'),
-    '#required' => TRUE,
-  );
-  $form['delta'] = array(
-    '#type' => 'machine_name',
-    '#required' => TRUE,
-    '#machine_name' => array(
-      'source' => array('admin_title'),
-      'exists' => 'block_api_load',
-    ),
-  );
-  $form['type'] = array(
-    '#type' => 'radios',
-    '#title' => t('Block type'),
-    '#required' => TRUE,
-    '#options' => array(),
-  );
-  foreach (block_api_get_info() as $type => $info) {
-    // Add the option.
-    $form['type']['#options'][$type] = $info['title'];
-    // Add the block type description and entire block info to the about to be
-    // expanded sub-element for the option.
-    $form['type'][$type]['#description'] = $info['description'];
-    $form['type'][$type]['#block_api'] = $info;
-  }
-
-  $form['actions'] = array('#type' => 'actions');
-  $form['actions']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Add block'),
-  );
-  return $form;
-}
-
-/**
- * Form submission handler for block_api_create_form().
- */
-function block_api_create_form_submit($form, &$form_state) {
-  form_state_values_clean($form_state);
-
-  $type = $form_state['values']['type'];
-  $block_info = $form['type'][$type]['#block_api'];
-  $delta = $form_state['values']['delta'];
-
-  // Save the block instance.
-  $instance = $form_state['values'];
-  $instance += $block_info;
-  $instance = (object) $instance;
-  block_api_save($instance);
-
-  // @see block_add_block_form_submit()
-  $query = db_insert('block')->fields(array(
-    'visibility', 'pages', 'custom', 'title', 'module', 'theme', 'status', 'weight', 'delta', 'cache',
-  ));
-  foreach (list_themes() as $key => $theme) {
-    if ($theme->status) {
-      $query->values(array(
-        'visibility' => 0,
-        'pages' => '',
-        'custom' => 0,
-        'title' => '',
-        'module' => 'block_api',
-        'theme' => $theme->name,
-        'status' => 0,
-        'weight' => 0,
-        'delta' => $delta,
-        'cache' => DRUPAL_NO_CACHE,
-      ));
-    }
-  }
-  $query->execute();
-
-  drupal_set_message(t('The block has been created.'));
-
-  $form_state['redirect'] = 'admin/structure/block/manage/block_api/' . $delta;
-}
