Enano CMS Project

Enano architecture overview

The Enano API was built with ultimate extensibility in mind. Writing Enano plugins should be quite easy, provided that you have some basic PHP experience and a short knowledge of how the Enano API is organized.

The five pillars of Enano

No pun intended. Enano has five components, with each handling a seperate important function. Each component has one class, and thus one object, that can be used anywhere. Here's a list of the components of Enano:

  • $db - the database abstraction layer. Pretty simple - it handles making MySQL queries, connecting to the DB, SQL debugging, etc. Works a lot like the one in phpBB, in fact many of the methods have the same names. Defined in includes/dbal.php.
  • $paths - URL and page management. This is perhaps the single most important component - without $paths, Enano would not know what page to send, and thus it would not be able to determine a lot of other important information. Defined in includes/paths.php.
  • $session - security and user functions. The session manager determines user rights, and handles logins, authentication, and ban control. Defined in includes/sessions.php.
  • $template - the part that turns a bunch of template files into usable (X)HTML. Perhaps the most complex part of Enano. The template manager assigns variables to and processes statements in the template files. This object probably contains the most useful methods for plugin developers. Defined in includes/template.php.
  • $plugins - a three-method mini-class that simply fetches plugin enablement status from the database and loads plugins according to that list. Also handles hooks. Defined in includes/plugins.php.

These five objects contain 95% of the Enano code. As a result you'll want to use them in all of your functions. No problem, just insert this into the top of each of your functions:

global $db, $session, $paths, $template, $plugins; // Common objects

That code is found pretty much about every 20 lines in the Enano source. Once those globals are included, nearly every part of Enano can be accessed and tweaked.

Important methods and variables

Of course if there are objects then there are important methods to be called. Here's a list of them, along with some important variables, sorted by object:

$db - the database abstraction layer

  • $db->_die(string $error_explaination) - halts execution of Enano in the case of a database error, initializes the database-less version of the template class, and prints a user-friendly error message. This method should be used whenever a database error takes place. Returns: null
  • $db->sql_query(string $sql_query) - sends a query to MySQL. Use as little as possible, the goal of Enano is to keep it under 20 queries per page! Returns: MySQL result resource
  • $db->fetchrow(optional resource $mysql_result) - fetches an associative array containing the next row returned by a SQL SELECT or SHOW statement. If the first parameter is not specified, the result from the most recent MySQL query is used. Returns: Array
  • $db->numrows(optional resource $mysql_result) - Returns the number of rows included in the most recent SELECT or SHOW statement. If the first parameter is not specified, the result from the most recent MySQL query is used. Returns: integer
  • $db->num_queries - the number of queries made so far in the Enano execution.

$paths - the URL parser and page manager

  • $paths->add_page(array $page_info) - adds a page to the Enano page list in $pages. NEVER manipulate $paths->pages manually - let the path manager do it for you. NOTE: this method does NOT add the page to the database, only to the pages array in memory. IMPORTANT: The array passed should contain the following keys:
    • name: the page name, spaces allowed
    • urlname: the page name as shown on the URL, no spaces; underscores encouraged as opposed to CamelCase
    • namespace: a valid namespace ID - see below for a list of namespace IDs that come bundled with Enano
    • special: integer, 1 or 0 - if 1, template header and footer are not sent
    • visible: integer, 1 or 0 - if 1, page is shown in logs and contrib pages (hiding not implemented yet at the time of this writing), use 0 VERY sparingly
    • comments_on: integer, 1 or 0 - if 1, comments are enabled for the page. Should not be used on Special or Admin pages
    • protected: integer, 1 or 0 - if 1, page cannot be edited. Should be set to 1 on all pages added by plugins.
    • delvotes: should be an integer set to 0
    • delvote_ips: should be an empty string ("")

Returns: null

  • $paths->addAdminNode(string $folder_name, string $node_name, string $admin_page_id) - adds an administration page to the tree menu in the admin panel. $admin_page_id should be the URL-name of the admin page, without the 'Admin:' prefix. Example: $paths->addAdminNode('General', 'General Configuration', 'GeneralConfig'); Returns: null
  • $paths->main_page() - sends the user a Location: header and redirects them to the main page of the site, then halts script execution. Returns: nothing
  • $paths->sysmsg(string page_id) - returns the contents of the specified system message page (System or "Enano:" namespace). $page_id should be the URL-name of the message, without the "Enano:" prefix. Use sparingly. Returns: string
  • $paths->get_pageid_from_url() - returns the page ID as passed on the URL. Use this only when $paths->init() has not been called, in all other cases use the $paths->cpage array. Returns: string
  • $paths->pages - associative AND numbered array containing information on every page in the database and every page added by a plugin.
  • $paths->page - URL-name of the current page.
  • $paths->cpage - associative array containing lots of information on the current page. Referenced quite often in the Enano source.

