upgrade.php 25 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
/**
 * This program is part of Mahara
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 *
 * @package    mahara
20
21
 * @subpackage core
 * @author     Penny Leach <penny@catalyst.net.nz>
22
23
24
25
26
27
28
29
30
31
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
 * @copyright  (C) 2006,2007 Catalyst IT Ltd http://catalyst.net.nz
 *
 */

defined('INTERNAL') || die();

/**
 * Class to use for installation exceptions
 */
32
class InstallationException extends SystemException {}
33
34
35


/**
36
37
38
39
40
 * This function checks core and plugins for which need to be upgraded/installed
 *
 * @param string $name The name of the plugin to check. If no name is specified,
 *                     all plugins are checked.
 * @return array of objects
41
 */
42
function check_upgrades($name=null) {
43

44
45
46
47
    $pluginstocheck = plugin_types();

    $toupgrade = array();
    $installing = false;
48
    $disablelogin = false;
49
50

    require('version.php');
51
52
53
    if (isset($config->disablelogin) && !empty($config->disablelogin)) {
        $disablelogin = true;
    }
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
    // check core first...
    if (empty($name) || $name == 'core') {
        try {
            $coreversion = get_config('version');
        } 
        catch (Exception $e) {
            $coreversion = 0;
        }
        if (empty($coreversion)) {
            $core = new StdClass;
            $core->install = true;
            $core->to = $config->version;
            $core->torelease = $config->release;
            $toupgrade['core'] = $core;
            $installing = true;
        } 
        else if ($config->version > $coreversion) {
71
72
73
            $corerelease = get_config('release');
            if (isset($config->minupgradefrom) && isset($config->minupgraderelease) 
                && $coreversion < $config->minupgradefrom) {
74
                throw new ConfigSanityException("Must upgrade to $config->minupgradefrom "
75
76
                                          . "($config->minupgraderelease) first "
                                          . " (you have $coreversion ($corerelease)");
77
            }
78
79
80
            $core = new StdClass;
            $core->upgrade = true;
            $core->from = $coreversion;
81
            $core->fromrelease = $corerelease;
82
83
84
85
86
87
            $core->to = $config->version;
            $core->torelease = $config->release;
            $toupgrade['core'] = $core;
        }
    }

88
    // If we were just checking if the core needed to be upgraded, we can stop here
89
    if ($name == 'core') {
90
        $toupgrade['core']->disablelogin = $disablelogin;
91
92
93
94
95
        return $toupgrade['core'];
    }

    $plugins = array();
    if (!empty($name)) {
96
97
98
99
100
101
        try {
            $bits = explode('.', $name);
            $pt = $bits[0];
            $pn = $bits[1];
            $pp = null;
            if ($pt == 'blocktype' && strpos($pn, '/') !== false) {
102
                $bits = explode('/', $pn);
103
104
105
106
107
108
                $pp = get_config('docroot') . 'artefact/' . $bits[0]  . '/blocktype/' . $bits[1];
            }
            validate_plugin($pt, $pn, $pp);
            $plugins[] = explode('.', $name);
        }
        catch (InstallationException $_e) {
109
            log_warn("Plugin $pt $pn is not installable: " . $_e->GetMessage());
110
        }
111
112
113
114
115
116
117
118
119
120
121
    }
    else {
        foreach ($pluginstocheck as $plugin) {
            $dirhandle = opendir(get_config('docroot') . $plugin);
            while (false !== ($dir = readdir($dirhandle))) {
                if (strpos($dir, '.') === 0) {
                    continue;
                }
                if (!is_dir(get_config('docroot') . $plugin . '/' . $dir)) {
                    continue;
                }
122
123
124
125
126
                try {
                    validate_plugin($plugin, $dir);
                    $plugins[] = array($plugin, $dir);
                }
                catch (InstallationException $_e) {
127
                    log_warn("Plugin $plugin $dir is not installable: " . $_e->GetMessage());
128
129
130
131
132
                }

                if ($plugin == 'artefact') { // go check it for blocks as well
                    $btlocation = get_config('docroot') . $plugin . '/blocktype';
                    if (!is_dir($btlocation)) {
133
                        continue;
134
135
136
137
138
139
140
141
142
143
                    }   
                    $btdirhandle = opendir($btlocation);
                    while (false !== ($btdir = readdir($btdirhandle))) {
                        if (strpos($btdir, '.') === 0) {
                            continue;
                        }
                        if (!is_dir(get_config('docroot') . $plugin . '/blocktype/' . $btdir)) {
                            continue;
                        }
                        $plugins[] = array('blocktype', $dir . '/' . $btdir);
144
145
                    }
                }
146
147
148
149
150
151
152
153
154
155
            }
        }
    }

    foreach ($plugins as $plugin) {
        $plugintype = $plugin[0];
        $pluginname = $plugin[1];
        $pluginpath = "$plugin[0]/$plugin[1]";
        $pluginkey  = "$plugin[0].$plugin[1]";

156
157
158
159
160
161
        if ($plugintype == 'blocktype' && strpos($pluginname, '/') !== false) {
            // sigh.. we're a bit special...
            $bits = explode('/', $pluginname);
            $pluginpath = 'artefact/' . $bits[0] . '/blocktype/' . $bits[1];
        }

162
163
164
165
        // Don't try to get the plugin info if we are installing - it will
        // definitely fail
        $pluginversion = 0;
        if (!$installing) {
166
            if ($installed = get_record($plugintype . '_installed', 'name', $pluginname)) {
167
168
169
                $pluginversion = $installed->version;
                $pluginrelease =  $installed->release;
            }
170
        }
171
172

        $config = new StdClass;
173
174
175
        require(get_config('docroot') . $pluginpath . '/version.php');
        if (isset($config->disablelogin) && !empty($config->disablelogin)) {
            $disablelogin = true;
176
177
178
        }

        if (empty($pluginversion)) {
179
180
181
            if (empty($installing) && $pluginkey != $name) {
                continue;
            }
182
183
184
185
            $plugininfo = new StdClass;
            $plugininfo->install = true;
            $plugininfo->to = $config->version;
            $plugininfo->torelease = $config->release;
186
187
188
189
190
191
            if (property_exists($config, 'requires_config')) {
                $plugininfo->requires_config = $config->requires_config;
            }
            if (property_exists($config, 'requires_parent')) {
                $plugininfo->requires_parent = $config->requires_parent;
            }
192
193
194
            $toupgrade[$pluginkey] = $plugininfo;
        }
        else if ($config->version > $pluginversion) {
195
196
197
198
199
            if (isset($config->minupgradefrom) && isset($config->minupgraderelease)
                && $pluginversion < $config->minupgradefrom) {
                throw new ConfigSanityException("Must upgrade to $config->minupgradefrom "
                                          . " ($config->minupgraderelease) first "
                                          . " (you have $pluginversion ($pluginrelease))");
200
            }
201
202
203
204
205
206
            $plugininfo = new StdClass;
            $plugininfo->upgrade = true;
            $plugininfo->from = $pluginversion;
            $plugininfo->fromrelease = $pluginrelease;
            $plugininfo->to = $config->version;
            $plugininfo->torelease = $config->release;
207
208
209
210
211
212
            if (property_exists($config, 'requires_config')) {
                $plugininfo->requires_config = $config->requires_config;
            }
            if (property_exists($config, 'requires_parent')) {
                $plugininfo->requires_parent = $config->requires_parent;
            }
213
214
215
216
217
218
219
220
221
222
223
            $toupgrade[$pluginkey] = $plugininfo;
        }
    }

    // if we've just asked for one, don't return an array...
    if (!empty($name) && count($toupgrade) == 1) {
        $upgrade = new StdClass;
        $upgrade->name = $name;
        foreach ((array)$toupgrade[$name] as $key => $value) {
            $upgrade->{$key} = $value;
        }
224
        $upgrade->disablelogin = $disablelogin;
225
226
        return $upgrade;
    }
227
    $toupgrade['disablelogin'] = $disablelogin;
228
229
230
    if (count($toupgrade) == 1) {
        $toupgrade = array();
    }
231
    uksort($toupgrade, 'sort_upgrades');
232
233
234
    return $toupgrade;
}

