June 18, 2008

Events and why using references is so nice

Filed under: PHP, ZenMagick — DerManoMann @ 1:58 am

I just checked in a couple changes that fire new events in case of a new account being created. The really nice things is now that event listener have a chance of modifying the account directly without having to change a single line of core code (or globals!).

For example, the following code would change the default authentication status for all new accounts:

class Blocker {
public function onZMCreateAccount($args) {
$account = $args['account'];
$account->setAuthorization(ZM_ACCOUNT_AUTHORIZATION_BLOCKED);
}
}

ZMEvents::instance()->attach(new Blocker());

I guess it couldn’t be any easier than that (other than re-defining the default authentication value ;)

June 11, 2008

compressing PHP packages

Filed under: PHP, ZenMagick — DerManoMann @ 2:03 am

I have written before about how I managed to compress Creole into a single file. Now, I have extracted the more generic bits of code into a single utility class. The class has a couple callback methods to cope with custom handling. Actually, I implemented those callbacks exactly the way I needed them to implement the creole specific code, but it should the typical exceptions.

To use this, I added the first CLI script to ZenMagick. I do not expect a lot of user to require to run it, but it makes for a nice example of how to use the class.

For those interested in all the gory details, here is the source of the script:


// load ZenMagick core
$coreDir = dirname(dirname(__FILE__)) . '/core/';
require $coreDir.'ZMLoader.php';
ZMLoader::instance()->addPath($coreDir);
ZMLoader::resolve('ZMObject');
ZMLoader::resolve('ZMPhpPackagePacker');

/**
* Custom class for Creole specific dependency handling.
*/
class CreolePacker extends ZMPhpPackagePacker {
/**
* {@inheritDoc}
*/
public function isResolved($class, $level, $files) {
// Record does have circular references
return (’Record’ == $class && 1 == $level);
}

/**
* {@inheritDoc}
*/
public function finalizeDependencies($dependencies, $files) {
// there is no explicit include/require for this
$dependencies[’DebugConnection’][] = ‘Connection’;
return $dependencies;
}
}

// pack; ideally path/version should be CLI args…
$creoleVersion = ‘creole-1.1.0′;
$packer = new CreolePacker(’c:/temp/’.$creoleVersion.’/classes/’, ‘c:/temp/’.$creoleVersion.’.packed.php’);
$packer->setDebug(false);
$packer->packFiles();

The script extends the generic package packer class to implement custom callbacks. Creole is actually a quite easy to analyze, as almost all (except for one Connection) dependencies are covered by include and require statements.

So, executing the scirpt will result in the new file creole-1.1.0.pack.php which is about 187kb large and, at least for the default drivers, makes the custom class loading in Creole obsolete.

long term I hope to be able to extract the generic MVC code out of ZenMagick and compress is using the some similar code. This will require some more work, though, as the current class does not look at extends and implements of classes. Since all code depends on the loader, rather than import/require, analyzing those will be required in order to build a proper dependency map.

Should anyone use this for their own project, then it would be great to let me know.

May 8, 2008

Compressing Creole into a single file

Filed under: PHP, ZenMagick — DerManoMann @ 5:28 am

Right, I am just about to check in some new code that makes will make it very easy to import/prepare Creole for the ZenMagick loader architecture. The new (mostly unused) class ZMPhpCompressor also allows to squezze a full Creole release (everything under classes) into a single 188kb file.

I am actually not sure if I should include that already with the next release, as right now there are probably about 3 or four queries per request done by the new API and I might as well stick with the existing code a bit longer - we’ll see.

The code depends on two other ZenMagick classes, so it’s not very portable (if anyone is interested), but apart from that it works fine ;)

The actual code to do the magic looks like this on my XP box:

$creole = 'creole-1.1.0';
zm_creole_import('C:/TEMP/'.$creole);

$comp = new ZMPhpCompressor();
$comp->setRoot(’C:\Program Files\Apache Group\Apache2\htdocs\zen-cart\zenmagick\core\ext/’.$creole);
$comp->setOut(’C:\Program Files\Apache Group\Apache2\htdocs\zen-cart\zenmagick\core\ext/’.$creole.’.php’);
$comp->setTemp(’C:\Program Files\Apache Group\Apache2\htdocs\zen-cart\tmp’);
$comp->compress();

Not sure how often I’ll be using this, but it’s nice not having to try to remember these things once they are needed again!

The only caveeat is that compressing into a single file breaks the Creole ‘dot-path notation’, so in order to use the MySQL driver you’ll need to do something like:

Creole::registerDriver('mysql', 'MySQLConnection');

