<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="FeedCreator 1.7.6(BH)" -->
<rss version="0.91">
    <channel xmlns:g="http://base.google.com/ns/1.0">
        <title>Midgard RFCs</title>
        <description></description>
        <link>http://www.midgard-project.org/development/mrfc/</link>
        <lastBuildDate>Sun, 06 Jul 2008 00:32:55 +0000</lastBuildDate>
        <generator>FeedCreator 1.7.6(BH)</generator>
        <language>en</language>
        <item>
            <title>Midgard D-Bus identifiers</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0038.html</link>
            <description>
&lt;h1&gt;Revision history&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;2008-04-30, created by Piotr Pokora&lt;/li&gt;
&lt;li&gt;2008-05-26, clarified message content ( Piotr Pokora )&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Background&lt;/h1&gt;

&lt;p&gt;As D-Bus allows to create self, freely defined paths for objects, it might be confusing to send messages to other objects without any knowledge about their particular paths. This document defines D-Bus messages and objects' paths, at which instances has been created.&lt;/p&gt;

&lt;p&gt;'midgard_article' class name is used in every example below.&lt;/p&gt;

&lt;h1&gt;Main Bus name&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;org.midgardproject&lt;/strong&gt; - the main Midgard D-Bus service name &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;/org/midgardproject&lt;/strong&gt; - the main Midgard D-Bus service path&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Services&lt;/h1&gt;

&lt;p&gt;Services objects can be created by any application as long as they conform to this mRFC.&lt;/p&gt;

&lt;h1&gt;Clients&lt;/h1&gt;

&lt;p&gt;Clients objects can be created by any application as long as they conform to this mRFC.
For asynchronous massages, Midgard API shall provide automatic messages for main I/0 operations.&lt;/p&gt;

&lt;h1&gt;Database identifier&lt;/h1&gt;

&lt;p&gt;To limit possible collisions and provide clear and safe services' and clients' identifiers, Midgard configuration name is appended to main service's path. Midgard API implementation should not require to append this name by application, and path with configuration name should be created automatically.&lt;/p&gt;

&lt;p&gt;For example, if application has been initialized with default 'midgard' configuration, the base path for services and clients shall look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/org/midgardproject/midgard
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Of course for configuration named 'myconfig', the base path shall look like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/org/midgardproject/myconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Midgard application should not be aware of configuration name as both service and client will be created for the same base path. Midgard API for D-Bus should require only module or class names.&lt;/p&gt;

&lt;h1&gt;Module or class identifier&lt;/h1&gt;

&lt;p&gt;Services' paths should be created with classes' names, and if possible with module's or feature's names to separate services objects. For example all user defined MgdSchema classes should be created for 'MgdSchema' path. Class method should be appended to path to finally identify service's name.&lt;/p&gt;

&lt;p&gt;This document must define clear path's method name, if class' real method name can not be appended to path or any other name suits better.&lt;/p&gt;

&lt;h2&gt;MgdSchema&lt;/h2&gt;

&lt;p&gt;Services for MgdSchema should be created at path with following tokens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mgdschema&lt;/li&gt;
&lt;li&gt;class name&lt;/li&gt;
&lt;li&gt;method name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every mgdschema class' service or client shall be initialized with the same convention.&lt;/p&gt;

&lt;h3&gt;Create&lt;/h3&gt;

&lt;p&gt;'create' shall be appended to object's path.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/mgdschema/midgard_article/create
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On success, Midgard API shall send asynchronous message to object at path.&lt;/p&gt;

&lt;h3&gt;Update&lt;/h3&gt;

&lt;p&gt;'update' shall be appended to object's path&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/mgdschema/midgard_article/update
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On success, Midgard API shall send asynchronous message to object at path.&lt;/p&gt;

&lt;h3&gt;Delete&lt;/h3&gt;

&lt;p&gt;'delete' shall be appended to object's path&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/mgdschema/midgard_article/delete
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On success, Midgard API shall send asynchronous message to object at path.&lt;/p&gt;

&lt;h3&gt;Purge&lt;/h3&gt;

&lt;p&gt;'purge' shall be appended to object's path&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/mgdschema/midgard_article/purge
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;On success, Midgard API shall send asynchronous message to object at path.&lt;/p&gt;

&lt;h3&gt;Get&lt;/h3&gt;

&lt;p&gt;'get' shall be appended to object's path for one of these methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;constructor&lt;/li&gt;
&lt;li&gt;get_by_guid&lt;/li&gt;
&lt;li&gt;get_by_id&lt;/li&gt;
&lt;li&gt;get_by_path&lt;/li&gt;
&lt;li&gt;&lt;p&gt;get_parent&lt;/p&gt;

&lt;p&gt;/mgdschema/midgard_article/get&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Midgard API implementation will send asynchronous messages in above cases, only if object is successfully retrieved from database.&lt;/p&gt;

&lt;h2&gt;Replication&lt;/h2&gt;

&lt;p&gt;Services for replication should be created at path with following tokens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;replication&lt;/li&gt;
&lt;li&gt;class name&lt;/li&gt;
&lt;li&gt;operation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Import&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;/replication/midgard_article/import
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Export&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;/replication/midgard_article/export
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Messages&lt;/h1&gt;

&lt;p&gt;Messages sent to Midgard D-Bus services should contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serialized object as xml data&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;References&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;http://dbus.freedesktop.org/doc/dbus-tutorial.html&lt;/li&gt;
&lt;/ul&gt;
</description>
            <author>&lt;webmaster@www.midgard-project.org&gt;</author>
            <pubDate>Wed, 30 Apr 2008 09:51:50 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-0e7044e8169b11dda66def9f4bf5a56ba56b</guid>
        </item>
        <item>
            <title>Name uniqueness</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0037.html</link>
            <description>
&lt;h1&gt;Revision history&lt;/h1&gt;

&lt;p&gt;2007-12-05 Created by Piotr Pokora&lt;/p&gt;

&lt;h1&gt;Background&lt;/h1&gt;

&lt;p&gt;This document describes Midgard objects' name uniqueness, scope of uniqueness and configuration possibilities. It is also part of Midgard Tree functionality.&lt;/p&gt;

&lt;h1&gt;Terminology&lt;/h1&gt;

&lt;p&gt;Whenever &lt;strong&gt;name&lt;/strong&gt; word is used in this document it refers to object property registered with MgdSchema and configured to be unique in particular scope.&lt;/p&gt;

&lt;h1&gt;Name uniqueness&lt;/h1&gt;

&lt;p&gt;Unique name should be a property of any type, however it's recommended to use string type with unique names. Name should be configured in Midgard Schema xml file and there should be only one unique name defined per class ( type ). Name should be configured only for classes which may be represented in Midgard Tree. For any other class, unique name should be ignored.&lt;/p&gt;

&lt;p&gt;Reserved configuration attribute which defines unique name itself, doesn't qualifies a class ( for which name belongs to) as Midgard Tree enabled.&lt;/p&gt;

&lt;p&gt;Name uniqueness should not be supported by underlying database storage provider, unless such functionality would not break sitegroup or Midgard Tree specifications.&lt;/p&gt;

&lt;h1&gt;Configuration&lt;/h1&gt;

&lt;p&gt;Unique name should be configured only with reserved &lt;strong&gt;unique&lt;/strong&gt; attribute(s) in xml file.
A value for the given attribute should define 3 different scopes of uniquness:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;parent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It guarantees a name is unique in scope of parent type object's identifier.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;self&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It guarantees a name is unique in scope of the same type object's identifier.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;both&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It guarantees a name is unique in scope of the same and parent type object's identifier.&lt;/p&gt;

&lt;h2&gt;Examples&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;property name=&quot;title&quot; unique=&quot;both&quot;&amp;gt;
&amp;lt;property name=&quot;name&quot; unique=&quot;parent&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;OR&lt;/strong&gt;
 Unique name should be configured only with reserved &lt;strong&gt;unique&lt;/strong&gt; and &lt;strong&gt;scope&lt;/strong&gt; attribute(s) in xml file.&lt;/p&gt;

&lt;h2&gt;Examples&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;property name=&quot;title&quot; unique=&quot;yes&quot; unique_scope=&quot;both&quot;&amp;gt;
&amp;lt;property name=&quot;name&quot; unique=&quot;yes&quot; unique_scope=&quot;self&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;TODO&lt;/h2&gt;

&lt;p&gt;Describe parent name uniqueness enforce when value is set to 'both'.&lt;/p&gt;

&lt;h1&gt;References:&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://www.midgard-project.org/documentation/mgdschema/&quot;&gt;MgdSchema documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
            <author>&lt;webmaster@www.midgard-project.org&gt;</author>
            <pubDate>Wed, 05 Dec 2007 15:50:36 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-d22e5bd8a34911dc9eece5f35230a5a7a5a7</guid>
        </item>
        <item>
            <title>Administrative modules for Asgard</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0036.html</link>
            <description>
&lt;p&gt;Asgard is the administrative interface used for Midgard CMS. By default it provides a comprehensive object browser and management tool.&lt;/p&gt;

&lt;p&gt;It is possible to extend the Asgard functionality by adding other modules to the system.&lt;/p&gt;

&lt;h2&gt;Request handler plugin setup&lt;/h2&gt;

