5 * Copyright 1999,2005,2006 $ThePhpWikiProgrammingTeam
7 * This file is part of PhpWiki.
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.
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.
19 * You should have received a copy of the GNU General Public License along
20 * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * Backend for handling file storage as pure, readable flatfiles,
26 * as with PageDump. All other methods are taken from file, which
27 * handles serialized pages.
28 * latest version_data is it page_data/
29 * previous ver_data is at ver_data/
30 * latest_ver should not be needed (todo)
32 * Author: Reini Urban, based on the file backend by Jochen Kalmbach
35 require_once 'lib/WikiDB/backend/file.php';
36 require_once 'lib/loadsave.php';
38 class WikiDB_backend_flatfile
39 extends WikiDB_backend_file
41 // *********************************************************************
42 // common file load / save functions:
43 // FilenameForPage is from loadsave.php
44 function _pagename2filename($type, $pagename, $version) {
45 $fpagename = FilenameForPage($pagename);
46 if (strstr($fpagename, "/")) {
47 $fpagename = preg_replace("/\//", "%2F", $fpagename);
49 return $this->_dir_names[$type].'/'.$fpagename;
51 return $this->_dir_names[$type].'/'.FilenameForPage($pagename);
53 return $this->_dir_names[$type].'/'.FilenameForPage($pagename).'--'.$version;
57 // Load/Save Page-Data
58 function _loadPageData($pagename) {
59 if ($this->_page_data != NULL) {
60 if ($this->_page_data['pagename'] == $pagename) {
61 return $this->_page_data;
64 //$pd = $this->_loadPage('page_data', $pagename, 0);
66 $filename = $this->_pagename2filename('page_data', $pagename, 0);
67 if (!file_exists($filename)) return NULL;
68 if (!filesize($filename)) return array();
69 if ($fd = @fopen($filename, "rb")) {
70 $locked = flock($fd, 1); // Read lock
72 ExitWiki("Timeout while obtaining lock. Please try again");
74 if ($data = fread($fd, filesize($filename))) {
75 // This is the only difference from file:
76 if ($parts = ParseMimeifiedPages($data)) {
79 //if ($set_pagename == true)
80 $pd['pagename'] = $pagename;
81 //if ($version != 0) $pd['version'] = $version;
83 ExitWiki(sprintf(gettext("'%s': corrupt file"),
84 htmlspecialchars($filename)));
90 $this->_page_data = $pd;
91 if ($this->_page_data != NULL) {
92 if ($this->_page_data['pagename'] == $pagename) {
93 return $this->_page_data;
96 return array(); // no values found
99 /** Store latest version as full page_data flatfile,
100 * earlier versions as file backend ver_data.
101 * _cached_html will not be stored.
102 * If the given ($pagename,$version) is already in the database,
103 * this method completely overwrites any stored data for that version.
105 function _saveVersionData($pagename, $version, $data) {
106 // check if this is a newer version:
107 if ($this->_getLatestVersion($pagename) < $version) {
108 // write new latest-version-info
109 $this->_setLatestVersion($pagename, $version);
110 // save it as latest page, not serialized version hash
111 // TODO: load latest version data and merge it with new pagedata
112 $this->_savePageData($pagename, array('versiondata' => $data));
113 } else { // save/update old version data hash
114 $this->_savePage('ver_data', $pagename, $version, $data);
118 // This is different to file and not yet finished.
119 // TODO: fields not being saved as page_data should be saved to ver_data
120 // Store as full page_data flatfile
121 // pagedata: date, pagename, hits
122 // versiondata: _cached_html and the rest
123 function _savePageData($pagename, $data) {
127 $filename = $this->_pagename2filename($type, $pagename, $version);
129 // Construct a dummy page_revision object
130 $page = new WikiDB_Page($this->_wikidb, $pagename);
131 // data may be pagedate or versiondata updates
132 if (USECACHE and empty($data['pagedata'])) {
133 $cache =& $this->_wikidb->_cache;
134 if (!empty($cache->_pagedata_cache[$pagename])
135 and is_array($cache->_pagedata_cache[$pagename]))
137 $cachedata = &$cache->_pagedata_cache[$pagename];
138 foreach($data as $key => $val)
139 $cachedata[$key] = $val;
141 $cache->_pagedata_cache[$pagename] = $data;
144 //unset ($data['pagedata']);
145 //if (empty($data['versiondata']))
146 // $data['versiondata'] = $data;
148 // with versiondata merge it with previous pagedata, not to overwrite with empty pagedata
149 // with pagedata merge it with previous versiondata, not to overwrite with empty versiondata (content)
150 $olddata = $this->_loadPageData($pagename);
151 if (isset($data['version'])) {
152 $version = $data['version'];
153 $latestversion = $this->_getLatestVersion($pagename);
154 if ($latestversion < $version) {
155 $oldversiondata = $this->_loadVersionData($pagename, $latestversion);
157 $olddata['versiondata'] = array_merge($oldversiondata, $olddata['versiondata']);
160 $data['pagedata'] = array_merge($olddata['pagedata'], $data['pagedata']);
161 $data['versiondata'] = array_merge($olddata['versiondata'], $data['versiondata']);
162 if (empty($data['versiondata']['%content']))
163 $data['versiondata']['%content'] = $olddata['content'];
164 $current = new WikiDB_PageRevision($this->_wikidb, $pagename, $version, $data['versiondata']);
165 unset ($data['versiondata']);
166 foreach ($data as $k => $v) {
167 if ($k == 'pagedata')
168 $current->_data = array_merge($current->_data, $v);
169 elseif ($k == 'versiondata')
170 $current->_data = array_merge($current->_data, $v);
172 $current->_data[$k] = $v;
174 $this->_page_data = $current->_data;
175 $pagedata = "Date: " . Rfc2822DateTime($current->get('mtime')) . "\r\n";
176 $pagedata .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n",
178 $pagedata .= MimeifyPageRevision($page, $current);
180 if ($fd = fopen($filename, 'a+b')) {
181 $locked = flock($fd, 2); // Exclusive blocking lock
183 ExitWiki("Timeout while obtaining lock. Please try again");
187 $len = strlen($pagedata);
188 $num = fwrite($fd, $pagedata, $len);
189 assert($num == $len);
192 ExitWiki("Error while writing page '$pagename'");
201 // c-hanging-comment-ender-p: nil
202 // indent-tabs-mode: nil