Developing ATK modules - Part 1 (Basic): Difference between revisions
m →Installing the module in Achievo: quote fix |
|||
| Line 219: | Line 219: | ||
If everything went smooth, we now get to the point of this guide: implementing the userinterface | If everything went smooth, we now get to the point of this guide: implementing the userinterface | ||
for our pizza database! | for our pizza database! | ||
= The Pizza node = | |||
The what? | |||
Before you can understand the title of this chapter, I should tell you what a node is. A node is | |||
ATK's term for a class that implements an 'informational unit'. For example, projects, | |||
customers and activities are pieces of information in Achievo. Every type of information is | |||
represented by a node class. There is a class for managing projects, for managing customers and so on. | |||
A node defines how information is structured. It tells the system how to handle records, and | |||
how to create a user-interface for managing the information. For example, the projects node | |||
tells Achievo that a project is made up of an id, a name, description etc. In other words, the | |||
node class is the link between the database table and the user-interface. You will see later | |||
on that we don’t even need to implement a user-interface. If the nodes are defined correctly, | |||
the user-interface is automatically generated for us by the application. | |||
People familiar with Java might compare the node concept with Java-Beans. Although a | |||
node is completely different from a bean, the concepts are similar. | |||
Every type of information is represented by a node class, so what we have to do is create a | |||
node class for our Pizza table. | |||
== Creating the node class == | |||
We first have to determine a name for the node. It is best to use a name that describes the | |||
information that the node represents. The node that represents project management is called | |||
‘project’; the node that represents customers is called ‘customer’ and so on. Since our node | |||
will handle management of pizzas, we will call it ‘pizza’. | |||
Every node is located in its own file. The name of the file is important. It should always be | |||
‘class.<the name of your node>.inc’, in our case ‘class.pizza.inc’. If you name it differently, | |||
Achievo won’t be able to find it. | |||
Let’s create the file, and put the first lines of code in it (again, I will first show you the code | |||
and afterwards explain it): | |||
<?php | |||
class pizza extends atkNode | |||
{ | |||
function pizza() | |||
{ | |||
$this->atkNode("pizza"); | |||
} | |||
} | |||
?> | |||
Like with the module, we start with defining the class. Every node extends the atkNode class, | |||
the mother of all nodes. Doing this makes it possible for Achievo to interface with the class. | |||
We also add one function to the class, with the same name as the class itself. This is called a | |||
constructor function. The function with the same name as the class is always called when a node is created. In this function, we initialize the base-class, telling it the name of the node, with this line: | |||
$this->atkNode(”pizza”); | |||
If all this talk about constructors and base classes is abracadabra to you, don’t worry. It’s not | |||
essential that you understand this. These are just lines that always need to be there. Do the | |||
same in your own nodes and it will work. Trust me. | |||
Now it's time to implement some functionality in the pizza node. We start by telling the node | |||
what database fields the pizza table has. Let’s start with the id and name fields. We do this | |||
by adding a few lines to the constructor: | |||
function pizza() | |||
{ | |||
$this->atkNode("pizza"); | |||
'''$this->add(new atkAttribute("id", AF_PRIMARY|AF_HIDE|AF_AUTO_INCREMENT));''' | |||
'''$this->add(new atkAttribute("name", AF_UNIQUE|AF_OBLIGATORY));''' | |||
} | |||
The two lines we just added add so-called ‘attributes’ to the node. Each attribute represents | |||
a field in the database. Let’s take a closer look at the first line we added, so I can explain to | |||
you exactly what it does: | |||
$this->add | |||
This is the function-call to add attributes to our node. $this is the node itself. | |||
new atkAttribute | |||
Here, we create an atkAttribute, a database field representation. There are a lot of different | |||
types of attributes. Each type of field may have its own kind of attribute. For example, there is | |||
an atkDateAttribute for manipulating dates. The atkAttribute is the default, most common | |||
attribute. We will find out more about other attributes later on. | |||
"id" | |||
This is the name of the field in the database. The name we specify here has to be exactly the | |||
name of the field in the database. | |||
AF_PRIMARY|AF_HIDE|AF_AUTO_INCREMENT | |||
The second parameter to the atkAttribute function-call represents the so-called ‘flags’. Flags | |||
influence the behavior of the attribute. Each flag starts with ‘AF_’. You can specify more than | |||
one flags by separating them with a ‘|’. There are over 30 different flags. We won’t get to see | |||
all of them in this guide. For now, I’ll explain the flags as we encounter them. | |||
The AF_PRIMARY flag indicates to Achievo that this field is the primary key of the table. You | |||
should specify this flag for the same fields that you indicated as primary keys in the | |||
database. Achievo uses this information to determine which record the user is manipulating. | |||
(note: still have to copy/paste/fix this from the pdfs; start with page 7) | (note: still have to copy/paste/fix this from the pdfs; start with page 7) | ||
Revision as of 09:07, 13 January 2007
Introduction
If you’ve been using Achievo for a while, and you want to develop your own extensions to the application, this is the guide for you!
After reading this guide (and working through the examples), you will have an understanding of how Achievo works and how you can extend it to meet the needs of your organisation. You will find how incredibly easy it is to develop extra features for Achievo.
From the start of the project, Achievo has been developed with extension in mind. A project management suite is typically an application that never completely fits to an organisation. Each organisation has its own way of doing things. Each organisation has its own workflow. With this in mind, we created a powerful backend that allows you to completely adapt Achievo to your needs.
In this guide, we will teach you the basics of Achievo’s architecture. Later, in Part II we will dive deeper into the internals of Achievo, and teach you how you can make your extensions even more powerful and feature-rich. Finally in Part III, you will learn how to change existing Achievo functionality, without hacking the original Achievo code, and the most powerful features of the backend.
If you encounter any problems with the examples in this guide, or if you have any questions or comments, just drop me a mail (ivo@achievo.org). This is the first version of the guide, so some things may not be clear enough yet. I welcome any suggestions for improvements.
Prerequisites
In order to develop extensions for Achievo, you should have some knowledge about programming in PHP, since that is the language Achievo was written in. You don’t need to be a guru, but knowledge of the basic concepts will help you understand this guide. If you have never used PHP before, find a tutorial on the web. The official PHP site, www.php.net, is a good starting point if you want to learn more about PHP.
Experience with databases is recommended. It’s certainly not necessary to be an expert in SQL. (You will find out how little SQL you will actually have to write when developing Achievo extensions!) You should have some basic knowledge about databases however. We need to create some tables, so you need to know at least a bit of SQL. In this guide we concentrate on MySQL as a database server, but the instructions are quite similar for other databases.
We assume you have a working Achievo installation that you are able to develop on (Achievo 0.8 or newer). Don’t use your company’s production installation, or production database! Your fellow Achievo users will be very unhappy if you do that. Just create a copy of the database and a copy of the Achievo installation. (Don’t forget to update Achievo’s config.inc.php file so Achievo will use the database copy instead of the original, and don’t forget to grant correct privileges to the databaseuser.) If you installed a new database, make sure you have some initial data in it: at least one security profile and a user.
Finally, all you need is a text editor. I can recommend SciTE (www.scintilla.org/SciTE.html), which is a free source code editor which features syntax highlighting. But of course you can use the text editor you are most comfortable with.
So. If any of the above did not scare you away, we are now ready to start.
Pizza
Pizza? Yes. Pizza.
The example we are going to use in this guide is a Pizza Database. This example is chosen for a few reasons. First, it’s going to show you that you can add virtually anything to Achievo. This illustrates that Achievo is not branch-specific, and extensions for all kinds of businesses can be added. Second, it is a feature that is unlikely to ever exist in Achievo for real, so it can be used perfectly as an example application. And finally, I was hungry when I wrote this guide. If you like the guide, buy me a pizza sometime. :-)
Let me explain to you first what we’re going to develop. Suppose we own a Pizza Restaurant, and for some obscure reason, we use Achievo to track time we spent on baking pizzas.
An ideal Achievo extension for our little restaurant would be to have a database where we can store what Pizzas we serve (to be used later to generate menu cards, keep track of orders etc.)
So what do we need? A feature in Achievo where we can manage Pizzas. Management of Pizzas includes saving new pizzas, editing existing ones and deleting pizzas we no longer serve.
Data model
Once you know what you want to develop, you will need to design a data model. This means, we’re going to think about the database tables that we will need for our feature.
Let’s think of what we want to store about a pizza. A pizza of course has a name. It also should have a description, and a price. Maybe we also want to know the date that we entered the Pizza in the database. As you probably already know: in a database, a record should also have a unique id. While the name of a pizza might be unique, it’s a good idea to use a separate numeric id as primary key. (Read some database tutorials if you want to know why.)
Let’s leave it at that for now, to keep the example simple. (In Part 2, I will teach you how you can keep track of orders, how you can manage ingredients and some more advanced features, but to understand the basics, the fields I just mentioned are sufficient.)
So we should create a table in the Achievo database called ‘pizza’ with the fields we just described. This is what the table should look like:
Pizza
| Fieldname | Type |
|---|---|
| id | integer |
| name | string |
| description | text |
| price | float |
| entrydate | date |
When we create the table in the database, using reasonable values for field lengths etc., the
SQL script might look like:
CREATE TABLE pizza( id int(10) NOT NULL, name varchar(50), description text, price decimal(5,2), entrydate date, PRIMARY KEY (id) );
This script is for MySQL databases. If you use a different database, you might need to modify the script a bit to accommodate for some database dependent SQL statements.
After we run this script on the database, we are ready to start development.
Achievo modules
Everything we add to Achievo will be located in a so-called module. A module is a set of source files in a directory that belong to each other, and that together form the implementation of a feature.
We will not modify the original source code of Achievo, nor will we put our code between the existing Achievo code.
This happens for a good reason. When new Achievo versions are released, we want to be able to use our module with this new version, without having to write our code all over again. This also keeps our code nicely together. And finally, it makes it easier to distribute features you created. (We will create a module repository on www.achievo.org where you can upload your module, so other users can benefit from it.)
Creating the module
A module is stored in a directory. You could use the modules/ directory in Achievo to store your module, but I prefer to reserve that directory for standard Achievo modules, and put my own modules in a directory outside of Achievo’s directory structure.
Suppose you have Achievo installed in /var/www/html/achievo-0.8/, we could create the directory /var/www/html/achievo_modules/ to store our own modules. It doesn’t really matter how you name the directory and where you put it, as long as the directory is accessible by your webserver. So make sure you set the correct permissions on the directory once you created it. The directory has to be readable by the user that runs your webserver (usually something like ‘nobody’, or ‘www’).
We will call our module ‘pizzaman’ (short for ‘pizza manager’). The first thing we do when creating the module is create the directory. It is best to name the directory after the module, so we create the directory /var/www/html/achievo_modules/pizzaman/.
An important rule when developing an Achievo module is that every module should have a file named module.inc, which contains a definition of the module. This definition specifies, among other things, what menu items should appear in Achievo when you activate the module.
For now, we will create a very basic implementation of a module, which we will complete later on.
Create a file called module.inc in the achievo_modules/pizzaman directory and put the following code in the file (don’t worry if you don’t understand it, I will explain it after you created the file):
<?php
class mod_pizzaman extends atkModule
{
}
?>
You should already know that the <?php and ?> markers indicate that we are writing a PHP source file. What we did here is create a class (yes, Achievo is ‘object-oriented’!) with the name mod_pizzaman. The name of this class is always ‘mod_’ plus the name of the module.
What we also specified is that this class extends atkModule. The atkModule class is what you might call ‘the mother of all modules’. If you derive your module class from atkModule, you actually prepare the module for use in Achievo. Achievo can now interface with your module. Later on, we will add some necessary code to the module, to indicate to Achievo what menu-items to show etc. For now, this bit of code suffices. Next, we will activate the module in Achievo.
Installing the module in Achievo
Open Achievo’s configuration file (config.inc.php), and look for a section named ‘external modules’ (near the end of the file). Add the following line to activate your module:
module("pizzaman", "../achievo_modules/pizzaman/");
This will tell Achievo to load the module ‘pizzaman’ and load it from the specified directory. The directory is relative to Achievo’s own directory, but you may also specify an absolute path here. Once the file is saved, we have activated the module. (Don’t forget the trailing slash at the end of the directory name. The example in config.inc.php doesn’t have this, but that’s an error.)
You may instead put this line in the file modules/config.modules.inc, but again, I prefer to keep this directory for ‘official’ Achievo modules. This will also help you when upgrading, since you usually keep your configuration file when you switch to a new version of Achievo.
Before we continue, I first want you to change the file atkconf.inc in the Achievo directory. Find the entry named $config_debug and change it’s value to 1. This will turn on the debugger, which is helpful when developing extensions. With the debugger turned on, Achievo will show you a lot of information, including error messages and warnings if there are any.
You may now browse to your Achievo test installation with your favorite browser. Nothing happens yet, since we still haven’t implemented any functionality. But at least you should not get any error messages. If you see errors or warnings, revise the steps taken so far. Notice the lines that appear near the bottom of the screen: they contain the debug information. It’s a time-stamped log of what happens when a screen is rendered.
If everything went smooth, we now get to the point of this guide: implementing the userinterface for our pizza database!
The Pizza node
The what?
Before you can understand the title of this chapter, I should tell you what a node is. A node is ATK's term for a class that implements an 'informational unit'. For example, projects, customers and activities are pieces of information in Achievo. Every type of information is represented by a node class. There is a class for managing projects, for managing customers and so on.
A node defines how information is structured. It tells the system how to handle records, and how to create a user-interface for managing the information. For example, the projects node tells Achievo that a project is made up of an id, a name, description etc. In other words, the node class is the link between the database table and the user-interface. You will see later on that we don’t even need to implement a user-interface. If the nodes are defined correctly, the user-interface is automatically generated for us by the application.
People familiar with Java might compare the node concept with Java-Beans. Although a node is completely different from a bean, the concepts are similar. Every type of information is represented by a node class, so what we have to do is create a node class for our Pizza table.
Creating the node class
We first have to determine a name for the node. It is best to use a name that describes the information that the node represents. The node that represents project management is called ‘project’; the node that represents customers is called ‘customer’ and so on. Since our node will handle management of pizzas, we will call it ‘pizza’.
Every node is located in its own file. The name of the file is important. It should always be ‘class.<the name of your node>.inc’, in our case ‘class.pizza.inc’. If you name it differently, Achievo won’t be able to find it.
Let’s create the file, and put the first lines of code in it (again, I will first show you the code and afterwards explain it):
<?php
class pizza extends atkNode
{
function pizza()
{
$this->atkNode("pizza");
}
}
?>
Like with the module, we start with defining the class. Every node extends the atkNode class, the mother of all nodes. Doing this makes it possible for Achievo to interface with the class.
We also add one function to the class, with the same name as the class itself. This is called a constructor function. The function with the same name as the class is always called when a node is created. In this function, we initialize the base-class, telling it the name of the node, with this line:
$this->atkNode(”pizza”);
If all this talk about constructors and base classes is abracadabra to you, don’t worry. It’s not essential that you understand this. These are just lines that always need to be there. Do the same in your own nodes and it will work. Trust me.
Now it's time to implement some functionality in the pizza node. We start by telling the node what database fields the pizza table has. Let’s start with the id and name fields. We do this by adding a few lines to the constructor:
function pizza()
{
$this->atkNode("pizza");
$this->add(new atkAttribute("id", AF_PRIMARY|AF_HIDE|AF_AUTO_INCREMENT));
$this->add(new atkAttribute("name", AF_UNIQUE|AF_OBLIGATORY));
}
The two lines we just added add so-called ‘attributes’ to the node. Each attribute represents a field in the database. Let’s take a closer look at the first line we added, so I can explain to you exactly what it does:
$this->add
This is the function-call to add attributes to our node. $this is the node itself.
new atkAttribute
Here, we create an atkAttribute, a database field representation. There are a lot of different types of attributes. Each type of field may have its own kind of attribute. For example, there is an atkDateAttribute for manipulating dates. The atkAttribute is the default, most common attribute. We will find out more about other attributes later on.
"id"
This is the name of the field in the database. The name we specify here has to be exactly the name of the field in the database.
AF_PRIMARY|AF_HIDE|AF_AUTO_INCREMENT
The second parameter to the atkAttribute function-call represents the so-called ‘flags’. Flags influence the behavior of the attribute. Each flag starts with ‘AF_’. You can specify more than one flags by separating them with a ‘|’. There are over 30 different flags. We won’t get to see all of them in this guide. For now, I’ll explain the flags as we encounter them.
The AF_PRIMARY flag indicates to Achievo that this field is the primary key of the table. You should specify this flag for the same fields that you indicated as primary keys in the database. Achievo uses this information to determine which record the user is manipulating.
(note: still have to copy/paste/fix this from the pdfs; start with page 7)