&lt;p&gt;Components wishing to operate as Asgard plugins must have a class that registers plugin handler classes to the request switch. This is defined in component manifest via:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;'customdata' =&amp;gt; array
(
    'asgard_plugin' =&amp;gt; array
    (
        'class' =&amp;gt; 'net_example_adminmodule_request',
        'src' =&amp;gt; 'file:/net/example/adminmodule/request.php',
        'name' =&amp;gt; 'Example admin',
        'config' =&amp;gt; null,
    ),
),
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The actual class must have a method &lt;code&gt;get_plugin_handlers()&lt;/code&gt; that returns a &lt;em&gt;request switch&lt;/em&gt; array and initiates the Asgard library:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function get_plugin_handlers()
{
    $_MIDCOM-&amp;gt;load_library('midgard.admin.asgard');
    $_MIDCOM-&amp;gt;auth-&amp;gt;require_valid_user();
    return Array
    (
        'index' =&amp;gt; Array
        (
            'handler' =&amp;gt; array('net_example_adminmodule_handler_main', 'main'),
        ),
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There must be handler for a view without arguments as this will be the screen users enter when choosing the module from Asgard navigation.&lt;/p&gt;

&lt;h2&gt;Handler class&lt;/h2&gt;

&lt;p&gt;The handler class must populate some data used by Asgard.&lt;/p&gt;

&lt;h3&gt;Handle phase&lt;/h3&gt;

&lt;p&gt;During the handle phase the plugin must register itself to Asgard:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$my_title = $_MIDCOM-&amp;gt;i18n-&amp;gt;get_string('example admin plugin', 'net.example.adminplugin');
midgard_admin_asgard_plugin::prepare_plugin($my_title, &amp;amp;$data);
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Show phase&lt;/h3&gt;

&lt;p&gt;During show phase the element must show Asgard's elements around its own content:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;midcom_show_style('midgard_admin_asgard_header');
midcom_show_style('midgard_admin_asgard_middle');

// Show plugin's own output

midcom_show_style('midgard_admin_asgard_footer');
&lt;/code&gt;&lt;/pre&gt;
</description>
            <author>Henri Bergius &lt;henri.bergius@iki.fi&gt;</author>
            <pubDate>Tue, 24 Jul 2007 12:34:56 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-4941cf4239e211dcbeae0b511a09f898f898</guid>
        </item>
        <item>
            <title>On-demand service loading for MidCOM</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0035.html</link>
            <description>
&lt;p&gt;This is a proposal for moving service and library loading infrastructure in MidCOM 3 to a more on-demand service oriented model.&lt;/p&gt;

&lt;h2&gt;Background&lt;/h2&gt;

&lt;p&gt;Currently MidCOM loads a huge number of libraries and services for each request, requiring large amounts of file accesses and PHP parsing. Most of the services loaded are however not really used in a typical request, and so can be seen as being loaded &quot;just in case&quot;.&lt;/p&gt;

&lt;p&gt;The belief is that this makes the MidCOM environment heavier and more difficult to understand. This proposal outlines how MidCOM could migrate from the current model to a model where services would be loaded when they are used for the first time.&lt;/p&gt;

&lt;h2&gt;MidCOM service loader&lt;/h2&gt;

&lt;p&gt;A new class &lt;code&gt;midcom_helper_serviceloader&lt;/code&gt; needs to be defined to act as the access point to the MidCOM service system. It will be instantiated as &lt;code&gt;$_MIDCOM-&amp;gt;serviceloader&lt;/code&gt; at MidCOM start-up.&lt;/p&gt;

&lt;p&gt;The service loader should provide two public methods:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;boolean can_load($service)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Method for checking if a particular service is available on the system. This would enable components to deal with missing requirements or other situations where some functionality is not available more cleanly.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;object load($service)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Method for instantiating an implementation of a particular service.&lt;/p&gt;

&lt;h2&gt;Inversion of control&lt;/h2&gt;

&lt;p&gt;An additional benefit of the service loader model is that MidCOM's services can start following the Inversion of Control design pattern.&lt;/p&gt;

&lt;p&gt;This means that services are defined by their interface classes, but actual implementation of a service can be chosen by site administrator. This will enable us to easily try and swap between various ways of doing things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; URL name generation can be moved to a &lt;code&gt;midcom_core_service_urlgenerator&lt;/code&gt; service. Since the default URL name generator shipping with MidCOM does not deal particularly well with the Georgian language, a web developer deploying Midgard in Georgia can write their own service implementation and just swap that to be used in site configuration.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$GLOBALS['midcom_config_local']['service_midcom_core_service_urlgenerator'] = 'ge_convert_urlgenerator';
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Performance&lt;/h2&gt;

&lt;p&gt;The two-tiered approach of having interface and implementation separately means that two files have to be loaded for each service. This causes a slight performance hit when compared to current approach of one file per service.&lt;/p&gt;

&lt;p&gt;However, it is believed that the benefit of loading services only when they're needed and being able to change service implementations on configuration level easily offsets this.&lt;/p&gt;

&lt;h2&gt;Related tasks&lt;/h2&gt;

&lt;p&gt;The actual service loader and an URL generator service have already been implemented as an experiment in MidCOM trunk. If this proposal is accepted, all services and &quot;helper libraries&quot; in MidCOM need to be refactored to the new model and components switched to use them.&lt;/p&gt;

&lt;p&gt;As this is a big task, the proposal is to switch services to the new model one-by-one, starting from libraries that are used in only few places.&lt;/p&gt;

&lt;p&gt;As of 2007-07-19, MidCOM loads 57 files in the &lt;code&gt;midcom.php&lt;/code&gt;, with many of them potentially loading sub-dependencies. Most of these could be moved to on-demand handling or removed by the separately proposed DBA rewrite.&lt;/p&gt;
</description>
            <author>Henri Bergius &lt;henri.bergius@iki.fi&gt;</author>
            <pubDate>Thu, 19 Jul 2007 21:24:20 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-69ab5e80363e11dc8e75233b98e980308030</guid>
        </item>
        <item>
            <title>General Membership</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0034.html</link>
            <description>
&lt;h1&gt;Revision history&lt;/h1&gt;

&lt;p&gt;2007-07-05 Created by Piotr Pokora&lt;/p&gt;

&lt;h1&gt;Background&lt;/h1&gt;

&lt;p&gt;Generic membership describes the basic way to group any MidgardSchema ( MgdSchema ) type ( class ) as an member of any other type registered in Midgard application. This mRFC also describes known Midgard functionality to group midgard_persons objects as a members of midgard_group one, and capabilities of membership introspection.&lt;/p&gt;

&lt;h1&gt;Member owner type&lt;/h1&gt;

&lt;p&gt;The type which groups other types. 
One type ( class ) can not group objects of the same type.&lt;/p&gt;

&lt;h1&gt;Member type&lt;/h1&gt;

&lt;p&gt;The type which belongs to owner group.
One type ( class ) can not belongs to group of the same type.&lt;/p&gt;

&lt;h1&gt;Membership type&lt;/h1&gt;

&lt;p&gt;The type which holds required information ( like owner or member identifier ) for members and owners.&lt;/p&gt;

&lt;h1&gt;MidgardSchema definition&lt;/h1&gt;

&lt;p&gt;Membership information shall be defined in xml schema file as a type properties and attributes and
particular introspection capabilities shall be implemented on API level.
Membership shall be always defined for member type and never for owner type.&lt;/p&gt;

&lt;p&gt;Minimal information should contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Member owner type name&lt;/li&gt;
&lt;li&gt;Membership type name&lt;/li&gt;
&lt;li&gt;Property and (or) field names which should be used for membership links&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Example&lt;/h2&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;type name=&quot;midgard_person&quot; table=&quot;person&quot; parentfield=&quot;creator&quot;&amp;gt;
    &amp;lt;membership name=&quot;midgard_member&quot; owner=&quot;midgard_group&quot; &amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Membership introspection&lt;/h1&gt;

&lt;p&gt;Membership implementation should allow to retrieve following information:&lt;/p&gt;

&lt;h2&gt;Member owner type&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If type has members&lt;/li&gt;
&lt;li&gt;What type name(s) are members of owner type&lt;/li&gt;
&lt;li&gt;Fetch all members&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Member type&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If type is a member&lt;/li&gt;
&lt;li&gt;What type is an owner of member type's &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Member creation and deletion&lt;/h1&gt;

&lt;p&gt;In general, members should be created with particular membership type implementation, to avoid direct and random database access. Membership type should always create or delete member for given member and owner type.&lt;/p&gt;
</description>
            <author>Piotr Pokora &lt;piotrek.pokora@gmail.com&gt;</author>
            <pubDate>Thu, 05 Jul 2007 11:33:37 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-9230d33e2aeb11dc8ffb796102bd70a070a0</guid>
        </item>
        <item>
            <title>Midgard Object serialization</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0033.html</link>
            <description>
&lt;h1&gt;Revision history&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;2006-09-22 Updated by Piotr Pokora, added fixed 'midgard_object' root element to xml schema&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Background&lt;/h1&gt;

&lt;p&gt;This mRFC describes xml file format which should be used for objects' replication, and for data exchange between Midgard and other systems. It is impossible to define xml file format for every type registered in Midgard type system , however this mRFC focuses on minimal xml schema &lt;a href=&quot;http://www.w3.org/TR/xmlschema-0/&quot;&gt;(2)&lt;/a&gt; file which should describe serialized Midgard object.
Xml file with serialized Midgard Object should contain Midgard namespace, Midgard Object type name, optionally its guid and lang which identify object and common metadata.&lt;/p&gt;

&lt;h1&gt;Namespace&lt;/h1&gt;

&lt;p&gt;Midgard namespace should be defined as: 
__http://www.midgard-project.org/midgard_object/1.8__&lt;/p&gt;

&lt;p&gt;( Optionally namespace could define Midgard version for which given xml file can be used )&lt;/p&gt;

&lt;h1&gt;MidgardObject&lt;/h1&gt;

&lt;p&gt;Midgard type should be defined as complexType identified by name of string type. Optionally 'guid' and 'lang' atributes could be used to identify Midgard Object. Guid attribute if used should be at least 28 and at most 80 characters long &lt;a href=&quot;http://www.midgard-project.org/development/mrfc/0018.html&quot;&gt;(1)&lt;/a&gt;. Lang &lt;a href=&quot;http://www.loc.gov/standards/iso639-2/index.html&quot;&gt;(3)&lt;/a&gt; attribute should be 2 letter language code name and define available languages enumeration.&lt;/p&gt;

&lt;p&gt;For better understanding and connectivity , midgard-core should have implemented functionality to create xml schema file for any type registered in Midgard Schema. Additionally this implementation should create languages enumeration for all available languages &lt;a href=&quot;http://www.loc.gov/standards/iso639-2/index.html&quot;&gt;(3)&lt;/a&gt; in Midgard environment. Every Midgard object's property should be defined as element type with optional attributes.&lt;/p&gt;

&lt;h1&gt;Multilingual data&lt;/h1&gt;

&lt;p&gt;If serialized object is multilingual Midgard type and more than one language is used for such object , all language content objects should be serialized and stored in one xml file. In such case deserialization implementation should return array of multilingual objects, and lang attribute's value should be mandatory set in xml file.&lt;/p&gt;

&lt;h1&gt;Parameters and attachments&lt;/h1&gt;

&lt;p&gt;Optionally , object's paramaters ( registered as standalone midgard_parameter type ) and object's attachments ( registered as standalone midgard_attachment type ) could be serialized and stored in object's xml file.&lt;/p&gt;

&lt;h1&gt;Minimal XML schema file:&lt;/h1&gt;

&lt;p&gt;&lt;?xml version=&quot;1.0&quot;?&gt;
   &lt;xsd:schema  xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;
    targetNamespace=&quot;http://www.midgard-project.org/midgard_object/1.8&quot;&gt;
    &lt;xsd:element name=&quot;midgard_object&quot; type=&quot;xsd:string&quot;  fixed=&quot;midgard_object&quot;&gt;
    &lt;xsd:complexType&gt;
    &lt;xsd:sequence&gt;
    &lt;xsd:element name=&quot;any&quot; type=&quot;xsd:string&quot;&gt;
        &lt;xsd:complexType&gt;
            &lt;xsd:sequence&gt;
                &lt;xsd:any minOccurs=&quot;0&quot;/&gt;
                &lt;xsd:element name=&quot;metadata&quot; type=&quot;xsd:string&quot; fixed=&quot;metadata&quot;&gt;
                    &lt;xsd:complexType&gt;&lt;br /&gt;
                        &lt;xsd:sequence&gt;
                        &lt;xsd:element name=&quot;created&quot; type=&quot;xsd:datetime&quot;/&gt;
                            &lt;xsd:element name=&quot;creator&quot; type=&quot;xsd:string&quot; maxOccurs=&quot;80&quot;/&gt;
                            &lt;xsd:element name=&quot;revisor&quot; type=&quot;xsd:string&quot; maxOccurs=&quot;80&quot;/&gt;
                            &lt;xsd:element name=&quot;revised&quot; type=&quot;xsd:datetime&quot;/&gt;
                            &lt;xsd:element name=&quot;revision&quot; type=&quot;xsd:nonNegativeInteger&quot;/&gt;
                            &lt;xsd:element name=&quot;locker&quot; type=&quot;xsd:string&quot; maxOccurs=&quot;80&quot;/&gt;
                            &lt;xsd:element name=&quot;locked&quot; type=&quot;xsd:datetime&quot;/&gt;
                            &lt;xsd:element name=&quot;approver&quot; type=&quot;xsd:string&quot; maxOccurs=&quot;80&quot;/&gt;
                            &lt;xsd:element name=&quot;approved&quot; type=&quot;xsd:datetime&quot;/&gt;
                            &lt;xsd:element name=&quot;authors&quot; type=&quot;xsd:string&quot; maxOccurs=&quot;unbounded&quot;/&gt;
                            &lt;xsd:element name=&quot;owner&quot; type=&quot;xsd:string&quot; maxOccurs=&quot;80&quot;/&gt;
                            &lt;xsd:element name=&quot;schedulestart&quot; type=&quot;xsd:datetime&quot;/&gt;
                            &lt;xsd:element name=&quot;scheduleend&quot; type=&quot;xsd:datetime&quot;/&gt;
                            &lt;xsd:element name=&quot;hidden&quot; type=&quot;xsd:boolean&quot; default=&quot;false&quot;/&gt;
                            &lt;xsd:element name=&quot;navnoentry&quot; type=&quot;xsd:boolean&quot; default=&quot;false&quot;/&gt;
                            &lt;xsd:element name=&quot;size&quot; type=&quot;xsd:nonNegativeInteger&quot;/&gt;
                            &lt;xsd:element name=&quot;published&quot; type=&quot;xsd:datetime&quot;/&gt;
                            &lt;xsd:element name=&quot;score&quot; type=&quot;xsd:nonNegativeInteger&quot;/&gt;
                            &lt;xsd:element name=&quot;imported&quot; type=&quot;xsd:datetime&quot;/&gt;
                            &lt;xsd:element name=&quot;exported&quot; type=&quot;xsd:datetime&quot;/&gt;
                            &lt;xsd:element name=&quot;deleted&quot; type=&quot;xsd:boolean&quot; default=&quot;false&quot;/&gt;&lt;br /&gt;
                        &lt;/xsd:sequence&gt;
                    &lt;/xsd:complexType&gt;
                &lt;/xsd:element&gt;
        &lt;/xsd:sequence&gt;
            &lt;xsd:attribute name=&quot;guid&quot; type=&quot;xsd:string&quot; use=&quot;optional&quot;&gt;
                &lt;xsd:simpleType&gt;
                    &lt;xsd:restriction base=&quot;xsd:string&quot;&gt;
                        &lt;xsd:minLength value=&quot;28&quot;/&gt;
                        &lt;xsd:maxLength value=&quot;80&quot;/&gt;
                    &lt;/xsd:restriction&gt;
                &lt;/xsd:simpleType&gt;
            &lt;/xsd:attribute&gt;
            &lt;xsd:attribute name=&quot;lang&quot; type=&quot;xsd:string&quot; use=&quot;optional&quot;&gt;
                &lt;xsd:simpleType&gt;
                    &lt;xsd:restriction base=&quot;xsd:string&quot;&gt;
                        &lt;xsd:length value=&quot;2&quot;/&gt;
                        &lt;xsd:enumeration value=&quot;en&quot;/&gt;
                        &lt;xsd:enumeration value=&quot;pl&quot;/&gt;
                        &lt;xsd:enumeration value=&quot;fi&quot;/&gt;
                        &lt;xsd:enumeration value=&quot;de&quot;/&gt;
                    &lt;/xsd:restriction&gt;
                &lt;/xsd:simpleType&gt;
            &lt;/xsd:attribute&gt;
        &lt;/xsd:complexType&gt;
    &lt;/xsd:element&gt;&lt;br /&gt;
    &lt;/xsd:sequence&gt;
    &lt;/xsd:complexType&gt;
    &lt;/xsd:element&gt;
   &lt;/xsd:schema&gt;&lt;/p&gt;

&lt;h1&gt;Example:&lt;/h1&gt;

&lt;pre&gt;&lt;code&gt; &amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;
 &amp;lt;midgard_object xmlns=&quot;http://www.midgard-project.org/midgard_object/1.8&quot;&amp;gt;
   &amp;lt;midgard_article guid=&quot;26b621b938c4aea0e021d4baae69d6ab&quot; lang=&quot;en&quot;&amp;gt;
     &amp;lt;metadata&amp;gt;
       &amp;lt;creator&amp;gt;&amp;lt;/creator&amp;gt;
       &amp;lt;created&amp;gt;1999-05-07 18:04:04&amp;lt;/created&amp;gt;
       &amp;lt;revisor&amp;gt;&amp;lt;/revisor&amp;gt;
       &amp;lt;revised&amp;gt;2006-09-10 09:28:08&amp;lt;/revised&amp;gt;
       &amp;lt;revision&amp;gt;1&amp;lt;/revision&amp;gt;
       &amp;lt;locker&amp;gt;&amp;lt;/locker&amp;gt;
       &amp;lt;locked&amp;gt;1999-08-17 16:01:32&amp;lt;/locked&amp;gt;
       &amp;lt;approver&amp;gt;&amp;lt;/approver&amp;gt;
       &amp;lt;approved&amp;gt;&amp;lt;/approved&amp;gt;
       &amp;lt;authors&amp;gt;f6b665f1984503790ed91f39b11b5392&amp;lt;/authors&amp;gt;
       &amp;lt;owner&amp;gt;&amp;lt;/owner&amp;gt;
       &amp;lt;schedulestart&amp;gt;&amp;lt;/schedulestart&amp;gt;
       &amp;lt;scheduleend&amp;gt;&amp;lt;/scheduleend&amp;gt;
       &amp;lt;hidden&amp;gt;0&amp;lt;/hidden&amp;gt;
       &amp;lt;navnoentry&amp;gt;0&amp;lt;/navnoentry&amp;gt;
       &amp;lt;size&amp;gt;481&amp;lt;/size&amp;gt;
       &amp;lt;published&amp;gt;1999-05-07 18:04:04&amp;lt;/published&amp;gt;
       &amp;lt;score&amp;gt;0&amp;lt;/score&amp;gt;
       &amp;lt;imported&amp;gt;&amp;lt;/imported&amp;gt;
       &amp;lt;exported&amp;gt;2006-09-14 12:37:40+0000&amp;lt;/exported&amp;gt;
       &amp;lt;deleted&amp;gt;0&amp;lt;/deleted&amp;gt;
     &amp;lt;/metadata&amp;gt;
     &amp;lt;action&amp;gt;&amp;lt;/action&amp;gt;
     &amp;lt;id&amp;gt;2&amp;lt;/id&amp;gt;
     &amp;lt;created&amp;gt;1999-05-07 18:04:04&amp;lt;/created&amp;gt;
     &amp;lt;revisor&amp;gt;f6b665f1984503790ed91f39b11b5392&amp;lt;/revisor&amp;gt;
     &amp;lt;score&amp;gt;0&amp;lt;/score&amp;gt;
     &amp;lt;title&amp;gt;Host Administration&amp;lt;/title&amp;gt;
     &amp;lt;abstract&amp;gt;Midgard host and directory management
 &amp;lt;/abstract&amp;gt;
     &amp;lt;locker&amp;gt;f6b665f1984503790ed91f39b11b5392&amp;lt;/locker&amp;gt;
     &amp;lt;caldays&amp;gt;0&amp;lt;/caldays&amp;gt;
     &amp;lt;approved&amp;gt;&amp;lt;/approved&amp;gt;
     &amp;lt;calstart&amp;gt;0000-00-00&amp;lt;/calstart&amp;gt;
     &amp;lt;content&amp;gt;&amp;lt;p&amp;gt;
 Use the host administration tool to create and maintain the       structure and functionality of your web sites. Use the layout adminstration tool for controlling the appearance of the site and the content administration tool for the dynamic content of the site.   &amp;lt;/content&amp;gt;
     &amp;lt;icon&amp;gt;0&amp;lt;/icon&amp;gt;
     &amp;lt;type&amp;gt;0&amp;lt;/type&amp;gt;
     &amp;lt;creator&amp;gt;f6b665f1984503790ed91f39b11b53922&amp;lt;/creator&amp;gt;
     &amp;lt;revised&amp;gt;&amp;lt;/revised&amp;gt;
     &amp;lt;approver&amp;gt;0&amp;lt;/approver&amp;gt;
     &amp;lt;extra1&amp;gt;&amp;lt;/extra1&amp;gt;
     &amp;lt;name&amp;gt;&amp;lt;/name&amp;gt;
     &amp;lt;author&amp;gt;f6b665f1984503790ed91f39b11b5392&amp;lt;/author&amp;gt;
     &amp;lt;url&amp;gt;&amp;lt;/url&amp;gt;
     &amp;lt;contentauthor&amp;gt;1&amp;lt;/contentauthor&amp;gt;
     &amp;lt;contentcreated&amp;gt;1999-05-07 18:04:04&amp;lt;/contentcreated&amp;gt;
     &amp;lt;print&amp;gt;0&amp;lt;/print&amp;gt;
     &amp;lt;extra2&amp;gt;&amp;lt;/extra2&amp;gt;
     &amp;lt;view&amp;gt;0&amp;lt;/view&amp;gt;
     &amp;lt;extra3&amp;gt;&amp;lt;/extra3&amp;gt;
     &amp;lt;revision&amp;gt;0&amp;lt;/revision&amp;gt;
     &amp;lt;sid&amp;gt;2&amp;lt;/sid&amp;gt;
     &amp;lt;locked&amp;gt;1999-08-17 16:01:32&amp;lt;/locked&amp;gt;
     &amp;lt;up&amp;gt;d0099a92c1018461bc6e33cd0a1c435b&amp;lt;/up&amp;gt;
   &amp;lt;/midgard_article&amp;gt;
 &amp;lt;/midgard_object&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;References:&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;http://www.midgard-project.org/development/mrfc/0018.html&lt;/li&gt;
&lt;li&gt;http://www.w3.org/TR/xmlschema-0/&lt;/li&gt;
&lt;li&gt;http://www.loc.gov/standards/iso639-2/index.html&lt;/li&gt;
&lt;/ul&gt;
</description>
            <author>Piotr Pokora &lt;piotrek.pokora@gmail.com&gt;</author>
            <pubDate>Mon, 18 Sep 2006 13:16:29 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-12c0c7a12f2cf7d302ca4f21489753c2</guid>
        </item>
        <item>
            <title>Multilingual MidCOM</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0032.html</link>
            <description>
&lt;p&gt;This proposal outlines how multilingual sites should be managed in the MidCOM framework utilizing the MultiLang features of Midgard 1.8. This mRFC been submitted to the Midgard Community for discussion and approval under the Creative Commons Attribution-ShareAlike license.&lt;/p&gt;

&lt;h2&gt;Multilingual sites&lt;/h2&gt;

&lt;p&gt;Midgard's base of power is Europe where there are many languages and many organizations operating across language barriers. This makes it very important to support easy management of multilingual sites.&lt;/p&gt;

&lt;p&gt;Traditionally there have been two different types of multilingual sites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sites in multiple languages:&lt;/strong&gt; These are sites that contain approximately same information in each language, either mandated by law or by organization's desire to reach different language audiences&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multiple language versions of site:&lt;/strong&gt; These sites can contain very different content structures targeted at domestic and foreign markets, or based on some other differentiation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This proposal focuses on the first of these two. Multiple language versions of a site are better managed using separate content trees for each site than using MultiLang features.&lt;/p&gt;

&lt;h2&gt;MultiLang background&lt;/h2&gt;

&lt;p&gt;Right from the beginnings of the project, Midgard has had a strong international focus. Multibyte character set support landed in Midgard already in October 1999 in order to support managing sites in languages like Russian and Chinese. UTF-8 was made the default character set for Midgard in the 1.6 series.&lt;/p&gt;

&lt;p&gt;However, in addition to character sets, also translation of actual content was needed. &lt;a href=&quot;http://www.midgard-project.org/midcom-permalink-a22d4e60eaa3ebcf3ac425856df2dc13&quot;&gt;MultiLingual Midgard&lt;/a&gt; was presented as &lt;a href=&quot;http://midgard.dataflow.ch/&quot;&gt;a patch&lt;/a&gt; by David Schmitter from DataFlow in Switzerland in May 2003, and entered Midgard proper for the 1.5.0 release.&lt;/p&gt;

&lt;p&gt;This made the Midgard content formats support different translations of content, but besides DataFlow's proprietary &lt;a href=&quot;http://www.dataflow-solutions.ch/products/webinone/&quot;&gt;WebInOne&lt;/a&gt; publishing tool, no Midgard authoring interface has actually added MultiLang support.&lt;/p&gt;

&lt;p&gt;The reason for not supporting MultiLang has mostly been the difficulty of integrating good translation workflow, and unclear PHP-level programming APIs for it. The APIs have now however matured enough with integration to MgdSchema and &lt;a href=&quot;http://www.midgard-project.org/midcom-permalink-7d3914b74c189137e500088a64d55403&quot;&gt;Query Builder&lt;/a&gt; tools so that supporting MultiLingual content cleanly is finally possible.&lt;/p&gt;

&lt;h2&gt;Implementation into MidCOM&lt;/h2&gt;

&lt;p&gt;Here is a description on how MultiLang should be implemented into the Midgard Component Framework. The aim here is to make creating and maintaining multilingual sites easy without having to impose changes into MidCOM components.&lt;/p&gt;

&lt;h3&gt;Choosing languages used on site&lt;/h3&gt;

&lt;p&gt;Webite's language selections (languages available for the site and the default language) are stored in the MidCOM configuration array.&lt;/p&gt;

&lt;p&gt;The language selections can be made using Site Wizard for better convenience&lt;/p&gt;

&lt;h3&gt;Language selection for content&lt;/h3&gt;

&lt;p&gt;Languages would be selected using the &lt;code&gt;$argv[0]&lt;/code&gt; prefix of the site, i.e. Finnish version of &quot;About us&quot; would reside in &lt;code&gt;/fi/about&lt;/code&gt;. This can be implemented in a centralized fashion by modifying MidCOM's URL parser and making it call the corresponding &lt;a href=&quot;http://www.midgard-project.org/midcom-permalink-c731d33b1ece522121099a63c800c729&quot;&gt;MidCOM i18n service&lt;/a&gt; &lt;code&gt;set_language&lt;/code&gt; method for changing language.&lt;/p&gt;

&lt;p&gt;In addition to the per-language URLs, there would be the &quot;language neutral&quot; URL for each object. This would redirect user to appropriate URL based on their browser language selection, i.e. &lt;code&gt;/about&lt;/code&gt; would redirect me to &lt;code&gt;/de/about&lt;/code&gt; for German language users.&lt;/p&gt;

&lt;h3&gt;Navigation building and object instantiation&lt;/h3&gt;

&lt;p&gt;Language versions of site should obviously show only the contents translated to their languages in navigation and content listings (like news lists for instance). Since MidCOM has a centralized wrapper for Query Builder, the DBA can easily add the language constraint into all DB queries transparently. This means components don't have to do any language-based processing to show only Norwegian news items.&lt;/p&gt;

&lt;p&gt;Similarly, when an object is instantiated (&lt;code&gt;get_by_guid&lt;/code&gt; etc), DBA should check if the &lt;code&gt;$object-&amp;gt;lang&lt;/code&gt; is the current language and if not fail the instantiation.&lt;/p&gt;

&lt;p&gt;MidCOM should contain a specific &quot;translation to this language not found&quot; error  message that could be triggered if requested object is not available in current language. This error message could contain links to the existing language versions.&lt;/p&gt;

&lt;h3&gt;Content editing&lt;/h3&gt;

&lt;p&gt;Since editing MidCOM content now happens on-site and there are language prefixes available, switching editing views between languages is just a matter of changing the site prefix.&lt;/p&gt;

&lt;p&gt;However, there should be some facilities for showing to translators what has been changes in the &quot;default language&quot; contents of an object so they know what to translate. This relates to RCS version control services in MidCOM.&lt;/p&gt;

&lt;h3&gt;Content language vs. UI language&lt;/h3&gt;

&lt;p&gt;MidCOM's i18n service has already been modified so that user interface language can be different from actual content language. Many multilingual organizations prefer to run their software in a common language to ease documentation and training.&lt;/p&gt;

&lt;h3&gt;Different language versions&lt;/h3&gt;

&lt;p&gt;The information on different language versions of an object must be available so that MidCOM's metadata system can populate links to the different translations.&lt;/p&gt;

&lt;h2&gt;API-level requirements&lt;/h2&gt;

&lt;p&gt;Here is a list of requirements from the MultiLang implementation in Midgard Core that are needed for this mRFC:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;midgard_language&lt;/code&gt; objects must be available for regular Query Builder operations, and must contain a &lt;code&gt;locale&lt;/code&gt; field with the appropriate UNIX system locale&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;mgd_set_lang(X)&lt;/code&gt; has been called, all object update/create/delete operations must apply to the content of that particular language&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$object-&amp;gt;get_languages()&lt;/code&gt; must return list of languages the object is available for&lt;/li&gt;
&lt;li&gt;Each language version must contain a revision timestamp to help with translation workflow&lt;/li&gt;
&lt;li&gt;When &lt;code&gt;set_lang&lt;/code&gt; has been called for Query Builder, it must only return objects that are in that particular language, no &lt;em&gt;lang0&lt;/em&gt; objects&lt;/li&gt;
&lt;/ul&gt;
</description>
            <author>Henri Bergius &lt;henri.bergius@iki.fi&gt;</author>
            <pubDate>Wed, 26 Jul 2006 14:55:44 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-2ce647c080dd10a0a862fe43746ce3a3</guid>
        </item>
        <item>
            <title>MidgardApacheCache</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0031.html</link>
            <description>
&lt;p&gt;MidgardApacheCache&lt;/p&gt;

&lt;h1&gt;Revision history&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;2006-06-14 Created by Piotr Pokora&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Background&lt;/h1&gt;

&lt;p&gt;Cache approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;data reusability&lt;/li&gt;
&lt;li&gt;limit the need to query the same objects with every request&lt;/li&gt;
&lt;li&gt;cache objects which are queried with the same data with every request&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Implementation&lt;/h1&gt;

&lt;p&gt;MidgardApacheCache should extend base MidgardCache class, and should be optimized 
for any midgard extension which is used in Apache module environment.
MidgardCache base class should be assigned as private member of MidgardConnection
and thus connection handler object could be responsible for managing internal's core
objects references counts.&lt;/p&gt;

&lt;p&gt;MidgardApacheCache when instanciated should return UUID which should be available 
during the whole application runtime. For Apache module, it means - as long as httpd
server is running.&lt;/p&gt;

&lt;p&gt;There shouldn't be any method or function in implementation which should allow list 
all cache entries ( MidgardApacheCache instances ) available.&lt;/p&gt;

&lt;p&gt;Retrieving MidgardApacheCache instance should be possible only with UUID representing
particular object instance and application which use cache object should be responsible 
to store this UUID.&lt;/p&gt;

&lt;h3&gt;Example&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

$application_cache_guid = &quot;guid_string&quot;; 

$cache = new midgard_apache_cache($application_cache_guid);
if(!$cache-&amp;gt;exists())
    $application_cache_guid = $cache-&amp;gt;create();
else 
    $cache-&amp;gt;get();
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The main purpose of MidgardApacheCache should be possibility to store objects , however
other types should be supported as well. Objects should be identified by guids in the same 
way as are identified and retrieved in typical Midgard applications.
Other types like arrays should be registered with unique names.&lt;/p&gt;

&lt;h3&gt;Example&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

$object = $cache-&amp;gt;get_type_by_guid(&quot;object_guid_string&quot;);
$object-&amp;gt;register(&quot;my_constant_array&quot;, $array_type);
$array = $object-&amp;gt;get_type_by_name(&quot;my_constant_array&quot;);

?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;MidgardApacheCache should implement such features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;initialize cache&lt;/li&gt;
&lt;li&gt;get cache object instance identified by UUID&lt;/li&gt;
&lt;li&gt;add type to cache&lt;/li&gt;
&lt;li&gt;update type in cache&lt;/li&gt;
&lt;li&gt;get type from cache&lt;/li&gt;
&lt;li&gt;remove type from cache&lt;/li&gt;
&lt;/ul&gt;
</description>
            <author>Piotr Pokora &lt;piotrek.pokora@gmail.com&gt;</author>
            <pubDate>Wed, 14 Jun 2006 16:46:23 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-f39ef5aac462e34a806b6a0008a889d0</guid>
        </item>
        <item>
            <title>Midgard object replication</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0030.html</link>
            <description>
&lt;h1&gt;Revision history&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;2006-06-02 Created by Piotr Pokora &lt;/li&gt;
&lt;li&gt;2006-06-17 Updated: possibility to delete and undelete 
objects &lt;/li&gt;
&lt;li&gt;2006-06-19 (torben) Commented the MidCOM section, reset
the mRFC to draft status due to this.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Background&lt;/h1&gt;

&lt;p&gt;This mRFC is a proposal for repligard functionality replacement , supported by midgard-core and by any language for which Midgard language bindings exist. As repligard supported Midgard database replication without any possibility to change its behaviour a lot , this mRFC focuses on object's records  replication , object exporting and object importing to or from any database storage. This mRFC also describes possibility to undelete and purge object's record(s).&lt;/p&gt;

&lt;p&gt;Examples in this mRFC use PHP as scripting language.&lt;/p&gt;

&lt;h3&gt;Example: exporting all newest objects example.&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php  

$exported_objects = array();
foreach ($_MIDGARD['types'] as $type =&amp;gt; $type_id) {
    $qb = new midgardquerybuilder($type);
    $qb-&amp;gt;add_constraint(&quot;metadata.created&quot;, &quot;&amp;gt;&quot;, $yesterday); 
$retval = $qb-&amp;gt;execute();
    $exported_objects = array_merge($exported_objects, $retval);
}

foreach($exported_objects as $object){
    $object-&amp;gt;export();
}   
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h1&gt;Midgard object metadata&lt;/h1&gt;

&lt;p&gt;Every Midgard object's metadata class should have 'exported' and 'imported' members assigned as properties of midgard_metadata type. These two properties's values represented by corresponding database storage values should be settable only by midgard-core with particular methods.
Both properties must be MGD_TYPE_DATETIME type.&lt;/p&gt;

&lt;h1&gt;Midgard object methods&lt;/h1&gt;

&lt;p&gt;Midgard-core must support &lt;strong&gt;export&lt;/strong&gt; and &lt;strong&gt;import&lt;/strong&gt; methods for object's replication. Object's replication related metadata should be managed by basic methods: create, update, delete, undelete , purge, import, export.&lt;/p&gt;

&lt;h2&gt;Create&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;created&lt;/strong&gt; , current datetime value must be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;revised&lt;/strong&gt;, current datetime value should be set &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;imported&lt;/strong&gt;, empty value must be set  &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;exported&lt;/strong&gt;, empty value must be set&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Update&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;created&lt;/strong&gt;, value can not be set &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;revised&lt;/strong&gt;, current datetime value must be set &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;imported&lt;/strong&gt;, empty value must be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;exported&lt;/strong&gt;, empty value must be set&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Import&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;created&lt;/strong&gt;, value can not be set if object's record exists in database
in any other case object's record must be created and metadata &lt;strong&gt;created&lt;/strong&gt;
with current datetime value must be set &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;revised&lt;/strong&gt;, value shouldn't be set if object's record doesn't exists in database
in any other case metadata &lt;strong&gt;revised&lt;/strong&gt; must be set with value of imported object's 
metadata &lt;strong&gt;revised&lt;/strong&gt; value&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;imported&lt;/strong&gt;, current datetime value should be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;exported&lt;/strong&gt;, empty value must be set&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Object can be imported to database only if &lt;strong&gt;imported&lt;/strong&gt; metadata property value of the object for which record in database exists is empty and its metadata &lt;strong&gt;revised&lt;/strong&gt; property value is not newer
than the value of the same property of object which is to be imported.&lt;/p&gt;

&lt;h2&gt;Export&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;created&lt;/strong&gt;, value can not be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;revised&lt;/strong&gt;, value can not be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;imported&lt;/strong&gt;, value can not be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;exported&lt;/strong&gt;, current datetime value must be set&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Object can be exported from database without any restriction. Application which exports objects defines what constraints are used to export object records.&lt;/p&gt;

&lt;h3&gt;Example: exporting visible midgard_article records&lt;/h3&gt;

&lt;p&gt;This example demonstrates how to export newest and not hidden midgard_article objects&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php

$qb = new midgardquerybuilder(&quot;midgard_article&quot;);
$qb-&amp;gt;add_constraint(&quot;metadata.created&quot;, &quot;&amp;gt;&quot;, $yesterday);
$qb-&amp;gt;add_constraint(&quot;metadata.hidden&quot;, &quot;=&quot;, FALSE);

/* Do not export objects which were created and exported for the last 24 hours */
$qb-&amp;gt;add_constraint(&quot;metadata.exported&quot;, &quot;=&quot;, &quot;&quot;);

$retval = $qb-&amp;gt;execute();

foreach($retval as $object){
    $object-&amp;gt;export();
}   
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Delete&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;created&lt;/strong&gt;, value can not be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;revised&lt;/strong&gt;, current datetime value must be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;imported&lt;/strong&gt;, value can not be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;exported&lt;/strong&gt;, value can not be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;metadata.deleted&lt;/strong&gt;, value must be set.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Object's record(s) can not be deleted from database when delete method is invoked. Instead , object's metadata delete property should be explicitly updated with correct delete value. For performance reason this value should be an integer type. This metadata property should be also used by midgard core as mandatory Midgard Query Builder's constraint added internally by Query Builder implementation.&lt;/p&gt;

&lt;h3&gt;Undelete&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;created&lt;/strong&gt;, value can not be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;revised&lt;/strong&gt;, current datetime value must be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;imported&lt;/strong&gt;, value can not be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;exported&lt;/strong&gt;, value can not be set&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;metadata.deleted&lt;/strong&gt;, value must be (re)set to initial default state.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Purge&lt;/h3&gt;

&lt;p&gt;When this method is invoked, midgard core should delete object's record(s) from database and should update repligard table. Following values should be set for corresponding record in repligard table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;object's class name&lt;/li&gt;
&lt;li&gt;object's guid&lt;/li&gt;
&lt;li&gt;purge action should be set to TRUE value&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Repligard table&lt;/h2&gt;

&lt;p&gt;Repligard table must containt only object's guid and typename ( classname ) for which new object instance with particular guid can be created. Additionaly repligard table should contain information if object's record(s) was purged.&lt;/p&gt;

&lt;h3&gt;Query deleted objects&lt;/h3&gt;

&lt;p&gt;Midgard core should implement functionality which allows to query only  deleted objects. This functionality could be implemented with new  Midgard Query Builder method or with new Midgard type.&lt;/p&gt;

&lt;h2&gt;Staging/live in MidCOM&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Missing topics: Data model, general service architecture,
  including the layers of the communication infrastucture.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since replication interfaces are exposed to PHP level, the staging/live process can be handled in MidCOM space. This should make the simple replication scenarios like an article that is approved much faster, the system more fault tolerant due to the queue system, and finally the replication logic easier to tweak because it is entirely in PHP level.&lt;/p&gt;

&lt;p&gt;There will be a midcom.helper.staginglive purecode component to handle the replication process.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This will have to be &lt;code&gt;midcom.services.replication&lt;/code&gt;.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Invoking replication&lt;/h3&gt;

&lt;p&gt;The replication component will register UPDATE and DELETE watchers for &lt;code&gt;midcom_core_dbobject&lt;/code&gt;. Since approvals are stored into Midgard metadata fields using &lt;code&gt;update()&lt;/code&gt; method approval should be carried to this watcher.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note, that you cannot register watches for 
  &lt;code&gt;midcom_core_dbobject&lt;/code&gt;, as this class is not a base class
  for other DBA classes. It is more of a &quot;mix-in&quot; due to
  Limitations of the PHP OOP API. The correct definition 
  would be adding watches to all defined DBA classes by
  not limiting the watch to any class.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To catch objects updated or deleted outside MidCOM DBA the system will also provide a &lt;code&gt;cron&lt;/code&gt; entry that will query through all MgdSchema types to see if there is something to replicate. This can be run relatively seldom, for example once per day.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is not very precise. The criteria after which objects
  are marked for replication should be outlined.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Export process&lt;/h3&gt;

&lt;p&gt;The export watchers will execute an exporting method in the midcom.helper.staginglive interface class and provide it with the affected object as argument.&lt;/p&gt;

&lt;p&gt;If approvals or scheduling are being used, the system will first check if the object itself is set to be visible. Otherwise visibility will be assumed.&lt;/p&gt;

&lt;p&gt;If the object is visible, the same check will be done for its parent.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note, that this can prohibit replication under certain
  circumstances: Assume that a topic and one of its articles
  are both changed. The article gets approved, the topic not.
  Replication of the article will then be delayed.&lt;/p&gt;
  
  &lt;p&gt;Note as well, that there is another case, where you 
  actually need to be careful if you change the behavoir to
  cover the above special case: If the topic in question was
  newly created, it won't be available on the target server.&lt;/p&gt;
  
  &lt;p&gt;Normally, the latter should be no problem if and only if
  only GUIDs are used for linking and, as such, ID mappings
  are not required. The legacy data structures do not yet
  do this. I very strongly suggest that this will be changed
  prior implementing this, even if this means that existing
  code (mainly QB lookups) have to be adapted to it.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the parent is visible, the object will be marked for exporting. If the parent is not visible export is aborted and UI message &quot;Object not exported because parent is not visible&quot; sent to the user.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;What happens later, when the parent gets cleared? Is the
  delayed object queued somewhere? This needs much more 
  detail.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then the method will query the object's children and call the same method for them.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I assume that this is the fix for the above problem I 
  mentioned. The problem I see here is that you will often
  get large trees here, especially if you are at the top
  of the tree. Also you will have difficulties as you have
  to know all types which potentially have the object in
  question as a parent:&lt;/p&gt;
  
  &lt;p&gt;Especially topics are tricky here, as several of the 
  components I wrote lately assign their data to topics,
  without actually using &lt;code&gt;midgard_article&lt;/code&gt;. But groups
  or persons can easily reach a similar spread.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;pre&gt;&lt;code&gt;TODO: Pseudocode for the exporting decision
&lt;/code&gt;&lt;/pre&gt;

&lt;blockquote&gt;
  &lt;p&gt;I'd like to see this before +1'ing anything.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally the exported objects will be stored into replication queue and an &lt;code&gt;at&lt;/code&gt; entry registered for running the replication next minute.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Is this wise? Or would it be more appropriate to have a 
  cron job doing it every X minutes to optimize / batch 
  the changes.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;UI message &quot;3 articles and 1 topic exported for replication&quot; is sent to the user.&lt;/p&gt;

&lt;h3&gt;Subscribers and replication queue&lt;/h3&gt;

&lt;p&gt;Subscribers (Midgard sites to replicate to) are stored in the database. The subscriber entry contains the replication method used for that subscriber and address and authentication information required for the method.&lt;/p&gt;

&lt;p&gt;When objects are exported, the export XML is stored into a &lt;code&gt;midcom_helper_staginglive_queue_entry&lt;/code&gt; object for each subscriber.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Data duplication, the data model should be revised here.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Replication is launched by the &lt;code&gt;at&lt;/code&gt; entry registered at export phase. The replication process goes through all subscribers, and tries to send the items of their queue to them using the defined method.&lt;/p&gt;

&lt;p&gt;There can be multiple replication methods supported by the system. At first we will only implement a simple HTTP PUT (or POST) method sent to a MidCOM &lt;code&gt;exec&lt;/code&gt; handler of the midcom.helper.staginglive component, authenticated using HTTP Basic Auth. Other methods could include Jabber/XMPP, DBE or even email.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Wouldn't some XML-RPC or other standardized remoting 
  mechanism be more appropriate then some proprietary
  solution?&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Email could provide a high security replication solution where the exporting end would GPG encrypt and sign the email, then send it out as an email. The importing end would then read the email from the server, check its signature, decrypt it and import. This way the importing end could even be a mostly offline computer that would only connect to internet to receive the emails once per day (this is how FSF Europe's member registry works to protect privacy).&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Consider using regular X.509 based encryption / signing
  instead of PGP. More standardized (almost as easy to use)
  and integrated into existing PKI infrastructures. This 
  should be available completly independant of the actual
  transport layer used, btw.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the replication is successful, the queue entry is deleted. If not, the replication will be attempted again every hour using a &lt;code&gt;cron&lt;/code&gt; entry.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Provide some fallback mechanism, similar to the SMTP 
  system. There should be a fixed number of retries, maybe
  with increased waiting periods after certain escalation
  levels.&lt;/p&gt;
  
  &lt;p&gt;Also, it is recommended to flag entries as failed after
  a certain amount of retries have been reached.&lt;/p&gt;
  
  &lt;p&gt;Failed connections to a subscriber should escalate as well,
  disabling the subscriber until the situation is resolved.
  Otherwise, there would be an easy DOS scenario when too 
  many replications pile up for a given subscriber.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;Subscription types&lt;/h4&gt;

&lt;p&gt;In the initial implementation every object is replicated to every subscriber. At a later stage we can implement different subscription type handlers that will enable limiting the subscription to particular MgdSchema types, object trees or even particular query constraints.&lt;/p&gt;

&lt;p&gt;Examples of subscription types would be &quot;content in tree&quot;, &quot;my tasks&quot; or &quot;all forum posts&quot;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This is rather vague, especially since the neccessary 
  basic infrastructure to provide something like this is
  never mentioned above. Goes into the chapter &quot;missing
  service architecture&quot;.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Import process&lt;/h3&gt;

&lt;p&gt;Import process will simply call the Midgard &lt;code&gt;import&lt;/code&gt; method for each object in the imported XML file.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;No sanity checks, nothing? I think there has to be a high
  level of bulletproofing when letting such replications in.&lt;/p&gt;
  
  &lt;p&gt;Torben&lt;/p&gt;
&lt;/blockquote&gt;
</description>
            <author>Piotr Pokora &lt;piotrek.pokora@gmail.com&gt;</author>
            <pubDate>Fri, 02 Jun 2006 17:47:52 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-b8a2c4d18d1566cf608c40f75774f96d</guid>
        </item>
        <item>
            <title>MidgardCollector</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0029.html</link>
            <description>
&lt;h1&gt;Revision history&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;2006-05-18 Created by Piotr Pokora &lt;/li&gt;
&lt;li&gt;2006-05-18 Added use case examples by Piotr Pokora &lt;/li&gt;
&lt;li&gt;2006-06-14 Constraint specifications and returned data changes by Piotr Pokora &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Background&lt;/h1&gt;

&lt;p&gt;The main idea of MidgardCollector type is code , resources and data reusability for all data values which are not objects itself and as part of any object could be retrieved from Midgard database without any need to retrieve full objects' records. MidgardCollector is special limited resource data handler and is optimized for performance and data accessibility. The most important approach is to reuse the same functionality for Midgard features like style engine, objects' parameters and object's attachments.&lt;/p&gt;

&lt;p&gt;However MidgardCollector should be usable for any Midgard type defined for Midgard application.&lt;/p&gt;

&lt;h1&gt;Implementation details&lt;/h1&gt;

&lt;p&gt;MidgardCollector should be implemented as MidgardQueryBuilder wrapper with extended constraints management and extended caching possibilities. Following Midgard objects parameters' convention , MidgardCollector should use 3 constraints to query records drom database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;domain

&lt;ul&gt;
&lt;li&gt;property name and its value to limit selected records&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;name 

&lt;ul&gt;
&lt;li&gt;property name ( and optionally its value ) to limit selected records&lt;/li&gt;
&lt;li&gt;property name which value should be returned as part of a result&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;value

&lt;ul&gt;
&lt;li&gt;property name which value should be returned as part of a result&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally another type should be settable as a parent of the type already initialized for MidgardCollector. In such case type initialized for MidgardCollector should have defined reserved database storage columns not accesible by application. Column names should be prefixed with 'midgard_' namespace like word.&lt;/p&gt;

&lt;h1&gt;Data retrieving&lt;/h1&gt;

&lt;p&gt;MidgardCollector should be initialized only for one particular type. This type's property names should be set as domain , name and value constraints.&lt;/p&gt;

&lt;p&gt;Returned type should be an hash array with collector's name assigned as key and value as  key's value. Additionally guid of an record should be assigned as another array key.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;name -
      |-value -&amp;gt; variable
      |-guid -&amp;gt; variable
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;These hash array should be always set as returned resultset and number of returned records should be limited by domain's value and optionally by name's value. Additionally MidgardQueryBuilder methods like limit or add_constraint or add_order could be used to limit or to order selected records. 
Parent type assigned to MidgardCollector should be also used to limit selected records , limiting returned results by its type name and guid.&lt;/p&gt;

&lt;p&gt;Returned array should be available during the whole application's runtime unless explicitly destroyed by application. If and when returned object should be destroyed depends on application's implementation and its not part of this mRFC.&lt;/p&gt;

&lt;h1&gt;Data overwriting&lt;/h1&gt;

&lt;p&gt;MidgardCollector should be able to overwrite data in existing array by destroying already existing key value pair and replacing it with new name and value. Such overwrite should be done with existing collector's instance , without any need to create new instance of object.&lt;/p&gt;

&lt;h1&gt;Methods&lt;/h1&gt;

&lt;p&gt;MidgardCollector should have implemented methods which allow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set domain and its value&lt;/li&gt;
&lt;li&gt;Set name its value&lt;/li&gt;
&lt;li&gt;Get resultset by domain &lt;/li&gt;
&lt;li&gt;Get resultset by domain and name&lt;/li&gt;
&lt;li&gt;Get resultset limited to parent type&lt;/li&gt;
&lt;li&gt;Destroy name and value&lt;/li&gt;
&lt;li&gt;Destroy the whole collection&lt;/li&gt;
&lt;li&gt;Overwrite value for existing name&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Examples&lt;/h1&gt;

&lt;h2&gt;Style elements&lt;/h2&gt;

&lt;p&gt;Select all style elements' values and render one of them:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$mc = new midgard_collector(&quot;midgard_element&quot;);
$mc-&amp;gt;add_domain(&quot;style&quot;, $_MIDGARD-&amp;gt;page);
$mc-&amp;gt;add_name(&quot;name&quot;);
$mc-&amp;gt;add_value(&quot;value&quot;);

$mc-&amp;gt;execute();

$style_engine-&amp;gt;render($mc-&amp;gt;resultset['ROOT']);
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Parameters&lt;/h2&gt;

&lt;p&gt;Select paremeters by domain, update parameter and collector.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$mc = new midgard_collector(&quot;midgard_parameter&quot;);
$mc-&amp;gt;add_domain(&quot;domain&quot;, &quot;midcom&quot;);
$mc-&amp;gt;add_name(&quot;name&quot;);
$mc-&amp;gt;add_value(&quot;value&quot;);

$mc-&amp;gt;add_parent_type(&quot;midgard_topic&quot;); 
$mc-&amp;gt;add_parent_guid(&quot;fkj34h68d3f1js0du347fh4j4df&quot;); 

$mc-&amp;gt;execute();

$component = $mc-&amp;gt;resultset['component'];

/* update parameter */

$topic = new midgard_topic(&quot;fkj34h68d3f1js0du347fh4j4df&quot;);
$topic-&amp;gt;paramater(&quot;midcom&quot;, &quot;component&quot;, &quot;net.nehmer.static&quot;);
$mc-&amp;gt;add(&quot;component&quot;, &quot;net.nehmer.static&quot;);

$component = $mc-&amp;gt;resultset['component'];
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Attachments&lt;/h2&gt;

&lt;p&gt;Select only image/jpg attachments.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$mc = new midgard_collector(&quot;midgard_blob&quot;);
$mc-&amp;gt;add_domain(&quot;mimetype&quot;, &quot;image/jpg&quot;);
$mc-&amp;gt;add_name(&quot;name&quot;);
$mc-&amp;gt;add_value(&quot;content&quot;);

$mc-&amp;gt;add_parent_type(&quot;midgard_article&quot;); 
$mc-&amp;gt;add_parent_guid(&quot;fkj34h68d3f1js0du347fh4j4df&quot;); 

$mc-&amp;gt;execute();

$retval = $mc-&amp;gt;resultset;
&lt;/code&gt;&lt;/pre&gt;
</description>
            <author>Piotr Pokora &lt;piotrek.pokora@gmail.com&gt;</author>
            <pubDate>Thu, 18 May 2006 12:30:50 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-fcaef8614142662442c04ca760e7e6e0</guid>
        </item>
        <item>
            <title>SVN+PEAR for MidCOM</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0028.html</link>
            <description>
&lt;p&gt;This mRFC is a part of the MidCOM 2.6 release process. It outlines the changes neccessary to make 2.6 source management and PEAR packaging easy to use.&lt;/p&gt;

&lt;p&gt;2006-05-19: Accepted according to the lazy consensus rules.&lt;/p&gt;

&lt;h2&gt;Reasons to switch to SVN&lt;/h2&gt;

&lt;p&gt;The main reason for me why I want SVN is the ability for atomic commits on several files. The ability to track several changes belonging together has become increasingly difficult with CVS in the past, especially since the MidCOM codebase has increased so much in size.&lt;/p&gt;

&lt;p&gt;Since this means greater changes in any way, it is the best point to restructure the repository according to the requirements of easy PEAR packaging:&lt;/p&gt;

&lt;h2&gt;New repository structure&lt;/h2&gt;

&lt;p&gt;The basic idea behind the new structure is separating the source tree into their corresponding PEAR packages.&lt;/p&gt;

&lt;p&gt;The source files of each package will be in their own dir named after the package (to make packaging easy) in a central src directory:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/src/midcom.core
/src/midcom.admin.content
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note that the main package will be renamed to midcom.core. I recommend this to free the package name &quot;midcom&quot; as a meta-package which collects the core and all packages we deem as &quot;required&quot; to get a basic midcom running (f.x. to include required admin components).&lt;/p&gt;

&lt;p&gt;Static files will move to the components &lt;code&gt;static&lt;/code&gt; directory, for example &lt;code&gt;/src/midcom.helper.datamanager2/static/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;PEAR packaging&lt;/h2&gt;

&lt;p&gt;Since SVN now uses one directory per package, the packaging scripts themselves should be easy to simplify.&lt;/p&gt;

&lt;p&gt;To ger MidCOM PEAR releases as frequent as possible, especially in the case of Bug Fixes, a few enhancements have to be made to the packaging script:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Automatic uploads should be possible.&lt;/li&gt;
&lt;li&gt;The Version-Number should be settable (and svn committed) from the command line. Ideally we should have an auto-increment method which increases the current patch-level by one (2.6.0 to 2.6.1 etc.)&lt;/li&gt;
&lt;li&gt;The full pear packaging process should be hidden.&lt;/li&gt;
&lt;li&gt;All temporary files should go to a temporary dir outside SVN (&lt;code&gt;/tmp&lt;/code&gt; perhaps). &lt;/li&gt;
&lt;li&gt;The new version number should be tagged in SVN implicitly.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Example session:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd src/midcom.core
midcom-package 2.6.0
# Package is built to src/midcom.core-2.6.0.tgz
midcom-upload ../midcom.core-2.6.0.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Session with implicit upload:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd src/midcom.core
midcom-package -u 2.6.0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Session with auto-increment:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd src/midcom.core
midcom-package -u
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Releasenotes&lt;/h3&gt;

&lt;p&gt;Ideally, the new PEAR Package Tool can generate Package release notes automatically from the CHANGES file in the documentation directory.&lt;/p&gt;

&lt;p&gt;It should be not to hard to identify the entries since the last release since an entry is always started by a ISO Timestamp.&lt;/p&gt;

&lt;h2&gt;Running MidCOM from SVN&lt;/h2&gt;

&lt;p&gt;Obviously, MidCOM can no longer be run from SVN using this structure. Thus, a simple script which creates a symlinked tree of MidCOM must be written (otherwise development will be hell).&lt;/p&gt;

&lt;p&gt;All standard components should be linkable with a single symlink to their root / static directories. Special care must only be taken for midcom.core which has to be linked on a file-level hierarchy to allow adding components like &lt;code&gt;midcom.helper.search&lt;/code&gt; etc.&lt;/p&gt;
</description>
            <author>Torben Nehmer &lt;torben &lt;at&gt; nehmer &lt;dot&gt; net&gt;</author>
            <pubDate>Mon, 08 May 2006 20:56:06 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-159867aafba85f943a9be10008fc59a4</guid>
        </item>
        <item>
            <title>Midgard sitegroup authentication and objectcreation.</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0027.html</link>
            <description>
&lt;h1&gt;Background&lt;/h1&gt;

&lt;p&gt;Sitegroups are logical containers implemented in Midgard to use one database but to separate out different clients by adding an extra sitegroup attribute to all records in the database.&lt;/p&gt;

&lt;p&gt;There is also a sitegroup 0 (SG0) that is special in that all items from that sitegroup are read-only from other sitegroups (SGn) and may act as parents to an object (for example a style) in a sitegroup.&lt;/p&gt;

&lt;p&gt;There are some usecases that need to be understood with regard to sitegroups. They are described in this document.&lt;/p&gt;

&lt;p&gt;The basic information about sitegroups can be found in documentation:
http://www.midgard-project.org/midcom-permalink-f624e440f76a466d5870374bca8e1449&lt;/p&gt;

&lt;h1&gt;Sitegroup ID&lt;/h1&gt;

&lt;p&gt;Up to and including 1.7 the sitegroup id has been an integer. In the future the attribute may be an integer (id) or string ( guid or uuid ) which identifies sitegroup by its record in database. The type of identifier depends on implementation.&lt;/p&gt;

&lt;h1&gt;Sitegroup creation&lt;/h1&gt;

&lt;p&gt;Sitegroup can be created only by authenticated person which is member of the Administration group in Sitegroup 0 ( SG0 ). These are the only users who can delete or update sitegroups as well.&lt;/p&gt;

&lt;p&gt;When a sitegroup is created, it needs to be created with an adminigroup and a administrator.&lt;/p&gt;

&lt;p&gt;The following code is a sample of how sitegroup creation should work for midgard 1.8:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// create the sitegroup 
$sitegroup = new midgard_sitegroup();
$sitegroup-&amp;gt;name = &quot;Sitegroup&quot;;
$sitegroup-&amp;gt;create();
// create the admin and the admingroup
$group = new midgard_group();
$group-&amp;gt;name = &quot;admingroup&quot;;
$group-&amp;gt;sitegroup = $sitegroup-&amp;gt;id;
$group-&amp;gt;create();
// create the admin
$person = new midgard_person();
$person-&amp;gt;username = &quot;admin&quot;;
$person-&amp;gt;sitegroup= $sitegroup-&amp;gt;id; 
$person-&amp;gt;create();
mgd_update_password($person-&amp;gt;id, $person-&amp;gt;username, &quot;pwd&quot;);
$member = new midgard_member();
$member-&amp;gt;uid = $person-&amp;gt;id;
$member-&amp;gt;gid = $group-&amp;gt;id;
$member-&amp;gt;sitegroup = $sitegroup-&amp;gt;id;
$member-&amp;gt;create();
$sitegroup-&amp;gt;admingroup = $group-&amp;gt;id;
$sitegroup-&amp;gt;update();
[NOT TESTED!]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;How should this look for 1.7?&lt;/p&gt;

&lt;h1&gt;Creation of sitegrouped objects from sitegroup 0.&lt;/h1&gt;

&lt;p&gt;There are some usecases where the SG0 admins want to create objects into a sitegroup.&lt;/p&gt;

&lt;h3&gt;Creation in 1.7.&lt;/h3&gt;

&lt;p&gt;To creat an object in midgard 1.x , x&amp;lt;=7, you need to run the following code:
   $obj = mgd_get_object();
   $obj-&gt;name = &quot;some name&quot;;
   // set some other attributes
   $id = $obj-&gt;create();
   $obj = mgd_get_object($id);
   $obj-&gt;setsitegroup($sgid);&lt;/p&gt;

&lt;p&gt;This will change the objects sitegroup, but not attachments or parameters creatd before changing the objects sitegroup, they will remain in SG0. Also, if you add attachments and parameters to the object later as SG0 these parameters will also stay SG0.&lt;/p&gt;

&lt;h3&gt;Suggested change to 1.7:&lt;/h3&gt;

&lt;p&gt;Setsitegroup() should change the sitegroup of the objects attachments and parameters as well.&lt;/p&gt;

&lt;h3&gt;Creation in 1.8&lt;/h3&gt;

&lt;p&gt;In 1.8 the following [NOT IMPLEMENTED] rules apply to adding a sitegroup to an object:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1) If user is in SGn (n &amp;gt; 0), create object in SGn
2) If parent object is in SGn (n &amp;gt; 0), create object in SGn
3) If sitegroup property is set to SGn (n &amp;gt; 0), create object in SGn
4) Otherwise create object in SG0
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This implies that you cannot change the sitegroup of a created object after it has been created. &lt;strong&gt;you cannot change the sitegroup using the update method&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The only way to change the objects sitegroup once it is created, is to export it and import it through replication by another sitegroups person.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; $obj-&gt;update() should return false when a user tries to reset an objects sitegroup and return the error &quot;Sitegroup cannot be changed after creation.&quot;, error number 32.&lt;/p&gt;