235
236
237
238
239
/**
 * Upgrades the core system to given upgrade version.
 *
 * @param object $upgrade   The version to upgrade to
 * @return bool             Whether the upgrade succeeded or not
240
 * @throws SQLException     If the upgrade failed due to a database error
241
 */
242
243
244
function upgrade_core($upgrade) {
    global $db;

245
    $location = get_config('libroot') . 'db/';
Penny Leach's avatar
Penny Leach committed
246
247

    db_begin();
248
249

    if (!empty($upgrade->install)) {
Penny Leach's avatar
Penny Leach committed
250
        if (!install_from_xmldb_file($location . 'install.xml')) {
Penny Leach's avatar
Penny Leach committed
251
            throw new SQLException("Failed to upgrade core (check logs for xmldb errors)");
Penny Leach's avatar
Penny Leach committed
252
        }
253
254
255
    }
    else {
        require_once($location . 'upgrade.php');
Penny Leach's avatar
Penny Leach committed
256
        xmldb_core_upgrade($upgrade->from);
257
258
    }

Penny Leach's avatar
Penny Leach committed
259
260
    set_config('version', $upgrade->to);
    set_config('release', $upgrade->torelease);
261
262
    
    if (!empty($upgrade->install)) {
Penny Leach's avatar
Penny Leach committed
263
        core_postinst();
264
    }
265

Penny Leach's avatar
Penny Leach committed
266
267
    db_commit();
    return true;
268
269
}

