Index: block_api_type/CHANGELOG.txt
===================================================================
RCS file: block_api_type/CHANGELOG.txt
diff -N block_api_type/CHANGELOG.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ block_api_type/CHANGELOG.txt	12 Dec 2010 22:24:15 -0000
@@ -0,0 +1,5 @@
+// $Id: CHANGELOG.txt,v 1.3 2010/11/19 21:10:35 sun Exp $
+
+Custom block type 7.x-1.x, xxxx-xx-xx
+-------------------------------------
+by sun: Added initial baseline of module files.
Index: block_api_type/README.txt
===================================================================
RCS file: block_api_type/README.txt
diff -N block_api_type/README.txt
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ block_api_type/README.txt	12 Dec 2010 22:24:40 -0000
@@ -0,0 +1,39 @@
+/* $Id: README.txt,v 1.2 2010/11/18 18:01:28 sun Exp $ */
+
+-- SUMMARY --
+
+Allows to create custom block types.
+
+For a full description of the module, visit the project page:
+  http://drupal.org/project/block_api
+To submit bug reports and feature suggestions, or to track changes:
+  http://drupal.org/project/issues/block_api
+
+
+-- REQUIREMENTS --
+
+* Block API module.
+
+* Entity module.
+
+
+-- INSTALLATION --
+
+* Install as usual, see http://drupal.org/node/70151 for further information.
+
+
+-- CONFIGURATION --
+
+* @todo
+
+
+-- USAGE --
+
+* @todo
+
+
+-- CONTACT --
+
+Current maintainers:
+* Daniel F. Kudwien (sun) - http://drupal.org/user/54136
+
Index: block_api_type/block_api_type.info
===================================================================
RCS file: block_api_type/block_api_type.info
diff -N block_api_type/block_api_type.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ block_api_type/block_api_type.info	12 Dec 2010 22:22:51 -0000
@@ -0,0 +1,6 @@
+; $Id: title.info,v 1.2 2010/11/18 18:01:28 sun Exp $
+name = Custom block type
+description = Allows to create custom block types.
+core = 7.x
+dependencies[] = block_api
+dependencies[] = entity
Index: block_api_type/block_api_type.install
===================================================================
RCS file: block_api_type/block_api_type.install
diff -N block_api_type/block_api_type.install
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ block_api_type/block_api_type.install	12 Dec 2010 22:27:31 -0000
@@ -0,0 +1,45 @@
+<?php
+// $Id: title.install,v 1.2 2010/11/18 18:01:28 sun Exp $
+
+/**
+ * @file
+ * Installation functions for Custom block type module.
+ */
+
+/**
+ * Implements hook_field_schema().
+ */
+function block_api_type_schema() {
+  $schema['block_api_type'] = array(
+    'description' => 'Stores custom Block API block types.',
+    'fields' => array(
+      'type' => array(
+        'description' => 'Machine name of the block type.',
+        'type' => 'varchar',
+        // @see block_api_schema()
+        'length' => 128,
+        // A primary key always needs to be 'not null' and always requires a
+        // 'default' value.
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'title' => array(
+        'description' => 'Block type title.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'description' => array(
+        'description' => 'Block type description.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+    ),
+    'primary key' => array('type'),
+  );
+  return $schema;
+}
+
Index: block_api_type/block_api_type.module
===================================================================
RCS file: block_api_type/block_api_type.module
diff -N block_api_type/block_api_type.module
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ block_api_type/block_api_type.module	12 Dec 2010 23:08:57 -0000
@@ -0,0 +1,162 @@
+<?php
+// $Id: title.module,v 1.2 2010/11/18 18:01:28 sun Exp $
+
+/**
+ * @file
+ * Allows to create custom block types.
+ */
+
+/**
+ * Implements hook_entity_info().
+ */
+function block_api_type_entity_info() {
+  $types['block_api_type'] = array(
+    'label' => t('Block type'),
+    'entity class' => 'Entity',
+    'controller class' => 'EntityAPIController',
+    'base table' => 'block_api_type',
+    'entity keys' => array(
+      'id' => 'type',
+      'name' => 'type',
+      'label' => 'title',
+    ),
+    // @todo 'bundle of' is soon going to be removed; the bundle entity type is
+    //   referenced from the entity type instead.
+    // @see http://drupal.org/node/977380
+    'bundle of' => 'block_api',
+    'admin ui' => array(
+      'path' => 'admin/structure/block/types',
+    ),
+  );
+  return $types;
+}
+
+/**
+ * Implements hook_entity_info_alter().
+ */
+function block_api_type_entity_info_alter(&$types) {
+  $types['block_api']['fieldable'] = TRUE;
+
+  foreach (block_api_type_load_multiple(FALSE) as $name => $type) {
+    $entity_info['block_api']['bundles'][$name] = array(
+      'label' => $type->title,
+      'admin' => array(
+        'path' => 'admin/structure/block/types/manage/%block_api_type',
+        'real path' => 'admin/structure/block/types/manage/' . $name,
+        'bundle argument' => 5,
+        'access arguments' => array('administer blocks'),
+      ),
+    );
+  }
+}
+
+/**
+ * Loads a block type from the database.
+ *
+ * @param $name
+ *   The block type name to load.
+ */
+function block_api_type_load($name) {
+  $types = block_api_type_load_multiple(array($name));
+  return isset($types[$name]) ? $types[$name] : FALSE;
+}
+
+/**
+ * Loads multiple block types from the database.
+ *
+ * @param $names
+ *   A list of block type names to load.
+ * @param $conditions
+ *   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.
+ *
+ * @return
+ *   An array of loaded block types, keyed by type name.
+ */
+function block_api_type_load_multiple($names = array(), array $conditions = array(), $reset = FALSE) {
+  return entity_load('block_api_type', $names, $conditions, $reset);
+}
+
+/**
+ * Saves a block type to the database.
+ *
+ * @param $type
+ *   The block type object to save.
+ */
+function block_api_type_save($type) {
+  module_invoke_all('block_api_type_presave', $type);
+
+  $status = db_merge('block_api_type')
+    ->fields(array(
+      'title' => $type->title,
+      'description' => $type->description,
+    ))
+    ->key(array(
+      'type' => $type->type,
+    ))
+    ->execute();
+
+  if ($status == SAVED_NEW) {
+    module_invoke_all('block_api_type_insert', $type);
+  }
+  else {
+    module_invoke_all('block_api_type_update', $type);
+  }
+
+  return $status;
+}
+
+/**
+ * Form constructor to add or edit a block type.
+ */
+function block_api_type_form($form, &$form_state, $type) {
+  if (!$type) {
+    $type = (object) array(
+      'type' => NULL,
+      'title' => NULL,
+      'description' => NULL,
+    );
+  }
+
+  $form['title'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Title'),
+    '#required' => TRUE,
+    '#default_value' => $type->title,
+  );
+  $form['type'] = array(
+    '#type' => 'machine_name',
+    '#maxlength' => 128,
+    '#required' => TRUE,
+    '#machine_name' => array(
+      'source' => array('title'),
+      'exists' => 'block_api_type_load',
+    ),
+    '#default_value' => $type->type,
+    '#disabled' => !empty($type->type),
+  );
+  $form['description'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Description'),
+    '#default_value' => $type->description,
+  );
+
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Add block type'),
+  );
+  return $form;
+}
+
+/**
+ * Form submission handler for block_api_type_form().
+ */
+function block_api_type_form_submit($form, &$form_state) {
+  form_state_values_clean($form_state);
+  $type = (object) $form_state['values'];
+
+  block_api_type_save($type);
+}
