Extending a block

Permalink
Hi,

I'm new to concrete5 and trying to understand some of the aspects in terms of extensibility.

I'd like to be able to extend an existent block with the minimum extra code, i.e. without the need to either copy the code from the orginal block or create code to do what the code is already doing plus my own code.

As an example, I'd like to add a 'content' block to an 'image' block plus a caption text (it's just an example and it probably does not make sense).
In order to do this I imagine I need a text field in the db.xml to store the caption and then modify or extend the add/edit/view.php files to show the two extra fields/blocks.
Now... I learned that with templates I could extend the way the block is shown, so that's probably clear to me, but how do I extend the add/edit behaviour of the base block? What would be the way or the best way to do it?

Thanks in advance!
Cheers!

 
jordanlev replied on at Permalink Reply
jordanlev
I've just built a tool that does this exact thing. I will be submitting it to the marketplace in a day or two (and it will take a few days at least to go through the approval process), but in the meantime you can get it from here:
https://github.com/jordanlev/c5_designer_content...

(scroll down to the bottom of that page to see installation instructions)

-Jordan
TheRealSean replied on at Permalink Reply
TheRealSean
Without detracting from Jordan's block which is very good, for creating your own custom block.

There is the market place a Free addon called "Content around Image"
which sounds like it will do what you want(at least in your example)
http://www.concrete5.org/marketplace/addons/content-around-image/...

Ie Content Block with an image floated left|right with an option for a link and caption on the image.

But if you get this also take a look at Jordanlev's block as this is a great custom block creator

-Sean
bochaco replied on at Permalink Reply
Thanks Jordan and Sean, I'll definetly take a look at the blocks you mentioned.

Nevertheless I was thinking in terms of c5 framework, i mean without the need of copying code from a block to create a new one instead of just extending it, so if the original block gets updated the block I created won't get the updates.

Thanks!
jordanlev replied on at Permalink Reply
jordanlev
I understand where you're coming from with the concern for pulling in core updates over time, but I think in this case while it makes sense from afar, it doesn't make sense up close when you look at the details.

First of all, the content and image blocks have been around forever and haven't changed in a long time, and probably never will. Even if they did, what incredible feature could they possible add that would be so great that you wouldn't want to use your custom blocks anymore?
Also, even if you do customize the existing blocks, it's more than likely you'll still need to modify your code to work with the updates, so that wouldn't really be any better than modifying the code of your custom blocks to add the updated feature (as an aside, when people talk about extending core features safely like C5 lets you do, it doesn't mean that your extensions will automatically get new features as they're rolled out, rather it means that your site won't stop working when the update happens -- which is hugely valuable, but they'll keep working "the old way", not start working the new way).

Lastly, having gone through the process of building my own custom blocks like you're talking about, and then extrapolating that out into the block generator (that "Designer Content" thing I linked to above), I learned that there are a lot of bugs or oversights in the core C5 code that prevent you from including an image control on the same form as the TinyMCE/WYSIWYG editor (same goes for "link to page" controls, btw). I spent a good amount of time smoothing those over so that my block generator works as it should, and trust me it's not something you're going to want to waste your time on. Hopefully I can roll those fixes into the core for future updates, but who knows how far into the future that will be.

Anyway, like I said, I totally appreciate where you're coming from on this, and if you're interested in using this as a learning exercise to get better at programming C5 blocks, then totally you should go for it. But if you're just looking for the most practical solution to your problem, take it from someone who has been there many times over: it is probably not going to be worth the effort to do it yourself.

-Jordan
bochaco replied on at Permalink Reply
Thanks a lot Jordan for your detailed reply.

It's not that I want to do it in the way I was explaining, just that I thought that would be the best way since I'd been extending instead of 'copying and pasting' code (and kinda duplicating code if you will). I understand what you are saying and I can see that the new block should be what I need.

I'm looking for the best practical solution but without loosing maintainability of the blocks/code.

Thanks a lot again!
jordanlev replied on at Permalink Reply
jordanlev
I forgot to mention that this "extending the core" concept only really applies to custom templates -- there is no simple way to extend the functionality, add fields, etc. to the core blocks. (There are convoluted ways to do it but they don't really give you the benefit of maintainable/upgradable code that you're looking for).

