Contemplate Assembler

1.0a

07 Feb 2003
By popular demand, the ability to use a combination of hard-coded and passthru arguments in your embed tags has been reinstated. Just include a hard-coded tag, then insert any passthru variables with square brackets, and join the variable and hard-coded arguments with a + symbol. For example, if you include the argument name=Joe in your dynamic URL, then your template can include the tags

<!--#embed args=field,content.html,name[0] -->
<!--#embed args=field,content.html,name[0]+_age -->
<!--#embed args=field,content.html,name[0]+_occupation -->

This functionality was removed in version 4.0 to emphasize the direct relationship between arguments in the dynamic URL and embed tags, but it has proven too useful to do without in templates that include many small pieces of embedded content.

Even more significantly, the PHP version will automatically render any PHP code in your content files or templates. The rendering takes place after the extraction, so code contained in a template will share the same variable scope as code contained in a content file. This behavior is identical to what you can achieve by running the Perl version in the PHP wrapper.

Unfortunately, PHP and ASP error messages that refer to line numbers aren't very useful in this scenario, since the line number is relative to the assembled file, whereas you'll be editing a separate script with different numbering. Therefore, assembler.ini now supports a "show source" setting; if you add "show source: 1" to assembler.ini, the assembler will render the page normally, then append a numbered dump of the page source -- after assembly, but before PHP or ASP parsing. This will allow you to pinpoint the part of your script that the error messages are referring to. To retain the security of your server-side code, however, you can't pass the show source setting to the assembler through the page URL; you can only set it in the ini file.

A new embed tag attribute called "variable" tells Contemplate to put embedded content into a variable rather than displaying it in the assembled page. This allows you to manipulate the content as desired from your scripts, then optionally print it when you're done. The variable that Contemplate creates is available to scripts written in the same language as Contemplate itself. For example, if you're using assembler.php, and you include the tag <!--#embed main variable --> in your template, Contemplate will create a PHP variable called $main that contains the embedded content.

It's now easy to modify your pages on the fly based on the current page or template name -- just include one of these passthru tags in your template to obtain the value: <!--#embed page[0] --> <!--#embed template[0] -->.

A bug was fixed that prevented some complex conditional statements from evaluating accurately.

A bug was fixed that resulted in values passed to assembled pages via the URL string appearing as arrays to server-side scripts. Internally, Contemplate converts page definitions to variables and arrays so that you can easily refer to file and field names in your embed tags. Now, however, Contemplate returns these values to their original formats before displaying the page and rendering any code it contains.

Numerous insignificant adjustments were made to conform the code between the Perl and PHP versions.

1.0b

27 May 2003
Assembler.asp will now render ASP code in your content files or templates, in the same way that assembler.php renders PHP code. Please note, however, that assembler.asp only supports ASP code written using the JScript language (not VBScript), and that it will only recognize scripts enclosed in <% %> tags. Incidentally, assembler.cgi will never support this functionality, since it's impossible to embed Perl scripts inside HTML pages.

For the first time, the Assembler will parse any embed tags or conditional tags that you place into your content files. This means, for example, that you can create a header file that contains Contemplate-based logic or embedded content, and embed that header file into your templates. This is called recursive parsing, and it's enabled automatically.

Assembler.ini is now called preferences.ini, and will soon contain settings for other components besides the Assembler.

A new setting in preferences.ini lets you control how assembler determines the host values in your traffic reports. If you set "host lookups for logs" to "off," assembler will rely on the web server to look up your visitors' host names. If you set it to "auto," assembler will perform its own host name lookups if the web server provides the same value for the visitor's host name and IP address. If you set it to "on," assembler will perform its own host name lookups regardless of the web server configuration. The default setting is "auto."