270
271
272
273
274
/**
 * Upgrades the plugin to a new version
 *
 * @param object $upgrade   Information about the plugin to upgrade
 * @return bool             Whether the upgrade succeeded or not
275
 * @throws SQLException     If the upgrade failed due to a database error
276
 */
277
278
279
280
281
282
283
284
function upgrade_plugin($upgrade) {
    global $db;

    $plugintype = '';
    $pluginname = '';

    list($plugintype, $pluginname) = explode('.', $upgrade->name);

285
286
287
288
    if ($plugintype == 'blocktype' && strpos($pluginname, '/') !== false) {
        list($artefactplugin, $blocktypename) = explode('/', $pluginname);
    }   

289
    $location = get_config('docroot') . $plugintype . '/' . $pluginname . '/db/';
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
    $db->StartTrans();

    if (!empty($upgrade->install)) {
        if (is_readable($location . 'install.xml')) {
            $status = install_from_xmldb_file($location . 'install.xml');
        }
        else {
            $status = true;
        }
    }
    else {
        if (is_readable($location .  'upgrade.php')) {
            require_once($location . 'upgrade.php');
            $function = 'xmldb_' . $plugintype . '_' . $pluginname . '_upgrade';
            $status = $function($upgrade->from);
        }
        else {
            $status = true;
        }
    }
    if (!$status || $db->HasFailedTrans()) {
        $db->CompleteTrans();
Penny Leach's avatar
Penny Leach committed
312
        throw new SQLException("Failed to upgrade $upgrade->name (check logs for xmldb errors)");
313
314
315
316
317
318
    }

    $installed = new StdClass;
    $installed->name = $pluginname;
    $installed->version = $upgrade->to;
    $installed->release = $upgrade->torelease;
319
320
321
322
323
324
325
326
    if ($plugintype == 'blocktype') {
        if (!empty($blocktypename)) {
            $installed->name = $blocktypename;
        }
        if (!empty($artefactplugin)) { // blocks come from artefactplugins.
            $installed->artefactplugin = $artefactplugin;
        }
    }
327
328
329
330
331
332
    if (property_exists($upgrade, 'requires_config')) {
        $installed->requires_config = $upgrade->requires_config;
    }
    if (property_exists($upgrade, 'requires_parent')) {
        $installed->requires_parent = $upgrade->requires_parent;
    }
333
    $installtable = $plugintype . '_installed';
334
335
336
337
338
339
340
341
342

    if (!empty($upgrade->install)) {
        insert_record($installtable,$installed);
    } 
    else {
        update_record($installtable, $installed, 'name');
    }

    // postinst stuff...
Nigel McNie's avatar
Nigel McNie committed
343
    safe_require($plugintype, $pluginname);
344
    $pcname = generate_class_name($plugintype, $installed->name);
345
346
347
348
349
350
351
352
353
354
355
356
357

    if ($crons = call_static_method($pcname, 'get_cron')) {
        foreach ($crons as $cron) {
            $cron = (object)$cron;
            if (empty($cron->callfunction)) {
                $db->RollbackTrans();
                throw new InstallationException("cron for $pcname didn't supply function name");
            }
            if (!is_callable(array($pcname, $cron->callfunction))) {
                $db->RollbackTrans();
                throw new InstallationException("cron $cron->callfunction for $pcname supplied but wasn't callable");
            }
            $new = false;
358
            $table = $plugintype . '_cron';
359
360
361
            if (!empty($upgrade->install)) {
                $new = true;
            }
362
            else if (!record_exists($table, 'plugin', $pluginname, 'callfunction', $cron->callfunction)) {
363
364
365
366
                $new = true;
            }
            $cron->plugin = $pluginname;
            if (!empty($new)) {
367
                insert_record($table, $cron);
368
369
            }
            else {
370
                update_record($table, $cron, array('plugin', 'callfunction'));
371
372
373
374
375
376
377
378
            }
        }
    }
    
    if ($events = call_static_method($pcname, 'get_event_subscriptions')) {
        foreach ($events as $event) {
            $event = (object)$event;

379
            if (!record_exists('event_type', 'name', $event->event)) {
380
381
382
383
384
385
386
387
388
389
390
391
                $db->RollbackTrans();
                throw new InstallationException("event $event->event for $pcname doesn't exist!");
            }
            if (empty($event->callfunction)) {
                $db->RollbackTrans();
                throw new InstallationException("event $event->event for $pcname didn't supply function name");
            }
            if (!is_callable(array($pcname, $event->callfunction))) {
                $db->RollbackTrans();
                throw new InstallationException("event $event->event with function $event->callfunction for $pcname supplied but wasn't callable");
            }
            $exists = false;
392
            $table = $plugintype . '_event_subscription';
393
            if (empty($upgrade->install)) {
394
                $exists = get_record($table, 'plugin' , $pluginname, 'event', $event->event);
395
396
397
            }
            $event->plugin = $pluginname;
            if (empty($exists)) {
398
                insert_record($table, $event);
399
400
            }
            else {
401
                update_record($table, $event, array('id' => $exists->id));
402
403
404
405
            }
        }
    }

406
407
     // install artefact types
    if ($plugintype == 'artefact') {
408
409
410
        if (!is_callable(array($pcname, 'get_artefact_types'))) {
            throw new InstallationException("Artefact plugin $pcname must implement get_artefact_types and doesn't");
        }
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
        $types = call_static_method($pcname, 'get_artefact_types');
        $ph = array();
        if (is_array($types)) {
            foreach ($types as $type) {
                $ph[] = '?';
                if (!record_exists('artefact_installed_type', 'plugin', $pluginname, 'name', $type)) {
                    $t = new StdClass;
                    $t->name = $type;
                    $t->plugin = $pluginname;
                    insert_record('artefact_installed_type',$t);
                }
            }
            $select = '(plugin = ? AND name NOT IN (' . implode(',', $ph) . '))';
            delete_records_select('artefact_installed_type', $select,
                                  array_merge(array($pluginname),$types));
        }
427
428

        //@todo install blocks here too.
429
    }
430
    
431
432
    $prevversion = (empty($upgrade->install)) ? $upgrade->from : 0;
    call_static_method($pcname, 'postinst', $prevversion);
433
434
435
436
437
438
439
    
    if ($db->HasFailedTrans()) {
        $status = false;
    }
    $db->CompleteTrans();
    
    return $status;
440
441
442
443
444
445
446
447

}