And to step back a little bit, these kinds of blocks you're talking about are relatively simple (with the exception of those problems I mentioned of getting TinyMCE and image control to play nice together). So in terms of maintainability, we're not really talking about adding any significant complexity. This is one of the benefits of C5's blocks architecture -- everything is isolated and modularized into small pieces, so even if you have gnarly code, it's so small that it's still easy to go in and figure out.


-Jordan

PS: don't take my comments the wrong way -- I am always happy to see other coders on here talking about things like this. Some programmers are *too* practical and write horrible sloppy code just to get something out the door, so I want to assure you that what I'm suggesting is not because I don't believe in elegant architecture, but rather I have personally found it to be the best balance of practical solution vs. architectural elegance (within the context of C5's ecosystem).
bochaco replied on at Permalink Reply
I perfectly unhderstand your point.

Thanks!
TheRealSean replied on at Permalink Reply
TheRealSean
You could use custom blocks to pull in other blocks,

I tend to create blocks to cherry pick the bits I need when including a block, but you could (at least I think pull in a block from another block)

I normally do this from the dashboard though. But in theory you could do something like this from the block level,

$bt = BlockType::getByHandle('slideshow');
      $bt->controller->fsID = 3; # ID of the fileset to use
      $bt->controller->playback = 'RANDOM';
      $bt->controller->duration = 15;                    
      $bt->controller->fadeDuration = 4;                    
      $bt->controller->__construct($bt);
      $bt->render('view'); //or $bt->render('templates/custom-view');


I have no idea if this would work though? sorry Im thinking out loud here, if I where to be adding this I would do it from the dashboard so would be doing it at the page level, ie
$data = array('fsID' => $fsID, 'playback' => 'RANDOM','duration' => 15, 'fadeDuration' => 4);
$page->addBlock($bt, 'Main',$data);


But this goes back to the Adding the Blocks to the page, but this way you can group the block into a single page on the dashboard and add everything in one go including the use of custom templates to extend the layout of the default blocks

ps, I am afraid I am one of those sloppy code writers :S, Im still very much cutting my teeth with concrete and know a lot of the stuff I am writing could be done much cleaner and quicker if done by a more experienced coder but Im getting there.
jordanlev replied on at Permalink Reply
jordanlev
Not sure I understand what you're doing here -- does this allow the user to edit the content of those blocks you're pulling in?
TheRealSean replied on at Permalink Reply
TheRealSean
I am attempting to build on an existing blocks, I believe you could allow the user to edit those blocks within a custom template. Then pull in various blocks. (not in the default content block)

so in theory,
$bt = BlockType::getByHandle('slideshow');
      $bt->controller->fsID = $fsID;
      $bt->controller->playback = $playback;
      $bt->controller->duration = $duration;                    
      $bt->controller->fadeDuration = $fDuration;                    
      $bt->controller->__construct($bt);
print "<div class='slideshow'>";
      $bt->render('view'); //or $bt->render('templates/custom-view');
print "</div>";
print "<div class='content'>"
print $controller->getContent();
print "</div>"


Should then render A slideshow block within the custom content template with fileset 3 and then display with options passed through to it??

The example is only a simple hardcoded method but in theory could be replaced with variables placed in a custom block.

I was saving the variables within a page attribute, for a gallery page I created and then passing the variables through to your sortable fancy box package.

I do it from the dashboard so add to the page in areas,
$bt = BlockType::getByHandle('content');
$data = array(
$content = $_POST['Body']);
$p->addBlock($bt, 'Main', $data);
$bt = BlockType::getByHandle('slider');
$slideData = array('fsID' => $_POST['fsID'], 'playback' => $RANDOM,'duration' => $duration, 'fadeDuration' => $fDuration);
$p->addBlock($bt, 'Main', $slideData);
       $block = $p->getBlocks('Main');
      foreach($block as $b) {
         if($b->getBlockTypeHandle()=='content'){
            $b->setCustomTemplate('customTemplate');
         }
if($b->getBlockTypeHandle()=='slider'){
            $b->setCustomTemplate('customTemplate2');
         }


I can not do anything that is not done within the controller though(unless you can include your own controllers within the template?), just pass through the variables I would like as default.
jordanlev replied on at Permalink Reply
jordanlev
That is some crazy jujitsu -- I had no idea that was possible!

-Jordan