For a while now I've had the problem of going into an existing site and, seeing a blatant abuse of the core block system; with custom blocks out the wazoo, needing to get these custom blocks into code. Ultimately it would be great to have a drush utility to simply export all of those blocks into code and get them out of the database. Following this line of thought I came to the boxes module and think this a very good solution for replacing the current block system. I'm sure you've found the difficulties in trying to export cor blocks and thus the reason for this module.

So in an effort to still solve my original problem, it would be really great if we could come up with a way to convert all of the existing custom blocks into boxes so that they are then exportable and can then be handled via features and stored accordingly.

Has there been any activity around converting blocks into boxes, or thoughts in general? I'd really love to know your thoughts on my proposed workflow here.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jmiccolis’s picture

Very early in the development of this module I had code that would transform all existing custom blocks in to boxes, but it got nixed simply because I didn't get around to working the workflow kinks out of it. I think a drush command would be brilliant. I had been doing it on install, but that made it impossible to turn the module off and still have access to your old blocks.

I'd be very happy to commit a drush command that kept the blocks in the database but changed them from blocks to boxes. That transformation itself should be pretty straightforward, just collect the body and format of the block, serialize that properly and save it to box.options and user `simple` as the box.plugin_key. You can probably get away with using the `info` property as the box.delta and box.description. So the only tricky part is the title.

Things to be aware of... The core block system stores the title with the visibility settings and not with the block's content. So some decision needs to be made in the case where a block is used with two themes and different titles. Also the old custom blocks should be deleted by the migration to boxes, but we'd probably want to confirm that with the user.

infojunkie’s picture

subscribe

sirkitree’s picture

Far from finished yet, but I got a little time to start in on this today. It's the basic conversion of putting things in the box table. More to come soon.

require_once './includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

DEFINE('BOX_TABLE', 'box'); //box module
DEFINE('BOXES_TABLE', 'boxes'); //block module
DEFINE('BLOCKS_TABLE', 'blocks'); //shared

/**
 * Conversion table.
 *
 * box.delta        => blocks.delta
 * box.plugin_key   => 'simple'
 * box.title        => blocks.title
 * box.description  => boxes.info
 * box.options      => serialize(boxes.body, boxes.format)
 */

// select all custom blocks
$sql = "SELECT boxes.body, boxes.info as description, boxes.format, blocks.delta, blocks.title
        FROM {blocks}
        INNER JOIN {boxes} ON boxes.bid = blocks.delta
        WHERE blocks.module = '%s'";
$query = db_query($sql, 'block');

while ($result = db_fetch_object($query)) {
  // create box record
  $record = (object) $result;
  $record->plugin_key = 'simple';
  $record->options = array('body' => $result->body, 'format' => $result->format);
  unset($record->body);
  unset($record->format);
  
  // save this $record into the box table
  drupal_write_record('box', $record);
}
jmiccolis’s picture

right on.

sirkitree’s picture

Getting back into this this week, wanted to write down a few more thoughts.

You mention having the old blocks available, but I think it would be more confusing to show both of these at the same time. Granted we could probably hide the blocks if they're duplicated, but if we provide a way to convert back and forth I don't see a need for this. This gives us flexibility and a way to revert.

So an extra link in the blocks ui that gives a conversion link on boxes: 'convert to block' and blocks: 'convert to box' (menu callback with a confirmation form). If this can be done on a one by one basis, we can simply update entries in the {blocks} and {blocks_roles} tables and just add or remove the entry in the {boxes} table.

sirkitree’s picture

Status: Active » Needs work
FileSize
5.32 KB

Alright, here's my first patch at this for now. It's working in the desired manner for the conversion from a block to a box. W00t!

Some things of note:

1) The convert link is appended to the configure link separated by | because it's hard to add an extra link in there due to the excessive theming of the block ui table. If you know an easy way please let me know.

2) Loader function for blocks (atypical).

3) One new menu callback item. The path is current 'boxes/convert/%/%', but it might make sense to create 'boxes/convert/%/%boxes' and 'boxes/convert/%/%boxes_block' - and make the loader mentioned in #2 an actual loader.

4) Uses ctools_cleanstring() to come up with a new delta based on the block desc + delta.

5) The conversion from boxes back to blocks still needs done.

6) Multiple theme considerations still need to be made.

sirkitree’s picture

Here's an updated patch. New in this patch:
1) Properly formatted comments
2) Working box to block conversion

Next I'll be testing multiple theme settings per block/box conversion.

Also still needed is how to deal with converting boxes that are exported.

sirkitree’s picture

Interesting note here: the core block system doesn't actually save the title per theme until you actually switch to that other theme and then go to the /admin/build/block/configure form (which actually does not load the correct row's title value for that theme). Upon changing the title and saving the form it actually updates both entries, for each theme to this new value.

This all leads me to the conclusion that upon conversion of a block to a box we can simply update any and all entries for that module/delta combination and not really worry about title's per theme since saving them updates both anyway in core.

sirkitree’s picture

Status: Needs work » Needs review
FileSize
7.15 KB

Update patch. New in this patch:
1) Working conversion from blocks to boxes and back to blocks with multiple theme settings.

Still to test:
1) How this reacts with exported blocks.

sirkitree’s picture

Ok, so this acted as I expected. If you have a box exported to code, say in a feature, and you revert this box through the block UI and then try to convert that box to a block (whew!) your box stay there, defined in code, and a new copy of this box is created - basically cloning the box that is in code into a new block. Kinda cool - but I'm not sure how desirable this is.

sirkitree’s picture

Actually thinking about this I think it is desirable - if you want to move away from boxes, and all of your boxes are in code, you have a convenient way of turning them all back into blocks and then turning off boxes module.

