2 rcs_id('$Id: WikiDB.php,v 1.4 2002-01-10 23:28:54 carstenklapp 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(sprintf(_("Attempt to delete most recent revision of '%s'"),$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(sprintf(_("Attempt to merge most recent revision of '%s'"),$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(sprintf(_("%s: Date of new revision is %s"),$pagename,"'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(sprintf(_("Optimizing %s"),'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(_("Describe %s here."),
838 "[". $this->_pagename ."]");
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 __sprintf("Acck! Revision %s of %s seems to have been deleted!",
873 $version, $pagename);
878 * Get meta-data for this revision.
883 * @param $key string Which meta-data to access.
885 * Some reserved revision meta-data keys are:
887 * <dt> 'mtime' <dd> Time this revision was created (seconds since midnight Jan 1, 1970.)
888 * The 'mtime' meta-value is normally set automatically by the database
889 * backend, but it may be specified explicitly when creating a new revision.
891 * <dd> To ensure consistency of RecentChanges, the mtimes of the versions
892 * of a page must be monotonically increasing. If an attempt is
893 * made to create a new revision with an mtime less than that of
894 * the preceeding revision, the new revisions timestamp is force
895 * to be equal to that of the preceeding revision. In that case,
896 * the originally requested mtime is preserved in 'orig_mtime'.
897 * <dt> '_supplanted' <dd> Time this revision ceased to be the most recent.
898 * This meta-value is <em>always</em> automatically maintained by the database
899 * backend. (It is set from the 'mtime' meta-value of the superceding
900 * revision.) '_supplanted' has a value of 'false' for the current revision.
902 * FIXME: this could be refactored:
904 * <dd> Author of the page (as he should be reported in, e.g. RecentChanges.)
906 * <dd> Authenticated author of a page. This is used to identify
907 * the distinctness of authors when cleaning old revisions from
909 * <dt> 'is_minor_edit' <dd> Set if change was marked as a minor revision by the author.
910 * <dt> 'summary' <dd> Short change summary entered by page author.
913 * Meta-data keys must be valid C identifers (they have to start with a letter
914 * or underscore, and can contain only alphanumerics and underscores.)
916 * @return string The requested value, or false if the requested value
920 if (!$key || $key[0] == '%')
922 $data = &$this->_data;
923 return isset($data[$key]) ? $data[$key] : false;
927 * Get all the revision page meta-data as a hash.
929 * @return hash The revision meta-data.
931 function getMetaData() {
933 foreach ($this->_data as $key => $val) {
934 if (!empty($val) && $key[0] != '%')
942 * Return a string representation of the revision.
944 * This is really only for debugging.
948 * @return string Printable representation of the WikiDB_Page.
950 function asString () {
952 printf("[%s:%d\n", get_class($this), $this->get('version'));
953 print_r($this->_data);
954 echo $this->getPackedContent() . "\n]\n";
955 $strval = ob_get_contents();
963 * A class which represents a sequence of WikiDB_Pages.
965 class WikiDB_PageIterator
967 function WikiDB_PageIterator(&$wikidb, &$pages) {
968 $this->_pages = $pages;
969 $this->_wikidb = &$wikidb;
973 * Get next WikiDB_Page in sequence.
977 * @return object The next WikiDB_Page in the sequence.
980 if ( ! ($next = $this->_pages->next()) )
983 $pagename = &$next['pagename'];
984 if (isset($next['pagedata']))
985 $this->_wikidb->_cache->cache_data($next);
987 return new WikiDB_Page($this->_wikidb, $pagename);
991 * Release resources held by this iterator.
993 * The iterator may not be used after free() is called.
995 * There is no need to call free(), if next() has returned false.
996 * (I.e. if you iterate through all the pages in the sequence,
997 * you do not need to call free() --- you only need to call it
998 * if you stop before the end of the iterator is reached.)
1003 $this->_pages->free();
1008 * A class which represents a sequence of WikiDB_PageRevisions.
1010 class WikiDB_PageRevisionIterator
1012 function WikiDB_PageRevisionIterator(&$wikidb, &$revisions) {
1013 $this->_revisions = $revisions;
1014 $this->_wikidb = &$wikidb;
1018 * Get next WikiDB_PageRevision in sequence.
1022 * @return object The next WikiDB_PageRevision in the sequence.
1025 if ( ! ($next = $this->_revisions->next()) )
1028 $this->_wikidb->_cache->cache_data($next);
1030 $pagename = $next['pagename'];
1031 $version = $next['version'];
1032 $versiondata = $next['versiondata'];
1033 assert(!empty($pagename));
1034 assert(is_array($versiondata));
1035 assert($version > 0);
1037 return new WikiDB_PageRevision($this->_wikidb, $pagename, $version, $versiondata);
1041 * Release resources held by this iterator.
1043 * The iterator may not be used after free() is called.
1045 * There is no need to call free(), if next() has returned false.
1046 * (I.e. if you iterate through all the revisions in the sequence,
1047 * you do not need to call free() --- you only need to call it
1048 * if you stop before the end of the iterator is reached.)
1053 $this->_revisions->free();
1059 * Data cache used by WikiDB.
1061 * FIXME: Maybe rename this to caching_backend (or some such).
1067 // FIXME: cache (limited) version data, too.
1069 function WikiDB_cache (&$backend) {
1070 $this->_backend = &$backend;
1072 $this->_pagedata_cache = array();
1076 $this->_pagedata_cache = false;
1079 function get_pagedata($pagename) {
1080 assert(is_string($pagename) && $pagename);
1081 $cache = &$this->_pagedata_cache;
1083 if (!isset($cache[$pagename]) || !is_array($cache[$pagename])) {
1084 $cache[$pagename] = $this->_backend->get_pagedata($pagename);
1085 if (empty($cache[$pagename]))
1086 $cache[$pagename] = array();
1089 return $cache[$pagename];
1092 function update_pagedata($pagename, $newdata) {
1093 assert(is_string($pagename) && $pagename);
1095 $this->_backend->update_pagedata($pagename, $newdata);
1097 if (is_array($this->_pagedata_cache[$pagename])) {
1098 $cachedata = &$this->_pagedata_cache[$pagename];
1099 foreach($newdata as $key => $val)
1100 $cachedata[$key] = $val;
1104 function invalidate_cache($pagename) {
1105 $this->_pagedata_cache[$pagename] = false;
1108 function delete_page($pagename) {
1109 $this->_backend->delete_page($pagename);
1110 $this->_pagedata_cache[$pagename] = false;
1114 function cache_data($data) {
1115 if (isset($data['pagedata']))
1116 $this->_pagedata_cache[$data['pagename']] = $data['pagedata'];
1119 function get_versiondata($pagename, $version, $need_content = false) {
1120 $vdata = $this->_backend->get_versiondata($pagename, $version, $need_content);
1122 if ($vdata && !empty($vdata['%pagedata']))
1123 $this->_pagedata_cache[$pagename] = $vdata['%pagedata'];
1127 function set_versiondata($pagename, $version, $data) {
1128 $new = $this->_backend->
1129 set_versiondata($pagename, $version, $data);
1132 function update_versiondata($pagename, $version, $data) {
1133 $new = $this->_backend->
1134 update_versiondata($pagename, $version, $data);
1137 function delete_versiondata($pagename, $version) {
1138 $new = $this->_backend->
1139 delete_versiondata($pagename, $version);
1146 // c-basic-offset: 4
1147 // c-hanging-comment-ender-p: nil
1148 // indent-tabs-mode: nil