XOOPS 2.5.6
Final
Main Page
Related Pages
Classes
Files
Examples
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Pages
modulesadmin.php
Go to the documentation of this file.
1
<?php
18
defined(
'XOOPS_INSTALL'
) or die('XOOPS Installation wizard die');
19
require_once XOOPS_ROOT_PATH . "/modules/system/admin/modulesadmin/modulesadmin.php";
20
21
/*
22
function xoops_module_install($dirname)
23
{
24
global $xoopsUser, $xoopsConfig;
25
$dirname = trim($dirname);
26
$db =& $GLOBALS["xoopsDB"];
27
$reservedTables = array('avatar', 'avatar_users_link', 'block_module_link', 'xoopscomments', 'config', 'configcategory', 'configoption', 'image', 'imagebody', 'imagecategory', 'imgset', 'imgset_tplset_link', 'imgsetimg', 'groups','groups_users_link','group_permission', 'online', 'bannerclient', 'banner', 'bannerfinish', 'priv_msgs', 'ranks', 'session', 'smiles', 'users', 'newblocks', 'modules', 'tplfile', 'tplset', 'tplsource', 'xoopsnotifications', 'banner', 'bannerclient', 'bannerfinish');
28
$module_handler =& xoops_gethandler('module');
29
if ($module_handler->getCount(new Criteria('dirname', $dirname)) == 0) {
30
$module =& $module_handler->create();
31
$module->loadInfoAsVar($dirname);
32
$module->setVar('weight', 1);
33
34
$error = false;
35
$errs = array();
36
$msgs = array();
37
$msgs[] = '<h4 style="text-align:left;margin-bottom: 0px;border-bottom: dashed 1px #000000;">'._MD_AM_INSTALLING .$module->getInfo('name').'</h4>';
38
if ($module->getInfo('image') != false && trim($module->getInfo('image')) != '') {
39
$msgs[] ='<img src="'.XOOPS_URL.'/modules/'.$dirname.'/'.trim($module->getInfo('image')).'" alt="" />';
40
}
41
$msgs[] ='<strong>'._VERSION.':</strong> '.$module->getInfo('version');
42
if ($module->getInfo('author') != false && trim($module->getInfo('author')) != '') {
43
$msgs[] ='<strong>'._AUTHOR.':</strong> '.trim($module->getInfo('author'));
44
}
45
$msgs[] = '';
46
$errs[] = '<h4 style="text-align:left;margin-bottom: 0px;border-bottom: dashed 1px #000000;">'._MD_AM_INSTALLING .$module->getInfo('name').'</h4>';
47
48
// Load module specific install script if any
49
$install_script = $module->getInfo('onInstall');
50
if ($install_script && trim($install_script) != '') {
51
include_once XOOPS_ROOT_PATH . '/modules/' . $dirname . '/' . trim($install_script);
52
}
53
$func = "xoops_module_pre_install_{$dirname}";
54
// If pre install function is defined, execute
55
if (function_exists($func)) {
56
$result = $func($module);
57
if ( !$result ) {
58
$error = true;
59
$errs[] = "<p>" . sprintf(_MD_AM_FAILED_EXECUTE, $func) . "</p>";
60
$errs = array_merge($errs, $module->getErrors());
61
} else {
62
$msgs[] = "<p>" . sprintf(_MD_AM_FAILED_SUCESS, "<strong>{$func}</strong>") . "</p>";
63
$msgs += $module->getErrors();
64
}
65
}
66
67
if ($error == false) {
68
$sqlfile = $module->getInfo('sqlfile');
69
if (is_array($sqlfile) && !empty($sqlfile[XOOPS_DB_TYPE])) {
70
71
$sql_file_path = XOOPS_ROOT_PATH."/modules/".$dirname."/".$sqlfile[XOOPS_DB_TYPE];
72
if (!file_exists($sql_file_path)) {
73
$errs[] = "<p>".sprintf(_MD_AM_SQL_NOT_FOUND, "<strong>{$sql_file_path}</strong>");
74
$error = true;
75
} else {
76
$msgs[] = "<p>".sprintf(_MD_AM_SQL_FOUND, "<strong>{$sql_file_path}</strong>")."<br />" ._MD_AM_CREATE_TABLES;
77
include_once XOOPS_ROOT_PATH.'/class/database/sqlutility.php';
78
$sql_query = fread(fopen($sql_file_path, 'r'), filesize($sql_file_path));
79
$sql_query = trim($sql_query);
80
SqlUtility::splitMySqlFile($pieces, $sql_query);
81
$created_tables = array();
82
foreach ($pieces as $piece) {
83
// [0] contains the prefixed query
84
// [4] contains unprefixed table name
85
$prefixed_query = SqlUtility::prefixQuery($piece, $db->prefix());
86
if (!$prefixed_query) {
87
$errs[] ="<p>".sprintf(_MD_AM_SQL_NOT_VALID, "<strong>".$piece."</strong>");
88
$error = true;
89
break;
90
}
91
// check if the table name is reserved
92
if (!in_array($prefixed_query[4], $reservedTables)) {
93
// not reserved, so try to create one
94
if (!$db->query($prefixed_query[0])) {
95
$errs[] = $db->error();
96
$error = true;
97
break;
98
} else {
99
100
if (!in_array($prefixed_query[4], $created_tables)) {
101
$msgs[] = " " . sprintf(_MD_AM_TABLE_CREATED, "<strong>" . $db->prefix($prefixed_query[4]) . "</strong>");
102
$created_tables[] = $prefixed_query[4];
103
} else {
104
$msgs[] = " " . sprintf(_MD_AM_INSERT_DATA, "<strong>" . $db->prefix($prefixed_query[4]) . "</strong>");
105
}
106
}
107
} else {
108
// the table name is reserved, so halt the installation
109
$errs[] = " " . sprintf(_MD_AM_TABLE_RESERVED, "<strong>" . $prefixed_query[4] . "</strong>");
110
$error = true;
111
break;
112
}
113
}
114
// if there was an error, delete the tables created so far, so the next installation will not fail
115
if ($error == true) {
116
foreach ($created_tables as $ct) {
117
$db->query("DROP TABLE " . $db->prefix($ct));
118
}
119
}
120
}
121
}
122
}
123
// if no error, save the module info and blocks info associated with it
124
if ($error == false) {
125
if (!$module_handler->insert($module)) {
126
$errs[] = "<p>".sprintf(_MD_AM_INSERT_DATA_FAILD, "<strong>".$module->getVar('name')."</strong>");
127
foreach ($created_tables as $ct) {
128
$db->query("DROP TABLE ".$db->prefix($ct));
129
}
130
$ret = "<p>".sprintf(_MD_AM_FAILINS, "<strong>".$module->name()."</strong>")." "._MD_AM_ERRORSC."<br />";
131
foreach ( $errs as $err ) {
132
$ret .= " - ".$err."<br />";
133
}
134
$ret .= "</p>";
135
unset($module);
136
unset($created_tables);
137
unset($errs);
138
unset($msgs);
139
return $ret;
140
} else {
141
$newmid = $module->getVar('mid');
142
unset($created_tables);
143
$msgs[] = "<p>"._MD_AM_INSERT_DATA_DONE. sprintf(_MD_AM_MODULEID, "<strong>".$newmid."</strong>");
144
$tplfile_handler =& xoops_gethandler('tplfile');
145
$templates = $module->getInfo('templates');
146
if ($templates != false) {
147
$msgs[] = _MD_AM_TEMPLATES_ADD;
148
foreach ($templates as $tpl) {
149
$tplfile =& $tplfile_handler->create();
150
$tpldata =& xoops_module_gettemplate($dirname, $tpl['file']);
151
$tplfile->setVar('tpl_source', $tpldata, true);
152
$tplfile->setVar('tpl_refid', $newmid);
153
154
$tplfile->setVar('tpl_tplset', 'default');
155
$tplfile->setVar('tpl_file', $tpl['file']);
156
$tplfile->setVar('tpl_desc', $tpl['description'], true);
157
$tplfile->setVar('tpl_module', $dirname);
158
$tplfile->setVar('tpl_lastmodified', time());
159
$tplfile->setVar('tpl_lastimported', 0);
160
$tplfile->setVar('tpl_type', 'module');
161
if (!$tplfile_handler->insert($tplfile)) {
162
$msgs[] = ' <span style="color:#ff0000;">'.sprintf(_MD_AM_TEMPLATE_ADD_ERROR, "<strong>".$tpl['file']."</strong>")."</span>";
163
} else {
164
$newtplid = $tplfile->getVar('tpl_id');
165
$msgs[] = " ".sprintf(_MD_AM_TEMPLATE_ADD_DATA, "<strong>".$tpl['file']."</strong>")."(ID: <strong>".$newtplid."</strong>)";
166
// generate compiled file
167
include_once XOOPS_ROOT_PATH.'/class/template.php';
168
if (!xoops_template_touch($newtplid)) {
169
$msgs[] = ' <span style="color:#ff0000;">'.sprintf(_MD_AM_TEMPLATE_COMPILED_FAILED, "<strong>".$tpl['file']."</strong>")."</span>";
170
} else {
171
$msgs[] = " ".sprintf(_MD_AM_TEMPLATE_COMPILED, "<strong>".$tpl['file']."</strong>");
172
}
173
}
174
unset($tpldata);
175
}
176
}
177
include_once XOOPS_ROOT_PATH.'/class/template.php';
178
xoops_template_clear_module_cache($newmid);
179
$blocks = $module->getInfo('blocks');
180
if ($blocks != false) {
181
$msgs[] = _MD_AM_BLOCKS_ADD;
182
foreach ($blocks as $blockkey => $block) {
183
// break the loop if missing block config
184
if (!isset($block['file']) || !isset($block['show_func'])) {
185
break;
186
}
187
$options = '';
188
if (!empty($block['options'])) {
189
$options = trim($block['options']);
190
}
191
$newbid = $db->genId($db->prefix('newblocks').'_bid_seq');
192
$edit_func = isset($block['edit_func']) ? trim($block['edit_func']) : '';
193
$template = '';
194
if ((isset($block['template']) && trim($block['template']) != '')) {
195
$content =& xoops_module_gettemplate($dirname, $block['template'], true);
196
}
197
if (empty($content)) {
198
$content = '';
199
} else {
200
$template = trim($block['template']);
201
}
202
$block_name = addslashes(trim($block['name']));
203
$sql = "INSERT INTO ".$db->prefix("newblocks")." (bid, mid, func_num, options, name, title, content, side, weight, visible, block_type, c_type, isactive, dirname, func_file, show_func, edit_func, template, bcachetime, last_modified) VALUES ($newbid, $newmid, ".intval($blockkey).", '$options', '".$block_name."','".$block_name."', '', 0, 0, 0, 'M', 'H', 1, '".addslashes($dirname)."', '".addslashes(trim($block['file']))."', '".addslashes(trim($block['show_func']))."', '".addslashes($edit_func)."', '".$template."', 0, ".time().")";
204
if (!$db->query($sql)) {
205
$msgs[] = ' <span style="color:#ff0000;">'.sprintf(_MD_AM_BLOCK_ADD_ERROR, "<strong>".$block['name']."</strong>").sprintf(_MD_AM_BLOCK_ADD_ERROR_DATABASE, "<strong>".$db->error()."</strong>")."</span>";
206
} else {
207
if (empty($newbid)) {
208
$newbid = $db->getInsertId();
209
}
210
$msgs[] = " ".sprintf(_MD_AM_BLOCK_ADD, "<strong>".$block['name']."</strong>").sprintf(_MD_AM_BLOCK_ID, "<strong>".$newbid."</strong>");
211
$sql = 'INSERT INTO '.$db->prefix('block_module_link').' (block_id, module_id) VALUES ('.$newbid.', -1)';
212
$db->query($sql);
213
if ($template != '') {
214
$tplfile =& $tplfile_handler->create();
215
$tplfile->setVar('tpl_refid', $newbid);
216
$tplfile->setVar('tpl_source', $content, true);
217
$tplfile->setVar('tpl_tplset', 'default');
218
$tplfile->setVar('tpl_file', $block['template']);
219
$tplfile->setVar('tpl_module', $dirname);
220
$tplfile->setVar('tpl_type', 'block');
221
$tplfile->setVar('tpl_desc', $block['description'], true);
222
$tplfile->setVar('tpl_lastimported', 0);
223
$tplfile->setVar('tpl_lastmodified', time());
224
if (!$tplfile_handler->insert($tplfile)) {
225
$msgs[] = ' <span style="color:#ff0000;">'.sprintf(_MD_AM_TEMPLATE_ADD_ERROR, "<strong>".$block['template']."</strong>")."</span>";
226
} else {
227
$newtplid = $tplfile->getVar('tpl_id');
228
$msgs[] = " ".sprintf(_MD_AM_TEMPLATE_ADD_DATA, "<strong>".$block['template']."</strong>")." (ID: <strong>".$newtplid."</strong>)";
229
// generate compiled file
230
include_once XOOPS_ROOT_PATH.'/class/template.php';
231
if (!xoops_template_touch($newtplid)) {
232
$msgs[] = ' <span style="color:#ff0000;">'.sprintf(_MD_AM_TEMPLATE_COMPILED_FAILED, "<strong>".$block['template']."</strong>")."</span>";
233
234
} else {
235
$msgs[] = " ".sprintf(_MD_AM_TEMPLATE_COMPILED, "<strong>".$block['template']."</strong>");
236
}
237
}
238
}
239
}
240
unset($content);
241
}
242
unset($blocks);
243
}
244
$configs = $module->getInfo('config');
245
if ($configs != false) {
246
if ($module->getVar('hascomments') != 0) {
247
include_once(XOOPS_ROOT_PATH.'/include/comment_constants.php');
248
array_push($configs, array('name' => 'com_rule', 'title' => '_CM_COMRULES', 'description' => '', 'formtype' => 'select', 'valuetype' => 'int', 'default' => 1, 'options' => array('_CM_COMNOCOM' => XOOPS_COMMENT_APPROVENONE, '_CM_COMAPPROVEALL' => XOOPS_COMMENT_APPROVEALL, '_CM_COMAPPROVEUSER' => XOOPS_COMMENT_APPROVEUSER, '_CM_COMAPPROVEADMIN' => XOOPS_COMMENT_APPROVEADMIN)));
249
array_push($configs, array('name' => 'com_anonpost', 'title' => '_CM_COMANONPOST', 'description' => '', 'formtype' => 'yesno', 'valuetype' => 'int', 'default' => 0));
250
}
251
} else {
252
if ($module->getVar('hascomments') != 0) {
253
$configs = array();
254
include_once(XOOPS_ROOT_PATH.'/include/comment_constants.php');
255
$configs[] = array('name' => 'com_rule', 'title' => '_CM_COMRULES', 'description' => '', 'formtype' => 'select', 'valuetype' => 'int', 'default' => 1, 'options' => array('_CM_COMNOCOM' => XOOPS_COMMENT_APPROVENONE, '_CM_COMAPPROVEALL' => XOOPS_COMMENT_APPROVEALL, '_CM_COMAPPROVEUSER' => XOOPS_COMMENT_APPROVEUSER, '_CM_COMAPPROVEADMIN' => XOOPS_COMMENT_APPROVEADMIN));
256
$configs[] = array('name' => 'com_anonpost', 'title' => '_CM_COMANONPOST', 'description' => '', 'formtype' => 'yesno', 'valuetype' => 'int', 'default' => 0);
257
}
258
}
259
// RMV-NOTIFY
260
if ($module->getVar('hasnotification') != 0) {
261
if (empty($configs)) {
262
$configs = array();
263
}
264
// Main notification options
265
include_once XOOPS_ROOT_PATH . '/include/notification_constants.php';
266
include_once XOOPS_ROOT_PATH . '/include/notification_functions.php';
267
$options = array();
268
$options['_NOT_CONFIG_DISABLE'] = XOOPS_NOTIFICATION_DISABLE;
269
$options['_NOT_CONFIG_ENABLEBLOCK'] = XOOPS_NOTIFICATION_ENABLEBLOCK;
270
$options['_NOT_CONFIG_ENABLEINLINE'] = XOOPS_NOTIFICATION_ENABLEINLINE;
271
$options['_NOT_CONFIG_ENABLEBOTH'] = XOOPS_NOTIFICATION_ENABLEBOTH;
272
273
$configs[] = array ('name' => 'notification_enabled', 'title' => '_NOT_CONFIG_ENABLE', 'description' => '_NOT_CONFIG_ENABLEDSC', 'formtype' => 'select', 'valuetype' => 'int', 'default' => XOOPS_NOTIFICATION_ENABLEBOTH, 'options' => $options);
274
// Event-specific notification options
275
// FIXME: doesn't work when update module... can't read back the array of options properly... " changing to "
276
$options = array();
277
$categories =& notificationCategoryInfo('',$module->getVar('mid'));
278
foreach ($categories as $category) {
279
$events =& notificationEvents ($category['name'], false, $module->getVar('mid'));
280
foreach ($events as $event) {
281
if (!empty($event['invisible'])) {
282
continue;
283
}
284
$option_name = $category['title'] . ' : ' . $event['title'];
285
$option_value = $category['name'] . '-' . $event['name'];
286
$options[$option_name] = $option_value;
287
}
288
}
289
$configs[] = array ('name' => 'notification_events', 'title' => '_NOT_CONFIG_EVENTS', 'description' => '_NOT_CONFIG_EVENTSDSC', 'formtype' => 'select_multi', 'valuetype' => 'array', 'default' => array_values($options), 'options' => $options);
290
}
291
292
if ($configs != false) {
293
$msgs[] = _MD_AM_MODULE_DATA_ADD;
294
$config_handler =& xoops_gethandler('config');
295
$order = 0;
296
foreach ($configs as $config) {
297
$confobj =& $config_handler->createConfig();
298
$confobj->setVar('conf_modid', $newmid);
299
$confobj->setVar('conf_catid', 0);
300
$confobj->setVar('conf_name', $config['name']);
301
$confobj->setVar('conf_title', $config['title'], true);
302
$confobj->setVar('conf_desc', $config['description'], true);
303
$confobj->setVar('conf_formtype', $config['formtype']);
304
$confobj->setVar('conf_valuetype', $config['valuetype']);
305
$confobj->setConfValueForInput($config['default'], true);
306
$confobj->setVar('conf_order', $order);
307
$confop_msgs = '';
308
if (isset($config['options']) && is_array($config['options'])) {
309
foreach ($config['options'] as $key => $value) {
310
$confop =& $config_handler->createConfigOption();
311
$confop->setVar('confop_name', $key, true);
312
$confop->setVar('confop_value', $value, true);
313
$confobj->setConfOptions($confop);
314
$confop_msgs .= '<br /> '._MD_AM_CONFIG_ADD. _MD_AM_NAME .' <strong>'.$key.'</strong> '. _MD_AM_VALUE.' <strong>'.$value.'</strong> ';
315
unset($confop);
316
}
317
}
318
$order++;
319
if ($config_handler->insertConfig($confobj) != false) {
320
$msgs[] = ' '.sprintf(_MD_AM_CONFIG_DATA_ADD, "<strong>".$config['name']."</strong>").$confop_msgs;
321
322
} else {
323
$msgs[] = ' <span style="color:#ff0000;">'.sprintf(_MD_AM_CONFIG_DATA_ADD_ERROR, "<strong>".$config['name']."</strong>")."</span>";
324
}
325
unset($confobj);
326
}
327
unset($configs);
328
}
329
}
330
if ($module->getInfo('hasMain')) {
331
$groups = array(XOOPS_GROUP_ADMIN, XOOPS_GROUP_USERS, XOOPS_GROUP_ANONYMOUS);
332
} else {
333
$groups = array(XOOPS_GROUP_ADMIN);
334
}
335
// retrieve all block ids for this module
336
$blocks = XoopsBlock::getByModule($newmid, false);
337
$msgs[] = _MD_AM_GROUP_SETTINGS_ADD;
338
$gperm_handler =& xoops_gethandler('groupperm');
339
foreach ($groups as $mygroup) {
340
if ($gperm_handler->checkRight('module_admin', 0, $mygroup)) {
341
$mperm =& $gperm_handler->create();
342
$mperm->setVar('gperm_groupid', $mygroup);
343
$mperm->setVar('gperm_itemid', $newmid);
344
$mperm->setVar('gperm_name', 'module_admin');
345
$mperm->setVar('gperm_modid', 1);
346
if (!$gperm_handler->insert($mperm)) {
347
$msgs[] = ' <span style="color:#ff0000;">'.sprintf(_MD_AM_ACCESS_ADMIN_ADD_ERROR, "<strong>".$mygroup."</strong>")."</span>";
348
} else {
349
$msgs[] = " ".sprintf(_MD_AM_ACCESS_ADMIN_ADD, "<strong>".$mygroup."</strong>");
350
}
351
unset($mperm);
352
}
353
$mperm =& $gperm_handler->create();
354
$mperm->setVar('gperm_groupid', $mygroup);
355
$mperm->setVar('gperm_itemid', $newmid);
356
$mperm->setVar('gperm_name', 'module_read');
357
$mperm->setVar('gperm_modid', 1);
358
if (!$gperm_handler->insert($mperm)) {
359
$msgs[] = ' <span style="color:#ff0000;">'.sprintf(_MD_AM_ACCESS_USER_ADD_ERROR, "<strong>".$mygroup."</strong>")."</span>";
360
} else {
361
$msgs[] = ' '.sprintf(_MD_AM_ACCESS_USER_ADD_ERROR, "<strong>".$mygroup."</strong>");
362
}
363
unset($mperm);
364
foreach ($blocks as $blc) {
365
$bperm =& $gperm_handler->create();
366
$bperm->setVar('gperm_groupid', $mygroup);
367
$bperm->setVar('gperm_itemid', $blc);
368
$bperm->setVar('gperm_name', 'block_read');
369
$bperm->setVar('gperm_modid', 1);
370
if (!$gperm_handler->insert($bperm)) {
371
$msgs[] = ' <span style="color:#ff0000;">'._MD_AM_BLOCK_ACCESS_ERROR.' Block ID: <strong>'.$blc.'</strong> Group ID: <strong>'.$mygroup.'</strong></span>';
372
} else {
373
$msgs[] = ' '._MD_AM_BLOCK_ACCESS. sprintf(_MD_AM_BLOCK_ID, "<strong>".$blc."</strong>") .sprintf(_MD_AM_GROUP_ID, "<strong>".$mygroup."</strong>");
374
}
375
unset($bperm);
376
}
377
}
378
unset($blocks);
379
unset($groups);
380
381
// execute module specific install script if any
382
$func = "xoops_module_install_{$dirname}";
383
if (function_exists($func)) {
384
if ( !$lastmsg = $func($module) ) {
385
$msgs[] = "<p>" . sprintf(_MD_AM_FAILED_EXECUTE, $func) . "</p>";
386
} else {
387
$msgs[] = "<p>" . sprintf(_MD_AM_FAILED_SUCESS, "<strong>{$func}</strong>") . "</p>";
388
if ( is_string( $lastmsg ) ) {
389
$msgs[] = $lastmsg;
390
}
391
}
392
}
393
394
$ret = '<div>' . implode("<br />", $msgs) . '</div><br />' . sprintf(_MD_AM_OKINS, "<strong>" . $module->getVar('name') . "</strong>");
395
unset($msgs);
396
unset($errs);
397
unset($module);
398
return $ret;
399
} else {
400
$ret = '<p>' . sprintf(_MD_AM_FAILINS, '<strong>' . $dirname . '</strong>') . ' ' . _MD_AM_ERRORSC . '<br />' . implode("<br />", $errs) . '</p>';
401
unset($msgs);
402
unset($errs);
403
return $ret;
404
}
405
} else {
406
return "<p>".sprintf(_MD_AM_FAILINS, "<strong>".$dirname."</strong>")." "._MD_AM_ERRORSC."<br /> ".sprintf(_MD_AM_ALEXISTS, $dirname)."</p>";
407
}
408
}
409
410
411
412
function &xoops_module_gettemplate($dirname, $template, $block = false)
413
{
414
global $xoopsConfig;
415
$ret = '';
416
if ($block) {
417
$path = XOOPS_ROOT_PATH.'/modules/'.$dirname.'/templates/blocks/'.$template;
418
} else {
419
$path = XOOPS_ROOT_PATH.'/modules/'.$dirname.'/templates/'.$template;
420
}
421
if (!file_exists($path)) {
422
return $ret;
423
} else {
424
$lines = file($path);
425
}
426
if (!$lines) {
427
return $ret;
428
}
429
$count = count($lines);
430
for ($i = 0; $i < $count; $i++) {
431
$ret .= str_replace("\n", "\r\n", str_replace("\r\n", "\n", $lines[$i]));
432
}
433
return $ret;
434
}
435
*/
436
?>
L:
0xoops
xoops-2.5.6
htdocs
install
include
modulesadmin.php
Generated on Fri May 10 2013 01:04:27 for XOOPS 2.5.6 by
1.8.3.1