to avoid errors about missing drivers. Since all database access in ZenMagick is handled by a single database provider class that’s not really an issue, though.

That means the last open issue is to write some proper release notes - oh, well, babysteps ;)

April 2, 2008

writing a database abstraction layer…

Filed under: PHP, ZenMagick — DerManoMann @ 4:24 am

Writing a database abstraction layer is definitely not something I had in mind when stating ZenMagick :) On the other hand I really enjoy this sort of work - in fact much more than working on new store features.

So far I have a single interface ZMDatabase that will eventually be used to access the database. Right now there are two implementations and the implementation class is configured via a setting.

The interface is not complete yet, I’ll add stuff as a go through the code and convert database access. Currently there is only ZMManufacturers upgraded to use the new code and it works perfect.

Only worry right now is that Creole may throw Exceptions. In itself that is not a problem - is’s actually a nice change to know whether things have worked or not. However, currently none of the code is the least exception aware.  I probably should change that before going to far down that way to avoid having to redo a lot of changes.

I just fear that by starting that can of worms I’ll end up rewriting most of the current dispatch code in order to properly handle exceptions throughout the request process… Oh, well, one step at a time…

March 31, 2008

*importing* creole into ZenMagick

Filed under: PHP, ZenMagick — admin @ 3:41 am

Today I spend some time massaging Creole to properly load in ZenMagick using either ZMLoader or as part of core.php.

There were a number of issues I ran into:

  1. include and require statements in Creole sources rely on the PHP include_path
  2. Some files are missing the closing ‘?>’
  3. DebugConnection.php does not include/require Connection.php, breaking the otherwise perfect dependencies
  4. Record.php includes a require for QueryDataSet.php which actually creates some sort of circular dependency loop, since QueryDataSet.php also depends on Record.php

#1 was to be expected in one form or another, so it wasn’t really an issue.
#2 is actually something I do not really understand, but then, I never had the time/energy to read the PHP specs to figure out why this is working at all. If you know, feel free to leave a comment…

#3 turned out to be a problem, because in order to be able to include all files in core.php I had to rearrange all source files based on dependency. A short script that build a simple dependency tree was easily done based on include/require statements, except for this one file (which I ended up hardcoding in the script…)

#4 was really annoying because it meant that initially I had to patch Record.php in order to get all files loaded at all using the include_path solution (which is the documented way of installing Creole!) . Eventually I changed my *import* script to load the files from a non ZenMagick folder, so no initial loading was done.

One thing that might come out of this exercise is that hopefully I will have time to split ZMCoreCompressor into a generic class and a ZenMagick specific subclass. That should allow me to easily build a single file Creole version that can then be included in ZenMagick versions instead of the full 90 odd single files (this is version 1.1). I might strip this down, though, excluding all non MySql drivers as there is currently no point loading them…

One really nice thing I discovered was that Creole follows a concept of filename-classname relationship very similar to ZenMagick. That definitely made it a lot easier!

March 26, 2008

database progress

Filed under: PHP, ZenMagick — admin @ 5:14 am

As a first step of migrating to a more sophisticated database access system I have started with adding a simple layer (read: interface) that eventually will replace all $db usage. The interface will provide some simple methods to read/write the database using a lot of the ZenMagick binding code.

That should make it easy to replace the current $db based implementation with something different. The nice thing right now is that I can migrate services and other database access classes one by one without breaking anything.

Once all code is converted to using the new interface I’ll start investigating alternative implementations. I really like Creole, as it looks (intentinally) a lot like Java and the interface design is done with that in mind, so it will be easy enough to create an implementation using Creole…

March 13, 2008

CakePHP

Filed under: PHP — DerManoMann @ 10:05 pm

For a current project I joined the growing number of people using CakePHP.  Even though I didn’t use any of the bakery options if found it mostly very useful.

Of course, there is the time spend to figure out how all fits together and I pssobily haven’t even touched half of the features.

One thing that I noticed, though, is the lack of consistent documentation. I mean, there is lots out there, but usually the stuff that breaks is so specific that it really takes a while to find the answer. On the other hand the CakePHP newsgroup was more then helpful for me.

There were two big issues I had so far:

1) Upload progress bar.

Thi si snot really CakePHP specific, but it took me a while to figure out how to tell the controller to not use a layout and view. But then, I usually prefer to read sources rather than read documentation.

But before it came to all that there was the realization that PHP doesn’t really make it easy to do that at all. As of PHP5.2 there is basic support, but even then it requires to install an extension in order to be able to really doe something useful.

Further complications are that the code seems to be less reliable on Windows installations. After some late nights experimenting with the sample code of the extensions author I tried an alternative demo which finally worked.