function core_postinst() {
    $status = true;
    $pages = site_content_pages();
    $now = db_format_timestamp(time());
    foreach ($pages as $name) {
Donal McMullan's avatar
Donal McMullan committed
448
        $page = new stdClass();
449
450
451
452
453
454
455
456
        $page->name = $name;
        $page->ctime = $now;
        $page->mtime = $now;
        $page->content = get_string($page->name . 'defaultcontent', 'install');
        if (!insert_record('site_content',$page)) {
            $status = false;
        }
    }
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488

    // Attempt to create session directories
    $sessionpath = get_config('dataroot') . 'sessions';
    if (check_dir_exists($sessionpath)) {
        // Create three levels of directories, named 0-9, a-f
        $characters = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
        foreach ($characters as $c1) {
            if (check_dir_exists("$sessionpath/$c1")) {
                foreach ($characters as $c2) {
                    if (check_dir_exists("$sessionpath/$c1/$c2")) {
                        foreach ($characters as $c3) {
                            if (!check_dir_exists("$sessionpath/$c1/$c2/$c3")) {
                                $status = false;
                                break(3);
                            }
                        }
                    }
                    else {
                        $status = false;
                        break(2);
                    }
                }
            }
            else {
                $status = false;
                break;
            }
        }
    }
    else {
        $status = false;
    }
489
490
491
492

    // Set default search plugin
    set_config('searchplugin', 'internal');

493
    set_config('lang', 'en.utf8');
494
    return $status;
495
496
}

