 |
|
Wednesday, February 23. 2005
Once Syntax 1.2 is released, some confusion may arise from two similar methods within the Section object. Remember, sections are essentially the pages on your site. With the nice cleanup of URL paths that Sandy worked on, sections now have a method called getUrlPath(). They have for some time now, had a method called getNavPath. So, what exactly is the difference and when do you use or need each one?
First, getUrlPath() returns the full, complete, and unique path to the section including it's root node. Typically, the root node is the homepage of your site and is named _home. A sample URL Path would be _home/about/contact_us. URL Paths can be used to get a section object by calling Section::getByUrlPath( _home/about/contact_us ).
In comparison, getNavPath() returns the part of the URL Path needed to navigate to a section on a web page. Essentially, it removes the root element for your site set by the constant NAV_ROOT_EL in config/static.conf.php. In the example above, calling getNavPath() for your section would return '/about/contact_us. To build a link to that page on a template, you'd use the following code:
echo "<a href=\"/section".$section->getNavPath()."\">"
Monday, February 14. 2005
A powerful new feature was added to Syntax CMS v.1.1.2 that allows developers to capture Syntax events on objects and to handle those events with custom functionality. This provides a mechanism for Syntax developers to extend the functionality of Syntax to provide customized features without having to change the core Syntax code.
The architecture is quite simple. There are two new classes:
- pxdb_event_dispatcher (lib/ext/PxDB/classes/events/pxdb_event_dispatcher.class.php)
- pxdb_event_listener
(lib/ext/PxDB/classes/events/pxdb_event_listener.class.php)
A pxdb_event_dispatcher object is created in pxdb.inc.php. It is a singleton object so if you try and create a new object it will only return a reference to this single instance of the dispatcher. When this object is created it looks in the directory lib/ext/PxDB/events for event listeners.
Event listeners are classes that implement (extend) the pxdb_event_listener abstract class. In order to be automatically registered as listeners they must:
- Be located in the lib/ext/PxDB/events directory
- The file must have the file extension .class.php
- The class must be a subclass of pxdb_event_listener
- The class must add triggers to indicate what triggers/events it is interested in receiving
- The class must define and implement a method called execute(). This is the method that will be called by the dispatcher when an event occurs
When a listener is registered any notifications sent to the dispatcher will be sent to the listener if that listener has expressed an interest in receiving the notification. If the listener has expressed an interest in receiving the notification then the dispatcher will call the listener's execute() method where all the actual work of the listener is executed.
NOTE: The event dispatcher will loop through all the registered listeners that have been mapped to that trigger/event. Listeners can be chained in such a way that multiple listeners can handle the same event. Common sense and good application design is expected from developers.
The event/triggers that have been defined and implemented in the pxdb_commit class include:
- SYNTAX_EVENT_INSERT : An new content-item is added to the database
- SYNTAX_EVENT_UPDATE : An existing content-item is modified
- SYNTAX_EVENT_DELETE : A content-item is removed from the database
- SYNTAX_EVENT_APPROVE : A content-item is approved
- SYNTAX_EVENT_UNAPPROVE : A content-item is unapproved
- SYNTAX_EVENT_PUBLISH : A content-item is published to a section
- SYNTAX_EVENT_UNPUBLISH : A content-item is removed from a section
Important Caveats
- Since events are triggered when an object is saved (INSERT, UPDATE), removed (DELETE) or approved (APPROVED, UNAPPROVE) an event listener should not perform any operation on the triggered object that will fire one of these events. There is a very real danger of creating an infinite loop condition by doing so.
- You will also want to be very careful about changing the record state because of how events chain. The order in which event listeners are called is determined from the filename order in the directory. There is a danger that you get the order wrong and your data gets changed into an inconsistant state that is difficult to debug when problems and side-effects arise. If you need to change the state of an object consider using a post-processor plugin before resorting to using event listeners.
I will post detailed instructions on how to write your own event listener classes with some examples in a follow-up article.
Tuesday, January 18. 2005
Here is a quick example of how the Syntax API accelerates development by making it easy to search for a collection of objects. In this case, I had an array with some country info, including the name. I needed to see if any documents were tagged to that country:
Step one, figure out the numeric id of the country:
pxdb_import( 'content.output.pxdb_picktable' );
$country_picktable = new pxdb_picktable( 'country' );
$pick_id = $country_picktable->lookup_value( $country['name'] );
Step two, use a Document Collection to find matching records:
$documents = new DocumentCollection();
$documents->findByCountries( $pick_id );
$documents->execute();
If you use dbasis to generate the code for your abstract collection object, it will create methods for filtering/finding by any relationship or pick field in your object.
Thursday, December 23. 2004
I've checked into CVS, a new feature to the Syntax site administration application that automagically creates filters for working with content type lists. As your content repository grows, finding a specific record or set of records was only doable thorugh the search form. Now, in the left sidebar, syntax will provide a list of drop-down select menus based on the picklists used by the current datatype. You can also filter to show only approved or only unapproved records.
Besides the automatic generation of these, you can control the filters in two ways. You can suppress their appearance by setting a preference named 'admin_filters', using the content type integer id as the key and zero as the value. You can also specify which fields are used in the filters by creating a view called 'admin_filters' for a content type. Only picklist fields will be used so text or relationship fields added here are ignored. The image below shows the filters in action for an 'Organization' content type.