&lt;p&gt;[NOT IMPLEMENTED]&lt;/p&gt;

&lt;h3&gt;Updating objects&lt;/h3&gt;

&lt;p&gt;When a SG0 admin updates an object, different attached records like quota or metadata, may be affected. These records should get the same sitegroup as the object - not the sitegroup of the application.&lt;/p&gt;

&lt;h1&gt;Application sitegroup&lt;/h1&gt;

&lt;p&gt;Every Midgard application ( which uses midgard connection and midgard  database ) runs in a sitegroup context.&lt;/p&gt;

&lt;p&gt;The context of a sitegroup'ed application is identified by sitegroup's identifier assigned as member of the midgard connection. Application's sitegroup can be set ( or even changed ) in one way only - by authentication as a user.&lt;/p&gt;

&lt;h2&gt;Setting the application sitegroup with no authenticated user.&lt;/h2&gt;

&lt;p&gt;Today, when no user is logged in, the application runs in anonymous mode. If the application is running through Apache, the application sitegroup is set according to the sitegroup of the  current page. [NOT VERIFIED]&lt;/p&gt;

&lt;h3&gt;Anonymous mode as a user.&lt;/h3&gt;

&lt;p&gt;It is suggested to change the way the anonymous mode works. 
To run application in anonymous mode( when the application must be used
within particular sitegroup context and no person should be logged in )
anonymous account should be created for particular sitegroup. Access control
for the anonymous account should be covered by the ACL mRFC.&lt;/p&gt;

