Introduction: Just What is Molly?

HTML, XML, XHTML & MAML

When Tim Berners-Lee created HTML (HyperText Markup Language) in the early 1990s he based it on the concept of tag markup used by SGML (Standard Generalized Markup Language) and so we all became familiar with the practice of structuring (and formatting in the pre-CSS days) text with tags like <h1> and <p>. HTML was rather loosely defined and the various browsers' developers each created their own versions of it and added their own tags, so HTML evolved, though somewhat haphazardly. Before long two things became clear; one, that HTML was inconsistent and difficult for software to parse and interpret correctly, and two, it was neither extensible, nor sufficient for all of the tasks web developers wished to do. To address these two deficiencies the W3C (World Wide Web Consortium), headed by Berners-Lee, created XML and XHTML. XML stands for eXtensible Markup Language. XML is basically a set of rules for creating markup languages that use tags like HTML. By following these rules any software developer can create a markup language to serve whatever purposes they might have. XHTML is a reformulation of HTML that follows the rules of XML. This slightly stricter version of HTML has supplanted HTML as of version 4.01, and provides web developers several benefits including a cleaner separation of structure and presentation than HTML and the ability to be used and parsed together with other XML-based markup languages.

Molly uses an XML-based markup language named MAML (Molly Active Markup Language) mixed together with XHTML to allow web site developers to easily add sophisticated server-side functionality to their sites without having to learn complex programming languages like PHP, Perl, Java, ASP, or .NET. Instead, web developers use the XHTML tags they already know together with new MAML tags that Molly uses to generate more XHTML dynamically based on things such as database lookups which would normally require a fair amount of custom programming.

History of Molly

In the mid 1990s one of us (Vullo) began building web-based applications for dental education. These included online learning and electronic dental records. Even then, it was clear that web sites needed pages which were dynamically generated from information stored in databases. At the time the database he used was Apple's FileMaker Pro and the tool for embedding that information into a web page was Blue World's Lasso.

Several years later Vullo was called upon to create a new distance education and medical record system. This was to be a more ambitious project and after prototyping with Lasso it became clear that a more robust and flexible system would be required. Fortune smiled and PHP 4 was released about this time and with its maturity was rapidly developing a reputation as an outstanding server-side web development language. PHP also supported access to multiple database systems including the then up-and-coming MySQL.

While the typical PHP approach to building web applications at the time was to simply build HTML pages and embed snippets of stand-alone PHP code wherever dynamic content was required, Vullo decided to take a different approach. He recognized that such a development style quickly becomes difficult to support and scales poorly with large sites. Instead he decided to build an organized code library, encapsulating oft-needed functionality into generic functions. Then, instead of embedding chunks of code into a web page, a single line function call would be used instead, much more like an HTML tag than an embedded program. Thus was born (the as-of-yet unnamed) Molly version 1. Soon after this one of us (Hoey) gave birth to a daughter and named her Molly. Vullo named the software after Molly as a gift to her mother.

Soon thereafter the W3C released XML and XHTML and it became clear that the next logical step was to eliminate the PHP entirely from the web pages and replace the function calls with XML tags designed to be usable by HTML authors without any need of programming or understanding PHP. This change necessitated a new architecture for Molly, and so Molly II was developed.

How Molly is different from other Systems

Over the years Molly has been compared with various other systems such as ColdFusion, Mambo, Joomla, and Ruby on Rails. While each of these systems has its strengths, and share some abilities with Molly, they are also different enough in design, philosophy, architecture, and implementation for us to confidently continue to develop and use Molly. Here then is a brief comparison of Molly's similarities and differences to these other tools:

ColdFusion

Adobe's ColdFusion is perhaps most like Molly in that it uses a tag syntax. There are a number of notable differences however, not the least of which is that ColdFusion is expensive ($1,299 - $7,499 as this was written) and proprietary, whereas Molly is free and open source. While ColdFusion uses tags as its syntax (CFML - ColdFusion Markup Language) it is not XML compliant and so would break any standards-based XML parser. ColdFusion is also, despite its tag syntax, considered a programming language and in fact has an ECMAScript-like (but not compatible) syntax as well.

Mambo & Joomla

Mambo & Joomla are two versions of the same content management system which forked in the midst of considerable controversy and angst among its developers. While there are a lot of devoted users of the products, it is perhaps because they have invested so much energy in building sites with the products and choosing sides in the split. Both products are built with PHP, are ostensibly open source, and take the same approach as Molly I (which we abandoned for the simpler to use XML syntax and cleaner architecture of Molly II and beyond). Mambo and Joomla support only MySQL whereas Molly supports MySQL, Oracle, PostgreSQL, ODBC, SQLite, LDAP and many others.

Ruby on Rails

Perhaps the single most backward-named computer software, Ruby on Rails is actually an object framework (Rails) built in a programming language named Ruby. It has the advantage of being free and open source and was hailed for a while as "the next big thing" in web development. But in the authors' opinion Ruby on Rails has two fatal flaws: First is a rather steep learning curve and the necessity to adopt the Rails system whereby structure happening automatically based on a naming scheme. Second, and perhaps more important, is that many developers have experienced scalability issues for large or busy sites.

How Molly Works

Molly is a web server-side technology, which is to say that all of the work that Molly does happens on the web server. The user never sees any of Molly's MAML tags or underlying programming. Contrast this with client-side technologies like JavaScript where all the user needs to do is "View Source" in their browser and they can see all of the code. When a user does that on a page processed by Molly, all they see is the XHTML that Molly generates.

So, being a server-side technology, Molly has to be installed on a web server. How to do that is explained in Appendix I: Installing Molly.

Molly uses special new tags to add server-side functionality to your web pages. Because XHTML is a language built in XML it allows us to add other XML languages' tags to our code. Molly implements one such language — Molly Active Markup Language, or MAML. MAML tags look and are written just like XHTML tags with one difference; they include the "maml:" prefix that tells Molly (and other XML processors) that those tags are not XHTML. That way MAML can have tags with the same name as XHTML tags and there is no problem. For example, XHTML has the <form> tag and Molly has the <maml:form> tag. These can both be used in the same document without any problem. At this point you may be wondering why Molly would have her own form tag and not just call it something else. Well, Molly's forms look and act just like XHTML's forms, except that Molly's automatically connect to the database and process the data when the user clicks the submit button. With an XHTML form the webmaster would have to write all of the necessary server-side programs necessary to do that.

So Molly is at her heart an XML parser, but she's really much more. She's what we call an "abstraction layer." Molly's MAML tags are abstractions that hide all the underlying programming from you so that you can focus on building your web site and not on the details of programming the functionality that makes your site dynamic. Just like XHTML and CSS together form an abstraction layer that hides the complexity of delivering content over the internet and rendering it into the pixels you see on your computer screen.

Molly is written in a programming language called PHP. (Programming languages themselves are abstraction layers above the binary code that computer processors actually read and write.) Molly is designed to be extensible and so if you know PHP and wish to add new functionality that is not only possible, but fairly easy to do thanks to over a decade of experience in designing and building her architecture. Part III: Under the Hood explains that architecture and the rules we follow when programming Molly.

How Molly Helps

Makes building sites rapid and easy. :o)


Part I: Learning Molly & MAML

If you already know how to build web pages in XHTML, then you are well on your way to learning how to use MAML, since MAML uses simple tags very much like those with which you are already familiar. The first thing we will cover is the basic structure of a MAML page. We will demonstrate how MAML is translated by Molly into XHTML. After that we will explain how to to use a few MAML tags, and how they are transformed by Molly into XHTML.

A Basic MAML page's boilerplate code is virtually identical to a normal XHTML page. So to see the difference, let's build "Hello World" in XHTML and in MAML.

