 |
|
Wednesday, May 23. 2007
A short missive on using the file path constants that SyntaxCMS. Relative paths can make your applicatoin more fragile than it needs to be (see dbasis), so don't do the following:
include realpath('./../../stx/lib/documentInfo/documentInfo.php');
The correct way is (note the parens around include as well, that's our coding standard)
include(STX_LIB_PATH . '/documentInfo/documentInfo.php);
There's a corresponding SITE_LIB_PATH for private/lib, which is for project specific includes. You can see what global path constants Syntax sets up in stx/init/init.urls.php. Also, realpath() incurs a stat call, iirc, which degrades performance.
Next:
$doc = new documentInfo();
$doc->set_file(realpath(SITE_PATH.'/..') . $Record->getFile());
There's a constant for the files path - PXDB_FILESTORE_PATH, so the above should be the following. The basename call is extra, because int his case Syntax is storing the filename as "/files/205_file_myfile.pdf" due to a pxdb_prefs setting.
$doc = new documentInfo();
$doc->set_file(PXDB_FILE_STORE . '/' . basename($Record->getFile()));
First, note above that the name $doc is a bit misleading, a better name would be $doc_info. Instead of embedding this functionality in a specific template (the detail template in this case), fetching the file information should be encapsulated as a method of the Document object by adding the following to lib/Document.class.php file. A review of the documentInfo API turns up a method that returns a document Info object for a file in a SyntaxCMS instance, named stxFactory and takes the file value as a parameter. So we add the following method to our Document class definition:
/**
Returns a documentInfo object for the File field.
@access public
@return object
/
function getFileInfo()
{
// only need to instantiate this once per object
if (!isset($this->_docInfo))
{
$this->_file_info = documentInfo::stxFactory($this->getFile());
}
return $this->_file_info;
}
Why is the extra effort worth it, if the starting code works? Imagine that a week from now, you're asked to display the file, and its size and type information, wherever it is listed. Are you going to copy and paste that snippet to multiple templates? What if you discover a bug in the code you cut and paste - how can you be sure you hunt down and correct all the copies? With good encapsulation your display template(s) are getting the values they need to display from a single source.
Monday, May 21. 2007
Over on the Syntax CMS site, I've posted a PDF guide to working with the General module, which you can download. A lot has gone into the general module since the last official release to automate and standardize how routine lists of Records (of one Content Type or mixed Content Types) can be built.
SyntaxCMS also now, through the general module, creates usable, well organized content archives with minimal development effort. You can view such archive pages on recently launched SyntaxCMS sites such as Alliance for Aging Reseearch.org, National Alliance for Public Charter Schools.
Thursday, January 4. 2007
Syntax's built in search engine has had search suggestions for a while now, you can see it in action on NCLR's site. These "best bet" recommendations are a simple match for the user's search query in the name field of each object. This makes sense since for relevant content the keywords are often within the title of a press release, publication, or person.
Search tools has looked into search suggestions, and come up with eight principles for good search suggestions.
Search suggestion systems complement search engine results with human judgment, providing links to specific landing pages for common search terms where the algorithmic results may be confusing or unavailable.
The list is an excellent set of recommendations that has me thinking about adding some intelligence to our search engine. Particularly the idea of of logging search queries and using that data to understand what users are searching for and fine tune recommendations. I could see a system that:
- Tracks search term frequency by month, incrementing the count for a search term in a simple table with fields for the search query, the month, and count. You could then use that data to see what are popular search terms in a given month and also analyze how terms change from month to month.
- Use the log to provide suggested search terms as the user types. For example, if the type in "Leg", a small drop down appears with "Legal" or "Legislation" as possible matches. Using jquery and its autocomplete plugin, this wouldn't be technically difficult to implement
- Provides a way for site administrators to view search query data. A simple log can provide some insight into what user's are looking when they visit.
You'd probably need some sort of filter so that profanity and offensive terms don't get logged in the system and shown to other search users. Since search is a common navigation tool, improving the search interface would improve the user experience.
Monday, September 25. 2006
A vulnerability was discovered in SyntaxCMS testing code that can be exploited to include a remote file. If you're site is running with php's register_globals turned on, and allow_url_fopen turned on, with PHP 4.3.0 or later, you may be vulnerable. We've prepared a patch to fix the vulnerability, which you can find here.
If you can't update from CVS or patch your system you can also disable register_globals and allow_url_fopen, delete the public/admin/testing directory, or drop the following .htaccess file into public/admin/testing/tests if you are using Apache:
<Files .php>
deny from all
</Files>
Monday, August 28. 2006
We've rolled out SyntaxCMS on a handful of low cost, shared hosting providers and found our initial experiences more frustrating than they had to be. Of course, we expected a number of difficulties, primarliy because of the directory structure we assume. By default syntax cms expects:
+ Your Site Directory
- private
- public (document root)
The public folder contains all the files that Apache serves to the public, while the private directory contains all our code and configuration settings safely outside of the document root. On most cheap ISPs, you can only put you files in your web root and that requires a lot of tinkering.
Another limitation is not being able to add files to your host's PEAR directory. Since SyntaxCMS depends on Pear_Cache, this is problematic if your ISP doesn't provide it. To make life easier, we've added a private/lib/ext/PEAR directory that is added automatically to your include_path. If you need to include a pear library, extract the archive into that directory and SyntaxCMS will find it.
This is currently in the latest CVS versions but a new release should be just around the corner.
Friday, June 9. 2006
We've added a lot of very convenient methods to various SyntaxCMS classes to automate repetitive tasks and overall make common tasks easier. Here are 8 tips for using the API.
1) Get a URL to a Record's detail page.
Perfect for a module or template where you're working with muliple content types. It also makes it possible to rename a module without having to update templates.
<a href="<?= f1cms::getDetailUrl($Record) ?>"><?= $Record->getName() ?></a>
2) Get a section's absolute URL on the site
Sections, which are essentialy a site's pages, also have a method to return a public URL.
<a href="<?= $Section->getNavPath() ?>"><?= $Section->getName() ?></a>
3) Get all of a section's ancestors as a collection object
In some cases you might want to know all the ancestors for your section, maybe for building a breadcrumb.
$ancestor = $Section->getAncestorCollection()
4) Tell the general module to use a custom listitem template
The general module is very flexible in how it can retrieve lists of content. It has some built in automatic logic for determining what template to use to display a particular record in a list. You can override this behavior by passing the list capability a parameter named listitem.
echo f1cms::callModule('general', 'list', array('listitem' => 'summary'))
This will have the general module look for a file named listitem-summary.tpl first in the template director of the module that handles a datatype. If that module does not exist or have that file, general will look for the template file in its own template directory.
5) obfuscate and email string
Useful to hide email from some spam harvesting bots.
echo StxUtilities::obfuscate_asci('omerida@example.com');
6) Test if a record contains a field with a given name
In cases where you are working with collections of mixed content types, you may not know if a given record has a particular field. You can test for this with the following code:
if ($Record->has_field('upload'))
{
/ do something /
}
7) Test if a record is approved
Usually, a Collection object will only return approved records. If you need to test this at the record level, you can do:
if ( true == $Record->is_approved())
{
/ do something /
}
Test if the current user is authorized to see a record
Again, a Collection object will only return records that the current user can read. If you need to test this, use:
if ( true == $Record->is_authorized())
{
/ do something /
}
Thursday, April 13. 2006
If you need to calculate the properties of an object when its created or edited by users, you have two choices with SyntaxCMS. One option is to use the relatively newer Event Dispatcher. You'll have to create a custom event that listens for a create or update event for the content types that you're interested in that will calculate the new properties. This is probably the most powerful way, and as I found out, you're guaranteed that the Event Dispatcher will notify your events whenever a create or update event occurs.
The other option is to define fields within your content-type as "autogen" plugins. These plugin types have been in SyntaxCMS since the beginning and are a rudimentary and straightforward event to calculate the value of one property based on other object properties. One limitation of this method is that, if you use a content-type view to limit the properties a user can edit, if you ommit your autogen properties from the view, they will not be calculated. Since they are not in the view, when pxdb_commit goes to save the object to the database, it doesn't know about those properties. Since event notification hooks are not tied to the fields being edited by a user, a custom event would still be notified to calculate those properties.
I hope the description above is not too wordy and if it is I'd be glad to help anyone sort it out inthe comments to this post.
Monday, February 20. 2006
A Cross-site scripting vulnerability has been identified in ADOdb's adodb-pager.inc.php. A secunia advisory is available. While SyntaxCMS uses ADOdb to abstract the database connection layer, we do not use ADOdb's pager script to display links pagination links and are not affected by this vulnerability.
Tuesday, December 20. 2005
A scrollable list widget like the ones shown at Check it, don't select it would be a great way to improve the usability of the forms we generate. Checkboxes would perform better than the current drop-downs for multiple selects because they would not require a round trip to refresh the form as you add each element. One could also implement some pretty simple javascript to filter options by the first letter of the value, or add letter heading that show/hide option's grouped by the first letter.
Tuesday, December 6. 2005
In case you've been wondering what we've been up in terms of improving and enhancing SyntaxCMS, I've put together this overview of new features and fixes we've committed to CVS since the last release.
Continue reading "CVS Changes Roundup"
Wednesday, September 28. 2005
Rob Sullivan has an article on choosing a content management system with questions to ask to evaluate how search engine friendly resulting pages are. I thought I'd take a moment to evaluate how SyntaxCMS compares to his criteria.
Does the system support unique meta tags?
SyntaxCMS supports unique metadata for each page (section in SyntaxCMS) and they are modifiable. However, SyntaxCMS does not provide unique meta-tags for detail pages.
Does the system support static pages?
By static pages, Rob actually means clean urls with no query strings. SyntaxCMS does use clean urls for the majority of content, specifically for sections (pages). It does not require session variable or other dynamic variable to display a page, a URI is sufficient to access any page (unless its not viewable by the public). However, once you start adding in filtering and pagination of content lists, it will use a query string.
How flexible is the folder structure?
He also suggests that it'd be best if "all pages could reside in the root folder", as he says that pages deep in subfolders are ranked lower in relevancy by search engines. SyntaxCMS uses the "directory" structure in the url to figure out what content to retrieve, so this leads to urls that are longer than his ideal. I don't think this really ranks heavily in search engine relevancy, there are more important factors to optimize. These factors include using good title links, good text for links ( no "Click here" nonsense), and overall good content.
What platform does the CMS need to run on?
SyntaxCMS is intended to run on any platform that supports apache, php4, and mysql. Currently, it is most tested on linux distributions. It does run on windows systems but since mysql on windows doesn't support the ENCRYPT() function in the same way it is not usable. This is something we are looking to address in the future by migrating away from the ENCRYPT function.
What kind of customer service does the CMS company offer?
SyntaxCMS is open source, anyone with decent PHP/MySQL skills could add functionality. Forum One Communications offers commericial development, hosting and support as well.
Monday, September 26. 2005
I've just checked into CVS updated section handling code that verifies if a user (or the public user 'Everybody') has been given read privileges to a requested section. Remember, sections are what make up the page-based content management part of Syntax CMS. The ability to specify the privileges has been in the content administration application for quite a while now, but the request handling code wasn't enforcing it at all. Now, when you request a section, SyntaxCMS will first check if the user has 'read' privileges to that section and all of its ancestors.
This means you can create a section called 'Member Only' and then create children sections beneath it. By just restricting access to the 'Member Only' section, you're also effectively restricting content to all of its descendants (not just its immediate children).
I also fixed a very broken getAncestorsCollection method in the SectionNavigator class and eliminated a lot of php notices as well.
Thursday, August 25. 2005
This is a must read: Six deadly PHP sins. Its a perfect summary of practices to avoid if you want your code to be maintainable and usable to someone 2 weeks from now. It's also nice to be able to say that we avoid all of those practices in our code for SyntaxCMS. It maybe over-engineered in some parts, uses eval's in a few spots (though I tried to remove those but couldn't), and it does use Smarty for just one thing, but it does seperate logic from presentation pretty well, abstract out working with the database, and functions are organized rationally into classes.
Sandy points out that the article needs spell checking but other than that you should set aside 3 minutes to read it.
Wednesday, August 10. 2005
Heres a quick run down of new features sitting in CVS as we make progress towards our next realease: 1.3.0
- Revamped Event Calendar module with a new monthly grid view. It correctly handles events spanning multiple days/months. The Event object also has a convenient method to pretty print the start to end dates. So if you're event is only one day it writes August 18, 2005, multiple day events within a month show up as August 18-22, 2005 and month spanning events in a year correctly show just the month and days. See CGD's Calendar of Events
- A module that can read and write RSS feeds.
- Admin Section Navigator: significant speed improvements and the option to work within a specific part of your site's navigation tree. This cuts down the clutter and scrolling needed to build out a part of your site.
- PHP5 compatibility
Wednesday, April 27. 2005
In this part, we'll look at using dbasis, the web-based developer tool for Syntax, to create content types, define their fields, and make them available to users of the admin tool for our blog module.
Continue reading "Build a Blog Part 2 - Working with Content Types"
|
|