-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi.
I've begun further filling out the gaps in the Design. Some preliminary interface definitions alongside with an Roadmap are new. Have a look, comments always welcome. Live long and prosper! Torben Nehmer - -- Torben Nehmer, Munich, Germany http://www.nathan-syntronics.de, mailto:[EMAIL PROTECTED] PGP Public Key ID on wwwkeys.(de.)pgp.net: 0x7E9DE456 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.6 (GNU/Linux) Comment: For info see http://www.gnupg.org iD8DBQE8lSgbJPh4Kn6d5FYRAlF9AKDZE18esABGx5mU/dlzcaPHLgGI7wCguM5V CvRSuPftSih/AxfvKqNvILc= =R+Tf -----END PGP SIGNATURE-----
RFC: Midgard Components (MidCom)
================================
Author: Torben Nehmer, Linksystem Muenchen GmbH <[EMAIL PROTECTED]>
Date : March 4th, 2002
Abstract
--------
This document represents a draft about a component architecture for the Midgard
Content Management System. Its intend is to provide an easily extensible
Application Framework based on Midgard. It should -- in its ultimate
extent -- enable end users to "click their sites together" using common
Components for news tickers, discussion boards or similar things.
This document describes an incremental process. Especially the last parts of
the documents are only there because it struck me some time in the night that
"this would be fine". They are not neccessary for the system.
Note: Everytime I talk about "Stages" I refer to the Roadmap in Appendix B.
Table of Contents
-----------------
1. Design Goals
2. Application Infrastructure Overview
3. Components
3.1. MidCom Hooks
3.2. Component Code
3.3. Administration Interface
3.4. Layout Hooks
3.5. Configuration
4. Namespace Conventions
4.1. SnippetDirs: Component Storage
4.2. Global Variables
4.3. Class and Function identifiers
4.4. Namespace "midcom"
5. Interface Definitions
5.1. Component Management
5.2. Component Invocation, URL Parsing and Component Configuration
5.4. User and Administration Interfaces, Layout Management
5.5. Documentation
6. Preparing a Site for Components
7. Using Components
8. Automated Administration Interfaces
9. Advanced Layout Engine
10. Navigation Access Points (NAPs)
11. Debugging
12. Security System
13. Versioning
APPENDIX A. References
APPENDIX B. Roadmap
1. Design Goals
---------------
What Midgard currently lacks most is an easy way of importing applications into
an existing site. Most written applications are site-specific and can hardly be
exported into another site without great customization. This is where Midgard
Components come in:
Every MidCom application is contained within a Component with an explicitly
defined interface to the world. Controlling infrastructure is the topic tree
not the page tree giving you a far greater flexibility. The code itself is
completely encaspulated in snippets, making replication very easy.
A framework is used to manage the components, both for public and private sites
such as a web site and its administrative site. In theory this could even
automate the building of administration interfaces by "traversing" every active
component.
2. Application Infrastructure Overview
--------------------------------------
The basic idea is that the regular Midgard Program Flow (see midgard-root.php)
is enhanced by the MidCom Framework. It uses the "code-global", "code-init"
and "content" (magic) page elements to relay execution to the different
components. Basically you can treat a MidCom as a fully encaspulated package
that provides hooks for the following program flow:
Step 1: <[code-global]>
<? Component Configuration ?>
<[code-global-local]>
Step 2: <[code-init]>
<? URL Parsing ?>
<? Component Initialisation ?>
Step 3: <[content]>
<? Component display ?>
Except from the call to <[code-global-local]>, every call is handled by the
component framework, basically giving you this:
Step 1 loads all necessary functions for the component framework, initializes
the system and loads the component information along with its
configuration. The framework also calls the custom element
<[code-global-local]> where you can place site-specific, not MidCom-related
configuration directives.
After that the real processing starts in Step 2. A URL Parser is used to map
the request URL to the given topic tree. Every component has the chance to
manipulate this process. The parser design is two-staged: First the given
component gets the chance to evaluate the URL. If this is successful, parsing
stops and execution continues. If not, the system executes MidCom's default
handler, which tries a direct mapping between the topic tree and the URL.
If no error occurs during parsing, the component-specific initialisation code
is called. It prepares everything for the final display in the "content"
element.
Further Notes (-> things to incorporate into the rest of the document):
- Inheritance has to be enabled explicitly for each subtree if desired. If no
Component handler is defined either through direct accociation or through
inheritance, a predefined default Component is used.
- Idea: It could be possible to define mulitple component handlers for a single
object, especially if using inheritance. Along with a precedence, MidCom would
traverse the list of handlers and execute the first one, that actually declares
to be able to handle the request.
3. Components
-------------
Technically a MidCom is delivered as a repligarded SnippetDir with a defined
layout. Basically there are five parts of a MidCom, each contained in its own
SnippetDir below the main one:
1. MidCom Hooks: Hooks for the MidCom Framwork, required to handle the
Component
2. Component Code: The Application itself
3. Administation Interface: Snippets for the Admin Site Builder
4. Layout Hooks: Snippets to control the output of a MidCom
5. Configuration: Global Configuration of the MidCom
While the first three parts should not never be touched by an end-user, the
last two most certainly will be. This should be kept in mind that those parts
of a MidCom should _not_ be replicated in updates. (Repligard would
overwrite the customized snippets with the default ones. A good idea(tm) for
repligard would be an option to copy the imported data, especially usful in a
situation like this.)
Remember the replication problem everywhere in the vincinity around
MidCom. Everything you write should be replication safe. If possible, avoid
using Object-IDs where there is no automatic translation from Repligard. Use
Names -- or if you find no alternative, GUIDs -- instead. This has to be
bulletproof, since most more complex site will use a staging-live setup where
MidCom has to work its magic too. (And it has to work it as smoothly as it
would do without replication.)
3.1. MidCom Hooks
-----------------
This is the real interface to the outside world. It defines a set of classes
that the Framework uses to access the Component. The classes found here have to
present a defined interface for the different operations. Entry points are
defined for:
- Global Component Initialization
- URL Parsing
- Local Component Initialization
- User Interface Display
- Administration Interface Display
- Navigation Access Points
3.2. Component Code
-------------------
This is the place where you write all your component code. Call it Application
Logic, Business Logic or whatever you want, but this is the place where you can
roam around. But keep the Namespace Conventions (see below) in mind!
Component Code is private, which means that it will not be called from anyone
else as your own component. Even the MidCom Framework uses the Hooks to access
these classes.
You might attach a "version number" to the data objects created with your
MidCom. This will enable you to do "versioning" within your component, keeping
track of neccessary updates.
3.3. Administration Interface
-----------------------------
Even though this part is theoretically already covered under "Component Code",
it is separated to make a component more clearly structured. It contains all
necessary Classes to dynamically create an administration interface to the
MidCom. The classes in here have to follow a defined Interface to enable the
automatic interface-building.
3.4. Layout Hooks
-----------------
This SnippetDir roughly works like a Style. It gives you a number of Snippets,
each representing a part of the interface layout. Whether you write the HTML
Code directly into those snippets or not is your choice.
Concerning Replication: Since the Layout Hooks SnippetDir is not in the
upgrade-XML file, special care has to be take here if you introduce new
Elements. Preferably you explicitly export those new elements into the
upgrade-XML file to ensure completness of the Component.
See also: "Advanced Layout Engine"
3.5. Configuration
------------------
Put the global Snippet Configuration (i.e. for I18N ...) into this
SnippetDir. How you organize this snippetdir is entirely up to you,
configuration process is invoked through a class in the MidCom Hooks section.
The configuration itself should be done in two stages. First any global
configuration which holds true for all snippets should be loaded. The
configuration data of this part is located whithin the MidCom Snippetdir.
In the second stage the configuration is adapted to the current environment
using an accociatve array given by the MidCom Framework. In essence this data
is located in parameters attached to the snippet. Midcom also provides a
mechanism to update the configuration data at runtime.
4. Namespace Conventions
------------------------
Very important is the Namespace Convention of the whole framework. Current
Midgard Solutions often have no explicit Namespacing (since it isn't supported
by PHP or Midgard anyway), which often results in a certain chaos if you try to
integrate multiple applications into one site.
The basic idea behind MidCom Namespacing is a System similar to Java's Package
Hierarchy. To achieve globally unique Package identifiers it suggests using
Internet Domain Names as a Hierarchy. This leads to package Names like
"de.linkm.newsticker". This path, called the "MidCom Path", represents the
MidCom Namespace of Component itself. It is used everywhere to seperate
different Components from each other.
A component's name must match this regular expression:
[a-z][a-z0-9]*
All non-valid characters (i.e. "-" in Domain Names) have to be dropped.
4.1. SnippetDirs: Component Storage
-----------------------------------
Translated into Snippetdirs the path given above results in
"/de/linkm/newsticker/". This path is used to store the Components in an
hierarchical order.
Each component has the five defined snippetdirs form chapter 3, which in
addition with the snippetdir "documentation" (don't look at me like this!) are
the only reserved names for SnippetDirs. Therefore a MidCom package is valid if
and only if a SnippetDir contains all six SubSnippetDirs and the defined set
of classes (see below) in the MidCom Hooks Section. This gives us this Basic
Layout:
/------------------------------------------------------------------------------
| Figure: Basic MidCom Package Structure
|------------------------------------------------------------------------------
|
| de
| \-linkm
| \-newsticker => Base SnippetDir
| |-_component
| |-_adminsite
| |-_midcom
| |-_layouthooks
| |-_config
| \-_documentation
\------------------------------------------------------------------------------
This structure leads to the conclusion, that every element within this tree can
be both a component and a container for further components. An exception are
the Top-Level Domains (com, net, org, de ...), which must not be used as a
Component.
Although it is possible to put additional Components "into" an existing one,
this is strongly discouraged, because it makes the whole tree difficult to
read. If you require it (i.e. to extend an existing site), the defined
SubSnippetDir's are all prefixed with an "_" to get them at the right place in
the sorting order.
4.2. Global Variables
---------------------
Each Component will most probably require a number of global variables for
processing. Again we use the MidCom Path as a prefix for the variables,
replacing the dots with underscores. In our example the newsticker Component
would call its Global Variables de_linkm_newsticker_...
Any other global variables not starting with one of the domain-prexies plus an
underscore will be considered local and is therefore _not_ guranteed to survive
any function call within the MidCom framework. So either you use real local
variables within your function (which is perfectly fine) or remeber the rule
above. Never trust an variable outside of your namespace.
4.3. Class and Function identifiers
-----------------------------------
Basically this works like Global Variable naming above.
4.4. Namespace "midcom"
-----------------------
This is a special Namespace on the same level as the top-level domains. It is
used as entry Point into the MidCom Framework. Anything below midcom.* is
therefore not allowed for any Components (shouldn't be the case anyway).
Any System Component like the URL Parser, the Automatic Admin Site or the
Enhanced Layouting engine will also fall into the midcom Namespace. For now the
final decision what goes into the midcom namespace and what not, is done by the
MidCom Development team.
4.5. Parameters in the Topic Tree
---------------------------------
MidCom uses Parameters to Content Objects (topics, articles, attachments) to
control the whole web site. Again the Component Path is used to set
configuration Parameters. The Domain "midcom" is used to control MidCom
itself. Important is the Parameter midcom.component, which contains the Path to
the component MidCom should load at this point. Component Specifc Parameters go
into a domain named after the MidCom Path, in our example
"de.linkm.newsticker".
This leads to the conclusion, that a single Topic or Article could hold the
configuration data for more then one component, which could be used for
Switching to Test Data during development. Perhaps this could also be used in a
deferral-like mechanism where one component delegates Processing to one of his
"childs", like in an object inheritance tree.
5. Interface Definitions
------------------------
While you could use inheritance to create the MidCom Hook Classes, this is not
necessary - PHP doesn't support abstract classes anyway. Due to this an
approach similar to the Standard Template Libraries "Concepts" ist taken here.
A definition of required methods is defined for every Interface, which are
needed by the Framework.
The class names defined here have to be prefixed with the correct component
path. For example the concept class "config" would be named
"de_linkm_newsticker_config" in our example. This leads to a range of classes
every component must posess in order for the framework to work.
5.1. Component Management
-------------------------
This Hook is used to control the MidCom itself. For Stage 1 it is there to load
all neccessary Snippets for the MidCom to work. Later on things like pre and
post-installon Scripts, can also go here.
Concept "Component Management":
class midcom {
function initialize();
}
Concept Description:
- bool midcom::initialize();
Return Value: TRUE if initialize was successful, FALSE otherwise.
This function prepares everything to incorporate the MidCom into the
runtime environment. Important: It does not load configuration or anything
else. The sole purpose of this method should be loading and preparing any
external dependencies that are required to "link" the MidCom into the
existing runtime environment. Most of the time this function will load the
required snippets from the component snippetdir. If this function returns
FALSE, the whole System will ignore the component and won't try to access
it. Any time a component that returned FALSE is required to execute a site,
the default handler is executed instead (or any subsequent handlers, if the
multiple-handler-idea is realized). In the case that this leads to a
component that can't be displayed, a HTTP 500 is the result.
5.2. Component Invocation, URL Parsing and Component Configuration
------------------------------------------------------------------
This part gets more interesting. Here the MidCom loads its global
configuration. The snippet will also receive any tree-local confiuration data
through this interface. It can be used to prepare everything. Later on in the
MidCom Runtime Cycle the real processing invocation ("code-init") will arrive
through this concept class.
Concept "Component Invocation":
class component {
function global_config();
function local_config(configuration[]);
function can_handle(current_object, argc, argv[]);
function handle(current_object, argc, argv[]);
function handle_errcode();
function handle_errstr();
}
Concept Description:
- bool component::global_config();
Return Value: TRUE if configuration was loaded successfully, FALSE
otherwise
This function will load the systemwide configuration directives. It still
wont get any local data, it is used to prepare the whole system for the
decision, which component will handle the request. Only include real site
wide configuration here. If this function returnes FALSE, MidCom behavior
is like in midcom::initialize();
- bool component::local_config(Array[configkey => configvalue] configuration);
Parameter configuration: Contains an assionciative array holding all
configuration keys with their values attached to a given Object whithin the
domain of the MidCom.
Return Value: TRUE if configuration was loaded successfully, FALSE
otherwise
This function will customize the MidCom to the current situation at
hand. It will receive the local configuration through the Array
configuration through the MidCom Framework. It needs not to bother where
exactly this data is stored. Otherwise the behavior is like
component::global-config();
- bool component::can_handle(MidgardObject current_object, int argc,
string argv[]);
Parameter current_object: It contains a copy of the object the framework is
currently processing. Currently this could be either a MidgardTopic,
MidgardArticle or MidgardAttachment.
Parameters argc, argv[]: All remaining arguments of the URL in a
Midgard-like form. All already processed items are removed, the current
object is always at argv[0].
Return Value: TRUE if the component can handle this specific request, FALSE
otherwise.
This function tests whether the component can handle the current request in
the given tree. It just has to decide exactly this, not more. The result of
an URL parsing process can be cached for later usage in component::handle,
the system gurantees that can_handle will be called at least once bevore
component::handle is called. If this function returnes TRUE, MidCom stops
URL processing and initiates the display of the component after
component::handle has executed. If this function returnes FALSE, regular
URL evaluation will continue.
- bool component:handle (MidgardObject current_object, int argc, string
argv[]);
Parameter current_object: It contains a copy of the object the framework is
currently processing. Currently this could be either a MidgardTopic,
MidgardArticle or MidgardAttachment.
Parameters argc, argv[]: All remaining arguments of the URL in a
Midgard-like form. All already processed items are removed, the current
object is always at argv[0].
Return Value: TRUE if processing was successful, FALSE otherwise.
This function does the real preparation of the component display. If it
returns false, it has to set its internal state in a way that
component::handle_errcode and component::handle_errstr return the HTTP
Errorcode along with an appropriate message why the Handler failed.
- int component::handle_errcode();
Return Value: The HTTP Errorcode of the last handle call. 200 if everything
was OK; 4xx otherwise.
This function is bound to some (yet to be defined) constants in the
errorcodes it can deliver. It is only queried if component::handle returns
false. Nevertheless it should return 200 while everything is ok, just to
stay consistent.
- string component::handle_errstr();
Return Value: The error message of the last component::handle run. Empty if
the run was successful.
According to component::handle_errcode this function returns an appropriate
error message. It is displayed in the Error Page that is returned to the
client. It should be empty in all non-error cases.
5.3. User and Administration Interfaces, Layout Management
5.4. Documentation
6. Preparing a Site for Components
----------------------------------
>> Allgemein:
>>
>> Ich w�rde diese default-fallbacks (topic/article-admin, urlparser-defaults)
>> nicht als bestandteil der komponentenarchitektur betrachten, sondern als
>> "mitgelieferte standard-komponenten". Die haben strukturell mit dem modell
>> nichts zu tun, ausser dass sie entweder in der globalen Initialisierung
>> speziell als Defaults registriert werden oder einfach per Namenskonvention
>> definiert sind.
Basically (not including MidCom Installation...):
- Create the site, with a single, active page
- Write <[code-global]>:
Instantinate MidCom Main Application Object
- OPTIONAL: Write <[code-global-local]>:
Put your custom Init Code here.
- Write <[code-init]>:
Call MidCom's code-init-Method
- Write <[content]>:
Call MidCom's content Method.
- Create Main Site Style, not referencing to any other page-element then
<[content]>
- Use MidCom Functions to dynamically place Navigation Elements within
the Style tree
- Configure MidCom (most probable in <[code-global]>:
- Define root Topic
- ...
7. Using Components
-------------------
Basically the only thing you have to do is put a Parameter to an Article or
Topic referencing a MidCom and, if neccessary, some parameters.
8. Automated Administration Interfaces
--------------------------------------
-> Uses the same infrastructure as the public site to display the Admin
interfaces of the different used components.
Using the same infrastructure you could easily create an automated
administration site. By default it gives you a standard interface (which is
defined in the configuration), but as it encounters other components, i.e. a
newsticker, the MidCom framework loads the MidCom's own admin interface. Here a
clear abstraction between layout and the application itself is very important
to provide a way to automagically merge the different administration
interfaces into a single admin site.
9. Advanced Layout Engine
----------------------------
-> Replace the <[...]> Syntax for Style-Elements with custom functions to
enable dynamic style switching.
An enhanced Layout Engine could be created, still using styles and elements,
but not accessing them through midgard but through custom fuctions. The
advantage here is, that you are not bound to use the style accociated with the
active page, but any style available. Neccessary to do this is a new layer
replacing the <[...]> Syntax with custom function calls that access the Style
Tree directly. Using this Interface, you could do automatic mapping between the
Layout Snippets of the component and an accoicated Style.
10. Navigation Access Points (NAPs)
-----------------------------------
Each component should have a "navigation mode" for display that gives you
enough information to dynamically build navigation trees. It should not be
neccessary to know the internals of a component to be able to build a
navigation system. Therefore several functions give you an abstract access to
this information.
11. Debugging
-------------
12. Security System
-------------------
13. Versioning
--------------
APPENDIX A. References
----------------------
From: "Armand A. Verstappen" <[EMAIL PROTECTED]>
To: "[EMAIL PROTECTED]" <[EMAIL PROTECTED]>
Subject: Re: [midgard-user] RFC: Midgard Components, First Architecture Draft
Date-Sent: Samstag, M�rz 09, 2002 20:05:15 +0100
Just got up to speed with the long thread about Midgard Components,
great stuff!
I think our repligard system is a great concept, but also poses a lot of
problems. It mandates that all content be in the database if you want to
have a one-go replication process set up. As a result we kind of fork
away from the open source community, because the tools produced by the
community don't work for us in a comfortable way. vi, emacs, cvs, rpm,
apt-get, they are all of no use to us. (Well, not easily, that is)
The discussions in this thread made be combine thoughts and come up with
a 'serialize and bootstrap' concept, one that absolutely needs refining,
but potentially could be of great support to the MidCom initiative.
CONCEPT
namespaces within the snippetdir/snippet hierarchy will be tagged as
filespace snippets. a utility 'bootstrap', can scan the configured
filesystem directories for files, wich will be imported as snippets, a
utility 'serialize' will flatten out existing snippet trees for writing
to the filesystem.
FORMAT
The format of the 'serialized' snippets must be of a workable design, so
that normal tools will work on it. So instead of using XML, we might
turn a snippet into a directory whith files for each of elements:
snippetdir/snippetname/GUID
/SG
/code
/author
/.... (etc)
a snippetdir should also hold files to discribe it properties.
If properly designed, this would allow us to use the timestamps and the
GUID to interface with repligard to do the bootstrapping/serializing.
This would enable us to use existing packaging tools to distribute
aplications, use cvs in shared development, etc, while still having
repligard at the core.
APPENDIX B. Roadmap
-------------------
Stage 1: Basic implementation
Implement the basic features of the MidCom framework. Automatic Component
loading, replication safety. Drive everything directly from the snippet tree,
no automatism for Layouting or so. Administration will be done solely by hand
via your favorit Parameter capable Admin-Interface.
Stage 2: Enhance Layouting
Prepare the system to relay layouting to a specified style. Route all style
requests to a style specified in the configuration.
Stage 3: Navigation Interface
Provide a way how the style can Access MidCom to dynamically build a
Navigation hierarchy. This has to be independent from the specified
components. Develop a Acess Interface for this.
Stage 4: Automatic Admin site
Build the neccessary Infratstructure that administrative sites will be
created automagically. Including some chance to modify the Look&Feel of the
generated site.
Stage 5: Packaging
Build an automatic way of distributing and controlling the MidCom
Packages. Preferred is something like apt-get, preferably controlled by the
Automaitc Administration Site.
Stage 6: Start playing around
Add the favourite Feature of your choice that is missing. A lot could be
done: A full fledged debugging system, a security interface which builds an
ACL controlled access control system into MidCom, complete Versioning with
the possibility of automatic upgrades both of MidComs and MidCom Data
Elements and ... and ... and ...
===============================================================================
$Id: midgard-components.txt,v 1.7 2002/03/17 23:24:35 torben Exp $
midgard-components.txt.sig
Description: PGP signature
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
