diff --git modules/block/block.admin.inc modules/block/block.admin.inc index f771cd9..4c82c20 100644 --- modules/block/block.admin.inc +++ modules/block/block.admin.inc @@ -100,7 +100,7 @@ function block_admin_display_form(&$form_state, $blocks, $theme = NULL) { ); $form[$key]['configure'] = array( '#markup' => l(t('configure'), - 'admin/structure/block/configure/' . $block['module'] . '/' . $block['delta']), + 'admin/structure/block/configure/' . $block['block_id']), ); if ($block['module'] == 'block') { $form[$key]['delete'] = array( @@ -179,32 +179,33 @@ function _block_compare($a, $b) { /** * Menu callback; displays the block configuration form. */ -function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { +function block_admin_configure(&$form_state, $block) { $form['module'] = array( '#type' => 'value', - '#value' => $module, + '#value' => $block->module, ); $form['delta'] = array( '#type' => 'value', - '#value' => $delta, + '#value' => $block->delta, ); - $edit = db_query("SELECT pages, visibility, custom, title FROM {block} WHERE module = :module AND delta = :delta", array( - ':module' => $module, - ':delta' => $delta, - ))->fetchAssoc(); + $form['block_id'] = array( + '#type' => 'value', + '#value' => (isset($block->block_id)) ? $block->block_id : '', + ); $form['block_settings'] = array( '#type' => 'fieldset', '#title' => t('Block specific settings'), '#collapsible' => TRUE, + '#weight' => field_attach_extra_weight($block->block_machine_name, 'block_settings'), ); $form['block_settings']['title'] = array( '#type' => 'textfield', '#title' => t('Block title'), '#maxlength' => 64, - '#description' => $module == 'block' ? t('The title of the block as shown to the user.') : t('Override the default title for the block. Use <none> to display no title, or leave blank to use the default block title.'), - '#default_value' => $edit['title'], + '#description' => $block->module == 'block' ? t('The title of the block as shown to the user.') : t('Override the default title for the block. Use <none> to display no title, or leave blank to use the default block title.'), + '#default_value' => (isset($block->title)) ? $block->title : '', '#weight' => -18, ); @@ -216,6 +217,7 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { '#collapsed' => TRUE, '#description' => t('Specify in which region this block is displayed.'), '#tree' => TRUE, + '#weight' => field_attach_extra_weight($block->block_machine_name, 'regions'), ); $theme_default = variable_get('theme_default', 'garland'); @@ -225,8 +227,8 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { // Only display enabled themes if ($theme->status) { $region = db_query("SELECT region FROM {block} WHERE module = :module AND delta = :delta AND theme = :theme", array( - ':module' => $module, - ':delta' => $delta, + ':module' => $block->module, + ':delta' => $block->delta, ':theme' => $theme_key, ))->fetchField(); @@ -242,16 +244,22 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { } // Module-specific block configurations. - if ($settings = module_invoke($module, 'block_configure', $delta)) { + if ($settings = module_invoke($block->module, 'block_configure', $block->delta)) { foreach ($settings as $k => $v) { $form['block_settings'][$k] = $v; } } // Get the block subject for the page title. - $info = module_invoke($module, 'block_info'); - if (isset($info[$delta])) { - drupal_set_title(t("'%name' block", array('%name' => $info[$delta]['info'])), PASS_THROUGH); + $info = module_invoke($block->module, 'block_info'); + if (isset($info[$block->delta])) { + drupal_set_title(t("'%name' block", array('%name' => $info[$block->delta]['info'])), PASS_THROUGH); + } + + // Attach fields. + if (isset($block->block_id)) { + field_attach_load('block', array($block->block_id => $block)); + field_attach_form('block', $block, $form, $form_state); } $form['page_vis_settings'] = array( @@ -259,13 +267,14 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { '#title' => t('Page specific visibility settings'), '#collapsible' => TRUE, '#collapsed' => TRUE, + '#weight' => field_attach_extra_weight($block->block_machine_name, 'page_vis_settings'), ); $access = user_access('use PHP for settings'); - if ($edit['visibility'] == 2 && !$access) { + if (isset($block->visibility) && $block->visibility == 2 && !$access) { $form['page_vis_settings'] = array(); $form['page_vis_settings']['visibility'] = array('#type' => 'value', '#value' => 2); - $form['page_vis_settings']['pages'] = array('#type' => 'value', '#value' => $edit['pages']); + $form['page_vis_settings']['pages'] = array('#type' => 'value', '#value' => (isset($block->pages)) ? $block->pages : ''); } else { $options = array(t('Every page except those specified below.'), t('Only the pages specified below.')); @@ -279,20 +288,20 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { '#type' => 'radios', '#title' => t('Show block on specific pages'), '#options' => $options, - '#default_value' => $edit['visibility'], + '#default_value' => (isset($block->visibility)) ? $block->visibility : '', ); $form['page_vis_settings']['pages'] = array( '#type' => 'textarea', '#title' => t('Pages'), - '#default_value' => $edit['pages'], + '#default_value' => (isset($block->pages)) ? $block->pages : '', '#description' => $description, ); } // Role-based visibility settings. $default_role_options = db_query("SELECT rid FROM {block_role} WHERE module = :module AND delta = :delta", array( - ':module' => $module, - ':delta' => $delta, + ':module' => $block->module, + ':delta' => $block->delta, ))->fetchCol(); $role_options = db_query('SELECT rid, name FROM {role} ORDER BY name')->fetchAllKeyed(); $form['role_vis_settings'] = array( @@ -300,6 +309,7 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { '#title' => t('Role specific visibility settings'), '#collapsible' => TRUE, '#collapsed' => TRUE, + '#weight' => field_attach_extra_weight($block->block_machine_name, 'role_vis_settings'), ); $form['role_vis_settings']['roles'] = array( '#type' => 'checkboxes', @@ -311,14 +321,15 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { // Content type specific configuration. $default_type_options = db_query("SELECT type FROM {block_node_type} WHERE module = :module AND delta = :delta", array( - ':module' => $module, - ':delta' => $delta, + ':module' => $block->module, + ':delta' => $block->delta, ))->fetchCol(); $form['content_type_vis_settings'] = array( '#type' => 'fieldset', '#title' => t('Content type specific visibility settings'), '#collapsible' => TRUE, '#collapsed' => TRUE, + '#weight' => field_attach_extra_weight($block->block_machine_name, 'content_type_vis_settings'), ); $form['content_type_vis_settings']['types'] = array( '#type' => 'checkboxes', @@ -334,6 +345,7 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { '#title' => t('User specific visibility settings'), '#collapsible' => TRUE, '#collapsed' => TRUE, + '#weight' => field_attach_extra_weight($block->block_machine_name, 'user_vis_settings'), ); $form['user_vis_settings']['custom'] = array( '#type' => 'radios', @@ -344,12 +356,13 @@ function block_admin_configure(&$form_state, $module = NULL, $delta = 0) { t('Hide this block by default but let individual users show it.') ), '#description' => t('Allow individual users to customize the visibility of this block in their account settings.'), - '#default_value' => $edit['custom'], + '#default_value' => (isset($block->custom)) ? $block->custom : '', ); $form['submit'] = array( '#type' => 'submit', '#value' => t('Save block'), + '#weight' => 99, ); return $form; @@ -365,10 +378,18 @@ function block_admin_configure_validate($form, &$form_state) { form_set_error('info', t('Please ensure that each block description is unique.')); } } + $block = (object) $form_state['values']; + $block->block_machine_name = $block->module . ':' . $block->delta; + field_attach_form_validate('block', $block, $form, $form_state); } function block_admin_configure_submit($form, &$form_state) { if (!form_get_errors()) { + $block = (object) $form_state['values']; + $block->block_machine_name = $block->module . ':' . $block->delta; + field_attach_submit('block', $block, $form, $form_state); + field_attach_presave('block', $block); + db_update('block') ->fields(array( 'visibility' => (int) $form_state['values']['visibility'], @@ -411,7 +432,7 @@ function block_admin_configure_submit($form, &$form_state) { // Store regions per theme for this block foreach ($form_state['values']['regions'] as $theme => $region) { db_merge('block') - ->key(array('theme' => $theme, 'delta' => $form_state['values']['delta'], 'module' => $form_state['values']['module'])) + ->key(array('block_id' => $block->block_id, 'theme' => $theme, 'delta' => $form_state['values']['delta'], 'module' => $form_state['values']['module'])) ->fields(array( 'region' => $region, 'pages' => trim($form_state['values']['pages']), @@ -420,6 +441,8 @@ function block_admin_configure_submit($form, &$form_state) { ->execute(); } + field_attach_update('block', $block); + module_invoke($form_state['values']['module'], 'block_save', $form_state['values']['delta'], $form_state['values']); drupal_set_message(t('The block configuration has been saved.')); cache_clear_all(); @@ -431,7 +454,23 @@ function block_admin_configure_submit($form, &$form_state) { * Menu callback: display the custom block addition form. */ function block_add_block_form(&$form_state) { - return block_admin_configure($form_state, 'block', NULL); + $block = array( + 'block_machine_name' => 'block_0', + 'module' => 'block', + 'delta' => 0 + ); + $form = block_admin_configure($form_state, (object) $block); + // When creating a new custom block the Field API bundle for the block and + // block_body field have not been created yet. Collect input for the + // block_body field here and place it in the new Field API field once it has + // been created. + $form['block_body'] = array( + '#type' => 'textarea', + '#title' => t('Block body'), + '#text_format' => FILTER_FORMAT_DEFAULT, + '#required' => TRUE, + ); + return $form; } function block_add_block_form_validate($form, &$form_state) { @@ -448,30 +487,30 @@ function block_add_block_form_validate($form, &$form_state) { function block_add_block_form_submit($form, &$form_state) { $delta = db_insert('block_custom') ->fields(array( - 'body' => $form_state['values']['body'], 'info' => $form_state['values']['info'], - 'format' => $form_state['values']['body_format'], )) ->execute(); - $query = db_insert('block')->fields(array('visibility', 'pages', 'custom', 'title', 'module', 'theme', 'status', 'weight', 'delta', 'cache')); + $block = array( + 'visibility' => (int) $form_state['values']['visibility'], + 'pages' => trim($form_state['values']['pages']), + 'custom' => (int) $form_state['values']['custom'], + 'title' => $form_state['values']['title'], + 'module' => $form_state['values']['module'], + 'status' => 0, + 'weight' => 0, + 'delta' => $delta, + 'cache' => DRUPAL_NO_CACHE, + ); + foreach (list_themes() as $key => $theme) { if ($theme->status) { - $query->values(array( - 'visibility' => (int) $form_state['values']['visibility'], - 'pages' => trim($form_state['values']['pages']), - 'custom' => (int) $form_state['values']['custom'], - 'title' => $form_state['values']['title'], - 'module' => $form_state['values']['module'], - 'theme' => $theme->name, - 'status' => 0, - 'weight' => 0, - 'delta' => $delta, - 'cache' => DRUPAL_NO_CACHE, - )); + // Make sure we are creating a new instance of the block for each theme. + unset($block['bid']); + $block['theme'] = $theme->name; + $block = block_save($block); } } - $query->execute(); $query = db_insert('block_role')->fields(array('rid', 'module', 'delta')); foreach (array_filter($form_state['values']['roles']) as $rid) { @@ -505,6 +544,41 @@ function block_add_block_form_submit($form, &$form_state) { ->execute(); } + // Create the 'block_body' field if it doesn't already exist. + $field = field_info_field('block_body'); + if (empty($field)) { + $field = array( + 'field_name' => 'block_body', + 'type' => 'text_long', + ); + field_create_field($field); + } + + // Attach an instance of the 'block_body' field to the new block bundle. + $instance = array( + 'field_name' => 'block_body', + 'bundle' => 'block_' . $delta, + 'label' => t('Block body'), + 'description' => t('The content of the block as shown to the user.'), + 'required' => TRUE, + 'settings' => array('text_processing' => 1), + 'widget' => array( + 'type' => 'text_textarea', + 'label' => t('Block body'), + ), + 'display' => array( + 'full' => array('label' => 'hidden'), + ), + ); + field_create_instance($instance); + + // Move the content from the temporary block_body field to the new Field API + // block_body field. + $block['block_machine_name'] = 'block:' . $delta; + $block['block_body'][FIELD_LANGUAGE_NONE][0]['value'] = $form_state['values']['block_body']; + $block['block_body'][FIELD_LANGUAGE_NONE][0]['format'] = $form_state['values']['block_body_format']; + field_attach_insert('block', (object) $block); + drupal_set_message(t('The block has been created.')); cache_clear_all(); $form_state['redirect'] = 'admin/structure/block'; diff --git modules/block/block.install modules/block/block.install index 7311d40..6c0f469 100644 --- modules/block/block.install +++ modules/block/block.install @@ -18,6 +18,12 @@ function block_schema() { 'not null' => TRUE, 'description' => 'Primary Key: Unique block ID.', ), + 'block_id' => array( + 'type' => 'int', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'Entity ID for block', + ), 'module' => array( 'type' => 'varchar', 'length' => 64, @@ -168,12 +174,6 @@ function block_schema() { 'not null' => TRUE, 'description' => "The block's {block}.bid.", ), - 'body' => array( - 'type' => 'text', - 'not null' => FALSE, - 'size' => 'big', - 'description' => 'Block contents.', - ), 'info' => array( 'type' => 'varchar', 'length' => 128, @@ -181,13 +181,6 @@ function block_schema() { 'default' => '', 'description' => 'Block description.', ), - 'format' => array( - 'type' => 'int', - 'size' => 'small', - 'not null' => TRUE, - 'default' => 0, - 'description' => "Block body's {filter_format}.format; for example, 1 = Filtered HTML.", - ) ), 'unique keys' => array( 'info' => array('info'), @@ -221,6 +214,7 @@ function block_install() { */ function block_uninstall() { drupal_uninstall_schema('block'); + variable_del('block_id_sequence'); } /** @@ -274,3 +268,91 @@ function block_update_7001() { db_create_table($ret, 'block_node_type', $schema['block_node_type']); return $ret; } + +/** + * Convert custom block body to a field. + */ +function block_update_7002() { + $ret = array(); + + // Add a block_id column that stores a theme independent entity ID for each + // block. + $block_id_field = array( + 'type' => 'int', + 'not null' => TRUE, + 'initial' => 0, + 'description' => 'Entity ID for block', + ); + + // Check that the field hasn't been updated in an aborted run of this + // update. + if (!db_column_exists('block', 'block_id')) { + // Add a new field for the block_id. + db_add_field($ret, 'block', 'block_id', $block_id_field); + } + + $blocks = db_query('SELECT * FROM {block}'); + $next_id = 1; + $updated_blocks = array(); + foreach ($blocks as $block) { + if (!in_array($block->module . '_' . $block->delta, $updated_blocks)) { + db_update('block') + ->fields(array('block_id' => $next_id)) + ->condition('module', $block->module) + ->condition('delta', $block->delta) + ->execute(); + $next_id++; + $updated_blocks[] = $block->module . '_' . $block->delta; + } + } + + // Create the 'block_body' field if it doesn't already exist. + $field = field_info_field('block_body'); + if (empty($field)) { + $field = array( + 'field_name' => 'block_body', + 'type' => 'text_long', + ); + field_create_field($field); + } + + // Attach an instance of the 'block_body' field to all custom blocks. + $boxes = db_query('SELECT bx.*, b.block_id FROM {box} bx INNER JOIN {block} b ON b.delta = bx.bid GROUP BY bx.bid'); + foreach ($boxes as $box) { + // Create a new bundle for the block + field_attach_create_bundle('block_' . $box->bid); + + $instance = array( + 'field_name' => 'block_body', + 'bundle' => 'block_' . $box->bid, + 'label' => t('Block body'), + 'description' => t('The content of the block as shown to the user.'), + 'required' => TRUE, + 'settings' => array('text_processing' => 1), + 'widget' => array( + 'type' => 'text_textarea', + 'label' => t('Block body'), + ), + 'display' => array( + 'full' => array('label' => 'hidden'), + ), + ); + field_create_instance($instance); + + // Move the block body to the new 'block_body' field. + $box->block_machine_name = 'block_' . $box->bid; + $box->block_body[FIELD_LANGUAGE_NONE][0]['value'] = $box->body; + unset($box->body); + $box->block_body[FIELD_LANGUAGE_NONE][0]['format'] = $box->format; + unset($box->format); + // This is a core update and no contrib modules are enabled yet, so we can + // assume default field storage for a faster update. + field_sql_storage_field_storage_write('block', $box, FIELD_STORAGE_INSERT, array()); + } + + // Remove the now-obsolete body info from box. + db_drop_field($ret, 'box', 'body'); + db_drop_field($ret, 'box', 'format'); + + return $ret; +} diff --git modules/block/block.module modules/block/block.module index 3ba83ce..051e3b4 100644 --- modules/block/block.module +++ modules/block/block.module @@ -18,7 +18,7 @@ function block_help($path, $arg) { switch ($path) { case 'admin/help#block': $output = '

' . t('Blocks are boxes of content rendered into an area, or region, of a web page. The default theme Garland, for example, implements the regions "left sidebar", "right sidebar", "content", "header", and "footer", and a block may appear in any one of these areas. The blocks administration page provides a drag-and-drop interface for assigning a block to a region, and for controlling the order of blocks within regions.', array('@blocks' => url('admin/structure/block'))) . '

'; - $output .= '

' . t('Although blocks are usually generated automatically by modules (like the User login block, for example), administrators can also define custom blocks. Custom blocks have a title, description, and body. The body of the block can be as long as necessary, and can contain content supported by any available text format.', array('@text-format' => url('admin/settings/filter'))) . '

'; + $output .= '

' . t('Although blocks are usually generated automatically by modules (like the User login block, for example), administrators can also define custom blocks. Custom blocks have a title, description, and a body field by default with the option to add additional fields. The body of the block can be as long as necessary, and can contain content supported by any available text format.', array('@text-format' => url('admin/settings/filter'))) . '

'; $output .= '

' . t('When working with blocks, remember that:') . '

'; $output .= '