Writing a 3rd Party Component in MODx Revolution, Pt. I

This tutorial only works in Revolution-alpha-2 or later, or on the SVN version of MODx Revolution-alpha, which can be obtained from:
http://svn.modxcms.com/svn/tattoo/tattoo/branches/revolution

Also note that the lexicon management is handled differently in Revolution-alpha-4 or the SVN.

So, you've seen some of the basic PHP tutorials for MODx Revolution, and now you want to start writing your snippet or plugin or such. Well, first, a few name changes.

Snippets/Modules/Plugins/Templates/TVs/Chunks in Revolution are no longer called 'resources'. They are called 'Elements', and when bundled together, they are called 'Components'. For example, the QuickEdit package is a Component, but it contains a plugin element and a module element.

'Packages' in Revolution are the containers that Components are 'packaged' in and stored for easy download/retrieval. They are created using the Package Builder (which builds components into packages), and managed via the Workspaces section of Revolution. A package may contain one or more components. For example, you might have a bundle of components (like a ditto/jot bundle) compiled into one distrobution package.

Now that we've got those terms under wraps, lets start the process. We're going to create a component in the next few articles that grabs and displays the top 5 downloaded 'doodles', which are stored at a specified location and referenced via a table called 'modx_doodles' in the MODx DB.

So, we've got a few factors here to consider:
1) We're using a non-modx table, so we'll need to create a schema for it, like the modx Revolution schema.
2) We want our package to be completely separate from the modx core, so our modx install can be upgradeable.
3) We want our package to be i18n (internationalization) compatible, with translations in different languages.
4) Right now, we will only use snippets, but we might eventually want a module/plugin that loads a management page for doodles in the Revolution manager.
5) We want to build a package that we can store on our website and people can download, install it, and utilize Revolution's Workspaces utility.

In this article, we'll start with setting up the basic component structure, and defining the schema definition.

Component Structure

We want a properly built component, so let's define our package structure. Now, the thing about packages is, when transported, they will mock the directory structure of the package. We also want it SVN compatible. So we'll want our directories to look like this:

/doodles
/doodles/branches/
/doodles/tags/
/doodles/trunk/
/doodles/trunk/_build/
/doodles/trunk/_build/schema/
/doodles/trunk/assets/
/doodles/trunk/assets/model/
/doodles/trunk/assets/lexicon/ // only needed in revo-alpha-3 or below
/doodles/trunk/assets/elements/
/doodles/trunk/assets/elements/snippets/

So, let's explain. The branches/tags directories are SVN-style directories; 'branches' are different versions or mods of the component (say, if you wanted a 2.0 version later, you could make a 2.0 branch). The tags is a SVN utility, and 'trunk' means the latest, stable branch. We'll work out of the trunk currently.

_build is the directory that you'll put your build script and schema in, and assets is the directory that will eventually be /modx/assets/, distributed by the package.

So, let's create a schema in /doodles/trunk/_build/schema/, and name it "doodles.mysql.schema.xml".

The Schema

First off, let's create the database table in our database, with the following fields:

CREATE TABLE `modx_modx`.`modx_doodles` (
    `id` INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR( 255 ) NOT NULL,
    `description` TEXT NOT NULL,
    `location` TEXT NOT NULL,
    `downloads` INT( 10 ) UNSIGNED NOT NULL DEFAULT '0',
    PRIMARY KEY ( `id` )
) ENGINE = MYISAM

The schema for our database is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<model package="doodles" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM"
     phpdoc-package="doodles" phpdoc-subpackage="">

    <object class="Doodle" table="doodles" extends="xPDOSimpleObject">
        <field key="name" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
        <field key="description" dbtype="text" phptype="string" null="false" default="" />
	<field key="location" dbtype="text" phptype="string" null="false" default="" />
        <field key="downloads" dbtype="int" precision="10" attributes="unsigned" phptype="integer"
                 null="false" default="0" />
    </object>

</model>

Something to note: Doodle extends "xPDOSimpleObject", which is an extension of an xPDOObject (or, rather, an object mapped to a database table). The "Simple" part is that it automatically assumes there is an 'id' column that is the primary key with an autoincrement status.

So now that we've got our schema, let's make a schema generation script to build out that schema and create the classes and maps for it. Yes - xPDO automatically creates the classes and maps (which are PHP array representations of the schema) for each object you define.

Create a 'build.doodles.php' file in the schema/ directory, and put in the following code. There are comments inline explaining each part.

<?php
// sets up the MODX_ defines and the paths to the xPDO core
// you'll want to change this first line to point to the actual MODx install path
define('MODX_BASE_PATH', dirname(dirname(dirname(dirname(dirname(dirname(__FILE__)))))) . '/MODx 0.9.7/');
define('MODX_CORE_PATH', MODX_BASE_PATH.'core/');
require_once (MODX_CORE_PATH . 'config/config.inc.php');
include_once (MODX_CORE_PATH . 'model/modx/modx.class.php');

// first get the actual trunk path
$trunk = dirname(dirname(dirname(__FILE__)));

// create the modx object and load the modPackageBuilder class
$modx = new modX();
$modx->initialize('mgr');
$modx->loadClass('transport.modPackageBuilder','',false, true);
$builder = new modPackageBuilder($modx);

// build the schema, using the PackageBuilder's buildSchema function. It takes 2 parameters:
// - the location of the model directory where you want the files to generate to
// - the schema xml file
$builder->buildSchema($trunk.'/assets/model/',$trunk.'/_build/schema/doodles.mysql.schema.xml');

echo 'Finished!';
exit();

Now, load your browser and point it to the newly-created build.doodles.php file, and let it run.

That should populate your /doodles/trunk/assets/model/ directory with all the class files and maps. Congrats! You've got the basic setup done. In the next article, we'll actually create the snippet file and language files.

Comments

Bob Ray says:

distrobution should be distribution.

 You might say about "tags:"

 Tags is an SVN utility that lets you store (in the tags directory) "snapshots" of particular versions so that you can, for example, create perfect copies of each release at any time in the future.

<< June 2008 >>
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30          

Writing a 3rd Party Component in MODx Revolution, Pt. II >>
<< PHP Coding in MODx Revolution, Pt. III


Browse Space

- Pages
- Blog
- Labels
- Attachments
- Bookmarks
- Advanced

Explore Confluence

- Popular Labels
- Notation Guide

Your Account

Log In

Other Features

Add Content

- Browse Space