497
function core_install_lastcoredata_defaults() {
498
    db_begin();
499
    $auth_instance = new StdClass;
500
501
502
503
    $institution->name = 'mahara';
    $institution->displayname = 'No Institution';
    $institution->authplugin  = 'internal';
    insert_record('institution', $institution);
504
505

    $auth_instance->instancename  = 'internal';
506
    $auth_instance->priority='1';
507
508
    $auth_instance->institution   = 'mahara';
    $auth_instance->authname      = 'internal';
509
    $auth_instance->id = insert_record('auth_instance', $auth_instance, 'id', true);
510
    $institution = new StdClass;
511

512
513
514
515
516
517
518
519
520
521
    // Insert the root user
    $user = new StdClass;
    $user->id = 0;
    $user->username = 'root';
    $user->password = '*';
    $user->salt = '*';
    $user->institution = 'mahara';
    $user->firstname = 'System';
    $user->lastname = 'User';
    $user->email = 'root@example.org';
522
    $user->quota = get_config_plugin('artefact', 'file', 'defaultquota');
523
524
525
526
527
    $newid = insert_record('usr', $user);

    if ($newid > 0 && get_config('dbtype') == 'mysql') { // gratuitous mysql workaround
        set_field('usr', 'id', 0, 'id', $newid);
    }
528
529
530
531
532

    $user = new StdClass;
    $user->username = 'admin';
    $user->password = 'mahara';
    $user->institution = 'mahara';
533
    $user->authinstance = $auth_instance->id;
534
535
536
537
538
    $user->passwordchange = 1;
    $user->admin = 1;
    $user->firstname = 'Admin';
    $user->lastname = 'User';
    $user->email = 'admin@example.org';
539
    $user->quota = get_config_plugin('artefact', 'file', 'defaultquota');
540
541
542
543
544
545
546
547
    $user->id = insert_record('usr', $user, 'id', true);
    set_profile_field($user->id, 'email', $user->email);
    set_profile_field($user->id, 'firstname', $user->firstname);
    set_profile_field($user->id, 'lastname', $user->lastname);
    set_config('installed', true);
    db_commit();
}

548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
function core_install_firstcoredata_defaults() {
    // Install the default institution
    db_begin();
    
    set_config('session_timeout', 1800);
    set_config('sitename', 'Mahara');
    set_config('pathtofile', '/usr/bin/file');

    // install the applications
    $app = new StdClass;
    $app->name = 'mahara';
    $app->displayname = 'Mahara';
    $app->xmlrpcserverurl = '/api/xmlrpc/server.php';
    $app->ssolandurl = '/auth/xmlrpc/land.php';
    insert_record('application', $app);

    $app->name = 'moodle';
    $app->displayname = 'Moodle';
    $app->xmlrpcserverurl = '/mnet/xmlrpc/server.php';
    $app->ssolandurl = '/auth/mnet/land.php';
    insert_record('application', $app);

    // insert the event types
    $eventtypes = array(
        'createuser',
        'updateuser',
        'suspenduser',
        'unsuspenduser',
        'deleteuser',
        'undeleteuser',
        'expireuser',
        'unexpireuser',
        'deactivateuser',
        'activateuser',
        'saveartefact',
        'deleteartefact',
        'saveview',
        'deleteview',
    );

    foreach ($eventtypes as $et) {
        $e = new StdClass;
        $e->name = $et;
        insert_record('event_type', $e);
    }

    // install the activity types
    $activitytypes = array(
        array('maharamessage', 0, 0),
        array('usermessage', 0, 0),
        array('feedback', 0, 0),
        array('watchlist', 0, 1),
        array('newview', 0, 1),
        array('viewaccess', 0, 1),
        array('contactus', 1, 1),
        array('objectionable', 1, 1),
        array('virusrepeat', 1, 1),
        array('virusrelease', 1, 1),
    );

    foreach ($activitytypes as $at) {
        $a = new StdClass;
        $a->name = $at[0];
        $a->admin = $at[1];
        $a->delay = $at[2];
        insert_record('activity_type', $a);
    }

    // install the cronjobs...
    $cronjobs = array(
        'rebuild_artefact_parent_cache_dirty'    => array('*', '*', '*', '*', '*'),
        'rebuild_artefact_parent_cache_complete' => array('0', '4', '*', '*', '*'),
        'auth_clean_partial_registrations'       => array('5', '0', '*', '*', '*'),
        'auth_handle_account_expiries'           => array('5', '10', '*', '*', '*'),
        'activity_process_queue'                 => array('*/5', '*', '*', '*', '*'),
    );
    foreach ($cronjobs as $callfunction => $times) {
        $cron = new StdClass;
        $cron->callfunction = $callfunction;
        $cron->minute       = $times[0];
        $cron->hour         = $times[1];
        $cron->day          = $times[2];
        $cron->month        = $times[3];
        $cron->dayofweek    = $times[4];
        insert_record('cron', $cron);
    }
    
    // install the blocktype categories

    db_commit();
}