In addition to accessing the current page name and template name with passthru tags (e.g. <!--#embed page[0] -->, <!--#embed template[0] -->), you can also access the page definition (e.g. <!--#embed page_definition[0] -->). This allows your own scripts to do any parsing you like based on any element of the page definition.

Furthermore, you can now access the page[0], template[0], and page_definition[0] variables in Contemplate's conditional tags, so you can add logic to your templates based on these values without using any additional scripting. You can't, however, use these three variables as names for your embed tags; Assembler will show an error stating that page, template, or page_definition is a reserved word.

A new attribute for embed tags, fill_defer, tells the Formulator to parse the tag normally and then show the popup menus for selecting content at the bottom of the page rather than at the spot where the content appears. This is useful when you're embedding content into a script or an HTML tag, and positioning the popup menus there would seriously disrupt the display of the page. The fill_defer option doesn't apply to hard-coded tags, which you can't set in the Formulator, or to passthrough tags, which always appear as an input field at the top of the page, but adding it to these kinds of embed tags won't cause any problems.

Previously, the assembler's pre-rendering feature and all of the flattener's functionality did not work on password-protected sites. Now, these features work in the PHP and ASP versions, on password-protected sites that use HTTP-standard, basic authentication. Making this work in the Perl version is an item on the Known Issues list.

The form parsing routine was revised considerably. You can now surround your input values with single quotes, double quotes, or neither -- although the equals signs in your tag attributes should not have spaces around them. Also, you can now include punctuation and other special characters in form values.

Contemplate's error messages no longer contain any single or double quote marks, so if you place embed tags into variable assignments in your own scripts, and those tags result in Contemplate errors, your scripts won't generate additional errors caused by conflicting quote marks.

Contemplate no longer continues processing tag attributes like strip and replace after it encounters an error. Therefore, the error message text won't be inadvertently processed and possibly rendered unreadable.

A bug in the alpha which allowed "secure" preference settings, like read_files_from, to be overridden through the URL string was fixed. If you include allowed preference overrides in your URL string, however, you will not be able to also refer to those argument values in your embed tags (e.g. the passthru tag <!--#embed show_errors[0] --> won't work if you include &show_errors=1 in the URL).

1.0

29 Aug 2003
All Contemplate scripts now look for different environment variables depending on what server platform they're running from. This resolves a particular problem when running PHP as a CGI module, but should make the scripts more compatible in general.

In the last release, Assembler.cgi was not processing replace attributes. This functionality is now restored.

The Assembler now correctly reads XML content fields whose names are not surrounded by quote marks.

The Assembler now parses large content files faster, especially the ASP version, which was parsing large files quite slowly in the previous release.

The Assembler now warns you in more situations if you use an embed tag name that conflicts with one of its internal variable names. Removing the possibility of such conflicts has been added to the known issues list.

The get_setting function now contains an extra line to ensure that Contemplate will evaluate a setting of "0" in the preferences file as false in every language. The ASP version was evaluating "0" as true, resulting in some preference settings not taking effect.

1.0.1

30 Oct 2003
The Assembler now takes a new preference called "show source to IP address," and the previous "show source" preference works differently. Now, you can show the page source on the fly by adding show_source=1 to your page URL, but you must first list your local IP address in the "show source to IP address" setting. This makes it easy for site developers to see their own page source at any time, while making it impossible for other site visitors to ever see the source.

You can now list multiple page definitions files, separated by commas, in the "read page definitions from" setting of preferences.ini, and the Assembler will search through each definitions file you list until it finds the page you've specified. Please note that this functionality is only a partial step toward future support for multiple page definitions files. It is not yet mentioned in the Contemplate documentation and is not yet supported in the other Contemplate components.

You no longer need to specify the directory location of your page definitions file if you store it in the contemplate directory. For example, your setting for "read page definitions from" in preferences.ini might be simply "pages.txt." You can still store your definitions file elsewhere by using a setting like "../other/pages.txt."

If you're using Apache's mod_rewrite or other software to rewrite dynamic URLs, you no longer need to use "assembled" as the string that triggers the rewrite. If you wish to use a different string, you can open each of the server-side scripts included with your version of Contemplate, look for the $URL_rewriting_flag variable definition, and change it in the script. (This setting is not available in the preferences file because the scripts need it in order to read the preferences file.)

Previously, the Assembler returned script errors when it tried adding an external link target to an anchor tag that contained a server-side script embedded into it. Now the Assembler correctly parses those anchor tags.

The $allow_partial argument in the get_setting() function in assembler.cgi was misnumbered, causing some preference settings to behave incorrectly. This is now fixed.

1.0.2

21 Nov 2003
By default, Contemplate will read files in all the subfolders of the content and templates folders and the additional folders you specify in the read files from setting. However, you can now disable this recursiveness by adding a "read files recursively" setting to your preferences file and setting it to 0.

The $URL_rewrite_flag variable is now properly declared as a global in PHP functions. This problem primarily affected the Flattener and only affected the PHP version of Contemplate.

The navigation embed types no longer generate errors when the name of the current page also appeared in the page definitions file as a part of the definition of a different page.

1.0.3

18 May 2004
Assembler.asp now supports embedded ASP scripts written in either JScript or VBScript -- it formerly only supported scripts written in JScript. However, it will now interpret scripts enclosed within <% %> as VBScript, rather than as JScript as before. If you want to embed JScript code, you'll have to enclose it in <script language="JScript" runat="Server"></script> tags.

When using the "variable" tag attribute, assembler.asp used to create variables whose names started with the $ symbol, which were accessible from JScript code. Now it creates variables whose names do not start with that symbol, so the variables are accessible from within both JScript and VBScript code. For example, the tag <!--#embed skin variable --> creates a variable called $skin in assembler.php and assembler.cgi, and a variable called skin in assembler.asp.

Assembler.asp no longer stops with a script error when you create a conditional tag that contains a reference to an argument that does not appear in the page definition. The conditional will simply evaluate false and the Assembler will continue processing your page.

Assembler.asp now correctly generates error messages with &quot; entities rather than actual double-quote symbols, so that content embedded into variable assignments in your scripts will not cause string termination errors in your script if the embed fails.

The built-in search function no longer returns error messages or oddly formatted content in assembler.asp. The ASP version of the search function now behaves like the PHP and Perl versions.

You can now access the special passthrough variables page[0], template[0], and page_definition[0] in combo tags.

You can now access the values of navigation and environment tags in conditional tags. For example, the following code prints a message if the current page is the last in a group in your page definitions file:

<!--#if (page[0] == nav_last) -->
Sorry, there are no more pages after this one!
<!--#end if -->

Assembler.php was logging HTTP errors into the reporter/data/YYYY-MM.txt files rather than the reporter/data/YYYY-MM-errors.txt files. Now it will log HTTP errors in the correct file, provided you are running PHP 4.1.0 or newer.

All versions of the Assembler no longer display the wrong XML field if a preceding field in an XML file had a name that began with the name of the desired field.

Assembler.php and flattener.php now come with a few lines commented out to enable compatibility with open_basedir restrictions on some servers. The commented-out lines let the scripts write data to files with relative paths, which usually works and avoids open_basedir problems. To use absolute paths, if you receive errors writing data, you can search the scripts for "open_basedir" and restore the indicated lines.

1.0.4

06 Aug 2004
The primary purpose of this release is to improve security. First, we now check incoming data to avoid cross-site scripting attacks and other vulnerabilities. Specifically, the Assembler now strips special characters out of file names that appear in the query string, and encodes < and > to &lt; and &gt; in all user-supplied data.

Second, the Flattener and Formulator scripts no longer allow users to override your Contemplate preferences by passing values in through the query string. Since these are the two scripts that can write files, this change prevents a malicious user from manipulating these scripts to overwrite your content files.

Third, the default password protection scheme now uses direct password protection on each of the Contemplate subfolders, rather than on a login file that all the utility pages include. This change required moving the Flattener script to its own subfolder. Under this arrangement, you can set separate permissions for each of the Contemplate subfolders, or, with some web servers (e.g., Apache), copy the same permissions to each subfolder for single-login access to all of them.

Finally, the default Contemplate folder structure now places your preferences and page definitions files in a subfolder called data that you can also password-protect along with the other Contemplate folders. This structure should also make it easier to updgrade your version of Contemplate, since you can safely overwrite all the files except those in the data folder. This change requires you to add the data subfolder to your "read page definitions from" path in preferences.ini.

The Assembler's built-in content search functionality has a few cosmetic changes. The URLs in search results now appear in the same format as the search results page itself (e.g., contemplate/assembler.php?page=search_results versus assembled/search_results.html). Ellipses no longer appear if the preview text starts at the beginning or reaches the end of the full text. And the search results are now displayed with CSS styles named search-results-heading, search-results-link, and search-results-preview, so you can define those styles along with the styles for the rest of your site to control the appearance of the results.

Similarly, Contemplate now displays error messages with a CSS style named error-text, so you can control the appearance of those messages.

1.1.0

10 Dec 2004
Following through on the last version's effort to make upgrading Contemplate a simpler process, we've moved the language and active component settings from contemplate/index.html to contemplate/data/index_settings.html. We've also changed the location of the Reporter data files from contemplate/reporter/data to contemplate/data/reporter. If you upgrade to this version and are using Contemplate to log site traffic, please move the reporter/data file to the data folder and rename it to reporter. Now you can upgrade to future versions of Contemplate by overwriting all but your contemplate/data folder, which contains all of your settings and data.

The Assembler now has a new embed type: menu. This allows you to set up a menu structure containing text, links, and graphics in your content files using easily editable bulleted lists, but pass this information as multidimensional arrays to an interactive menu that you create in Flash, DHTML, or some other technology. The Assembler parses your bulleted list, extracts the relevant information, and outputs it in as arrays that another program can more easily parse.

Although Contemplate makes it easy to move beyond a one-to-one relationship between content and pages and share content across pages without duplication, sometimes you just want to build a straightforward site where every piece of content only appears on one page. In this case, you could simplify your page definitions dramatically by creating embed tags based on elements of the page name. For example, if your template contains main, header, and sidebar areas, and your page name is contact, you could use embed tags like <!--#embed args=field,main.html,page[0]_main -->, <!--#embed args=field,main.html,page[0]_header -->, and <!--#embed args=field,main.html,page[0]_sidebar --> and eliminate all three arguments from your page definitions. But what if you want to base an embed tag on a portion of a page name? With a new option in preferences.ini, Contemplate can now split a page name on a delimiter of your choice and return each portion of the page name in the page[] array. For example, if you include

split page names on: _

in preferences.ini, and your page name is "company_contact," then page[0] in an embed tag will return "company" and page[1] will return "contact."

Whenever you use square brackets to access an element of an array in your embed tags, you can now leave out the index to return a string containing the entire array. For example, if the page name is "company_contact" and you use the split option described above, page[0] will return "company," page[1] will return "contact," and page[] will return "company_contact." Similarly, if you have an argument

home=field,main.html,home

in your page definition, home[0] will return "field," home[1] will return "main.html," home[2] will return "home," and home[] will return "field,main.html,home."

Please note that this functionality might not provide the desired results if you embed all elements of an array into a combination embed tag, because the elements will be comma-delimited and the assembler will parse the array as separate elements when processing the tag. For example, if name=john,doe and you use an embed tag like <!--#embed args=field,people.html,name[] -->, the Assembler will convert that to <!--#embed args=field,people.html,john,doe -->, look for a field named "john," and ignore the fourth "doe" argument. On the other hand, if name=field,people.html,johndoe, then you could use an embed tag like <!--#embed args=name[] -->, which the assembler would convert back to <!--#embed args=field,people.html,johndoe -->. We can't imagine, however, an example where this would be useful.

You can now use the Assembler to access a single piece of content directly, without the use of a template. If you pass the Assembler a list of args, just like in a passthru embed tag…

../contemplate/assembler.php?args=field,main.html,contact

…the Assembler will output just that piece of content. This is useful for debugging as well as for using Contemplate to help pull content into a Flash file or other dynamic media.

The log site traffic option in preferences.ini is now set to 0 by default in new Contemplate downloads, since leaving this on caused problems for some webmasters who weren't ready to use it. When you're ready to use Contemplate to log your site traffic, just change this value to 1.

Previously, if you embedded JScript code into a template, assembler.asp evaluated that code as VBScript unless you set the language attribute to "JScript" (case-sensitive). Now assembler.asp will evaluate your code as JScript regardless of how you capitalize the language attribute.

Assembler.php now runs without warning messages if you've lowered your PHP error reporting level to show warnings. All internal variables are properly initialized to enable this change.

Previously, Contemplate did not support dashes in page, field, and form element names. It should now.

In the last version, the Assembler couldn't read the page definitions file from the contemplate/data folder if the "read files recursively" option was turned off in your preferences file. Now, the Assembler can always read from the contemplate/data folder, as well as the content and templates folders.

The <!--#embed env_last_modified --> tag has been broken in the last few versions of assembler.php. It is now working again.

Previously, embed tags could only contain one passthru value, so a tag like <!--#embed args=field,lesson[0]_text.html,page[0]_main --> wouldn't work properly. This was a bug and has been fixed.

Previously, conditional tags could only contain one navigation or environment value, so a tag like <!--#if nav_current == nav_total --> wouldn't work properly. This was a bug and has been fixed.

Assembler.asp used to fail completely with an ASP script error rather than failing gracefully with a Contemplate error if an embed tag for a field didn't include the field name. This was a bug and has been fixed.

1.1.1

19 May 2005
The external_link_target option now works a bit differently. Rather than applying the link target to all links containing "http:", Contemplate now applies the link target to all links containing "://". The advantage of this change is that any absolute URL, regardless of protocol, will have the external link target applied. The disadvantage is that links to resources on the same site but with different protocols will have the external link target applied, which may not be the desired behavior. If you need to use an absolute URL to link to a resource on the same site and do not wish to have the external link target applied, you can specify a different link target (e.g., "_top") and Contemplate will not override that.

A bug in assembler.asp that prevented the script from reading content files with names containing a second character of "w" has been fixed.

A bug in assembler.asp and assembler.php that caused errors or incorrect parsing when a page definition argument name ended in "page" has been fixed.

Assembler.asp and assembler.php no longer show errors when a variable used in a conditional or passthru tag doesn't exist or doesn't contain the requested index. In these cases, Contemplate treats the variable as if it exists with the requested index set to an empty string.

Assembler.php correctly sends HTTP headers when you set enable the "prevent page caching" option in preferences.ini. Previously, it would lose the Content-Type header, which would cause some browsers to display pages incorrectly when viewed over an SSL connection.

When the security checks in the Assembler stop it from opening a file, it correctly returns the message that the file could not be opened rather than the message that a field could not be found within the file. When opening a page definitions file, it correctly returns the message that the file could not be opened rather than a message that a definition could not be found within the file. However, the Perl version of the Assembler still returns the incorrect messages when reading remote files over http, because we don't know how to test for the existence of a file in that scenario (see the comment "to do: how can we test for this?" in assembler.cgi).

1.2.0

19 Dec 2005
Contemplate now makes it easier to set up a password-protected area of your website. If you add the option "require authentication to read files from " to your preferences.ini file, and follow it with a comma-delimited list of folder paths, the Assembler will only display pages whose content or templates reside in those folders if a basic HTTP-authentication username is present. For example, the following line will require authentication for any page whose content is contained in the "staff" or "clients" folders:

require authentication to read files from: ../staff/, ../clients/

Note that Contemplate will not check for a specific username or password -- it will simply assume that if a username is present, the user logged in correctly through a mechanism that you set up elsewhere on the site. This allows Contemplate to work in conjunction with whatever authentication mechanisms your web server provides. Here's one way to use this Contemplate option with Apache's htaccess files:

  1. Add the line "require authentication to read files from: ../members/" to your preferences.ini file.
  2. Create a directory called "members" on your site and password-protect it with an htaccess and htpasswd file.
  3. Create a new content file in the members directory, and create a set of pages using content from that file.
  4. Add an index.html file to the members directory, containing a redirect to your first password-protected page.
  5. Add a "member login" button to your site and link it to members/index.html.

When users click the member login button, their web browsers will prompt them to log into the members directory, and will then redirect to the first members page. Since Contemplate sees that they have logged in, it will display any page containing content from this directory. If a user tries to view a members page without logging in first, Contemplate will display an error message. NOTE: This option has not been tested in the ASP version and is not included in the Perl version.

The menu embed type now accepts a fourth argument of "HTML," which tells the Assembler to simply return the unparsed HTML of your menu content. This is useful for placing into a <noscript> page in your template, to allow search engines and other software to navigate your site.

A few references to ../graphics/spacer.gif assumed that all sites contained a graphic in that location, and generated 404 errors in server logs when they did not. All versions of the Assembler now reference ../contemplate/graphics/spacer.gif, which is a part of Contemplate's standard installation.

The Assembler used to have built-in support for Flash templates, but newer versions of Contemplate give developers several ways to load Contemplate-driven content into Flash movies with more control and flexibility. The old code that provided built-in support has been removed.

Some old code that supported the Flattener's obsolete "unflatten" option has been removed.

1.2.1

01 Mar 2006
Assembler.php now correctly sends HTML headers to avoid the "header may not contain more than a single header" error that appeared on some servers.

1.2.2

01 Mar 2007
Contemplate relies on several environment variables to find files on different kinds of servers, and it used to use the "OS" environment variable to decide which additional environment variables it could look for. However, the "OS" environment variable itself is not available on all servers. Contemplate now simply tries a couple different environment variables, and shows error messages if at least one of the required variables is not present.

Assembler.asp used to merge the physical path to the Contemplate directory with the apparent path as shown in the browser address bar, to construct a path that originated at the server root but included any virtual directories used to construct the URL. However, virtual directories on Windows servers aren't valid for reading files through the file system anyway, so this functionality -- which resulted in incorrect paths on some application servers -- has been removed. The ability to use symlinks in the site path on Unix computers still remains: Contemplate will find files relative to the "virtual" directory location created with symlinks.

A common way to improve your site usability and search engine optimization is to use URL rewriting to transform addresses like contemplate/assembler.php?page=home to assembled/home.html. Now Contemplate allows you to use other keywords besides "assembled" to give the appearance of a site organized into multiple directories. For example, if you added these rewrite rules to your site configuration…

RewriteRule ^main/(.+).html$ /contemplate/assembler.php?page=$1&%{QUERY_STRING}
RewriteRule ^products/(.+).html$ /contemplate/assembler.php?page=$1&%{QUERY_STRING}
RewriteRule ^services/(.+).html$ contemplate/assembler.php?page=$1&%{QUERY_STRING}

…then any of these addresses would work:

main/home.html
products/software.html
services/consulting.html

The "graphics" subtype of Contemplate's "menu" embed type is now named "images." However, the "graphics" name will still work, for backwards compatibility. And Contemplate now offers three additional menu subtypes: "images_width," "images_height," and "images_alt" will capture the width, height, and alt values you set in the HTML image tags of your menu content.

When the Assembler displays search results or error messages, it now correctly includes quotes around HTML attributes for strict HTML 4 validation.

The text phrases used at the top of search results are now defined at the top of the Assembler script for easier localization. Eventually we could move these phrases to a separate file in the data folder to eliminate having to replace translated text after upgrading to a new version of Contemplate.

The random_string function used to create visitor IDs for display in the Reporter no longer includes vowels in its output. Also, the random_string function in the PHP version of the Assembler now works just like in the CGI and ASP versions.

1.2.3

04 Nov 2008
No changes were made to the Assembler in this release.

1.2.4

30 Nov 2009
Previously, conditional expressions that tested multiple variables with AND or OR logic may have been evaluated incorrectly. For example, the expression ((page[0])||(section[0])) would have only evaluated true if the first part were true. This has been corrected.

In the PHP version, a setting for the PCRE backtrack limit was added to the top of the Assembler script. This compensates for a lower default setting in recent versions of PHP.

The Assembler no longer logs traffic when it is called from the Flattener.

Two instances of the split() function in the PHP version were replaced with explode(). This will avoid an alert message in some PHP configurations that split() is deprecated.

Any quoting around the external link target preference value are now removed, and the value is inserted into anchor tags using the same quoting that the href attribute uses. This includes an escape character (backslash) if present. Also, the target attributes will be added to anchor tags with escaped quotes.

1.3.0

1 Dec 2009
The Assembler now includes a few extra routines it needs to integrate with the Meditate(tm) Web Content Editor. These additions have no effect on assembling website pages.

1.3.1

3 Nov 2010
The Assembler no longer strips line endings from content edited with Meditate.

The Return to Editor link that appears when you browse a site from Meditate now links to the correct page.

If you place a hard-coded embed tag into your template and use the "variable" keyword, you can access it in your code from the $hardcoded variable. Previously, you could only do this with one hard-coded tag per page. Now, if you use multiple hard-coded tags with the "variable" keyword, they will be available as $hardcoded_1, $hardcoded_2 and so on. The numbers will only be added if more than one hard-coded tag uses the "variable" keyword, so this is backwards-compatible with existing sites.

2.0

23 Nov 2010
The Assembler now includes routines to support the page management feature in Meditate(tm) Web Content Editor. This feature provides a web-based interface for editing the pages.txt file. At the same time, Contemplate no longer includes the Formulator (since Meditate handles that functionality now) or the Flattener (since virtually every HTML delivery method these days supports server-side script execution), so the routines to support those components have been removed from the Assembler. Also, the Reporter now stores its data into a database rather than text files, so the routines to support that component have been rewritten. These changes should have no affect on assembling web pages.

Contemplate no longer supports the menu embed type, since CSS is more effective at transforming a bulleted list into a visual menu.

Contemplate now supports a new "database" embed type. This allows you to embed a content field from a database into your templates. For more information, see the Page Definitions section of the documentation.

The new database tag allows you to select random content from the database by leaving off the last two arguments. For consistency, you can now leave out the third value of a field embed tag too, to randomly display one field from the selected file. However, the previous notation of a "random" embed type still works.

Contemplate now includes a function called merge_values($content, $values) that you can use in your scripts, in conjunction with the "variable" embed attribute. This function finds any PHP variables in $content, and sets them to the corresponding values in $values, which is an associative array. For more information, see the Tips and Tricks section of the documentation.

Contemplate also supports a new kind of tag that you can place into your content. A "split" tag extracts a portion of your content, puts it into a variable that your code can access and manipulate, and replaces the content with a reference to the variable. A combination of the merge_values function and the split tags makes it easy to loop through a repeatable piece of content and merge data into it. For more information, see the Tips and Tricks section of the documentation.

Contemplate now shows a warning message if you create an embed tag with a name that conflicts with one of its reserved words (and the number of reserved words has been reduced to about a half-dozen).

Previously, if you requested a page definition that did not exist, Contemplate would only display its own error message. Now it will return a Status 404 header, and if you specify the name of an assembled page or the URL of a static page in the ERROR_PAGE_404 setting, Contemplate will display that instead. In either case, the Reporter will still log an assembler error as before; if you use this new setting, it will also log a 404 HTTP error.

The special env_last_modified tag now displays a value in the SQL-standard format, YYYY-MM-DD HH:MM:SS.

Contemplate now removes the CDATA tag before displaying content from an XML file, so you can include this tag in your files.

The Assembler script no longer crashes if you place a less-than symbol (<) into a conditional tag.

Changes to the Reporter component will be included in this file from now on, rather than in a separate set of release notes. For Reporter notes prior to this release, click here.

The Reporter has been rewritten to store traffic data in a database rather than a log file. This dramatically speeds up the display of traffic reports (which look the same as they did before). In order to log traffic with Contemplate 2.0, you need to create a database table using the schema included in docs/install.txt, then specify your database connection information in the Reporter preferences section of config/constants.php (this are separate from the Contemplate database preferences, but you can enter the same values if you're using the same database for content and traffic reports). You can import your Reporter data from versions older than 2.0 by following the instructions in docs/upgrade.txt.

The Reporter preferences no longer include a "show inspector rollover" option. Originally built with JavaScript, this option slowed down the loading of large pages. The current CSS implementation doesn't have this problem, so the option is always on.

2.0.1

22 Jun 2011
The LOG_SITE_TRAFFIC preference can now be overridden by passing its value in through the query string, as described in the Preferences section of the documentation.

In the last version, the SHOW_SOURCE setting did not work and the page source appeared whenever the SHOW_SOURCE_TO_IP_ADDRESS setting was configured. This has been corrected.

The EXTERNAL_LINK_TARGET option is now applied after all PHP code is executed, so that it affects any links that are generated by your PHP code. Also, the option is no longer applied to internal links that use absolute URLs.

In the last version, Contemplate was including a header called Foo in the HTTP response. This was meant for debugging and has been removed.

2.0.2

16 Nov 2011
Added support for show_errors and hide_errors attributes in embed tags. You can use these attributes to override the SHOW_ERRORS setting in config/constants.php for particular tags.

When using the SHOW_SOURCE setting in config/constants.php (or passing show_source=1 into a page from the query string), Contemplate now only displays the source, rather than rendering the page and then displaying the source. This ensures that you will see the source even if the source contains serious errors that would prevent it from rendering.

The formatting of the source display is improved to include any indenting or spacing in your code.