]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/backend/flatfile.php
Reformat code
[SourceForge/phpwiki.git] / lib / WikiDB / backend / flatfile.php
1 <?php
2
3 /**
4  * Copyright 1999,2005,2006 $ThePhpWikiProgrammingTeam
5  *
6  * This file is part of PhpWiki.
7  *
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.
12  *
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.
17  *
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.
21  */
22
23 /**
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)
30  *
31  * Author: Reini Urban, based on the file backend by Jochen Kalmbach
32  */
33
34 require_once 'lib/WikiDB/backend/file.php';
35 require_once 'lib/loadsave.php';
36
37 class WikiDB_backend_flatfile
38     extends WikiDB_backend_file
39 {
40     // *********************************************************************
41     // common file load / save functions:
42     // FilenameForPage is from loadsave.php
43     function _pagename2filename($type, $pagename, $version)
44     {
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     {
60         if ($this->_page_data != NULL) {
61             if ($this->_page_data['pagename'] == $pagename) {
62                 return $this->_page_data;
63             }
64         }
65         //$pd = $this->_loadPage('page_data', $pagename, 0);
66
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
72             if (!$locked) {
73                 ExitWiki("Timeout while obtaining lock. Please try again");
74             }
75             if ($data = fread($fd, filesize($filename))) {
76                 // This is the only difference from file:
77                 if ($parts = ParseMimeifiedPages($data)) {
78                     $pd = $parts[0];
79                 }
80                 //if ($set_pagename == true)
81                 $pd['pagename'] = $pagename;
82                 //if ($version != 0) $pd['version'] = $version;
83                 if (!is_array($pd))
84                     ExitWiki(sprintf(gettext("'%s': corrupt file"),
85                         htmlspecialchars($filename)));
86             }
87             fclose($fd);
88         }
89
90         if ($pd != NULL)
91             $this->_page_data = $pd;
92         if ($this->_page_data != NULL) {
93             if ($this->_page_data['pagename'] == $pagename) {
94                 return $this->_page_data;
95             }
96         }
97         return array(); // no values found
98     }
99
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.
105      */
106     function _saveVersionData($pagename, $version, $data)
107     {
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);
117         }
118     }
119
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)
126     {
127
128         $type = 'page_data';
129         $version = 1;
130         $filename = $this->_pagename2filename($type, $pagename, $version);
131
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])
139             ) {
140                 $cachedata = &$cache->_pagedata_cache[$pagename];
141                 foreach ($data as $key => $val)
142                     $cachedata[$key] = $val;
143             } else {
144                 $cache->_pagedata_cache[$pagename] = $data;
145             }
146         }
147         //unset ($data['pagedata']);
148         //if (empty($data['versiondata']))
149         //    $data['versiondata'] = $data;
150         // TODO:
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);
159                 if ($oldversiondata)
160                     $olddata['versiondata'] = array_merge($oldversiondata, $olddata['versiondata']);
161             }
162         }
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;
175         }
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",
179             PHPWIKI_VERSION);
180         $pagedata .= MimeifyPageRevision($page, $current);
181
182         if ($fd = fopen($filename, 'a+b')) {
183             $locked = flock($fd, 2); // Exclusive blocking lock
184             if (!$locked) {
185                 ExitWiki("Timeout while obtaining lock. Please try again");
186             }
187             rewind($fd);
188             ftruncate($fd, 0);
189             $len = strlen($pagedata);
190             $num = fwrite($fd, $pagedata, $len);
191             assert($num == $len);
192             fclose($fd);
193         } else {
194             ExitWiki("Error while writing page '$pagename'");
195         }
196     }
197 }
198
199 ;
200
201 // Local Variables:
202 // mode: php
203 // tab-width: 8
204 // c-basic-offset: 4
205 // c-hanging-comment-ender-p: nil
206 // indent-tabs-mode: nil
207 // End: