]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/backend/flatfile.php
New FSF address
[SourceForge/phpwiki.git] / lib / WikiDB / backend / flatfile.php
1 <?php // -*-php-*-
2 // $Id$
3
4 /**
5  * Copyright 1999,2005,2006 $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 along
20  * with PhpWiki; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 /**
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)
31  *
32  * Author: Reini Urban, based on the file backend by Jochen Kalmbach
33  */
34
35 require_once('lib/WikiDB/backend/file.php');
36 require_once('lib/loadsave.php');
37
38 class WikiDB_backend_flatfile
39 extends WikiDB_backend_file
40 {
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);
48         }
49         return $this->_dir_names[$type].'/'.$fpagename;
50 /*      if ($version == 0)
51              return $this->_dir_names[$type].'/'.FilenameForPage($pagename);
52          else
53              return $this->_dir_names[$type].'/'.FilenameForPage($pagename).'--'.$version;
54 */
55     }
56
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;
62              }
63        }
64        //$pd = $this->_loadPage('page_data', $pagename, 0);
65
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
71            if (!$locked) {
72                ExitWiki("Timeout while obtaining lock. Please try again");
73            }
74            if ($data = fread($fd, filesize($filename))) {
75                // This is the only difference from file:
76                if ($parts = ParseMimeifiedPages($data)) {
77                    $pd = $parts[0];
78                }
79                //if ($set_pagename == true)
80                $pd['pagename'] = $pagename;
81                //if ($version != 0) $pd['version'] = $version;
82                if (!is_array($pd))
83                    ExitWiki(sprintf(gettext("'%s': corrupt file"),
84                                     htmlspecialchars($filename)));
85            }
86            fclose($fd);
87        }
88
89        if ($pd != NULL)
90             $this->_page_data = $pd;
91        if ($this->_page_data != NULL) {
92             if ($this->_page_data['pagename'] == $pagename) {
93                 return $this->_page_data;
94              }
95        }
96        return array();  // no values found
97     }
98
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.
104      */
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);
115         }
116     }
117
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) {
124
125         $type = 'page_data';
126         $version = 1;
127         $filename = $this->_pagename2filename($type, $pagename, $version);
128
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]))
136             {
137                 $cachedata = &$cache->_pagedata_cache[$pagename];
138                 foreach($data as $key => $val)
139                     $cachedata[$key] = $val;
140             } else {
141                 $cache->_pagedata_cache[$pagename] = $data;
142             }
143         }
144         //unset ($data['pagedata']);
145         //if (empty($data['versiondata']))
146         //    $data['versiondata'] = $data;
147         // TODO:
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);
156                 if ($oldversiondata)
157                     $olddata['versiondata'] = array_merge($oldversiondata, $olddata['versiondata']);
158             }
159         }
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);
171             else
172                 $current->_data[$k] = $v;
173         }
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",
177                          PHPWIKI_VERSION);
178         $pagedata .= MimeifyPageRevision($page, $current);
179
180         if ($fd = fopen($filename, 'a+b')) {
181             $locked = flock($fd, 2); // Exclusive blocking lock
182             if (!$locked) {
183                 ExitWiki("Timeout while obtaining lock. Please try again");
184             }
185             rewind($fd);
186             ftruncate($fd, 0);
187             $len = strlen($pagedata);
188             $num = fwrite($fd, $pagedata, $len);
189             assert($num == $len);
190             fclose($fd);
191         } else {
192             ExitWiki("Error while writing page '$pagename'");
193         }
194     }
195 };
196
197 // Local Variables:
198 // mode: php
199 // tab-width: 8
200 // c-basic-offset: 4
201 // c-hanging-comment-ender-p: nil
202 // indent-tabs-mode: nil
203 // End:
204 ?>