2 rcs_id('$Id: upgrade.php,v 1.16 2004-06-16 10:38:58 rurban Exp $');
5 Copyright 2004 $ThePhpWikiProgrammingTeam
7 This file is part of PhpWiki.
9 PhpWiki is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 PhpWiki is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with PhpWiki; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * Upgrade the WikiDB and config settings after installing a new
28 * Status: experimental, no queries for verification yet, no db update,
30 * Installation on an existing PhpWiki database needs some
31 * additional worksteps. Each step will require multiple pages.
34 * 1. Check for new or changed database schema and update it
35 * according to some predefined upgrade tables. (medium)
36 * 2. Check for new or changed (localized) pgsrc/ pages and ask
37 * for upgrading these. Check timestamps, upgrade silently or
38 * show diffs if existing. Overwrite or merge (easy)
39 * 3. Check for new or changed or deprecated index.php settings
40 * and help in upgrading these. (hard)
41 * 4. Check for changed plugin invocation arguments. (hard)
42 * 5. Check for changed theme variables. (hard)
44 * @author: Reini Urban
46 require_once("lib/loadsave.php");
49 * TODO: check for the pgsrc_version number, not the revision
51 function doPgsrcUpdate(&$request,$pagename,$path,$filename) {
52 $dbi = $request->getDbh();
53 $page = $dbi->getPage($pagename);
54 if ($page->exists()) {
55 // check mtime: update automatically if pgsrc is newer
56 $rev = $page->getCurrentRevision();
57 $page_mtime = $rev->get('mtime');
58 $data = implode("", file($path."/".$filename));
59 if (($parts = ParseMimeifiedPages($data))) {
60 usort($parts, 'SortByPageVersion');
62 $pageinfo = $parts[0];
63 $stat = stat($path."/".$filename);
64 $new_mtime = @$pageinfo['versiondata']['mtime'];
66 $new_mtime = @$pageinfo['versiondata']['lastmodified'];
68 $new_mtime = @$pageinfo['pagedata']['date'];
70 $new_mtime = $stat[9];
71 if ($new_mtime > $page_mtime) {
72 echo "$path/$pagename: ",_("newer than the existing page."),
73 _(" replace "),"($new_mtime > $page_mtime)","<br />\n";
74 LoadAny($request,$path."/".$filename);
77 echo "$path/$pagename: ",_("older than the existing page."),
78 _(" skipped"),".<br />\n";
81 echo "$path/$pagename: ",("unknown format."),
82 _(" skipped"),".<br />\n";
85 echo sprintf(_("%s does not exist"),$pagename),"<br />\n";
86 LoadAny($request,$path."/".$filename);
91 /** need the english filename (required precondition: urlencode == urldecode)
92 * returns the plugin name.
94 function isActionPage($filename) {
95 static $special = array("DebugInfo" => "_BackendInfo",
96 "PhpWikiRecentChanges" => "RssFeed",
97 "ProjectSummary" => "RssFeed",
98 "RecentReleases" => "RssFeed",
100 $base = preg_replace("/\..{1,4}$/","",basename($filename));
101 if (isset($special[$base])) return $special[$base];
102 if (FindFile("lib/plugin/".$base.".php",true)) return $base;
106 function CheckActionPageUpdate(&$request) {
107 echo "<h3>",_("check for necessary ActionPage updates"),"</h3>\n";
108 $dbi = $request->getDbh();
109 $path = FindFile('pgsrc');
110 $pgsrc = new fileSet($path);
111 // most actionpages have the same name as the plugin
112 foreach ($pgsrc->getFiles() as $filename) {
113 if (substr($filename,-1,1) == '~') continue;
114 $pagename = urldecode($filename);
115 if (isActionPage($filename)) {
116 doPgsrcUpdate($request, $pagename, $path, $filename);
121 // see loadsave.php for saving new pages.
122 function CheckPgsrcUpdate(&$request) {
123 echo "<h3>",_("check for necessary pgsrc updates"),"</h3>\n";
124 $dbi = $request->getDbh();
125 $path = FindLocalizedFile(WIKI_PGSRC);
126 $pgsrc = new fileSet($path);
127 // fixme: verification, ...
129 foreach ($pgsrc->getFiles() as $filename) {
130 if (substr($filename,-1,1) == '~') continue;
131 $pagename = urldecode($filename);
132 // don't ever update the HomePage
133 if (defined(HOME_PAGE))
134 if ($pagename == HOME_PAGE) $isHomePage = true;
136 if ($pagename == _("HomePage")) $isHomePage = true;
137 if ($pagename == "HomePage") $isHomePage = true;
139 echo "$path/$pagename: ",_("always skip the HomePage."),
140 _(" skipped"),".<br />\n";
144 if (!isActionPage($filename)) {
145 doPgsrcUpdate($request,$pagename,$path,$filename);
152 * TODO: Search table definition in appropriate schema
154 * Supported: mysql and generic SQL, for ADODB and PearDB.
156 function installTable(&$dbh, $table, $backend_type) {
158 if (!in_array($DBParams['dbtype'],array('SQL','ADODB'))) return;
159 echo _("MISSING")," ... \n";
160 $backend = &$dbh->_backend->_dbh;
162 $schema = findFile("schemas/${backend_type}.sql");
164 echo " ",_("FAILED"),": ",sprintf(_("no schema %s found"),"schemas/${backend_type}.sql")," ... <br />\n";
168 extract($dbh->_backend->_table_names);
169 $prefix = isset($DBParams['prefix']) ? $DBParams['prefix'] : '';
172 assert($session_tbl);
173 if ($backend_type == 'mysql') {
175 CREATE TABLE $session_tbl (
176 sess_id CHAR(32) NOT NULL DEFAULT '',
177 sess_data BLOB NOT NULL,
178 sess_date INT UNSIGNED NOT NULL,
179 sess_ip CHAR(15) NOT NULL,
180 PRIMARY KEY (sess_id),
185 CREATE TABLE $session_tbl (
186 sess_id CHAR(32) NOT NULL DEFAULT '',
187 sess_data ".($backend_type == 'pgsql'?'TEXT':'BLOB')." NOT NULL,
189 sess_ip CHAR(15) NOT NULL
191 $dbh->genericQuery("CREATE UNIQUE INDEX sess_id ON $session_tbl (sess_id)");
193 $dbh->genericQuery("CREATE INDEX sess_date on session (sess_date)");
196 $user_tbl = $prefix.'user';
197 if ($backend_type == 'mysql') {
199 CREATE TABLE $user_tbl (
200 userid CHAR(48) BINARY NOT NULL UNIQUE,
201 passwd CHAR(48) BINARY DEFAULT '',
206 CREATE TABLE $user_tbl (
207 userid CHAR(48) NOT NULL,
208 passwd CHAR(48) DEFAULT ''
210 $dbh->genericQuery("CREATE UNIQUE INDEX userid ON $user_tbl (userid)");
214 $pref_tbl = $prefix.'pref';
215 if ($backend_type == 'mysql') {
217 CREATE TABLE $pref_tbl (
218 userid CHAR(48) BINARY NOT NULL UNIQUE,
219 prefs TEXT NULL DEFAULT '',
224 CREATE TABLE $pref_tbl (
225 userid CHAR(48) NOT NULL,
226 prefs TEXT NULL DEFAULT '',
228 $dbh->genericQuery("CREATE UNIQUE INDEX userid ON $pref_tbl (userid)");
232 $member_tbl = $prefix.'member';
233 if ($backend_type == 'mysql') {
235 CREATE TABLE $member_tbl (
236 userid CHAR(48) BINARY NOT NULL,
237 groupname CHAR(48) BINARY NOT NULL DEFAULT 'users',
243 CREATE TABLE $member_tbl (
244 userid CHAR(48) NOT NULL,
245 groupname CHAR(48) NOT NULL DEFAULT 'users',
247 $dbh->genericQuery("CREATE INDEX userid ON $member_tbl (userid)");
248 $dbh->genericQuery("CREATE INDEX groupname ON $member_tbl (groupname)");
252 $rating_tbl = $prefix.'rating';
253 if ($backend_type == 'mysql') {
255 CREATE TABLE $rating_tbl (
256 dimension INT(4) NOT NULL,
257 raterpage INT(11) NOT NULL,
258 rateepage INT(11) NOT NULL,
259 ratingvalue FLOAT NOT NULL,
260 rateeversion INT(11) NOT NULL,
261 tstamp TIMESTAMP(14) NOT NULL,
262 PRIMARY KEY (dimension, raterpage, rateepage)
266 CREATE TABLE $rating_tbl (
267 dimension INT(4) NOT NULL,
268 raterpage INT(11) NOT NULL,
269 rateepage INT(11) NOT NULL,
270 ratingvalue FLOAT NOT NULL,
271 rateeversion INT(11) NOT NULL,
272 tstamp TIMESTAMP(14) NOT NULL,
274 $dbh->genericQuery("CREATE UNIQUE INDEX rating ON $rating_tbl (dimension, raterpage, rateepage)");
278 echo " ",_("CREATED"),"<br />\n";
282 * currently update only session, user, pref and member
283 * jeffs-hacks database api (around 1.3.2) later
284 * people should export/import their pages if using that old versions.
286 function CheckDatabaseUpdate($request) {
287 global $DBParams, $DBAuthParams;
288 if (!in_array($DBParams['dbtype'], array('SQL','ADODB'))) return;
289 echo "<h3>",_("check for necessary database updates"),"</h3>\n";
290 $dbh = &$request->_dbi;
291 $tables = $dbh->_backend->listOfTables();
292 $backend_type = $dbh->_backend->backendType();
293 $prefix = isset($DBParams['prefix']) ? $DBParams['prefix'] : '';
294 extract($dbh->_backend->_table_names);
295 foreach (explode(':','session:user:pref:member') as $table) {
296 echo sprintf(_("check for table %s"), $table)," ...";
297 if (!in_array($prefix.$table, $tables)) {
298 installTable($dbh, $table, $backend_type);
300 echo _("OK")," <br />\n";
303 $backend = &$dbh->_backend->_dbh;
304 // 1.3.8 added session.sess_ip
305 if (phpwiki_version() >= 1030.08 and USE_DB_SESSION and isset($request->_dbsession)) {
306 echo _("check for new session.sess_ip column")," ... ";
307 $database = $dbh->_backend->database();
308 assert(!empty($DBParams['db_session_table']));
309 $session_tbl = $prefix . $DBParams['db_session_table'];
310 $sess_fields = $dbh->_backend->listOfFields($database, $session_tbl);
311 if (!strstr(strtolower(join(':', $sess_fields)),"sess_ip")) {
312 echo "<b>",_("ADDING"),"</b>"," ... ";
313 $dbh->genericQuery("ALTER TABLE $session_tbl ADD sess_ip CHAR(15) NOT NULL");
319 // 1.3.10 mysql requires page.id auto_increment
320 // mysql, mysqli or mysqlt
321 if (phpwiki_version() >= 1030.099 and substr($backend_type,0,5) == 'mysql') {
322 echo _("check for page.id auto_increment flag")," ...";
323 assert(!empty($page_tbl));
324 $database = $dbh->_backend->database();
325 $fields = mysql_list_fields($database, $page_tbl, $dbh->_backend->connection());
326 $columns = mysql_num_fields($fields);
327 for ($i = 0; $i < $columns; $i++) {
328 if (mysql_field_name($fields, $i) == 'id') {
329 $flags = mysql_field_flags($fields, $i);
330 //FIXME: something wrong with ADODB here!
331 if (!strstr(strtolower($flags),"auto_increment")) {
332 echo "<b>",_("ADDING"),"</b>"," ... ";
333 // MODIFY col_def valid since mysql 3.22.16,
334 // older mysql's need CHANGE old_col col_def
335 $dbh->genericQuery("ALTER TABLE $page_tbl CHANGE id id INT NOT NULL AUTO_INCREMENT");
336 $fields = mysql_list_fields($database, $page_tbl);
337 if (!strstr(strtolower(mysql_field_flags($fields, $i)),"auto_increment"))
338 echo " <b><font color=\"red\">",_("FAILED"),"</font></b><br />\n";
340 echo _("OK"),"<br />\n";
342 echo _("OK"),"<br />\n";
347 mysql_free_result($fields);
349 // check for mysql 4.1.x binary search bug
350 // http://bugs.mysql.com/bug.php?id=1491
351 // not yet tested for 4.1.2alpha, but confirmed for 4.1.0alpha
352 if (substr($backend_type,0,5) == 'mysql') {
353 echo _("check for mysql 4.1.x binary search bug")," ...";
354 $result = mysql_query("SELECT VERSION()",$dbh->_backend->connection());
355 $row = mysql_fetch_row($result);
356 $mysql_version = $row[0];
357 $arr = explode('.',$mysql_version);
358 $version = (string)(($arr[0] * 100) + $arr[1]) . "." . $arr[2];
359 if ($version > 410.0 and $version < 420.0) {
360 $dbh->genericQuery("ALTER TABLE $page_tbl CHANGE pagename pagename VARCHAR(100) NOT NULL;");
361 echo sprintf(_("version <em>%s</em> <b>FIXED</b>"), $mysql_version),"<br />\n";
363 echo sprintf(_("version <em>%s</em> not affected"), $mysql_version),"<br />\n";
370 * Upgrade: Base class for multipage worksteps
371 * identify, validate, display options, next step
376 class Upgrade_CheckPgsrc extends Upgrade {
379 class Upgrade_CheckDatabaseUpdate extends Upgrade {
382 // TODO: At which step are we?
383 // validate and do it again or go on with next step.
385 /** entry function from lib/main.php
387 function DoUpgrade($request) {
389 if (!$request->_user->isAdmin()) {
390 $request->_notAuthorized(WIKIAUTH_ADMIN);
392 HTML::div(array('class' => 'disabled-plugin'),
393 fmt("Upgrade disabled: user != isAdmin")));
397 StartLoadDump($request, _("Upgrading this PhpWiki"));
398 CheckActionPageUpdate($request);
399 CheckDatabaseUpdate($request);
400 CheckPgsrcUpdate($request);
401 //CheckThemeUpdate($request);
402 EndLoadDump($request);
407 $Log: not supported by cvs2svn $
408 Revision 1.15 2004/06/07 19:50:40 rurban
409 add owner field to mimified dump
411 Revision 1.14 2004/06/07 18:38:18 rurban
412 added mysql 4.1.x search fix
414 Revision 1.13 2004/06/04 20:32:53 rurban
415 Several locale related improvements suggested by Pierrick Meignen
416 LDAP fix by John Cole
417 reanable admin check without ENABLE_PAGEPERM in the admin plugins
419 Revision 1.12 2004/05/18 13:59:15 rurban
420 rename simpleQuery to genericQuery
422 Revision 1.11 2004/05/15 13:06:17 rurban
423 skip the HomePage, at first upgrade the ActionPages, then the database, then the rest
425 Revision 1.10 2004/05/15 01:19:41 rurban
426 upgrade prefix fix by Kai Krakow
428 Revision 1.9 2004/05/14 11:33:03 rurban
429 version updated to 1.3.11pre
430 upgrade stability fix
432 Revision 1.8 2004/05/12 10:49:55 rurban
433 require_once fix for those libs which are loaded before FileFinder and
434 its automatic include_path fix, and where require_once doesn't grok
435 dirname(__FILE__) != './lib'
436 upgrade fix with PearDB
437 navbar.tmpl: remove spaces for IE button alignment
439 Revision 1.7 2004/05/06 17:30:38 rurban
440 CategoryGroup: oops, dos2unix eol
441 improved phpwiki_version:
442 pre -= .0001 (1.3.10pre: 1030.099)
443 -p1 += .001 (1.3.9-p1: 1030.091)
444 improved InstallTable for mysql and generic SQL versions and all newer tables so far.
445 abstracted more ADODB/PearDB methods for action=upgrade stuff:
446 backend->backendType(), backend->database(),
447 backend->listOfFields(),
448 backend->listOfTables(),
450 Revision 1.6 2004/05/03 15:05:36 rurban
453 Revision 1.4 2004/05/02 21:26:38 rurban
454 limit user session data (HomePageHandle and auth_dbi have to invalidated anyway)
455 because they will not survive db sessions, if too large.
456 extended action=upgrade
457 some WikiTranslation button work
458 revert WIKIAUTH_UNOBTAINABLE (need it for main.php)
459 some temp. session debug statements
461 Revision 1.3 2004/04/29 22:33:30 rurban
462 fixed sf.net bug #943366 (Kai Krakow)
463 couldn't load localized url-undecoded pagenames
465 Revision 1.2 2004/03/12 15:48:07 rurban
466 fixed explodePageList: wrong sortby argument order in UnfoldSubpages
467 simplified lib/stdlib.php:explodePageList
476 // c-hanging-comment-ender-p: nil
477 // indent-tabs-mode: nil