$session - security and users

As of Enano 1.0RC1, the session API has been completely rewritten. It is fully commented and documented. A phpDoc guide to $session will be posted soon. This is part of an ongoing effort to provide full phpDoc-compliant inline documentation in Enano.

$template: page rendering

  • $template->header() - prints the page header.
  • $template->footer() - prints the page footer.
  • $template->getHeader() - returns the page header. Returns: string
  • $template->getFooter() - returns the page footer. Returns: string
  • $template->sidebar_widget(string $widget_title, string $widget_html) - adds a new section to the sidebar. The new section is not made a slider, due to CSS issues.
  • $template->add_header(string $html) - adds the specified HTML to the section of the rendered page.
  • $template->process_template(string $filename) - processes a template file according to the variables below. Returns: string (will be compiled HTML)
  • $template->tplWikiFormat(string $template_code) - wiki-formats template code using the $VARNAME and {if foo}...{/if} syntax described in the "Manage sidebar" section of the Enano admin panel.
  • $template->tpl_bool - an array containing all of the conditionals used in template files. Values in this array override anything set by the template parser. All values in this array should be either true or false, otherwise you may get some very cryptic errors. Values in this array are checked using the ... code in templates.
  • $templates->tpl_strings - array containing all string variables in template files. Referenced in template files using {VARIABLE_NAME}.
  • $templates->sidebar_extra - string containing all extra code to be added to the sidebar. Use sparingly, not well supported at the moment.

RenderMan: text formatting and page retrieval

