4 * Copyright 1999,2005,2006 $ThePhpWikiProgrammingTeam
6 * This file is part of PhpWiki.
8 * PhpWiki is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * PhpWiki is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * Backend for handling file storage as pure, readable flatfiles,
25 * as with PageDump. All other methods are taken from file, which
26 * handles serialized pages.
27 * latest version_data is it page_data/
28 * previous ver_data is at ver_data/
29 * latest_ver should not be needed (todo)
31 * Author: Reini Urban, based on the file backend by Jochen Kalmbach
34 require_once 'lib/WikiDB/backend/file.php';
35 require_once 'lib/loadsave.php';
37 class WikiDB_backend_flatfile
38 extends WikiDB_backend_file
40 // *********************************************************************
41 // common file load / save functions:
42 // FilenameForPage is from loadsave.php
43 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)
60 if ($this->_page_data != NULL) {
61 if ($this->_page_data['pagename'] == $pagename) {
62 return $this->_page_data;
65 //$pd = $this->_loadPage('page_data', $pagename, 0);
67 $filename = $this->_pagename2filename('page_data', $pagename, 0);
68 if (!file_exists($filename)) return NULL;
69 if (!filesize($filename)) return array();
70 if ($fd = @fopen($filename, "rb")) {
71 $locked = flock($fd, 1); // Read lock
73 ExitWiki("Timeout while obtaining lock. Please try again");
75 if ($data = fread($fd, filesize($filename))) {
76 // This is the only difference from file:
77 if ($parts = ParseMimeifiedPages($data)) {
80 //if ($set_pagename == true)
81 $pd['pagename'] = $pagename;
82 //if ($version != 0) $pd['version'] = $version;
84 ExitWiki(sprintf(gettext("'%s': corrupt file"),
85 htmlspecialchars($filename)));
91 $this->_page_data = $pd;
92 if ($this->_page_data != NULL) {
93 if ($this->_page_data['pagename'] == $pagename) {
94 return $this->_page_data;
97 return array(); // no values found
100 /** Store latest version as full page_data flatfile,
101 * earlier versions as file backend ver_data.
102 * _cached_html will not be stored.
103 * If the given ($pagename,$version) is already in the database,
104 * this method completely overwrites any stored data for that version.
106 function _saveVersionData($pagename, $version, $data)
108 // check if this is a newer version:
109 if ($this->_getLatestVersion($pagename) < $version) {
110 // write new latest-version-info
111 $this->_setLatestVersion($pagename, $version);
112 // save it as latest page, not serialized version hash
113 // TODO: load latest version data and merge it with new pagedata
114 $this->_savePageData($pagename, array('versiondata' => $data));
115 } else { // save/update old version data hash
116 $this->_savePage('ver_data', $pagename, $version, $data);
120 // This is different to file and not yet finished.
121 // TODO: fields not being saved as page_data should be saved to ver_data
122 // Store as full page_data flatfile
123 // pagedata: date, pagename, hits
124 // versiondata: _cached_html and the rest
125 function _savePageData($pagename, $data)
130 $filename = $this->_pagename2filename($type, $pagename, $version);
132 // Construct a dummy page_revision object
133 $page = new WikiDB_Page($this->_wikidb, $pagename);
134 // data may be pagedate or versiondata updates
135 if (USECACHE and empty($data['pagedata'])) {
136 $cache =& $this->_wikidb->_cache;
137 if (!empty($cache->_pagedata_cache[$pagename])
138 and is_array($cache->_pagedata_cache[$pagename])
140 $cachedata = &$cache->_pagedata_cache[$pagename];
141 foreach ($data as $key => $val)
142 $cachedata[$key] = $val;
144 $cache->_pagedata_cache[$pagename] = $data;
147 //unset ($data['pagedata']);
148 //if (empty($data['versiondata']))
149 // $data['versiondata'] = $data;
151 // with versiondata merge it with previous pagedata, not to overwrite with empty pagedata
152 // with pagedata merge it with previous versiondata, not to overwrite with empty versiondata (content)
153 $olddata = $this->_loadPageData($pagename);
154 if (isset($data['version'])) {
155 $version = $data['version'];
156 $latestversion = $this->_getLatestVersion($pagename);
157 if ($latestversion < $version) {
158 $oldversiondata = $this->_loadVersionData($pagename, $latestversion);
160 $olddata['versiondata'] = array_merge($oldversiondata, $olddata['versiondata']);
163 $data['pagedata'] = array_merge($olddata['pagedata'], $data['pagedata']);
164 $data['versiondata'] = array_merge($olddata['versiondata'], $data['versiondata']);
165 if (empty($data['versiondata']['%content']))
166 $data['versiondata']['%content'] = $olddata['content'];
167 $current = new WikiDB_PageRevision($this->_wikidb, $pagename, $version, $data['versiondata']);
168 unset ($data['versiondata']);
169 foreach ($data as $k => $v) {
170 if ($k == 'pagedata')
171 $current->_data = array_merge($current->_data, $v);
172 elseif ($k == 'versiondata')
173 $current->_data = array_merge($current->_data, $v); else
174 $current->_data[$k] = $v;
176 $this->_page_data = $current->_data;
177 $pagedata = "Date: " . Rfc2822DateTime($current->get('mtime')) . "\r\n";
178 $pagedata .= sprintf("Mime-Version: 1.0 (Produced by PhpWiki %s)\r\n",
180 $pagedata .= MimeifyPageRevision($page, $current);
182 if ($fd = fopen($filename, 'a+b')) {
183 $locked = flock($fd, 2); // Exclusive blocking lock
185 ExitWiki("Timeout while obtaining lock. Please try again");
189 $len = strlen($pagedata);
190 $num = fwrite($fd, $pagedata, $len);
191 assert($num == $len);
194 ExitWiki("Error while writing page '$pagename'");
205 // c-hanging-comment-ender-p: nil
206 // indent-tabs-mode: nil