diff --git boxes.admin.inc boxes.admin.inc index bda1d71..e666906 100644 --- boxes.admin.inc +++ boxes.admin.inc @@ -82,3 +82,30 @@ function theme_boxes_box($block) { $output .= ''; return $output; } + +/** + * Block/Box conversion confirmation form. + */ +function boxes_convert_form($form_state, $module, $delta) { + $form['module'] = array('#type' => 'hidden', '#value' => $module); + $form['delta'] = array('#type' => 'hidden', '#value' => $delta); + switch ($module) { + case 'block': + return confirm_form($form, t('Are you sure you want to convert this block to a box?'), 'admin/build/block', '', t('Convert'), t('Cancel')); + break; + case 'boxes': + return confirm_form($form, t('Are you sure you want to convert this box to a block?'), 'admin/build/block', '', t('Convert'), t('Cancel')); + break; + case 'default': + drupal_not_found(); + die(); + } +} + +/** + * Submit handler for boxes_convert_form + */ +function boxes_convert_form_submit($form, &$form_state) { + boxes_convert($form_state['values']['module'], $form_state['values']['delta']); + $form_state['redirect'] = 'admin/build/block'; +} diff --git boxes.module boxes.module index bc0c683..c51dc7e 100644 --- boxes.module +++ boxes.module @@ -28,6 +28,13 @@ function boxes_menu() { 'type' => MENU_CALLBACK, 'file' => 'boxes.admin.inc', ); + $items['boxes/convert/%/%'] = array( + 'page callback' => 'drupal_get_form', + 'page arguments' => array('boxes_convert_form', 2, 3), + 'access callback' => 'boxes_access_admin', + 'type' => MENU_CALLBACK, + 'file' => 'boxes.admin.inc', + ); return $items; } @@ -347,6 +354,13 @@ function boxes_form_block_admin_display_form_alter(&$form, $form_state) { } } } + // Add convert link. + if (($module == 'block' || $module == 'boxes') && strpos($delta, 'add__') !== 0) { + $module_opp = $module == 'block' ? 'box' : 'block'; + if (($module_opp == 'box' && $box->plugin_key == 'simple') || $module_opp == 'block') { + $form[$i]['configure']['#value'] .= ' | '. l(t('convert to @type', array('@type' => $module_opp)), 'boxes/convert/'. $module .'/'. $delta); + } + } } } @@ -542,3 +556,126 @@ function boxes_create_hash($identifier) { } return $hash; } + +/** + * Loader for blocks. + * + * @todo + * Might be a way to use one query instead of two. + */ +function boxes_load_blocks($delta) { + $query = db_query("SELECT boxes.body, boxes.info AS description, boxes.format FROM {boxes} WHERE boxes.bid = '%s'", $delta); + while ($box = db_fetch_object($query)) { + $boxes[$delta] = $box; + } + + $query = db_query("SELECT blocks.delta, blocks.title, blocks.bid FROM {blocks} WHERE blocks.module = 'block' AND blocks.delta = '%s'", $delta); + while ($block = db_fetch_object($query)) { + $blocks[$block->bid] = (object) array_merge((array) $block, (array) $boxes[$delta]); + } + + return $blocks; +} + +/** + * Converts blocks to boxes or boxes to blocks. + * + * @param $module + * String of the controlling module. + * @param $delta + * String of the delta for the block or box to convert. + */ +function boxes_convert($module, $delta) { + // Depending on what the module is we convert to the other. + switch ($module) { + case 'block': + // Load the block information. + $blocks = boxes_load_blocks($delta); + + // Remove {boxes} entry. + db_query("DELETE FROM {boxes} WHERE bid = %d", $delta); + + // Update the {blocks} entry. + ctools_include('cleanstring'); + foreach ($blocks as $block) { + // We have to update the delta because when a new block is created + // we will run into duplicate keys. + $block->delta = ctools_cleanstring( + $block->description . '-' . $delta, + array( + 'separator' => '', + 'lower case' => TRUE, + 'max length' => 32, // Size of blocks.delta. + ) + ); + $block->module = 'boxes'; + drupal_write_record('blocks', $block, 'bid'); + } + + // Update the {blocks_roles} entries (if any). + $query = db_query("SELECT rid FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta); + while ($result = db_fetch_object($query)) { + db_query("DELETE FROM {blocks_roles} WHERE module = '%s' AND delta = '%s' AND rid = %d", $module, $delta, $result->rid); + $record = array( + 'module' => 'boxes', + 'delta' => $block->delta, + 'rid' => $result->rid, + ); + drupal_write_record('blocks_roles', $record); + } + + // Create the {box} record. + $block->plugin_key = 'simple'; + $block->options = array('body' => $block->body, 'format' => $block->format); + unset($block->body); + unset($block->format); + unset($block->bid); + drupal_write_record('box', $block); + break; + + case 'boxes': + // Load the box information. + $box = boxes_load($delta); + + // We only handle the 'simple' box plugin. + if ($box->plugin_key == 'simple') { + // Create {boxes} entry. + // Bid is autoincremental here, so once we insert we need to make sure + // that all deltas match. Luckily drupal_write_record() makes this easy. + $boxes = new stdClass(); + $boxes->info = $box->description; + $boxes->body = $box->options['body']; + $boxes->format = $box->options['format']; + drupal_write_record('boxes', $boxes); + $new_delta = $boxes->bid; + + // Update the {blocks} entry. + $query = db_query("SELECT bid FROM {blocks} WHERE module = 'boxes' and delta = '%s'", $delta); + while ($blocks = db_fetch_object($query)) { + $blocks->module = 'block'; + $blocks->delta = $new_delta; + drupal_write_record('blocks', $blocks, 'bid'); + } + + // Update the {blocks_roles} entry (if any). + $query = db_query("SELECT rid FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta); + while ($result = db_fetch_object($query)) { + db_query("DELETE FROM {blocks_roles} WHERE module = '%s' AND delta = '%s'", $module, $delta); + $record = array( + 'module' => 'block', + 'delta' => $new_delta, + 'rid' => $result->rid, + ); + drupal_write_record('blocks_roles', $record); + } + + // Remove the {box} record. + db_query("DELETE FROM {box} WHERE delta = '%s'", $delta); + } + else { + drupal_set_message(t("We only handle boxes made with the 'simple' plugin.")); + } + break; + } +} +