Next up: #805584: drush integration for conversion and export
$ drush boxes-convert [optional-block-delta]
$ drush boxes-export [optional-block-delta]

(creating a new thread for this)

sirkitree’s picture

So now that i've done all this work, I find http://drupal.org/project/features_extra which has exportable blocks and block settings.

sirkitree’s picture

After reviewing the above module today, converting to boxes is still much better. That module can export blocks alright, but you can never really 'read' a block from code. This means if you update a block locally, update your feature, and push that to your server, the block is still reading from the db, and must be deleted. Once you delete the box, you can revert the feature and it will reinsert the block. However, this new block that is created has a different id because block module uses an auto-increment field (stupid block module again) which then invalidates what your context is pointing to.

SO! Lesson here is if you have old blocks, convert them to boxes so you can read them from code.

However, the features_extra module is good for block settings - even boxes have block settings, and to get these into code you can use the fe_block module, specifically the block setting exports.

q0rban’s picture

subscribe

greg.harvey’s picture

This is awesome! Got a site I'm working on at the moment and I want to move the blocks to boxes. Not sure when I'll get a chance/budget to do it, but I will be reviewing this patch as soon as I get the green light. This is *exactly* what I'll need! =)

steveparks’s picture

subscribe. great idea

galooph’s picture

Looks really handy!

jmiccolis’s picture

Status: Needs review » Needs work

@sirkitree, great patch. One minor thing, you'll want to check that a box uses the 'simple' plugin before presenting a link, and probably check again before actually trying to do the transformation.

I am a little wary about showing these links on all boxes and blocks, but I guess have a confirm for is probably protection enough.

sirkitree’s picture

Status: Needs work » Needs review
FileSize
7.54 KB

Sure thing! I added in a check for the link and a double check before conversion just for safe measure.

jmiccolis’s picture

Status: Needs review » Needs work

So one small thing, one question;

Small thing

When you calculate the new block delta during the block->box conversion, it's seems quite possible that the newly crafted delta will get truncated when it gets inserted into the database. `boxes.info` can be 128 chars, but `blocks.delta` can only be 32. So we should probably do some truncation in here...

$block->delta = ctools_cleanstring($block->description .'_'. $delta);

Question

Should we roll this into a submodule so you can disable it and prevent reckless clients/administrators from messing about?

boran’s picture

+1

wizonesolutions’s picture

Looks like this is really close to fruition. I can't wait for this either...I'm starting to move a site to Features and finding myself doing this. Fortunately it's not too hard for a couple blocks by hand...but this'd be cool.

halcyonCorsair’s picture

Subscribing.

Looks like this could do with some serious work on the interface side of things.

mlncn’s picture

Status: Needs work » Needs review
FileSize
6.64 KB

Re-rolled (it no longer applied), and truncated $block->delta to 32 characters (using ctools_cleanstring()'s options; also set to lowercase and removed unknown characters rather than replacing them with a dash).

benjamin, agaric

kate’s picture

Should there be a link that says "convert" next to the 'configure' and 'delete' links that appear on the main blocks listing page? If so, then I cannot see the link. So I don't know how to convert a block to a box.

I am using Boxes version 6.x-1.0-beta11 and Ctools version 6.x-1.7

jwilson3’s picture

Subscribing.

achton’s picture

Subscribing.

jmiccolis’s picture

Status: Needs review » Needs work

I'm also missing the convert link as reported in comment 25. It seems like the link is getting added to the form array, so there must be something in the form themeing that needs addressing.

Also, I'm not particularly fond of the boxes_load_blocks() method. As the todo indicates in the code it uses two queries for what can be one and then does some funky cast-as-array-merge-cast-back-into-object stuff. I think this can just go away if we do something like;

SELECT bx.body, bx.info AS descriptions, bx.format, blk.title, blk.bid
FROM boxes bx JOIN blocks blk ON bx.bid = blk.delta AND blk.module = 'block'
WHERE bx.delta = '%s'
mbria’s picture

Subscribing.

cluke009’s picture

Not sure why this isn't displaying but I was able figure out the convert url from the module code.

Say your block url is "/admin/build/block/configure/block/15" the convert url would be "/boxes/convert/block/15"

// The offending function is at Line 379 of the patched boxes.module 6.x-1.0.
// 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);        
  }
}
cluke009’s picture

This feels hacky but maybe thats only because I don't fully understand all the code. The $module and $delta variables weren't returning any value because they weren't set within the scope of the statement. Preventing the link from showing and linking correctly.

/** 
 * The offending function is at Line 379 of the patched boxes.module 6.x-1.0.
 */
// 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);       
  }
}

/** 
 * Replace above code with this
 */
// Add convert link.
$module = $form[$i]['module']['#value'];
if (($module == 'block' || $module == 'boxes') && strpos($delta, 'add__') !== 0) {
  $module_opp = $module == 'block' ? 'box' : 'block';
  $delta = $form[$i]['delta']['#value'];
  $form[$i]['configure']['#value'] .= ' | '. l(t('convert to @type', array('@type' => $module_opp)), 'boxes/convert/'. $module .'/'. $delta);        
}

Someone more familiar with this module should have a look at this and reup the patch.

I tested it on my dev box and everything seems to be in order now.

cluke009’s picture

Status: Needs work » Needs review
girishmuraly’s picture

Just a thought while this ticket is still open - it would be good to be able to make it a two way street - by being able to convert from boxes to blocks as well, so users are not stuck later for whatsoever reason.

Anonymous’s picture

Any chance this can be ported for 7.x-1.x-dev?

emptyvoid’s picture

Too bad this never made it into 7.x branch.

Does any documentation exist for writing bridge modules between one block module and boxes?

I am using menu blocks in my contexts, but any time I attempt to place content or even edit a context using context field only box "blocks" remain while all menu block "blocks" are automatically removed from the context.