&lt;p&gt;The anonymous account may be duplicated ( replicated ) between different sitegropups as long as as can be identified by particular sitegroup, even when record itself is identified by
the same guid or uuid. When sitegroup has no anonymous user, the application
should run in SG0 context.&lt;/p&gt;

&lt;h2&gt;Issues&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What should be done with available resources when sitegroup context is changed when application runs?&lt;/li&gt;
&lt;li&gt;What should be done with SG0 and with SGn available resources?&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Sitegroups and authentication.&lt;/h1&gt;

&lt;p&gt;Today login to Midgard happens in two ways:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;- Through basic authentication where the user may only enter username and password.
- Through the function mgd_auth_midcom($username, $password, $sendcookie)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Many if not most sites uses the mgd_auth_midcom function.&lt;/p&gt;

&lt;p&gt;A problem is that midgard needs to determine the sitegroup the user has before checking the password as a username may exist in more than one sitegroup. This is solved in versions up to 1.8 by using a delimiter and the sitegroup name.&lt;/p&gt;

&lt;p&gt;A problem with this approach is that the delimiters may be used in the username. When this happens, logins will fail as Midgard cannot divide the username-sitegroup combo properly.&lt;/p&gt;
</description>
            <author>Tarjei Huse &lt;tarjei@nu.no&gt;</author>
            <pubDate>Fri, 10 Mar 2006 09:56:51 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-e234ade3c7cdc6f2798b709b69af8bee</guid>
        </item>
        <item>
            <title>On-Site Toolbar Management for MidCOM 2.6+</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0026.html</link>
            <description>