The RenderMan class provides the methods that wiki-format text and handle HTML/PHP stripping, smiley formatting, and all sorts of other fun stuff. Please note that there is no global object variable for RenderMan - it is intended to be called using the Paamayim Nekudotayim syntax (::). (That means "double colon" in Hebrew, and it's the official way to refer to the scope resolution operator in PHP 5.)

  • RenderMan::getPage(string $page_id, string $namespace_id, optional int $wiki, optional bool $smilies, optional bool $filter_links, optional bool $allow_redirection, optional bool $allow_format) - Fetches a page from the database and runs it through RenderMan::render (discussed below) with the specified flags. $wiki is the format to use when wiki-formatting the text - 0 means don't format, 1 means use the standard Text_Wiki parser, and 2 means use $template->tplWikiFormat for system messages. $smilies should be set to true if textual smilies should replaced with tags, false otherwise. $filter_links is a deprecated option and is ignored. $allow_redirection should be set to true if you want to allow redirect pages to work, false otherwise. $allow_format should almost always be set to true unless you need the raw text from the row. The parameters $wiki and $smilies are not handled by getPage, instead they are passed to the render() method (below). Returns: string
  • RenderMan::render(string $text, optional int $wiki, optional bool $smilies, optional bool $filter_links) - Formats a text string ($text) using the specified flags. $wiki is the format to use when wiki-formatting the text - 0 means don't format, 1 means use the standard Text_Wiki parser, and 2 means use $template->tplWikiFormat for system messages. $smilies should be set to true if textual smilies should replaced with tags, false otherwise. $filter_links is a deprecated option and is ignored. Returns: string
  • RenderMan::strToPageID(string $text) - Extracts the page ID and namespace from a given page title, and returns an array with key 0 being the page ID and key 1 being the namespace ID. For example, if you pass "Enano_CMS:About" as the $text parameter (on this site where the title is "Enano CMS") then the method would return Array('About', 'Project'). Returns: array
  • RenderMan::preprocess_text(string $text, optional bool $always_strip_php) - Sanitizes HTML and escapes a string ($text) for being sent to MySQL. If $always_strip_php is set to true (default) then PHP is stripped even if the currently logged-in user is an administrator. Otherwise, PHP is only stripped if $session->user_level < 2.
  • RenderMan::smileyize(string $text) - Replaces smilies with tags. Pretty much automatic now, but may require a call to an initSmileys function in later versions, depending on whether I add support for smiley packs like phpBB.

$plugins - plugin management, loading, and hooks

  • $plugins->setHook(string $hook_name) - adds a new hook.
  • $plugins->attachHook(string $hook_name, string $php_code) - adds a new block of code to be eval'ed at the point in the Enano source where $plugins->setHook($hook_name) is called. Some of the most common hooks are:
    • session_started - in common.php, right after $session->start() is called
    • page_set - in paths.php, right after the page info ($paths->page, $paths->cpage) is determined
    • page_type_string_set - in template.php, right after the text for the "article" button on the toolbar has been determined (on this page that text is "documentation page"). Allows you to override that text easily.
    • compile_template - in template.php, called immediately before a template is compiled. Use this for any last-minute overrides to template info.
    • A complete list of hooks is available here.

Some common functions

  • wikiFormat(string $text) - converts a wiki-formated block of text into XHTML. Returns: string
  • grinding_halt(string $title, string $body) - Kills the database connection and immediately exits with the error strings passed on the function callback line. Use this method for reporting errors very early on in Enano's execution (like database connection failure) and for high-priority security intrusions (e.g. user banned). Both this function and die_semicritical() require the default Oxygen theme to be installed. Mainly because these functions don't have database access to determine which theme to load.
  • die_semicritical(string $title, string $body) - Almost the same as grinding_halt(), but uses the site name and site description in the header. Use this in place of grinding_halt unless you are before the stage where the configuration info is fetched (VERY early).
  • die_friendly(string $title, string $body) - same as die_semicritical(), but properly parses the template (including sidebar, etc.) and exits with the text passed on the function call. Use this after sessions and templates have been initialized.

Important constants

Only a few, so we might as well cover them here:

  • scriptPath - the path to Enano, relative to the document root, without the trailing slash. Used in template files and such to allow some neat tricks like initializing/displaying Enano or including Enano files from another directory.
  • contentPath - the complete prefix appended to page URLs. For example, if you wanted the page User:dandaman32 and the URL to the page was "/index.php?title=User:dandaman32", then contentPath = "/index.php?title=".
  • ENANO_ROOT - the root path of Enano, relative to the server's filesystem, without the trailing slash. Use for including files.
  • ENANO_INSTALLED - defined in config.php, if this is not defined, Enano is halted at a very early stage.

Valid namespaces and their IDs

  • Special namespace, used for pages that require a lot of custom code.
    • ID: "Special"
    • URL prefix: "Special:"
  • Admin namespace, identical to Special but with a different name.
    • ID: "Admin"
    • URL prefix: "Admin:"
  • Article namespace, used for the vast majority of pages.
    • ID: "Article"
    • URL prefix: "" (nothing)
  • User namespace, for user pages:
    • ID: "User"
    • URL prefix: "User:"
  • File namespace, used for uploaded files (not yet implemented)
    • ID: "File"
    • URL prefix: "File:"
  • Help namespace, identical to Article except for the name
    • ID: "Help"
    • URL prefix: "Help:"
  • System namespace, used for system messages
    • ID: "System"
    • URL prefix: "Enano:"
  • Template namespace, used for templates (not yet implemented)
    • ID: "Template"
    • URL prefix: "Template:"
  • Category namespace, used for category pages:
    • ID: "Category"
    • URL prefix: "Category:"
  • Project namespace, identical to Article except for the name
    • ID: "Project"
    • URL prefix: site name, with all spaces replaced with underscores

Difference between IDs and URL prefixes?

The URL prefix is what the user sees. It can be changed. The ID is used internally by Enano and should never be changed. To get the URL prefix of a namespace, use $paths->nslist['Namespace ID'].

Client-side stuff

If you haven't noticed, Enano has a huge assortment of client-side scripts that handle everything from AJAX to Z-index management. A guide to the Javascript part of Enano can be found at the Javascript API page.

That's it!

There you have it, a short (well sortof...) description of the Enano API for plugin developers. Hopefully you guys can all start developing plugins now ;).

Your browser does not support CSS.

If you can see this text, it means that your browser does not support Cascading Style Sheets (CSS). CSS is a fundemental aspect of XHTML, and as a result it is becoming very widely adopted by websites, including this one. You should consider switching to a more modern web browser, such as Mozilla Firefox or Opera 9.

Because of this, there are a few minor issues that you may experience while browsing this site, not the least of which is some visual elements below that would normally be hidden in most browsers. Please excuse these minor inconveniences.