1 <!-- $Id: msql.php,v 1.6.2.1 2001-08-18 00:34:27 dairiki Exp $ -->
7 MakeDBHash($pagename, $pagehash)
10 RetrievePage($dbi, $pagename, $pagestore)
11 InsertPage($dbi, $pagename, $pagehash)
12 SaveCopyToArchive($dbi, $pagename, $pagehash)
13 IsWikiPage($dbi, $pagename)
14 InitTitleSearch($dbi, $search)
15 TitleSearchNextMatch($dbi, &$pos)
16 InitFullSearch($dbi, $search)
17 FullSearchNextMatch($dbi, &$pos)
18 MakeBackLinkSearchRegexp($pagename)
19 InitBackLinkSearch($dbi, $pagename)
20 BackLinkSearchNextMatch($dbi, &$pos)
21 GetAllWikiPageNames($dbi)
25 // open a database and return the handle
26 // ignores MAX_DBM_ATTEMPTS
28 function OpenDataBase($dbinfo) {
31 if (! ($dbc = msql_connect())) {
32 $msg = gettext ("Cannot establish connection to database, giving up.");
34 $msg .= sprintf(gettext ("Error message: %s"), msql_error());
37 if (!msql_select_db($msql_db, $dbc)) {
38 $msg = gettext ("Cannot open database %s, giving up.");
40 $msg .= sprintf(gettext ("Error message: %s"), msql_error());
45 $dbi['table'] = $dbinfo['table']; // page metadata
46 $dbi['page_table'] = $dbinfo['page_table']; // page content
51 function CloseDataBase($dbi) {
52 // I found msql_pconnect unstable so we go the slow route.
53 return msql_close($dbi['dbc']);
57 // This should receive the full text of the page in one string
58 // It will break the page text into an array of strings
59 // of length MSQL_MAX_LINE_LENGTH which should match the length
60 // of the columns wikipages.LINE, archivepages.LINE in schema.minisql
62 function msqlDecomposeString($string) {
65 // initialize the array to satisfy E_NOTICE
66 for ($i = 0; $i < MSQL_MAX_LINE_LENGTH; $i++) {
71 // zero, one, infinity
72 // account for the small case
73 if (strlen($string) < MSQL_MAX_LINE_LENGTH) {
74 $ret_arr[$el] = $string;
79 $line = $string2 = "";
81 // split on single spaces
82 $words = preg_split("/ /", $string);
83 $num_words = count($words);
86 $ret_arr[0] = $words[0];
89 // for all words, build up lines < MSQL_MAX_LINE_LENGTH in $ret_arr
90 for ($x = 2; $x < $num_words; $x++) {
91 $length = strlen($line) + strlen($words[$x])
92 + strlen($ret_arr[$el]) + 1;
94 if ($length < MSQL_MAX_LINE_LENGTH) {
95 $line .= " " . $words[$x];
97 // put this line in the return array, reset, continue
98 $ret_arr[$el++] .= $line;
99 $line = " $words[$x]"; // reset
102 $ret_arr[$el] = $line;
107 // Take form data and prepare it for the db
108 function MakeDBHash($pagename, $pagehash)
110 $pagehash["pagename"] = addslashes($pagename);
111 if (!isset($pagehash["flags"]))
112 $pagehash["flags"] = 0;
113 if (!isset($pagehash["content"])) {
114 $pagehash["content"] = array();
116 $pagehash["content"] = implode("\n", $pagehash["content"]);
117 $pagehash["content"] = msqlDecomposeString($pagehash["content"]);
119 $pagehash["author"] = addslashes($pagehash["author"]);
120 if (empty($pagehash["refs"])) {
121 $pagehash["refs"] = "";
123 $pagehash["refs"] = serialize($pagehash["refs"]);
130 // Take db data and prepare it for display
131 function MakePageHash($dbhash)
133 // unserialize/explode content
134 $dbhash['refs'] = unserialize($dbhash['refs']);
139 // Return hash of page + attributes or default
140 function RetrievePage($dbi, $pagename, $pagestore) {
141 $pagename = addslashes($pagename);
142 $table = $pagestore['table'];
143 $pagetable = $pagestore['page_table'];
145 $query = "select * from $table where pagename='$pagename'";
146 // echo "<p>query: $query<p>";
147 $res = msql_query($query, $dbi['dbc']);
148 if (msql_num_rows($res)) {
149 $dbhash = msql_fetch_array($res);
151 $query = "select lineno,line from $pagetable " .
152 "where pagename='$pagename' " .
156 if ($res = msql_query($query, $dbi['dbc'])) {
157 $dbhash["content"] = array();
158 while ($row = msql_fetch_array($res)) {
159 $msql_content .= $row["line"];
161 $dbhash["content"] = explode("\n", $msql_content);
164 return MakePageHash($dbhash);
170 // Either insert or replace a key/value (a page)
171 function InsertPage($dbi, $pagename, $pagehash) {
173 $pagehash = MakeDBHash($pagename, $pagehash);
174 // $pagehash["content"] is now an array of strings
175 // of MSQL_MAX_LINE_LENGTH
177 // record the time of modification
178 $pagehash["lastmodified"] = time();
180 if (IsWikiPage($dbi, $pagename)) {
182 $PAIRS = "author='$pagehash[author]'," .
183 "created=$pagehash[created]," .
184 "flags=$pagehash[flags]," .
185 "lastmodified=$pagehash[lastmodified]," .
186 "pagename='$pagehash[pagename]'," .
187 "refs='$pagehash[refs]'," .
188 "version=$pagehash[version]";
190 $query = "UPDATE $dbi[table] SET $PAIRS WHERE pagename='$pagename'";
194 // build up the column names and values for the query
196 $COLUMNS = "author, created, flags, lastmodified, " .
197 "pagename, refs, version";
199 $VALUES = "'$pagehash[author]', " .
200 "$pagehash[created], $pagehash[flags], " .
201 "$pagehash[lastmodified], '$pagehash[pagename]', " .
202 "'$pagehash[refs]', $pagehash[version]";
205 $query = "INSERT INTO $dbi[table] ($COLUMNS) VALUES($VALUES)";
208 // echo "<p>Query: $query<p>\n";
210 // first, insert the metadata
211 $retval = msql_query($query, $dbi['dbc']);
212 if ($retval == false) {
213 printf(gettext ("Insert/update failed: %s"), msql_error());
218 // second, insert the page data
219 // remove old data from page_table
220 $query = "delete from $dbi[page_table] where pagename='$pagename'";
221 // echo "Delete query: $query<br>\n";
222 $retval = msql_query($query, $dbi['dbc']);
223 if ($retval == false) {
224 printf(gettext ("Delete on %s failed: %s"), $dbi[page_table],
229 // insert the new lines
230 reset($pagehash["content"]);
232 for ($x = 0; $x < count($pagehash["content"]); $x++) {
233 $line = addslashes($pagehash["content"][$x]);
234 $query = "INSERT INTO $dbi[page_table] " .
235 "(pagename, lineno, line) " .
236 "VALUES('$pagename', $x, '$line')";
237 // echo "Page line insert query: $query<br>\n";
238 $retval = msql_query($query, $dbi['dbc']);
239 if ($retval == false) {
240 printf(gettext ("Insert into %s failed: %s"), $dbi[page_table],
248 // for archiving pages to a separate table
249 function SaveCopyToArchive($dbi, $pagename, $pagehash) {
250 global $ArchivePageStore;
252 $pagehash = MakeDBHash($pagename, $pagehash);
253 // $pagehash["content"] is now an array of strings
254 // of MSQL_MAX_LINE_LENGTH
256 if (IsInArchive($dbi, $pagename)) {
258 $PAIRS = "author='$pagehash[author]'," .
259 "created=$pagehash[created]," .
260 "flags=$pagehash[flags]," .
261 "lastmodified=$pagehash[lastmodified]," .
262 "pagename='$pagehash[pagename]'," .
263 "refs='$pagehash[refs]'," .
264 "version=$pagehash[version]";
266 $query = "UPDATE $ArchivePageStore[table] SET $PAIRS WHERE pagename='$pagename'";
270 // build up the column names and values for the query
272 $COLUMNS = "author, created, flags, lastmodified, " .
273 "pagename, refs, version";
275 $VALUES = "'$pagehash[author]', " .
276 "$pagehash[created], $pagehash[flags], " .
277 "$pagehash[lastmodified], '$pagehash[pagename]', " .
278 "'$pagehash[refs]', $pagehash[version]";
281 $query = "INSERT INTO archive ($COLUMNS) VALUES($VALUES)";
284 // echo "<p>Query: $query<p>\n";
286 // first, insert the metadata
287 $retval = msql_query($query, $dbi['dbc']);
288 if ($retval == false) {
289 printf(gettext ("Insert/update failed: %s"), msql_error());
293 // second, insert the page data
294 // remove old data from page_table
295 $query = "delete from $ArchivePageStore[page_table] where pagename='$pagename'";
296 // echo "Delete query: $query<br>\n";
297 $retval = msql_query($query, $dbi['dbc']);
298 if ($retval == false) {
299 printf(gettext ("Delete on %s failed: %s"),
300 $ArchivePageStore[page_table], msql_error());
304 // insert the new lines
305 reset($pagehash["content"]);
307 for ($x = 0; $x < count($pagehash["content"]); $x++) {
308 $line = addslashes($pagehash["content"][$x]);
309 $query = "INSERT INTO $ArchivePageStore[page_table] " .
310 "(pagename, lineno, line) " .
311 "VALUES('$pagename', $x, '$line')";
312 // echo "Page line insert query: $query<br>\n";
313 $retval = msql_query($query, $dbi['dbc']);
314 if ($retval == false) {
315 printf(gettext ("Insert into %s failed: %s"),
316 $ArchivePageStore[page_table], msql_error());
325 function IsWikiPage($dbi, $pagename) {
326 $pagename = addslashes($pagename);
327 $query = "select pagename from wiki where pagename='$pagename'";
328 // echo "Query: $query<br>\n";
329 if ($res = msql_query($query, $dbi['dbc'])) {
330 return(msql_affected_rows($res));
335 function IsInArchive($dbi, $pagename) {
336 $pagename = addslashes($pagename);
337 $query = "select pagename from archive where pagename='$pagename'";
338 // echo "Query: $query<br>\n";
339 if ($res = msql_query($query, $dbi['dbc'])) {
340 return(msql_affected_rows($res));
346 // setup for title-search
347 function InitTitleSearch($dbi, $search) {
348 $search = addslashes($search);
349 $query = "select pagename from $dbi[table] " .
350 "where pagename clike '%$search%' order by pagename";
351 $res = msql_query($query, $dbi['dbc']);
357 // iterating through database
358 function TitleSearchNextMatch($dbi, $res) {
359 if($o = msql_fetch_object($res)) {
368 // setup for full-text search
369 function InitFullSearch($dbi, $search) {
370 // select unique page names from wikipages, and then
371 // retrieve all pages that come back.
372 $search = addslashes($search);
373 $query = "select distinct pagename from $dbi[page_table] " .
374 "where line clike '%$search%' " .
376 $res = msql_query($query, $dbi['dbc']);
381 // iterating through database
382 function FullSearchNextMatch($dbi, $res) {
383 global $WikiPageStore;
384 if ($row = msql_fetch_row($res)) {
385 return RetrievePage($dbi, $row[0], $WikiPageStore);
391 ////////////////////////
392 // new database features
394 // Compute PCRE suitable for searching for links to the given page.
395 function MakeBackLinkSearchRegexp($pagename) {
396 global $WikiNameRegexp;
398 // Note that in (at least some) PHP 3.x's, preg_quote only takes
399 // (at most) one argument. Also it doesn't quote '/'s.
400 // It does quote '='s, so we'll use that for the delimeter.
401 $quoted_pagename = preg_quote($pagename);
402 if (preg_match("/^$WikiNameRegexp\$/", $pagename)) {
403 # FIXME: This may need modification for non-standard (non-english) $WikiNameRegexp.
404 return "=(?<![A-Za-z0-9!])$quoted_pagename(?![A-Za-z0-9])=";
407 // Note from author: Sorry. :-/
409 . '(?<!\[)\[(?!\[)' // Single, isolated '['
410 . '([^]|]*\|)?' // Optional stuff followed by '|'
411 . '\s*' // Optional space
412 . $quoted_pagename // Pagename
413 . '\s*\]=' ); // Optional space, followed by ']'
414 // FIXME: the above regexp is still not quite right.
415 // Consider the text: " [ [ test page ]". This is a link to a page
416 // named '[ test page'. The above regexp will recognize this
417 // as a link either to '[ test page' (good) or to 'test page' (wrong).
421 // setup for back-link search
422 function InitBackLinkSearch($dbi, $pagename) {
423 global $WikiLinksStore;
425 $topage = addslashes($pagename);
427 // FIXME: this is buggy. If a [multiword link] is split accross
428 // multiple lines int the page_table, we wont find it.
429 // (Probably the best fix is to implement the link table, and use it.)
430 $res['regexp'] = MakeBackLinkSearchRegexp($pagename);
431 $res['res'] = msql_query( "SELECT pagename, line FROM $dbi[page_table]"
432 . " WHERE line LIKE '%$topage%'"
433 . " ORDER BY pagename",
435 $res['lastpage'] = '';
441 // iterating through database
442 function BackLinkSearchNextMatch($dbi, $res) {
444 if ( ! ($o = msql_fetch_object($res['res']))) {
447 if ( $res['lastpage'] == $o->pagename )
449 if ( ! preg_match($res['regexp'], $a->line) )
451 $res['lastpage'] = $o->pagename;
456 function IncreaseHitCount($dbi, $pagename) {
458 $query = "select hits from hitcount where pagename='$pagename'";
459 $res = msql_query($query, $dbi['dbc']);
460 if (msql_num_rows($res)) {
461 $hits = msql_result($res, 0, 'hits');
463 $query = "update hitcount set hits=$hits where pagename='$pagename'";
464 $res = msql_query($query, $dbi['dbc']);
467 $query = "insert into hitcount (pagename, hits) " .
468 "values ('$pagename', 1)";
469 $res = msql_query($query, $dbi['dbc']);
475 function GetHitCount($dbi, $pagename) {
477 $query = "select hits from hitcount where pagename='$pagename'";
478 $res = msql_query($query, $dbi['dbc']);
479 if (msql_num_rows($res)) {
480 $hits = msql_result($res, 0, 'hits');
490 function InitMostPopular($dbi, $limit) {
492 $query = "select * from hitcount " .
493 "order by hits desc, pagename limit $limit";
495 $res = msql_query($query, $dbi['dbc']);
500 function MostPopularNextMatch($dbi, $res) {
502 if ($hits = msql_fetch_array($res)) {
509 function GetAllWikiPageNames($dbi_) {
510 $res = msql_query("select pagename from wiki", $dbi['dbc']);
511 $rows = msql_num_rows($res);
512 for ($i = 0; $i < $rows; $i++) {
513 $pages[$i] = msql_result($res, $i, 'pagename');
518 ////////////////////////////////////////
519 // functionality for the wikilinks table
521 // takes a page name, returns array of scored incoming and outgoing links
523 /* Not implemented yet. The code below was copied from mysql.php...
525 function GetWikiPageLinks($dbi, $pagename) {
527 $pagename = addslashes($pagename);
528 $res = msql_query("select wikilinks.topage, wikiscore.score from wikilinks, wikiscore where wikilinks.topage=wikiscore.pagename and wikilinks.frompage='$pagename' order by score desc, topage", $dbi['dbc']);
530 $rows = msql_num_rows($res);
531 for ($i = 0; $i < $rows; $i++) {
532 $out = msql_fetch_array($res);
533 $links['out'][] = array($out['topage'], $out['score']);
536 $res = msql_query("select wikilinks.frompage, wikiscore.score from wikilinks, wikiscore where wikilinks.frompage=wikiscore.pagename and wikilinks.topage='$pagename' order by score desc, frompage", $dbi['dbc']);
537 $rows = msql_num_rows($res);
538 for ($i = 0; $i < $rows; $i++) {
539 $out = msql_fetch_array($res);
540 $links['in'][] = array($out['frompage'], $out['score']);
543 $res = msql_query("select distinct hitcount.pagename, hitcount.hits from wikilinks, hitcount where (wikilinks.frompage=hitcounts.pagename and wikilinks.topage='$pagename') or (wikilinks.topage=pagename and wikilinks.frompage='$pagename') order by hitcount.hits desc, wikilinks.pagename", $dbi['dbc']);
544 $rows = msql_num_rows($res);
545 for ($i = 0; $i < $rows; $i++) {
546 $out = msql_fetch_array($res);
547 $links['popular'][] = array($out['pagename'], $out['hits']);
554 // takes page name, list of links it contains
555 // the $linklist is an array where the keys are the page names
556 function SetWikiPageLinks($dbi, $pagename, $linklist) {
557 $frompage = addslashes($pagename);
559 // first delete the old list of links
560 msql_query("delete from wikilinks where frompage='$frompage'",
563 // the page may not have links, return if not
564 if (! count($linklist))
566 // now insert the new list of links
567 while (list($topage, $count) = each($linklist)) {
568 $topage = addslashes($topage);
569 if($topage != $frompage) {
570 msql_query("insert into wikilinks (frompage, topage) " .
571 "values ('$frompage', '$topage')", $dbi["dbc"]);
575 msql_query("delete from wikiscore", $dbi["dbc"]);
576 msql_query("insert into wikiscore select w1.topage, count(*) from wikilinks as w1, wikilinks as w2 where w2.topage=w1.frompage group by w1.topage", $dbi["dbc"]);