&lt;p&gt;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.&lt;/p&gt;

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

&lt;h2&gt;Requirements&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;This document will give a complete overview about the required functionality.&lt;/p&gt;

&lt;h3&gt;What should be managed?&lt;/h3&gt;

&lt;p&gt;There are several &quot;levels&quot; on which objects should be managed. Generally speaking, there is a &lt;em&gt;node&lt;/em&gt;, &lt;em&gt;page&lt;/em&gt; and &lt;em&gt;object&lt;/em&gt; level. This distinction is based on the scope of the operation being done:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Node&lt;/em&gt; operations affect the whole topic. They are not bound to a specific article, leaf or similar, more specific structure. Stuff like &quot;Create new article&quot; 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 &quot;top&quot; AIS toolbar.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Page&lt;/em&gt; operations affect the &lt;em&gt;main object&lt;/em&gt; 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 &quot;standard&quot; article on the frontpage. This especially means, that under normal circumstances only a component can reliably add information to this toolbar. Stuff like &quot;Edit object&quot; will go into this toolbar. This represents the original &quot;lower&quot; AIS toolbar.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Object&lt;/em&gt; operations are special toolbars which apply only to a single object being displayed in the current page. If you take cases like the original &lt;code&gt;net.siriux.photos&lt;/code&gt; 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives us essentially two toolbars which are always present (&lt;em&gt;node&lt;/em&gt; and &lt;em&gt;page&lt;/em&gt;) 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.&lt;/p&gt;

