Add a plugin installation procedure

Introduction

Sometimes, a plugin may need additional parameters, or to modify a database schema. This step is covered by the automatic installation procedure. In fact, this procedure is semi-automatic and leaves great flexibility for the developer to make a specific installation and update procedure.

The _install.php file

The whole installation and automatic update procedure is handled by the _install.php file in your plugin. If such a file exists, it will be called everytime the user goes in his/her blog admin dashboard.

This file contains some PHP code indicating its status in three different ways:

  • return true: The plugin was installed
  • return: Nothing to do, no message (to be used when there is nothing necessary)
  • throw new Exception('error message'): if any error occurs

Let's see a simple example. Our plugin is called toto and is going to save its version in the versions table.

<?php
if (!defined('DC_CONTEXT_ADMIN')) { return; }
 
# We read the plugin version
$m_version = $core->plugins->moduleInfo('toto','version');
 
# We read the plugin version in the versions table
$i_version = $core->getVersion('toto');
 
# The version in the table is greater or equal to
# the module one, we do not do anything since this
# one is already installed.
if (version_compare($i_version,$m_version,'>=')) {
	return;
}
 
# The install procedure really starts here
$core->setVersion('toto',$m_version);
?>

Warning:

The name passed to moduleInfo is not necessarily the plugin name defined in _define.php: it is the directory name where is stored your plugin!

Create new preferences

Your plugin may need preferences to work. It is a good idea to use the automatic installation to create them.

Here is an example of automatic installation adding a global preference:

<?php
if (!defined('DC_CONTEXT_ADMIN')) { return; }
 
$m_version = $core->plugins->moduleInfo('toto','version');
 
$i_version = $core->getVersion('toto');
 
if (version_compare($i_version,$m_version,'>=')) {
	return;
}
 
# Setting creation (if it exists, it will be kept)
$core->blog->settings->addNamespace('toto');
$settings->toto->put('toto_setting',true,'boolean','toto setting',false,true);
 
$core->setVersion('toto',$m_version);
?>

Note:

addNamespace() parameter must only contain digits or characters without accents.

Allowed: [a-zA-Z][a-zA-Z0-9]

The $type parameter of put can be 'string', 'integer', 'float', 'boolean' or 'null'. If $type is 'null' and the setting already exists, the current type will be kept. Else, the 'string' type will be applied.

Please check the settings documentation to use those parameters after installation.

Modify the database schema

One of the most interesting features of the installation system is to allow you to easily modify database schema. You can create new tables, add fields in an existing table, create indexes or references.

UDBS

UDBS stands for "Universal DataBase Schema". This system defines a database schema then compares it to the existing one to update it if required.

Since UDBS is compatible with multiple database types, it has a few limits:

  • You cannot delete a field. UDBS only creates or updates.
  • UDBS can rename an index or changes its related fields, but not both at the same time (it will create a new index).
  • Only some data types are allowed.

Allowed data types

Since it has to be compatible with MySQL, PostgreSQL and SQLite, UDBS only works with the following data types:

smallint 2 bytes signed integer
integer 4 bytes signed integer
bigint 8 bytes signed integer
real 4 bytes float
float 8 bytes float
numeric Exact numerical value
date Calendar date (day, month, year)
time Hour of the day
timestamp Date and hour
char A fixed length string of n characters
varchar A variable length string of n characters
text A variable length text

dbStruct object instance

By creating an instance of dbStruct you can define a schema (completely or partially).

$s = new dbStruct($core->con,$core->prefix);

The class takes a connection object and the prefixes we want to use. In the previous and following examples, we are using the objects that come with Dotclear.

Define a table

dbStruct and dbStructTable provide very useful features.

  • Most of the methods return $this so they can be chained together.
  • Any call to a non-existing property of dbStruct will have the same effect as creating a dbStructTable object if it does not exist and retrieve the instance.
  • Any call to a non-existing method of dbStructTable will have the same effect as calling the field method which adds a field in the table.

Here is a classic example that does not use the advanced properties of dbStruct:

$s = new dbStruct($core->con,$core->prefix);
 
$t = $s->table('mytable');
$t->field('field1','varchar',255,false,"'-'");
$t->field('field2','smallint',0,true);

In this example, we define the mytable table in which we add two fields:

  • field1, a 255 characters long, not null varchar with default value '-'
  • field2, a smallint that can be null and with no default value.

This example works perfectly well, but here is another way of how to achieve exactly the same result:

$s = new dbStruct($core->con,$core->prefix);
 
$s->mytable
	->field1('varchar',255,false,"'-'")
	->field2('smallint',0,true)
	;

Much better, no?

Add an index

To add an index to your schema extension:

$s->mytable->index('idx_mytable_field1','btree','field2');

The index method takes the following parameters: The index name, the type ("btree" only) and at least one field name. You can add more fields as additional parameters of the method.

Add a primary key to a table

$s->mytable->primary('pk_mytable','field1');

Just like index method, this method can take more than two parameters if the key is made of several table fields.

Add a unique key

$s->mytable->unique('uk_mytable','field2');

Just like index method, this method can take more than two parameters if the key is made of several table fields.

Add a reference to another table

The references indicante if the field of a table is linked to the field of another one. They ensure data integrity and automate some processes such as deleting or updating. They are also called "foreign keys".

$s->category->reference('fk_category_blog','blog_id','blog','blog_id','cascade','cascade');

Cet exemple crée la référence fk_category_blog sur le champ blog_id de la table category référençant le champ blog_id de la table blog. Les deux derniers paramètres sont les actions possibles dans les cas respectifs de mise à jour et de suppression d'une valeur référencée.

This example creates the fk_category_blog reference on the blog_id field from the category table, referencing the blog_id field from the blog table. The last two parameters are the possible actions, respectively in the case of an update and a deletion of a referenced value.

Schema synchronization

Once a schema has been written, it must be synchronized. Here is how to do it with the previous code:

$s = new dbStruct($core->con,$core->prefix);
 
$s->mytable
	->field1('varchar',255,false,"'-'")
	->field2('smallint',0,true)
	;
 
$si = new dbStruct($core->con,$core->prefix);
$changes = $si->synchronize($s);

As you can see, we create a new instance of dbStruct, then we call the synchronize method passing it the instance of the previous dbStruct. This method will return the number of changes made.

Interacting with the Import/Export plugin

Wiki powered by Dokuwiki.