'Instances', 'description' => t('Create and delete instances of blocks.'), 'page callback' => 'multiblock_general', 'access callback' => 'user_access', 'access arguments' => array('administer blocks'), 'type' => MENU_LOCAL_TASK, 'weight' => -1, ); $items['admin/build/block/instances/delete'] = array( 'title' => 'Delete Block Instance', 'page callback' => 'drupal_get_form', 'page arguments' => array('multiblock_delete_form'), 'access callback' => 'user_access', 'access arguments' => array('administer blocks'), 'type' => MENU_CALLBACK, ); return $items; } /** * Implementation of hook_block(). */ function multiblock_block($op = 'list', $delta = 0, $edit = array()) { if ($op == 'list') { // Get all of the block instances that exist. $blocks = multiblock_get_block(NULL); $list = array(); foreach ($blocks as $block) { // $list[$block->delta] = array('info' => check_plain($block->title)); $list[$block->delta] = array('info' => $block->title); } return $list; } // Any op besides list we want to dispatch the call to its respective module. else if ($op == 'view' || $op == 'configure' || $op == 'save') { return multiblock_call_block($delta, $op, $edit); } } /** * Fetch a given block from the multiblock database table. * * @param $delta * Optional. Retreive a single block based on this delta. If none specified, * all multiblock instances are returned. * @param $reset * Optional. Boolean value to reset the interal cache of this function. */ function multiblock_get_block($delta = NULL, $reset = FALSE) { static $blocks; if (!isset($blocks) || $reset) { $blocks = array(); $result = db_query("SELECT * FROM {multiblock}"); while ($row = db_fetch_object($result)) { $blocks[$row->delta] = $row; } } return is_numeric($delta) ? $blocks[$delta] : $blocks; } /** * Dispatch a hook_block call to it's respective module. Paramater $delta * is the new multiblock delta that we're using and $op is the op we are * dispatching. */ function multiblock_call_block($delta, $op, $edit) { $result = db_query("SELECT module, orig_delta, delta, multi_settings FROM {multiblock} WHERE delta='%s'", $delta); if ($block_info = db_fetch_object($result)) { // If this block is multiblock enabled, send it the delta of the block we're using. if ($block_info->multi_settings == 1 ) { $edit['multiblock_delta'] = array( '#type' => 'value', '#value' => $block_info->delta, ); } $block = module_invoke($block_info->module, 'block', $op, $block_info->orig_delta, $edit); // if ($op == 'view') { // $block['orig_module'] = $block_info->module; // $block['orig_delta'] = $block_info->orig_delta; // } return $block; } // No such multiblock, shouldn't ever happen. return; } /** * Page callback for the "Manage Block Instances page". */ function multiblock_general() { if (func_num_args() && func_get_arg(0) == 'edit' && is_numeric($instance = func_get_arg(1))) { $req_block = multiblock_get_block($instance); } // Fetch blocks directly from modules using block.module function. $blocks = _block_rehash(); // Sort blocks how we want them. usort($blocks, 'multiblock_block_sort'); // Fetch "Add Instance" form. if (isset($req_block)) { $form = drupal_get_form('multiblock_add_form', $blocks, $req_block); } else { $form = drupal_get_form('multiblock_add_form', $blocks); } // Get an array of existing blocks. $multiblocks = multiblock_get_block(NULL, TRUE); return theme('multiblock_general', $form, $multiblocks, isset($req_block)); } /** * "Add Instance" form. */ function multiblock_add_form(&$form_state, $blocks, $update = NULL) { $form = array(); $form['title'] = array( '#type' => 'textfield', '#title' => t('Instance Title'), '#maxlength' => 256, '#required' => TRUE, '#default_value' => ($update ? $update->title : NULL), ); if ($update) { $form['instance'] = array('#type' => 'value', '#value' => $update->delta); } else { // Turn $blocks into form options of block types. // Remember we need the module and delta to be able to tell what kind of // blocks we're talking about. $options = array(); foreach ($blocks as $block) { // Don't include multiblock module blocks in the list. if ($block['module'] != 'multiblock') { $options[$block['module'] .'***MB***'. $block['delta']] = $block['info']; } } $form['block'] = array( '#type' => 'select', '#title' => t('Block type'), '#options' => $options, '#required' => TRUE, ); } $form['submit'] = array( '#type' => 'submit', '#value' => t('Save'), ); return $form; } function multiblock_delete_form($form_state, $delta) { $block = multiblock_get_block($delta); if (empty($block)) { drupal_set_message(t('The multiblock with the delta @delta was not found.', array('@delta' => $delta)), 'error'); return array(); } $form['delta'] = array('#type' => 'value', '#value' => $delta); return confirm_form($form, t('Delete the block instance %title?', array('%title' => $block->title)), 'admin/build/block/instances', t('This will delete the instance of the block %title.', array('%title' => $block->title)), t('Delete'), t('Cancel')); } function multiblock_delete_form_submit($form, &$form_state) { if (multiblock_delete($form_state['values']['delta'])) { drupal_set_message(t('Block successfully deleted!')); } else { drupal_set_message(t('There was a problem deleting the block')); } $form_state['redirect'] = 'admin/build/block/instances'; } /** * Add a multiblock instance. * * @param $original_block * The original block for which an instance is being created. * @param $block_instance * An object contain information about the particular block instance. * @return * The delta of the newly added block. */ function multiblock_add($original_block, $block_instance) { // Create new delta for block instance. $sql = "INSERT INTO {multiblock} (title, module, orig_delta, multi_settings) VALUES ('%s', '%s', '%s', %d)"; $result = db_query($sql, $block_instance->title, $original_block->module, $original_block->delta, $block_instance->mb_enabled); return db_last_insert_id('multiblock', 'delta'); } /** * Delete a multiblock instance. */ function multiblock_delete($multiblock_delta) { $result = db_query('DELETE FROM {multiblock} WHERE delta = %d', (int)$multiblock_delta); if (ctype_digit($multiblock_delta) && db_affected_rows() == 1) { _block_rehash(); return TRUE; } else { return FALSE; } } /** * Validate "Add Block Instance" form. */ function multiblock_add_form_validate($form, &$form_state) { if (!isset($form_state['values']['instance'])) { // Make sure we are getting a valid block to add. if (!preg_match('/^.+\*\*\*MB\*\*\*.+$/', $form_state['values']['block'])) { form_set_error('block', t('Bad block module input, contact administrator')); return; } // Make sure the block and delta exist. $orig_block = multiblock_blockinfo_from_form($form_state['values']['block']); if (!module_hook($orig_block['module'], 'block') || !array_key_exists($orig_block['delta'], module_invoke($orig_block['module'], 'block', 'list'))) { form_set_error('block', t('Module or block doesn\'t exist, contact administrator')); } } } /** * Add block instance to database from "Add Block Instance" form. */ function multiblock_add_form_submit($form, &$form_state) { if (isset($form_state['values']['instance'])) { db_query("UPDATE {multiblock} SET title='%s' WHERE delta=%d", $form_state['values']['title'], $form_state['values']['instance']); $form_state['redirect'] = 'admin/build/block/instances'; return; } // Get the original block info. $orig_block = multiblock_blockinfo_from_form($form_state['values']['block']); // Check whether this module is multiblock enabled. $mb_enabled = (int) (module_invoke($orig_block['module'], 'block', 'mb_enabled') == 'mb_enabled'); // Create block instance information. $orig_block = (object) $orig_block; $instance = (object) array('title' => $form_state['values']['title'], 'mb_enabled' => $mb_enabled); // Add the block instance. multiblock_add($orig_block, $instance); drupal_set_message(t('Block instance %instance created.', array('%instance' => $form_state['values']['title']))); } /** * Custom sort based on info element of array. */ function multiblock_block_sort($a, $b) { return strcmp($a['info'], $b['info']); } /** * Get the module and delta from the "Add Block Instance" block form element. */ function multiblock_blockinfo_from_form($form_value) { $matches = array(); preg_match('/^(.+)\*\*\*MB\*\*\*(.+)$/', $form_value, $matches); return array('module' => $matches[1], 'delta' => $matches[2]); } /** * Get title of a block by its module and delta. */ function multiblock_get_block_title($module, $delta) { $block_info = module_invoke($module, 'block', 'list'); return $block_info[$delta]['info']; } /** * Implementation of hook_theme(). */ function multiblock_theme() { return array( 'multiblock_general' => array( 'arguments' => array('add_block_form' => NULL, 'multiblocks' => NULL), ), ); } /** * Theme function for the "Manage Block Instances" page. */ function theme_multiblock_general($add_block_form, $multiblocks, $edit = FALSE) { $output = ''; // $noyes = array('No', 'Yes'); $noyes = array('misc/watchdog-error.png', 'misc/watchdog-ok.png'); $output .= '

'. ($edit ? t('Edit Instance') : t('Add Instance')) .'

'. $add_block_form .'

'; $header = array(t('Title'), t('Original Block Title'), t('Original Module'), t('MultiBlock Enabled'), t('Original Delta'), t('Action')); foreach ($multiblocks as $row) { $ops_link = l(t('Edit'), 'admin/build/block/instances/edit/'. $row->delta) .' '. l(t('Delete'), 'admin/build/block/instances/delete/'. $row->delta); $title = multiblock_get_block_title($row->module, $row->orig_delta); $mb_enabled = $noyes[$row->multi_settings]; $alt = t('Not Multiblock enabled'); if ($row->multi_settings) { $alt = t('Multiblock enabled'); } $rows[] = array( check_plain($row->title), $title, $row->module, array('data' => theme('image', $mb_enabled, $alt, $alt), 'align' => 'center'), $row->orig_delta, $ops_link, ); } $output .= '

'. t('Manage Instances') .'

'. theme('table', $header, $rows) .'

'; return $output; }