JHM

PHP

Multiple Node Access logic patch
jhm – Fri, 2008 – 11 – 14 11:13

drupal related

w2box
jhm – Mon, 2006 – 07 – 10 14:18

This is a simple php script which allow you to upload and download files. There isn't any complex user management because it aims more for private file repository use.

It as direct file deletion using AJAX, instant table sort using a self modified version of sorttable.js and finally upload file progressbar using a cgi(perl) script.

If you want to know more about those technologies, go to more information section.

zephyr - an ajax based framework for php5 developers
jhm – Sat, 2006 – 05 – 20 11:52

zephyr is an ajax based framework for php5 developers. you can easily develop business applications using this robust framework. this is extremely easy to learn and very simple to implement. you can deliver a full fledged ajax application with strong business layer in backend within some minutes. installation and deployment of packages that you develop for zephyr is hassle free. moreover you will get all the features of most popular templating engine "smarty" and powerfull data access layer "adoDB". lets go through the documentation process to discover how easy is to develop an ajax applicatio

G2 notification module
jhm – Sat, 2006 – 05 – 13 21:07

notification module (with scheduler discussion)

G2 Module
jhm – Sun, 2005 – 10 – 02 07:17

This forum entry by valiant is probably the most useful documentation I have found about the architecture of G2 (http://gallery.menalto.com/node/36885)

A few G2 concepts:
- Views:
A view is a HTML page that displays something, e.g. the album and the photo pages are "ShowItem" views. There's also a view to add a comment, the AddComment view. Etc.
- Controllers:
A controller executes a command / handles a requested action. E.g. When you view the AddComment page which is a view and hit "submit", you tell a controller to add this comment to G2. The controller receives the comment title and comment text and for which item it should add a comment and finally creates this comment.
- Controller vs. Views:
Views should only display something. In a View, you load data from G2 with some API calls. You never change data / alter data in a view. You just load data and prepare it for presentation.
In a controller, you do the work. You add a comment to the database, you add an item to an album, etc.
Views and controllers are coupled very tightly. Hence there is a "MVC" (Model View Controller) programming pattern. A view shows a web form, you as a user send the form filled with data back to G2, G2 tells loads the requested controller, the controller receives the data and does something with it, finally the controller redirects to a view (the same or another) such that the user receives some feedback, e.g. "thank you, your request was successfully handled" page.
- Blocks, Callbacks, Preloads:
We learned that a view shows a page in G2. Blocks are smaller building blocks of a complete HTML page. E.g. in the G2 sidebar, you can add a search block, a item actions block, a random image block etc. Also, the exif data below photos on the ShowItem view is a block.
Basically, a block is a piece of HTML and you can show as many blocks on a single page as you want.
There is a GUI to add / remove / configure blocks in "Site admin" -> Themes -> Matrix (or any other theme that supports blocks).
You can add blocks to the sidebar, to album pages and to photo pages with this GUI.
Alternatively, you can place blocks anywhere on a page, but then you have to edit templates manually. More on templates later.
Some blocks need to load additional data. E.g. the random imge block needs to load a random image. This is done in the Callback. If a Callback is defined, G2 loads it. And the loaded data is added to the data that is loaded anyway and given to the block template.
Some blocks need to add HTML to the <head> section of the resulting HTML page. E.g. to add CSS or javascript. The Preloads are called before the page outputting begins and in the Preloads, you can add content to the <head> section.
- Modules:
G2 is modular. That means, that you can add views/controllers/blocks/themes/special handling for new file types/... in a modular way. You don't have to edit files, you just can write your own G2 module, place it into your gallery2/modules/ directory and click install & activate in the admin section of G2 and that's it.
The most important and the only mandatory module is the core module. It has all the core functionality, e.g. show album and photo pages, add items, albums, etc. And it also has the API to handle other modules. Finally, it offers a numberous means to include your own functionality whereever you need it.
- Entities:
G2 has a very elegant architecture. You need to have a basic understanding of object-oriented programming (OOP) to understand it. Of course you can learn the basics of OOP quickly. In G2, we deal with albums, photos, thumbnails, resized versions (resizes), movies, users, groups, etc. If you look up the definition of the word "entity", you'll understand that these are all entities, since "entity" is a very general term. So, we deal with the term "entity" quite often in G2.
In G2, we prefix our entities with "Gallery", such that we don't have a conflict when you use G2 integrated in other applications.
So it is GalleryEntitiy and not just entity.
A GalleryEntity has attributes like a unique ID, it has a creation timestamp (when was it created in G2), a modification timestamp etc. All entities have this in common.
See Gallery Class tree which is not quite up to date, but the most up to date schema we have.
So at the root, there is the the GalleryEntity. Ignore the ThumbnailImage entity on the right, that's just an entity from the thumbnail module (specify a default thumbnail for each file type). So, we see that GalleryUser, GalleryGroup are a GalleryEntity (they extend the GalleryEntity class). A GalleryUser has all the properties and functions of a GalleryEntity, plus the atributes of a user, e.g. a user name, a full name, a password etc. A GalleryGroup has a group name and that's it.
And then we see the GalleryChildEntity: G2 is basically a tree. Each album can contain subalbums and subitems, subalbums can again have subsubalbums etc. This is a tree structure. At the root of the tree, there is root album, which doesn't have a parent. All other items, be it photos, albums, or any other type, have a parent. This relationship, item <-> parent is relfected in this class, GalleryChildEntity. So each GalleryChildEntity has the properties of a GalleryEntity plus a parentId.
When we scroll down, we see that there are two GalleryChildEntities.
We differentiate GalleryFilesystemEntity from GalleryDerivative. The former are things that you explicitely create / add. E.g. an album is a folder in the filesystem. Thus it's a FileSystemEntity. When you add an item to G2, e.g. a photo, it is stored as a file in a folder, thus it is also a FileSystemEntity. GalleryDerivatives are the result of operations acting on a FilesystemEntity, e.g. to generate a thumbnail, we just have to call a function which generates it from an original photo.
In reality, we store GalleryDerivatives also on the filesystem, but in a different way. We store it in a g2data/cache/derivatives/ folder sorted by their ID. But we could leave the cache away and it G2 would still work. Also, we will see that GalleryFileSystemEntities have many different properties than derivatives. So it's important to differentiate the two.
There are two types of GalleryItems: GalleryAlbumItem and GalleryDataItem (photos, movies, ...). They both have a lot in common. E.g. they both need a title, summary, description etc. and thus, the GalleryItem class was introduced.
We can set the theme separately for each album, so this is a album property.
GalleryDataItem is the general term for all files that you upload to G2. A DataItem has a mimeType. You can implement special functionality for any mimeType, e.g. add a embedded audio player for audio items, or open a rich text editor for text files. At the moment, there are implementations of a GalleryPhotoItem, GalleryMovieItem (e.g. is responsible for showing movies in an embedded player in the browser) and GalleryAnimationItem (shows flash embedded in the browser). Everything else is GalleryUnknownItem. A module could register a GalleryAudioItem and implement a few functions and that's all that is needed to play sound files embedded in the browser.
Read about Derivatives in the next section.
Summary: In the end, you won't have to deal with this class hierarchy too much. There's an API function to load the children of an album and you'll receive album items and data items (mostly photos) as a result. You can then call $item->getTitle() or $item->getCreationTimeStamp(), etc. and it's just good to know where all the properties and functions come from. There's an auto-generated documentation on all classes and functions here (API docs): http://gallery.menalto.com/dev
You can extend this architecture / class hierarchy in any way. Just register your own classes and implementations.
- Derivatives:
Thumnails and resizes have something in common. They are both generated from the original photos. Using another term, they are both "derived" from an original. Thus, we call them both "derivative". In OOP, you often try to collect the attributes and features of similar things (classes) in a more general thing. And this is here the case. thumbnails and resizes are very similar, thus we introduced the derivatives.
There are several types of derivatives: Thumbnails, resizes and preferred resizes.
The mentioned derivatives are all derivatives of a photo. But in G2, you can have derivatives of any file type. Well, there isn't any other derivatives than the mentioned ones, but you could extend G2 with a module to create a smaller movie of a long movie, or a low bit rate version of a high fidelity song.
Thus we have the GalleryDerivative entity, which can be anything. And we have the GalleryDerivativeImage which is either a thumb, a resize or a preferred resize. A GalleryDerivativeImage extends the GalleryDerivative (OOP), so it has all the properties and functions of a GalleryDerivative too.
- Events:
Think of the following problem:
Whenever an item is added to my Gallery, I'd like to be informed with an email. The "add item" code is in the core module. But we decided to reduce the core functionality / module to a minimum. We don't want to add all features, e.g. user notications in the core module. And we don't want that you have to modify some files just to get this feature.
For things like this we have events. When ever an item (or an entity to be more general) is created in G2, we notify all other modules of this event. More specifically, we notify only those modules, that are interested in such an event.
To solve the above problem, you have to create a new G2 module and register an event listener. An event listener is a class that implements a specific function (handleEvent()). In the handleEvent function you just write a send email API call and that's it. The end user just has to download your notification module and install it with a mouseclick.
There are a other events in G2 too: e.g. when a user does a login, logout, etc. So you can add modules that do specific things when something specific happens.
- Themes:
Themes are responsible for the look and feel of G2. A theme can decide what to present and how to show it. A theme tells G2 what data to load and what template to show. This sounds very general and it actually is. As it is with very general things, they tend to be complex. To simplify the life of a theme creator, G2 already loads a lot of typical data by itself. E.g. the children of an album and related things. But a theme doesn't have to obey these very typical album / photo pages look, it could show anything. It's up to the creativity of the theme designer.
- Templates:
Templates are (X) HTML pages in G2 which include some smarty markup to include dynamic content. E.g. the album.tpl file of the matrix theme shows a by default 3 rows by 3 columns of thumbnails. In the matrix album.tpl template, this is done with HTML <table> <tr> rows and <td> cells.
Smarty is used to make the number of rows and columns dynamic. Smarty is also used to include another G2 template to show in each table cell an image.
G2 templates support the basic smarty markup and additionally, we have the tags that start with {g-> ...}, e.g. {g->image ...} includes an image, {g->url ...} includes a specific URL, {g->text ...} shows some text in the language of the active G2 user, {g->block ...} includes a G2 block, etc.
In any G2 templates/ folder, you can create a templates/local/ folder and place in their a customized / changed template.
Soon, themes will be able to override / replace any module template.
- Factory:
Remember that you can extend the G2 class hierarchy, add your own GalleryAudioItem, etc.? This is done with the Factory. A factory produces something. In G2, you order something from the factory with $entity = GalleryCoreApi::newFactoryInstance(i want an instance of an item that is specialized for audio files); Then the factory searches its store for something that is specialized for audio items. If it finds something, it returns it. If it doesn't find a specialized audio item, it returns the UnknownItem, since we cannot do anything about it.
If you want to write a module that adds audio item support to G2, you have to tell the factory about it. You have to call GalleryCoreApi::registerFactoryImplementation('GalleryItem', 'GalleryAudioItem', 'modules/audio/classes/GalleryAudioItem.class', ... ,'audio/wav'); Once registered, the factory will know about your implementation and when you add a new wav file to G2, it will call ::newFactoryInstance('GalleryItem', ..., 'audio/wav'); and it will find your GalleryAudioItem implementation.
But the factory is used for a lot of other things too:
* Register your own ItemAdd plugin / method: E.g. Add item from local server, add item with the upload applet etc. could all be done in modules. The module just has to register the new method
* Register your own ItemAddOption, sizelimit, quota, create thumbnail on upload etc. are all item add options. This code is executed on-the-fly when items are added
* Register a ItemEditOption: the customfields, multilang, thumbnail, album, photo, ... tabs in the edit album / edit photo / ... tab are all plugins
* Register your own URL generator: the Rewrite url generator creates short urls with the help of mod_rewrite by replacing the original G2 url generator. Another url generator uses a global content distribution network (coral) to safe bandwidth of your server.
* Register a maintenance task that will be listed in site admin -> maintenance: e.g. change all spaces to dashes in all items
* Register your own cart plugin / checkout option: do something with a collection of items. e.g. zip download, print with shutterfly, ...
* Register a onLoad handler for a specific entity type: e.g. the multilanguage module loads captions in different languages for all loaded items. The random thumbnail module loads a random thumbnail for album items, etc.
* Register a colorpack, a customfields implementation, ...
* Register your own validation plugin: e.g. the captcha test in the register view is such a validation plugin
* Register new toolkits and toolkit operations, e.g. in a module, that can create low bitrate versions of high fidelity music files
* Register a SearchInterface implementation, to make additional data searchable, e.g. the comment module registers a search interface implementation to add the search comments functionality
* If you need plugins somewhere else, e.g. in an existing module or the core, please hack your G2 and if you can convince us, we will maybe add other get-plugin-calls too

How to write drupal filters
jhm – Thu, 2005 – 06 – 16 06:32

This is a 'bookmark' so I can find the page again

SAJAX - Simple Ajax Toolkit
jhm – Sun, 2005 – 03 – 20 15:42

Sajax is an open source tool to make programming websites using the Ajax framework — also known as XMLHTTPRequest or remote scripting — as easy as possible. Sajax makes it easy to call PHP, Perl or Python functions from your webpages via JavaScript without performing a browser refresh. The toolkit does 99% of the work for you so you have no excuse to not use it.

JpGraph
jhm – Sun, 2005 – 02 – 27 11:20

JpGraph is a fully OO (Object-Oriented) Graph creating class library for PHP >= 4.3.0. The library can be used to create numerous types of graphs on-line. JpGraph makes it easy to draw both "quick and dirty" graphs with a minimum of code as well as complex graphs which requires a very fine grained control. The library assigns context sensitive default values for most of the parameters which minimizes the learning curve. The features are there when you need it - they don't get in your way!