1 <?php rcs_id('$Id: msql.php,v 1.6.2.7 2001-11-16 02:53:21 wainstead Exp $');
6 MakeDBHash($pagename, $pagehash)
9 RetrievePage($dbi, $pagename, $pagestore)
10 InsertPage($dbi, $pagename, $pagehash)
11 SaveCopyToArchive($dbi, $pagename, $pagehash)
12 IsWikiPage($dbi, $pagename)
13 InitTitleSearch($dbi, $search)
14 TitleSearchNextMatch($dbi, &$pos)
15 InitFullSearch($dbi, $search)
16 FullSearchNextMatch($dbi, &$pos)
17 MakeBackLinkSearchRegexp($pagename)
18 InitBackLinkSearch($dbi, $pagename)
19 BackLinkSearchNextMatch($dbi, &$pos)
20 GetAllWikiPageNames($dbi)
24 // open a database and return the handle
25 // ignores MAX_DBM_ATTEMPTS
27 function OpenDataBase($dbinfo) {
30 if (! ($dbc = msql_connect())) {
31 $msg = gettext ("Cannot establish connection to database, giving up.");
33 $msg .= sprintf(gettext ("Error message: %s"), msql_error());
36 if (!msql_select_db($msql_db, $dbc)) {
37 $msg = gettext ("Cannot open database %s, giving up.");
39 $msg .= sprintf(gettext ("Error message: %s"), msql_error());
44 $dbi['table'] = $dbinfo['table']; // page metadata
45 $dbi['page_table'] = $dbinfo['page_table']; // page content
50 function CloseDataBase($dbi) {
51 // I found msql_pconnect unstable so we go the slow route.
52 return msql_close($dbi['dbc']);
56 // This should receive the full text of the page in one string
57 // It will break the page text into an array of strings
58 // of length MSQL_MAX_LINE_LENGTH which should match the length
59 // of the columns wikipages.LINE, archivepages.LINE in schema.minisql
61 function msqlDecomposeString($string) {
64 // initialize the array to satisfy E_NOTICE
65 for ($i = 0; $i < MSQL_MAX_LINE_LENGTH; $i++) {
70 // zero, one, infinity
71 // account for the small case
72 if (strlen($string) < MSQL_MAX_LINE_LENGTH) {
73 $ret_arr[$el] = $string;
78 $line = $string2 = "";
80 // split on single spaces
81 $words = preg_split("/ /", $string);
82 $num_words = count($words);
85 $ret_arr[0] = $words[0];
88 // for all words, build up lines < MSQL_MAX_LINE_LENGTH in $ret_arr
89 for ($x = 2; $x < $num_words; $x++) {
90 $length = strlen($line) + strlen($words[$x])
91 + strlen($ret_arr[$el]) + 1;
93 if ($length < MSQL_MAX_LINE_LENGTH) {
94 $line .= " " . $words[$x];
96 // put this line in the return array, reset, continue
97 $ret_arr[$el++] .= $line;
98 $line = " $words[$x]"; // reset
101 $ret_arr[$el] = $line;
106 // Take form data and prepare it for the db
107 function MakeDBHash($pagename, $pagehash)
109 $pagehash["pagename"] = addslashes($pagename);
110 if (!isset($pagehash["flags"]))
111 $pagehash["flags"] = 0;
112 if (!isset($pagehash["content"])) {
113 $pagehash["content"] = array();
115 $pagehash["content"] = implode("\n", $pagehash["content"]);
116 $pagehash["content"] = msqlDecomposeString($pagehash["content"]);
118 $pagehash["author"] = addslashes($pagehash["author"]);
119 if (empty($pagehash["refs"])) {
120 $pagehash["refs"] = "";
122 $pagehash["refs"] = serialize($pagehash["refs"]);
129 // Take db data and prepare it for display
130 function MakePageHash($dbhash)
132 // unserialize/explode content
133 $dbhash['refs'] = unserialize($dbhash['refs']);
138 // Return hash of page + attributes or default
139 function RetrievePage($dbi, $pagename, $pagestore) {
140 $pagename = addslashes($pagename);
141 $table = $pagestore['table'];
142 $pagetable = $pagestore['page_table'];
144 $query = "select * from $table where pagename='$pagename'";
145 // echo "<p>query: $query<p>";
146 $res = msql_query($query, $dbi['dbc']);
147 if (msql_num_rows($res)) {
148 $dbhash = msql_fetch_array($res);
150 $query = "select lineno,line from $pagetable " .
151 "where pagename='$pagename' " .
155 if ($res = msql_query($query, $dbi['dbc'])) {
156 $dbhash["content"] = array();
157 while ($row = msql_fetch_array($res)) {
158 $msql_content .= $row["line"];
160 $dbhash["content"] = explode("\n", $msql_content);
163 return MakePageHash($dbhash);
169 // Either insert or replace a key/value (a page)
170 function InsertPage($dbi, $pagename, $pagehash) {
172 $pagehash = MakeDBHash($pagename, $pagehash);
173 // $pagehash["content"] is now an array of strings
174 // of MSQL_MAX_LINE_LENGTH
176 // record the time of modification
177 $pagehash["lastmodified"] = time();
179 if (IsWikiPage($dbi, $pagename)) {
181 $PAIRS = "author='$pagehash[author]'," .
182 "created=$pagehash[created]," .
183 "flags=$pagehash[flags]," .
184 "lastmodified=$pagehash[lastmodified]," .
185 "pagename='$pagehash[pagename]'," .
186 "refs='$pagehash[refs]'," .
187 "version=$pagehash[version]";
189 $query = "UPDATE $dbi[table] SET $PAIRS WHERE pagename='$pagename'";
193 // build up the column names and values for the query
195 $COLUMNS = "author, created, flags, lastmodified, " .
196 "pagename, refs, version";
198 $VALUES = "'$pagehash[author]', " .
199 "$pagehash[created], $pagehash[flags], " .
200 "$pagehash[lastmodified], '$pagehash[pagename]', " .
201 "'$pagehash[refs]', $pagehash[version]";
204 $query = "INSERT INTO $dbi[table] ($COLUMNS) VALUES($VALUES)";
207 // echo "<p>Query: $query<p>\n";
209 // first, insert the metadata
210 $retval = msql_query($query, $dbi['dbc']);
211 if ($retval == false) {
212 printf(gettext ("Insert/update to table 'wiki' failed: %s"), msql_error());
217 // second, insert the page data
218 // remove old data from page_table
219 $query = "delete from $dbi[page_table] where pagename='$pagename'";
220 // echo "Delete query: $query<br>\n";
221 $retval = msql_query($query, $dbi['dbc']);
222 if ($retval == false) {
223 printf(gettext ("Delete on %s failed: %s"), $dbi[page_table],
228 // insert the new lines
229 reset($pagehash["content"]);
231 for ($x = 0; $x < count($pagehash["content"]); $x++) {
232 $line = addslashes($pagehash["content"][$x]);
233 if ($line == '') continue; // why do we always have 127 lines?
234 $esc_pagename = addslashes($pagename);
235 $query = "INSERT INTO $dbi[page_table] " .
236 "(pagename, lineno, line) " .
237 "VALUES('$esc_pagename', $x, '$line')";
238 //echo "Page line insert query: $query<br>\n";
239 $retval = msql_query($query, $dbi['dbc']);
240 if ($retval == false) {
241 printf(gettext ("Insert into %s failed: %s"), $dbi[page_table],
249 // for archiving pages to a separate table
250 function SaveCopyToArchive($dbi, $pagename, $pagehash) {
251 global $ArchivePageStore;
253 $pagehash = MakeDBHash($pagename, $pagehash);
254 // $pagehash["content"] is now an array of strings
255 // of MSQL_MAX_LINE_LENGTH
257 if (IsInArchive($dbi, $pagename)) {
259 $PAIRS = "author='$pagehash[author]'," .
260 "created=$pagehash[created]," .
261 "flags=$pagehash[flags]," .
262 "lastmodified=$pagehash[lastmodified]," .
263 "pagename='$pagehash[pagename]'," .
264 "refs='$pagehash[refs]'," .
265 "version=$pagehash[version]";
267 $query = "UPDATE $ArchivePageStore[table] SET $PAIRS WHERE pagename='$pagename'";
271 // build up the column names and values for the query
273 $COLUMNS = "author, created, flags, lastmodified, " .
274 "pagename, refs, version";
276 $VALUES = "'$pagehash[author]', " .
277 "$pagehash[created], $pagehash[flags], " .
278 "$pagehash[lastmodified], '$pagehash[pagename]', " .
279 "'$pagehash[refs]', $pagehash[version]";
282 $query = "INSERT INTO archive ($COLUMNS) VALUES($VALUES)";
285 // echo "<p>Query: $query<p>\n";
287 // first, insert the metadata
288 $retval = msql_query($query, $dbi['dbc']);
289 if ($retval == false) {
290 printf(gettext ("Insert/update into table 'archive' failed: %s"), msql_error());
294 // second, insert the page data
295 // remove old data from page_table
296 $query = "delete from $ArchivePageStore[page_table] where pagename='$pagename'";
297 // echo "Delete query: $query<br>\n";
298 $retval = msql_query($query, $dbi['dbc']);
299 if ($retval == false) {
300 printf(gettext ("Delete on %s failed: %s"),
301 $ArchivePageStore[page_table], msql_error());
305 // insert the new lines
306 reset($pagehash["content"]);
308 for ($x = 0; $x < count($pagehash["content"]); $x++) {
309 $line = addslashes($pagehash["content"][$x]);
310 $query = "INSERT INTO $ArchivePageStore[page_table] " .
311 "(pagename, lineno, line) " .
312 "VALUES('$pagename', $x, '$line')";
313 // echo "Page line insert query: $query<br>\n";
314 $retval = msql_query($query, $dbi['dbc']);
315 if ($retval == false) {
316 printf(gettext ("Insert into %s failed: %s"),
317 $ArchivePageStore[page_table], msql_error());
326 function IsWikiPage($dbi, $pagename) {
327 $pagename = addslashes($pagename);
328 $query = "select pagename from wiki where pagename='$pagename'";
329 // echo "Query: $query<br>\n";
330 if ($res = msql_query($query, $dbi['dbc'])) {
331 return(msql_affected_rows($res));
336 function IsInArchive($dbi, $pagename) {
337 $pagename = addslashes($pagename);
338 $query = "select pagename from archive where pagename='$pagename'";
339 // echo "Query: $query<br>\n";
340 if ($res = msql_query($query, $dbi['dbc'])) {
341 return(msql_affected_rows($res));
347 // setup for title-search
348 function InitTitleSearch($dbi, $search) {
349 $search = preg_replace('/(?=[%_\\\\])/', "\\", $search);
350 $search = addslashes($search);
351 $query = "select pagename from $dbi[table] " .
352 "where pagename clike '%$search%' order by pagename";
353 $res = msql_query($query, $dbi['dbc']);
359 // iterating through database
360 function TitleSearchNextMatch($dbi, $res) {
361 if($o = msql_fetch_object($res)) {
370 // setup for full-text search
371 function InitFullSearch($dbi, $search) {
372 // select unique page names from wikipages, and then
373 // retrieve all pages that come back.
374 $search = preg_replace('/(?=[%_\\\\])/', "\\", $search);
375 $search = addslashes($search);
376 $query = "select distinct pagename from $dbi[page_table] " .
377 "where line clike '%$search%' " .
379 $res = msql_query($query, $dbi['dbc']);
384 // iterating through database
385 function FullSearchNextMatch($dbi, $res) {
386 global $WikiPageStore;
387 if ($row = msql_fetch_row($res)) {
388 return RetrievePage($dbi, $row[0], $WikiPageStore);
394 ////////////////////////
395 // new database features
397 // Compute PCRE suitable for searching for links to the given page.
398 function MakeBackLinkSearchRegexp($pagename) {
399 global $WikiNameRegexp;
401 // Note that in (at least some) PHP 3.x's, preg_quote only takes
402 // (at most) one argument. Also it doesn't quote '/'s.
403 // It does quote '='s, so we'll use that for the delimeter.
404 $quoted_pagename = preg_quote($pagename);
405 if (preg_match("/^$WikiNameRegexp\$/", $pagename)) {
406 # FIXME: This may need modification for non-standard (non-english) $WikiNameRegexp.
407 return "=(?<![A-Za-z0-9!])$quoted_pagename(?![A-Za-z0-9])=";
410 // Note from author: Sorry. :-/
412 . '(?<!\[)\[(?!\[)' // Single, isolated '['
413 . '([^]|]*\|)?' // Optional stuff followed by '|'
414 . '\s*' // Optional space
415 . $quoted_pagename // Pagename
416 . '\s*\]=' ); // Optional space, followed by ']'
417 // FIXME: the above regexp is still not quite right.
418 // Consider the text: " [ [ test page ]". This is a link to a page
419 // named '[ test page'. The above regexp will recognize this
420 // as a link either to '[ test page' (good) or to 'test page' (wrong).
424 // setup for back-link search
425 function InitBackLinkSearch($dbi, $pagename) {
426 global $WikiLinksStore;
428 $topage = addslashes($pagename);
431 // FIXME: this is buggy. If a [multiword link] is split accross
432 // multiple lines int the page_table, we wont find it.
433 // (Probably the best fix is to implement the link table, and use it.)
434 $res['regexp'] = MakeBackLinkSearchRegexp($pagename);
435 $query = "SELECT pagename, line FROM $dbi[page_table]"
436 . " WHERE line LIKE '%$topage%'"
437 . " ORDER BY pagename";
439 //echo "<p>$query<p>\n";
440 $res['res'] = msql_query($query, $dbi["dbc"]);
445 // build an array of the results.
446 while ($hash = msql_fetch_array($res[res]) ) {
447 if ($arr[$count -1 ] == $hash[pagename])
449 $arr[$count] = $hash[pagename];
461 // iterating through database
462 function BackLinkSearchNextMatch($dbi, &$res) {
464 if ($res[count] > count($res[arr]))
467 $retval = $res[arr][$res[count]];
474 if ( ($o = msql_fetch_object($res['res'])) == FALSE ) {
475 echo "returning zero<p>\n";
476 echo "it's '$o' <p>\n";
479 if ( $res['lastpage'] == $o->pagename )
481 if ( ! preg_match($res['regexp'], $a->line) )
483 $res['lastpage'] = $o->pagename;
489 function IncreaseHitCount($dbi, $pagename) {
491 $qpagename = addslashes($pagename);
492 $query = "select hits from hitcount where pagename='$qpagename'";
493 $res = msql_query($query, $dbi['dbc']);
494 if (msql_num_rows($res)) {
495 $hits = msql_result($res, 0, 'hits');
497 $query = "update hitcount set hits=$hits where pagename='$qpagename'";
498 $res = msql_query($query, $dbi['dbc']);
501 $query = "insert into hitcount (pagename, hits) " .
502 "values ('$qpagename', 1)";
503 $res = msql_query($query, $dbi['dbc']);
509 function GetHitCount($dbi, $pagename) {
511 $qpagename = addslashes($pagename);
512 $query = "select hits from hitcount where pagename='$qpagename'";
513 $res = msql_query($query, $dbi['dbc']);
514 if (msql_num_rows($res)) {
515 $hits = msql_result($res, 0, 'hits');
525 function InitMostPopular($dbi, $limit) {
527 $query = "select * from hitcount " .
528 "order by hits desc, pagename limit $limit";
530 $res = msql_query($query, $dbi['dbc']);
535 function MostPopularNextMatch($dbi, $res) {
537 if ($hits = msql_fetch_array($res)) {
544 function GetAllWikiPageNames($dbi_) {
545 $res = msql_query("select pagename from wiki", $dbi['dbc']);
546 $rows = msql_num_rows($res);
547 for ($i = 0; $i < $rows; $i++) {
548 $pages[$i] = msql_result($res, $i, 'pagename');
553 ////////////////////////////////////////
554 // functionality for the wikilinks table
556 // takes a page name, returns array of scored incoming and outgoing links
558 /* Not implemented yet. The code below was copied from mysql.php...
560 function GetWikiPageLinks($dbi, $pagename) {
562 $pagename = addslashes($pagename);
563 $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']);
565 $rows = msql_num_rows($res);
566 for ($i = 0; $i < $rows; $i++) {
567 $out = msql_fetch_array($res);
568 $links['out'][] = array($out['topage'], $out['score']);
571 $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']);
572 $rows = msql_num_rows($res);
573 for ($i = 0; $i < $rows; $i++) {
574 $out = msql_fetch_array($res);
575 $links['in'][] = array($out['frompage'], $out['score']);
578 $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']);
579 $rows = msql_num_rows($res);
580 for ($i = 0; $i < $rows; $i++) {
581 $out = msql_fetch_array($res);
582 $links['popular'][] = array($out['pagename'], $out['hits']);
589 // takes page name, list of links it contains
590 // the $linklist is an array where the keys are the page names
591 function SetWikiPageLinks($dbi, $pagename, $linklist) {
592 $frompage = addslashes($pagename);
594 // first delete the old list of links
595 msql_query("delete from wikilinks where frompage='$frompage'",
598 // the page may not have links, return if not
599 if (! count($linklist))
601 // now insert the new list of links
602 while (list($topage, $count) = each($linklist)) {
603 $topage = addslashes($topage);
604 if($topage != $frompage) {
605 msql_query("insert into wikilinks (frompage, topage) " .
606 "values ('$frompage', '$topage')", $dbi["dbc"]);
610 msql_query("delete from wikiscore", $dbi["dbc"]);
611 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"]);