2 rcs_id('$Id: WikiDB.php,v 1.2 2001-10-29 17:58:37 dairiki Exp $');
4 //FIXME: arg on get*Revision to hint that content is wanted.
6 define('WIKIDB_FORCE_CREATE', -1);
9 * Abstract base class for the database used by PhpWiki.
11 * A <tt>WikiDB</tt> is a container for <tt>WikiDB_Page</tt>s
12 * which in turn contain <tt>WikiDB_PageRevision</tt>s.
14 * Conceptually a <tt>WikiDB</tt> contains all possible <tt>WikiDB_Page</tt>s,
15 * whether they have been initialized or not. Since all possible pages are already
16 * contained in a WikiDB, a call to WikiDB::getPage() will never fail
17 * (barring bugs and e.g. filesystem or SQL database problems.)
19 * Also each <tt>WikiDB_Page</tt> always contains at least one <tt>WikiDB_PageRevision</tt>:
20 * the default content (e.g. "Describe [PageName] here."). This default content
21 * has a version number of zero.
23 * <tt>WikiDB_PageRevision</tt>s have read-only semantics. One can only create new
24 * revisions or delete old ones --- one can not modify an existing revision.
28 * Open a WikiDB database.
30 * This is a static member function. This function inspects its
31 * arguments to determine the proper subclass of WikiDB to instantiate,
32 * and then it instantiates it.
36 * @param $dbparams hash Database configuration parameters.
37 * Some pertinent paramters are:
40 * <dd> The back-end type. Current supported types are:
43 * <dd> Generic SQL backend based on the PEAR/DB database abstraction
46 * <dd> Dba based backend.
50 * <dd> (Used by the SQL backend.)
51 * The DSN specifying which database to connect to.
54 * <dd> Prefix to be prepended to database table (and file names).
57 * <dd> (Used by the dba backend.)
58 * Which directory db files reside in.
61 * <dd> (Used by the dba backend.)
62 * Timeout in seconds for opening (and obtaining lock) on the db files.
65 * <dd> (Used by the dba backend.)
66 * Which dba handler to use. Good choices are probably either 'gdbm'
70 * @return object A WikiDB object.
72 function open ($dbparams) {
73 $dbtype = $dbparams{'dbtype'};
74 include_once("lib/WikiDB/$dbtype.php");
75 $class = 'WikiDB_' . $dbtype;
76 return new $class ($dbparams);
84 function WikiDB ($backend, $dbparams) {
85 $this->_backend = &$backend;
86 $this->_cache = new WikiDB_cache($backend);
88 //FIXME: devel checking.
89 //$this->_backend->check();
93 * Get any user-level warnings about this WikiDB.
95 * Some back-ends, e.g. by default create there data files
96 * in the global /tmp directory. We would like to warn the user
97 * when this happens (since /tmp files tend to get wiped
98 * periodically.) Warnings such as these may be communicated
99 * from specific back-ends through this method.
103 * @return string A warning message (or <tt>false</tt> if there is none.)
105 function genericWarnings() {
110 * Close database connection.
112 * The database may no longer be used after it is closed.
114 * Closing a WikiDB invalidates all <tt>WikiDB_Page</tt>s,
115 * <tt>WikiDB_PageRevision</tt>s and <tt>WikiDB_PageIterator</tt>s which
116 * have been obtained from it.
121 $this->_backend->close();
122 $this->_cache->close();
126 * Get a WikiDB_Page from a WikiDB.
128 * A WikiDB consists of the (infinite) set of all possible pages,
129 * therefore this method never fails.
132 * @param $pagename string Which page to get.
133 * @return object The requested WikiDB_Page.
135 function getPage($pagename) {
136 assert(is_string($pagename) && $pagename);
137 return new WikiDB_Page($this, $pagename);
142 //function nPages() {
147 * Determine whether page exists (in non-default form).
150 * $is_page = $dbi->isWikiPage($pagename);
154 * $page = $dbi->getPage($pagename);
155 * $current = $page->getCurrentRevision();
156 * $is_page = ! $current->hasDefaultContents();
158 * however isWikiPage may be implemented in a more efficient
159 * manner in certain back-ends.
163 * @param $pagename string Which page to check.
165 * @return boolean True if the page actually exists with non-default contents
166 * in the WikiDataBase.
168 function isWikiPage ($pagename) {
169 $page = $this->getPage($pagename);
170 $current = $page->getCurrentRevision();
171 return ! $current->hasDefaultContents();
175 * Delete page from the WikiDB.
177 * Deletes all revisions of the page from the WikiDB.
178 * Also resets all page meta-data to the default values.
182 * @param $pagename string Name of page to delete.
184 function deletePage($pagename) {
185 $this->_cache->delete_page($pagename);
186 $this->_backend->set_links($pagename, false);
190 * Retrieve all pages.
192 * Gets the set of all pages with non-default contents.
194 * FIXME: do we need this? I think so. The simple searches
199 * @param $include_defaulted boolean Normally pages whose most recent
200 * revision has empty content are considered to be non-existant.
201 * Unless $include_defaulted is set to true, those pages will
204 * @return object A WikiDB_PageIterator which contains all pages
205 * in the WikiDB which have non-default contents.
207 function getAllPages($include_defaulted = false) {
208 $result = $this->_backend->get_all_pages($include_defaulted);
209 return new WikiDB_PageIterator($this, $result);
215 * Search for pages containing (or not containing) certain words in their
218 * Pages are returned in alphabetical order whenever it is practical
221 * FIXME: should titleSearch and fullSearch be combined? I think so.
224 * @param $search object A TextSearchQuery
225 * @return object A WikiDB_PageIterator containing the matching pages.
226 * @see TextSearchQuery
228 function titleSearch($search) {
229 $result = $this->_backend->text_search($search);
230 return new WikiDB_PageIterator($this, $result);
236 * Search for pages containing (or not containing) certain words in their
237 * entire text (this includes the page content and the page name).
239 * Pages are returned in alphabetical order whenever it is practical
244 * @param $search object A TextSearchQuery object.
245 * @return object A WikiDB_PageIterator containing the matching pages.
246 * @see TextSearchQuery
248 function fullSearch($search) {
249 $result = $this->_backend->text_search($search, 'full_text');
250 return new WikiDB_PageIterator($this, $result);
254 * Find the pages with the greatest hit counts.
256 * Pages are returned in reverse order by hit count.
260 * @param $limit unsigned The maximum number of pages to return.
261 * Set $limit to zero to return all pages.
263 * @return object A WikiDB_PageIterator containing the matching pages.
265 function mostPopular($limit = 20) {
266 $result = $this->_backend->most_popular($limit);
267 return new WikiDB_PageIterator($this, $result);
271 * Find recent page revisions.
273 * Revisions are returned in reverse order by creation time.
277 * @param $params hash This hash is used to specify various optional
281 * <dd> (integer) At most this many revisions will be returned.
283 * <dd> (integer) Only revisions since this time (unix-timestamp) will be returned.
284 * <dt> include_minor_revisions
285 * <dd> (boolean) Also include minor revisions. (Default is not to.)
286 * <dt> exclude_major_revisions
287 * <dd> (boolean) Don't include non-minor revisions.
288 * (Exclude_major_revisions implies include_minor_revisions.)
289 * <dt> include_all_revisions
290 * <dd> (boolean) Return all matching revisions for each page.
291 * Normally only the most recent matching revision is returned
295 * @return object A WikiDB_PageRevisionIterator containing the matching revisions.
297 function mostRecent($params = false) {
298 $result = $this->_backend->most_recent($params);
299 return new WikiDB_PageRevisionIterator($this, $result);
305 * An abstract base class which representing a wiki-page within a WikiDB.
307 * A WikiDB_Page contains a number (at least one) of WikiDB_PageRevisions.
311 function WikiDB_Page(&$wikidb, $pagename) {
312 $this->_wikidb = &$wikidb;
313 $this->_pagename = $pagename;
314 assert(!empty($this->_pagename));
318 * Get the name of the wiki page.
322 * @return string The page name.
325 return $this->_pagename;
330 * Delete an old revision of a WikiDB_Page.
332 * Deletes the specified revision of the page.
333 * It is a fatal error to attempt to delete the current revision.
337 * @param $version integer Which revision to delete. (You can also
338 * use a WikiDB_PageRevision object here.)
340 function deleteRevision($version) {
341 $backend = &$this->_wikidb->_backend;
342 $cache = &$this->_wikidb->_cache;
343 $pagename = &$this->_pagename;
345 $version = $this->_coerce_to_version($version);
350 $latestversion = $backend->get_latest_version($pagename);
351 if ($latestversion && $version == $latestversion) {
353 trigger_error("Attempt to delete most recent revision of '$pagename'",
358 $cache->delete_versiondata($pagename, $version);
363 * Delete a revision, or possibly merge it with a previous
367 * Suppose an author make a (major) edit to a page. Shortly
368 * after that the same author makes a minor edit (e.g. to fix
369 * spelling mistakes he just made.)
371 * Now some time later, where cleaning out old saved revisions,
372 * and would like to delete his minor revision (since there's really
373 * no point in keeping minor revisions around for a long time.)
375 * Note that the text after the minor revision probably represents
376 * what the author intended to write better than the text after the
377 * preceding major edit.
379 * So what we really want to do is merge the minor edit with the
382 * We will only do this when:
384 * <li>The revision being deleted is a minor one, and
385 * <li>It has the same author as the immediately preceding revision.
388 function mergeRevision($version) {
389 $backend = &$this->_wikidb->_backend;
390 $cache = &$this->_wikidb->_cache;
391 $pagename = &$this->_pagename;
393 $version = $this->_coerce_to_version($version);
398 $latestversion = $backend->get_latest_version($pagename);
399 if ($latestversion && $version == $latestversion) {
401 trigger_error("Attempt to merge most recent revision of '$pagename'",
406 $versiondata = $cache->get_versiondata($pagename, $version, true);
408 // Not there? ... we're done!
413 if ($versiondata['is_minor_edit']) {
414 $previous = $backend->get_previous_version($pagename, $version);
416 $prevdata = $cache->get_versiondata($pagename, $previous);
417 if ($prevdata['author_id'] == $versiondata['author_id']) {
418 // This is a minor revision, previous version is by the
419 // same author. We will merge the revisions.
420 $cache->update_versiondata($pagename, $previous,
421 array('%content' => $versiondata['%content'],
422 '_supplanted' => $versiondata['_supplanted']));
427 $cache->delete_versiondata($pagename, $version);
433 * Create a new revision of a WikiDB_Page.
437 * @param $content string Contents of new revision.
439 * @param $metadata hash Metadata for new revision.
440 * All values in the hash should be scalars (strings or integers).
443 * @param $version int Version number for new revision.
444 * To ensure proper serialization of edits, $version must be
445 * exactly one higher than the current latest version.
446 * (You can defeat this check by setting $version to
447 * WIKIDB_FORCE_CREATE --- not usually recommended.)
449 * @param $links array List of pagenames which this page links to.
451 * @return object Returns the new WikiDB_PageRevision object. If $version was incorrect,
454 function createRevision($version, &$content, $metadata, $links) {
455 $backend = &$this->_wikidb->_backend;
456 $cache = &$this->_wikidb->_cache;
457 $pagename = &$this->_pagename;
461 $latestversion = $backend->get_latest_version($pagename);
462 $newversion = $latestversion + 1;
463 assert($newversion >= 1);
465 if ($version != WIKIDB_FORCE_CREATE && $version != $newversion) {
472 foreach ($data as $key => $val) {
473 if (empty($val) || $key[0] == '_' || $key[0] == '%')
477 assert(!empty($data['author_id']));
478 if (empty($data['author_id']))
479 @$data['author_id'] = $data['author'];
481 if (empty($data['mtime']))
482 $data['mtime'] = time();
484 if ($latestversion) {
485 // Ensure mtimes are monotonic.
486 $pdata = $cache->get_versiondata($pagename, $latestversion);
487 if ($data['mtime'] < $pdata['mtime']) {
488 trigger_error("$pagename: Date of new revision non-monotonic",
490 $data['orig_mtime'] = $data['mtime'];
491 $data['mtime'] = $pdata['mtime'];
494 // FIXME: use (possibly user specified) 'mtime' time or time()?
495 $cache->update_versiondata($pagename, $latestversion,
496 array('_supplanted' => $data['mtime']));
499 $data['%content'] = &$content;
501 $cache->set_versiondata($pagename, $newversion, $data);
503 //$cache->update_pagedata($pagename, array(':latestversion' => $newversion,
504 //':deleted' => empty($content)));
506 $backend->set_links($pagename, $links);
510 // FIXME: probably should have some global state information in the backend
511 // to control when to optimize.
512 if (time() % 50 == 0) {
513 trigger_error('"Optimizing" backend', E_USER_NOTICE);
514 $backend->optimize();
517 return new WikiDB_PageRevision($this->_wikidb, $pagename, $newversion, $data);
521 * Get the most recent revision of a page.
525 * @return object The current WikiDB_PageRevision object.
527 function getCurrentRevision() {
528 $backend = &$this->_wikidb->_backend;
529 $cache = &$this->_wikidb->_cache;
530 $pagename = &$this->_pagename;
533 $version = $backend->get_latest_version($pagename);
534 $revision = $this->getRevision($version);
541 * Get a specific revision of a WikiDB_Page.
545 * @param $version integer Which revision to get.
547 * @return object The requested WikiDB_PageRevision object, or false if the
548 * requested revision does not exist in the WikiDB. Note that
549 * version zero of any page always exists.
551 function getRevision($version) {
552 $cache = &$this->_wikidb->_cache;
553 $pagename = &$this->_pagename;
556 return new WikiDB_PageRevision($this->_wikidb, $pagename, 0);
558 assert($version > 0);
559 $vdata = $cache->get_versiondata($pagename, $version);
562 return new WikiDB_PageRevision($this->_wikidb, $pagename, $version, $vdata);
566 * Get previous page revision.
568 * This method find the most recent revision before a specified version.
572 * @param $version integer Find most recent revision before this version.
573 * You can also use a WikiDB_PageRevision object to specify the $version.
575 * @return object The requested WikiDB_PageRevision object, or false if the
576 * requested revision does not exist in the WikiDB. Note that
577 * unless $version is greater than zero, a revision (perhaps version zero,
578 * the default revision) will always be found.
580 function getRevisionBefore($version) {
581 $backend = &$this->_wikidb->_backend;
582 $pagename = &$this->_pagename;
584 $version = $this->_coerce_to_version($version);
589 $previous = $backend->get_previous_version($pagename, $version);
590 $revision = $this->getRevision($previous);
597 * Get all revisions of the WikiDB_Page.
599 * This does not include the version zero (default) revision in the
600 * returned revision set.
602 * @return object a WikiDB_PageRevisionIterator containing all revisions of
603 * this WikiDB_Page in reverse order by version number.
605 function getAllRevisions() {
606 $backend = &$this->_wikidb->_backend;
607 $revs = $backend->get_all_revisions($this->_pagename);
608 return new WikiDB_PageRevisionIterator($this->_wikidb, $revs);
612 * Find pages which link to or are linked from a page.
616 * @param $reversed enum Which links to find: true for backlinks (default).
618 * @return object A WikiDB_PageIterator containing all matching pages.
620 function getLinks($reversed = true) {
621 $backend = &$this->_wikidb->_backend;
622 $result = $backend->get_links($this->_pagename, $reversed);
623 return new WikiDB_PageIterator($this->_wikidb, $result);
627 * Access WikiDB_Page meta-data.
631 * @param $key string Which meta data to get.
632 * Some reserved meta-data keys are:
634 * <dt>'locked'<dd> Is page locked?
635 * <dt>'hits' <dd> Page hit counter.
636 * <dt>'score <dd> Page score (not yet implement, do we need?)
639 * @return scalar The requested value, or false if the requested data
643 $cache = &$this->_wikidb->_cache;
644 if (!$key || $key[0] == '%')
646 $data = $cache->get_pagedata($this->_pagename);
647 return isset($data[$key]) ? $data[$key] : false;
651 * Get all the page meta-data as a hash.
653 * @return hash The page meta-data.
655 function getMetaData() {
656 $cache = &$this->_wikidb->_cache;
657 $data = $cache->get_pagedata($this->_pagename);
659 foreach ($data as $key => $val) {
660 if (!empty($val) && $key[0] != '%')
667 * Set page meta-data.
672 * @param $key string Meta-data key to set.
673 * @param $newval string New value.
675 function set($key, $newval) {
676 $cache = &$this->_wikidb->_cache;
677 $pagename = &$this->_pagename;
679 assert($key && $key[0] != '%');
681 $data = $cache->get_pagedata($pagename);
683 if (!empty($newval)) {
684 if (!empty($data[$key]) && $data[$key] == $newval)
685 return; // values identical, skip update.
688 if (empty($data[$key]))
689 return; // values identical, skip update.
692 $cache->update_pagedata($pagename, array($key => $newval));
696 * Increase page hit count.
698 * FIXME: IS this needed? Probably not.
700 * This is a convenience function.
701 * <pre> $page->increaseHitCount(); </pre>
702 * is functionally identical to
703 * <pre> $page->set('hits',$page->get('hits')+1); </pre>
705 * Note that this method may be implemented in more efficient ways
706 * in certain backends.
710 function increaseHitCount() {
711 @$newhits = $this->get('hits') + 1;
712 $this->set('hits', $newhits);
716 * Return a string representation of the WikiDB_Page
718 * This is really only for debugging.
722 * @return string Printable representation of the WikiDB_Page.
724 function asString () {
726 printf("[%s:%s\n", get_class($this), $this->getName());
727 print_r($this->getMetaData());
729 $strval = ob_get_contents();
737 * @param $version_or_pagerevision int or object
738 * Takes either the version number (and int) or a WikiDB_PageRevision
740 * @return int The version number.
742 function _coerce_to_version($version_or_pagerevision) {
743 if (method_exists($version_or_pagerevision, "getContent"))
744 $version = $version_or_pagerevision->getVersion();
746 $version = (int) $version_or_pagerevision;
748 assert($version >= 0);
754 * This class represents a specific revision of a WikiDB_Page within
757 * A WikiDB_PageRevision has read-only semantics. You may only
758 * create new revisions (and delete old ones) --- you cannot
759 * modify existing revisions.
761 class WikiDB_PageRevision
763 function WikiDB_PageRevision(&$wikidb, $pagename, $version, $versiondata = false) {
764 $this->_wikidb = &$wikidb;
765 $this->_pagename = $pagename;
766 $this->_version = $version;
767 $this->_data = $versiondata ? $versiondata : array();
771 * Get the WikiDB_Page which this revision belongs to.
775 * @return object The WikiDB_Page which this revision belongs to.
778 return new WikiDB_Page($this->_wikidb, $this->_pagename);
782 * Get the version number of this revision.
786 * @return int The version number of this revision.
788 function getVersion() {
789 return $this->_version;
793 * Determine whether this revision has defaulted content.
795 * The default revision (version 0) of each page, as well as
796 * any pages which are created with empty content
797 * have their content defaulted to something like:
799 * Describe [ThisPage] here.
804 * @return boolean Returns true if the page has default content.
806 function hasDefaultContents() {
807 $data = &$this->_data;
808 return empty($data['%content']);
812 * Get the content as an array of lines.
816 * @return array An array of lines.
817 * The lines should contain no trailing white space.
819 function getContent() {
820 return explode("\n", $this->getPackedContent());
824 * Get the content as a string.
828 * @return string The page content.
829 * Lines are separated by new-lines.
831 function getPackedContent() {
832 $data = &$this->_data;
835 if (empty($data['%content'])) {
836 // Replace empty content with default value.
837 return sprintf(gettext("Describe [%s] here."),
841 // There is (non-default) content.
842 assert($this->_version > 0);
844 if (!is_string($data['%content'])) {
845 // Content was not provided to us at init time.
846 // (This is allowed because for some backends, fetching
847 // the content may be expensive, and often is not wanted
850 // In any case, now we need to get it.
851 $data['%content'] = $this->_get_content();
852 assert(is_string($data['%content']));
855 return $data['%content'];
858 function _get_content() {
859 $cache = &$this->_wikidb->_cache;
860 $pagename = $this->_pagename;
861 $version = $this->_version;
863 assert($version > 0);
865 $newdata = $cache->get_versiondata($pagename, $version, true);
867 assert(is_string($newdata['%content']));
868 return $newdata['%content'];
871 // else revision has been deleted... What to do?
872 return "Acck! Revision $version of $pagename seems to have been deleted!";
877 * Get meta-data for this revision.
882 * @param $key string Which meta-data to access.
884 * Some reserved revision meta-data keys are:
886 * <dt> 'mtime' <dd> Time this revision was created (seconds since midnight Jan 1, 1970.)
887 * The 'mtime' meta-value is normally set automatically by the database
888 * backend, but it may be specified explicitly when creating a new revision.
890 * <dd> To ensure consistency of RecentChanges, the mtimes of the versions
891 * of a page must be monotonically increasing. If an attempt is
892 * made to create a new revision with an mtime less than that of
893 * the preceeding revision, the new revisions timestamp is force
894 * to be equal to that of the preceeding revision. In that case,
895 * the originally requested mtime is preserved in 'orig_mtime'.
896 * <dt> '_supplanted' <dd> Time this revision ceased to be the most recent.
897 * This meta-value is <i>always</i> automatically maintained by the database
898 * backend. (It is set from the 'mtime' meta-value of the superceding
899 * revision.) '_supplanted' has a value of 'false' for the current revision.
901 * FIXME: this could be refactored:
903 * <dd> Author of the page (as he should be reported in, e.g. RecentChanges.)
905 * <dd> Authenticated author of a page. This is used to identify
906 * the distinctness of authors when cleaning old revisions from
908 * <dt> 'is_minor_edit' <dd> Set if change was marked as a minor revision by the author.
909 * <dt> 'summary' <dd> Short change summary entered by page author.
912 * Meta-data keys must be valid C identifers (they have to start with a letter
913 * or underscore, and can contain only alphanumerics and underscores.)
915 * @return string The requested value, or false if the requested value
919 if (!$key || $key[0] == '%')
921 $data = &$this->_data;
922 return isset($data[$key]) ? $data[$key] : false;
926 * Get all the revision page meta-data as a hash.
928 * @return hash The revision meta-data.
930 function getMetaData() {
932 foreach ($this->_data as $key => $val) {
933 if (!empty($val) && $key[0] != '%')
941 * Return a string representation of the revision.
943 * This is really only for debugging.
947 * @return string Printable representation of the WikiDB_Page.
949 function asString () {
951 printf("[%s:%d\n", get_class($this), $this->get('version'));
952 print_r($this->_data);
953 echo $this->getPackedContent() . "\n]\n";
954 $strval = ob_get_contents();
962 * A class which represents a sequence of WikiDB_Pages.
964 class WikiDB_PageIterator
966 function WikiDB_PageIterator(&$wikidb, &$pages) {
967 $this->_pages = $pages;
968 $this->_wikidb = &$wikidb;
972 * Get next WikiDB_Page in sequence.
976 * @return object The next WikiDB_Page in the sequence.
979 if ( ! ($next = $this->_pages->next()) )
982 $pagename = &$next['pagename'];
983 if (isset($next['pagedata']))
984 $this->_wikidb->_cache->cache_data($next);
986 return new WikiDB_Page($this->_wikidb, $pagename);
990 * Release resources held by this iterator.
992 * The iterator may not be used after free() is called.
994 * There is no need to call free(), if next() has returned false.
995 * (I.e. if you iterate through all the pages in the sequence,
996 * you do not need to call free() --- you only need to call it
997 * if you stop before the end of the iterator is reached.)
1002 $this->_pages->free();
1007 * A class which represents a sequence of WikiDB_PageRevisions.
1009 class WikiDB_PageRevisionIterator
1011 function WikiDB_PageRevisionIterator(&$wikidb, &$revisions) {
1012 $this->_revisions = $revisions;
1013 $this->_wikidb = &$wikidb;
1017 * Get next WikiDB_PageRevision in sequence.
1021 * @return object The next WikiDB_PageRevision in the sequence.
1024 if ( ! ($next = $this->_revisions->next()) )
1027 $this->_wikidb->_cache->cache_data($next);
1029 $pagename = $next['pagename'];
1030 $version = $next['version'];
1031 $versiondata = $next['versiondata'];
1032 assert(!empty($pagename));
1033 assert(is_array($versiondata));
1034 assert($version > 0);
1036 return new WikiDB_PageRevision($this->_wikidb, $pagename, $version, $versiondata);
1040 * Release resources held by this iterator.
1042 * The iterator may not be used after free() is called.
1044 * There is no need to call free(), if next() has returned false.
1045 * (I.e. if you iterate through all the revisions in the sequence,
1046 * you do not need to call free() --- you only need to call it
1047 * if you stop before the end of the iterator is reached.)
1052 $this->_revisions->free();
1058 * Data cache used by WikiDB.
1060 * FIXME: Maybe rename this to caching_backend (or some such).
1066 // FIXME: cache (limited) version data, too.
1068 function WikiDB_cache (&$backend) {
1069 $this->_backend = &$backend;
1071 $this->_pagedata_cache = array();
1075 $this->_pagedata_cache = false;
1078 function get_pagedata($pagename) {
1079 assert(is_string($pagename) && $pagename);
1080 $cache = &$this->_pagedata_cache;
1082 if (!isset($cache[$pagename]) || !is_array($cache[$pagename])) {
1083 $cache[$pagename] = $this->_backend->get_pagedata($pagename);
1084 if (empty($cache[$pagename]))
1085 $cache[$pagename] = array();
1088 return $cache[$pagename];
1091 function update_pagedata($pagename, $newdata) {
1092 assert(is_string($pagename) && $pagename);
1094 $this->_backend->update_pagedata($pagename, $newdata);
1096 if (is_array($this->_pagedata_cache[$pagename])) {
1097 $cachedata = &$this->_pagedata_cache[$pagename];
1098 foreach($newdata as $key => $val)
1099 $cachedata[$key] = $val;
1103 function invalidate_cache($pagename) {
1104 $this->_pagedata_cache[$pagename] = false;
1107 function delete_page($pagename) {
1108 $this->_backend->delete_page($pagename);
1109 $this->_pagedata_cache[$pagename] = false;
1113 function cache_data($data) {
1114 if (isset($data['pagedata']))
1115 $this->_pagedata_cache[$data['pagename']] = $data['pagedata'];
1118 function get_versiondata($pagename, $version, $need_content = false) {
1119 $vdata = $this->_backend->get_versiondata($pagename, $version, $need_content);
1121 if ($vdata && !empty($vdata['%pagedata']))
1122 $this->_pagedata_cache[$pagename] = $vdata['%pagedata'];
1126 function set_versiondata($pagename, $version, $data) {
1127 $new = $this->_backend->
1128 set_versiondata($pagename, $version, $data);
1131 function update_versiondata($pagename, $version, $data) {
1132 $new = $this->_backend->
1133 update_versiondata($pagename, $version, $data);
1136 function delete_versiondata($pagename, $version) {
1137 $new = $this->_backend->
1138 delete_versiondata($pagename, $version);
1145 // c-basic-offset: 4
1146 // c-hanging-comment-ender-p: nil
1147 // indent-tabs-mode: nil