What is MidCOM? Why bother and how to customize it? Read further to find about flexibility of modern approach to web development.
MidCOM is an Open Source LGPL based CMS framework based on Midgard Content Management Framework. MidCOM provides a firm and flexible platform for making CMS driven websites. There is no need to talk about all details described at its website. What is worth talking about is a way to invent or reorganizing MidCOM to tailor your needs.
Case: "We want be able to rotate pictures uploaded as article attachements"
While working on a website for my customer I was quite frequently stepping on mines that were placed in a project documentation. One of them was a simple feature of rotating uploaded images. The point was that 'image' datamanager type, however allows to define image processing chain in data schema lacked the possibility of editing already uploaded images. Since editor are not techies, sometimes rotating and scaling images is a job too big. That's why I decided to modify normal behavior of DM image type & widget.
First I had to find code responsible for displaying image in a DM form. It, of course was living in /midcom/helper/datamanager2/widget/image.php file. There I found the way it is being rendered. Then, I placed a bti of HTML code for rotate options:
$static_html = "<br clear='left' />".$this->_l10n->get('type image: actions') . ":\n";
$static_html .= "<ul class='midcom_helper_datamanager2_widget_image_rotate'>";
$static_html .= "<li title='".$this->_l10n->get('rotate left')."'>";
$static_html .= "<input type='image' name='{$this->name}_rotate[left]' src='".MIDCOM_STATIC_URL."/stock-icons/16x16/rotate_ccw.png' /></li>\n";
$static_html .= "<li title='".$this->_l10n->get('rotate right')."'>";
$static_html .= "<input type='image' name='{$this->name}_rotate[right]' src='".MIDCOM_STATIC_URL."/stock-icons/16x16/rotate_cw.png' /></li>\n";
$static_html .= "</ul>\n";
$elements[] =& HTML_QuickForm::createElement('static', "{$this->name}_rotate", '', $static_html);
to add rotate action to a widget. Why did I placed plain HTML code for inputs instead of QF elemets? I didn't want them to be rendered in a same way as other DM from elements. At this point I didn't know how to make DM do desired actions, so I just saved changes and moved to on_submit method to add hooks for rotation:
if (array_key_exists("{$this->name}_rotate", $results))
{
if (! $this->_type->rotate($results["{$this->name}_rotate"]))
{
debug_push_class(__CLASS__, __FUNCTION__);
debug_add("Failed to rotate image on the field {$this->name}.", MIDCOM_LOG_ERROR);
debug_pop();
}
}
And that seemed to be all on widget side - next part is type processing. If we already got saved attachment and all data stored in Midgard, we fortunately don't need to make too many moves: just open file handler and make a working copy, then run some filtering (rotate) and update attachment blob stored on a file system. In the end we need to update Midgard's data about image sizes etc.:
function rotate($type)
{
$dir = ($type=="left")?270:90;
require_once(MIDCOM_ROOT . '/midcom/helper/imagefilter.php');
$this->_filter = new midcom_helper_imagefilter();
foreach($this->attachments as $identifier => $image)
{
if ($identifier == 'original') continue;
$tmpname = tempnam($GLOBALS['midcom_config']['midcom_tempdir'], "midcom_helper_datamanager2_type_image");
$src = mgd_open_attachment($image->id,'r');
$dst = fopen($tmpname, 'w+');
while (! feof($src))
{
$buffer = fread($src, 131072); /* 128 kB */
fwrite($dst, $buffer, 131072);
}
fclose($src);
fclose($dst);
$this->_filter->set_file($tmpname);
$this->_filter->process_chain("rotate({$dir})");
$dst = fopen($tmpname, 'r');
$image->copy_from_handle($dst);
$image->update();
$this->_set_image_size($identifier,$tmpname);
$this->_update_attachment_info($identifier);
fclose($dst);
@unlink($tmpname);
}
return true;
}
This is a very rough example without debugging and bulletproofing, but is clear enough to show how easy it is to customize internal MidCOM operations. All you need is a bunch of hours to scan thru the code and since it is quite modular you'll find it easy to change :)