Open Source Content Management System

mRFC 0026: On-Site Toolbar Management for MidCOM 2.6+

  1. Requirements
    1. What should be managed?
    2. page vs. object toolbars
    3. Context sensitivity aka "dynamic load support"
  2. Proposed API
    1. The toolbars Service
    2. The toolbar classes
    3. Request API integration
  3. Open questions / TODOs

This mRFC is a part of the on-site administration integration process. Its goal is to outline a centralized way to create and handle toolbars displayed on-site.

Implementation Note: The page toolbar has been renamed to the view toolbar (I didn't have the mRFC at hand during my holiday, sorry ;-)).

Requirements

As a part of the on-site adminitration work, it is important to provide the user with an unified way to manage the objects being displayed. The currently used midcom_helper_toolbars is a good start here, but fails to meet a few requirements if it should go into the MidCOM core.

This document will give a complete overview about the required functionality.

What should be managed?

There are several "levels" on which objects should be managed. Generally speaking, there is a node, page and object level. This distinction is based on the scope of the operation being done:

  • Node operations affect the whole topic. They are not bound to a specific article, leaf or similar, more specific structure. Stuff like "Create new article" will go into this toolbar. Also, which is an important thing, this part of operations will always be open to the MidCOM core to add topic management operations to the system (given the right permissions apply). This represents the original "top" AIS toolbar.
  • Page operations affect the main object shown in the current output page. What the main object is, is largely dependant on the component. The newsticker frontpage, for example, does not have a single main object, while the taviewer does have a sinlge "standard" article on the frontpage. This especially means, that under normal circumstances only a component can reliably add information to this toolbar. Stuff like "Edit object" will go into this toolbar. This represents the original "lower" AIS toolbar.
  • Object operations are special toolbars which apply only to a single object being displayed in the current page. If you take cases like the original net.siriux.photos AIS interface you will see that a single page has several objects displayed simultaneously each with its own toolbar. The newsticker could in theory provide a similar functionality. The information in this toolbar always affects exactly a single object, and it is possible to have more then one object toolbar visible at the same time.

This gives us essentially two toolbars which are always present (node and page) and from which we always have exactly one instance per context (see below for context-related problems).In addition we have a variable number of the third kind of toolbars that might be used depending on the component.

page vs. object toolbars

As you might have already seen, page and object toolbars will have many things in common in most cases. Only compontens managing large counts of objects (like net.siriux.photos) will have real use for object toolbars.

For all other cases it makes sense to have a page toolbar which is actually bound to an object thus eliminating the distinction between these two kinds of toolbars.

You might now ask why I'm bothering for this distinction at all if it is really that specific: This is relativly simple: The toolbar system has to be built in a way so that the MidCOM core can add operations to the toolbars.

MidCOM only knows two levels of objects: First, there are the topics, also known as Nodes. They are the main (and only) container element known on the Core level and thus need their own toolbar operations (which is undisputed).

Then, as next level, MidCOM knows only objects, nothing more. In the original design, this was bound to the nap leaves. MidCOM was bound to have an individual leaf for each object. Not only for performance reasons, this link has been removed in 2.5 entirely. Nowadays there are many compontents which do have a broad range of management "possibilities", and active objects are a rather flexible term.

Nevertheless there needs to be a way for MidCOM to add commands applicable to a single object only. This is interesting for stuff like Metadata or permission management for example.

The new toolbar system thus has to cover both cases.

The proposed way to do this is to a) give the page toolbar the optional ability to bind to an object and to b) allow a component author to create an arbitary number of object toolbars independant of the page toolbar.

Context sensitivity aka "dynamic load support"

The MidCOM dynamic load ("dl") facility introduces quite a few complicaitons into this, as it blurs the idea of a single toolbar for a page quite a bit.

If you do not respect contexts, what can happen is a dl'ed subrequest can add its own toolbar options to the toolbars actually created for the main request. (Which can have really funny effects if you have, say, 10 dls on a single page.)

The original implementation in midcom_helper_toolbars is not safe in this respect.

Proposed API

