 |
|
Tuesday, June 15. 2004
We agreed to use the following conventions for numbering versions as we make releases in the future:
- Major revision numbers would indicate radical changes to Syntax or its requirements, such as moving to PHP5 or using XML instead of mysql to persist datatype definitions.
- Middle revision numbers indicate a release that requires changes to the database, either creation of new tables or altering existing table structures.
- Minor revision numbers will indicate improvements and fixes to the Syntax classes.
Friday, June 11. 2004
With the changes we thought were going to be in 0.0.5, we found that the CMS was stable enough (and used in production internally enough) to be called 1.0. So here's a tentative roadmap:
0.0.4 (current)
On the public SourceForge site, this is only the API, and is fairly badly out of date. We've made a number of stability and feature enhancements to it. However, we're going to abandon 0.0.4 as is, because it's not worth updating singly.
1.0 (main trunk)
1.0 has lots of feature and performance enhancements from 0.0.4.
- A big honkin' CMS built with Syntax API technology. We'll put detailed feature lists in a separate announcement.
- Performance: We've achieved between a 2- and 4-fold increase in speed, mainly by optimizing the base classes and adding caching to commonly-requested data.
- Lots and lots and lots of bug fixes.
- A revamped interface for
Context, the content administration tool. It is now very stylable by CSS, has a tabbed interface for assigning privileges and sections, an export module to dump your content for each datatype automatically to Excel, an improved listing of picktables for editing, as well as an all-in-one view of approved and unapproved items, and it does not depend on JavaScript.
- Enhancements to
DBasis, including permissions for add, edit, and delete of datatypes as well as a separation of abstract datatype classes that you can safely replace when you reconfigure a datatype, leaving your user class with any encapsulated functionality intact.
1.1 (development branch)
- Add the ability to "feature" a content object in multiple sections while leaving it unfeatured in others.
- Event notification so you can have actions that occur when something is changed through the administrative classes.
This is tenative, but we hope to go to 1.0 publicly soon. 1.1 will be released...when it's released. We expect some point releases to 1.0 to occur as we fix bugs or release features that don't affect sites built with 1.0. If you just want the API, it's fairly easy to extract those elements from the source tree.
Friday, June 11. 2004
I updated the pxdb_collection class to no longer need to call pxdb_collection::find() after calling pxdb_collection::set_order(). Now you can either explicitly call pxdb_collection::execute() or simply start iterating through your list with pxdb_collection::fetch_record(), which calls pxdb_collection::execute() automatically if there's no result set.
Friday, June 11. 2004
Problem:
I want to change the order in which my records are returned, in SQL this is 'order by my_field ASC'. I see that the pxdb_collection class has the set_order() method, but when I try this it doesn't seem to work. My code is:
$Records = &new pxdb_collection(DATATYPE_DOCUMENT);
$Records->set_order('sunrise DESC');
echo $Records->get_sql();
Continue reading "Changing the order of results: set_order() & find()"
Thursday, June 10. 2004
Riddle me this: Where, oh where, does the Syntax API register or even define the "check_date" validation function?
My answer? Dunno. Spent two hours looking for the little bugger. It must be defined in software somehow so that a grep for "check_date" reveals nothing. Somewhere there is a lambda function generating "check_" and "date", in some sort of bizarre obfuscation technique.
After all, it's not important that we know how we validate dates, is it? I mean, it's not like there are any errors in the code elsewhere, so why should I be concerned?
Update: I found it--it's not in the framework, where one might expect a default dbfield type to be validated. It's set and managed strictly in the Context tool, as basically client functionality.
It's nifty that you can extend the validation a second way like that, but that implies that such validation won't happen when you write an app that uses pxdb_commit and pxdb_input in the regular CMS--or any non Context application, for that matter.
The upshot is, I'm going to change this at some point. In the meantime, beware. Validation that seems like it should be framework level may be happening in client code.
Thursday, June 10. 2004
Securing dbasis with the standard, Syntax session-based authentication turns out to be relatively simple. The version of dbasis in cvs now has this for all future sites going forward. To secure exisiting instances drop in the following code after line 115. This requires a login from a user in the admin group.
line 115: $session->initialize();
# Authentication
# --------------
require_once($PXDB_PATH . '/classes/auth/pxdb_auth.class.php');
$auth = &new pxdb_auth('dbasis');
$auth->set_username_field('idnum');
//$auth->debug = true;
// restrict to admin group
if($_GET['logout']) { $auth->logout(); }
$auth->restrict( 'admin' );
if(!($user = &$auth->authenticate())) {
//include(SITE_ROOT . '/display/header.disp.php');
$auth->showlogin();
//include(SITE_ROOT . '/display/footer.disp.php');
exit;
}
Thursday, June 10. 2004
I had to re-figure this out today, so I thought I'd document it to save hair-pulling later.
If you are mucking about with Syntax's API innards (the pxdb_* classes) and make a structural change to the database, you need to create an upgrade script to handle it.
Background: Every time the Syntax API gets used, it calls PxDB/config/initialize.php. This checks to see if its sister-file run-once.php has been modified more recently than the database has been initialized. If so, it runs it.
initialize.php has a place to define the current version of the Syntax API. This is used by run-once to determine if an upgrade script needs to be run. If the version number is lower in the database than the file, it runs the script. If the version number is higher in the database than the file, it fires off a warning. If two version numbers are the same, it does not include an upgrade script.
The upgrade script goes in PxDB/config/install/ and should be named according to the ADODB name for the database you're using followed by a hyphen and the word "upgrade", e.g. mysql-upgrade.php. The script should ideally check the version number and retain previous upgrades, so theoretically someone could go from a version 0.0.1 to the absolute latest and catch all relevant upgrades.
You should also test for the existence of various columns and tables that you wish to affect so you don't get someone with a mismatched version number in too much trouble.
Once you've done all your testing, alter any tables and convert any data. Finally the script should set the version number in the DB pref key to the version number you've declared in initialize.php IF AND ONLY IF every SQL statement has executed successfully.
Note: This is true as of version 0.0.5. Oooh! Did I slip some news in? Maybe!
Thursday, June 10. 2004
Problem:
On a Syntax site, You have a uri like
http://www.mysite.com/content/news/detail/5678/ and you need to extract
the number to use as your record id:
Continue reading "From Oscar: Extracting parameters from Request URI"
Tuesday, June 8. 2004
To access values in the widget parameters box ( the mysterious text input below the widget drop down in dbasis), in your widget script you have to access the $plugin_info['params'] array. It will have a hash of your key=>value pairs which are semicolon separated.
Example:
in the mystery text box your have
'watch=topic;relid=29'
in your widget script you can get the values via:
$watch = & $plugin_info['params']['watch'] ;
$relid = & $plugin_info['params']['relid'] ;
This sounds like something that should be in the syntax wiki...
-Oscar
OK, how about the blog instead?
Tuesday, June 8. 2004
One of the features syntax provides via content input forms is a widget that allows users to upload files to the site and make them available to visitors. This feature entails more than just putting the uploaded files in a directory in your public site root. This article focuses on how files are served to site visitors and we won't touch upon how the actual upload is handled.
- Uploaded files are saved to your sites filestore. This path is specified by the datastore, path preference.
- The datastore, url preference tells syntax to prepend that path to file path saved in the records table. Syntax also prepends the record id to the file. By default, the datastore url is '/files'. If you change this, you'll have to change an apache rewrite.
- When a user requests a document, a rewrite rule sends the request through public/files.php this file does the following:
- Checks if the file's extension matches the FILES_PASSTHRU_REGEX, if so it is sent to the user. By default, the files passthru regular expression is meant to catch image files.
- If it is not a file, it checks to make sure that the user is allowed to read the record that the file is attached to by parsing out the record id. If so, the file is sent, otherwise a 403 Access Forbidden header is sent
One last thing to note is that newer versions of files.php will save bandwidth by looking for a If-Modified-Since header from the browser and if the file hasn't been changed since that file, it'll respond witha 304 Not Modified header.
Monday, June 7. 2004
Got this odd little bug forwarded to me from a client:
There seems to be a minor bug in the Article / Resource "add" page, and perhaps elsewhere, but I haven't tried to track down whether or not it comes up everywhere. When the time of day is between the hour and the half hour, the default posting time is 12:00am. After the half hour, the default posting time is the correct time of day.
I looked into it and it was a weird bug left over from the initial implementation. I fixed it on a test site and checked it into CVS.
The original author was making the number of minutes round down to the next lowest 15 minutes this way:
floor($minutes / 15) * 15
(and casting it to an int) but then he simply concatenated that value with the number of hours, which worked great 3/4 of the time. In the case of anything less than 15, however, that expression evaluates to zero, so after concatenation, you got:
10:0
instead of the
10:00
that you would expect. A quick sprintf() fixed it.
The upshot is, the bug only happens on the first 15 minutes of each hour, which is why nobody from our first Syntax client forward has noticed it until now, I'm guessing.
Anyway, if you see this bug, that's the class to update from CVS.
Update: Oops, that class I'm referring to is pxdb_widget in private/lib/ext/PxDB/classes/content/input/
Monday, June 7. 2004
I've had two instances of the same bug today. The symptom is this:
You use Context, the Syntax CMS administration tool, and it works fine except that once you login, any link you click on will take you back to the login screen. It just can't remember your login.
That's because it can't write the session files it needs. The solution is twofold: Make sure the directory private/tmp/session/ exists and is readable and writeable by the Web server. Then, in your public/.htaccess file, make sure that this line exists and points to your site:
php_value session.save_path "/path/to/your/Syntax/CMS/instance/private/tmp/session"
Once you do both of those, your admin tool should work (or at least be free of that problem).
Monday, June 7. 2004
One of our contractors today had an issue with the pxdb_auth class and login behavior. He wanted to submit a login form but stay on the members page he was submitting the login to (instead of $_SERVER['SCRIPT_URL'] as is expected). Even though the URL changed to reflect the fact he was POST-ing to a different URL, the section he'd logged in from stubbornly kept displaying.
It turns out that there are two hidden variables that by default are passed with login forms (you can see them in the login.tpl template). They are preserved_get_vars and preserved_post_vars. While the pxdb_auth class doesn't do anything different because of them, it does directly array_merge() them into the $_GET and $_POST arrays directly.
And in /private/init.php we see this line:
$Request->setPath($_GET['request']);
That means that the preserved_get_vars were encoding the current request path and passing them along. pxdb_auth->authenticate() was blythely putting them into the $_GET array, and the above line in init.php set the script to the previous request path.
The upshot being that no matter what you set the login form's action to, it would be clobbered by the preserved_get_vars setting for request.
I suppose the rationale behind this was to preserve any variables, such as ad-hoc search terms or sorting, and make sure that simply logging in to a URL didn't divert you from the exact page you were trying to view in the exact state you were trying to view it in. However, I think that's a kind of fragile way to do it, and maybe too limiting. I'm not sure if it was really intended to preserve the request path as well, and I'm not sure why the request path should always be expected to be in the $_GET variable.
So that's the way things work in the pre-release version of Syntax CMS, but I'd not rely on this behavior, as I think it's a prime candidate for correction in the near future.
Friday, June 4. 2004
This is an echange where Hans laid out his approach to error handling in Syntax CMS, and I added thoughts on error handling in general.
I know that error-handling, logging & the load that places on the server is becoming increasingly important. The error-handling/logging framework I adopted for GlobalEU should help eliminate excessive server load. Essentially, instead of sending an email or opening a log file each time an error is triggered, error messages (and debugging messages, if applicable) are collected and only written to the log file at the end of the script.
I used PEAR's error handling classes -- with a small PHP function that served to pass all PHP errors through the PEAR error handling mechanism. My error handler, Site::errorHandler(), knows to re-direct to an error page if error is above a configuration-specified threshold (i.e. fatal) and otherwise (if the error level meets the 'logable' criteria) will simply add the error to the Log queue.
That's all pretty standard. The different thing is that the log is only written at the end of the script. This is done by registering a shutdown function w/ PHP. My Site::shutdown() method performs all logging and any other cleanup actions, and is registered with PHP like this:
$Site = &Site::singleton(); // b/c you can't register static methods
register_shutdown_function(array($Site, 'shutdown'));
Doing logging at script termination will mean that an error email or mysql insert will only happen once per script execution, and not once per every error on the page. (Though, I think Jo would prefer we not use either of those methods for error logging.)
My reply:
The other good thing about Hans's approach here is that provides a hook for explicitly handling errors for the user. This is something we're starting to do but can do more of.
In my old classes, I would throw a warning as soon as an error occurred and then immediately return false from that function. The calling code would test for that, and either compensate or throw an error and return false itself, up the line until I got to the page level code, which would also verify that no function or method it called threw an error, otherwise it "handles" the error and triggers its own warning.
So even if you don't replace PHP's error functions with your own (ideal), you can still explicitly handle things at the warning level and provide non-ugly recovery or a friendly notice to your users. Either way, we should be testing for failure and providing code that works in case of failure so our users don't see broken-looking or error-ridden pages.
Sadly, pxdb_* classes were not built with that level of error handling. Also, we found out that PEAR::Error is a huge performance hog, and we sped up the sites noticeably by ditching it...and additionally, we got more reliable error reporting, especially for warnings that should have been dealt with before sites moved to production.
I think we need to move back to a Syntax CMS-level function that handles fatal errors (E_ERROR or E_USER_ERROR) and does the redirecting to an error page--but this time it won't be identical to the authentication failed page and the file not found (404) page.
Friday, June 4. 2004
Still going through my old inbox entries. This one talks about the history of filter classes and gives a bit of the rationale for the current design. Would it had been discussed a bit more (it could be smarter about left joins)...
From: hans@forumone.com
Subject: [classes] next generation filtering
Date: September 5, 2002 10:32:56 AM EDT
To: dev@forumone.com
Hi F1devers,
For those of you who have used the f1db_filter class, I have a new f1db
filter class available [built for PHlexDB, but does not depend on
PHlexDB framework] that is infinitely more flexible.
The current f1db_filters class has 1-level of filtering depth. I.e. you
can filter on docs related to a given author, or on authors related to a
given organization, but there is no way to filter on docs related to
people who are related to a given organization. For BYJ, Sandy hacked
the class to support 2-level deep filtering on picklists (I think it was
to add ability to filter on X related to X that has a certain picklist
value).
The new filtering paradigm has no limitations on levels of depth. Also
filter components can be re-used & re-combined to produce different
result sets.
It's pretty slick -- I've used this filtering framework extensively on
new project spaces "intranet" page, where you will be able to see, e.g.,
all documents which are related to a project of which you are a member.
Additionally, the new filtering class is actually a "search" class --
you can choose whether you want to filter (i.e. 'exclusive') or search
('inclusive') the records table.
Bear this in mind if you think you could use more flexible filtering
systems in a project.
Cheers,
Hans
|
|