&lt;h3&gt;&lt;em&gt;page&lt;/em&gt; vs. &lt;em&gt;object&lt;/em&gt; toolbars&lt;/h3&gt;

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

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

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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).&lt;/p&gt;

&lt;p&gt;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 &quot;possibilities&quot;, and active objects are a rather flexible term.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;The new toolbar system thus has to cover both cases.&lt;/p&gt;

&lt;p&gt;The proposed way to do this is to a) give the &lt;em&gt;page&lt;/em&gt; 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 &lt;em&gt;page&lt;/em&gt; toolbar.&lt;/p&gt;

&lt;h3&gt;Context sensitivity aka &quot;dynamic load support&quot;&lt;/h3&gt;

&lt;p&gt;The MidCOM dynamic load (&quot;dl&quot;) facility introduces quite a few complicaitons into this, as it blurs the idea of a single toolbar for a page quite a bit.&lt;/p&gt;

&lt;p&gt;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.)&lt;/p&gt;

&lt;p&gt;The original implementation in &lt;code&gt;midcom_helper_toolbars&lt;/code&gt; is not safe in this respect.&lt;/p&gt;

&lt;h2&gt;Proposed API&lt;/h2&gt;

&lt;p&gt;Even though the current &lt;code&gt;midcom_helper_toolbars&lt;/code&gt; 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.)&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;The &lt;code&gt;toolbars&lt;/code&gt; Service&lt;/h3&gt;

&lt;p&gt;What I propose is having a &lt;code&gt;midcom_services_toolbars&lt;/code&gt; available as &lt;code&gt;$_MIDCOM-&amp;gt;toolbars&lt;/code&gt; which serves as a central proxy for all toolbar related operations.&lt;/p&gt;

&lt;p&gt;Basic API draft:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class midcom_services_toolbars
{
    midcom_helper_toolbar_node &amp;amp; get_node_toolbar($context = $current_context);
    midcom_helper_toolbar_page &amp;amp; get_page_toolbar($context = $current_context);

    midcom_helper_toolbar_object create_object_toolbar(&amp;amp;object);

    string render_node_toolbar($context = $current_context);
    string render_page_toolbar($context = $current_context);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Due to the context sensitivity, it is currently not possible to provide direct references to the &lt;em&gt;object&lt;/em&gt; and &lt;em&gt;page&lt;/em&gt; 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).&lt;/p&gt;

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

&lt;pre&gt;&lt;code&gt;// some site style element
$toolbar =&amp;amp; $_MIDCOM-&amp;gt;get_node_toolbar();
$toolbar-&amp;gt;do_something($tm);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Rendering though is even easier:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;// some site style element
$_MIDCOM-&amp;gt;toolbars-&amp;gt;render_node_toolbar();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You will usually only render the current context's toolbars. The &lt;code&gt;$context&lt;/code&gt; option should be considered reversed for core usage.&lt;/p&gt;

&lt;p&gt;Note, that the render call will automatically add the neccessary CSS classes if neccessary.&lt;/p&gt;

&lt;h3&gt;The toolbar classes&lt;/h3&gt;

&lt;p&gt;All toolbar instances used will derive from &lt;code&gt;midcom_helper_toolbar&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The code of this class needs to be cleaned up a bit, especially to allow easier default usage. Instead of the current&lt;/p&gt;

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

&lt;p&gt;the class should automatically apply the defaults:&lt;/p&gt;

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

