forked from jelix/jelix-manual-en
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcreate-install-scripts.gtw
186 lines (110 loc) · 11.2 KB
/
create-install-scripts.gtw
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
~~LANG:FR@frman:creer-script-installation~~
Since 1.2, Jelix provides an installation system, which allows to execute scripts when you want to install a module inside an application, or to install the whole application.
===== How a module is installed =====
When you install a module with the @@installmodule@@ or the @@installapp@@ command :
* jelix looks at the @@modules@@ section inside the configuration of each entry point, and retrieve the access value of the module
* It will launch the installation of the module **for each entry points** where the access value of the module is higher than 0
* It then looks at the @@F@var/config/installer.ini.php@@ file: it checks if the module is already installed
* If it is already installed, it will execute all scripts of update provided by the module, corresponding to a version between the installed version and the new version of the module
* If it is not already installed, it will execute the installation script provided by the module
* After the installation or the update, Jelix stored the new version number of the module into @@[email protected]@@.
Of course, installation scripts or scripts of update are not required.
But if you provide them, **it is very important to store into the module.xml file, a good version number and the date of the release ** !
== Why is an installation script called several time? ==
Your installation probably needs to do some modifications specifically to each entry points. But the installation system doesn't know if your script will do it, and the installation script doesn't know in advance, how many and which entry points the application have (Remember that your module could be reuse in others applications).
This is why the installation script is executed **for each entry points**.
However, you probably don't want to execute the same thing for each entry points, or for the same database profile. Fortunately, you have some method to know easily if you can execute some things, without knowing the number of entry points or profile configuration.
===== An installation script =====
This is a file, @@[email protected]@@, that you store into the @@F@install/@@ directory of the module.
It should contain a class, inheriting from @@C@jInstallerModule@@, and named @@C@{module}ModuleInstaller@@, where @@{module}@@ should be the name of the module. Ex: @@C@mainModuleInstaller@@ for the @@main@@ module.
In this class, you need to create a method @@M@install@@ where you'll do all things to install the module: database modifications, file copies, configuration changes etc..
<code php>
<?php
class newsModuleInstaller extends jInstallerModule {
function install() {
if ($this->firstDbExec()) {
$db = $this->dbConnection();
$db->exec('CREATE TABLE...');
}
}
}
</code>
You can redefine the methods @@M@preInstall@@ and @@M@postInstall@@, which are executed respectively before and after the installation of all modules.
<code php>
<?php
class newsModuleInstaller extends jInstallerModule {
function install() {
if ($this->firstDbExec()) {
$db = $this->dbConnection();
$db->exec('CREATE TABLE...');
}
}
}
</code>
@@C@jInstallerModule@@ contains a number of properties and method which helps you to access to the database, to the configuration file etc..
==== Main properties or methods ====
Here are some of methods or properties you can use:
* @@$this->dbConnection()@@: it returns a @@C@jDbConnection@@ object. Don't call @@jDb::getConnection()@@, because you don't really know which is the profile used for the module.
* @@$this->execSQLScript()@@: it executes a SQL script stored into the @@F@install/@@ directory (or in one of its sub directory). Indicates a simple name, and it will load the script @@F@{name}.{dbtype}.sql@@. for example, if you call @@$this->execSQLScript('sql/install')@@ and if the database of the default profile is mysql, it will load the file @@F@sql/install.mysql.sql@@. You can indicate the full name of the sql script, but it should be compatible to all databases supported by your application.
* @@$this->copyDirectoryContent()@@ to copy some files, from the install directory to another place, typically to the @@F@www/@@ of the application
* @@$this->config@@: the @@C@jIniMultifilesModifier@@ object corresponding to the configuration file of the current entry point. With this object, you can retrieve content of the configuration file or to set parameters.
Don't hesitate to read the reference API of @@C@jInstallerModule@@ and @@C@jInstallerBase@@, and to look at the installation script of modules provided by Jelix. You'll certainly learn many things.
==== To not execute some part of your script ====
You notice that in the example, we call the method @@M@firstDbExec@@. It tells you if this is the first time that you want to access to the database, for the current database profile (some entry points can share the same database profile). Remember that your installation script is called for each entry points (read above).
You have also the method @@M@firstConfExec@@ to know if you did already have some changes to the current configuration file (some entry points can share the same configuration file, other than @@defaultconfig.ini.php@@). If it returns true, you can then access to the configuration file, by retrieving the @@P@config@@ property, which is a @@C@jIniMultifilesModifier@@ object.
Then you have the method @@M@firstExec@@. You pass a keyword to this method. And it tells you if you already call this method with this keyword (false) or not (true). You call this method to determine yourself, in some conditions, if you want to execut severalt time a part of your installation script.
==== Database profile used for the installation ====
If your installation script interacts with a database (creating a table, modifying records in some tables etc), you have to use the method @@M@dbConnection()@@ or @@M@execSQLScript@@ to exécute queries. By default, it uses the "default" profile. An alternate profile can be indicated in several places (listed by priority, the first has the higher priority):
* In your install class, you call @@M@useDbProfile@@, by given the profile you want to use.
* In the property @@P@defaultDbProfile@@ of your install class, you can indicate the default profile to use for the installation of the module
==== Parameters for an installation ====
You may want to execute the installation with some parameters given by the user of your module.
Parameters for an installation script can be simple booleans, or some values. To indicate parameters, the user have to set an option in the @@modules@@ section of the configuration file of the application. The name of this option is @@{module}.installparam@@. For example, for a @@news@@ module, it will be @@news.installparam@@.
In this option, you can indicates simple names (it will be some booleans), or some names and values.
<code ini>
news.installparam = "enablecategories,defaultcategory=In the world"
</code>
Here, parameters will be a boolean named "enablecategories", and a parameter named "defaultcategory" with the value "In the world". We can imagine here that the installation script of the module "news" have the possibility to enable a "categories" management, and we could indicate the name of the default category to create.
To read parameters from the installation script, you have the @@M@getParameter@@ method. Indicates the name of the parameter, and it will return its value (true for a boolean). If the parameter does not exists in the installparam option, it returns @@null@. Example:
<code php>
function install() {
if ($this->getParameter('enablecategories')) {
// here some code to create the categories table for example...
// ...
// now create the default category
$defaultCategory = $this->getParameter('defaultcategory');
if ($defaultCategory) {
// here we could insert a record in the categories table
// with the label given into $defaultCategory.
}
}
}
</code>
===== Scripts to update a module =====
These scripts have specific file names: @@F@upgrade_{label}.php@@ where @@{label}@@ is a name which will be part of the name of the class. In jelix 1.2.5 and lower, the filename could be @@F@upgrade_to_{version}_{label}.php@@, where @@{version}@@ should be replaced by a version number. This format is now deprecated.
These scripts should be stored into the @@F@install/@@ directory of the module. They will be executed in the ascendant order of the version indicated into the filename. And only those for which the version is higher than the current installed version of the module, and lower and equal than the new version of the module. Imagine that you have these scripts (with deprecated format of names):
* @@F@upgrade_to_1.0_aaa.php@@
* @@F@upgrade_to_1.1pre.1234_bbb.php@@
* @@F@upgrade_to_1.1pre.1350_ccc.php@@
* @@F@upgrade_to_1.1_ddd.php@@
* @@F@upgrade_to_1.2a1_eee.php@@
* @@F@upgrade_fff.php@@ (new name format, with a version number 1.2, indicated into the class)
* @@F@upgrade_to_1.3_ggg.php@@
If the current version of the module is 1.1 and the new version of the module (indicated by the new @@[email protected]@@ file) is 1.2, then only these scripts will be executed, in this order:
* @@F@upgrade_to_1.2a1_eee.php@@
* @@F@upgrade_fff.php@@
A script for update should contain a class, named @@{module}ModuleUpgrader_{label}@@, where @@{module}@@ should be the module name, and @@{label}}@@, the label indicated in the filename of the script.
Because several scripts for update can be executed for the module, then class name must be different (else PHP won't like it). This is why we use a label, which **should be different for each script of a module**. (Jelix developers could use the version number instead of a label, but unfortunately, PHP doesn't like characters like "." or "-" in a class name).
The class should inherit from @@M@jInstallerModule@@, so you have exactely same behaviors and methods as in installation script. So you must implements a method @@M@install@@, you can call @@M@firstDbExec@@, @@M@getParameter@@ etc..
For scripts with new names (jelix 1.2.6 and higher), you must indicate the version number into the property @@P@$targetVersions@@ (which is an array), and a date in the property @@P@$date@@ with the format 'yyyy-mm-dd' or 'yyyy-mm-dd HH:ii'.
<code php>
<?php
class newsModuleUpgrader_fff extends jInstallerModule {
public $targetVersions = array('1.2');
public $date = '2001-06-21';
function install() {
// ....
}
}
</code>
You'll guess that you can indicate several versions in @@P@$targetVersions@@. It is useful when you have several branch in a project, and when an update script should be executed for several branch. With the date of the release, Jelix can determinate if, during an update, it can execute the script or not. For instance, you have a script for an update for versions 1.24 and 1.35. If the user update from the version 1.2.3 or from the version 1.3.4, the script will be called. If he update from the version 1.2.5 to the version 1.3.6, the script won't be called because the 1.2.6 version contains modifications brought by the 1.2.5 version.