Even though the current midcom_helper_toolbars could be easily adapted to fix the dl problem, I propose to create a new implementation in the midcom_services hirarchy. (We are talking about around 50 lines of code + docs, so this is not that much of an issue.)

This will ease transition to the new system asquite some components are out there still using the old class. Replacing them could have interesting side effects. These components will need some additional changes anyway as the toolbar api will be extended a bit to accomodate the idea of object-specific toolbars.

The toolbars Service

What I propose is having a midcom_services_toolbars available as $_MIDCOM->toolbars which serves as a central proxy for all toolbar related operations.

Basic API draft:

class midcom_services_toolbars
{
    midcom_helper_toolbar_node & get_node_toolbar($context = $current_context);
    midcom_helper_toolbar_page & get_page_toolbar($context = $current_context);

    midcom_helper_toolbar_object create_object_toolbar(&object);

    string render_node_toolbar($context = $current_context);
    string render_page_toolbar($context = $current_context);
}

Due to the context sensitivity, it is currently not possible to provide direct references to the object and page toolbar instances; there is no context switching notification to any service in the current core (and it won't be added before the page-transition for reasons not important here right now).

The getters will default to the currently active context, which is useful if you need to add site-local stuff into it.

// some site style element
$toolbar =& $_MIDCOM->get_node_toolbar();
$toolbar->do_something($tm);

Rendering though is even easier:

// some site style element
$_MIDCOM->toolbars->render_node_toolbar();

You will usually only render the current context's toolbars. The $context option should be considered reversed for core usage.

Note, that the render call will automatically add the neccessary CSS classes if neccessary.

The toolbar classes

All toolbar instances used will derive from midcom_helper_toolbar.

The code of this class needs to be cleaned up a bit, especially to allow easier default usage. Instead of the current

$toolbar->add_item(Array(
    MIDCOM_TOOLBAR_URL => $data['delete_url'],
    MIDCOM_TOOLBAR_LABEL => $data['l10n_midcom']->get('delete'),
    MIDCOM_TOOLBAR_HELPTEXT => null,
    MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/trash.png',
    MIDCOM_TOOLBAR_ENABLED => true,
));

the class should automatically apply the defaults:

$toolbar->add_item(Array(
    MIDCOM_TOOLBAR_URL => $data['delete_url'],
    MIDCOM_TOOLBAR_LABEL => $data['l10n_midcom']->get('delete'),
    MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/trash.png',
));

Apart from this the page toolbar must have at least one special interface function:

class midcom_helper_toolbar_page extends midcom_helper_toolbar
{
    void bind_to_object(&$object);
}

The bind_to_object call essentially does add the object toolbar specific options to the given page toolbar. This is for the very common use-case where there is just a single object per page.

Depending on the implementation itself, other private helpers and public convenience methods will be added, of course.

Request API integration

The request base class will import references to the toolbars of the current context into private memebers, which will be propagated into handler classes as well.

class midcom_baseclasses_components_request ...
{
    var $_node_toolbar;
    var $_page_toolbar;

    ...

    function initialize(...)
    {
        ...
        $this->_node_toolbar =& $_MIDCOM->toolbars->get_node_toolbar();
        $this->_page_toolbar =& $_MIDCOM->toolbars->get_page_toolbar();

        ...
    }
}

This will be done not only for convenience but also to protect the average user from missing the reference-assignment neccessary.

Open questions / TODOs

  • Should the toolbar classes be moved into the services hirarchy as well? Example: midcom_helper_toolbars_toolbar instead of midcom_helper_toolbar That way all code would be in the same place using the same convention most new services employ. Typing shouldn't be an issue, as all toolbars are created using the toolbars service factory methods.

  • There is urgent need for beautification of these toolbars, especially various styles would be good. Some advanced menu style could be of help.

  • Multi-level toolbars (in conjunciton with a dropdown menu style) would be useful as well.

  • The browser-driven tooltips should be replaced by some Overlib driven tooltip to work around the limitations of the browsers when rendering the tooltips (and thus also allowing HTML there).

Back

Designed by Nemein, hosted by Anykey