Wednesday, December 22. 2004
Syntax CMS comes with two very flexible Request handlers for routing incoming URLs. Which handler
is used is determined by the first directory in the url, i.e. http://www.example.com/section/
or http://www.example.com/content. Such requests are routed either to the section.php script
( via /section ) or to a capability of a registered module ( via /content ).
For a recent project, I needed to write a new Request handler, primarily to provide pages under a url first level
directory (/resource_centers) but also because I would need to provide a hierarchy of sections as well
as module calls all under one directory.
All a request handler does is tell syntax what php script to run, by returning
the full path to the script It could, therefore, return any sort of output to the browser/client - it
doesn't have to be a web page. These are the basic steps needed to implement your own
custom request handler.,
1. Directing your request
The first step is to route requests using mod_rewrite. You'll need to edit the .htacess file in
your public web documents root and add two rewrite rules.
RewriteRule ^resource_centers/(.+) /load.php?navtype=resource_center&request=$1 [L,QSA]
RewriteRule ^resource_centers/? /load.php?navtype=resource_center&request=$1 [L,QSA]
2. A class to handle it
When a request comes in, syntax looks for a class that extends the Request class. Save the new
file in your private/lib/syntaxcms/Request directory. The filename should be "Resource_centersRequest.class.php",
capitalize the first letter of your directory and append "Request.class.php" to it.
The class definition should look like:
require_once( dirname(_FILE_).'/Request.class.php' );
/**
Custom request class for handling resource centers
/
class Resource_CentersRequest extends Request
{
3. Implement getScript()
Now when syntax finds your request handler, it'll create an instance and try to call
a getScript method. This method takes no input and returns the path to the php script
that should be executed to handle the request. Since it extends the Request class, you
can use the getPathElement method to inspect the url path, 0 is the first element and so on.
You can also use the getVar method to get the value of GET/POST variables.
Monday, December 20. 2004
Has this ever happened to you?
You're coding along, and you need to reference a module. You remember you called it 'calendar'. You know modules are references with URLs that begin with /content/, so you put in a link to /content/calendar/, and you test the link only to find it barf horribly.
Oh, that's right, you forgot to specify a default path in path_rewrites.conf.php...so mnemonically named, how could you forget!
Well, fret no more, dear developer. I too was annoyed by this and did something about it. Now you just need to have a new module attribute that you add when you're configuring the module in user.conf.php, where all the other module-related config stuff lives. Just add the line Modules::setAttribute('my_module_name', 'default_action', 'my_default_action'); and you're good to go.
But what if, in the heat of development, you forget? Well, since the code generators and example modules in Syntax CMS tend to assume that your default action is going to be called "list" anyway, it will try that. If that fails, you'll get the same old ugly screen you would have gotten otherwise.
The other good news is that there is now one less configuration file for you to worry about, as path_rewrites.conf.php is now history.
All this will be included in the 1.2.0 release, and is in CVS now.
Friday, December 17. 2004
In anticipation of a 1.2.0 version of Syntax CMS, we have checked in an upgrade to how Sections work.
Previously, every section had to have a unique URL ID. This meant if you had a series of top level sections like "Marketing", "Tech," and "Consulting", you couldn't have "/marketing/about/" and "/consulting/about/" simultaneously. We had to resort toURIs like "/marketing/about_marketing/" or "/consulting/about_consulting/".
If you check out the latest CVS files, however, you can have "/marketing/about/" and "/consulting/about/". The only restriction, invisible to the user, is that you can't have two sections with the URL ID "about" under the same section...i.e., you can't have two sections with the URI "/marketing/about/". Now Syntax CMS will handle this case by creating "/marketing/about/" and "/marketing/about1/"...and "marketing/about2/" and "/marketing/about3/" and so on, as needed.
If you're upgrading, bear in mind it does require a database upgrade. Anything that relies on the assumption that a section's URL ID will be unique may break. However, anything using the standard SectionNavigator classes should still work unless you are passing a URL ID for any reason (these should now be the full URL path, which actually includes the URL IDs of every section from the top-level section down to the current section).
Affected files include:
/private/lib/syntaxcms/F1CMS.class.php
/private/lib/syntaxcms/functions.lib.php
/private/lib/syntaxcms/Section.class.php
/private/lib/syntaxcms/SectionNavigator.php
/private/lib/syntaxcms/SectionNavigatorOptimized.php
/private/lib/syntaxcms/Site.class.php
/private/lib/syntaxcms/Request/SectionRequest.class.php
/private/lib/ext/PxDB/classes/content/input/pxdb_commit.php
/private/lib/ext/PxDB/classes/events/pxdb_event_dispatcher.class.php
/private/lib/ext/PxDB/events/syntax_section_handler.class.php
/private/lib/ext/PxDB/config/initialize.php
/private/lib/ext/PxDB/config/install/mysql-upgrade.php
/public/admin/db.php
/public/admin/modules/navigation/lib.php
Monday, December 13. 2004
It'd be nice if a forms errors were listed as hyperlinks at the top to named anchors within the form. The message text would be the same but this way you click to jump down to the field that requires attention.
Monday, December 13. 2004
Syntax CMS has a flexible records privileges system in place that controls what users and groups can read and/or write a particular data record. As long as you use the pxdb_collections class to retrieve data, the appropriate sql and checks are added automatically. Through the Access Privileges tab in the Admin application, you can manually specify what groups can have read and/or write access to a specific record. For example, you could have a 'registered users' group that will have access to embargoed content on your site. To make sure only a logged in user in that group can see that record, you'd remove read access for the 'Everyone' group, and give read access to the 'registered users' group. On the front-end, Syntax CMS would take care of showing that record, in any collection or on a detail page, only to the 'registered users' group.
But, Syntax also assigns privileges automagically by default whenever a new record is entered. Here is how:
- The 'Everyone' group gets read privileges.
- If a user is logged in, then that user gets both read/write privileges to a record.
- The group id specified in the pxdb preference 'gid_admin' gets read/write privileges
This works fine most of the time. It'd be nice to have more control, maybe at the content type level, over if Everyone gets read access automatically or to specify additional groups that should get default read/write access to a content types's records.
Update: currently, only the admin group can see the 'Access Privileges' tab in the Admin application. Maybe we need to add a 'set_privileges' datatype priv and use that to test if a group can modify the record privileges.
To clarify, Syntax CMS has two levels of privileges. Datatype privs define what a group can do (add|edit|delete|approve) with a specific type of content ( ie documents|links|events). Record privs define what a user or group can do with a specific instance of a content type ( the link to Google, the Annual Conference event, and so on ).
Friday, December 10. 2004
With our new release of Syntax CMS, we've re-rolled the API-level documentation for developers:
Class and method-level documentation for the data access API that Syntax CMS uses. These are the classes that developers creating new modules or modifying template behavior will deal with most of the time.
The DocumentInfo class helps you provide automatically-generated download info based on file types and sizes. It works for local and remote files.
The DynTables class automates the creation of sortable tables from Syntax CMS data. It's a presentation-level helper class.
Class and method-level documentation of the CMS-level Syntax CMS classes. They provide functionality for handling requests (both browser and internal), creating site nativation, and many other functions.
Tuesday, December 7. 2004
If you're looking to install an Apache, MySql, PHP environment ( on either Linux or Windows ), instead of doing it piecemeal you may be better off grabing a middleware stack like XAMPP from Apache Friends. An article at IBM, details how to install such a middleware stack. This is perfect for folks who may not have the expertise, time, and or patience to install all these components seperately and, inevitably, troubleshoot the bugs that arise. Instead, you can concentrate on building your website instead of building your infrastructure. Seen in PHP Magazine.
Friday, December 3. 2004
We've rolled up another release of Syntax CMS. Sandy went on a cruft cleanup rampage and we've integrated a number of new features we've been working on. A lot of work has gone into making it possible to share the content repository among multiple sites and segregate parts of the repository among sites and/or user groups.
Public Website
- Added a Sitemap and an improved Search Module.
- Bundled templates use solely CSS to control layout and appearance.
- Removed leftover test datatypes and testing code
- For authentication of registered users, you can enable saving the user's login to a cookie.
Site Administration
- Various layout fixes to the interface.
- If sharing the content repository (database) among multiple sites, you can now control what content types show up in each admin instance explicitly.
- Section Navigator can be configured to automatically add new sections to a default section. Added a button to add a new section as a child of an existing section, instead of having to add it and then specify the parent.
- Section Navigator can be configured to only show below a specific section, instead of showing all sections.
- Removed dependecy on register_global being on (finally).
Under the Hood Enhancements
- Settings & Installation testing: makes it much less painful to get a site up and running by helping diagnose the hard-to-find show stoppers.
- Event Handling and Notification. Adding, editing, and deleting records triggers event notifications which are sent to custom Listeners. It's not actually used out-of-the-box but it provides a facility for running custom code on your own installation. We're using it to sync database records with a 3rd party e-commerce package on a client site.
- Section Navigator and all section related code respects the NAV_ROOT_EL constant when building out site navigation.
- Cleaned up template and php-code generators. Added a generator to make a simple detail template for a content type.
- Added a more advanced relationship picker widgets. Instead of forcing users to scan a huge list of SELECT OPTIONS, shows options in an iframe which is filterable.
Monday, November 22. 2004
In the upcoming release of Syntax, I've started to address the difficulty associated with getting an instance installed and up and running from the archive file. It's still doesn't work straight out-of-the-box but the new installation tests will save you hours chasing obscure and frustrating bugs. Some features, such as file uploading and Smarty templates, depend on the web server process being able to write, or outright own, specific directories. Because of that, we'll probably never get to a point where Syntax will work without some setup time.
Once you have extracted the Syntax files and setup your webserver to make the public directory available over http, you can access the installation tests at admin/testing/. The testing script goes through a handful of php scripts that output settings and test the connection settings to your Syntax CMS database, check ownsership of key directories, and checks that necessary symbolic links exist. Where possible, the script will try to correct any errors by itself but if it cannot, it shows the exact commands you need to execute to fix anything. The screenshot below is an example of output with an error found.

This was previously mentioned installation tests when I checked the instalation tests into CVS.
Thursday, November 4. 2004
I added another out-of-the-box feature into CVS today. It's a module that automatically builds a sitemap based on the sections you create for content. The output is simply unstyle, nested lists inside of a div with an id named, cleverly, "sitemap". You can use CSS selectors to customize the output of the template. You can also write your own display template to tweak the layout to your liking. This will be part of the next release, which should be real-soon-now.
An example of the sitemap module, with a few added bells and whistles.
Tuesday, November 2. 2004
I've just checked in to cvs a suite of testing scripts that check to verify that you're Syntax site is setup correctly. At Forum One, we've had an internal deployment script to use for setting up a new site. But if you're installing Syntax on a foreign server, you've had to hope that the planets are correctly aligned, that you've followed the installation instructions correctly, and that we didn't leave out a critical installation step. This script, which I've placed in the public/admin/testing directory checks the following:
- availability of smarty and Adodb.
- connection to the database specified in config/db.conf.php.
- Syntax framework initialization
- critical directories are writeable by the web server
This will be a part of the next Syntax release but until then you can check out the module ( syntax-cms/src/public/admin/testing ) from CVS on tigris.
|
|