]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/backend/file.php
and again a couple of more native db args: backlinks
[SourceForge/phpwiki.git] / lib / WikiDB / backend / file.php
1 <?php // -*-php-*-
2 rcs_id('$Id: file.php,v 1.21 2004-11-25 17:20:52 rurban Exp $');
3
4 /**
5  Copyright 1999, 2000, 2001, 2002, 2003 $ThePhpWikiProgrammingTeam
6
7  This file is part of PhpWiki.
8
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.
13
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.
18
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
22  */
23
24
25
26 /**
27  * Backend for handling file storage. 
28  *
29  * Author: Jochen Kalmbach, Jochen@kalmbachnet.de
30  */
31
32 /*
33  * TODO: 
34  * - Implement "optimize" / "sync" / "check" / "rebuild"
35  * - Optimize "get_previous_version"
36  * - Optimize "get_links" (reversed = true)
37  * - Optimize "get_all_revisions"
38  * - Optimize "most_popular" (separate file for "hitcount", 
39  *   which contains all pages)
40  * - Optimize "most_recent"
41  * - What should be done in "lock"/"unlock"/"close" ?
42  * - "WikiDB_backend_file_iter": Do I need to return 'version' and 'versiondata' ?
43  *
44  */
45
46 require_once('lib/WikiDB/backend.php');
47 require_once('lib/ErrorManager.php');
48
49 class WikiDB_backend_file
50 extends WikiDB_backend
51 {
52     var $data_dir;
53     var $_dir_names;
54
55     var $_page_data;          // temporarily stores the pagedata (via _loadPageData)
56     var $_page_version_data;  // temporarily stores the versiondata (via _loadVersionData)
57     var $_latest_versions;    // temporarily stores the latest version-numbers (for every pagename)
58
59     function WikiDB_backend_file( $dbparam )
60     {
61         $this->data_dir = $dbparam['directory'];
62         if (file_exists($this->data_dir) and is_file($this->data_dir))
63                 unlink($this->data_dir);
64         if (is_dir($this->data_dir) == false) {
65             mkdir($this->data_dir, 0755);
66         }
67
68         $this->_dir_names
69             = array('ver_data'     => $this->data_dir.'/'.'ver_data',
70                     'page_data'    => $this->data_dir.'/'.'page_data',
71                     'latest_ver'   => $this->data_dir.'/'.'latest_ver',
72                     'links'        => $this->data_dir.'/'.'links' );
73
74         foreach ($this->_dir_names as $key => $val) {
75                 if (file_exists($val) and is_file($val))
76                     unlink($val);
77             if (is_dir($val) == false)
78                 mkdir($val, 0755);
79         }
80
81         $this->_page_data = NULL;
82         $this->_page_version_data = NULL;
83         $this->_latest_versions = NULL;
84
85
86     }
87
88     // *********************************************************************
89     // common file load / save functions:
90     function _pagename2filename($type, $pagename, $version) {
91          if ($version == 0)
92              return $this->_dir_names[$type].'/'.urlencode($pagename);
93          else
94              return $this->_dir_names[$type].'/'.urlencode($pagename).'--'.$version;
95     }
96
97     function _loadPage($type, $pagename, $version, $set_pagename = true) {
98       $filename = $this->_pagename2filename($type, $pagename, $version);
99       if (!file_exists($filename)) return NULL;
100       if (!filesize($filename)) return array();
101       if ($fd = @fopen($filename, "rb")) {
102          $locked = flock($fd, 1); # Read lock
103          if (!$locked) { 
104             ExitWiki("Timeout while obtaining lock. Please try again"); 
105          }
106          if ($data = fread($fd, filesize($filename))) {
107             $pd = unserialize($data);
108             if ($set_pagename == true)
109                 $pd['pagename'] = $pagename;
110             if ($version != 0)
111                 $pd['version'] = $version;
112             if (!is_array($pd))
113                 ExitWiki(sprintf(gettext("'%s': corrupt file"),
114                                  htmlspecialchars($filename)));
115             else
116               return $pd;
117          }      
118          fclose($fd);
119       }
120       return NULL;
121     }
122
123     function _savePage($type, $pagename, $version, $data) {
124         $filename = $this->_pagename2filename($type, $pagename, $version);
125         if($fd = fopen($filename, 'a+b')) { 
126            $locked = flock($fd,2); #Exclusive blocking lock 
127            if (!$locked) { 
128               ExitWiki("Timeout while obtaining lock. Please try again"); 
129            }
130
131            rewind($fd);
132            ftruncate($fd, 0);
133            $pagedata = serialize($data);
134            fwrite($fd, $pagedata); 
135            fclose($fd);
136         } else {
137            ExitWiki("Error while writing page '$pagename'");
138         }
139     }
140
141     function _removePage($type, $pagename, $version) {
142         $filename = $this->_pagename2filename($type, $pagename, $version);
143         if (!file_exists($filename)) return NULL;
144         $f = @unlink($filename);
145         if ($f == false)
146             trigger_error("delete file failed: ".$filename." ver: ".$version, E_USER_WARNING);
147     }
148
149     // *********************************************************************
150
151     // *********************************************************************
152     // Load/Save Version-Data
153     function _loadVersionData($pagename, $version) {
154         if ($this->_page_version_data != NULL) {
155             if ( ($this->_page_version_data['pagename'] == $pagename) && 
156                 ($this->_page_version_data['version'] == $version) ) {
157                 return $this->_page_version_data;
158              }
159         }
160         $vd = $this->_loadPage('ver_data', $pagename, $version);
161         if ($vd != NULL) {
162             $this->_page_version_data = $vd;
163             if ( ($this->_page_version_data['pagename'] == $pagename) && 
164                 ($this->_page_version_data['version'] == $version) ) {
165                 return $this->_page_version_data;
166              }
167         }
168         return NULL;
169     }
170
171     function _saveVersionData($pagename, $version, $data) {
172         $this->_savePage('ver_data', $pagename, $version, $data);
173
174         // check if this is a newer version:
175         if ($this->_getLatestVersion($pagename) < $version) {
176             // write new latest-version-info
177             $this->_setLatestVersion($pagename, $version);
178         }
179     }
180
181
182     // *********************************************************************
183     // Load/Save Page-Data
184     function _loadPageData($pagename) {
185         if ($this->_page_data != NULL) {
186             if ($this->_page_data['pagename'] == $pagename) {
187                 return $this->_page_data;
188              }
189         }
190         $pd = $this->_loadPage('page_data', $pagename, 0);
191         if ($pd != NULL)
192             $this->_page_data = $pd;
193         if ($this->_page_data != NULL) {
194             if ($this->_page_data['pagename'] == $pagename) {
195                 return $this->_page_data;
196              }
197         }
198         return array();  // no values found
199     }
200
201     function _savePageData($pagename, $data) {
202         $this->_savePage('page_data', $pagename, 0, $data);
203     }
204
205     // *********************************************************************
206     // Load/Save Latest-Version
207     function _saveLatestVersions() {
208         $data = $this->_latest_versions;
209         if ($data == NULL)
210             $data = array();
211         $this->_savePage('latest_ver', 'latest_versions', 0, $data);
212     }
213
214     function _setLatestVersion($pagename, $version) {
215         // make sure the page version list is loaded:
216         $this->_getLatestVersion($pagename);
217         if ($version > 0) {
218             $this->_getLatestVersion($pagename);
219             $this->_latest_versions[$pagename] = $version;
220         }
221         else {
222             // Remove this page from the Latest-Version-List:
223             unset($this->_latest_versions[$pagename]);
224         }
225         $this->_saveLatestVersions();
226     }
227
228     function _loadLatestVersions() {
229         if ($this->_latest_versions != NULL)
230             return;
231
232         $pd = $this->_loadPage('latest_ver', 'latest_versions', 0, false);
233         if ($pd != NULL)
234             $this->_latest_versions = $pd;
235         else
236             $this->_latest_versions = array(); // empty array
237     }
238
239     function _getLatestVersion($pagename) {
240        $this->_loadLatestVersions();
241        if (array_key_exists($pagename, $this->_latest_versions) == false)
242            return 0; // do version exists
243        return $this->_latest_versions[$pagename];
244     }
245
246
247     // *********************************************************************
248     // Load/Save Page-Links
249     function _loadPageLinks($pagename) {
250         $pd = $this->_loadPage('links', $pagename, 0, false);
251         if ($pd != NULL)
252             return $pd;;
253         return array();  // no values found
254     }
255
256     function _savePageLinks($pagename, $links) {
257         $this->_savePage('links', $pagename, 0, $links);
258     }
259
260
261
262     /**
263      * Get page meta-data from database.
264      *
265      * @param $pagename string Page name.
266      * @return hash
267      * Returns a hash containing the page meta-data.
268      * Returns an empty array if there is no meta-data for the requested page.
269      * Keys which might be present in the hash are:
270      * <dl>
271      *  <dt> locked  <dd> If the page is locked.
272      *  <dt> hits    <dd> The page hit count.
273      *  <dt> created <dd> Unix time of page creation. (FIXME: Deprecated: I
274      *                    don't think we need this...) 
275      * </dl>
276      */
277     function get_pagedata($pagename) {
278         return $this->_loadPageData($pagename);
279     }
280
281     /**
282      * Update the page meta-data.
283      *
284      * Set page meta-data.
285      *
286      * Only meta-data whose keys are preset in $newdata is affected.
287      *
288      * For example:
289      * <pre>
290      *   $backend->update_pagedata($pagename, array('locked' => 1)); 
291      * </pre>
292      * will set the value of 'locked' to 1 for the specified page, but it
293      * will not affect the value of 'hits' (or whatever other meta-data
294      * may have been stored for the page.)
295      *
296      * To delete a particular piece of meta-data, set it's value to false.
297      * <pre>
298      *   $backend->update_pagedata($pagename, array('locked' => false)); 
299      * </pre>
300      *
301      * @param $pagename string Page name.
302      * @param $newdata hash New meta-data.
303      */
304     /**
305      * This will create a new page if page being requested does not
306      * exist.
307      */
308     function update_pagedata($pagename, $newdata) {
309         $data = $this->get_pagedata($pagename);
310         if (count($data) == 0) {
311             $this->_savePageData($pagename, $newdata);  // create a new pagedata-file
312             return;
313         }
314         
315         foreach ($newdata as $key => $val) {
316             if (empty($val))
317                 unset($data[$key]);
318             else
319                 $data[$key] = $val;
320         }
321         $this->_savePageData($pagename, $data);  // write new pagedata-file
322     }
323     
324
325     /**
326      * Get the current version number for a page.
327      *
328      * @param $pagename string Page name.
329      * @return int The latest version number for the page.  Returns zero if
330      *  no versions of a page exist.
331      */
332     function get_latest_version($pagename) {
333         return $this->_getLatestVersion($pagename);
334     }
335     
336     /**
337      * Get preceding version number.
338      *
339      * @param $pagename string Page name.
340      * @param $version int Find version before this one.
341      * @return int The version number of the version in the database which
342      *  immediately preceeds $version.
343      *
344      * FIXED: Check if this version really exists!
345      */
346     function get_previous_version($pagename, $version) {
347         $prev = ($version > 0 ? $version - 1 : 0);
348         while ($prev and !file_exists($this->_pagename2filename('ver_data', $pagename, $prev))) {
349             $prev--;
350         }
351         return $prev;
352     }
353     
354     /**
355      * Get revision meta-data and content.
356      *
357      * @param $pagename string Page name.
358      * @param $version integer Which version to get.
359      * @param $want_content boolean
360      *  Indicates the caller really wants the page content.  If this
361      *  flag is not set, the backend is free to skip fetching of the
362      *  page content (as that may be expensive).  If the backend omits
363      *  the content, the backend might still want to set the value of
364      *  '%content' to the empty string if it knows there's no content.
365      *
366      * @return hash The version data, or false if specified version does not
367      *    exist.
368      *
369      * Some keys which might be present in the $versiondata hash are:
370      * <dl>
371      * <dt> %content
372      *  <dd> This is a pseudo-meta-data element (since it's actually
373      *       the page data, get it?) containing the page content.
374      *       If the content was not fetched, this key may not be present.
375      * </dl>
376      * For description of other version meta-data see WikiDB_PageRevision::get().
377      * @see WikiDB_PageRevision::get
378      */
379     function get_versiondata($pagename, $version, $want_content = false) {
380         $vd = $this->_loadVersionData($pagename, $version);
381         if ($vd == NULL)
382             return false;
383         return $vd;
384     }
385
386     /**
387      * Rename all files for this page
388      *
389      * @access protected   Via WikiDB
390      */
391     function rename_page($pagename, $to) {
392         $version = _getLatestVersion($pagename);
393         foreach ($this->_dir_names as $type => $path) {
394             if (is_dir($path)) {
395                 $filename = $this->_pagename2filename($type, $pagename, $version);
396                 $new = $this->_pagename2filename($type, $to, $version);
397                 @rename($filename,$new);
398             }
399         }
400         $this->update_pagedata($pagename, array('pagename' => $to)); 
401         return true;
402     }
403
404     /**
405      * Delete page from the database.
406      *
407      * Delete page (and all it's revisions) from the database.
408      *
409      * @param $pagename string Page name.
410      */
411     function delete_page($pagename) {
412         $ver = $this->get_latest_version($pagename);
413         while($ver > 0) {
414             $this->_removePage('ver_data', $pagename, $ver);
415             $ver = $this->get_previous_version($pagename, $ver);
416         }
417         $this->_removePage('page_data', $pagename, 0);
418         $this->_removePage('links', $pagename, 0);
419         // remove page from latest_version...
420         $this->_setLatestVersion($pagename, 0);
421     }
422             
423     /**
424      * Delete an old revision of a page.
425      *
426      * Note that one is never allowed to delete the most recent version,
427      * but that this requirement is enforced by WikiDB not by the backend.
428      *
429      * In fact, to be safe, backends should probably allow the deletion of
430      * the most recent version.
431      *
432      * @param $pagename string Page name.
433      * @param $version integer Version to delete.
434      */
435     function delete_versiondata($pagename, $version) {
436         if ($this->get_latest_version($pagename) == $version) {
437             // try to delete the latest version!
438             // so check if an older version exist:
439             if ($this->get_versiondata($pagename, 
440                                        $this->get_previous_version($pagename, $version), 
441                                        false) == false) {
442               // there is no older version....
443               // so the completely page will be removed:
444               $this->delete_page($pagename);
445               return;
446             }
447         }
448         $this->_removePage('ver_data', $pagename, $version);
449     }                           
450
451     /**
452      * Create a new page revision.
453      *
454      * If the given ($pagename,$version) is already in the database,
455      * this method completely overwrites any stored data for that version.
456      *
457      * @param $pagename string Page name.
458      * @param $version int New revisions content.
459      * @param $data hash New revision metadata.
460      *
461      * @see get_versiondata
462      */
463     function set_versiondata($pagename, $version, $data) {
464         $this->_saveVersionData($pagename, $version, $data);
465     }
466
467     /**
468      * Update page version meta-data.
469      *
470      * If the given ($pagename,$version) is already in the database,
471      * this method only changes those meta-data values whose keys are
472      * explicity listed in $newdata.
473      *
474      * @param $pagename string Page name.
475      * @param $version int New revisions content.
476      * @param $newdata hash New revision metadata.
477      * @see set_versiondata, get_versiondata
478      */
479     function update_versiondata($pagename, $version, $newdata) {
480         $data = $this->get_versiondata($pagename, $version, true);
481         if (!$data) {
482             assert($data);
483             return;
484         }
485         foreach ($newdata as $key => $val) {
486             if (empty($val))
487                 unset($data[$key]);
488             else
489                 $data[$key] = $val;
490         }
491         $this->set_versiondata($pagename, $version, $data);
492     }
493     
494     /**
495      * Set links for page.
496      *
497      * @param $pagename string Page name.
498      *
499      * @param $links array List of page(names) which page links to.
500      */
501     function set_links($pagename, $links) {
502         $this->_savePageLinks($pagename, $links);
503     }
504         
505     /**
506      * Find pages which link to or are linked from a page.
507      *
508      * @param $pagename string Page name.
509      * @param $reversed boolean True to get backlinks.
510      *
511      * FIXME: array or iterator?
512      * @return object A WikiDB_backend_iterator.
513      */
514     function get_links($pagename, $reversed=true, $include_empty=false,
515                        $sortby=false, $limit=false, $exclude=false) {
516         if ($reversed == false)
517             return new WikiDB_backend_file_iter($this, $this->_loadPageLinks($pagename));
518
519         $this->_loadLatestVersions();
520         $pagenames = $this->_latest_versions;  // now we have an array with the key is the pagename of all pages
521
522         $out = array();  // create empty out array
523
524         foreach ($pagenames as $key => $val) {
525             $links = $this->_loadPageLinks($key);
526             foreach ($links as $key2 => $val2) {
527                 if ($val2 == $pagename)
528                     array_push($out, $key);
529             }
530         }
531         return new WikiDB_backend_file_iter($this, $out);
532     }
533
534     /**
535      * Get all revisions of a page.
536      *
537      * @param $pagename string The page name.
538      * @return object A WikiDB_backend_iterator.
539      */
540     /*
541     function get_all_revisions($pagename) {
542         include_once('lib/WikiDB/backend/dumb/AllRevisionsIter.php');
543         return new WikiDB_backend_dumb_AllRevisionsIter($this, $pagename);
544     }
545     */
546     
547     /**
548      * Get all pages in the database.
549      *
550      * Pages should be returned in alphabetical order if that is
551      * feasable.
552      *
553      * @access protected
554      *
555      * @param $include_defaulted boolean
556      * If set, even pages with no content will be returned
557      * --- but still only if they have at least one revision (not
558      * counting the default revision 0) entered in the database.
559      *
560      * Normally pages whose current revision has empty content
561      * are not returned as these pages are considered to be
562      * non-existing.
563      *
564      * @return object A WikiDB_backend_iterator.
565      */
566     function get_all_pages($include_empty=false, $sortby=false, $limit=false, $exclude=false) {
567         require_once("lib/PageList.php");
568         $this->_loadLatestVersions();
569         $a = array_keys($this->_latest_versions);
570         if (empty($a))
571             return new WikiDB_backend_file_iter($this, $a);
572         $sortby = $this->sortby($sortby, 'db', $this->sortable_columns());
573         switch ($sortby) {
574         case '': break;
575         case 'pagename ASC':  sort($a); break;
576         case 'pagename DESC': rsort($a); break;
577         }
578         return new WikiDB_backend_file_iter($this, $a);
579     }
580
581     function sortable_columns() {
582         return array('pagename');
583     }
584
585     function numPages($filter=false, $exclude='') {
586         $this->_loadLatestVersions();
587         return count($this->_latest_versions);
588     }
589
590     /**
591      * Lock backend database.
592      *
593      * Calls may be nested.
594      *
595      * @param $write_lock boolean Unless this is set to false, a write lock
596      *     is acquired, otherwise a read lock.  If the backend doesn't support
597      *     read locking, then it should make a write lock no matter which type
598      *     of lock was requested.
599      *
600      *     All backends <em>should</em> support write locking.
601      */
602     function lock($write_lock = true) {
603         //trigger_error("lock: Not Implemented", E_USER_WARNING);
604     }
605
606     /**
607      * Unlock backend database.
608      *
609      * @param $force boolean Normally, the database is not unlocked until
610      *  unlock() is called as many times as lock() has been.  If $force is
611      *  set to true, the the database is unconditionally unlocked.
612      */
613     function unlock($force = false) {
614         //trigger_error("unlock: Not Implemented", E_USER_WARNING);
615     }
616
617
618     /**
619      * Close database.
620      */
621     function close () {
622         //trigger_error("close: Not Implemented", E_USER_WARNING);
623     }
624
625     /**
626      * Synchronize with filesystem.
627      *
628      * This should flush all unwritten data to the filesystem.
629      */
630     function sync() {
631         //trigger_error("sync: Not Implemented", E_USER_WARNING);
632     }
633
634     /**
635      * Optimize the database.
636      */
637     function optimize() {
638         return 0;//trigger_error("optimize: Not Implemented", E_USER_WARNING);
639     }
640
641     /**
642      * Check database integrity.
643      *
644      * This should check the validity of the internal structure of the database.
645      * Errors should be reported via:
646      * <pre>
647      *   trigger_error("Message goes here.", E_USER_WARNING);
648      * </pre>
649      *
650      * @return boolean True iff database is in a consistent state.
651      */
652     function check() {
653         //trigger_error("check: Not Implemented", E_USER_WARNING);
654     }
655
656     /**
657      * Put the database into a consistent state.
658      *
659      * This should put the database into a consistent state.
660      * (I.e. rebuild indexes, etc...)
661      *
662      * @return boolean True iff successful.
663      */
664     function rebuild() {
665         //trigger_error("rebuild: Not Implemented", E_USER_WARNING);
666     }
667
668     function _parse_searchwords($search) {
669         $search = strtolower(trim($search));
670         if (!$search)
671             return array(array(),array());
672         
673         $words = preg_split('/\s+/', $search);
674         $exclude = array();
675         foreach ($words as $key => $word) {
676             if ($word[0] == '-' && $word != '-') {
677                 $word = substr($word, 1);
678                 $exclude[] = preg_quote($word);
679                 unset($words[$key]);
680             }
681         }
682         return array($words, $exclude);
683     }
684        
685 };
686
687 class WikiDB_backend_file_iter extends WikiDB_backend_iterator
688 {
689     function WikiDB_backend_file_iter(&$backend, &$query_result) {
690         $this->_backend = &$backend;
691         $this->_result = $query_result;
692
693         if (count($this->_result) > 0)
694             reset($this->_result);
695     }
696     
697     function next() {
698         if (!$this->_result)
699             return false;
700         if (count($this->_result) <= 0)
701             return false;
702
703         $e = each($this->_result);
704         if ($e == false) {
705             return false;
706         }
707         
708         $pn = $e[1];
709         $pagedata = $this->_backend->get_pagedata($pn);
710         // don't pass _cached_html via iterators
711         if (isset($pagedata['_cached_html']))
712             unset($pagedata['_cached_html']);
713         unset($pagedata['pagename']);
714         $rec = array('pagename' => $pn,
715                      'pagedata' => $pagedata);
716         //$rec['version'] = $backend->get_latest_version($pn);
717         //$rec['versiondata'] = $backend->get_versiondata($pn, $rec['version'], true);
718         return $rec;
719     }
720     function asArray() {
721         reset($this->_result);
722         return $this->_result;
723     }
724     function count() {
725         return count($this->_result);
726     }
727     function free () {
728         $this->_result = array();
729     }
730 }
731
732 // $Log: not supported by cvs2svn $
733 // Revision 1.20  2004/11/23 13:35:49  rurban
734 // add case_exact search
735 //
736 // Revision 1.19  2004/11/21 11:59:26  rurban
737 // remove final \n to be ob_cache independent
738 //
739 // Revision 1.18  2004/11/09 17:11:17  rurban
740 // * revert to the wikidb ref passing. there's no memory abuse there.
741 // * use new wikidb->_cache->_id_cache[] instead of wikidb->_iwpcache, to effectively
742 //   store page ids with getPageLinks (GleanDescription) of all existing pages, which
743 //   are also needed at the rendering for linkExistingWikiWord().
744 //   pass options to pageiterator.
745 //   use this cache also for _get_pageid()
746 //   This saves about 8 SELECT count per page (num all pagelinks).
747 // * fix passing of all page fields to the pageiterator.
748 // * fix overlarge session data which got broken with the latest ACCESS_LOG_SQL changes
749 //
750 // Revision 1.17  2004/07/09 13:05:34  rurban
751 // just aesthetics
752 //
753 // Revision 1.16  2004/07/09 12:47:45  rurban
754 // dont cache _ cached_html and pagename in flatfile page iterators
755 //
756 // Revision 1.15  2004/07/09 10:06:50  rurban
757 // Use backend specific sortby and sortable_columns method, to be able to
758 // select between native (Db backend) and custom (PageList) sorting.
759 // Fixed PageList::AddPageList (missed the first)
760 // Added the author/creator.. name to AllPagesBy...
761 //   display no pages if none matched.
762 // Improved dba and file sortby().
763 // Use &$request reference
764 //
765 // Revision 1.14  2004/07/08 17:31:43  rurban
766 // improve numPages for file (fixing AllPagesTest)
767 //
768 // Revision 1.13  2004/07/08 15:23:59  rurban
769 // less verbose for tests
770 //
771 // Revision 1.12  2004/07/08 13:50:32  rurban
772 // various unit test fixes: print error backtrace on _DEBUG_TRACE; allusers fix; new PHPWIKI_NOMAIN constant for omitting the mainloop
773 //
774 // Revision 1.11  2004/07/08 11:12:49  rurban
775 // quiet the testruns
776 //
777 // Revision 1.10  2004/06/03 22:08:17  rurban
778 // fix bug #963268 (check existing previous version)
779 //
780 // Revision 1.9  2004/04/27 16:03:05  rurban
781 // missing pageiter::count methods
782 //
783 // Revision 1.8  2004/03/01 13:48:45  rurban
784 // rename fix
785 // p[] consistency fix
786 //
787 // Revision 1.7  2004/02/12 14:11:36  rurban
788 // more rename_page backend methods: only tested for PearDB! please help
789 //
790 // Revision 1.6  2004/01/26 09:17:51  rurban
791 // * changed stored pref representation as before.
792 //   the array of objects is 1) bigger and 2)
793 //   less portable. If we would import packed pref
794 //   objects and the object definition was changed, PHP would fail.
795 //   This doesn't happen with an simple array of non-default values.
796 // * use $prefs->retrieve and $prefs->store methods, where retrieve
797 //   understands the interim format of array of objects also.
798 // * simplified $prefs->get() and fixed $prefs->set()
799 // * added $user->_userid and class '_WikiUser' portability functions
800 // * fixed $user object ->_level upgrading, mostly using sessions.
801 //   this fixes yesterdays problems with loosing authorization level.
802 // * fixed WikiUserNew::checkPass to return the _level
803 // * fixed WikiUserNew::isSignedIn
804 // * added explodePageList to class PageList, support sortby arg
805 // * fixed UserPreferences for WikiUserNew
806 // * fixed WikiPlugin for empty defaults array
807 // * UnfoldSubpages: added pagename arg, renamed pages arg,
808 //   removed sort arg, support sortby arg
809 //
810 // Revision 1.5  2004/01/25 08:17:29  rurban
811 // ORDER BY support for all other backends,
812 // all non-SQL simply ignoring it, using plain old dumb_iter instead
813 //
814 // Revision 1.4  2003/02/24 01:53:28  dairiki
815 // Bug fix.  Don't need to urldecode pagenames in WikiDB_backend_file_iter.
816 //
817 // Revision 1.3  2003/01/04 03:41:51  wainstead
818 // Added copyleft flowerboxes
819 //
820 // Revision 1.2  2003/01/04 03:30:34  wainstead
821 // added log tag, converted file to unix format
822 //
823
824 // For emacs users
825 // Local Variables:
826 // mode: php
827 // tab-width: 8
828 // c-basic-offset: 4
829 // c-hanging-comment-ender-p: nil
830 // indent-tabs-mode: nil
831 // End:
832 ?>