Since IP.Board 2, we've had a "kernel" of classes which IP.Board uses but do not depend on IP.Board to use. A selection of these kernel classes includes DB management, file uploads, emailing, RSS parsing and reading, XML parsing and reading and our proprietry archive format XMLArchive.
For example, you could use "classUpload.php" and "classImage.php" in your own modifications or extensions to handle uploads and GD thumbnail generation. You would not have to initialize the registry or do anything else other than just include the file and use it.
As we took the plunge and went ahead with making PHP 5 a requirement, we were able to make some long-awaited improvements. Here are the high-lights.
Custom Fields
Josh has completely re-written custom field handling within IP.Board and this class ties it altogether. Josh uses just about every PHP 5 trick in the book including abstract classes, interfaces and ArrayAccess to provide a simple clean interface that can be used in almost any project. It doesn't have to be limited to just IP.Board's custom profile fields.
Graphing
Remco has extended this class to include many new graph types including "funnel", "bubble" and "radar" graphs so that presenting data is more relevant. As IP.Board 3.0.0 develops, we'll be making good use of these new methods for statistic reporting within the ACP.
GD and ImageMagick
Brandon virtually started from scratch with our GD image creation. He also wrote a class for imagemagick offering more choice for those who have it installed. It's now very simple to resize an image or add a watermark.
$image->init( array( 'image_path' => "/path/to/images/", 'image_file' => "image_filename.jpg" ) ); //Set max width and height $image->resizeImage( 600, 480 ); // Add a watermark $image->addWatermark( "/path/to/watermark/trans.png" ); $image->displayImage();
$image = new classImageGd();
XML Parsing and Creating
We've had a class for XML parsing and creating since IP.Board 2 but it was a kludge of PHPs then primative XML handling extension and a hand-rolled class for when the XML engine wasn't available. These methods functioned well but were known to be memory intensive.
Thankfully, PHP 5 has much better native XML handling which I took full advantage of when rewriting this class.
I looked at simpleXML intially but found it too, well, simple for our needs so I went ahead and used the full DOM methods. This gives us full control over both reading and creating XML documents.
Here's how simple it is to create a new XML document:
$xml->newXMLDocument(); /* Create a root element */ $xml->addElement( 'productlist', '', array( 'name' => 'myname', 'version' => '1.0' ) ); /* Add a child.... */ $xml->addElement( 'productgroup', 'productlist', array( 'name' => 'thisgroup' ) ); $xml->addElementAsRecord( 'productgroup', array( 'product', array( 'id' => '1.0' ) ), array( 'description' => array( 'This is a description' ), 'title' => array( 'Baked Beans' ), 'room' => array( '103', array( 'store' => 1 ) ) ) ); $xml->addElementAsRecord( 'productgroup', array( 'product', array( 'id' => '2.0' ) ), array( 'description' => array( 'This is another description' ), 'title' => array( 'Green Beans' ), 'room' => array( '104', array( 'store' => 2 ) ) ) ); $xmlData = $xml->fetchDocument();
$xml = new classXML( 'utf-8' );
This will produce this document:
<productgroup name="thisgroup"> <product id="1.0"> <description>This is a description</description> <title>Baked Beans</title> <room store="1">103</room> </product> <product id="2.0"> <description>This is another description</description> <title>Green Beans</title> <room store="2">104</room> </product> </productgroup> </productlist>
<productlist name="myname" version="1.0">
This is how you'd parse that document:
/* Grabbing specific data values from all 'products'... */ foreach( $xml->fetchElements('product') as $products ) { print $xml->fetchItem( $products, 'title' ) . "\"; } /* Prints: */ Baked Beans Green Beans
$xml->loadXML( $xmlData );
I'm sure you can appreciate how simple it is to use these new XML features!
XMLArchive
I created our XMLArchive format for IP.Board as a way of combining several files into one without using tar or zip which can be troublesome on some servers. XMLArchive is very simply file data in a basic XML format. I rewrote the class to make it easier to use and to add more functionality.
Here's how to read an archive:
$archive->read( "/path/to/archive.xml" ); print $archive['someDir/file.html'];
$archive = new classXMLArchive();
As you can see, we use PHPs ArrayAccess to transparently allow access to the contents of the fileset from the main class handle.
Here's how to create an archive:
$archive->add( "someDir" ); $archive->add( "anotherDir/anotherFile.html" ); $archive->add( "Create a new file from scratch!", "anotherDir/brandNewFile.html" ); # Save gzipped $archive->saveGZIP( "/path/to/archive.xml.gzip" ); # Save normally $archive->save( "/path/to/archive.xml" ); # Just return the data $archive->getArchiveContents();
$archive = new classXMLArchive();
For simplicity's sake, there is now just one interface to add files: "add()". Personally, the fewer function names to remember the better!
Naturally, this blog entry does not cover all the changes and improvements within the kernel classes but it does go some way to showing just how much energy we've invested in ensuring that IP.Board is as robust and efficient as it can be.