(Why "Hello World?" Well this is a computer book, and it's the law. ;o)

Basic HTML Document:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Hello World HTML</title>
</head>
<body>
    <p>Hello World!</p>
</body>
</html>

Basic MAML Document:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:maml="http://interpersonalnet.com/maml/">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Hello World MAML</title>
</head>
<body>
    <p>Hello World!</p>
</body>
</html>
 

See the difference? Yeah, it's hard. The only difference is on the third line. Here, this time I'll highlight it so you can see it easier:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:maml="http://interpersonalnet.com/maml/">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Hello World MAML</title>
</head>
<body>
    <p>Hello World!</p>
</body>
</html>
 

It's not much, but it's very important. What does that snippet of extra code do? Well, it does a little bit of XML magic and adds the "maml" namespace to the document so that Molly's XML parser can process the file and do all the cool things that make Molly what she is. That namespace declaration is why Molly's tags all begin with "maml:" like this:

<maml:box>Some text with a box around it.</maml:box>

This use of namespaces also makes the MAML XML syntax compliant with XML and XHTML standards, so any XML editor or processing software should have no problem with Molly's MAML code.

OK, so let's take our simple example a little further. We'll add the <maml:box> tag to our Hello World MAML file like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:maml="http://interpersonalnet.com/maml/">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <title>Hello World MAML</title>
</head>
<body>
    <p>Hello World!</p>
    <maml:box>Some text with a box around it.</maml:box>
</body>
</html>

Now if we save this as a file with a .maml extension like hello_world.maml and view it in a browser from a Molly Server it will look something like this:

Hello World!

Some text with a box around it.

(Remember, Molly is a "server-side" technology and so MAML pages have to be viewed in a web browser via HTTP from a server where Molly is installed. If you view the page from your local hard drive via the browser's file:// URL the browser will not understand the MAML code.)

Molly processes the MAML file and generates the following XHTML in its place:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 
<head>
    <meta http-equiv = "content-type" content = "text/html; charset=utf-8">
    <title>Hello World MAML</title>
    <link rel="stylesheet" type="text/css" href="/~rvullo/m9/decor/default.css" />
    <style type="text/css">
 
    </style>
 
    <script type="text/javascript">
 
    </script>
</head>
<body>
    <p>Hello World!</p>
    <div class="box">
    <p class="title"></p>
    <p class="contents">
        <span class="boxbottom">
Some text with a box around it.        </span>
    </p>
</div>
 
</body>
</html>

Now at this point you don't really have to worry about the specific code that Molly generated, this is simply to illustrate the point that Molly translates the MAML tags into XHTML and automates a lot of things like adding CSS and JavaScript when necessary.

Getting Started with Database Access

Molly makes it very easy to fetch information from a database and put it on a web page formatted however you want. Here is a simple example of that:

Notice that clicking the column titles sorts the results.

Here is the MAML and HTML source code to generate the above list (line numbers added for explanation reference):

  1. <maml:fetch table="molly_test" key="name" criteria="true" sort = "name" order = "ascending">
  2. <table style="width:22em; background-color: #f4f5fb;padding:1em;">
  3. <tr>
  4. <th><maml:sort sort="name">Name</maml:sort></th>
  5. <th><maml:sort sort="eyecolor">Eye Color</maml:sort></th>
  6. <th><maml:sort sort="age">Age</maml:sort></th>
  7. </tr>
  8. <maml:row>
  9. <tr>
  10. <td><maml:field name="name"/></td>
  11. <td><maml:field name="eyecolor"/></td>
  12. <td><maml:field name="age"/></td>
  13. </tr>
  14. </maml:row>
  15. <tr>
  16. <th colspan="3" style="text-align:right;">Total Records: <maml:numrows/></th>
  17. </tr>
  18. </table>
  19. </maml:fetch>
  1. The <maml:fetch> tag is used to set up a query to retrieve information from the database. The table attribute specifies which table to search. The key attribute specifies the key field for the table. The criteria attribute specifies the search. In this case we set criteria="true" so Molly fetches all of the records in the table. You could be more specific with something like criteria="age > 10" and fewer records would be found. Finally sort = "name" and order = "ascending" tell Molly to return the results sorted by the name field.
  2. This is an ordinary <table> tag. Because you mix MAML tags freely with HTML you can format your output however you wish. You could use an ordered list instead of a table if you like.
  3. Our first table row will have the column headers.
  4. This is a simple HTML <th>Name</th> one would normally use to create a table header with the addition of a <maml:sort sort="name"> tag. This simple tag tells Molly to create all the necessary code to allow users to click on the column head and retrieve a sorted list based on the field name specified in the sort attribute.
  5. As above we've added sorting, by eye color in this case.
  6. And here we're sorting by age.
  7. End of the header row of the table.
  8. Everything between the <maml:row> and </maml:row> tag pair will be repeated for every record found by the query specified in the <maml:fetch> tag.
  9. Because we're building an HTML table we'll repeat a <tr> table row.
  10. This HTML <td> contains the <maml:field name="name"/> tag which will be replaced by the results of the search for each row. The name attribute specifies the database field name.
  11. Likewise this table data cell will be filled with eye color.
  12. And this with data from the table's age field.
  13. End of the table row.
  14. And end of the record (and the portion of the code which will repeat for every record found).
  15. We're adding one last row to our table…
  16. Which will display the number of rows Molly found in the database (and rendered above).
  17. And we have to close all of our open tags.

Tokens

Tokens are place holders for values which Molly will substitute before sending the page to the browser. (Programmers can think of these as variables.) Some tokens are pre-defined as part of Molly's configuration to make it easy, for example, to create a path to an image which will work from any of the site's pages:

<img src="*[HTMLRoot]*decor/icons/gradcap-7.png" />

Other tokens can be set by the webmaster using the <maml:token> and <maml:persist> tags.

Pre-Defined Tokens

Configuration Tokens (Set in the site's .ini file and molly_config database table)

*[HTMLRoot]* —> HTML Path to the root of the site
*[SkinDirectory]* —> Path to skins directory, relative to *[HTMLRoot]*
*[Skin]* —> Current Skin
*[SystemRoot]* —> HTML Path to Molly's system directory
*[FileRoot]* —> Unix path to the root of the site
*[QueryString]* —> Query String (if any) sent by browser when requesting this page†
*[SkinScripts]* —> JavaScripts Molly will be inserted into the page's head†
*[ConfigTable]* —> The name of the table from which the site's configuration settings have been read.

†In general webmasters should not access these, they are for internal system use only

Tag-Specific Tokens

Some tags as part of their functionality create pre-defined tokens as well. For example, the <maml:login> tag will create tokens when a user logs into the site:

Molly Page Tokens relevant to login

*[LoggedIn]* —> Set to 1 (true) if the user is logged in, 0 (false) if not
*[LastName]* —> logged in user's last name
*[FirstName]* —> logged in user's first name
*[Salutation]* —> logged in user's salutation (i.e. Miss, Mrs, Mr, Dr, etc.)
*[UserID]* —> logged in user's unique user id (integer)
*[LoginName]* —> logged in user's unique username/alias

Currently Defined Tokens

The following is a dynamically generated list of all the currently defined tokens for this page view in the Molly installation you are using to read this page:


If you wish to see the current values for all of the tokens on your site, you can use the following code on a .maml page:

<div>
   ActiveLinkColor: *[ActiveLinkColor]*<br />
   AttachmentsDirectory: *[AttachmentsDirectory]*<br />
   BackgroundColor: *[BackgroundColor]*<br />
   BoxFrameColor: *[BoxFrameColor]*<br />
   ConfigTable: *[ConfigTable]*<br />
   CurrentYear: *[CurrentYear]*<br />
   FileRoot: *[FileRoot]*<br />
   FirstName: *[FirstName]*<br />
   FormDark: *[FormDark]*<br />
   FormLight: *[FormLight]*<br />
   FormMedium: *[FormMedium]*<br />
   HTMLRoot: *[HTMLRoot]*<br />
   HeaderBackground: *[HeaderBackground]*<br />
   HoverLinkColor: *[HoverLinkColor]*<br />
   LastName: *[LastName]*<br />
   LinkColor: *[LinkColor]*<br />
   LoggedIn: *[LoggedIn]*<br />
   LoginName: *[LoginName]*<br />
   MenuColor: *[MenuColor]*<br />
   MenuLinkColor: *[MenuLinkColor]*<br />
   MenuRolloverBackgroundColor: *[MenuRolloverBackgroundColor]*<br />
   MenuRolloverTextColor: *[MenuRolloverTextColor]*<br />
   MenuSelectedBackgroundColor: *[MenuSelectedBackgroundColor]*<br />
   MenuSelectedTextColor: *[MenuSelectedTextColor]*<br />
   MenuTextColor: *[MenuTextColor]*<br />
   PageColor: *[PageColor]*<br />
   QueryString: *[QueryString]*<br />
   Salutation: *[Salutation]*<br />
   SelectedTabColor: *[SelectedTabColor]*<br />
   SidebarHeadingBackgroundColor: *[SidebarHeadingBackgroundColor]*<br />
   SidebarHeadingTextColor: *[SidebarHeadingTextColor]*<br />
   SidebarLinkColor: *[SidebarLinkColor]*<br />
   SiteName: *[SiteName]*<br />
   Skin: *[Skin]*<br />
   SkinDirectory: *[SkinDirectory]*<br />
   SkinScripts: *[SkinScripts]*<br />
   SystemRoot: *[SystemRoot]*<br />
   TabColorHover: *[TabColorHover]*<br />
   TextColor: *[TextColor]*<br />
   UnselectedTabColor: *[UnselectedTabColor]*<br />
   UserID: *[UserID]*<br />
   VisitedLinkColor: *[VisitedLinkColor]*<br />
   WindoidFieldColor: *[WindoidFieldColor]*<br />
   WindoidFrameColor: *[WindoidFrameColor]*<br />
   copyright: *[copyright]*<br />
   javascript: *[javascript]*<br />
   stylesheet: *[stylesheet]*<br />
   tagline: *[tagline]*<br />
</div>

Skins

Molly uses a "skins" system to facilitate changing the look and feel of your web site, as well as allowing you to change the way many MAML tags render their output. All of the presentation code and images for Molly are contained in the decor directory in the root of your Molly site. Skins are contained within this decor directory (though the path to skins may be changed in your molly.ini file).

Anatomy of a Skin

Within the skins directory can be one or more directories, the name of which is the name of the skin. The name of the skin currently being used by this particular Molly installation is "mx." Skin directories have a specific structure and set of files. There are two required files:

And three required directories:

main.css File

This is the stylesheet that will be linked to every .maml page on your site. The file will be processed to replace tokens with their appropriate values. Most of these (the presentational ones) are set in the molly_config table of the database. Tokens which provide appropriate paths are set in the molly.ini file.

main.js.htmf File

This is a snippet of HTML (.htmf stands for hypertext markup fragment) which will be inserted into the <head></head> section of each page. This is where you should insert any JavaScript code which you would like to have on every page of your site.

images Directory

This directory contains any images used in the design of your site, such as background images, logos, etc. Images which are content (i.e. photos of your business, etc.) do not belong here. They should be outside of the decor directory which is reserved for presentational aspects of the site. Images in this directory may be templates for Molly's colorizing code and if so should be named with ".tplt" before the ".jpg" or ".png" file extension to make this clear.

scripts Directory

This directory contains all JavaScripts required by the skin. At a minimum it should have a main.js file which will be included in every page.

templates Directory

This directory contains all of the template files used by Molly to generate the resulting HTML of most of the MAML tags. In general when creating your own skins you can just copy the default templates directory with all of its template files and you will be fine. Most of the changes you are likely to want to maje can be accomplished by editing the main.js.htmf file. If, however, you wish to actually change the HTML (structure) that Molly generates, then these are the files you would edit.

Template files follow a naming convention and it is important that you understand and respect this convention if you are editing them or creating new ones for new MAML tags you might be creating (in a module, for example, or if you are working on extending Molly). Template files must have a ".tplt" file extension. Template files are named for the tag they are used by and in general since most tags have a begin tag and an end tag there is a separate file for each of these. So, for example, the <maml:windoid> tag uses the windoid.begin.tplt template file and the </maml:windoid> tag uses the windoid.end.tplt template file.

This system provides quite a bit of flexibility in modifying how Molly renders a page without editing the underlying PHP code. If you wish to do this, it is best that you create your own skin to do so. The easiest way to do that is to duplicate an existing skin, give it a new name, then edit your molly.ini file to use the new skin.

Skins and the molly_config Database Table

Skins will usually provide one or more SQL files for populating the molly_config table with appropriate values for tokens in the main.css file.

Currently Installed Skins

The following is a dynamically generated list (using <maml:filelist path="*[FileRoot]**[SkinDirectory]*" filetype="dir">) of the skins which are installed the decor/skins/ directory of this Molly installation:

Other Stuff I need to write about:

Users and Permissions

In your database, there should be a molly_login table and a molly_username table. This is where the information for each user who can log into your Molly site gets stored. The user_id number in the molly_login table must match with the user_id number of the corresponding user in the molly_username table.

The molly_permissions table is where you can set the editing permissions for each user. Again, the user_id number in this table must match with the corresponding user's user_id number. The group_name column lists the permissions each user has. The options are admin, editor, and config. These are the values that can be entered into the permitted attribute in the <maml:block> tag so that only certain users can edit that block. The permitted column shows whether or not the user has that permission; "1" means permitted, "0" means not permitted. The group_type column has three options: shared, independent, and exclusive. Shared means that users in that group can grant and revoke permissions for each other. Independent means that there are also multiple users in that group but they cannot grant or revoke permissions for each other. Exclusive means that there can only be one user in that group.


Part II: Building Sites with Molly

Page Approach vs. Wiki Approach

When building a site with Molly, there are two ways to approach it. The first way is to create multiple pages by creating multiple maml files and linking between the pages. The <maml:block> tag can be used to fill in the content of each page so that it can be edited dynamically from the web. The second approach is to use one maml file with multiple wiki pages from the database. Again, the <maml:block> tag can be used to set which wiki page will be displayed on each page, but only one wiki block can be placed on each maml page.

Creating a New Skin

Files for skins can be found in the decor directory. When building your website with Molly, you may want to create some of your own skins in addition to the default skins. If you already have an HTML webpage with a stylesheet that you would like to make into a skin, here are the steps to do so.

  1. Test your HTML template with the W3C Validator.
  2. Once it checks out, save the template as a .maml file.
  3. Replace the doctype and HTML tags with Molly versions (XHTML 1.1).
  4. Test your template in Molly to make sure the XHTML is well formatted.
  5. Create a new skin by duplicating an existing skin.
  6. Delete the existing CSS file in the skin directory and the images in the images folder.
  7. Copy your stylesheet into the skin directory and rename it “main.css”.
  8. Copy your images into the images folder.
  9. Change the skin in the molly.ini file.
  10. Fix any image paths in your HTML file or stylesheet.

Now that you’ve created your new skin, you can make the style more intelligent by replacing hard coded colors in your stylesheet with Molly tokens, which come from the molly_config table in your database. You can also colorize your images.

To make your pages more intelligent, you can change your template to a .htmf file and move it into the snippets folder. Use the maml:include tag to include snippets in your webpages. You can also use maml:block tags optionally surrounded by maml:windoid tags to make content editable via the web.


Part III: Under the Hood

Main Directory Structure

The default directory structure of a Molly installation is as follows:

folder open
Molly Distribution
vertical line
node
.htaccess
node
folder closed
system
node
folder closed
modules
node
folder closed
decor
vertical line
node
folder closedskins
node
folder closed
docs
node
folder closed
error
node
index.maml
vertical line
etc.
.htaccess
The .htaccess file is Apache's way of setting configurations on a per-directory basis. If your web server does not support .htaccess you will need to enable these configurations in other ways (i.e. via httpd.conf and php.ini). Here is a typical .htaccess file (line numbers added for documentation):
  1. AddType application/x-httpd-php .maml .html .php .tplt .ini .inc .txt .css .mss .php4 .php3 .phtml
  2. DirectoryIndex index.maml index.html index.php
  3.  
  4. php_flag register_globals off
  5.  
  6. SetEnv MOLLY_INI molly.ini
  7.  
  8. php_value short_open_tag off
  9.  
  10. php_value auto_prepend_file /Users/rvullo/Sites/mx/system/loader.php
  11. php_value auto_append_file /Users/rvullo/Sites/mx/system/parser.php
  12.  
  13. # 404: Not Found
  14. ErrorDocument 404 /~rvullo/mx/error/404.maml
  15.  
  16. IndexIgnore .htaccess
  17.  
  18. Options -Indexes
  19.  
  20. php_value upload_max_filesize 30M
Line-by-line Explanation:
  1. Tells Apache to process .maml, .html, .css, etc. files with PHP so that Molly can parse them.
  2. Tells Apache that files named "index.maml" should be loaded instead of listing the contents of a directory.
  3. #
  4. Tells PHP to turn off automatic global generation. This is the default configuration for most PHP installations now. It is included in Molly's .htaccess file just to be sure for security reasons.
  5. #
  6. This is where you tell Molly which .ini file to read for configuration information. By default this is simply molly.ini but if you have multiple Molly installations it is helpful to name each site's .ini file such that you can keep track of them.
  7. #
  8. Some PHP installations have short open tags enabled such that blocks of PHP code can begin with <? instead of <?php. This, however, breaks when you have an <?xml declaration.
  9. #
  10. Tells PHP to automatically include Molly's loader code at the beginning of every processed file.
  11. Tells PHP to automatically include Molly's parser code at the end of every processed file.
  12. #
  13. #
  14. Tells Apache to send Molly's not found page instead of the default apache message. This can be used to automatically redirect users or simply to customize the look of the error page.
  15. #
  16. Tells Apache not to serve .htaccess files.
  17. #
  18. Turns off Apache's automatic directory listings.
  19. #
  20. If your site allows file uploading this directive tells PHP how large of a file to allow.
system
This directory contains the bulk of the code that makes Molly work. See the next section for details.
modules
This is where add-on modules for Molly are located. For details on configuring and using modules see the Modules Reference appendix.
decor
The decor directory is where all files related to the site's look are kept, primarily in the skins subdirectory.
skins
Molly supports the notion of skins for easily varying the look and feel of your site. See the Skins section for details on how they work.
docs
Molly's documentation, primarily this page that you are reading right now. The docs directory is not required on a production site and may be safely removed.
error
Directory for error pages, notably the 404 Not Found page specified in Molly's .htaccess file (above).
index.maml
Default Molly site home page.

System Folder Directory Structure

folder open
system
vertical line
node
molly.ini
node
loader.php
node
parser.php
node
folder closed
core
vertical line
node
folder closed05_utility.inc
vertical line
node
folder closed10_date_time.inc
vertical line
node
folder closed15_file.inc
vertical line
node
folder closed20_database.inc
vertical line
node
folder closed25_sessions.inc
vertical line
node
folder closed27_security.inc
vertical line
node
folder closed30_XML.inc
vertical line
node
folder closed40_tags.inc
vertical line
node
folder closed70_modules.inc
vertical line
node
folder closed80_environment.inc
vertical line
node
folder closed90_parser.inc
vertical line
node
folder closedtags
vertical line
vertical line
last node
folder closedhtml.override.inc
vertical line
vertical line
last node
folder closedmaml.ajax.inc
vertical line
vertical line
last node
folder closedmaml.constructs.inc
vertical line
vertical line
last node
folder closedmaml.database.inc
vertical line
vertical line
last node
folder closedmaml.format.inc
vertical line
vertical line
last node
folder closedmaml.security.inc
vertical line
vertical line
last node
folder closedmaml.tokens.inc
vertical line
vertical line
last node
folder closedmaml.xml.inc
vertical line
node
folder closeddatabase
node
folder closed
scripts
vertical line
etc.
molly.ini
This file contains Molly's configuration settings including paths, database usernames and passwords, etc. May be named anything.ini to make multiple Molly installations more manageable.
loader.php
This script is automatically run at the beginning of a page load (because of the PHP auto_prepend_file directive in Molly's .htaccess file. It reads the molly.ini file (above) and sets up everything for Molly.
parser.php
This script is automatically run at the end of a page load (because of the PHP auto_append_file directive in Molly's .htaccess file. It does the actual parsing of Molly's MAML tags and substitution of tokens.
core
This directory contains all of the include (.inc) files that provide the bulk of Molly's functionality. All .inc files within this directory (and the tags directory with in it) are automatically included by loader.php (and 40_tags.inc). The include files directly inside the core are named with numerical prefixes because they must be loaded in order due to dependencies.
05_utility.inc
Utility functions for Molly programmers.
10_date_time.inc
Code for converting and manipulating dates, time, time zones, etc.
15_file.inc
File reading functions.
20_database.inc
Database abstraction functionality.
25_sessions.inc
Callback functions for session_set_save_handler() allowing Molly to store sessions and associated information in a database table. Among other things this allows us to easily determine who's logged in, and to share sessions across multiple web servers.
27_security.inc
Molly's user login system.
30_XML.inc
XML, DOM, and XSLT processing (no functionality yet).
40_tags.inc
Contains prototype tag and template classes, page building utility functions, and loads all of the tag class definitions from the tags directory.
70_modules.inc
Loads code for modules. Modules are optional add-ons to Molly. Over time some modules may migrate into Molly's core.

Modules to be loaded are specified in the molly.ini file for the site in the [Modules] section. This file automatically includes any .inc files found within each module's directory.

Each modules directory contains a documentation file named docs.htmf which is automatically be included into the Modules appendix of this document.
80_environment.inc
Utility code that Molly uses to determine the current environment - for example if a tag has been implemented.
90_parser.inc
The actual parser code called by parser.php.
tags
This directory contains the include files with all of Molly's MAML tag class definitions. They are in separate files based on functionality for easier coding and support.
html.override.inc
Molly processes a few HTML tags in order to simplify developing MAML pages. These include the <html>, <head>, and <style> tags.
maml.ajax.inc
Under development: hopefully simple way to implement AJAX.
maml.constructs.inc
Under development: rudimentary branching functionality.
maml.database.inc
Database access tags such as <maml:fetch> and <maml:form> and all of their associated tags.
maml.format.inc
Tags which implement user interface components such as menus and windoids.
maml.security.inc
Tags for implementing user login and user/group specific viewing permissions.
maml.tokens.inc
Tags which allow webmasters to create tokens either on a per-page-view basis or a per-session basis.
maml.xml.inc
Contains the class definition for the <maml:nothing> tag. This tag acts as a root XML element for MAML files which generate non-web-page results for use in AJAX and web services. If we re-implement Molly's SOAP functionality, that would go here.
database
Contains the ADODB database abstraction code employed by Molly. (Longtime Molly developers should note that this open source solution replaces Molly's original database abstraction code which had been developed specifically for Molly.)
scripts
Javascript code used by Molly.

Files to be parsed by Molly

Extension Action
.php Process as normal php, no Molly functionality
.inc PHP include files
.html Process similarly to Molly 1, that is, set all the globals and include basic function and object libraries and module libraries, then procede to pass the file through the php parser. (Note that for normal HTML files this does essentially nothing, but that it allows you to minimally incorporate some of Molly's functionality if you understand the underlying architecture.)
.maml Set all the globals and include all the libraries and modules, then parse the file through Molly's MAML XML parser.
.tplt template files
.ini prevent being served to the web
.txt (Maybe turn into a nice formatted web page?)
.mss & .css Treated like a template file - that is, all *[tokens]* are replaced with config values

Molly's Parsing Engine

Previous versions of molly used the SAX (Simple API for XML) parser using xml_parser_create(). SAX was available in PHP 4 and compatible with PHP 5. It functions as a stream parser with an event-driven API. It is a push parser; the user defines a number of callback methods that will be called when the parsing events occur. The SAX interface does not deal in elements, but in events that correspond to tags. SAX parsing is unidirectional, which means that previously parsed data cannot be reread without restarting the parsing operation. Molly's new engine uses the new XMLReader object. This is a wrapper on Libxml2, which is a widely used XML C parser. Like SAX, XMLReader is also a stream based parser. But unlike SAX, XMLReader is a pull parser, meaning it only parses what is asked for by the application. It acts as a cursor moving forward on the document stream and stopping at each node on the way. XMLReader has a very small memory footprint and is faster than SAX because there is no need for it to process callbacks you do not care about.

Embedded JavaScript

Molly is an XML Parser, so whenever she sees a < she thinks a tag is beginning. Now obviously this isn't the case in a block of JavaScript. Browsers have learned to ignore code inside <script></script> tags, but technically that's not correct. The solution is to place the JavaScript code inside a CDATA block which tells the XML parser not to parse that text.

<script language="javascript" type="text/javascript">
<![CDATA[
 
    // JavaScript code goes here
 
]]>
</script>

Appendix I: Installing Molly

Might be helpful: http://shapeshed.com/journal/setting_up_local_websites_on_snow_leopard/

Environment

Molly is designed to be deployed on a Unix or Linux system running the Apache web server and PHP 5. Molly users have successfully installed and used Molly on Windows servers running Apache, however the core developers do not currently test or support that environment. For the curious, the main development platform for core development is currently Mac OS X (version 10.6.2 - Snow Leopard), PHP 5 (version 5.3.0), Apache 2 (version 2.2.13), and MySQL Server (version 5.1.43). The main Molly site (molly.rit.edu) is deployed on production server running Linux (version), Apache 2 (version) PHP 5 (version), and MySQL (version). Molly should run fine on any recent version of the above software as we try to avoid specific late version dependencies.

Downloading and Uploading Molly

The latest version of Molly can always be downloaded from molly.rit.edu. Molly is distributed as a GZipped Tar file. Upload the Molly archive to your server's web directory. On many Unix and Linux systems this directory will be named "public_html" or "www" and on most Macintosh servers it is named "Sites."

  1. Using SSH connect to your server and log in. Change directories to your web directory.
  2. If you do an ls you should see the .tar.gz file that you just uploaded.
  3. Uncompress the molly archive file into a tar (Unix "tape archive") file, then untar the resulting .tar file.:
    gunzip molly.tar.gz
    tar -xf molly.tar

At this point you should have a directory named molly inside your web directory. (The Unix tar program preserves all of the directories' and files' privileges, so they are all set for you.)

Configuration

Once you have Molly's files installed on your server there are a few things you need to do to configure Molly:

Configure Apache

Modifying /private/etc/apache2/httpd.conf

Turn on Environment Variables module.

Find and uncomment (add if they're missing) the following two lines:

  #LoadModule env_module         libexec/httpd/mod_env.so
  #AddModule mod_env.c

Allow .htaccess files in the main web directory to modify configurations.

Around line 400 (inside the <Directory "/Library/WebServer/Documents"> on OS X) is the following directive:

  AllowOverride None

Change it to:

  AllowOverride All

(Actually, "AllowOverride FileInfo Options Indexes" should be sufficient.)

Modifying User .conf file(s)

MacOS X has an individual .conf file for each user on the system. In the /private/etc/apache2/users will be a .conf file for each user on the system. Edit the user.conf file for each user who will be using Molly as follows.

Change:

  AllowOverride None

to:

  AllowOverride FileInfo Options

Configure Database

Molly Account and Database

If you are the database administrator you will need to log in and create the database and username that Molly will use to access the database. If you do not have administrative privileges, skip to the next section and use the username and database assigned to you.

Replace MySQL stuff with updated screen captures.

Log in as the root user:

 
  [Ronald-Vullos-Computer:~/Sites] rvullo% mysql -uroot -p
  Enter password:
  Welcome to the MySQL monitor.  Commands end with ; or \g.
  Your MySQL connection id is 355 to server version: 4.0.17-standard
  
  Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
  
  mysql>

Let's assume you want to create a database named "mollydb" and that Molly will be connecting to this system as user "mollyuser" with the password "mollypass." As root user you would create the database and assign the access privileges as such:

 
  mysql> create database mollydb;
  Query OK, 1 row affected (0.07 sec)
  
  mysql> grant all privileges on mollydb.* to mollyuser@localhost identified by 'mollypass';
  Query OK, 0 rows affected (0.71 sec)
  
  mysql> 

Root administrative tasks are finished, so log out:

 
  mysql> exit
  Bye
  [Ronald-Vullos-Computer:~/Sites] rvullo% 

Install Database Tables

Creating Molly's Tables and Loading Default Data

The easiest way to do this is to first change directories into the directory containing the SQL files provided with Molly:

 
  [Ronald-Vullos-Computer:~/Sites] rvullo% cd system/database/sql
  [Ronald-Vullos-Computer:system/database/sql] rvullo% 
   

Next you will log into MySQL using the username and password that Molly will use (either created above, or provided by your database administrator or ISP). Once logged in you will select Molly's database and into it load first the schema which will create all the tables (mysql.sql), then the data to populate those tables (data.sql):

 
  [Ronald-Vullos-Computer:system/database/sql] rvullo% mysql -umollyuser -p
  Enter password: 
  Welcome to the MySQL monitor.  Commands end with ; or \g.
  Your MySQL connection id is 357 to server version: 4.0.17-standard
  
  Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
  
  mysql> use mollydb;
  Database changed
  mysql> source mysql.sql;
  Query OK, 0 rows affected (0.43 sec)
  
  Query OK, 0 rows affected (0.06 sec)
  
       Several identical lines deleted for brevity
  
  Query OK, 0 rows affected (0.00 sec)
  
  mysql> source data.sql;
  Query OK, 1 row affected (0.02 sec)
  
  Query OK, 1 row affected (0.00 sec)
  
       Many identical lines deleted for brevity
  
  Query OK, 1 row affected (0.00 sec)
  
  mysql> exit
  Bye
  [Ronald-Vullos-Computer:system/database/sql] rvullo% 
  

At this point Molly's database should be all set. The next step will be to set the appropriate values in the molly.ini file.

Edit molly.ini file

Go to the system directory within Molly and open up the molly.ini file. There are several things that you will need to change in this file.

  1. In line 34, change "jpeg" to "png" if necessary depending on your operating system.
  2. In line 41, change the email address to your own email address.
  3. In lines 48, 49, and 50, change the file paths to the correct paths to your directories.
  4. In lines 62, 63, 68, 69, 92, 93, 147, and 148, change the information to your database and username.
  5. In lines 64, 70, 94, and 149, change the password to your own password.
  6. In line 72, make the session name something unique.

Edit .htaccess file

The .htaccess file is located inside the main Molly directory. All you need to do with this file is to change "mollyuser" to your username in lines 13 and 14.

Testing Molly

  1. Start by accessing your Molly site from your browser. The URL should be something like: http://www.yourserver.com/~yourid/molly/ and should look like this:

    molly screen capture
  2. If the site looks like the one in the illustration above, then you're good to go. If you see a sort-of broken looking site with lots of pink, then there is a problem with your database, since Molly loads much of the user interface design information from a database table named 'molly_config.' You may also see error messages. Often this is a result of not having the correct mysql username and password settings in the molly.ini file. If what you see is nothing even close to a web site, then you probably have errors in your .htaccess file. (Molly's installer created both of these files for you, but you may edit them if need be.)


Appendix II: MAML Tag Reference

The following documentation is generated automatically from the class definitions used by Molly to implement MAML tags. All MAML & MAGE tags have optional id and style attributes. If you do not provide an ID, Molly will automatically generate a unique ID where appropriate. Default attribute values are shown. Some attribute defaults are set in the system/molly.ini file.

maml:a

Attributes:

Prototype: <maml:a showtext = "" href = "" rel = "" target = "" dateformat = "" startdate = "" enddate = "" startweek = "" endweek = "" startday = "" endday = "" permitted = "" id = "maml_a_0" class = "" style = "visibility:visible;"></maml:a>

Description: Description here.

Path: /var/www/html/modules/schedule/schedule.inc
Start Line: #723


maml:ajax

Attributes:

Prototype: <maml:ajax node = "" event = "" action = "" target = "" id = "maml_ajax_1" class = "" style = "visibility:visible;"></maml:ajax>

ajax docs here
Path: /var/www/html/system/core/tags/maml.ajax.inc
Start Line: #3


maml:block

Attributes:

Prototype: <maml:block permitted = "" blocknum = "" wiki = "" blockid = "" id = "maml_block_2" class = "" style = "visibility:visible;"></maml:block>

Description: Allows the webmaster to designate an area of the page as editable online by members of the permitted group. When those members are logged in they will see an editor in place of the normally static content.

Molly automatically creates the link between blocks and the records in the molly_blocks table (field: block_id) however it should be noted that these links are somewhat fragile as they are based on the file name (and path relative to HTMLRoot), and the position (order) of the block on the page if there are more than one block. Because of this, there is an optional blocknum attribute that can be used if the order of blocks on a page must be changed after the records in the database table exist. Alternatively the database record can be edited if neccessary to reflect a relocated block or renamed/moved page.

If the blockid is set, this allows the same block to be used on multiple pages rather than tying it to a particular page.

The block tag can also be used to create a wiki. Setting the wiki attribute returns that wiki page from the database and activates automatic wiki linking via putting {{link name}} in the block’s text. You can only have one wiki block per MAML page. To create a new wiki page, create a wiki link then follow it from the editor’s preview page (). Use of the wiki attribute overrides use of the blockid attribute.

Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #953


maml:box

Attributes:

Prototype: <maml:box title = "" id = "maml_box_3" class = "" style = "visibility:visible;"></maml:box>

Description: Creates a round-cornered box around whatever it encloses based on the box.top.tplt and box.bottom.tplt template files, the default.css styles, and values in the config database table. The optional title attribute is displayed at the top of the box. The box itself is created from two image files (decor/rounded-left-template.png and decor/rounded-right-template.png) which are colorized using Molly’s image colorizing code. It would be nice to add a color attribute to allow override of the default color BoxFrameColor from the config database table.

Path: /var/www/html/system/core/tags/maml.format.inc
Start Line: #148


maml:calendar

Attributes:

Prototype: <maml:calendar permitted = "" size = "" showappointments = "" year = "" month = "" mode = "" week = "" display = "" id = "" class = "" style = "visibility:visible;"></maml:calendar>

An empty calendar tag, <maml:calendar />, will produce a calendar in that location on the page. The user of the calendar can scroll forward or backward through the months. Additionally, based on the setting of the permitted attribute, users can add, edit, and delete events.

A tag with a specified mode with the value "static" is known as a static calendar. This will be a calendar independent of the other calendars on the page. This allows for more than one calendar to be on a page but does not allow the user the ability to scroll to the next or previous months.

Calendar Tag Attributes:

For more information, please see the module documentation.

Path: /var/www/html/modules/calendar/calendar.inc
Start Line: #41


maml:captcha

Attributes:

Prototype: <maml:captcha id = "maml_captcha_4" class = "" style = "visibility:visible;"></maml:captcha>

Adds captcha protection to Molly forms.

Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #600


maml:desist

Attributes:

Prototype: <maml:desist name = "data" id = "maml_desist_5" class = "" style = "visibility:visible;"></maml:desist>

Description: destroys a token created by a <maml:persist> tag and removes its data from memory.

Path: /var/www/html/system/core/tags/maml.tokens.inc
Start Line: #25


maml:else

Attributes:

Prototype: <maml:else id = "maml_else_6" class = "" style = "visibility:visible;"></maml:else>

Description: The <maml:else> works within the <maml:if> tag to allow one to conditionally display portions of the page.

<maml:if condition="'*[token]*' == 'value'">
    <p>True Stuff (inside an if).</p>
    <maml:else>
        <p>False Stuff (inside an else).</p>
    </maml:else>
</maml:if>
 
Path: /var/www/html/system/core/tags/maml.constructs.inc
Start Line: #52


maml:extension

Attributes:

Prototype: <maml:extension name = "" id = "maml_extension_7" class = "" style = "visibility:visible;"></maml:extension>

Description: Used in conjunction with <maml:filelist> tag to retrieve a list of files from a directory.

Replaces itself with the extension of the file for each file found.

Alternatively you may use the *[extension]* token, for example if you wish to include the extension in an attribute of another tag.

See <maml:filelist> tag for example usage.

Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #319


maml:fetch

Attributes:

Prototype: <maml:fetch query = "" table = "" fields = "*" sort = "" order = "ascending" criteria = "" maxentries = "" start = "1" key = "" detail = "" host = "" database = "" user = "" password = "" id = "maml_fetch_8" class = "" style = "visibility:visible;"></maml:fetch>

Description: Used to retrieve results from a database. Together with the <maml:row> and <maml:field> tags this allows you to retrieve and display data from Molly’s database.

Example:

<maml:fetch table="molly_test" key="name" criteria="true" detail="form.maml" format="off">
    <table style="width:20em;">
        <tr>
            <th><maml:sort sort="name">Name</maml:sort></th>
            <th><maml:sort sort="eyecolor" order="descending">Eye Color</maml:sort></th>
            <th><maml:sort sort="age">Age</maml:sort></th>
        </tr>
        <maml:row maxentries="3">
        <tr>
            <td><maml:field name="name"/></td>
            <td><maml:detail href="advancedLists.maml"> <maml:field name="eyecolor"/></maml:detail></td>
            <td><maml:detail href="advancedForm.maml"> <maml:field name="age"/></maml:detail></td>
        </tr>
        </maml:row>
    </table>
  Total Records: <maml:numrows/><br/>
  <maml:previous>Previous <maml:numrows/> Records </maml:previous>
  | <maml:pages delimiter="-" /> |
  <maml:next>Next <maml:numrows/> Records </maml:next><br/>
</maml:fetch> 
 

Results:

Name Eye Color Age
Genny Brown 6
Heather Blue 28
Michelle brown 12
Ron Brown 48
Tim brown 22
Total Records:
Previous Records | | Next Records

Things which are known to be not working:

Example from select_tag_test.maml - be sure to update these docs as functionality is added.

Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #17


maml:field

Attributes:

Prototype: <maml:field name = "" id = "maml_field_9" class = "" style = "visibility:visible;"></maml:field>

Description: Used in conjunction with <maml:fetch> tag to retrieve results from a database.

Replaces itself with the data retrieved from that field by the <maml:fetch> tag’s query.

See <maml:fetch> tag for example usage.

Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #251


maml:filelist

Attributes:

Prototype: <maml:filelist path = "FilePath" extension = "" dateformat = "d F Y H:i:s" id = "maml_filelist_10" class = "" style = "visibility:visible;"></maml:filelist>

<maml:filelist path="/unix/" extension="jpg" filetype="dir | file" dateformat="d F Y H:i:s">

The maml:filelist tag, together with the associated maml:filename, maml:fileroot, maml:filesize, maml:permissions, maml:filetype, maml:modtime, and maml:extension tags allow you to gather and use information about all of the files in a specified directory. This can be to display a simple list, like the example below, or to build a file picker widget like the one used in the config administration tool. The maml:filelist tag pair repeats its contents for each file found in the directory. Using the extension attribute you can limit the results to one or more file types.

Example:

<table>
    <tr>
        <th>filename</th>
        <th>fileroot</th>
        <th>filesize</th>
        <th>permissions</th>
        <th>filetype</th>
        <th>modtime</th>
        <th>extension</th>
    </tr>
    <maml:filelist path="/var/www/html/decor/skins/mx/images/" extension="gif jpg">
        <tr>
            <th><maml:filename /></th>
            <td><maml:fileroot /></td>
            <td><maml:filesize /></td>
            <td><maml:permissions /></td>
            <td><maml:filetype /></td>
            <td><maml:modtime /></td>
            <td><maml:extension /></td>
        </tr>
    </maml:filelist>
</table>
 

Results:

filenamefilerootfilesizepermissionsfiletypemodtimeextension
img01.tplt.jpg img01.tplt 22804 -rwxr-xr-x file 20 January 2012 08:41:27 jpg
img03.tplt.jpg img03.tplt 8372 -rwxr-xr-x file 09 October 2014 13:27:26 jpg
mxhead-dark.tplt.jpg mxhead-dark.tplt 42069 -rw-r--r-- file 10 October 2014 10:39:34 jpg
mxhead-light.tplt.jpg mxhead-light.tplt 59228 -rwxr-xr-x file 10 October 2014 10:35:12 jpg
mxhead.tplt.jpg mxhead.tplt 44546 -rw-r--r-- file 10 October 2014 10:38:28 jpg
test_pattern_green.gif test_pattern_green 23881 -rw-r--r-- file 19 January 2012 09:25:11 gif
tinymolly.jpg tinymolly 5543 -rwxr-xr-x file 03 February 2011 14:12:37 jpg
Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #108


maml:filename

Attributes:

Prototype: <maml:filename name = "" id = "maml_filename_11" class = "" style = "visibility:visible;"></maml:filename>

Description: Used in conjunction with <maml:filelist> tag to retrieve a list of files from a directory.

Replaces itself with the name of the file for each file found.

Alternatively you may use the *[filename]* token, for example if you wish to include the filename in an attribute of another tag.

See <maml:filelist> tag for example usage.

Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #223


maml:fileroot

Attributes:

Prototype: <maml:fileroot name = "" id = "maml_fileroot_12" class = "" style = "visibility:visible;"></maml:fileroot>

Description: Used in conjunction with <maml:filelist> tag to retrieve a list of files from a directory.

Replaces itself with the name of the file sans the extension for each file found.

Alternatively you may use the *[fileroot]* token, for example if you wish to include the fileroot in an attribute of another tag.

See <maml:filelist> tag for example usage.

Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #239


maml:filesize

Attributes:

Prototype: <maml:filesize name = "" id = "maml_filesize_13" class = "" style = "visibility:visible;"></maml:filesize>

Description: Used in conjunction with <maml:filelist> tag to retrieve a list of files from a directory.

Replaces itself with the filesize of the file for each file found.

Alternatively you may use the *[filesize]* token, for example if you wish to include the filesize in an attribute of another tag.

See <maml:filelist> tag for example usage.

Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #255


maml:filetype

Attributes:

Prototype: <maml:filetype name = "" id = "maml_filetype_14" class = "" style = "visibility:visible;"></maml:filetype>

Description: Used in conjunction with <maml:filelist> tag to retrieve a list of files from a directory.

Replaces itself with the filetype of the file for each file found.

Alternatively you may use the *[filetype]* token, for example if you wish to include the filetype in an attribute of another tag.

See <maml:filelist> tag for example usage.

Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #287


maml:form

Attributes:

Prototype: <maml:form keyvalue = "" table = "" keyfield = "" criteria = "" response = "" mode = "" action = "none" name = "maml_form_15" schema = "off" ownership = "none" owner = "" permitted = "all" linkname = "" linkfield = "" id = "maml_form_15" class = "" style = "visibility:visible;"></maml:form>

Description: Molly’s forms are, by design, very similar to the HTML forms webmasters are used to. The big difference is that Molly’s forms automatically connect with the database and require no additional programming.

The table attribute is the name of the database table that this form will be interacting with. The response attribute is the url of the page that the user will be sent to after submitting the form. The keyfield attribute identifies the field in the database used as the primary key. The schema attribute tells Molly to write the basic SQL code needed to create a database table to support the form (partially implemented).

<maml:form table="molly_test" response="form_test.maml" keyfield="test_id" keyvalue="*[t_Link]*" mode="replace" schema="on">
   Name: <maml:input type="text" name="name" size="24" /><br/>
   Eye Color: <maml:input type="text" name="eyecolor" value="*[t_RenderAs]*"/><br/>
   Age: <maml:input type="text" name="age" value="*[t_Link]*"/><br/>
 
    <maml:fetch table="molly_username" maxentries="2" fields="lastname, firstname, user_id" orderby="lastname">
        <maml:select name="file_token" size="1">
            <maml:option>Choose One:</maml:option>
            <maml:row>
                <maml:option value=""><maml:field name="lastname" />, <maml:field name="firstname"/> (*[user_id]*)</maml:option>
            </maml:row>
        </maml:select>
    </maml:fetch>
 
   <maml:input type="submit" value="MAML submit Button"/>
</maml:form>
 
Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #338


maml:if

Attributes:

Prototype: <maml:if condition = "" else = "" id = "maml_if_16" class = "" style = "visibility:visible;"></maml:if>

Description: The <maml:if> tag allows one to conditionally display portions of the page.

<maml:if condition="'*[token]*' == 'value'">
    <p>True Stuff (inside an if).</p>
    <maml:else>
        <p>False Stuff (inside an else).</p>
    </maml:else>
</maml:if>
 
Path: /var/www/html/system/core/tags/maml.constructs.inc
Start Line: #7


maml:img

Attributes:

Prototype: <maml:img id = "maml_img_17" class = "" style = "visibility:visible;"></maml:img>

Description: This is a placeholder for a future <maml:image /> tag with the following features:

Path: /var/www/html/system/core/tags/maml.format.inc
Start Line: #246


maml:include

Attributes:

Prototype: <maml:include src = "" parse = "maml" debug = "" id = "maml_include_18" class = "" style = "visibility:visible;"></maml:include>

Description: Reads the file specified in the src attribute and inserts it into the document. If parse="maml" then it is processed as a MAML file as it is being inserted. If parse="html" then only the portion of the file between the <body> and </body> tags is included. If src is a URL instead of a filespec, then this tag will fetch the file from the specified server. parse="xml" is not yet implemented.

Path: /var/www/html/system/core/tags/maml.format.inc
Start Line: #184


maml:input

Attributes:

Prototype: <maml:input type = "" name = "" value = "" size = "16" selected = "" id = "maml_input_19" onclick = "" onfocus = "" onblur = "" onchange = "" onselect = "" onreset = "" encryption = "" emailreset = "" passwordreset = "" class = "" style = "visibility:visible;"></maml:input>

New tag documentation goes here.

Old Docs:

Must be within <maml:form></maml:form> pair.

Required Attribute: type [text|submit|hidden|checkbox|radio|password]
Optional Attribute: name
Optional Attribute: value
Optional Attribute: selected 	// [CHECKED] for radio andcheckbox
Example:
	<maml:form table="test" response="/~rvullo/m2/test/list.maml" keyfield="age" schema="on">
		Name: <maml:input type="text" name="name"/><br/>
		Eye Color: <maml:input type="text" name="eyecolor"/><br/>
		Age: <maml:input type="text" name="age"/><br/>
		<maml:input type="submit" value="I am a submit Button"/>
	</maml:form> 
Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #619


maml:item

Attributes:

Prototype: <maml:item href = "" target = "_self" selected = "" id = "maml_item_20" class = "" style = "visibility:visible;"></maml:item>

prototype_tag is a generic class for MAML tags so that they can inherit methods such as id(). Undocumented tag classes inherit this documentation.
Path: /var/www/html/system/core/tags/maml.format.inc
Start Line: #105


maml:login

Attributes:

Prototype: <maml:login response = "/" fail = "Invalid Login" logout = "" id = "" class = "" style = "visibility:visible;"></maml:login>

prototype_tag is a generic class for MAML tags so that they can inherit methods such as id(). Undocumented tag classes inherit this documentation.
Path: /var/www/html/system/core/tags/maml.security.inc
Start Line: #4


maml:menu

Attributes:

Prototype: <maml:menu type = "tabs" id = "maml_menu_21" class = "" style = "visibility:visible;"></maml:menu>

prototype_tag is a generic class for MAML tags so that they can inherit methods such as id(). Undocumented tag classes inherit this documentation.
Path: /var/www/html/system/core/tags/maml.format.inc
Start Line: #72


maml:modtime

Attributes:

Prototype: <maml:modtime name = "" id = "maml_modtime_22" class = "" style = "visibility:visible;"></maml:modtime>

Description: Used in conjunction with <maml:filelist> tag to retrieve a list of files from a directory.

Replaces itself with the modtime of the file for each file found.

Alternatively you may use the *[modtime]* token, for example if you wish to include the modtime in an attribute of another tag.

See <maml:filelist> tag for example usage.

Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #303


maml:multiple

Attributes:

Prototype: <maml:multiple count = "1" button = "after" label = "Add Another" id = "maml_multiple_23" class = "" style = "visibility:visible;"></maml:multiple>

Description: This tag allows the user to replicate whatever it encloses using client-side (JavaScript/DOM) code. This is particularly useful inside a <maml:form> to allow the user to create several records at once when submitting a form. (This is actually what it is designed for, but we opened it up to be used outside fo forms to see what other uses we might find for it.)

Button value placements:

before Before the section to be duplicated.
after After the section to be duplicated.
beforeeach At the beginning of the section to be duplicated. (Gets duplicated along with section.)
aftereach At the end of the section to be duplicated. (Gets duplicated along with section.)
Path: /var/www/html/system/core/tags/maml.format.inc
Start Line: #272


maml:nothing

Attributes:

Prototype: <maml:nothing id = "maml_nothing_24" class = "" style = "visibility:visible;"></maml:nothing>

Description: The <maml:nothing tag allows you to insert tags to make the parser happy, such as declaring the maml namespace for files that only produce snippets for inclusion or AJAX calls.

Path: /var/www/html/system/core/tags/maml.xml.inc
Start Line: #6


maml:numrows

Attributes:

Prototype: <maml:numrows id = "maml_numrows_25" class = "" style = "visibility:visible;"></maml:numrows>

Description: Used in conjunction with <maml:fetch> tag to display the number of records returned.

Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #312


maml:option

Attributes:

Prototype: <maml:option id = "maml_option_26" onclick = "" ondblclick = "" onmousedown = "" onmousemove = "" onmouseout = "" onmouseover = "" onmouseup = "" onkeydown = "" onkeypress = "" onkeyup = "" disabled = "" label = "" selected = "" value = "" class = "" style = "visibility:visible;"></maml:option>

prototype_tag is a generic class for MAML tags so that they can inherit methods such as id(). Undocumented tag classes inherit this documentation.
Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #845


maml:permissions

Attributes:

Prototype: <maml:permissions name = "" id = "maml_permissions_27" class = "" style = "visibility:visible;"></maml:permissions>

Description: Used in conjunction with <maml:filelist> tag to retrieve a list of files from a directory.

Replaces itself with the unix-style permissions string of the file for each file found.

Alternatively you may use the *[permissions]* token, for example if you wish to include the permissions in an attribute of another tag.

See <maml:filelist> tag for example usage.

Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #271


maml:persist

Attributes:

Prototype: <maml:persist name = "data" id = "maml_persist_28" class = "" style = "visibility:visible;"></maml:persist>

Description: Creates a token and stores the contents of the tags in that token. Tokens persist until the browser session ends or times out, or until a <maml:desist> tag is encountered.

Path: /var/www/html/system/core/tags/maml.tokens.inc
Start Line: #4


maml:protect

Attributes:

Prototype: <maml:protect permitted = "all" denied = "" id = "maml_protect_29" class = "" style = "visibility:visible;"></maml:protect>

Description: The <maml:protect> tag allows one to restrict access to/viewability of a portion of page based on the user’s membership in a group specified in the permitted attribute. (These groups are represented in the molly_permissions table in the database.) The special group all allows all logged in users access, but not users who have not logged in (it represents, therefore, “all registered users”). Another special group guest allows only users who are not logged in to see the content.

The optional denied attribute specifies a string to be used to replace the protected section of the page. in the absence of the denied attribute the area will be left empty.

Path: /var/www/html/system/core/tags/maml.security.inc
Start Line: #59


maml:quickquery

Attributes:

Prototype: <maml:quickquery query = "select * from molly_test" height = "24em" id = "maml_quickquery_30" class = "" style = "visibility:visible;"></maml:quickquery>

Description: Perform a query and dump out the results using the PHP var_dump function (default query is "select * from molly_test"). This tag should not be used for user-viewed web pages. Results are placed in a scrollable <pre> area, the default height of which is 24em.

Path: /var/www/html/modules/developer/developer.inc
Start Line: #61


maml:quiz

Attributes:

Prototype: <maml:quiz permitted = "" id = "" style = "" retake = "" class = ""></maml:quiz>

An empty quiz tag <maml:quiz />, will produce a quiz module. This includes a quizbook which is a list of all of the quizzes in the database, the score if the quiz has been taken and the link to take it. When the user clicks on a link to take the quiz it will bring them to the correct quiz and allow them to take it. Once they have submitted the quiz, they will be redirected to a score page which shows them which questions they got correct and what their score is. If the user has never taken the quiz or gets a higher score than the score currently saved for them in the database, then their score will be saved. If they do not beat the highest score, their score will not be saved.

A tag with a specified style will determine the style that the answers will be displayed in. Currently this supports radio buttons and select menus

A tag with a specified retake will determine if retake is specified false, the user can only take the quiz once. If it is specified true, the user can take the quiz as many times as they want.

An example of this is <maml:quiz id="1" style="radio" retake="false" />

Path: /var/www/html/modules/quiz/quiz.inc
Start Line: #7


maml:redirect

Attributes:

Prototype: <maml:redirect href = "" id = "maml_redirect_31" class = "" style = "visibility:visible;"></maml:redirect>

Description: The <maml:redirect> leaves the current page and goes to the page specified in the href attribute. (Technically, it sends a location header to the browser telling it to request the new page.)

Path: /var/www/html/system/core/tags/maml.constructs.inc
Start Line: #81


maml:row

Attributes:

Prototype: <maml:row empty = "" maxentries = "" id = "maml_row_32" class = "" style = "visibility:visible;"></maml:row>

Description: Used in conjunction with <maml:fetch> tag to retrieve results from a database.

The <maml:row> tag duplicates its contents for each row (record) found by the <maml:fetch> tag’s query.

See <maml:fetch> tag for example usage.

Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #202


maml:schedule

Attributes:

Prototype: <maml:schedule dateformat = "" startdate = "" enddate = "" startweek = "" endweek = "" startday = "" endday = "" permitted = "" id = "maml_schedule_33" class = "" style = "visibility:visible;"></maml:schedule>

Description: Description here.

Path: /var/www/html/modules/schedule/schedule.inc
Start Line: #247


maml:select

Attributes:

Prototype: <maml:select name = "" size = "" disabled = "" multiple = "" tabindex = "" onclick = "" onfocus = "" onblur = "" onchange = "" onselect = "" onreset = "" id = "maml_select_34" class = "" style = "visibility:visible;"></maml:select>

prototype_tag is a generic class for MAML tags so that they can inherit methods such as id(). Undocumented tag classes inherit this documentation.
Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #753


maml:sort

Attributes:

Prototype: <maml:sort sort = "" order = "ascending" id = "maml_sort_35" class = "" style = "visibility:visible;"></maml:sort>

Description: Used in conjunction with <maml:fetch> tag to retrieve results from a database.

Creates links which allow the user to sort the results of the <maml:fetch> tag’s query.

See <maml:fetch> tag for example usage.

Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #267


maml:term

Attributes:

Prototype: <maml:term startdate = "" enddate = "" id = "maml_term_36" class = "" style = "visibility:visible;"></maml:term>

Must be within <maml:term></maml> pair.
    Required Attribute: startdate
    Required Attribute: dateformat
    Optional Attribute: enddate
Path: /var/www/html/modules/schedule/schedule.inc
Start Line: #10


maml:textarea

Attributes:

Prototype: <maml:textarea name = "" id = "maml_textarea_37" cols = "50" rows = "25" class = "" style = "" onclick = "" onfocus = "" onblur = "" onchange = "" onselect = "" onreset = ""></maml:textarea>

Tag documentation goes here.

Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #1092


maml:timeformat

Attributes:

Prototype: <maml:timeformat format = "unix" id = "maml_timeformat_38" class = "" style = "visibility:visible;"></maml:timeformat>

Description: Converts a timestamp (as from a database) to either unix or javascript timestamp format (i.e. second or miliseconds since January 1, 1970 00:00:00 UTC).

Path: /var/www/html/system/core/tags/maml.database.inc
Start Line: #1202


maml:token

Attributes:

Prototype: <maml:token name = "" value = "" id = "maml_token_39" class = "" style = "visibility:visible;"></maml:token>

Description: The <maml:token> tag allows you to set the value of a token for use later on the page. The token specified by the name attribute is set to the contents of the tag. You may also use the optional value attribute which will override the contents of the tag and so should be used with he empty tag syntax for clarity.

<maml:token name="Fred">My Name is Fred.</maml:token>
Token *<span>[Fred]</span>* is <strong> *[Fred]* </strong>

or

<maml:token name="Fred" value="My Name is Fred" />
Token *<span>[Fred]</span>* is <strong> *[Fred]* </strong>
Path: /var/www/html/system/core/tags/maml.tokens.inc
Start Line: #42


maml:upload

Attributes:

Prototype: <maml:upload label = "Upload Files" maxsize = "1048576" destination = "mp/videotracks" response = "" process = "" type = "" callback = "" id = "maml_upload_40" class = "" style = "visibility:visible;"></maml:upload>

Creates a widget for uploading files via AJAX.

Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #6


maml:vardump

Attributes:

Prototype: <maml:vardump global = "gv_SiteGlobals" height = "24em" id = "maml_vardump_41" class = "" style = "visibility:visible;"></maml:vardump>

Description: Dump out contents of a global variable. Set the global attribute to the name of the global variable - without the dollar sign (default is "gv_SiteGlobals"). Results are placed in a scrollable <pre> area, the default height of which is 24em.

Path: /var/www/html/modules/developer/developer.inc
Start Line: #38


maml:windoid

Attributes:

Prototype: <maml:windoid title = "" showMsg = "" hideMsg = "" id = "maml_windoid_42" class = "" style = "visibility:visible;"></maml:windoid>

Description: Creates a window-like box around whatever it encloses based on the windoid.begin.tplt and windoid.end.tplt template files, the default.css styles, and values in the config database table. The title attribute is displayed in the titlebar of the windoid.

In previous versions of Molly this tag had additional attributes, some of which we may wish to re-create or re-think:

Path: /var/www/html/system/core/tags/maml.format.inc
Start Line: #2


maml:windowsize

Attributes:

Prototype: <maml:windowsize id = "maml_windowsize_43" class = "" style = "visibility:visible;"></maml:windowsize>

Description: Creates widget that gives a live readout of the widow's dimensions.

Path: /var/www/html/modules/developer/developer.inc
Start Line: #5



Appendix III: Modules Reference

Modules are optional add-ons to Molly. Over time some modules may migrate into Molly's core.

Modules to be loaded are specified in the molly.ini file for the site in the [Modules] section. There each module is listed with the path to the module's directory. Molly will then automatically include any .inc files found within that directory. Most modules will only require one .inc file and by convention that .inc file will be named the same as the module. So, for example, the Calendar module included with Molly is located in the calendar directory and has one .inc file named calendar.inc

Example [Modules] Section of molly.ini

[Modules]		; path relative to [Paths]HTMLRoot + [Paths]ModulesDir
ZipCodes = "zipcodes/"
Calendar = "calendar/"			

Modules should also include a documentation file named docs.htmf which is automatically included into this Modules appendix. (htmf stands for HyperText Markup Fragment and indicates that this file should include valid, well formed HTML and text, but is not a complete HTML document. Its contents are to be inserted into a complete HTML document.)

Simplest Example Module docs.htmf Document:

<h3>Module Name</h3>
<p>Docs go here.</p>

Site Specific Code

If you have site-specific PHP code you would like to include on all of your pages, creating a module for that site is the safest and most convenient way to accomplish that.

Installed Modules Documentation

The following documentation is generated automatically from information provided by the modules' authors.

Calendar Module

The calendar module allows you to add an events calendar to your web site. You can grant users access to create and edit events via the Molly permissions system and the permitted attribute of the tag.

Calendar Tag Attributes

Calendar Configuration

Configure via calendar.ini within the calendar module directory. The sections of the .ini file are as follows:

[Defaults] Default values for size and styling of the calendar
[Days] allows language localization
[Months] allows language localization
[Categories] allows you to create categories for events - for each category you set the background and text colors in the next two sections
[TextColor] color of text for the corresponding category
[BackgroundColor] background color for the corresponding category
[MediaType] populates the media type pop-up in the event creation/edit dialog so that you can assign an icon to the optional link for the event
[Icon] the icon image associated with the corresponding MediaType(s)

Calendar Templates

Calendars are generated from template (.tplt) files inside the templates directory within the calendar module directory. (Note: Older versions of Molly and the Calendar module located the templates in the skin directory. These are no longer used and may be safely deleted.

Calendar Examples

Display a Single Month, full size, that users in group "editor" are allowed to add/edit/delete events:

<maml:calendar permitted="editor" />
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
 
 

Display a single month, January of 2020, and do not allow users to navigate:

<maml:calendar permitted="editor" year="2020" month="1" mode="static" />
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
 

Display the first 3 months of 1999 in small size:

<maml:calendar permitted="editor" size="small" year="1999" month="1" mode="static" style="float:left;" />
<maml:calendar permitted="editor" size="small" year="1999" month="2" mode="static" style="float:left;" />
<maml:calendar permitted="editor" size="small" year="1999" month="3" mode="static" style="float:left;" />
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
 
 
 
 
 
 
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 
 
 
 
 
 
 
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
 
 
 

Calendar module originally created by R. P. Vullo
Updated and enhanced by Catherine Walters, July 2017

Developer Module

This module is meant to be deployed temporarily while developing Molly or building a Molly site. It implements tags that allow quick checks of the sort that would normally require embedding a bit of PHP or JavaScript code in a page.

Current Developer Tags:

Developer module originally created by R. P. Vullo, July 2017

Schedule Module

The Schedule allows Molly site developers to schedule things to happen. There are two sorts of scheduling that the module plans to support: Content/Links and Events. Content viewability/linkability is scheduled via the <maml:term />, <maml:a>, and <maml:schedule> tags. Events are scheduled via the schedule.ini file. Content/Links are functional while Events are still being developed.

Content & Links

<maml:term />

Attribute Value Description
startdate date Date the term begins
enddate date Date the term ends (optional)
dateformatstringSet up for a global date format, look at the other tags on what is available

Sets the global variable $gv_TermStartDate to the date in the startdate attribute. Optionally sets the global variable $gv_TermEndDate to the enddate attribute's value. These dates are used by the <maml:a> and <maml:schedule> tag for calculating week and day values. Dateformat is so the dates entered here are understood by PHP.

<maml:a>Link Text</maml:a>

The <maml:a> tag allows the user to specify a date range, which may be open-ended either as to beginning or end, that a link will be available. If the showtext attribute is set to "true" or "yes" value, then the contents of the tag will be displayed outside the date range. If "false" or "no" then nothing will be displayed outside the date range. Within the date range the link becomes active.

Attribute Value Description
dateformat american|european|chinese|unix
american (default) = month/date/year
european = date/month/year
chinese = year/month/date
unix = Unix time stamp
Which format is used to specify dates for the tag's startdate and enddate attributes. Any of the standard separators ("/" – stroke (slash), "." – dots or full stops (periods), "-" – hyphens or dashes, " " – spaces) are allowed. Case insensitive
startdate date (in format specified by dateformat attribute if not American) The (optional) beginning of the range the link will be available/functional. If not specified, then always available until enddate (or endday/endweek).
enddate date (in format specified by dateformat attribute if not American) The (optional) end of the range the link will be available/functional. If not specified, then link remains available in perpetuity once it becomes available/functional as specified by startdate (or startday and startweek).
startweek integer The week of the term (as specified by the <maml:term /> tag) that the link becomes available. (optional) If no startday is specified, then begin at midnight on the morning of the first business day (Monday) of the week.
endweek integer The week of the term (as specified by the <maml:term /> tag) that the link becomes unavailable. (optional) If no endday is specified, then end at midnight on day before first business day of the next week (Sunday).
startday integer If no startweek is specified, then the day of the term (as specified by the <maml:term /> tag) the link will be available/functional. Otherwise the day of the week specified by startweek. Week begins at midnight on the morning of Monday (first business day of the week). (optional)
endday integer If no endweek is specified, then the day of the term (as specified by the <maml:term /> tag) the link will no longer be available/functional. Otherwise the day of the week specified by endweek. Week ends at midnight on day before first business day of the next week (Sunday). (optional)
showtext true|false|yes|no (case insensitive, default="yes") Whether or not to display the link text when outside the date range.
href URL
Pass through to template.
Specifies the URL of the page the link goes to.
rel Pass through to template, if defined. Specifies the relationship between the current document and the linked document.
target Pass through to template, if defined. Specifies where to open the linked document.

<maml:schedule>Shown/Hidden Content</maml:schedule>

The <maml:schedule> tag allows the user to specify a date range, which may be open-ended either as to beginning or end, that a block of content will be viewable.

Attribute Value Description
dateformat american|european|chinese|unix
american (default) = month/date/year
european = date/month/year
chinese = year/month/date
unix = Unix time stamp
Which format is used to specify dates for the tag's startdate and enddate attributes. Any of the standard separators ("/" – stroke (slash), "." – dots or full stops (periods), "-" – hyphens or dashes, " " – spaces) are allowed. Case insensitive
startdate date (in format specified by dateformat attribute if not American) The (optional) beginning of the range the link will be available/functional. If not specified, then always available until enddate (or endday/endweek).
enddate date (in format specified by dateformat attribute if not American) The (optional) end of the range the link will be available/functional. If not specified, then link remains available in perpetuity once it becomes available/functional as specified by startdate (or startday and startweek).
startweek integer The week of the term (as specified by the <maml:term /> tag) that the link becomes available. (optional) If no startday is specified, then begin at midnight on the morning of the first business day (Monday) of the week.
endweek integer The week of the term (as specified by the <maml:term /> tag) that the link becomes unavailable. (optional) If no endday is specified, then end at midnight on day before first business day of the next week (Sunday).
startday integer If no startweek is specified, then the day of the term (as specified by the <maml:term /> tag) the link will be available/functional. Otherwise the day of the week specified by startweek. Week begins at midnight on the morning of Monday (first business day of the week). (optional)
endday integer If no endweek is specified, then the day of the term (as specified by the <maml:term /> tag) the link will no longer be available/functional. Otherwise the day of the week specified by endweek. Week ends at midnight on day before first business day of the next week (Sunday). (optional)
permitted Molly Permissions Group Specifies who, based on Molly Permissions, can see the content when made available based on date.STILL BEING DEVELOPED

Events

CURRENTLY BEING DEVELOPED Using the Schedule module's schedule.ini file you can schedule repeated actions. These actions can be either a PHP script or an SQL query. These actions are useful for automatic backups or log management or other such utility actions you want performed at regular intervals. Every time a MAML page loads, the schedule module checks the ini for actions, then compares them to the molly_schedule database table to see if the interval has elapsed and it's time to execute the action.

Example schedule.ini

; The values from this file are used to schedule recurring actions via the Molly Schedule Module

[Test Schedule Item]         ; Must be a unique string, as it is the database key for the action.
                             ; Should also be descriptive of the action,
                             ; i.e. [Backup molly_userid and molly_username Tables]
Interval = 'weekly'          ; hourly | daily | weekly | monthly | annually
;DebugInterval = '30'        ; interval in seconds - use with great caution and only for testing
Type = 'SQL'                 ; PHP | SQL
Source = 'string'            ; string | file
                             ; if Source is file, then Action contains full path to the 
                             ; file - may use tokens
Action = "INSERT INTO  `molly_test` (`test_id` ,`name` ,`eyecolor` ,`age` ,`file_token`) VALUES (NULL ,  'Ferdinand',  'Brown',  '34',  '');"

[Another Test Schedule Item] ; Must be a unique string, as it is the database key for the action.
                             ; Should also be descriptive of the action,
                             ; i.e. [Backup molly_userid and molly_username Tables]
Interval = 'weekly'          ; hourly | daily | weekly | monthly | annually
;DebugInterval = '30'        ; interval in seconds - use with great caution and only for testing
Type = 'PHP'                 ; string | file
                             ; if Source is file, then Action contains full path to the 
                             ; file - may use tokens
Action = "/var/www/html/test.php"

Schedule Module originally created by Cullen Gray, July 2017 based on Specifications by R.P. Vullo

Quiz Module

Quiz Tag

An empty quiz tag <maml:quiz />, will produce a quiz module. This includes a quizbook which is a list of all of the quizzes in the database, the score if the quiz has been taken and the link to take it. When the user clicks on a link to take the quiz it will bring them to the correct quiz and allow them to take it. Once they have submitted the quiz, they will be redirected to a score page which shows them which questions they got correct and what their score is. If the user has never taken the quiz or gets a higher score than the score currently saved for them in the database, then their score will be saved. If they do not beat the highest score, their score will not be saved.

A tag with a specified style will determine the style that the answers will be displayed in. Currently this supports radio buttons and select menus

A tag with a specified retake will determine if retake is specified false, the user can only take the quiz once. If it is specified true, the user can take the quiz as many times as they want.

Quiz Admin

The quiz module admin section can only be accessed if the user has teacher permissions. Each user can only access the quizzes that they created or were granted access to by the creator.

To create your first quiz you would go to the manage quizzes section and click on create new. You will enter the new quiz information including the Quiz Name and the Groups Permitted and then click Add Quiz.

This will bring you to the quiz summary page which allows you to edit the quiz name and permitted group. It also shows the number of questions, the number of people in the permitted group, the number who have taken the quiz, and who created the quiz.

The next section is the quiz questions section. This section is where you add the questions for the quiz that you are making. To add answers the the questions click the edit button next to the question and it will bring you to a page where you can edit the question and add answers.

The Quiz statistics section shows a list of the users that should take the quiz/are in the group and their score if they have one. It also shows the average for the quizzes taken.

The quiz user section allows you to add editors to this quiz. This allows you to grant access to any other user who also has teacher permissions. Note if you grant permissions they will also be able to edit and delete from the quiz so do this with caution.

Quiz Module originally created by Catherine Walters, July 2017

MollyPoint

Mollypoint is an online lecture system. Documentation coming soon...

MollyPoint Configuration

Configure via mollypoint.ini within the MollyPoint module directory. The sections of the .ini file are as follows:

[DatabaseNames]

UserDBThis database stores which user id is the creator of each lecture by id. It is currently set as lecture_user_xref
CaptionDBThis database stores the captions including the caption number, caption content, which lecture it belongs to, and the caption time in seconds. It is currently set as vullo_captions
LectureDB This database stores the lectures including the lecture id, lecture name, course number associated with the lecture, if it is online or not, the poster, and if comments are enabled on the lecture. It is currently set as vullo_lectures
VideoDB This database stores the video information for the lectures. It includes the video id, which lecture id is associated with the video, the video file name, the video type, and the video length. It is currently set as vullo_lecture_videos
SlideDB This database stores the slide information for the lectures. It includes the slide id, the lecture id associated with the slide, the slide number for the order of the slides, the slide title, the content of the slide, the lecture notes, the student notes, and the slide seconds. It is currently set as vullo_slides
CommentsDB This database stores the comments information for the lectures. It includes the comments id, the slide id associated with the comment, the user id of the person who wrote the comment, the comment content, and the timestamp of when the comment was created. It is currently set as Slide_comments

WalkThrough to Create a Lecture

  1. The first screen starts on the lecture managment page. This page has two tabs "All Lectures" and "My Lectures". All lectures shows all of the lectures that are online that the user is allowed to view. My lectures shows only the lecures that the user is permitted to edit.
  2. To create a new lecture, click on the "My Lectures" tab.
  3. Click on Create New to create a new lecture.
  4. This will bring up a window where you can fill in the fields for Lecture Name and Course Number. To create the new lecture hit the create button once the fields are filled in. To cancel the creation, hit the cancel button
  5. If the lecture was successfully created it will redirect you to the lecture edit page.
  6. Initially it will land on the "Content" tab. This tab is used primarily for slide creation and management.
  7. If there are no slides the page will display a "No slides available for the lecture!" message.
  8. Just below this message is an area where you can edit the lecture name or the course number. To edit either one click on the pencil symbol and then enter the revised content. Once you have completed your edits, click on the save symbol or if you do not want to save the changes click on the cancel symbol .
  9. When you want to add a slide to your lecture, click on Add Slide. This creates a new blank slide.
  10. The initial title is set as "Change Title...". In order to change it click the pencil next to the title. This provides a text box to edit the text. Once you have completed your edits, click on the save symbol or if you do not want to save the changes click on the cancel symbol .
  11. The box just below the title is for the slide body content. On the bottom right of this box is the slide number. In order to change the content, click the pencil on the top right of the box. This provides a text box to edit the text. Once you have completed your edits, click on the save symbol or if you do not want to save the changes click on the cancel symbol .
  12. The lecture notes box is for the instructor to provide notes about the slide. In order to change the content, click the pencil on the top right of the box. This provides a text box to edit the text. Once you have completed your edits, click on the save symbol or if you do not want to save the changes click on the cancel symbol .
  13. The student notes box is to provide notes for students about the slides. In order to change the content, click the pencil on the top right of the box. This provides a text box to edit the text. Once you have completed your edits, click on the save symbol or if you do not want to save the changes click on the cancel symbol .
  14. If you need to delete a slide, click on the slide on the list of slides on the left then click Delete Slide.
  15. After you hit delete a window will appear that asks you to confirm that you really want to delete the selected slide. Click Yes to delete the slide or Cancel if you decide you do not want to delete the slide.
  16. If you want to enable comments on the lecture click the checkbox next to "Enable comments for this lecture:". This will allow people who view the lecture to leave comments on slides.
  17. If you want to change the order of the slides once you have created them, you can do so on this page. On the left is a list of slide previews with the title and the slide number. In order ot change the order of the slides click and hold on the slide that you want to move. Drag the slide image to the position that you would like to move the slide to and let go of the mouse. This automatically updates the order and slide numbers of all of the slides.
  18. Once you have completed the slides, you can move on to the "Caption" tab. This page is used for caption creation and management for the video that you will use for your lecture.
  19. Again there is an area where you can edit the lecture name or the course number. To edit either one click on the pencil symbol and then enter the revised content. Once you have completed your edits, click on the save symbol or if you do not want to save the changes click on the cancel symbol .
  20. To add a caption, click on Add Caption
  21. This will create a new blank caption. To add content to the caption, click on the pencil symbol .
  22. This will bring up a text box where you can type in your content or change content if you are editing a caption. Once you have completed your edits, click on the save symbol or if you do not want to save the changes click on the cancel symbol . On the bottom right corner of this box is the caption number.
  23. If you need to delete a caption, click on the caption on the list of captionss on the left then click Delete Caption.
  24. After you hit delete a window will appear that asks you to confirm that you really want to delete the selected caption. Click Yes to delete the caption or Cancel if you decide you do not want to delete the caption.
  25. There is another option to upload captions called bulk add. This allows the user to past or type all of the captions at once and the system creates the individual captions for them. You can do this by clicking on Upload caption(s).This brings up a text box with a select menu below it which allows the user to choose the method they would like to use to input their captions.
  26. The default method is CRLF which allows the user to paste or type in the captions separated by a carraige return(new line)
  27. The Custom Caption length option divides input by a user determined number of characters. For example if you put the number 3 in the text box, every 3 characters in the string will become its own caption. This custom length needs to be specified in the small text box that appears next to the select menu when this option is chosen.
  28. The Custom Delimiter option separates the input into different captions using the symbol or delimeter specified by the user. This custom delimeter needs to be specified in the small text box that appears next to the select menu when this option is chosen.
  29. Once the content is complete and the appropriate option is chosen, click the Upload button to create the captions or the Cancel button to cancel the creation and return to the caption list.
  30. When the Upload button is pressed, if there are already captions created for the lecture, a window appears asking if you would like to overwrite the existing captions or append the captions to the existing captions. If you would like to overwrite click Overwrite and if you would like to append the captions click Append.
  31. If you want to change the order of the captions once you have created them, you can do so on this page. On the left is a list of caption previews with the content and the slide number. In order ot change the order of the caption click and hold on the caption that you want to move. Drag the caption image to the position that you would like to move the caption to and let go of the mouse. This automatically updates the order and caption numbers of all of the captions.
  32. Once you have completed the captions, you can move on to the "Timeline" tab. This page is used for slide and caption timing with during the video.
  33. If no video exists yet for the lecture, there will be a box that provides you with a place to upload a video. You can either click on the Choose File button and browse your local files to find the video you would like to use or you can drag the file into the box and drop it in to upload it.
  34. If the upload is successful or there is already a video for the lecture, the video will appear on this page. Below the video there will be two tabs "Slide Timeline" and "Caption Timeline". Slide Timeline allows you to drag each slide to the point in the video that you would like the slide to become the active slide. Caption Timeline allows you to drag each caption to the point in the video where the caption lines up with the words.
  35. Once you have completed the timeline, you can go to the "Users" tab. This allows the users to add more users to have shared permissions for the lecture.
  36. To add a new user to the lecture click on the Add New User button.
  37. This will bring up a window that shows a preview of the users that you can add to the lecture. To see all of the users, check the box that says "Show All Users". Once you find the user you would like to add click the button Add next to their name. An alert will appear if the user was successfully added to the lecture. If you decide you do not want to add anyone to the lecture, you can hit the cancel button and it will close the window.
  38. On the Users page you can also delete a user from the lecture. To delete a user click the next to the user's name. A window will appear that will ask you to confirm if you would like to delete the user. If you would like to delete the user click Yes and if you decided you do not want to delete the user, click No.
  39. Once you have added the users to the lecture, you can move to the "Resources" tab. This page allows you to add and delete video files or posters for the lecture.
  40. To add a video to the lecture click Upload new video file. This will bring up a window that allows you to choose the file from your local files by clicking the "Choose File" button or by dragging the file and dropping it into the provided area. If you decide you do not want to add the video, you can hit the "Cancel" button.
  41. To delete a video from the lecture click the Delete button in the actions column of the Video section in the corresponding row.
  42. To add a poster to the lecture click Add Poster. This will bring up a window that allows you to choose the file from your local files by clicking the "Choose File" button or by dragging the file and dropping it into the provided area. If you decide you do not want to add the poster, you can hit the "Cancel" button.
  43. To delete the poster from the lecture click the Delete Poster button below the poster preview in the Poster section.
  44. Once the edits are done to the lecture, go to the "My lectures" tab. This will bring you back to the page that shows all of the lectures that you are permitted to edit. The lecture you just created should appear in the list of lectures.
  45. To go back to editing the lecture, click the Edit button.
  46. To create a copy of the lecture click Copy. This will bring up a window to enter the new lecture name and new course number. Once this information is entered, to copy the lecture click Copy or click Cancel. If you choose to copy the lecure, all of the videos, slides, captions, and posters will copy over to the new lecture.
  47. To delete the lecture click Delete. This will bring up a windown that asks if you are sure you want to delete the lecture. Click Yes to delete the lecture or click No to return to the lectures list.
  48. By default the lecture will be set to offline and will appear as Offline. If you would like to set the lecture as online so that it can be viewed by other users and so that it appears in the list in the "All lectures" tab, click the Offline Button. Once this button is clicked, it will change to Online.
  49. If you chose to add a video to your lecture, this symbol will show up next to the lecture name. If you would like to view the lecture with the video, click this symbol and it will bring up the lecture and load the video.
  50. If you did not choose to add a video or you do not wish to view the lecture with the video, click the button next to the lecture name. This will bring up the lecture without a video.
  51. When you open a lecture, the video will appear on the left, if there is a video. Above that is a hide video arrow button which will hide the video. The video player has controls. To view the video full screen, click the fullscreen button.
  52. The captions by default are turned off on the video. To turn on the captions, click the cc button. This will turn on the captions which will appear at the times specified on the timeline page. To turn the captions off click the cc button.
  53. As the video plays, the active slides will change as the video plays. This is based on what was set up on the timeline page. If you would like to advance to a certain slide you can click on the slide in the slide list below the video and the video will advance to the point where the slide is supposed to appear.
  54. If you have comments enabled on the lecture, a Comments button will appear under the active slide.
  55. If you click on the comments button, a section will appear listing all of the existing comments on that slide. It iwll have the comment, the User who created the comment, and the timestamp for when the comment was created.
  56. If you click the Add your comments button, a window will apear with a text box. This text box is where the content for the comment goes should be inserted. To submit the comment click Submit. If you decide you do not want to submit the comment click Cancel

MollyPoint module originally created by R. P. Vullo
Updated and enhanced by Natalia Ivaniuk, 2013
Updated and enhanced by Gaurav Kumar, 2015
Updated and enhanced by Catherine Walters, July 2017


Appendix IV: Programmers' Documentation

This appendix is available for PHP programmers interested in understanding how Molly works "under the hood" but is primarily here for the active developers of the core Molly code. Please note that there is no need to understand or program PHP to use Molly. If you do not wish to extend or improve Molly, or write modules for Molly using PHP, then you can safely ignore this appendix.

Molly is open source, so if you make improvements or extensions to Molly please share them with us so that we can roll them into the next release.

File Types & Molly

Molly's Default behavior is to consider the extension of the files and processes them as follows:

Extension Action
.php Process as normal php, no Molly functionality
.inc PHP include files
.html Process similarly to Molly 1, that is, set all the globals and include basic function and object libraries and module libraries, then procede to pass the file through the php parser. (Note that for normal HTML files this does essentially nothing, but that it allows you to minimally incorporate some of Molly's functionality if you understand the underlying architecture.)
.maml Set all the globals and include all the libraries and modules, then parse the file through Molly's MAML XML parser.
.tplt template files
.ini prevent being served to the web
.txt (Maybe turn into a nice formatted web page?)
.css Treated like a template file - that is, all *[tokens]* are replaced with config values

Molly Naming Conventions

When developing code (including modules) please adhere to the following naming conventions:

Prefix Example Meaning
$gv_ $gv_VarName Global Variable (will be found in $GLOBALS)
$fv_ $fv_VarName Variable with scope local to a function
$go_ $go_ObjectName Global Object
$fo_ $fo_ObjectName Object with scope local to a function
$pv_ $pv_ParemeterName Parameter passed to a function (function scope)
$po_ $po_ParameterObject Object passed to a function (function scope) or class
$t_ $GET['t_Name'] Tokens passed via the query string
maml_ maml_TagName Class name for MAML Tag
molly_ molly_ClassName Class name for non-tag objects used in Molly
molly_ molly_TableName Database Table specific to Molly
m_ m_FunctionName Function that is part of Molly
MOLLY_ MOLLY_CONST_NAME Molly Constants

Inline Documentation

When defining a maml_ class to create a new tag programmers must take care to set the $doctext to explain the use of the tag. This will allow Molly to generate user documentation which is accurate and current with the code and better able to withstand versioning. We will use PHP's Nowdoc syntax (http://www.php.net/manual/en/language.types.string.php#language.types.string.syntax.nowdoc) to accomplish this.

Molly System Constants

Constant Value
MOLLY_SYSTEM_DIRECTORY Unix Path to Molly's system directory (core functionality)
MOLLY_INI File Name of This Site's .ini file (allows multiple sites to share the same codebase by having different .ini files)

Molly's Internal Functions

m_AppendJavaScript($pv_Scripts, $pv_ScriptName, $pv_AllowDuplicates) [system/core/40_tags.inc]
Adds $pv_Scripts to the JavaScript section in the head of the page. $pv_ScriptName is tracked to know which scripts have already been added. $pv_AllowDuplicates is FALSE by default.
m_AppendQueryString($pv_Key, $pv_Value) [system/core/40_tags.inc]
Allows Molly to dynamically create the querystring for links such as <maml:sort>
m_AppendStylesheet($pv_Styles, $pv_StyleName, $pv_AllowDuplicates) [system/core/40_tags.inc]
Adds $pv_Styles to the stylesheet in the head of the page $pv_StyleName is tracked to know which styles have already been added. $pv_AllowDuplicates is TRUE by default.
m_ArrayLastKey($pv_TheArray) [system/core/80_environment.inc]
Returns the last key of an array
m_AutoInclude($pv_PathToIncludesDirectory, $pv_FileExtension) [system/loader.php]
Includes all the files in a directory with the specified extension
m_captchabasepath() [system/core/captcha/captcha-settings.php]
Returns the path to the captcha library directory.
m_captchacode() [system/core/captcha/captcha.inc]
Generates the random captcha code.
function m_captchadone() [system/core/captcha/captcha.inc]
Unsets the session variable that holds the current captcha code being tested against.
m_captchaimgurl() [system/core/captcha/captcha.inc]
Returns the global $captchaimg.
m_captchasendimg() [system/core/captcha/captcha.inc]
Generates an image of the current captcha code (generating a new code if one does not exist in the $_SESSION array). Randomly tilts, sizes, etc. the characters and generates noise to foil OCR systems.
m_captchasendwav() [system/core/captcha/captcha.inc]
Generates an spoken reading of the current captcha code (generating a new code if one does not exist in the $_SESSION array) formatted as a wav audio file.
m_captchawavurl() [system/core/captcha/captcha.inc]
Returns the global $captchawav.
m_CheckLogin($pv_LoginName, $pv_Password) [system/core/27_security.inc]
returns user_id for successful login, FALSE for failed login.
m_clean_params_for_query($pv_QueryComponent) [system/core/27_security.inc]
Used to clean user-provided data before building a query with it. Strips off semicolon and anything following it, then escapes other characters that are problematic in a database query.
m_DateGMT($p_UnixTimeStamp) [system/core/10_date_time.inc]
Converts a Unix timestamp to a formatted date, adjusted by user's timezone
m_debug($pv_TheDebugString) [system/core/05_utility.inc]
Caches debug string for output after parsing completes. Saves debug string(s) in a session variable until they can be displayed on the next MAML page since HTML pages are often used for invisible (to the user) forms processing. (see system/parser.php)
m_DirectoryList($pv_Directory, $pv_DateFormat="d F Y H:i:s") [system/core/15_file.inc]
Creates an array of hashes for each file in a specified directory. The hashes contain 'name', 'root', 'size', 'perm', 'type', 'time', 'extension' elements.
m_DoInsert($pv_Query, $pv_HostName='', $pv_User='', $pv_Password='', $pv_Database='', $pv_DatabaseApp='') [system/core/20_database.inc]
Does an insert query and returns an Insert ID.
m_DoLogin($pv_UserID) [system/core/27_security.inc]
Creates session variables to make a user logged in
m_DoQuery($pv_Query, $pv_HostName='', $pv_User='', $pv_Password='', $pv_Database='', $pv_DatabaseApp='') [system/core/20_database.inc]
Does a query and returns record set of the results.
m_EchoModulesDocs() [system/core/70_modules.inc]
Checks for the existence of docs.htmf file in each module directory (as specified in the molly.ini [Modules] section) and echos it (or a file not found message). This function is used in the docs page.
m_FetchDBHash($pv_Query, $pv_HostName='', $pv_User='', $pv_Password='', $pv_Database='', $pv_DatabaseApp='') [system/core/20_database.inc]
Does a query and returns an array of associative arrays (array of hashes)
m_FetchRecordsArray($p_TableName, $p_Fields, $p_Query, $p_OrderBy="", $p_Limit="") [system/core/20_database.inc]
Wrapper function for m_FetchDBHash that builds the SQL from appropriate pieces.
m_GetDocument ($pv_URL) [system/core/15_file.inc]
Returns the text of a file specified by $pv_URL
m_HashArrayToXML() [system/core/30_XML.inc] /* Not Currently Used */
m_ImplementedTags() [system/core/80_environment.inc]
returns an array of class names for implemented tags.
m_Interpolate($template, $hash, $prefix = '*[', $postfix = ']*') [system/loader.php]
Replaces placeholders in a template string with values from a hash
m_IsMollyTag($pv_TheTagName) [system/core/80_environment.inc]
Checks a string to see if it's a defined Molly tag classname
m_LoadModules() [system/core/70_modules.inc]
Loads modules specified in the molly.ini file for the site in the [Modules] section.
m_MakeUnixTimestampGMT($hh=0, $mm=0, $ss=0, $m, $d, $y) [system/core/10_date_time.inc]
Creates a unix timestamp from hour, minute, second, year, month, day
m_NakedHTML ($pv_URL) [system/core/15_file.inc]
Returns the text from between the <body></body> tags of an HTML document specified in $pv_URL
m_ParentDir($pv_Path) [system/loader.php]
Returns the parent directory pasth of the unix file path passed to it.
m_Permissions($pv_FilePathName) [system/core/15_file.inc]
Returns the the unix style permissions (as in ls -l) for the fully qualified file name passed as $pv_FilePathName.
m_permitted($pv_Group) [system/core/27_security.inc]
Checks to see if the currently logged in user is a member of the permissions group. Returns boolean.
m_PullParse() [system/core/90_parser.inc]
This is the actual XML parsing function that does Molly's magic. Starting with this version of Molly the parsing is done using the XMLReader extension (http://us.php.net/manual/en/intro.xmlreader.php). Previous versions used the expat XML Parser (http://us.php.net/manual/en/intro.xml.php).
m_session_close() [system/core/25_sessions.inc]
Callback function for session_set_save_handler() allowing Molly to store sessions and associated information in a database table. Among other things this allows us to easily determine who's logged in, and to share sessions across multiple web servers.
m_session_destroy($pv_Key) [system/core/25_sessions.inc]
Callback function for session_set_save_handler() allowing Molly to store sessions and associated information in a database table. Among other things this allows us to easily determine who's logged in, and to share sessions across multiple web servers.function m_session_destroy deletes the associated record in the session table, thus ending the session.
m_session_gc($maxlifetime) [system/core/25_sessions.inc]
Callback function for session_set_save_handler() allowing Molly to store sessions and associated information in a database table. Among other things this allows us to easily determine who's logged in, and to share sessions across multiple web servers. This is the function which collects garbage by deleting expired sessions from the sessions database. The probability that PHP will run this function is set in the php.ini directive "session.gc_probability."
m_session_open($pv_SavePath, $pv_SessionName) [system/core/25_sessions.inc]
Callback function for session_set_save_handler() allowing Molly to store sessions and associated information in a database table. Among other things this allows us to easily determine who's logged in, and to share sessions across multiple web servers. This function collects garbage by deleting expired sessions from the sessions database whenever a new session is opened.
m_session_read($pv_Key) [system/core/25_sessions.inc]
Callback function for session_set_save_handler() allowing Molly to store sessions and associated information in a database table. Among other things this allows us to easily determine who's logged in, and to share sessions across multiple web servers. This function reads the user's session data from the sessions database updates their session record to reset their session expiration time.
m_sess_write() [system/core/25_sessions.inc]
Callback function for session_set_save_handler() allowing Molly to store sessions and associated information in a database table. Among other things this allows us to easily determine who's logged in, and to share sessions across multiple web servers. This function stores the session data for a particular user. If the user already exists in the table, it updates the user's session value and expiry time. PHP serializes the session data and sends it in as a string.
m_SessionQuery($pv_Query) [system/core/25_sessions.inc]
Sends a query to the session database as configured in the molly.ini file - such that multiple servers can share the same session.
m_ShowINI($pv_VariableName) [system/core/80_environment.inc]
debugging tool for outputting two dimensional arrays as are read from INI files
m_StringToStyleClassName($pv_TheString) [modules/calendar/calendar.inc]
Converts a string to a valid CSS class name. (Part of Calendar module.)
m_testDOMi() [system/core/30_XML.inc] /* Not Currently Used */
m_TimeGMT($p_UnixTimeStamp) [system/core/10_date_time.inc]
Converts a Unix timestamp to a formatted time, adjusted by user's timezone
m_ValidateAgainstDB($pv_LoginName, $pv_Password) [system/core/27_security.inc]
Returns a user_id for successful login, FALSE for failed login using login database and hash algorithm specified in the molly.ini file.
m_ValidateAgainstLDAP($pv_LoginName, $pv_Password) [system/core/27_security.inc]
Returns a user_id for successful login, FALSE for failed login using the LDAP/Active Directory server specified in the molly.ini file. If the suser does not exist in the Molly login/username tables a record is created for the newly ldap-validated user.

The following list of Molly's internal functions is generated automatically for this particular installation.

Output Buffering & Molly

Output Control

The output buffering functions allow you to control when output is actually sent from the web server to the browser. By default, output is sent as soon as it's generated.

Output buffering can be useful in several different situations, especially if you need to send headers to the browser after your script has begun outputting data. The Output Control functions do not affect headers sent using header() or setcookie(), only functions such as print(), echo, var_dump() and plain HTML between blocks of PHP code are buffered.

Start Buffering

Use the ob_start(); function to turn output buffering on. From this point, no output will be sent to the browser until you turn off buffering.

End Buffering

To end buffering and send all the accumulated text on its way to the browser, call the ob_end_flush(); function.

Simple Example

<?php
ob_start();
echo "Hello\n";
 
setcookie("cookiename", "cookiedata");
 
ob_end_flush();
 
?>

This simple example allows you to send headers - with setcookie() - "after" you've had output from the echo.

Output Buffering in Molly

"OK, but why does this matter to me?"

When you're programming in Molly, you need to know that before any output is sent, output buffering is turned on. And the last thing Molly does after parsing a page is turn output buffering off and send the whole page.

So...

Let's...

...build a tag that uses output buffering: the <maml:smiley> tag.

The smiley tag will find any smileys like :) ;) and :( in its enclosed text and convert them into graphical smileys like :) ;) and :(

To save you some work, I've written a function that does the actual conversion for you, so all we have to worry about is the output buffering. The function is defined thusly:

<?php
    function smileys2Graphics($p_TheText) {
 
        global $g_HTMLRoot;
        $p_TheText =  str_replace (':)','<img src="' . $g_HTMLRoot . 'decor/icons/smile.gif" alt=":)">',$p_TheText);    
        $p_TheText =  str_replace (':-)','<img src="' . $g_HTMLRoot . 'decor/icons/smile.gif" alt=":-)">',$p_TheText);    
        $p_TheText =  str_replace (':(','<img src="' . $g_HTMLRoot . 'decor/icons/pout.gif" alt=":(">',$p_TheText);    
        $p_TheText =  str_replace (':-(','<img src="' . $g_HTMLRoot . 'decor/icons/pout.gif" alt=":-(">',$p_TheText);    
        $p_TheText =  str_replace (':P','<img src="' . $g_HTMLRoot . 'decor/icons/yuck.gif" alt=":P">',$p_TheText);    
        $p_TheText =  str_replace (':p','<img src="' . $g_HTMLRoot . 'decor/icons/yuck.gif" alt=":p">',$p_TheText);    
        $p_TheText =  str_replace (':b','<img src="' . $g_HTMLRoot . 'decor/icons/yuck.gif" alt=":b">',$p_TheText);    
        $p_TheText =  str_replace (':-P','<img src="' . $g_HTMLRoot . 'decor/icons/yuck.gif" alt=":-P">',$p_TheText);    
        $p_TheText =  str_replace (':-p','<img src="' . $g_HTMLRoot . 'decor/icons/yuck.gif" alt=":-p">',$p_TheText);    
        $p_TheText =  str_replace (':-b','<img src="' . $g_HTMLRoot . 'decor/icons/yuck.gif" alt=":-b">',$p_TheText);    
        $p_TheText =  str_replace (';)','<img src="' . $g_HTMLRoot . 'decor/icons/wink.gif" alt=";)">',$p_TheText);    
        $p_TheText =  str_replace (';-)','<img src="' . $g_HTMLRoot . 'decor/icons/wink.gif" alt=";-)">',$p_TheText);    
        $p_TheText =  str_replace ('[])','<img src="' . $g_HTMLRoot . 'decor/icons/coffee.gif" alt="[])">',$p_TheText);    
        $p_TheText =  str_replace (':.','<img src="' . $g_HTMLRoot . 'decor/icons/oh.gif" alt=":.">',$p_TheText);    
        $p_TheText =  str_replace (':-.','<img src="' . $g_HTMLRoot . 'decor/icons/oh.gif" alt=":-.">',$p_TheText);    
        return $p_TheText;
    } //smileys2Graphics
?>

Skeleton Tag

Here is the skeleton of our tag code. (All MAML tags start this way.)

class maml_smiley extends prototype_tag {
    protected $doctext = <<<'DOCBLOCK'
Convert typed smileys to graphics
DOCBLOCK;
 
    public function begin(){ //called at the <maml:smiley> tag
 
    }
 
    public function end(){ //called at the </maml:smiley> tag
 
    }
}
 

The Plan

We only want to convert smileys between our tags, so what we want to do is save the text that's been buffered so far and flush the buffer when our begin tag is encountered. When we get to the end tag, the only thing in the buffer is what's between our tags. At that point we can save that, flush the buffer again, and return the saved text to the buffer. Finally we can process the text between our tags and add it to the restored buffer.

Save and Flush

class maml_smiley extends prototype_tag {
    protected $doctext = <<<'DOCBLOCK'
Convert typed smileys to graphics
DOCBLOCK;
    protected $OutputCache='';
 
    public function begin(){ //called at the <maml:smiley> tag
        $this->OutputCache = ob_get_contents(); 
        // Fetch and save all the output cached thus far and... 
        ob_clean(); // ...clean the output buffer
    }
 
    public function end(){ //called at the </maml:smiley> tag
 
    }
}
 

Process and Restore

class maml_smiley extends prototype_tag {
    protected $doctext = <<<'DOCBLOCK'
Convert typed smileys to graphics
DOCBLOCK;
    protected $OutputCache='';
 
    public function begin(){ //called at the <maml:smiley> tag
        $this->OutputCache = ob_get_contents(); 
        // Fetch and save all the output cached thus far and... 
        ob_clean(); // ...clean the output buffer
    }
 
    public function end(){ //called at the </maml:smiley> tag
    // Fetch all the data between the <maml:smiley> and
    //</maml:smiley> tags after it's been parsed
        $v_SmileyText = ob_get_contents(); 
 
         // clean the output buffer                                    
        ob_clean();
        // return the previously saved cached output to the output buffer
        echo $this->OutputCache; 
        //Process our text
        $v_GraphicText=smileys2Graphics($v_SmileyText);
        // add the converted text to the page buffer
        echo $v_GraphicText;
    }
}
 

Molly is Smart

Because we do this all the time in Molly, the prototype_tag class which we extended to create our tag has output buffering methods and variables built in to simplify this process:

class maml_smiley extends prototype_tag {
    protected $doctext = <<<'DOCBLOCK'
Convert typed smileys to graphics
DOCBLOCK;
 
    public function begin(){ //called at the <maml:smiley> tag
        $this->startCache();
    }
 
    public function end(){ //called at the </maml:smiley> tag
        $this->finishCache();    
        $v_GraphicText=smileys2Graphics($this->tagCache);
        // add the converted text to the page buffer
        echo $v_GraphicText;
    }
}