Shannon Weyrick
Roadsend, Inc.
Jon Michel
Roadsend, Inc.
Roadsend PHP SiteManager by Shannon Weyrick and Jon Michel 2.2.x Production Series Edition Copyright 2001 by Roadsend, Inc.
Table of Contents
1. Introduction......................................................................................................................................................................................6 Overview....................................................................................................................................................................................6 Feature Summary .......................................................................................................................................................................6 About Roadsend.........................................................................................................................................................................8 2. General Information ......................................................................................................................................................................10 Version Numbering ..................................................................................................................................................................10 File Extensions for SiteManager Resource Files .....................................................................................................................10 Security Concerns ....................................................................................................................................................................10 Directory Layout......................................................................................................................................................................11 3. SiteManager Fundamentals ..........................................................................................................................................................12 SiteManager Global Variables .................................................................................................................................................12 SiteManager Root Object ($SM_siteManager) .......................................................................................................................13 loadSite Method ...........................................................................................................................................................13 loadModule Method.....................................................................................................................................................13 includeModule Method................................................................................................................................................14 rootTemplate Method...................................................................................................................................................14 loadTemplate Method ..................................................................................................................................................14 loadCodePlate Method.................................................................................................................................................15 dbConnect Method.......................................................................................................................................................15 startSessions Method ...................................................................................................................................................15 addPersistent Method...................................................................................................................................................15 completePage Method..................................................................................................................................................15 fatalDebugPage Method...............................................................................................................................................16 Global Conguration System...................................................................................................................................................16 getVar Method..............................................................................................................................................................17 getSection Method .......................................................................................................................................................17 setVar Method ..............................................................................................................................................................18 Variable Replacement ..................................................................................................................................................18 Section IDs..................................................................................................................................................................19 SM_Object Base Class.............................................................................................................................................................20 ......................................................................................................................................................................................20 Internationalization Support.........................................................................................................................................20 Directive Scripts.......................................................................................................................................................................21 Modules....................................................................................................................................................................................22 Overview......................................................................................................................................................................22 moduleCong Method .................................................................................................................................................22 moduleThink Method...................................................................................................................................................25 canModuleLoad Method..............................................................................................................................................26 Database Connectivity .................................................................................................................................................27 Session Functionality ...................................................................................................................................................28 Module within Modules...............................................................................................................................................29 Extending Your Modules .............................................................................................................................................29 preThinkList and postThinkList ..................................................................................................................................30 InVar Propagation (read-write inVars) .........................................................................................................................33 Multilingual Support....................................................................................................................................................33 Module Design Tips.....................................................................................................................................................34 Templates .................................................................................................................................................................................34
Templates within Templates (sub-templates)...............................................................................................................36 CodePlates................................................................................................................................................................................36 SmartForms..............................................................................................................................................................................39 Usage............................................................................................................................................................................39 Create a New Form ......................................................................................................................................................39 Congure Form............................................................................................................................................................40 Add Elements...............................................................................................................................................................40 Loading a SmartForm ..................................................................................................................................................41 Conguring Elements ..................................................................................................................................................42 Run Form and Input Validation Check ........................................................................................................................42 Form Templates............................................................................................................................................................43 Hidden Variables..........................................................................................................................................................44 Session Aware Forms...................................................................................................................................................45 Session Management ...............................................................................................................................................................45 Conguring Sessions ...................................................................................................................................................45 Using Sessions .............................................................................................................................................................46 Member Login Sessions...............................................................................................................................................47 Database Connectivity .............................................................................................................................................................49 Database Connection Settings......................................................................................................................................50 Multiple Database Connections ...................................................................................................................................50 Error Handling and Debugging................................................................................................................................................51 DebugOnVar ................................................................................................................................................................51 JavaScript Debug Window ...........................................................................................................................................52 Helpful Debug Routines ..............................................................................................................................................53 Miscellaneous Routines ...........................................................................................................................................................53 4. Designing a SiteManager Site By Example .................................................................................................................................54 Assess Site Needs ....................................................................................................................................................................54 Determine Separation of Static Layout from Dynamic Content..............................................................................................55 Determine Method of Splitting Dynamic Content Into Modules ............................................................................................56 Determine Site Plan .................................................................................................................................................................56 Implement Site Plan.................................................................................................................................................................57 Site Conguration ........................................................................................................................................................57 Template Design ..........................................................................................................................................................57 Module Design:............................................................................................................................................................57 5. Using The Test Site.........................................................................................................................................................................59 6. Extending SiteManager .................................................................................................................................................................60 7. Frequently Asked Questions .........................................................................................................................................................61 8. Getting More Help .........................................................................................................................................................................62 A. Directive Lists ................................................................................................................................................................................63 Module Directives....................................................................................................................................................................63 Template Directives .................................................................................................................................................................64 SmartForm Directives ..............................................................................................................................................................64 Input Entity Directives .................................................................................................................................................66 Filter Directives............................................................................................................................................................66 B. File Formats ...................................................................................................................................................................................67 .XSM Resource Files ...............................................................................................................................................................67 SMARTFORM.............................................................................................................................................................67 SMLANGUAGE..........................................................................................................................................................67
Chapter 1. Introduction
Overview
SiteManager is an Open Source Web Application Framework that leverages the power of PHP and its Object Oriented features to create a powerful base library for all types of web applications. SiteManager was designed with PHP programmers and development teams in mind. It allows them to separate the process of web site design into four steps: code creation, layout design, site implementation and site management. Step 1. Code Creation. During code creation developers construct modules of reusable source code. The modules can be shared easily between projects and developers. SiteManager simplies creating, conguring, and maintaining code modules by providing a common framework and an integrated library of tools. The library includes database connectivity, user session management, error handling, security, SmartForms, and much more. Step 2. Layout Design. During layout design, standard HTML tags, style sheets, and SiteManager XML Area Tags combine to form a powerful template engine. This engine lets developers keep the HTML layout separate from the code modules that power it. SiteManager Area Tags are used to identify important sections of the layout to the template engine. Layout based templates give designers and graphic artists freedom to create and change the appearance of the entire site without worrying about breaking the sites functionality. Advanced SiteManager developers can take reusable layout design even further through the implementation of CodePlates. Step 3. Site Implementation. During implementation developers use directive scripts to assemble modules of code and template layouts into the completed web site that clients will see. Only a few line of code are required to select which template is used, add modules into specic areas of the template, and customize each module. Step 4. Site Management. In order to facilitate maintenance of the site, almost all of the top level settings are stored in global (system wide) and local (site specic) XML conguration les. These settings include database connection information, directory locations and all of the conguration options for sessions, debugging and default extensions. Once the site has been created you can utilize the Global Conguration System to make changes and upgrades safely. As a truly Open Source project, Roadsend PHP SiteManager includes full source code, which is clean and well documented.
Feature Summary
Module System Modules are the nucleus of a SiteManager web application. They are the functional blocks of code such as a search engine, tree menu, or data driven news display that make a web site interactive or original. SiteManagers powerful object-oriented system helps programmers to design reusable modules for their websites by allowing for run time conguration. This lets the same module do different things depending on the context in which it was called or the page that loaded it. Modules even can decide not to load at all. Modules also have embedded support for cascading style sheets, client side scripting and for the extensive library of SiteManager object functions such as database access, sessions, and SmartForms. While many PHP web programmers are busy reinventing the wheel, users of the SiteManager system will have access to a growing library of modules developed by the Open Source community. Template System To support team-oriented development of web applications, SiteManager uses a powerful template engine which separates HTML, graphics and layouts from functionality. The SiteManager template engine gives developers much more than a simple "search and replace" template variable system. Using SiteManager tags, a template denes arbitrary "areas" in which to place modules of code. These tags are interpreted by the SiteManager system. A template can load specic modules into areas or
Chapter 1. Introduction
use Directive Scripts and CodePlates to extend modularity even further. Templates can also be used recursively (sub-templates), or even used inside of a module. CodePlates CodePlates take the template system a step further. CodePlates solve the problem of having to duplicate code when you use a similar template/module layout scheme in multiple pages. CodePlates are templates that already have certain modules associated with their areas. These modules are congured inside of the CodePlate. A CodePlate can be loaded as the main layout template or added to an area in another CodePlate or Template. This functionality makes creating co brands with SiteManagers template engine fantastically easy. SmartForms To truly create a "dynamic" website, input must be continually gathered from the user. This creates the need for a consistent, structured way to setup an input form, validate input, and gather the information. Creating form elements and validating input by hand is always slow and tedious. SmartForms were created as a way to rapidly create an input form using predened input entities, validate the input using predened lters, and gather the information in a structured way. SmartForms includes all the standard input types (textbox, checkbox, select list, etc) as well as some not so standard, but still often used types (date select,combo box, state list, country list, etc). It also includes many predened lters (required, number, email, credit card, phone, regexp + more) that you can attach to any input entity. You can attach any number of lters to any input entity. And, SmartForms are "database-aware" - we include entities such as DB Select list, which populates a list from a database. All entities and lters are pluggable modules of code, where all you have to do to add a new entity to the system is drop it into the correct directory. When using a SmartForm, you never have to worry about creating elements or checking for input validity by hand. You dont even have to worry about outputting the form its all handled by SmartForms. All you do is dene the form, run it, and ask it if all input was valid. Database Connectivity Roadsend SiteManager uses the PEAR Database abstraction layer for database connectivity. It is included with all versions of PHP (v4 and above). It allows connectivity to a number of different databases through a common API. SiteManager includes a middle layer of functionality that allows the PEAR DB system to be integrated within the SiteManager system. Database settings and creation of the database object are consistent with the framework for SiteManager and the Global Conguration System. Once a database connection is dened in the GCS, it is usable by all SiteManager objects. Global Conguration System All core classes in SiteManager have access to the SiteManager Global Conguration System or GCS. Stored in XML les for easy access, the default options are rst set on a global level in the Global Conguration le. When you create a new site, you can override or augment the default options in a local conguration le. User Sessions SiteManager includes its own user session management routines. The session manager can use a database or the URL to store information on each session. Sessions are maintained with cookies or a session ID passed with all internal links. Session variables are automatically included when passing information through SmartForms and regular HTTP links. Session management is available with or without a database. All session variables can be serialized, allowing complex objects to be kept persistent. Related to the session management is the Member system. SiteManager includes full support for allowing members to "log in" to the site, and all modules know if the current session is a Guest or Member session.
Chapter 1. Introduction
Security SiteManager adds a layer of protection when accessing variables coming in from a web client. A module designer is able tell SiteManager what type of variable its expecting (for example, an integer), and SiteManager will fail to run the script if the value passed for that variable doesnt match the type expected. This limits the amount of damage a user can do by passing or changing passed script variables. Support Routines Many supporting routines are included with SiteManager to help create your web application. These include: Authorization Routines Data Manipulation Routines Error Handling / Debug Routines Security Routines Misc Support Routines Object Oriented Framework The SiteManager framework is extensively object oriented, to promote reusable code and easy maintenance. The SiteManager source code is clean and well documented. Open Source Roadsend SiteManager is an Open Source project. The entire system may be distributed and used freely. The source is freely available for all to learn, review and change. Please read the license agreement available in the le LICENSE in the /doc directory, or on the web at http://www.roadsend.com/license/rpl1.txt We actively encourage all hackers to help us maintain and grow the project. Please see CONTRIBUTE in the /doc directory for more information. We continue to build our community of developers who are activity creating Modules, SmartForm Entities and Filters, example sites, and helping with maintenance of the project. In this way we will ensure SiteManagers continued growth as the leading Web Application Framework for PHP.
About Roadsend
Roadsend, Inc. is based in Fishkill, NY. We provide hosting and consulting services for Web business applications. Our website is http://www.roadsend.com, and you can reach us at <info@roadsend.com> Roadsend made the switch from PERL to PHP as its main web programming language back in 1998 around the time 3.0 was coming out. From then on it was obvious PHP would make a quick rise to the top as the best (and of course freely available) website development language. Over the course of 3 years, Roadsend developed many websites and libraries to support them. Eventually it became necessary to switch to a more structured, modularized framework. SiteManager has grown out of that system. Commercial support is available. Please see the main Roadsend website, or send us mail. The primary authors of Roadsend SiteManager are: Shannon Weyrick (<weyrick@roadsend.com>) Jon Michel (<pym@roadsend.com>)
Chapter 1. Introduction
Roadsend would like to thank all who have contributed to the project. For a full list of contributors, please see doc/THANKS in the distribution.
Security Concerns
We recommend you make all of the SiteManager Resource Files unreadable by the webserver, except ".php" les. The rest are not meant to be seen by users. The following line will accomplish this in Apache:
# dont allow access to SiteManager files <FilesMatch "\.(inc|tpt|stp|mod|xsm|cpt)$"> Order allow,deny
10
Directory Layout
Every site run by SiteManager has a common directory structure (on UNIX, this is commonly found in /var/www/myProject or /home/httpd/html/myProject)
/ /admin /modules /templates /smartForms /config /codePlates /locale /home (root) (admin / config directory) (local site modules) (local site templates) (local site smartForms) (local site configuration files) (local site codePlates) (localization files) (main page directory)
All les in /admin should be protected from reading by the webserver. None of these les located in this directory or its subdirectory should be readable by a user requesting them through the web. The best way to stop this is the stop the webserver from reading the le types found in these directories. Alternatively, you can tell the webserver not to serve any les under the admin/ directory. For even better security, you can move the directories underneath admin/ to a directory outside of the web document root. This is the most secure, as conguration les will then be unavailable to web clients. The only required le in the web root will be common.inc, which will be accessed by the directive scripts. If you need to, common.inc can be renamed to common.inc.php (just make sure your directive scripts access it this way!). SiteManager itself contains the following directory structure (on UNIX, this is commonly found in /usr/local/lib/php/)
/ /bin /cache /config /doc /lib /sfFilters /sfInputEntities /modules /skeletonSite /smartForms /tables /templates /testSite - (root) - (binary files/scripts for maintenance and automation) - (resource cache directory) - (configuration files, ie globalConfig.xsm) - (documentation, LICENSE, etc) - (main lib directory) - (SmartForm filters) - (SmartForm input entities) - (SiteManager core modules) - (skeleton site used for template when creating new site) - (site wide SmartForms) - (SQL table creation scripts) - (SiteManager core templates) - (Fully functional test site)
11
The root SiteManager class. Use this class for high level control of the site, such as starting the Database and Session systems, Loading a Module, or Loading the Root Template. You will use this object frequently throughout your SiteManager site.
$SM_siteID
This is the unique site ID for your project. It should be dened in admin/common.inc. It is used for conguration and debug purposes. It is arbitrary, but all capital by convention. It can only contain letters and numbers, and can not contain white space. An example siteID is TESTSITE. Note that this siteID MUST match the <SITE NAME=> tag from your projects config/localConfig.xsm le!
$SM_siteName
This is the site name for your project. It is arbitrary free-text, used for debugging purposes. It may contain white space. An example $SM_siteName is Test Site 1
$SM_sessionVars
A string that contains the current valid session parameters, useful for using as GET parameters to a script. All registered persistent variables will show up here. See also SM_session::getSessionVars(), which will update this variable to the latest session values and return a copy of itself.
$SM_debugOutput
An array with debug information. Each time a call to SM_debugLog is made, and new item is added to the array. You shouldnt need to access this array directly. See the ERROR HANDLING section for more information.
$SM_rootDir
If you dont want to - or cant - place the SiteManager directory into the PHP include path, you can set this variable in
siteManager.inc. Point it to the main SiteManager root directory, and SiteManager will be able to nd its library les. $SM_develState
The current value (true or false) of the develState ag from the GCS variable "debug" SECTION of the GCS. Use this ag in an if block when you want debug information to show up only when the develState ag is on. This is useful for limiting the amount of debug information that shows up on a production server.
$SM_defaultLocale
The current value of the defaultLocale variable from the GCS variable "localization" SECTION the GCS. It determines the site wide default locale.
12
$SM_clientLocale
A string (or possibly an array of strings) of the values retrieved from the HTTP_ACCEPT_LANGUAGE server variable. It will contain a list of locales the current client is using. It can used to determine which language should be used for output, for example. It is automatically used by the getText() method of SM_object to determine the default language.
$SM_debug
If debugOnVar is true in the GCS, and this variable is set to (int) 1, SiteManager will generate debug output before the main page output. See the Error Handling and Debugging section for more information.
Loading a Module Loading Layout Templates Starting the Database System Starting the Session System Accessing the Global Conguration System Debugging
What follows is a partial list of methods you may access from $SM_siteManager. For further documentation on these methods and others available through $SM_siteManager, consult the SiteManager API Documentation, available on the web at http://www.roadsend.com/siteManager
Return By Reference
Several methods in the SiteManager system return values by reference: you must use the reference assignment operator ( =& ) as in the examples shown in order to congure and use the objects returned properly. For more information on this, see the PHP documentation: References Explained (http://php.net/manual/en/language.references.php)
loadSite Method
loadSite($file)
Call this method to load in local conguration settings for your site. This is usually done in admin/common.inc See the next section, Global Conguration System, for more information on this. Also, have a look at the example common.inc in skeletonSite/admin/ directory. Note, you may call this more than once to load multiple conguration les.
Note: The <SITE NAME=siteID> tag in this le must match the $SM_siteID you dene in admin/common.inc!
13
loadModule Method
&loadModule($moduleFile, $moduleName=)
Call this method when you wish to load and create an instance of a module. See the Directive Script and Module sections for more information on why and when you would want to do this. This function will look through your module paths (as dened in the Global Cong System) for the le named $moduleFile (automatically adding a ".mod" extension). If the actual class name of the module is different from the le name of the module, you must specify its name in $moduleName. For example, if the module le name youre loading is testModule.mod, but the module class is myTestModule, you must use the following command:
$module =& $SM_siteManager->loadModule(testModule,myTestModule);
If you wish to load a module thats contained in the le testModule, and the class name is also named testModule, you may use simply:
$module =& $SM_siteManager->loadModule(testModule);
The one exception to this rule are modules that are prexed with "SM_". These modules are part of the SiteManager package, such as "SM_rawHTML". The le is located in <SM_DIR>/modules/rawHTML.mod, but the class name is SM_rawHTML. Normally you would have to solve this discrepancy by using both parameters of loadModule(), but in this case, it will nd and load them correctly without. For example, to use the SM_rawHTML module you need simply:
$htmlMod =& $SM_siteManager->loadModule(rawHTML);
See the Module System section and example scripts for more information.
includeModule Method
includeModule($moduleFile)
Call this method when you wish to load a modules denition, but not create an instance of it. This is generally used when you need a modules denition available because you are extending it to create a new module. See the Module System section for information on Extending Modules.
rootTemplate Method
&rootTemplate($fName)
Call this method to set the root HTML layout template for use. It will search the template paths (as dened in the Global Cong System) for the template le $fName (automatically adding .tpt extension for you) Example:
$rootTemplate =& $SM_siteManager->rootTemplate(basicTemplate);
The root template may also be a CodePlate. See the Template System section and example scripts for more information.
loadTemplate Method
&loadTemplate($fName)
14
Call this method to load an HTML layout template. You should only call this method directly if you plan of loading a template to place inside of another template (see the Templates section for more information on templates within templates) or from inside a module. Otherwise, you should be using rootTemplate() to load a single root template. This method will search template paths.
loadCodePlate Method
&loadCodePlate($fName)
Load a CodePlate for use. CodePlates are extensions of regular templates see the CodePlate section for more information. This method will search the codePlates paths.
dbConnect Method
dbConnect()
This method sets up database connection(s) for the rest of the system to use. It will use the database settings found in the Global Conguration System. This method does not take parameters, nor does it return anything. It should simply be called once (usually in common.inc) to create the database connection(s). See the Database Connectivity section for more information.
startSessions Method
startSessions()
This method starts sessions. It should be used when you wish to keep certain variables persistent between links and forms, or to use the member system. You almost always want to use this, and it should be called in common.inc. See the Sessions section for more information.
addPersistent Method
addPersistent($varName)
Use this method to specify that a variable should be kept persistent throughout the system. It should be called only after startSessions() is called. For example, if you would like to keep the variable "userName" persistent for a user:
$SM_siteManager->startSessions(); $SM_siteManager->addPersistent(userName);
All session-aware modules will now keep this variable intact automatically, as soon as it gets a value. Note, you may also setup persistent variables in the Local Site Conguration le. They should be in the "pVars" SECTION see the Global Conguration System section, or the testSite/admin/config/localConfig.xsm example le for more information. Depending on your session conguration, the variable type of the persistent variable value can be any valid PHP type (string, int, array, object, etc). See the Sessions section for more information.
15
completePage Method
completePage()
This method should be the last method called in a Directive Script. It runs all modules, collects their output, and inserts it into the templates. See the Directive Script section for more information, or look at the example scripts in skeletonSite/ and testSite/ directories.
fatalDebugPage Method
fatalDebugPage()
This method will generate a very informative debug page. It should be called in place of completePage() ie, AFTER all modules have been added and congured. Instead of showing the nal HTML output as completePage() does, it will show all information on how the page WOULD have been generated. That is, it will list all Global Conguration data, what templates are in use, which modules are loaded, how the modules are congured, what SmartForms are in use in these modules, and how the SmartForms are congured. This function should not be used on live production sites.
conguration les as you like. Conguration les can be cached - see the section on caching for more information. Every site that uses SiteManager is assigned a SITEID ($SM_siteID). This ID is used by the conguration system to determine which settings to use for this site. It is also used by the debug system when outputting errors and warnings.
$SM_siteID should be assigned in admin/common.inc BEFORE siteManager.inc is included.
SiteManager uses a custom XML le to describe conguration values. Conguration is basically a list of key/value pairs, broken up into various sections. Section examples include:
dirs localization db flags directory settings localization settings database settings misc flags
16
sessions pVars
The easiest way to explain the settings is to take a look at the XML le that actually stores the variables:
<SITE name="GLOBAL"> <SECTION name="dirs"> <VAR name="base" value = "/usr/local/lib/php/siteManager"/> <VAR name="libs" value = "/usr/local/lib/php/siteManager/lib"/> <VAR name="modules" value = "/usr/local/lib/php/siteManager/modules"/> <VAR name="modules" value = "/usr/local/lib/php/siteManager/modules/test" /> </SECTION> <SECTION name="db"> <VAR name="dbType" value = "mysql"/> <VAR name="persistent" value = "true" /> </SECTION> <SECTION name="pVars"> <VAR name="SMuserName" value = "" /> <VAR name="SMaddDate" value = "" /> </SECTION> </SITE>
This excerpt from globalConfig.xsm shows 1) how the XML structure is laid out 2) how variables are dened. To access a variable from $SM_siteManager->siteConfig in module code, you would use one of two function calls:
getVar Method
$SM_siteManager->siteConfig->getVar($section, $name, $mergeGlobal=false, $sectionID=)
This function should be used when a single variable is required. For instance, to retrieve the main lib directory from section dirs, you would use:
$libDir = $SM_siteManager->siteConfig->getVar(dirs,libs); $libDir would then be a single string variable that contains the main lib directory.
Notice you can list VAR names more than once in the cong le (such as the modules VAR in the example above). When this happens, an array is created. For example, to get the two modules directories from the global cong you would use:
$moduleDirs = $SM_siteManager->siteConfig->getVar(dirs,modules); $moduleDirs is now an array of values that contains the two values listed in the conguration le.
The $mergeGlobal option is used to tell the SM_config object whether you want to just use the LOCAL settings, or both the GLOBAL and LOCAL settings. Usually, you want the local settings to override global settings, but sometimes youd like to have both. Use this option to control that. When set to TRUE, you will receive an array of values that consists of all values set for that variable name in both GLOBAL and LOCAL context. The $sectionID is used when a section denes itself multiple times, with different IDs. If you need to, you can use this parameter to specify which ID youre accessing. Normally, you can leave this parameter off. See the section below regarding multiple IDs.
17
getSection Method
$SM_siteManager->siteConfig->getSection($section, $sectionID=)
This will return a hash that can be used in the following way:
$dbType = $dbSettings[dbType]; $pers = $dbSettings[persistent];
This function automatically merges GLOBAL and LOCAL settings. The $sectionID is used when a section denes itself multiple times, with different IDs. If you need to, you can use this parameter to specify which ID youre accessing. Normally, you can leave this parameter off. See the section below regarding multiple IDs.
setVar Method
You may also SET a variable through the global conguration system. This can be used to override a value read in from the cong le.
$SM_siteManager->siteConfig->setVar(dbSettings,dbType,mysql);
Note: You cannot change GLOBAL variables this way (only those LOCAL to this siteID)
Variable Replacement
To increase maintenance and portability, you can use variable replacement in all SMCONFIG les. Once you dene a VAR name/value pair, you may substitute the value in at a later time, by accessing much the same way you do as PHP variables. This is the way the globalConfig.xsm and localConfig.xsm les are done in the "dirs" SECTION:
<SECTION name="dirs"> <VAR name="smRoot" <VAR name="base" <VAR name="config" <VAR name="libs" <VAR name="modules" <VAR name="templates" <VAR name="smartForms" <VAR name="sfEntities" <VAR name="sfFilters" </SECTION>
= = = = = = = = =
"/usr/local/lib/php/siteManager/" /> "{$smRoot}"/> "{$base}config/"/> "{$base}lib/"/> "{$base}modules/"/> "{$base}templates/"/> "{$base}smartForms/"/> "{$base}lib/sfInputEntities/"/> "{$base}lib/sfFilters/"/>
18
By default, variable substitution only works for variables dened within the current SECTION. To reference a variable from another section, use the format:
<SECTION name="firstSection"> <VAR name="testVar" value = "value of testVar" /> </SECTION> <SECTION name="secondSection"> <VAR name="otherTestVar" value = "{$firstSection.testVar}" desc="sets value to value of testVar from SECTION firstSection" /> </SECTION>
In addition, if you try to use a variable that wasnt dened beforehand in this le, it will automatically attempt to substitute the current global PHP value of that variable. that means you can substitute in any PHP or server environment variable. You can also use an associative array (hash) in this context. For example:
<SECTION <VAR <VAR <VAR
... etc
Section IDs
It is possible for SECTIONs to be dened multiple times, if you specify an additional attribute (id). You may then either 1) Specify a sectionID when accessing that section (or a variable in the section), in which case you would receive only the value from the variable in the sectionID you requested or 2) Dont specify a sectionID, in which case you would receive the value of the variable you requested from all IDs, merged into one array (so that it appeared that there was only one section with multiple variables specied with the same name). This is used, for example, by the db section to dene multiple database connections:
<SECTION name="db" id="default"> <VAR name="dbType" value="mysql" /> <VAR name="defaultConnection" value="true" /> <VAR name="DSN" value = "mysql://testUser:testPass@localhost/test" /> <VAR name="persistent" value = "true" /> </SECTION> <SECTION name="db" id="secondary"> <VAR name="dbType" value="mysql" /> <VAR name="DSN" value = "mysql://testUser:testPass@localhost/test" /> <VAR name="persistent" value = "true" /> </SECTION>
If youre not accessing a section with multiple ids, you dont have to worry about this feature (leave that parameter blank when calling getVar() or getSection())
19
$directive. $directive is a standard associative array ie, a list of key/value pairs. It is used to congure the object. addDirective(), configure(), and loadConfig() all work to setup this array. Therefore, any object that inherits this class, such as SM_modules, can be congured through:
$module->addDirective(key,value);
This system is used extensively throughout SiteManager, and we recommend using it as an alternative to class variables when creating modules and other code. There are benets to doing so: 1. Its easier to create reusable code, because classes that have several parent classes are easier to maintain and congure 2. Common, expandable system for dening a conguration scheme for objects 3. Key/value pairs can be loaded from an XML le using built in methods 4. You can pass and receive directives easily from other objects that descend from SM_object $dbH. This variable is a reference to the current database handle. This is used by the module system, SmartForms, etc. as a common way to access the default database connection. $dbHL. This variable is a hash of all available database connections, indexed by the connection ID. If database support is on, there should be at least one entry with the index default. See the Database Connectivity section for more information on using this. $sessionH. This variable is a reference to the current session manager, if available. Its is an object of type SM_session. See Session Management section for more information. $classLog. This variable is an array that contains a list of debug messages for the class. It is populated with the SM_object::debugLog() method, and displayed with the SM_object::getClassLog() method. $liText. This variable is a multidimensional hash that stores different translations of text the object will use for output. It has two keys: [$locale][$textID]. It is populated with the SM_object::loadLanguage() method, which reads information from an XML le. You should not access this directly, however use the getText() method instead.
20
Internationalization Support
All SM_object descendants (include Modules, SmartForm entities, etc) include support for internationalization - currently, the ability to support multiple languages for output. This is done by loading an XML based language description le. The le is organized so that each block of text to be displayed is assigned an arbitrary ID string, and then listed multiple times in the le in different language sections, translated accordingly. The text may then be retrieved with the getText() method, in the desired (or default) language, by its ID string, and nally written for output. Because of the format of the XML le, translations can be added at any time, allowing for great scalability. The code need not change at all when a translation is added, since the block of text will still be accessed by the same ID string. For the le format of the XML language le, see Appendix B. For an explanation of using the loadLanguage() and getText() methods, see the Module section under Multilingual Support.
Directive Scripts
Directive scripts are the high level link between Modules and Templates. They are described here so that as you go through the Modules and Template section, you can better understand the parts they play. A directive script is an actual "page". It will be the script that the webserver loads rst when an URL is accessed. The directive script is generally very short - in fact, as a general rule, you want to do as little logic here as possible. Its job is to: 1. Include the sites common.inc, which in turn sets up the conguration for this site and includes the SiteManager libraries 2. Load the modules to be included in this page 3. Congure the modules 4. Load the template(s) or CodePlate(s) to be used for this page 5. Add the modules to the correct areas in the correct order 6. Output the nal page Generally, depending on the amount of conguration to be done to the modules, this can be done in 10-15 lines of code. When the command is given to "run" the page and output it, the following happens: 1. All modules run through their conguration routines (moduleConfig()) 2. All modules run through their "think" routines (moduleThink()) 3. HTML and JavaScript output is collected from each module 4. The output from the modules is placed in the proper areas in the template A sample, annotated directive script follows (yes this is the entire page):
<?php
// include site configuration file, which includes siteManager libs include(../admin/common.inc); // create a new module. notice, returns a reference!!
21
$mod1 =& $SM_siteManager->loadModule(rawHTML,SM_rawHTML); // configure the module $mod1->addDirective(output,<B>Hello World</B>); // create root template. notice, returns a reference!! $layout1 =& $SM_siteManager->rootTemplate("basicTemplate"); // add our module to area areaOne $layout1->addModule($mod1, "areaOne"); // finish display $SM_siteManager->completePage(); ?>
Modules
Overview
Modules are pieces of code that get executed so that their output is placed into a template. All modules are extended from the same base class, and have a common structure. The base class for all objects is SM_module Extending this class to create a module gives that object several important features: 1. It allows the new object to be added to a template or codePlate, where its output will be added into an area of the template 2. It sets up the object to receive input from SmartForms and other modules 3. It allows the object to create and use a SmartForm 4. It allows JavaScript code to be taken from this module and included with the main JavaScript output section of the template this module will show up in 5. It allows code to use the database and session systems available through SiteManager All modules, upon creation, are assigned a Module Prex. This prex is used by the system to differentiate between modules. It is used, for example, to avoid variable naming conicts when using modules that congure for themselves variables of the same name. The module prex is used behind the scenes, and generally should not have to be referenced at all. There is only one required method that must be implemented for the module to work:
moduleThink() - the "brains" of the module
moduleCong Method
For a module to be reusable in different contexts, it should be able to change its output and/or the way it looks when it outputs on the y. This means it needs to be congurable at run time through directive scripts (pages). Enter the moduleConfig() method.
22
One important difference between moduleConfig() and moduleThink() is that the moduleConfig() method is automatically run when a module is loaded through $SM_siteManager->loadModule(), and the moduleThink() method generally isnt run until $SM_siteManager->completePage() is called. This allows the user to re-congure any defaults that were dened in moduleConfig() before running the actual module. There are three main conguration options to be done in moduleConfig(). Of course, the module designer may do any conguration code they need in this space whats important is that this function is executed BEFORE the moduleThink() function. Here is a sample moduleConfig() method:
function moduleConfig() { // load base configuration files $this->loadConfig("moduleSettings");
// directives // these are defined and overridden by DIRECTIVE SCRIPTS $this->addDirective(tableName,); // table name to operate on $this->addDirective(maxVisibleSize,30); // max size of a form element (default) $this->addDirective(dataField,); // field to operate with (primary key) $this->addDirective(siteName,Test Site); // site name // variables this module will use for configuration (these are all made up and arbitrary) // thee are setup by GET and POST vars $this->addInVar(widgetType,0); // which widget type should we use? $this->addInVar(format,basic); // which "format" to use // styles we will use in this module $this->addStyle(linkText); $this->addStyle(baseText);
// style used when outputting HTTP links // style used for plain text
// if this module requires database functionality, // check for a proper connection if (!isset($this->dbH)) { SM_fatalErrorPage("this module requires a database connection, which wasnt present!"); } }
Directives. Often a module designer wishes to let the user congure how the module should act, such as whether it should output in a table, whether it should be run in "advanced" or "basic" mode, whether it should end the script after a form loads or transfer to another page, etc (all arbitrary examples). These settings are done through the $directive variable and addDirective() method. Setting a directive involves using the functionality inherited from SM_object. For example, to add a directive to a module:
$mod1->addDirective(siteName,Test Site);
Using a directive in the module code is as easy as referencing the $directive hash variable. For example, the code:
$this->say("Welcome to {$this->directive[siteName]}!");
23
It allows others to use the module and congure it without ever having to look at the internals of the way it works. You may also use the loadConfig() method inherited from SM_object. It allows you to have an external le that denes directives. If you are going to use loadConfig(), you should call this rst in moduleConfig(), so that later addDirectives will override those loaded in the external cong le. Using loadConfig(), you can setup certain directives that ALL modules should use such as "tableBorder" or other cosmetic options. Then, simply call loadConfig() in each of your modules. This way you only have to dene those options in one place, and when they need to change, you can change them all in one place. See the SM_object section for more information on
loadConfig()
Tip: Directives are different from INVARS (described below) in that they are meant to be congured and overridden by a programmer who is using the module to create a page.
inVars. If the module is to take any input (ie, from HTTP_POST_VARS of HTTP_GET_VARS) it must declare which variables it will be looking for using the class variable $inVar and method addInVar() It must declare inVars for several reasons:
SiteManager will be able to check the inVar for correct typeness. This allows SiteManager to (for example) make sure the integer variable youre expecting in variable foo wasnt actually passed as a string. This is a good security measure when youre taking a integer variable that will be used as an index in an SQL query, and you want to make sure someone isnt intentionally making the value a string of SQL commands. SiteManager will be able to check for conicts with other modules in the page. If you happen to be using two modules with the same inVar, but they are meant for different uses, SiteManager can warn you SiteManager will be able to keep variables from different modules who werent designed to work with each in tact. This allows you to place modules into a page without the modules worrying about passing variables they werent designed to know about. You access persistent session variables from your module by declaring an inVar with the same name as the declared persistent. You can access SmartForm variables passed from your forms in your module.
For example, if a module is expecting a "widget type" to be passed to it, through the "widgetType" variable such as: http://localhost/testScript.php?widgetType=5 then it should declare that it will use this variable in moduleConfig():
$this->addInVar(widgetType,0,int);
The second parameter is the default value to use, if one wasnt passed to the script. If this parameter is left blank, the default value is blank. The optional third parameter tells SiteManager that widgetType should be a number. If the script is called and widgetType is set, but its actually a string value, SiteManager will not let the script load. This is a security measure. Also see the section below about Propagating InVars.
Note: Variables passed to scripts should NOT be accessed directly, as in:
global $widgetType; - or -
24
$HTTP_GET_VARS[widgetType];
Again, using this system lets the module system handle naming conicts, session variables, and other behind the scenes voodoo.
Tip: INVARS are different from Directives in that they are meant to be variables that change based on how the script was accessed, ie they get setup either through GET or POST variables passed to the script, or through session code.
Styles. In order to promote re-usability, and module should be able to output itself in a manner thats congurable without touching the internals of the module. One way to do this is by using CSS Style Sheets when outputting HTML. This allows a user to use the module and change the way it looks simply by dening certain style sheet elements in their template. This way, they never have to touch the module code. All styles to be used in a module should be declared, in much the same way as INVARS, but with the addStyle() method:
$this->addStyle(headingText); // style used when outputting section headings $this->addStyle(linkText); // style used when outputting HTTP links
A module has a hash called $style. It contains a key/value pair that links two properties: 1. Internally named style sheet element 2. Externally named style sheet element This is done so that the module can reference a particular style sheet element name that may change later, when the module is congured. For example, if the module is to output a text or a link:
$this->say(<A HREF="test.php" CLASS=".$this->getStyle(linkText).">Test Link</A>);
$this->getStyle and $this->say reference the internal name of the style but later on, when the module is congured, the actual style sheet name it outputs may change. For example, then the user congures the variable in the Directive Script (page), they may wish to change "headingText" to be "boldRed", which is what they have dened in their style sheet:
$mod1->setStyle(headingText,boldRed); $this->say("Section One: Test Information","headingText");
When the module is run the following is displayed: <SPAN CLASS="boldRed">Section One: Test Information"</SPAN>
moduleThink Method
The required method to implement for a module is called moduleThink(). This method is what gives the module functionality. Here is a simple example:
function moduleThink() {
25
When this module is run, it will buffer output. NO MODULE SHOULD EVER USE echo or print! This is because the module must save its output for later when it will be placed into the correct area of the template.
Warning
A Module should never echo or print output!
Instead of echoing output, use the method say() or saybr() thats part of the SM_module class:
$this->saybr("This is module output");
DO NOT use:
echo "This is module output";
All output in SiteManager is buffered, so you wont see echoed output unless you have Debugging output turned on. See the Debugging section for more information on that. Another (special) method of output is the sayJS() function. This is used for the module to output JavaScript code. It requires its own function so that the JavaScript code shows up in the correct JavaScript area of the template. sayJS() works just like say(). You do NOT have to include any <SCRIPT> tags when using sayJS, the module system does this for you. See the Template section for more information on this. Other than that, the moduleThink() code may do anything youd like. You of course have the full power of PHP and all its extensions at your disposal. Here is a list of SiteManager helper functions that will be useful when designing modules. See the SiteManager API for more information on each method.
$this->say(); $this->saybr(); $this->sayJS(); $this->getVar(); $this->newSmartForm(); $this->getStyle(); $this->getText(); $this->directive[];
- use to buffer module output - use to buffer module output with a <br> tag - use to buffer JavaScript output - use to access a variable declared as an INVAR - create a new SmartForm for this module (see SmartForm section) - retrieve a style sheet element name - use to retrieve language independent text by ID - retrieve a directive
canModuleLoad Method
Sometimes a site designer will want to load and display a module only under certain circumstances - for example, if a particular variable was passed to the page. One way to do this is add logic code either to a directive script or a CodePlate that decides when to load and add the module to the template.
26
It can be more convenient, however, to always load the module in the directive script, and let the module itself decide whether it should display itself or not. This is a more portable method, as the module has full access to inVars and session variables, and you wont need to worry about adding display logic to every directive script you use this module in. For a module to decide not to display, it must implement the canModuleLoad() method. If this method exists, it is run after moduleCong, but before moduleThink. This allows it to be congured through directives, and allows access to declared inVars. The method should return either true or false. If it returns true, the module will run its moduleThink() code as normal. If it returns false, the moduleThink code will not run, and no output will be displayed by the module. Here is an example (module excerpt):
/** * configure the module. run before moduleThink */ function moduleConfig() { // Directives $this->addDirective(tableBorder,1); $this->addDirective(tableBgColor,#eeeeee); $this->addInVar(menuID,0,int); } /** * * only load if our inVar is set to 8 * */ function canModuleLoad() { return ($this->getVar(menuID) == 8); }
In this example, the module would only display itself if menuID were passed to the script, it was a number, and the value was 8.
Database Connectivity
Accessing a database in the modules is easy. When you extend the SM_module class, a class variable called $dbH is available automatically. Either this variable is NULL, in which case there is currently no available database connection, or it is a reference to the current default database connection. There is no need to make a connection by hand in a module. If your module requires access to a database, you should check for connectivity in moduleConfig, using:
// if this module requires database functionality, // check for a proper connection if (!isset($this->dbH)) { SM_fatalErrorPage("this module requires a database connection, which wasnt present!"); }
27
Then, in moduleThink(), you are guaranteed access to the database. You may use $this->dbH as a normal PEAR Database object. For example:
$SQL = "SELECT * FROM testTable"; $rh = $this->dbH->simpleQuery($SQL); if (DB::isError($rh)) { SM_debugLog($SQL,$this); SM_fatalErrorPage("There was a problem with the query!"); } while ($rr = $this->dbH->fetchRow($rh)) { $this->say($rr[firstName].<br>); } $this->dbH->freeResult($rh);
Youve now just written a data aware module that can be used in any SiteManager system, and on any database system that PEAR supports. Multiple Database Connections. SiteManager has the ability to have more than one active database connection. $this->dbH is always a pointer to the default database connection. If you wish to access a database connection handle other than the default, you use the $this->dbHL hash, and reference the database ID, such as:
$SQL = "SELECT * FROM testTable"; $rh = $this->dbHL[secondary]->simpleQuery($SQL); if (DB::isError($rh)) { SM_debugLog($SQL,$this); SM_fatalErrorPage("There was a problem with the query!"); } while ($rr = $this->dbHL[secondary]->fetchRow($rh)) { $this->say($rr[firstName].<br>); } $this->dbHL[secondary]->freeResult($rh);
See the Database Connectivity section for more information on setting up and accessing multiple database connections.
Session Functionality
Much like the database functionality, session functionality is contained automatically in the variable $this->sessionH To make your modules "session-aware", you should use the hLink() method.
hLink($link, $text, $class=, $extra=) hLink() will make a <A HREF> link to $link, around text $text. It will use a style of $class (from your $this->style array) if specied. $extra will place extra text into the <A> tag if you need it (such as TARGET="") hLink will automatically append the current session variables onto your link (even if $link contains variables of its own).
Using hLink() instead of hard coded $this->say("<A HREF=" .. tags will make your module session-aware. There are other session functions you may use in your modules, such as puLink() which will make your link show up in a JavaScript pop-up window. See the SiteManager API reference for the full list of available methods.
28
Take a look at the /modules directory for some examples of modules. Accessing Persistent Variables. To access a variable that has been declared as persistent variables with the session system, simply declare an inVar with the same variable name as the persistent variable. Then, use $this->getVar() method to retrieve it. Using this method, you can access strings, arrays, objects and any other variable you would like to keep persistent.
The code for the module to be loaded can be any normal module code. However, when designing a module to be run within other modules, make sure you turn off the outputInTable directive otherwise youll get two module tables inside of one module.
// (in sub-modules moduleConfig()) $this->addDirective(outputInTable,false);
29
function moduleThink() { // base think code, possibly blank } function extraFunction() { // extra base functionality } } class extendedModule extends testModule { function moduleThink() { // override custom base modules think function // call function from base module $this->extraFunction(); } } ?>
Normally, however, you wouldnt want to keep both the base module and the extended module in the same le. You might put the base module in a le called testModule.mod and the extended module in a le called extendedModule.mod - both in your sites modules/ directory. Note that when you do this, you must make sure that when you dene your extended module, it already knows the denition of your base module. You do this through the $SM_siteManager->includeModule() method. It will search your current module paths for the base module you specify. Note, however, you must declared $SM_siteManager global rst.
<? global $SM_siteManager; $SM_siteManager->includeModule(testModule); class extendedModule extends testModule {
function moduleThink() { // override custom base modules think function // call function from base module $this->extraFunction(); } } ?>
You can now call $SM_siteManager->loadModule() on your extended module in the normal way. For an example of extending modules, look in the testSite/admin/modules directory at base.mod and extendedMod.mod
30
/** * a base module. extends base SM_module class. * */ class baseMod extends SM_module { /** * configure the module. run before moduleThink */ function moduleConfig() { // configure which methods will be run automatically $this->preThinkList[] = moduleHeader; $this->postThinkList[] = moduleFooter; } /** * this function contains the core functionality entry point for the module. */ function moduleThink() {
31
} // this function will run automatically before moduleThink() // the designer of the extended module need not call it directly function moduleHeader() { // notice you can use directives here that may be setup by the extended module $this->say("<TABLE BORDER=1><TR><TD ALIGN=CENTER>{$this>directive[title]}</TD></TR><TD>"); } // this function will run automatically after moduleThink() // the designer of the extended module need not call it directly function moduleFooter() { $this->say("</TD></TR></TABLE>"); } }
/** * an extended module. extends baseMod class. * */ // include base module global $SM_siteManager; $SM_siteManager->includeModule(baseMod); class extendedMod extends baseMod { /** * configure the module. run before moduleThink */ function moduleConfig() { // configure parent::moduleConfig(); // other configuration here... $this->directive[title] = Extended Module Test; } /** * this function contains the core functionality entry point for the module. */ function moduleThink() { $this->saybr("This output is being displayed by the extended module. It is wrapped in a table generated by the base module");
32
$this->saybr("The generation of the table was done automatically through preThinkList and postThinkList methods"); } }
Multilingual Support
Because the Internet is a global network, your sites (and modules) need the ability to display in multiple languages. SiteManager handles this by allowing you to dene and load an XML language description le. The language XML le format is described in Appendix B. Once you have a language le dened, you load it into your module with the loadLanguage() method, which is inherited from SM_object. This method will search your "locale" paths. It may be called in either moduleConfig() or moduleThink(). After loading your language denitions, you use the getText() method to retrieve your text in the desired language, by the ID dened in the language le.
33
If you dont specify which language getText() should use, it will default to either 1) the preferred language of the current user on the site 2) the default for the site 3) the default for the module. To dene a default for the module, add a directive defaultLocale in the moduleConfig() section of your site. Once you have retrieved it, you may then say() the text as normal.
$this->loadLanguage(testSite.lang); $bText = $this->getText(text1); // browser detected language
$eText = $this->getText(text1,en_US); // test specification of English $dText = $this->getText(text1,da_DK); // test specification of danish $this->saybr("English: $eText"); $this->saybr("Danish: $dText");
See the Internationalization Support section of SM_object and Appendix B for more information.
should never exit, unless its a fatal error (and even then, call SM_fatalErrorPage()) or your transferring
to another script.
if calling header("Location: http://sampleUrl.com"), from within moduleThink(), make sure you exit(); afterwords dont use echo or print to output text for your module, use $this->say() or $this->saybr() use $this->hLink() for A HREF links to make your module "session-aware" make use of directives instead of hard coding conguration values into your module, so they can be congured later make use of loadLanguage() and getText() methods to add language independence to your modules
Templates
The template system is used to separate the module code from the way the nal page will look to the end user. SiteManager allows you to take a "template" of static HTML, dene arbitrary "areas", and dene which modules should go in which areas, and in what order. You may have as many areas as you like, and any number of modules in any area. You can also add other templates to areas (see Templates in Templates). A "template" is really just a static HTML le with a custom <SM> tag placed in them:
<SM TYPE="area" NAME="areaName"> <SM TYPE="module" NAME="moduleName" DIRECTIVES="key1=val1,key2=val2"> directly replace this tag with a module <SM TYPE="javaScript"> replace with JavaScript code collected from modules <SM TYPE="htmlTitle" NAME="Default Title"> replace with directive htmlTitle, or use default if undefined
- define an area -
34
<SM TYPE="htmlBody"> replace with HTML BODY tag, using directives bodyBGCOLOR, bodyLINK, etc @@sessionVars@@ special tag. directly replaces itself with current session variables
This simple template sets up 2 areas, a JavaScript area, and a footer module call. All area names are arbitrary. Here weve used "areaOne" and "areaTwo", we could just as easily have used "leftArea", "rightArea". The area name will be reference in the directive script, when you are adding modules. The javascript tag is optional, but if it appears it should be in the <HEAD> section of the HTML. This will allows modules and SmartForms to plug in javascript functionality.
@@sessionVars@@ is a direct search-and-replace convenience tag. It will replace itself with the current list of session variables (if
any). It exists so that one does not have to create a module merely to output static links with session variables included. If an area is listed in a template, but a module is not added to it by the time the page is displayed, the area tag is removed from the template and ignored. A template is loaded in the following fashion (usually in a directive script):
$template =& $SM_siteManager->rootTemplate(templateName);
This will search your template path for the requested template, and load it once found. From there you may add a previously loaded and congured module to the template using the addModule() method:
$template->addModule($modulePointer, areaOne);
This adds the module created into $modulePointer to area areaOne, and will cause its output to show up in the corresponding area.
35
Finally, the completeDisplay() method is called to run the modules and output the nished page. See the Directive Script section for more information on creating a template and adding modules to it. Direct Area Replacement. Another way to use templates is for direct text replacement. This allows you to replace an area you dene with an arbitrary block of text.
$template->addText(Hello there, world., areaOne);
Every loaded template has an addTemplate() method, which allows you to add an entire template (modules and all) into an area in another template. When a root template displays, if it encounters a template inside one of its areas, and it run recursively, gathering and returning output. Computer resources are the only limit to the depth of recursion. Also note, you can use CodePlates instead of templates, which also act recursively. See the next section on CodePlates.
CodePlates
CodePlates take templates a step further. They are templates that have modules associated with them. Often, youll want to use a template that has the same (or almost the same) module layout in several pages. For example, on a typical website you might have one main layout that includes a menu on the top, another menu in a left column, and the content in the center changes depending on the page loaded. One way to do this in SiteManager is to create a directive script for each page, and load and add the same menu modules on each page, then load a different module to place in the center section. But what if, at a
36
later date, you wanted to change which module gets loaded in the left column? You would have to go through each directive script to change it by hand. CodePlates solve this problem. To handle the above example, you would create a CodePlate that always has the menu in the top and left areas of the template. Then, instead of loading the template and modules in the directive scripts, you would load just the code plate, and the center module. Place the center module in the code plate, and youre all done. Since the menu modules were automatically added by the code plate, you dont have to worry about them (although you can still congure them if you wish, per directive script). CodePlates are actually a descendant of the SM_layoutTemplate class they have all the same methods and functionality of a regular template. You associate a CodePlate with an HTML template, and you can add modules to the areas in the same way. However, CodePlates have extra methods which are used to congure and dene which modules get loaded, and where they get placed. To use a CodePlate, you must create a class that extends the SM_codePlate class. This piece of code may be in an external le, and loaded in your sites common.inc Here is an example CodePlate:
/** * a test code plate * */ class mainLayout extends SM_codePlate { /** * * pre-configure the CodePlate * */ function codePlateConfig() { // configure a directive $this->addDirective(testDirective,testValue); // load and parse basic.tpt for my template // this will search my template paths // THIS CALL IS REQUIRED! $this->setMyTemplate(basic); }
/** * * define which modules i want where in my template * */ function codePlateThink() { // load a new module, and place it into area leftBar $mod1 =& $this->loadModule(menu,leftBar); // load another module, place it into area main $mod2 =& $this->loadModule(runTestModule,main);
37
// configure the menu $mod1->addDirective(menuStyle,sp); $mod1->addDirective(menuSpaces,5); // load more modules, for subtemplate $mod3 =& $this->loadModule(rawHTML); $mod4 =& $this->loadModule(rawHTML); // configure the module $mod3->addDirective(output,Module 2, Sub Template); $mod4->addDirective(output,Module 3, Sub-Sub Template); // load subtemplate, add it to main area of my codeplate $layout2 =& $this->loadTemplate("subTemplate",main); // add module to subtemplate $layout2->addModule($mod3, "areaOne"); // load subsubtemplate $layout3 =& $this->loadTemplate("subTemplate"); // add module to subsubtemplate $layout3->addModule($mod4, areaOne); // add subsubtemplate to subtemplate $layout2->addTemplate($layout3, areaTwo); } codePlateConfig() is required, because the call to $this->setMyTemplate() is required. By calling this method, you are
telling SiteManager which template this CodePlate will be based on. Once it loads and parses the template, it will know what areas are available to load modules (and possibly other templates or CodePlates) into. codePlateThink() is then used to load, congure, and add modules and templates to areas of the CodePlate. This is similar to a directive script, except when loading a module or template, you can specify which area it should be located in immediately. Also, you use built in methods rather than the global $SM_siteManager object to do so. Check the SiteManager API for the list of methods available to SM_codePlate decedents. CodePlates behave like any other template, and therefore can have any number of modules or templates (or even other CodePlates!) added to any area, and to any depth of recursion. Once you have a CodePlate dened and included in your site, you use it in your directive scripts much like a template. For example (this is a full directive script):
// include load site common include ("../admin/common.inc"); // load a module $mod1 =& $SM_siteManager->loadModule(detailedForm); // load code plate as root template $layout =& $SM_siteManager->rootTemplate("mainLayout.cpt"); // add form module into codeplate $layout->addModule($mod1, "intro");
38
As you can see, you can set a CodePlate to be the rootTemplate, in the same way as setting a normal template. You can also add modules to a CodePlate in the exact same manner.
Note: When using a CodePlate as a rootTemplate, you must include the extension (.cpt) so that the SiteManager system knows youre loading a CodePlate and not a regular template (which has a .tpt extension).
SmartForms
With SmartForms, you create an HTML form by programatically telling it exactly what you need and how the information needs to be formatted. SmartForms handles all other aspects of outputting, gathering, and validating the information from the form. SmartForm Feature List: 1. Generation of all HTML tags and other code, including all form elements, the table the form appears in for layout, and javascript functions. 2. Handles "enter information->submit->correct information->submit" loop automatically, highlighting which elements need to be corrected and why 3. Handles checking for valid input based on a list of lters for each for entity 4. Ability to use a template for form output, so the layout of the form elements are to your exact specication 5. Expandable library of common Input Entities: Check Box, Combo Box, Country List, Date Picker, DB Combo Box, DB Select, Static Text, Radio, Select List, State List, Switch Box, Text Area, Text 6. Ability to create new drop in Input Entities and lters, or use entities and lters designed by others by doing nothing more than placing a .inc le in the correct directory. 7. Expandable library of Filters: Credit Card, Email, User Function, Number, Phone, Regular Expression, Required, Variable Comparison 8. Can add any number of lter requirements to any entity 9. Filters and entities can contain optional JavaScript output for increased functionality. Javascript will go to correct JavaScript section of output template 10. Load a precreated SmartForm from an XML conguration le Now that you know a little more about what a SmartForm can do, heres how to use them.
Usage
1. Create or Load a Smart Form 2. Congure The Form 3. Add Elements 4. Congure Elements (setup options, add lters) 5. Run Form
39
Return By Reference
The object returned from this function is returned by reference: you must use the reference assignment operator ( =& ) as in the example above in order to congure and use the SmartForm properly. For more information on this, see the PHP documentation: References Explained (http://php.net/manual/en/language.references.php)
Congure Form
You can congure SmartForm directives through the standard addDirective() method call. You can, for example, tell the SmartForm that the value of the Reset button on the form should be "RESET FORM":
$myForm->addDirective(resetButton,RESET FORM);
Since a SmartForm extends SM_object, you can use loadConfig() to load directives from an external le. See the SM_object section for more info.
Tip: A full commented list of directives is available in the library lib/smartForm.inc. You can also check the Appendix section for an annotated directive list, which will describe all the ways in which you can congure a SmartForm.
Add Elements
If you are loading the form from an external le, you can skip this step, as the elements will be created for you from the XML conguration le. See the LOADING A SMARTFORM section below. Otherwise, add some elements. This is done through the add() method.
$myForm->add(varName,Input Title,text);
There are many parameters, but the rst three are all that are required. They are: 1. The variable name to use in the form 2. The title to use, which will tell the user what they are expected to enter 3. The type of input entity to create (in the above case, a text box) Here is another example, illustrating how to access methods of an input entity once its been added to a form. Notice how the input entity is returned as an object from the call to add():
40
This nal example shows a more complicated call to add(). Note that it makes use of the optional parameters. For a full, documented list of parameters, see the API documentation.
$selectList =& $myForm>add(sizeList,Select Your Size(s),select,true,large,array(multiple=>true,size=>5)); $selectList->addOption(XX-Large,xxlarge); $selectList->addOption(X-Large,xlarge); $selectList->addOption(Large,large); $selectList->addOption(Medium,medium); $selectList->addOption(Small,small); $selectList->addOption(X-Small,xsmall);
Return By Reference
The object returned from this function is returned by reference: you must use the reference assignment operator ( =& ) as in the example in order to congure and use the entity properly.
Loading a SmartForm
Instead of manually add()ing the elements to the SmartForm in your module, you can call the SM_smartForm::loadForm() method. It will read in an SmartForm XML denition le and congure the form as indicated in that le. The XML format is described in Appendix B, or you may check the testSite for examples. In that example, the form and its directives are congured all externally. Once you call the loadForm() method in your module, you can still congure and override all settings, using the addDirective() method as normal. For example:
// create form $myForm =& $this->newSmartForm(); // load from external file $myForm->loadForm("smTest.xsm"); // override configuration directives that // were loaded in from the XML form // one of the variables loaded in from the file // was userName. well configure that here. $myForm->setArgs(userName,array(size=>20)); $myForm->addFilter(userName,number,Must be a number); // run the form
41
$myForm->runForm(); $this->say($myForm->output());
Conguring Elements
You may also use the input entity returned from the add() call to setup directives for this entity:
$myPW = $myForm->add(passWord,Pass Word,text); $myPW->addDirective(passWord,true); // this tells the text entity to be of type PASSWORD // so it will show asterisk when someone types $myPW->addDirective(size,20); // make it size 20 characters
To verify the data coming into your script from the form, use lters. Adding lters to an element is easy. To make the above eld match a phone number pattern, we would:
$myPW->addFilter(phone,Must be in the form of a phone number); $myPW->setFilterArgs(phone,array(format=>(XXX) XXX-XXXX));
This would add the phone lter, and if the lter didnt pass, it would display the above message to the user as to why it didnt. You may add any number of lters to any entity. For the current list of lters included with the library, look in the lib/sfFilters directory.
This applies all lters and does some background magic. After the form has been run, you will know if the data has been veried or not. The check would be:
if ($myForm->dataVerified()) { // the form has all required input, and the input has been validated // against all filters // send email, write data to database, or do whatever necessary with // form data. access the variables with ->getVar function: $this->say($myForm->getVar(passWord). was passed and verified!); // or, dump all form input $this->say($myForm->dumpFormVars()); // how about looping through the form variables... $varList = $myForm->getVarList(); foreach ($varList as $formVar) {
42
$this->saybr("form variable $formVar had a value of: ".$myForm->getVar($formVar)); } } else { // the form either does not have all required input, or some filters // did not pass // display the form $this->say($myForm->output()); }
Here is a simple, complete SmartForm (when copied and pasted into a siteManager module, it should run correctly):
// create form $myForm =& $this->newSmartForm(); // configure form $myForm->addDirective("requiredStar","***"); // add a new text entity $myForm>add(userName,User Name,text,true,,array(size=>20,maxLength=>25),0); // add a couple more $myForm->add(firstName,First Name,text,false,,undef,1,"RIGHT"); $myForm->add(phone,Phone Number,text,false,,undef,2); // add filter $myForm->addFilter(phone,phone,Not a valid phone number,array(format=>(XXX) XXXXXXX)); // run the form $myForm->runForm(); // was data verified? if ($myForm->dataVerified()) { // yes! $this->say("thanks for the input!!<Br><br>"); } else { // no! output the form $this->say($myForm->output()); }
43
Form Templates
SmartForms by default will generate the table and layout for the form. There are many options for formatting the output of this table (see Appendix A for more information on SmartForm conguration directives). However, sometime you want your form to be in a specic layout - SmartForms handles this with templates. Here is a sample SmartForm template:
<TABLE border=0> <TR><TD>{userName.title}</td><td>{userName.input}</td> <TD>{firstName.title}</td><td>{firstName.input}</td> <TD>{lastName.title}</td><td>{lastName.input}</td> <td>{submit.Enter Data}</td></tr> </TABLE>
You should call this before you call runForm() There are two parts to setting up the template: you must tell SmartForms where to place the Title and the Input for each form entity. The format to do so is
{varName.title} {varName.input}
"varName" should be the same variable name you used when call the add() method to add your elements. The {submit} tag is a special tag which will place the Submit button. The text that shows up after the "." in the submit tag will be the text on the Submit button (in the example above, the submit button would read "Enter Data") Please note, there are many other options and conguration settings for SmartForms. Please reference the JavaDoc documentation in the following les (see the API documentation les):
lib/smartForm.inc lib/sfInputEntities.inc lib/sfFormEntity.inc lib/sfFilters.inc lib/sfFilters/* lib/sfInputEntities/*
Hidden Variables
To add hidden variables to your form, make an associative array. When passed, the key of the array will be the "NAME" and the value of the array will be the "VALUE" of the HIDDEN FORM tag. Setup your hidden by creating the array as follows:
$myHiddens = array ("hidden1" => "val1", "hidden2" => "val2");
44
Once its created, pass the array as the "hiddens" directive of your smartForm:
// add hiddens via addDirective... $myForm->addDirective(hiddens,$myHiddens);
Note that since your hidden variables will have their module prex attached to their name, you must use SM_smartForm::getVar() (or declare a module inVar) to retrieve their value. If you want your hiddens to use the variable name you specify, and NOT to attach the module prex, set the directive cleanHiddens to true.
Session Management
Sessions are used to maintain "states" for users when they access your site. For example, if a client accesses your site and enters a user name, it would be nice if next time they came to the site, they didnt have to enter the username again. This is where the SiteManager sessions system comes in. There are several ways to congure the sessions system, but there is always one common element: the persistent variables. These are the variables you would like to keep persistent between sessions for each user. It is possible to use persistent variables of any valid PHP type - this includes strings, integers, oats, arrays (multidimensional) and objects. To use a variable other than a string, however, you must be using a database and have serialization turned on (which it is by default). If you dont use serialization, you will only be able to keep strings persistent. For example, "userName" could be a persistent variable that gets dened in a SmartForm. If you make this variable persistent, once the user submits the SmartForm, the value will keep throughout their session. To access this variable through a module, simply declare "userName" as a module InVar (see the Module section). Depending on if you use cookies and/or a database for session storage, their session might last for as long their browser is open, or even until they come back next time, potentially days later. Possible ways to congure the session system: 1. Dont use database or cookies to store variables. This is the simplest method. In this system, all declared persistent variables are passed around throughout all the links on the site (through the hLink function). This method would let the user see all of the persistent variables in the URL of the script. You will not be able to keep arrays or objects persistent, only strings. 2. Use database to store variables, optionally using a cookie to store session ID. This method will store all declared persistent variables in a database. The session ID is passed around in all links throughout the site (through the hLink function). This method would let the user see their sessionID in the URL links, but not the different variables being kept for their session. If you use a cookie for session ID, the session will be maintained even after the user closes their browser. You can keep arrays and objects persistent with this method.
45
DATABASE NOTICE
Even though the session code uses the same PEAR database functionality as the rest of the SiteManager system, database structures and therefore SQL queries vary with each database type. Currently, MySQL and PostgreSQL are the only tested database engines. The code is written in such a way as to easily be able to handle other database structures. If you add support for another database layout, please submit it to us. The current sessions table format can be found in the tables/ directory.
Conguring Sessions
There are several options for conguring the sessions system to work with your site. Look in config/globalConfig.xsm in the "sessions" SECTION, for a commented list of all available options.
Using Sessions
To use the session system, simply call $SM_siteManager->startSessions() in your sites admin/common.inc. Then, use the addPersistent() method to tell SiteManager which variables you would like to keep persistent. For Example (from common.inc):
// use sessions $SM_siteManager->startSessions(); // add a variable to keep persistent $SM_siteManager->addPersistent("userName"); $SM_siteManager->addPersistent("firstName");
You may also set which variables you want to keep persistent in the local site conguration le (localConfig.xsm). See the Global Conguration System section for more info, or take a look at testSite/admin/config/localConfig.xsm in the pVars SECTION. Now, when "userName" or "rstName" get passed to a script (either through command line GET or from a SmartForm) the value will be remembered and passed around between links and forms in the site. To accomplish this, modules need to me "session-aware". See the Module System section for more information on this. If you would like to change the value of a persistent, so that at the end of the page load it saves a new value to the database, use the SM_session::setPersistent() method. For example (module excerpt):
function moduleThink() { // change the value of a persistent variable so that // at the end of this page load, a new value is written // to the database $this->sessionH->setPersistent(userName,testUser); }
One caveat to persistent variables is that if you are using a database to store the values, once the values get set and written to the database, they will not change until you call setPersistent (as above). If a SmartForm passes a value for that persistent, or a value is set on the URL, it will be overridden from the value retrieved from the database.
46
Note: If youre using sessions with a database, SiteManager will not automatically clean your session table of old session variables. You must do this yourself with cron and a script. You can use the dateCreated eld to see how long ago session variables were written.
desc="member tadesc="logged in memdesc="the userdesc="the passdesc="the unique user id field" /> desc="the unique ses-
Note: loginTTL is the number of seconds a member login session is valid for. After their session expires, they will have to login to reset it. Note the actual memberSessions entry isnt removed when their session expires unless you set maintainTables to true, but theres a performance hit by using this so we recommend you maintain your tables with a cron script.
The member system requires two tables: the member table, and the memberSessions table. Both are included in the tables/ directory of the main distribution. The members table is for keeping the actual information on a member. You dont have to use the included members table - it may have as many elds as youd like, but it must have a userName, passWord, and UID eld. The actual eld names are congurable (see above). UID is an identier string used by the sessions system. It should be a CHAR(32) eld. Username and Password are self explanatory - they should be CHAR elds. The memberSessions table must be as per the denition in the tables/ directory. After creating these tables in your database and conguring the appropriate variables in the GCS, all you need to do is add a mechanism for users to be able to login and out. For logging in, weve provided a simple generic module that creates a SmartForm
47
and calls the appropriate methods in the session system for logging in a user. Its a good starting point for creating a custom login form the module is called userLogin.mod and is in the main modules/ directory. For logging out, you need to setup a page that calls the SM_sessions::attemptLogout() method. For an example of this, and also an example of how to check to see if the current session is a member session, see the testMembers.mod module in the testSite/admin/modules directory. To use the member system in your modules, you have the following methods available to you, all of them available through the $this->sessionH variable:
isGuest() isMember() getMemberData() attemptLogin() attemptLogout() - returns true if the current session is a GUEST session - returns true if the current session is a MEMBER session - returns an associative array of all fields in your members table for the current member who is logged in - attempt to create a member session with the passed username and password this is to be used in login modules - attempt to remove a valid member login session
Here is an example of a module that displays the status of the current member system, and allows the option of logging out if they are currently logged in:
class loginCheck extends SM_module { /** * configure the module. run before moduleThink */ function moduleConfig() { // flag to single logout request $this->addInVar(l,0,int); } /** * this function contains the core functionality entry point for the module. */ function moduleThink() { global $PHP_SELF; // if they want to logout, do so here if ($this->getVar(l) == 1) { $this->sessionH->attemptLogout(); } // display status if ($this->sessionH->isGuest()) { $this->say("You are currently NOT logged in"); } else { // they are logged in, get their information! $member = $this->sessionH->getMemberData(); $this->say("You are logged in as: ".$member[userName]);
48
$this->say(" [".$this->sessionH->hLink($PHP_SELF.?l=1,logout).]); } } }
Custom Member Load Function. You can also specify a custom function to run when member data is loaded. This function can load additional information from a database, for example, or run whatever other code you need it to. The function will only be run if the session system determines the user is a member who is currently logged in. It will be run directly after loading the current members information. The function must take one parameter, $memberData. It will be the hash of data loaded from this member. You can use it to perform other database lookups based on this members information. The $memberData parameter can be taken by reference, and if so, changes made to it will be visible by modules using $this->sessionH->getMemberData() method. To create a custom member load function, dene the function either in common.inc or a le included therein. The name of the function can be any valid PHP function name (you will specify it later). As mentioned above, the function should take exactly one variable as a parameter (possibly by reference). The code inside the function can be any valid PHP code. If you need to access the current SiteManager database connection inside of the function, declare $SM_siteManager as global and use $SM_siteManager->dbH. The nal step is to tell the session system the name of the function youve created, and to use it. Both of these tasks are accomplished by specifying a variable in your localConfig.xsm called memberLoadFunction in the sessions SECTION. The value of the variable should be set to the name of the function you have declared. Here is an example custom load function:
// hook for grabbing extra member information // this is run when the member system loads the member information from the main table // (or from a persistent variable) function testMemberLoad(&$memberData) { // alter the main users memberData for other modules and code to see $memberData[testMemberLoad] = ran testMemberLoad; // could be looking up more info in a database, or whatever else... // to access the SiteManager database settings, use // $SM_siteManager->dbH // after declaring $SM_siteManager as a global }
This line would appear in the sites localConfig.xsm, in the sessions SECTION.
<VAR name="memberLoadFunction" value = "testMemberLoad" ning a custom function to load additional member information" />
49
Database Connectivity
Database connectivity in SiteManager uses the PEAR database abstraction library (http://pear.php.net). This keeps the interface to the database routines the same, while allowing multiple database engines to power the site. Connecting to a database should be done through the $SM_siteManager variable. Doing it this way allows other parts of the SiteManager system (modules, SmartForms, input entities, etc) to be database aware. Starting the database system using the database settings found in the Global Cong System is a simple matter of calling $SM_siteManager->dbConnect() in your sites common.inc. See skeletonSite/admin/common.inc for an example. Once connected, you may directly access the PEAR database object using $SM_siteManager->dbH, which points to the default database connection. You rarely directly access $SM_siteManager->dbH, however, since most of the database work is done inside of modules. See the Module section on how to make a module database aware.
= = = = = = =
"mysql" /> "true" /> "userName" /> "passWord" /> "hostName" /> "dataBaseName" /> "mysql://userName:passWord@hostName/dataBaseName" />
This may be dened in EITHER the globalConfig.xsm or per site in localConfig.xsm Note that you can dene either (userName, passWord, hostName, dataBase) OR use DSN. If DSN is available, it will always use that. The id tag lets SiteManager know which database connection this is. For information on multiple database connections, see the section below. dbType should match up to one of the valid PEAR database types. See the PEAR DB documentation for more information on that. For more help with the PEAR Database layer, see http://pear.php.net or /usr/local/lib/php/DB.php and
/usr/local/lib/php/DB/*
50
<SECTION name="db" id="secondary"> <VAR name="dbType" value = "mysql" /> <VAR name="persistent" value = "true" /> <VAR name="DSN" value = "mysql://userName:passWord@otherHost" /> </SECTION>
This would create two database connections, one identied as default and the other identied as secondary. Normally, most SiteManager objects access the database connection through their $dbH variable, which they inherit from the SM_object base class. This variable always points to the default database connection. To access a connection with a different id, use the $dbHL hash. The key to this hash is the id specied in the cong le. For example:
$SQL = "SELECT * FROM testTable"; $rh = $this->dbHL[secondary]->simpleQuery($SQL); if (DB::isError($rh)) { SM_debugLog($SQL,$this); SM_fatalErrorPage("There was a problem with the query!"); } while ($rr = $this->dbHL[secondary]->fetchRow($rh)) { $this->say($rr[firstName].<br>); } $this->dbHL[secondary]->freeResult($rh);
This function should be used when a fatal error has occurred, and the script should not, or can not, continue. It will create an error page, displaying $msg in red text, and display the current debug log. If you specify $obj, it will prex the message with which object issued the fatal error.
SM_debugLog($msg, $obj=NULL)
This is used for non-fatal debug output. $msg is the message to log, $obj is the calling object, if any. If its specied, the objects class name will be logged (usually you should specify $this, if youre using this function from a module) Use this function, in conjunction with the JavaScript Debug Window or debugOnVar, to track down errors. Calls to SM_debugLog() will not show up in the main page view, only in the debug log. This lets you view the complete page without test debug messages all over it, but still allows you to view any type of debug message you need. You can also use standard PHP functions such as echo, var_dump, and print_r. Their output will not show up in main page, only the debug page. Use either $SM_siteManager->fatalDebugPage() or one of the debugging methods listed below to view their output.
DebugOnVar
One simple way to debug your script is to use "debugOnVar". This is a variable set in the GCS in the "debug" SECTION. When its true, SiteManager will look for a global variable called "SM_debug" to be set to 1. If it is, it will generate a page that has all the debug output at the top, then your completed page below it. This separates the debug output from the main output and still allows
51
you to see all of your warning and debug message issued through SM_debugLog(). It will also display the output buffer, which you can use to view calls to PHPs var_dump() and print_r() routines. To use, make sure "debugOnVar" is set to "true" in your localCong.xsm le. Then, when viewing your script, add "SM_debug=1" to the URL, such as:
http://localhost/home/testScript.php?SM_debug=1
You should now see your page displayed with debug information attached to it.
You must also add one additional piece of code to your root template. You must tell the client to run the SM_viewDebugLog javascript function upon loading. Do this by adding the following tag to your templates <BODY> HTML tag:
ONLOAD="SM_viewDebugLog();"
If you dont wish to have to change your template to use the debug log, use the next option below. 2) The debug window opens and updates when you click on a link thats added to the bottom of all your pages To use this option, see the following conguration directives in globalConfig.xsm (or localConfig.xsm for your site) in the "debug" SECTION:
jsDebugWindow - true jsDebugLink - true jsDebugAutoFocus - true
With these options set, all of your pages will now have a link at the bottom [view debug output]. Clicking on this link will open the JavaScript Debug Output window, showing all messages that were written with SM_debugLog().
52
For example, one way to use the debugLog is to check a variable when youre not sure of its value. For example (excerpt from a module):
.... SM_debugLog("testVariable is $testVariable", $this); if ($testVariable == check) { // do something } ....
Then click on "open debug output" on the bottom of your page. It will pop open a window with your test message (or update the window if it was already open).
SmartForms contains its own debug output log. If ags => sfDebug is true in Global Cong, you should be able to view the source of an page that includes a directive script to see the debug output from a form.
Miscellaneous Routines
Other supportive routines are included in the SiteManager system. Please see the following library les and the API documentation for more information:
Authentication Routines Security Routines Support Routines Data Manipulation Routines (auth.inc) (security.inc) (support.inc) (dataManip.inc)
53
54
Sessions. If you will need to maintain information for clients that access your site, then you will need to use the Session system. For example, you might want to use sessions to track visitors by some global ID, or to keep track of preferences they may have set. Sessions are most useful when used with a database, as you will be able to store a wider range of information as a session variable. At this point, you need to think about what information you wish to keep persistent within your site. Decide how you will store this information (for example, do you want to keep an array of values? a simple string? perhaps a class object?). This will help you generate the list of Persistent Variables you will use. The dealership will keep one persistent variable: zip code. If the user enters their zip code into the zip code form, the value will be kept persistent for that user, and we will attempt to use a cookie so that if the user comes back to the site later, we will still know their zip code. The zip code will be used to gauge how far away the user is. Member Login System. Does your site need a member system? If you wish to have clients "log in" to your site, then the answer is yes. The member system is designed to be exible enough to allow you to store whatever information you need to about the members of your site, and allow your modules to know if the current session is a Member or Guest session. You should decide exactly what information you want to gather from each user - this will help you design your member table, and the SmartForms necessary for logging in, creating and updating a user account. The dealership will use the member system, but only for administrators. General users will not need to login to the site. Administrators who will be maintaining the inventory, however, must have a member entry and must login to use the administration forms. Client Administration System. Often when you design a site for a client, the client needs the ability to maintain their database or otherwise update the site themselves. For example, they may need a system for editing and maintaining an online catalog. If the site includes this requirement, you will need to build a Client Administration system. This usually involves extra modules with SmartForms that are designed for authorized administrators to update the sites content. You may also integrate this with the Member Login system, and some form of access control. As explained previously, this is exactly the system we will be using for the Roadsend Car Dealership. Co-brand System. Co-brands are a convenient way for one company to offer the functionality from their site to another company. This allows two companies to partner, whereby Company A has a functioning website that Company B wishes to use, but still make it look (to the user) like they are on Company Bs site. With SiteManager, this is a snap since the same modules used in Company As site can simply be placed in a template that contains the layout for Company B. Since the same code module is used in both places, when an update happens to the module (such as a bug x), it affects all co-brands automatically. The dealership wont be needing a co-brand system at this point in time. If we need it in the future, we can always add it later. Multilingual. The Internet is a global place, so SiteManager makes it easy to add multiple languages to your site. If you know you will need to support multiple languages, you can start planning IDs that will be used to access blocks of text. You will use the IDs to access the text from a particular language, instead of hard coding them into your modules. While you can always add this support later, if you plan ahead you can avoid rewriting your modules to use IDs instead of hard coded text. Since the dealership is a local company, we wont be using a multilingual system. Perhaps well add it when it becomes cost effective to ship cars throughout the country.
55
One site might have several root templates, one for each section of their site that has different content. Perhaps one root layout has a three column table, while another has a simple one column with no footer. Within these columns we will later place dynamic pieces of code to display different pieces of information. The dealership will have one root template. We will display a logo at the top of all pages, and use the company colors for displaying text and table background colors. There will be one main column (area) where content will show up. Will templates be needed for modules to load and use? At this point you can also determine if you will be loading templates into your modules. You might do this if you want to keep layout completely external from modules, instead of hard coding your module to output a particular bit of HTML code. The dealership wont be using this feature for now. Will templates be needed for the forms on the site? Another way to separate layout from code is by templating your SmartForms. This gives you exact control over the layout of the entities in the form. If you have a form that needs to be laid out in any other fashion then the default, two column table style, you will need to use a SmartForm template. The dealership will use SmartForm templates for both the administrative form and the feedback form, since we want to have concise control over the placement of the form entities. Determine dynamic content. Now you need to determine which parts of the site are dynamic. These are the parts of the site where the output will vary based on user input, database pull, or by some other dynamic means. For example, a News section on a site would be pulled from a database. A poll would change based on user input, and previous values stored in a database. By determining which parts of the site need to be dynamic, you can begin to understand how many modules you will be creating to complete the sites functionality. On the dealership site, there will be three major pieces of dynamic content that the user will have access to. We want to have a system for displaying a block of text pulled from a database, that can be administered by employees. This will be used for displaying general company information, as well as blocks of text like Directions. We will also have a system for displaying the current inventory list, which the user will be able to browse and sort. Finally, we will have the feedback system which will allow the user to send us feedback.
56
In addition to the specic information youve obtained about your site, there are also a few more general practices which may help in creating sites with a clean, consistent framework. Consistent Variable Names. Try to be consistent when using variables names throughout your site. Pick a naming structure and stick to it. For example, dont abbreviate "index" to "idx" in one variable, and "indx" in another. If you create several modules that make use of an email address, use "$emailAddress" in both modules, not "$email" in one and "$emailAddress" in another. Coding Practices. Choose a system of coding practices to follow. For example, indentation style and function/variable naming convention. Choose whether youre using tabs or spaces. Be consistent with functions and variable naming, for example functionName or function_name. You might want to prex "private" class variables with an underscore. The actual method you choose isnt important, as long as it makes sense to you and you stick to it. For example coding practices, see http://php.net/manual/en/pear.standards.php Directory Layout. Try to follow a consistent directory layout. SiteManager includes a pretty rigid directory structure thats meant to be consistent across sites and make it easy to nd your way to the various SiteManager resources used by the site. You may choose to follow this, or create your own - but keep it consistent across all of your SiteManager sites. As this manual isnt a introduction to programming in general, sufce to say there are many ways you can make your programming more efcient by having consistent coding standards. This will save you time and aggravation in the long run. Now that you have a complete plan for your site and standards with which to implement it, you can begin coding.
Site Conguration
First, edit the admin/common.inc le. This is rst include le loaded by all directive scripts, and is where you will specify such things as the Site ID, SiteName, and the base directory path of the site. It also includes the SiteManager library. In common.inc are also the calls to start the database and session systems. After editing admin/cong/localCong.xsm (in the next step) you may want to come back and uncomment these lines. If you need to include any other library les you may have, you can do that in common.inc. Next, edit admin/cong/localCong.xsm le. This is the main conguration le for the site. All of the values have descriptions, make sure you read through each one and set them up appropriately. Pay attention to the directory paths. If you wish to setup database access, you will need to specify database conguration values here.
Template Design
Now edit the template placed for you by the skeletonSite (admin/templates/basicTemplate.tpt). Since its strait HTML, you should be able to get the exact layout desired for your site. Add the static content, such as image links and background colors. Then, add the SM tags required by your site. You will need at least one SM AREA tag to add dynamic content.
Module Design:
Look at the sample module in admin/modules/basic.mod. This is a basic module that was added by the skeletonSite. It contains a lot of commented out code that will be useful while designing a module. It includes descriptions of how to use directives, inVars,
57
58
3. Create the test tables using the le test.db.sql in tables/ directory in the SiteManager root directory In testSite/admin/config/localConfig.xsm, the database settings are already setup to reect this. You should also check the "dirs" SECTION of this le to verify the paths match your setup. Otherwise, if SiteManager has been setup correctly on your system, and testSite is in your web document path somewhere, you may point your browser at the main directory and try it out. The testSite is also a great place to look for examples. You should nd at least a basic example of most of the features of SiteManager.
59
60
Alternatively, you can leave out the php_value include_path statement, and edit siteManager.inc. Edit the $SM_rootDir directory to point to the main SiteManager root directory. If you do this, you dont need to have it in the PHP path. If you do it this way, you will also have to specify the full path to siteManager.inc in your admin/common.inc le 3. Im trying to use the $SM_siteManager class, but I keep getting errors. Make sure its declared as global. Remember, PHP requires you to declare globals variables inside of functions and classes. It doesnt automatically give you access to all global variables. Since SM_siteManager is global, if youre in a function or a function within a class, you must declare it global before gaining access to it:
// declare SM_siteManager global global $SM_siteManager;
61
62
Module Directives
outputInTable (default: true) When set to true, the module will output itself in a table automatically. If you dont want your module to appear in a table (for example, its a module to be used within another module), then set this directive to false. outputInSpan (default: true) When set to true, the module output itself within a SPAN tag, with an ID attribute set to the value of the modules prex. Setting this to false will force the module NOT to output a SPAN tag. tableBorder (default: 0) When outputting module in a table, this is the BORDER size tableWidth (default: 100%) When outputting module in a table, this is the table WIDTH tableCellPadding (default: 0) When outputting module in a table, this is the table CELLPADDING tableCellSpacing (default: 0) When outputting module in a table, this is the table CELLSPACING tableBgColor (default: ) When outputting module in a table, this is the table BGCOLOR centerInTable (default: false) When outputting module in a table, this adds ALIGN=CENTER to the <TD> that the module appears in when set to true. No effect if outputInTable is false. dieOnBadInVarType (default: true) When adding an inVar through the addInVar() method, you can specify a data type you are expecting this inVar to be (for example, numeric). If SiteManager determines that the inVar was passed, but wasnt of this type, it can either issues a debug warning, or not continue loading the page. If this option is set to true, the page will not load if the data type is incorrect. This is a security measure and we recommend leaving it on.
63
propagateInVars (default: true) This sets the default for inVar propagation for this module. When true, all added inVars will be "read-write" or propagated by default. Note, you can also turn off propagation on a per inVar basis. See the Module section for more information.
Template Directives
bodyBGCOLOR (default: ) When using the SM TYPE="HTMLBODY" tag, this denes the BGCOLOR attribute of the BODY tag. bodyLINK (default: ) When using the SM TYPE="HTMLBODY" tag, this denes the LINK attribute of the BODY tag. bodyALINK (default: ) When using the SM TYPE="HTMLBODY" tag, this denes the ALINK attribute of the BODY tag. bodyVLINK (default: ) When using the SM TYPE="HTMLBODY" tag, this denes the VLINK attribute of the BODY tag. bodyBACKGROUND (default: ) When using the SM TYPE="HTMLBODY" tag, this denes the BACKGROUND attribute of the BODY tag. bodyONLOAD (default: ) When using the SM TYPE="HTMLBODY" tag, this denes the ONLOAD attribute of the BODY tag. bodyOther (default: ) When using the SM TYPE="HTMLBODY" tag, this denes arbitrary text that should be inserted as attributes into the BODY tag. You can use this to add attributes not directly supported as a directive.
SmartForm Directives
tableBorder (default: 0) When using the default SmartForm table layout, this is the BORDER size tableWidth (default: 100%) When using the default SmartForm table layout, this is the table WIDTH tableCellPadding (default: 0) When using the default SmartForm table layout, this is the table CELLPADDING
64
tableCellSpacing (default: 0) When using the default SmartForm table layout, this is the table CELLSPACING tableBgColor (default: ) When using the default SmartForm table layout, this is the table BGCOLOR requiredTag (default: true) When true, the default SmartForm table layout will show a message to the user indicating a symbol which means a particular eld is required. requiredStar (default: *) When not blank, this text will show up before every required eld. This may be an IMG tag. normalClassTag (default: sfNormal) The style sheet element to use for normal element titles badClassTag (default: sfBad) The style sheet element to use for element titles whos entity failed the lter check correctMessageClassTag (default: sfMessage) The style sheet element to use for displaying an error message when a eld failed a lter check requiredClassTag (default: sfNormal) The style sheet element to use for displaying the required tag message. rowColorAlt1, rowColorAlt2 (default: ) These two directives allow you to specify two colors the form should use for alternating rows. It value should be a hex color value (ie, #FFFFFF). The row color alternator will preserve groups. resetButton (default: ) If this value is non blank, a RESET button will be added whose title is the same as the value of this variable. controlsOnRight (default: false) If this value is true, the submit value will show up to the right of the form, instead of on the bottom. This is useful for forms with one element, where you want a vertically compact form. submitAlign (default: "LEFT") When not using a template for output, and resetButton is (so it wont show up), this directive species how the Submit button should be aligned at the bottom of the SmartForm. Should be either LEFT, RIGHT, or CENTER. freeFormSeperator (default: <br>) This value is used when layout is SF_LAYOUT_FREEFORM. It is the separator used between entities.
65
defaultLayout (default: SF_LAYOUT_NORMAL) This value is the default layout of form entities. Other options are SF_LAYOUT_FLIPPED, SF_LAYOUT_SINGLE, and SF_LAYOUT_FREEFORM. useJS (default: true) When true, JavaScript code will be collected and given back to the SiteManager system for inclusion in the nal output page. Some lters or entities might not work without this. postScript (default: $PHP_SELF) Normally a SmartForm will post to itself. If you want your form to POST to another page, set this directive. Note that the lter system will not work if this is changed. submitImage (default: ) If you would like the submit button to be an image instead of a regular button, set this directive with the image youd like to use. (ie /images/button.gif) showRequiredHelp (default: true) Set this to false to turn off both the message that says "* = Required Field" and the actual * next to required elds (ie, sets requiredTag to false and requiredStar to blank) cleanHiddens (default: false) Normally all hidden variables added to a SmartForm include the module prex attached to them. This is so variables added to this form dont conict with variables added from other modules. However, sometimes youll want to access the variables from a SmartForm with their prex - set this directive to true to allow the hiddens not to include their module prex. enctype (default: ) If you need your SmartForm to have a special ENCTYPE added to the FORM tag (for example, youre using your form to post a le), you can set this directive. badFormMessage (default: ) If this variable is non-blank, it will display its contents above the form (as a header) when any of the lters in the form fail. It should contain a message such as "The form was invalid, please check your input and try again".
Filter Directives
coming soon
66
SMARTFORM
SMARTFORM les describe a method for dening and conguring SiteManager SmartForms.
SMLANGUAGE
SMLANGUAGE les describe a method for dening translations of blocks of text.
<SMLANGUAGE VERSION="1"> <LDEF locale="en_US"> <TEXT id="text1">This is the text</TEXT> <TEXT id="text2">Here is some more text</TEXT> </LDEF> <LDEF locale="da_DK"> <TEXT id="text1">Dette er en tekst</TEXT> </LDEF> <LDEF locale="es_ES"> <TEXT id="text1">ste es el texto</TEXT> <TEXT id="text2">Aqu est ms texto</TEXT> </LDEF> <LDEF locale="fr_FR"> <TEXT id="text1">Cest le texte</TEXT> </LDEF> <LDEF locale="de_DE"> <TEXT id="text1">Dieses ist der Text</TEXT> </LDEF> <LDEF locale="it_IT"> <TEXT id="text1">Ci il testo</TEXT> </LDEF> </SMLANGUAGE>
An LDEF should appear for each language to be dened. The locale attribute should contain the language youre dening (if anyone can nd a reference as to where the ofcial list of these locale ids are, please notify us). Each block of text to be dened should be listed in a TEXT tag. The id attribute is arbitrary, and will be used by the getText() method for retrieving this block. The same ID should be used in each translation of that text.
SMOBJECT
SMOBJECT les describe a method for conguring SiteManager objects.
67
SMCONFIG
SMCONFIG les describe method for conguring SiteManager sites on a global and site-wide basis.
SMRESOURCE
SMRESOURCE les are to be for describing various SiteManager objects. These are to be used for tools that will parse these les and understand which objects are available for use. They are not used directly by the SiteManager library. Blank SMRESOURCE Object
<SMRESOURCE type="" name="" extends="" version=""> <DIRECTIVE name="" default="" desc="" type=""> <DESCRIPTION> </DESCRIPTION> </SMRESOURCE>
Tag Descriptions
SMRESOURCE type name version extends
type of object were describing name of the object being described what version of the SMRESOURCE are we using (optional) which object this extends (optional)
Start tag for a general SiteManager Resource object DIRECTIVE name default desc data dataType bool
the name of the directive the default value for the directive (optional) the description of the directive (optional) misc data stored for this directive or dataType (see below) (optional) format of value the directive should have (optional) - true/false value
68
numeric, integer free form text hex color value #rrggbb comma separated list of available values, stored in data attribute date value directory (path) percentage value 0-100%
A directive tag, which will indicate that the object may be configured through its directives using the variable indicated. DESCRIPTION A text description of this object
69