/** 
* xmldb will pass us the xml file and we can perform any substitution as necessary
*/ 
644
function local_xmldb_contents_sub(&$contents) {
645
    // the main install.xml file needs to sub in plugintype tables.
646
647
648
649
650
651
652
653
654
    $searchstring = '<!-- PLUGIN_TYPE_SUBSTITUTION -->';
    if (strstr($contents, $searchstring) === 0) {
        return;
    }
    // ok, we're in the main file and we need to install all the plugin tables
    // get the basic skeleton structure
    $plugintables = file_get_contents(get_config('docroot') . 'lib/db/plugintables.xml');
    $tosub = '';
    foreach (plugin_types() as $plugin) {
655
656
        // any that want their own stuff can put it in docroot/plugintype/lib/db/plugintables.xml 
        //- like auth is a bit special
657
658
659
660
661
        $specialcase = get_config('docroot') . $plugin . '/plugintables.xml';
        if (is_readable($specialcase)) {
            $tosub .= file_get_contents($specialcase) . "\n";
        } 
        else {
662
663
664
665
666
667
668
669
            $replaced = '';
            // look for tables to put at the start...
            $pretables = get_config('docroot') . $plugin . '/beforetables.xml';
            if (is_readable($pretables)) {
                $replaced = file_get_contents($pretables) . "\n";
            }

            // perform any additional once off substitutions
670
671
            require_once(get_config('docroot') . $plugin . '/lib.php');
            if (method_exists(generate_class_name($plugin), 'extra_xmldb_substitution')) {
672
                $replaced  .= call_static_method(generate_class_name($plugin), 'extra_xmldb_substitution', $plugintables);
673
            }
674
            else {
675
                $replaced .= $plugintables;
676
            }
677
            $tosub .= str_replace('__PLUGINTYPE__', $plugin, $replaced) . "\n";
678
            // look for any tables to put at the end..
679
680
681
            $extratables = get_config('docroot') . $plugin . '/extratables.xml';
            if (is_readable($extratables)) {
                $tosub .= file_get_contents($extratables) . "\n";
682
            }
683
684
        }
    }
685
    $contents = str_replace($searchstring, $tosub, $contents);
686
687
}

688
689
690
691
692
693
694
695

/**
 * validates a plugin for installation
 * @throws InstallationException
*/
function validate_plugin($plugintype, $pluginname, $pluginpath='') {

    if (empty($pluginpath)) {
696
        $pluginpath = get_config('docroot') . $plugintype . '/' . $pluginname;
697
698
699
700
701
702
703
704
705
706
    }
    if (!file_exists($pluginpath . '/version.php')) {
        throw new InstallationException(get_string('versionphpmissing', 'error', $plugintype, $pluginname));
    }
    require_once('artefact.php');
    $funname = $plugintype . '_check_plugin_sanity';
    if (function_exists($funname)) {
        $funname($pluginname);
    }
    // @TODO more?
707
    // validate the plugin class
708
}
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734

/*
* the order things are installed/upgraded in matters
*/

function sort_upgrades($k1, $k2) {
    if ($k1 == 'core') {
        return -1;
    }
    else if ($k2 == 'core') {
        return 1;
    }
    else if ($k1 == 'firstcoredata') {
        return -1;
    }
    else if ($k2 == 'firstcoredata') {
        return 1;
    }
    else if ($k1 == 'lastcoredata') {
        return 1;
    }
    else if ($k2 == 'lastcoredata') {
        return -1;
    }
    return 0;
}
735
?>