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