OK, time for another marathon post... here’s what I want to kick down to the Blue Sky forum ASAP for feedback:
The Future of MODx
MODx is an Internet Content Management Framework (CMF). This means it’s an extended web Content Management System (CMS) that developers use to quickly build custom websites and web applications.
MODx includes support for the latest “Web 2.0” technologies and trends including AJAX (Asynchronous JAvascript exchange), tagging, blogging, RSS feeds, and robust Web Standards (i.e. XHTML/CSS layouts) support.
It’s “Manager” site administration system also works seamlessly in the “big three” browsers: IE Windows, FireFox and Safari.
The Core Concepts
Content
Anything part of the MODx experience when browsing sites is “content” — a web page, a Javascript file, a CSS file, Flash, a link to an offsite location, a downloadable file, an RSS feed and so on.
Templates
Content is displayed through a template. Templates can apply to entire pages, or to just parts of pages (like “blocks” in other CMSes).
Widgets
This is the mojo that makes MODx a dynamic system for custom site and web application development. Widgets are little chunks or objects that serve a pretty specific purpose, and they come in two flavors: static and dynamic. Static widgets are non-changing HTML, XML, text, Javascript, CSS or other similar content. Dynamic Widgets contain PHP code with logic, database calls, or pretty much anything you can dream up.
Getting Started
Manager
This is the primary control center for all MODx content and configuration parameters. It works just fine, thank you, in Windows IE, Firefox, Safari and Opera. (Safari currently doesn’t work with “WYSIWYG” Rich Text Editors (RTEs), but there are no limitations in the ability to actually edit the content and configurations.)
Content Fields
This is where text, links or files are stored in MODx. There are no real limits to the number of content fields per page in Tattoo/MODx. Content Fields can be simple text fields, WYSIWYG text editors for complex data entry (via Rich Text Editors, or RTEs), pop-up lists, radio button options, etc. “[*content*]” is a non-deletable default Content Field for every page every page and cannot be deleted.
Links
Internal pages are linked together by referencing a unique ID number that is automatically assigned to each page.
Intermediate Concepts
Templates
Designers and Developers assign Templates to Pages, and the Templates almost always contain one or more Content Fields and/or Widgets. Templates set defaults attributes for pages inside MODx, too. These attributes include things like:
- content type (text, html, pdf, xml, etc.)
- disposition (send to screen or initiate a download)
- meta-content (keywords, descriptions, tags, etc.)
- ability to search pages using the template
- ability to cache the pages using the template
- and so forth
Default attributes automatically apply to every page created with the Template, but can be overridden on a per-page basis. Pages can also be reset to their default attribute states.
Static Widgets
These are simply blocks of text, HTML or code that do not contain application logic. They can have parameters passed into them which are simply returned to the browser (think of these as sub-templates, if you will). Static Widgets are typically used multiple times in a site, for example a site footer or copyright line with links.
Advanced Technologies
Dynamic Widgets
These are blocks of PHP code with application logic. These can be used for simple things like conditional display of Static Widgets based on a user’s input in a form, or creating dynamic navigation menus as pages are added to a site.
(Note: please put on your propeller beanie here…) Dynamic Widgets can also be tied to specific system events used by the document parser. These events allow you to trap the default behavior of the system and alter it in some way. This is how the Rich Text Editors convert a text area into a RTE instance. This is also how you can override core system functionality without changing the core system code. An example here is synchronizing user logins between multiple disparate programs.
There are no feasible limits on the number or type of parameters usable by Widgets, and you pass them in with the [[widget? ¶m1=`foo` ¶m2=`bar`]] convention.
@bindings
(Note: pocket-protector required…) These are powerful ways to dynamically attach various data sources to the Content Fields. Content Fields contain a default value that can be overridden on a page-by-page basis as well as input options. @bindings can be applied at either location. @bindings currently work with text files stored on the filesystem, Widgets, Documents, database queries, and PHP code. Future @bindings will include RSS feeds, XML, SOAP, XML-HTTP requests and recursive @bindings.
Formatting Widgets
Formatting Widgets are specialized Dynamic Widgets that are applied directly to Content Fields. Think of them as small extensions/behaviors that take a piece of text or data and transforms it into (typically) more complex elements with dynamic interaction. For example, Rich Text Editors, pop-up list input boxes, display grids or button builders.
Placeholders
These are system resources that are generated on the fly by code (or by system configuration settings) to represent various pieces of data. Placeholders are useful for use in Static Widgets to separate the design of things like forms or pages, from the complex application logic used to construct the output.
Modules
These are packages of Templates, database structures, Widgets and Content that can perform functions like altering the way the core system behaves (can be as simple as a single file performing a very specific override to a manager API call with no interface) or as complex as a full-blown integration with a third party application.
Implementing it all
The above is not definitive. We hope be able to make the parser consist of one recursive preg_match (or whatever) on nestable [[ tags with a separate pass for non-cached objects. The revsised syntax follows, which would allow for things like [[widget? &color=`[[*colors]]` &foo=`[[blah? &bar=`[[blahblah]]` ]]` ]] to work.
This would all be done in hopes of optimizing the performance and flexibility of the document parser via fewer loops to go through, and using function callbacks vs. case/switch statements. It would also hopefully provide for:
- all objects being cachable or non-cachable
- all objects being nestable
Here’s how to translate the current methods into the proposed new way:
- [[widget]] = [[snippet]] or {{chunk}} with a static/dynamic flag, plus a caching flag, eliminating the requirement to configure caching parameters via [!snippet!]
- [[~linkID]] = [~linkID~]
- [[+placehoder]] = [+placeholder+]
- [[++system_setting]] = a system placeholder with namespace uniqueness [(site_setting)]
- [[*contentField]] = Template Variable [*tv*]
- [[*#contentField]] = QuickEdit enabled content field [*#tv-or-content*]
- [[^parse_time]] = also time, date, size for current date/time and bytes of code (HTML text only... no includes or linked files/images) sent to the browser [[^timing^]]
Here’s some completely new/majorly enhanced constructs:
- [[$template]] = insesrts a template or sub-template in the page (n/a previously)
- [[%language]] = way to handle multi-lingual sites, to be addressed eventually (n/a previously)
- [[@onEventName]] = used to raise an event from within the page and allows for calling / invoking custom or system events. For example: [[@OnRenderRichText? &editor=`FCKEditor` &elements=`mytextarea`]] will invoke the RTE plugins and render the RTE on the page, replacing the textarea of ID=mytextarea with the FCKEditor instance, or [[@OnBackupInit]] could be used to trigger a backup whenever a page is viewed
- [!anything!] = for developers who want to maintain/override caching on any of the above items [!snippet!] (and previously limited only to snippets)
The following modifiers are what makes fair game sense to use:
~ ! @ $ % ^ *# _ - + = { } .
The following don’t to me due to logic/code/html associations/implications:
The # is obviously used by QuickEdit, which needs to be considered in the switch handling, obviously. The ! could also be used to denote inline cache disabling as needed: [[!non-cachable-snipet-call]], but more discussion is needed on this as to how it would affect execution times and overall architecture.