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.
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.
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:
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 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.
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.
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.
Makes building sites rapid and easy. :o)
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)
<!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>
<!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.
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):
<maml:fetch table="molly_test" key="name" criteria="true" sort = "name" order = "ascending"> <table style="width:22em; background-color: #f4f5fb;padding:1em;"> <tr> <th><maml:sort sort="name">Name</maml:sort></th> <th><maml:sort sort="eyecolor">Eye Color</maml:sort></th> <th><maml:sort sort="age">Age</maml:sort></th> </tr> <maml:row> <tr> <td><maml:field name="name"/></td> <td><maml:field name="eyecolor"/></td> <td><maml:field name="age"/></td> </tr> </maml:row> <tr> <th colspan="3" style="text-align:right;">Total Records: <maml:numrows/></th> </tr> </table> </maml:fetch>
<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.<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.<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.<maml:row>
and </maml:row>
tag pair will be repeated for every record found by the query specified in the <maml:fetch>
tag.<tr>
table row.<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.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.
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
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
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> </div>
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).
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 "hex." Skin directories have a specific structure and set of files. There are two required files:
And three required directories:
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.
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.
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.
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.
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 yourmolly.ini
file to use the new skin.
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:
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.
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.
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.
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.
The default directory structure of a Molly installation is as follows:
.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):
AddType application/x-httpd-php .maml .html .php .tplt .ini .inc .txt .css .mss .php4 .php3 .phtml DirectoryIndex index.maml index.html index.php php_flag register_globals off SetEnv MOLLY_INI molly.ini php_value short_open_tag off php_value auto_prepend_file /Users/rvullo/Sites/mx/system/loader.php php_value auto_append_file /Users/rvullo/Sites/mx/system/parser.php # 404: Not Found ErrorDocument 404 /~rvullo/mx/error/404.maml IndexIgnore .htaccess Options -Indexes php_value upload_max_filesize 30M
.htaccess
file just to be sure for security reasons.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.<?
instead of <?php
. This, however, breaks when you have an <?xml
declaration..htaccess
file (above).auto_prepend_file
directive in Molly's .htaccess
file. It reads the molly.ini file (above) and sets up everything for Molly.auto_append_file
directive in Molly's .htaccess
file. It does the actual parsing of Molly's MAML tags and substitution of tokens.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. 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.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.<html>
, <head>
, and <style>
tags.<maml:fetch>
and <maml:form>
and all of their associated tags.<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.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 |
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.
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>
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.
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."
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.)
Once you have Molly's files installed on your server there are a few things you need to do to configure Molly:
molly.ini
file.htaccess
file/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
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%
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.
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.
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.
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.)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.
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
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
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
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
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:
- permitted: The permission group allowed to create, edit, and delete events in the calendar.
- size: Either small or normal (default set in calendar.ini) controls how the calendar is rendered. The small format is a calendar widget where dates with appointments are highlighted. The normal format is a liquid full-size calendar with the events listed on the date they occur.
- showappointments: When showappointments is set to true, the appointments will show up on the calendar, when it is set to false there will only be an indicator on the number of the day with an event.
- year: Used together with the month to set the initially displayed month. If not set, calendar will display current month. When mode is set to static the user will not be able to change months.
- month:Used together with the year to set the initially displayed month. If not set, calendar will display current month. When mode is set to static the user will not be able to change months.
- mode: When mode is set to static the user will not be able to change months. This allows you to display multiple months on a single page instead of requiring the user to switch months.
- id: Allows you to set an ID for CSS or JavaScript.
- class: Allows you to set a class for CSS or JavaScript.
- style: Allows you to override default styles. (Observe generated code to use this effectively and/or adjust the appropriate calendar template(s).
- display: Allows you to set the initial display to week or month
- week: Used together with the month and year to set the initially displayed week when the display is set to week. If not set, calendar will display the first week. When mode is set to static the user will not be able to change weeks.
For more information, please see the module documentation.
Path: /var/www/html/modules/calendar/calendar.inc
Start Line: #41
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
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
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
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: #332
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:
Total Records:
Name Eye Color Age Genny Brown 6 Heather Blue 28 Michelle brown 12 Ron Brown 48 Tim brown 22
Previous Records | | Next Records
Things which are known to be not working:
- <maml:row> tag’s maxentries attribute
- <maml:previous>
- <maml:next>
- <maml:pages>
- <maml:detail>
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
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
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> <th>fmd5</th> </tr> <maml:filelist path="/var/www/html/decor/skins/hex/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> <td><maml:fmd5 /></td> </tr> </maml:filelist> </table>Results:
filename fileroot filesize permissions filetype modtime extension fmd5 img01.tplt.jpg img01.tplt 22804 -rwxr-xr-x file 20 January 2012 08:41:27 jpg 205e395db585dedab3c6c12422111d27 img03.tplt.jpg img03.tplt 8372 -rwxr-xr-x file 09 October 2014 13:27:26 jpg e7c86bfef9850ff1b8d614ce35856a06 mxhead-dark.tplt.jpg mxhead-dark.tplt 42069 -rw-r--r-- file 10 October 2014 10:39:34 jpg b82a050f3400dd02a6246d32694d4ad7 mxhead-light.tplt.jpg mxhead-light.tplt 59228 -rwxr-xr-x file 10 October 2014 10:35:12 jpg ae41ec7d7ec40c7960d2318676c451fa mxhead.tplt.jpg mxhead.tplt 44546 -rw-r--r-- file 10 October 2014 10:38:28 jpg 90e23346a3da304281e7125a8aa22113 test_pattern_green.gif test_pattern_green 23881 -rw-r--r-- file 19 January 2012 09:25:11 gif 053d9b94bc96ae204d37676498ccda7e tinymolly.jpg tinymolly 5543 -rwxr-xr-x file 03 February 2011 14:12:37 jpg cad47d5ce2943b34103ca8e68e80d495
Path: /var/www/html/system/core/tags/maml.file.inc
Start Line: #108
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: #236
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: #252
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: #268
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: #300
Prototype: <maml:fmd5 name = "" id = "maml_fmd5_15" class = "" style = "visibility:visible;"></maml:fmd5>
Description: Used in conjunction with <maml:filelist> tag to retrieve a list of files from a directory.
Replaces itself with the md5 hash of the file for each file found.
Alternatively you may use the *[fmd5]* 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: #348
Prototype: <maml:form keyvalue = "" table = "" keyfield = "" criteria = "" response = "" mode = "" action = "none" name = "maml_form_16" schema = "off" ownership = "none" owner = "" permitted = "all" linkname = "" linkfield = "" id = "maml_form_16" 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
Prototype: <maml:if condition = "" else = "" id = "maml_if_17" 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
Prototype: <maml:img id = "maml_img_18" class = "" style = "visibility:visible;"></maml:img>
Description: This is a placeholder for a future <maml:image /> tag with the following features:
- "non-downloadable" images (i.e. no right-click saving)
- optionally add watermark and/or custom message to the image
- hides actual server location of the image from the user
Path: /var/www/html/system/core/tags/maml.format.inc
Start Line: #246
Prototype: <maml:include src = "" parse = "maml" debug = "" id = "maml_include_19" 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
Prototype: <maml:input type = "" name = "" value = "" size = "16" selected = "" id = "maml_input_20" 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
Prototype: <maml:item href = "" target = "_self" selected = "" id = "maml_item_21" 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
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
Prototype: <maml:menu type = "tabs" id = "maml_menu_22" 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
Prototype: <maml:modtime name = "" id = "maml_modtime_23" 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: #316
Prototype: <maml:multiple count = "1" button = "after" label = "Add Another" id = "maml_multiple_24" 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.)
- count: Positive integer. How many times to automatically replicate the contents on the client side (default is 1).
- button: Where to position the button(s) that the user clicks to replicate the contents. May be one or more of the following:
none, before, after, beforeeach, aftereach- label: What text to label the button(s) with. Default is "Add Another"
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
Prototype: <maml:nothing id = "maml_nothing_25" 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
Prototype: <maml:numrows id = "maml_numrows_26" 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
Prototype: <maml:option id = "maml_option_27" 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
Prototype: <maml:permissions name = "" id = "maml_permissions_28" 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: #284
Prototype: <maml:persist name = "data" id = "maml_persist_29" 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
Prototype: <maml:protect permitted = "all" denied = "" id = "maml_protect_30" 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
Prototype: <maml:quickquery query = "select * from molly_test" height = "24em" id = "maml_quickquery_31" 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
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
Prototype: <maml:redirect href = "" id = "maml_redirect_32" 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
Prototype: <maml:row empty = "" maxentries = "" id = "maml_row_33" 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
Prototype: <maml:schedule dateformat = "" startdate = "" enddate = "" startweek = "" endweek = "" startday = "" endday = "" permitted = "" id = "maml_schedule_34" class = "" style = "visibility:visible;"></maml:schedule>
Description: Description here.
Path: /var/www/html/modules/schedule/schedule.inc
Start Line: #247
Prototype: <maml:select name = "" size = "" disabled = "" multiple = "" tabindex = "" onclick = "" onfocus = "" onblur = "" onchange = "" onselect = "" onreset = "" id = "maml_select_35" 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
Prototype: <maml:sha1 name = "" id = "maml_sha1_36" class = "" style = "visibility:visible;"></maml:sha1>
Description: Used in conjunction with <maml:filelist> tag to retrieve a list of files from a directory.
Replaces itself with the md5 hash of the file for each file found.
Alternatively you may use the *[fmd5]* 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: #365
Prototype: <maml:sort sort = "" order = "ascending" id = "maml_sort_37" 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
Prototype: <maml:term startdate = "" enddate = "" id = "maml_term_38" 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
Prototype: <maml:textarea name = "" id = "maml_textarea_39" 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
Prototype: <maml:timeformat format = "unix" id = "maml_timeformat_40" 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
Prototype: <maml:token name = "" value = "" id = "maml_token_41" 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
Prototype: <maml:upload label = "Upload Files" maxsize = "1048576" destination = "mp/videotracks" response = "" process = "" type = "" callback = "" id = "maml_upload_42" 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
Prototype: <maml:vardump global = "gv_SiteGlobals" height = "24em" id = "maml_vardump_43" 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
Prototype: <maml:windoid title = "" showMsg = "" hideMsg = "" id = "maml_windoid_44" 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:
- frameColor: colorspec
- frameLeft: thickness (i.e. 2px)
- frameRight: thickness
- frameTop: thickness
- frameBottom: thickness
- fieldColor: colorspec
- titleAlign [left|center|right]
- titleStyle: any style spec valid for text
- backLink: URL, relative or absolute
- titleColor: color of windoid title
- titleFontFamily: font family of title
- titleFontSize: size of title
- titleFontWeight: [bold|bolder|normal], etc.
- borderStyle: [solid|dotted|dashed], etc.
- background: add an image to windoid background
- dragable: can user move the windoid around the page?
Path: /var/www/html/system/core/tags/maml.format.inc
Start Line: #2
Prototype: <maml:windowsize id = "maml_windowsize_45" 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
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
[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.)
<h3>Module Name</h3> <p>Docs go here.</p>
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.
The following documentation is generated automatically from information provided by the modules' authors.
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" />
Display a single month, January of 2020, and do not allow users to navigate:
<maml:calendar permitted="editor" year="2020" month="1" mode="static" />
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;" />
Calendar module originally created by R. P. Vullo
Updated and enhanced by Catherine Walters, July 2017
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
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) |
dateformat | string | Set 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 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 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]
UserDB | This database stores which user id is the creator of each lecture by id. It is currently set as lecture_user_xref |
---|---|
CaptionDB | This 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
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
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.
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 |
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 |
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.
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) |
The following list of Molly's internal functions is generated automatically for this particular installation.
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.
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.
To end buffering and send all the accumulated text on its way to the browser, call the ob_end_flush(); function.
<?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.
"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...
...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 ?>
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 } }
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.
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 } }
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; } }
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; } }