&lt;p&gt;Apart from this the &lt;em&gt;page&lt;/em&gt; toolbar must have at least one special interface function:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class midcom_helper_toolbar_page extends midcom_helper_toolbar
{
    void bind_to_object(&amp;amp;$object);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;bind_to_object&lt;/code&gt; call essentially does add the &lt;em&gt;object&lt;/em&gt; 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.&lt;/p&gt;

&lt;p&gt;Depending on the implementation itself, other private helpers and public convenience methods will be added, of course.&lt;/p&gt;

&lt;h3&gt;Request API integration&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;class midcom_baseclasses_components_request ...
{
    var $_node_toolbar;
    var $_page_toolbar;

    ...

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

        ...
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This will be done not only for convenience but also to protect the average user from missing the reference-assignment neccessary.&lt;/p&gt;

&lt;h2&gt;Open questions / TODOs&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Should the toolbar classes be moved into the services hirarchy as well? Example: &lt;code&gt;midcom_helper_toolbars_toolbar&lt;/code&gt; instead of &lt;code&gt;midcom_helper_toolbar&lt;/code&gt; 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.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There is urgent need for beautification of these toolbars, especially various styles would be good. Some advanced menu
style could be of help.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-level toolbars (in conjunciton with a dropdown menu style) would be useful as well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The browser-driven tooltips should be replaced by some &lt;a href=&quot;http://www.bosrup.com/web/overlib/&quot;&gt;Overlib&lt;/a&gt; driven tooltip to work around the limitations of the browsers when rendering the tooltips (and thus also allowing HTML there).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
            <author>Torben Nehmer &lt;torben &lt;at&gt; nehmer &lt;dot&gt; net&gt;</author>
            <pubDate>Mon, 27 Feb 2006 16:58:52 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-b2229139731f9754da927c2cefc45d4e</guid>
        </item>
        <item>
            <title>Midcom site startup and configuration.</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0025.html</link>
            <description>
&lt;p&gt;This is an outline for how future MidCOM Sites should be created and
configured.&lt;/p&gt;

&lt;h2&gt;Background:&lt;/h2&gt;

&lt;p&gt;The current solution to set up MidCOM sites uses the Midgard Template to
create sites. The current template is slow and is hard to modify.&lt;/p&gt;

&lt;p&gt;For those who do not know, the following is an example of the setup of a
very basic MidCOM site.&lt;/p&gt;

&lt;p&gt;Midcom goes through three stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;initialization and startup&lt;/li&gt;
&lt;li&gt;Content output&lt;/li&gt;
&lt;li&gt;Ending. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most basic site template for use in MidCOM is this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php 
$GLOBALS['midcom_config_local']['midcom_root_topic_guid'] =
&quot;860f1b5af98b409abd916a80cdb0d68e&quot;;
require 'midcom.php';
$_MIDCOM-&amp;gt;codeinit();
?&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;?php
echo $_MIDCOM-&amp;gt;print_head_elements();

?&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body &amp;lt;?php echo $_MIDCOM-&amp;gt;print_jsonload(); ?&amp;gt; &amp;gt; 

&lt;?php echo $_MIDCOM-&gt;content(); ?&gt;

&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;?php $_MIDCOM-&gt;finish(); ?&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Site configuration&lt;/h2&gt;

&lt;p&gt;Today site configuration is contained in parameters to the host. This is
fairly inefficient as this generates a large set of queries to the
database on every request.&lt;/p&gt;

&lt;p&gt;The new system will not use a common rootpage for all sites. Instead common functionality is shared using styles.&lt;/p&gt;

&lt;p&gt;Instead of keeping the configuration in parameters it should be kept in
a simple pageelement that is included into the request by changing the normal midgard-root.php file to something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;(code-midcom-start)&amp;gt; &amp;lt;-- This element is autogenerated as outlined above
&amp;lt;(code-global)&amp;gt;
&amp;lt;(code-init)&amp;gt;
&amp;lt;(ROOT)&amp;gt; &amp;lt;-- the style calls $_MIDCOM-&amp;gt;content()
&amp;lt;(code-finish)&amp;gt;
&amp;lt;(code-midcom-finish)&amp;gt; &amp;lt;-- Calling $_MIDCOM-&amp;gt;finish();
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The following parameter must be set in the configuration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$GLOBALS['midcom_config_local']['midcom_root_topic_guid'] =
&quot;860f1b5af98b409abd916a80cdb0d68e&quot;;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Versioning&lt;/h2&gt;

&lt;p&gt;Hosts using this configuration will be defined as using version 1 and have the parameter &quot;midgard&quot;, &quot;midcom-configuration-version&quot; set to 1.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$host-&amp;gt;parameter(&quot;midgard&quot;, &quot;midcom-configuration-version&quot;, 1 );
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Hosts missing this parameter are expected not to run Midcom unless they have set their rootpage to the common MidCOM rootpage used in Midcom-Template today.&lt;/p&gt;

&lt;h2&gt;Site authentication&lt;/h2&gt;

&lt;p&gt;Today site authentication is handled by the old Nemein-Auth library.
This library is snippetbased and old. The new MidCOM authentication
libary exists and should be used instead. Thus there will not be
anything authentication related in the simple code-init.&lt;/p&gt;

&lt;h2&gt;The &quot;midcom_site&quot; array&lt;/h2&gt;

&lt;p&gt;Today, the template populates the midcom_site array with some objects as
well.&lt;/p&gt;

&lt;p&gt;This array should only be created in the compability style for the old Midcom-Template.&lt;/p&gt;

&lt;h2&gt;Site Configuration&lt;/h2&gt;

&lt;p&gt;Setting of page/host configuration options handled through a datamanager2 schema driven MidCOM.&lt;/p&gt;

&lt;p&gt;The editor most be accessable even when the site is down for some reason.&lt;/p&gt;

&lt;p&gt;This could be done today using a dummy topic[1] that could be set to run
MidCOM with a configuration module, and then run a normal MidCOM
session. This is a stopgap measure.&lt;/p&gt;

&lt;p&gt;Another option is a very simple stylelement that lets the user edit just the path to midcom and/or the generated pageelement in an atempt to generate a working configuration.&lt;/p&gt;

&lt;h2&gt;Implementation&lt;/h2&gt;

&lt;p&gt;The following needs to be done:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A MidCOM for generating the configuration must be created. &lt;/li&gt;
&lt;li&gt;&lt;p&gt;Todays M-T must be refactored into two styles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one simple style&lt;/li&gt;
&lt;li&gt;one backward compatible style
Both styles depend on a common root style.&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A midcom for creating hosts must be made.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;A midcom for creating Sitegroups must be made.&lt;/li&gt;
&lt;li&gt;A midcom that takes the other midcom and makes a Form-wizard out of them must be made.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please note that many of the implementation details must be left for another mRFC (f.x. how should sitecreation be configured in the future).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;[1] Dummy topic&lt;/strong&gt;
Midcom currently needs a topic to be able to run. By creating a set of dummy topics and then setting the
    $GLOBALS['midcom_config_local']['midcom_root_topic_guid'] 
it is possible to run a normal midcom component without having to create a local topic for it.&lt;/p&gt;
</description>
            <author>Tarjei Huse &lt;tarjei@nu.no&gt;</author>
            <pubDate>Sat, 11 Feb 2006 18:25:58 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-307940d91acd7e70423358aab6c8a0a9</guid>
        </item>
        <item>
            <title>Workflow in Midgard</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0023.html</link>
            <description>
&lt;p&gt;This proposal describes a workflow engine built for handling tasks, processes and workflows within MidCOM applications. This mRFC been submitted to the Midgard Community for discussion and approval under the Creative Commons Attribution-ShareAlike license.&lt;/p&gt;

&lt;h2&gt;Workflow&lt;/h2&gt;

&lt;p&gt;Wikipedia defines &lt;a href=&quot;http://en.wikipedia.org/wiki/Workflow&quot;&gt;workflow&lt;/a&gt; as:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Workflow is the operational aspect of a work procedure: how tasks are structured, who performs them, what their relative order is, how they are synchronized, how information flows to support the tasks and how tasks are being tracked. As the dimension of time is considered in Workflow, Workflow considers &quot;throughput&quot; as a distinct measure. Workflow problems can be modeled and analyzed using Petri nets.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Workflow is not for everybody&lt;/h3&gt;

&lt;p&gt;In the &lt;a href=&quot;http://www.jwz.org/doc/groupware.html&quot;&gt;Groupware bad&lt;/a&gt; paper, Jamie Zawinski comments that&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&quot;Groupware&quot; is all about things like &quot;workflow&quot;, which means, &quot;the chairman of the committee has emailed me this checklist, and I'm done with item 3, so I want to check off item 3, so this document must be sent back to my supervisor to approve the fact that item 3 is changing from 'unchecked' to 'checked', and once he does that, it can be directed back to committee for review.&quot;&lt;/p&gt;
  
  &lt;p&gt;Nobody cares about that shit. Nobody you'd want to talk to, anyway.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While this is true for a lot of use cases, there are still heavily regulated industries and activities where well defined and coordinated workflows are a must. This mRFC is split into two pieces: &lt;em&gt;Task management&lt;/em&gt; and &lt;em&gt;Workflow management&lt;/em&gt;. While workflows are needed by only some, task management should be useful for almost all Midgard users.&lt;/p&gt;

&lt;h3&gt;Prototypes and implementations&lt;/h3&gt;

&lt;p&gt;TODO&lt;/p&gt;

&lt;h4&gt;Object model&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Trail&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trails are the prototypes of processes&lt;/li&gt;
&lt;li&gt;Trails have a &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Trails may have a field map used if the trail is instantiated by a &lt;em&gt;Spawn&lt;/em&gt; 
step in another process for copying data from that process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Steps have a &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Steps have a &lt;code&gt;type&lt;/code&gt; telling which workflow phase it is&lt;/li&gt;
&lt;li&gt;Steps have an &lt;code&gt;up&lt;/code&gt; field telling after which step (predecessor) they begin

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Join&lt;/em&gt; and &lt;em&gt;Start&lt;/em&gt; steps don't have &lt;code&gt;up&lt;/code&gt; field defined, they get their 
predecessors from deliverables&lt;/li&gt;
&lt;li&gt;Only &lt;em&gt;Decisions&lt;/em&gt; and &lt;em&gt;Splits&lt;/em&gt; may have multiple successors&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Steps are the prototypes of tasks and belong to a trail&lt;/li&gt;
&lt;li&gt;Steps are assigned to roles (i.e. &lt;code&gt;midgard_groups&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Steps have two time definitions: &lt;code&gt;start&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; (deadline)

&lt;ul&gt;
&lt;li&gt;The end definition is some offset from a selected earlier step end&lt;/li&gt;
&lt;li&gt;The start definition is some offset from the step's end&lt;/li&gt;
&lt;li&gt;Both offset selections provide an integer field and pulldown 
(hours, days, weeks, months) for user input&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Process&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trail is the parent of the process

&lt;ul&gt;
&lt;li&gt;Process creation is a &lt;code&gt;midgard:create&lt;/code&gt; privilege inherited from trail&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Process has an &lt;code&gt;owner&lt;/code&gt; person, and &lt;code&gt;started&lt;/code&gt; and &lt;code&gt;completed&lt;/code&gt; timestamps&lt;/li&gt;
&lt;li&gt;Process has a &lt;code&gt;start&lt;/code&gt; timestamp telling when the &lt;em&gt;Start task&lt;/em&gt; has to be 
created

&lt;ul&gt;
&lt;li&gt;There is a daily check in &lt;code&gt;cron&lt;/code&gt; service to start processes&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Task&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mainly the existing &lt;code&gt;org_openpsa_task&lt;/code&gt; implementation&lt;/li&gt;
&lt;li&gt;Task has optional &lt;code&gt;process&lt;/code&gt; and &lt;code&gt;step&lt;/code&gt; link attributes&lt;/li&gt;
&lt;li&gt;Tasks are assigned to persons (single or multiple) using member objects&lt;/li&gt;
&lt;li&gt;Autocloseable&lt;/li&gt;
&lt;li&gt;Skippable&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Workflow phases&lt;/h4&gt;

&lt;p&gt;All workflow phases are modeled as steps, and handled during process&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start&lt;/strong&gt; (circle)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start is never instantiated as &lt;em&gt;Task&lt;/em&gt;, and is simply used to lead to first 
actual step&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Action&lt;/strong&gt; (box)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Actions are regular tasks within the workflow&lt;/li&gt;
&lt;li&gt;Actions always have a predecessor (&lt;code&gt;up&lt;/code&gt;), and a successor (phase which has 
&lt;code&gt;up&lt;/code&gt; pointing to this step)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Decision&lt;/strong&gt; (diamond)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decision editor asks for icon and text label of decision per each child
step

&lt;ul&gt;
&lt;li&gt;The editor must be available both in the decision step, and in each
child&lt;/li&gt;
&lt;li&gt;Icons are presented as a selection list populated from component config 
array&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Split&lt;/strong&gt; (triangle pointing down)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Split is never instantiated as &lt;em&gt;Task&lt;/em&gt;, and is simply used for pointing to
succeeding steps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Join&lt;/strong&gt; (triangle pointing up)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Join is a real &lt;em&gt;Auto-closing&lt;/em&gt; task pointing to predecessors that must be 
completed via deliverables&lt;/li&gt;
&lt;li&gt;Join is created only after all predecessor tasks exist&lt;/li&gt;
&lt;li&gt;Joins don't have assignees in most cases -&gt; rendered only in process view&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;End&lt;/strong&gt; (two concentric circles, innermost filled)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;End is never instantiated as a &lt;em&gt;Task&lt;/em&gt;. Instead, the process is completed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Spawn&lt;/strong&gt; (octagon)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starts another process, passing some information to it&lt;/li&gt;
&lt;li&gt;Spawn is a &quot;dead end&quot; step that that may not have successors, and does not
complete the process&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Prototype management&lt;/h4&gt;

&lt;p&gt;UI description/mock-up here&lt;/p&gt;

&lt;h2&gt;Task management&lt;/h2&gt;

&lt;p&gt;Task handling is centered into a &lt;em&gt;Task Inbox&lt;/em&gt; where the user can see a list of her current open tasks. The tasks may come from active workflow processes, OpenPsa projects, support tickets, or be simply standalone tasks like &quot;Remember to buy milk&quot;.&lt;/p&gt;

&lt;h3&gt;Deliverables&lt;/h3&gt;

&lt;p&gt;Deliverables are actual results of the task work. For example, if user is assigned to write a report about something, the deliverable could be a new OpenOffice.org document placed into a directory in the &lt;em&gt;org.openpsa.documents&lt;/em&gt; repository, or it could be a wiki page.&lt;/p&gt;

&lt;p&gt;As most workflows are related to highly regulated and paper-based processes, the most important deliverable will be &quot;Create document from template&quot;, which will present user with a datamanager form and an office document template connected to that particular workflow, and will store the resulting document into a specified directory.&lt;/p&gt;

&lt;h4&gt;Deliverable Plugin Interface&lt;/h4&gt;

&lt;p&gt;Pseudocode/stubs from existing implementation.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?php
/**
 * Deliverable object definition in PHP form (actually this is MgdSchema object)
 */
class org_openpsa_deliverable
{
    var $id&quot;; //Local id of the deliverable
    var $plugin; //Name of the plugin used
    var $task; //Id of the task this deliverable is linked to
    var $target; /* Target of the plugin, the plugin interprets the target as it sees fit
                    but generally this is a GUID */

    /**
     * Instances the deliverable plugin interface for this deliverable object 
     * and checks for status via it.
     */
    function status()
    {
    }
}

/**
 * Wrapper class for deliverables operations
 *
 * This allows us to change the ways the plugins work and are loaded at a later
 * time (in case we wish to move them to the actual target components)
 */
class org_openpsa_projects_deliverables_interface
{
    var $_plugins = array(); //List of plugins available

    /**
     * Searches for plugins and fills $this-&amp;gt;_plugins
     */
    function _find_plugins()
    {
    }

    /**
     * Returns an array of available plugins as objects
     */
    function list_plugins()
    {
    }

    /**
     * Checks all deliverables for task returns true if all return true otherwise false
     * @param integer $task_id Identifier of an OpenPsa Projects task
     * @return boolean Whether all deliverables of the task have been completed
     */
    function check_all_deliverables_status($task_id)
    {
    }

    /**
     * Takes plugin name and returns plugins classname for instancing
     */
    function _resolve_plugin($plugin)
    {
    }

    /**
     * Based on deliverable object id/guid returns correct plugin initialized
     */
    function get_deliverable_plugin($identifier)
    {
    }

    /**
     * Returns an empty (not initialized with deliverable object) plugin for plugin name
     */
    function get_plugin($name)
    {
    }
}

/**
 * Baseclass for deliverables plugins
 */
class org_openpsa_projects_deliverables_interface_plugin
{
    var $_deliverable; //A deliverable object
    var $name; //Name of the plugin
    var $description; //Description of the plugin

    /**
     * Returns true or false depending on whether the plugin considers the target
     * &quot;delivered&quot; or not.
     * @return boolean
     */
    function status()
    {
    }

    /**
     * In task view the select plugin(s) row for this
     */
    function render_select_plugin($task_id=NULL)
    {
    }

    /**
     * Creates the deliverable object (NOTE: not the target)
     */
    function handle_select_plugin($task_id)
    {
    }

    /**
     * Depending on deliverable status this will either render a way to
     * create the target or a link to the target
     *
     * There are two modes, 'task' and 'todo' for different renderings.
     */
    function render_deliverable($mode = 'task')
    {
    }

    /**
     * This will create the deliverable target
     *
     * At this time the mode selection has no effect.
     */
    function handle_deliverable($mode = 'task')
    {
    }
}

?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;Task micro-workflow&lt;/h3&gt;

&lt;p&gt;In addition to the regular workflows, all tasks within Midgard have a micro-workflow related to assigning it between people. This micro-workflow goes in the following way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project manager assigns tasks to resources&lt;/li&gt;
&lt;li&gt;Resources can be local or remote (DBE) users&lt;/li&gt;
&lt;li&gt;Resources can accept or decline task

&lt;ul&gt;
&lt;li&gt;Hours can be reported to task after acceptance &lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;When task is finished resources can mark it as completed

&lt;ul&gt;
&lt;li&gt;Task's deliverables (document, SVN commit, ...) must be completed first &lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;Project manager must approve the task before it is closed&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- Insert microworkflow graph project-workflow.png --&gt;

&lt;p&gt;When user assigns a task to herself the &lt;code&gt;proposed&lt;/code&gt; phase is skipped and task is automatically &lt;code&gt;accepted&lt;/code&gt; by the user, by same logic if user who is also &lt;code&gt;manager&lt;/code&gt; of task marks it as completed the task is &lt;code&gt;approved&lt;/code&gt; and &lt;code&gt;closed&lt;/code&gt; automatically.&lt;/p&gt;

&lt;h3&gt;Getting Things Done&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;http://www.43folders.com/2004/09/08/getting-started-with-getting-things-done/&quot;&gt;Getting Things Done&lt;/a&gt; is a popular task management methodology that focuses on storing all tasks, and making them easily filtrable based on the current working mode, or &lt;em&gt;context&lt;/em&gt;. An important concept is elimination of &quot;stuff&quot;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Getting Things Done succeeds because it first addresses a critical barrier to completing the atomic tasks that we want to accomplish in a given day. That’s “stuff.” Amorphous, unactionable, flop-sweat-inducing stuff. David says:&lt;/p&gt;
  
  &lt;p&gt;Here’s how I define “stuff:” anything you have allowed into your psychological or physical world that doesn’t belong where it is, but for which you haven’t yet determined the desired outcome and the next action step. [pg. 17]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To &lt;a href=&quot;http://www.minezone.org/wiki/MVance/GettingThingsDone&quot;&gt;follow the Getting Things Done model&lt;/a&gt;, the Midgard task manager must make &lt;strong&gt;addition and timing of new tasks&lt;/strong&gt; easy. It also must enable marking tasks into specific &lt;strong&gt;contexts&lt;/strong&gt;, and filtering them by those.&lt;/p&gt;

&lt;h3&gt;Digital Business Ecosystem&lt;/h3&gt;

&lt;p&gt;Midgard's task management is connected to the &lt;a href=&quot;http://www.digital-ecosystem.org/&quot;&gt;Digital Business Ecosystem&lt;/a&gt;. With DBE Midgard tasks can be replicated between business partners in a P2P network.&lt;/p&gt;

&lt;p&gt;The DBE connection works transparently for the user of the Midgard task manager. she just assigns tasks to remote users (identified by a different icon in user listings), or receives tasks from them. The micro-workflow and handling of deliverables remains the same.&lt;/p&gt;

&lt;p&gt;The actual DBE implementation is a Java ServENT (Server-Client) that monitors changes in tasks through Midgard-Java and pushes them to partners via the DBE network.&lt;/p&gt;

&lt;h3&gt;Synchronization&lt;/h3&gt;

&lt;p&gt;To support &lt;em&gt;Getting Things Done&lt;/em&gt;, Midgard task management should try to reach beyond the web. Lots of the &lt;em&gt;Contexts&lt;/em&gt; may be something that must be done away from the desktop, and these should be synchronizable to the smartphone, PDA or whatever.&lt;/p&gt;

&lt;p&gt;The main synchronization protocol for mobile devices is &lt;a href=&quot;http://www.openmobilealliance.org/tech/affiliates/syncml/syncmlindex.html&quot;&gt;SyncML&lt;/a&gt;. While a &lt;a href=&quot;http://www.horde.org/sync/&quot;&gt;Horde SyncML&lt;/a&gt; implementation in PHP exists, it is lacking in client support. Midgard task manager, and other PIM applications should support SyncML through the Java-based &lt;a href=&quot;http://www.sync4j.org/&quot;&gt;Sync4J&lt;/a&gt; implementation instead.&lt;/p&gt;

&lt;p&gt;In addition to SyncML, the task manager should seek to support subscribe-able &lt;a href=&quot;http://en.wikipedia.org/wiki/ICalendar#To-do_.28VTODO.29&quot;&gt;vTODO&lt;/a&gt; output and possible related Microformats.&lt;/p&gt;

&lt;p&gt;Note: According to Tantek from #microformats, the hCalendar microformat can be directly used for vTodo.&lt;/p&gt;

&lt;h2&gt;Misc&lt;/h2&gt;

&lt;p&gt;We need tasks that auto-close when all deliverables have been completed
- Joins are tasks that have the steps to join as deliverables
- Deliverable plugins call a task &lt;code&gt;on_deliverable_completed()&lt;/code&gt; method&lt;/p&gt;

&lt;p&gt;Idea: &quot;skip step&quot;, which opens the next step but keeps current task open as
well, steps need to be specifically marked as &quot;skippable&quot; in the workflow.&lt;/p&gt;

&lt;p&gt;Idea: inserting user-written entries for process's activity log&lt;/p&gt;

&lt;h2&gt;Glossary&lt;/h2&gt;

&lt;dl&gt;
    &lt;dt&gt;assignee&lt;/dt&gt;
        &lt;dd&gt;person that has been assigned to complete a task&lt;/dd&gt;
    &lt;dt&gt;deliverable&lt;/dt&gt;
        &lt;dd&gt;desired outcome of a task. e.g. a document written or decision made by assignee. Task may have multiple deliverables&lt;/dd&gt;
    &lt;dt&gt;process&lt;/dt&gt;
        &lt;dd&gt;an instance of a trail&lt;/dd&gt;
    &lt;dt&gt;role&lt;/dt&gt;
        &lt;dd&gt;abstraction of assignees based on business role. In Midgard terms, a midgard_group&lt;/dd&gt;
    &lt;dt&gt;step&lt;/dt&gt;
        &lt;dd&gt;one step in workflow, steps are prototypes of tasks, steps assignees are roles in stead of persons&lt;/dd&gt;
    &lt;dt&gt;task&lt;/dt&gt;
        &lt;dd&gt;any activity one needs to complete&lt;/dd&gt;
    &lt;dt&gt;trail&lt;/dt&gt;
        &lt;dd&gt;defines the workflow as a series of steps, trails are prototypes of processes&lt;/dd&gt;
&lt;/dl&gt;

&lt;h2&gt;Related work&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.openflow.it/EN/index_html&quot;&gt;OpenFlow&lt;/a&gt; - workflow engine for Python&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://mikespub.net/tools/galaxia/&quot;&gt;Galaxia&lt;/a&gt; - PHP workflow engine&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.tonymarston.net/php-mysql/workflow.html&quot;&gt;An activity based Workflow Engine for PHP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.vivtek.com/wftk/&quot;&gt;wftk&lt;/a&gt; - Workflow Toolkit for C and SOAP&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://web.openwfe.org/display/openwfe/Home&quot;&gt;OpenWFE&lt;/a&gt; - Workflow engine for Java, Python and Perl&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://is.tm.tue.nl/research/patterns/patterns.htm&quot;&gt;Workflow patterns research&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Workflow for Midgard 1.4 (Catalyst IT, New Zealand)&lt;/li&gt;
&lt;li&gt;Building a Smarter To-Do List &lt;a href=&quot;http://www.43folders.com/2005/09/12/building-a-smarter-to-do-list-part-i/&quot;&gt;Part I&lt;/a&gt; and &lt;a href=&quot;http://www.43folders.com/2005/09/13/building-a-smarter-to-do-list-part-ii/&quot;&gt;Part II&lt;/a&gt; (Merlin Mann)&lt;/li&gt;
&lt;/ul&gt;
</description>
            <author>Henri Bergius &lt;henri.bergius@iki.fi&gt;</author>
            <pubDate>Wed, 11 Jan 2006 13:39:22 +0000</pubDate>
            <guid>http://www.midgard-project.org/midcom-permalink-eee8e9aec76e34cf3f0c7c088b9124b5</guid>
        </item>
        <item>
            <title>Full text indexing in Midgard</title>
            <link>http://www.midgard-project.org/development/mrfc/view/0024.html</link>
            <description>
&lt;p&gt;This document proposes a way to support full text indexing in the Midgard core. This document covers both the indexing and querying mechanisms.&lt;/p&gt;

&lt;p&gt;This mRFC been submitted to the Midgard Community for discussion and approval under the Creative Commons Attribution-ShareAlike license.&lt;/p&gt;

&lt;h2&gt;Revision history&lt;/h2&gt;

&lt;p&gt;2006-01-02 Created by Jukka Zitting&lt;/p&gt;

&lt;p&gt;2006-01-03 Revised by Jukka Zitting to incorporate changes and omissions noticed by Torben Nehmer.&lt;/p&gt;

&lt;h2&gt;Background&lt;/h2&gt;

&lt;p&gt;Search functionality has traditionally not been a strong part of the Midgard framework. For a long time Midgard only supported the &lt;code&gt;mgd_list_...&lt;/code&gt; functions as the means for querying the database. More flexibility was gradually introduced by adding new query functions and introducing various optional query parameters in the existing functions. Even with these additions the standard Midgard programming model for more advanced queries was to start from a general object listing and to filter the results programmatically.&lt;/p&gt;

&lt;p&gt;This model performed poorly and was cumbersome to use, so various alternatives were introduced along the way. As Midgard contained no easy and efficient way to make general queries, various external search engines like &lt;a href=&quot;http://www.htdig.org/&quot;&gt;ht://Dig&lt;/a&gt; were often used as an alternative. While this solution produced decent end user search interfaces, it lacked integration with the Midgard object model and caused extra setup and administration overhead.&lt;/p&gt;

&lt;p&gt;Finally a more general solution was introduced by the &lt;a href=&quot;http://www.midgard-project.org/development/projects/midcom/&quot;&gt;MidCOM component framework&lt;/a&gt; version 2.4 in the form of the &lt;a href=&quot;http://www.nathan-syntronics.de/midgard/midcom/midcom-2_4/the-midcom-indexer.html&quot;&gt;MidCOM indexer&lt;/a&gt;. The MidCOM indexer uses the &lt;a href=&quot;http://lucene.apache.org/java/docs/&quot;&gt;Apache Lucene&lt;/a&gt; search engine as a backend for indexing and querying content using the MidCOM component model. The MidCOM indexer is the most powerful Midgard search feature to date, but it is limited to the MidCOM data model and does not detect content changes made by other tools than MidCOM.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;http://www.midgard-project.org/documentation/midgardquerybuilder/&quot;&gt;Midgard Query Builder&lt;/a&gt; was introduced in Midgard version 1.7 as an alternative advanced search feature. The Midgard Query Builder replaces the &lt;code&gt;mgd_list&lt;/code&gt; functions as the default query mechanism in the Midgard core. The Midgard Query Builder is a general purpose tool for searching any Midgard content, but it does not support full text queries and understands only the &lt;a href=&quot;http://www.midgard-project.org/documentation/mgdschema/&quot;&gt;MgdSchema&lt;/a&gt; data model.&lt;/p&gt;

&lt;p&gt;The current state of affairs is that the MidCOM indexer and the Midgard Query Builder together provide a quite complete feature set related to searching, but as they are not integrated and both have separate drawbacks, there still is no ideal solution to Midgard search needs. This document proposes adding full text indexing and other improvements to the Midgard Query Builder in order to overcome some of the limitations and to provide an easier path to an eventual integration with the MidCOM indexer.&lt;/p&gt;

&lt;h2&gt;Requirements&lt;/h2&gt;

&lt;p&gt;The requirements of the full text improvements proposed in this document are listed below:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Integrated API&lt;/dt&gt;
  &lt;dd&gt;
    The full text query API should be integrated with the existing
    Midgard Query Builder. It should be possible to combine traditional
    and full text constraints in a single query.
  &lt;/dd&gt;
  &lt;dt&gt;The MgdSchema data model&lt;/dt&gt;
  &lt;dd&gt;
    The indexer should fully support the MgdSchema data model. All data types
    and properties should be included in the index unless explicitly excluded,
    and it should be possible to query for content regardless of the object
    type or property name. The full text index should also be aware of the
    content tree structure.
  &lt;/dd&gt;
  &lt;dt&gt;Indexing binary attachments&lt;/dt&gt;
  &lt;dd&gt;
    The full text indexer should know how to index the common binary
    attachment formats like MS Word and PDF.
  &lt;/dd&gt;
  &lt;dt&gt;Automatic indexing&lt;/dt&gt;
  &lt;dd&gt;
    The full text index should automatically be kept up to date with the changes
    in the underlying Midgard database. Indexing should be transparent to all
    applications that use the standard Midgard API to modify the Midgard database.
    It should also be possible to manually recreate the entire full text index.
  &lt;/dd&gt;
&lt;/dl&gt;

&lt;h2&gt;The full text index&lt;/h2&gt;

&lt;p&gt;The proposed full text index shall be a &lt;a href=&quot;http://lucene.apache.org/&quot;&gt;Lucene&lt;/a&gt; index directory residing on the host that runs the Midgard applications. If there are multiple web servers accessing a shared backend database, then each frontend server shall have its own full text index. Each Midgard database shall have its own full text index that shall index the objects in all the sitegroups within the database. The index directories shall be located like the current midgard blob directories, i.e. the full text index of a database whose blobs are located in &lt;code&gt;/path/to/midgard/blobs/&lt;em&gt;database&lt;/em&gt;&lt;/code&gt; shall be in &lt;code&gt;/path/to/midgard/index/&lt;em&gt;database&lt;/em&gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The full text index shall contain information about all the MgdSchema objects in a database. All the object metadata (including its type and GUID) is indexed and by default also all the object properties. The special &lt;code&gt;index=&quot;no&quot;&lt;/code&gt; property attribute can be used in the schema declaration to exclude properties from being indexed. The properties are indexed both as separate index fields and as a general node content field. A property can be excluded from the node content field by adding the attribute &lt;code&gt;index=&quot;separate&quot;&lt;/code&gt; in the property definition.&lt;/p&gt;

&lt;p&gt;Parameters and attachment are treated as object properties in the full text index. Parameters are included as virtual properties named &quot;parameter:&lt;em&gt;domain&lt;/em&gt;:&lt;em&gt;name&lt;/em&gt;&quot;, and attachments (whose content can be extracted) as properties named &quot;attachment:&lt;em&gt;name&lt;/em&gt;&quot;. All link fields are stored as GUID entries in the full text index.&lt;/p&gt;

&lt;p&gt;MultiLang content shall be handled by prefixing all the MultiLang property names with the language code. A German version of a &quot;title&quot; property would be indexed as &quot;de:title&quot; while the default &quot;title&quot; property (MultiLang zero) would be indexed simply as &quot;title&quot;. Also the general node content field will be versioned by language.&lt;/p&gt;

&lt;p&gt;The index shall normally be created and queried using the standard analyzer to avoid problems with content in multiple different languages. It is possible that a future extension will add support for semi-automated language analyzers based on the Midgard MultiLang feature.&lt;/p&gt;

&lt;p&gt;The index directory shall be read directly by the midgard-core component in all Midgard application processes, but written by a separate indexer process. The indexer process shall monitor the Midgard database directly for record changes instead of relying on notifications from the Midgard applications. This makes the full text system robust in the face of indexer failures and reduces the amount of dependencies across different functions. The drawback of this approach is a slight delay before content changes are reflected in the full text index.&lt;/p&gt;

&lt;h2&gt;The parent cache&lt;/h2&gt;

&lt;p&gt;In addition to maintaining the full text index, the indexer shall also maintain a cache of the Midgard content tree structure.&lt;/p&gt;

&lt;p&gt;The content tree is derived from the parent link properties declared in the MgdSchema configuration. Each object can have a single parent link that points to another object. The parent links are required to form a forest structure, i.e. there can be multiple roots and no self-references or cycles are allowed in the parent links.&lt;/p&gt;

&lt;p&gt;The parent links are normally stored as fields in the content tables, which makes it difficult to efficiently traverse the content tree. A more efficient representation of the parent links shall therefore be added to the &lt;code&gt;repligard&lt;/code&gt; table to overcome this problem. This parent cache is a combination of the &lt;a href=&quot;http://www.sqlsummit.com/AdjacencyList.htm&quot;&gt;adjacency list&lt;/a&gt; and &lt;a href=&quot;http://www.developer.com/db/article.php/3517366&quot;&gt;nested set&lt;/a&gt; data models to allow efficient querying of both immediate parent/child and more distant ancestor/descendant relationships. The additions to the &lt;code&gt;repligard&lt;/code&gt; table are:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;parent_guid VARCHAR(80),
tree_left   INTEGER NOT NULL,
tree_right  INTEGER NOT NULL,
INDEX parent_index (parent_guid),
INDEX tree_index (parent_down, parent_up)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;parent_guid&lt;/code&gt; field will contain the GUID of the parent object and can be &lt;code&gt;NULL&lt;/code&gt; if the object has no parent. The &lt;code&gt;tree_left&lt;/code&gt; and &lt;code&gt;tree_right&lt;/code&gt; fields contain special depth-first traversal indexes of the object within the global content tree. This allows for very quick determination of ancestor relations using predicates like:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;A is an ancestor of B :-
    B.tree_left BETWEEN A.tree_left AND A.tree_right.
A is a descendant of B :-
    A.tree_left BETWEEN B.tree_left AND B.tree_right.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The full text indexer is responsible for setting up the parent cache and updating it whenever objects are created, moved, or deleted. The parent cache adds extra overhead whenever an object is created, moved, or deleted, but does not affect normal object updates. As the parent cache is managed by a separate indexer process, this performance hit is amortized at the cost of small periods of cache inconsistency.&lt;/p&gt;

&lt;h2&gt;The indexer process&lt;/h2&gt;

&lt;p&gt;The indexer process shall be a Java application that listens to all the configured Midgard databases and indexes all record changes in the respective full text indexes. Depending on the capabilities of the underlying Midgard database, the indexer can either use triggers, a dedicated change log, or the record change timestamps to locate the changed records.&lt;/p&gt;

&lt;p&gt;Whenever a record creation or change is detected, the indexer process will read the changed record and write the latest version to the full text index. Record deletions are handled by removing the respective index entry.&lt;/p&gt;

&lt;p&gt;The indexer process should keep a persistent timestamp of the last processed record change per Midgard database. This timestamp can be used to avoid having to fully reindex the entire database in case the indexer or the database is restarted. Full reindexing can be triggered simply by clearing this timestamp while restarting the indexer process.&lt;/p&gt;

&lt;p&gt;If possible the indexer process should contain both the MidCOM indexer and the indexing service described in this document. In addition to reducing the runtime and administration overhead, this would support the eventual goal of merging the two indexing mechanisms.&lt;/p&gt;

&lt;h2&gt;The