Still, it took me a ling time to figure out why my upload form wasn’t working when the demo could do it.

Two things really stand out here:

  •  The form needs a (hidden) MAX_FILE_SIZE field.
    Interesting is that the value that works is 411353512 which I believe is the default value. It doesn’t matter if PHP is configured differently. Even though I was able to upload larger files, increasing the value broke the upload progress extension (or PHP)
  • Each file input field needs a (hidden)  UPLOAD_IDENTIFIER field with a unique value. That value is then used to track progress.
    Again some very interesing things here. First of all the identifier field has to be right before the field input, it’s no use putting them all at the begin or end.
    The secod thing which took a lot longer to realise was that in order to work an additional identifier field was required after the last field input.

2) Session handling

Once I had the progress tracking basically working I ran into the next problem. Even though everything was working fine when doing it manually, tracking progress using Ajax caused the session to expire.

More experimenting showed that parallel or overlapping requests would cause the same problem. So, hitting reload a few times would make the session invalid!

This is where the CakePHP newsgoup kicked into action. After some very speedy responses and quick testing it turned out that the setting Security.level was the culprit.

It seems that recently the code was changed so the high setting would regenerate the session id for each request! that means with parallel requests the session id gets lost!

To sum it all up: I think CakePHP is really useful and does a lot of stuff assuming (rightly so) that most web apps works pretty much the same (login, authentications, sessions, forms, htm you name it).

However, once you need something more individual it takes a while to dig out all the nitty gritty details needed to make it do exactly what you want.

May 18, 2007

going commercial?

Filed under: General, Mozilla, PHP, ZenMagick — DerManoMann @ 12:13 am

.. not quite, but I am happy to announce that I am now able to offer commercial support and coding for ZenMagick,  zen-cart, Mozilla (Extensions) and other web work (Java, JavaScript, HTML, CSS, the works).

The official company website is mixedmatter.co.nz. Not a lot there yet, but i’s in the making…

Just to be sure, ZenMagick is FREE and will always be FREE (have a look at the licence if you don’t believe me). Still, I feel that there is perhaps a need for some security about ZenMagick and the future of it, especially for developers/companies that plan to use ZenMagick for their work.

There will also be an official announcement on the mixedmatter site once we get around to doing that. Until then, this somewhat informal announcement will have to do.

March 21, 2007

code

Filed under: PHP, ZenMagick — DerManoMann @ 11:25 pm

PHP is a scripting language. As such it is quite easy to put pieces of code that are used in different places into a separate file and include/require it when needed. This was and still is common practice, especially when not taking an object oriented approach.

So, what is wrong with it?

Every now and then I need to trace request processing in zen-cart to figure out what actually happens. This can be a very frustrating process as zen-cart does exaclty what I described above. Furthermore, there is code to load and instantiate classes and utility code on demand. Don’t get me wrong - this is perfectly legal and ZenMagick has also some code to do stuff like that.

What happened yesterday was that I was trying to fix a bug in ZenMagick code. On the checkout success page there is the option to select products that you are interested in and for whose you want to get update notifications. This was broken, as only one product got picked up, rather than all selected.

Eventually, I found that ZenMagick’s zm_href(..) function does not handle multiple values for a single request paramter correctly (for example: notify[]=3&notify[]=19) . The square brackets are the PHP way of creating an array of values in the request parameter arrays $_GET and $_POST, respectively.

Anyway, before I could find that, though, I had to find my way through includes, redirects to the same URL just with a different action value in the URL, redirects and eventually came across main_cart_actions.php. They only reason that I looked into that file was that a global searchfound the string notify in it. Now, thanks to the zen-cart event handling, there is lots of notify around, but still. So, it turns out that updates to product notifications are handled by the shopping cart! WTF!

The basic idea in zen-cart’s architecture of having a dedicated folder containing code to handle a particular request is not bad. But every time I am looking for something special, it’s handled in a special file that sits on a higher level. Makes sense as the code is shared between different requests. on the other hand it’s usually hard to find even though more often than not I look there first!

February 22, 2007

progress

Filed under: PHP, ZenMagick — admin @ 11:27 pm

While working on the upcoming release 0.7.0 I noticed some issues with the current release that I want to address first. In other words, there will be a version 0.6.4 shortly.

It will be a pure bugfix release including things like:

  • The current release identifies itself as 0.6.2 rather than 0.6.3
  • There is a small fix to the JavaScript validation
  • Sending gift vouchers is broken (my favourite thing to break, it seems)
  • Pretty links are broken :/

(more…)

Next Page »