📄 file.php
字号:
<?php // -*-php-*-rcs_id('$Id: file.php,v 1.22 2004/12/06 19:50:04 rurban Exp $');/** Copyright 1999, 2000, 2001, 2002, 2003 $ThePhpWikiProgrammingTeam This file is part of PhpWiki. PhpWiki is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. PhpWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with PhpWiki; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//** * Backend for handling file storage. * * Author: Jochen Kalmbach, Jochen@kalmbachnet.de *//* * TODO: * - Implement "optimize" / "sync" / "check" / "rebuild" * - Optimize "get_previous_version" * - Optimize "get_links" (reversed = true) * - Optimize "get_all_revisions" * - Optimize "most_popular" (separate file for "hitcount", * which contains all pages) * - Optimize "most_recent" * - What should be done in "lock"/"unlock"/"close" ? * - "WikiDB_backend_file_iter": Do I need to return 'version' and 'versiondata' ? * */require_once('lib/WikiDB/backend.php');require_once('lib/ErrorManager.php');class WikiDB_backend_fileextends WikiDB_backend{ var $data_dir; var $_dir_names; var $_page_data; // temporarily stores the pagedata (via _loadPageData) var $_page_version_data; // temporarily stores the versiondata (via _loadVersionData) var $_latest_versions; // temporarily stores the latest version-numbers (for every pagename) function WikiDB_backend_file( $dbparam ) { $this->data_dir = $dbparam['directory']; if (file_exists($this->data_dir) and is_file($this->data_dir)) unlink($this->data_dir); if (is_dir($this->data_dir) == false) { mkdir($this->data_dir, 0755); } $this->_dir_names = array('ver_data' => $this->data_dir.'/'.'ver_data', 'page_data' => $this->data_dir.'/'.'page_data', 'latest_ver' => $this->data_dir.'/'.'latest_ver', 'links' => $this->data_dir.'/'.'links' ); foreach ($this->_dir_names as $key => $val) { if (file_exists($val) and is_file($val)) unlink($val); if (is_dir($val) == false) mkdir($val, 0755); } $this->_page_data = NULL; $this->_page_version_data = NULL; $this->_latest_versions = NULL; } // ********************************************************************* // common file load / save functions: function _pagename2filename($type, $pagename, $version) { if ($version == 0) return $this->_dir_names[$type].'/'.urlencode($pagename); else return $this->_dir_names[$type].'/'.urlencode($pagename).'--'.$version; } function _loadPage($type, $pagename, $version, $set_pagename = true) { $filename = $this->_pagename2filename($type, $pagename, $version); if (!file_exists($filename)) return NULL; if (!filesize($filename)) return array(); if ($fd = @fopen($filename, "rb")) { $locked = flock($fd, 1); # Read lock if (!$locked) { ExitWiki("Timeout while obtaining lock. Please try again"); } if ($data = fread($fd, filesize($filename))) { $pd = unserialize($data); if ($set_pagename == true) $pd['pagename'] = $pagename; if ($version != 0) $pd['version'] = $version; if (!is_array($pd)) ExitWiki(sprintf(gettext("'%s': corrupt file"), htmlspecialchars($filename))); else return $pd; } fclose($fd); } return NULL; } function _savePage($type, $pagename, $version, $data) { $filename = $this->_pagename2filename($type, $pagename, $version); if($fd = fopen($filename, 'a+b')) { $locked = flock($fd,2); #Exclusive blocking lock if (!$locked) { ExitWiki("Timeout while obtaining lock. Please try again"); } rewind($fd); ftruncate($fd, 0); $pagedata = serialize($data); fwrite($fd, $pagedata); fclose($fd); } else { ExitWiki("Error while writing page '$pagename'"); } } function _removePage($type, $pagename, $version) { $filename = $this->_pagename2filename($type, $pagename, $version); if (!file_exists($filename)) return NULL; $f = @unlink($filename); if ($f == false) trigger_error("delete file failed: ".$filename." ver: ".$version, E_USER_WARNING); } // ********************************************************************* // ********************************************************************* // Load/Save Version-Data function _loadVersionData($pagename, $version) { if ($this->_page_version_data != NULL) { if ( ($this->_page_version_data['pagename'] == $pagename) && ($this->_page_version_data['version'] == $version) ) { return $this->_page_version_data; } } $vd = $this->_loadPage('ver_data', $pagename, $version); if ($vd != NULL) { $this->_page_version_data = $vd; if ( ($this->_page_version_data['pagename'] == $pagename) && ($this->_page_version_data['version'] == $version) ) { return $this->_page_version_data; } } return NULL; } function _saveVersionData($pagename, $version, $data) { $this->_savePage('ver_data', $pagename, $version, $data); // check if this is a newer version: if ($this->_getLatestVersion($pagename) < $version) { // write new latest-version-info $this->_setLatestVersion($pagename, $version); } } // ********************************************************************* // Load/Save Page-Data function _loadPageData($pagename) { if ($this->_page_data != NULL) { if ($this->_page_data['pagename'] == $pagename) { return $this->_page_data; } } $pd = $this->_loadPage('page_data', $pagename, 0); if ($pd != NULL) $this->_page_data = $pd; if ($this->_page_data != NULL) { if ($this->_page_data['pagename'] == $pagename) { return $this->_page_data; } } return array(); // no values found } function _savePageData($pagename, $data) { $this->_savePage('page_data', $pagename, 0, $data); } // ********************************************************************* // Load/Save Latest-Version function _saveLatestVersions() { $data = $this->_latest_versions; if ($data == NULL) $data = array(); $this->_savePage('latest_ver', 'latest_versions', 0, $data); } function _setLatestVersion($pagename, $version) { // make sure the page version list is loaded: $this->_getLatestVersion($pagename); if ($version > 0) { $this->_getLatestVersion($pagename); $this->_latest_versions[$pagename] = $version; } else { // Remove this page from the Latest-Version-List: unset($this->_latest_versions[$pagename]); } $this->_saveLatestVersions(); } function _loadLatestVersions() { if ($this->_latest_versions != NULL) return; $pd = $this->_loadPage('latest_ver', 'latest_versions', 0, false); if ($pd != NULL) $this->_latest_versions = $pd; else $this->_latest_versions = array(); // empty array } function _getLatestVersion($pagename) { $this->_loadLatestVersions(); if (array_key_exists($pagename, $this->_latest_versions) == false) return 0; // do version exists return $this->_latest_versions[$pagename]; } // ********************************************************************* // Load/Save Page-Links function _loadPageLinks($pagename) { $pd = $this->_loadPage('links', $pagename, 0, false); if ($pd != NULL) return $pd;; return array(); // no values found } function _savePageLinks($pagename, $links) { $this->_savePage('links', $pagename, 0, $links); } /** * Get page meta-data from database. * * @param $pagename string Page name. * @return hash * Returns a hash containing the page meta-data. * Returns an empty array if there is no meta-data for the requested page. * Keys which might be present in the hash are: * <dl> * <dt> locked <dd> If the page is locked. * <dt> hits <dd> The page hit count. * <dt> created <dd> Unix time of page creation. (FIXME: Deprecated: I * don't think we need this...) * </dl> */ function get_pagedata($pagename) { return $this->_loadPageData($pagename); } /** * Update the page meta-data. * * Set page meta-data. * * Only meta-data whose keys are preset in $newdata is affected. * * For example: * <pre> * $backend->update_pagedata($pagename, array('locked' => 1)); * </pre> * will set the value of 'locked' to 1 for the specified page, but it * will not affect the value of 'hits' (or whatever other meta-data * may have been stored for the page.) * * To delete a particular piece of meta-data, set it's value to false. * <pre> * $backend->update_pagedata($pagename, array('locked' => false)); * </pre> * * @param $pagename string Page name. * @param $newdata hash New meta-data. */ /** * This will create a new page if page being requested does not * exist. */ function update_pagedata($pagename, $newdata) { $data = $this->get_pagedata($pagename); if (count($data) == 0) { $this->_savePageData($pagename, $newdata); // create a new pagedata-file return; } foreach ($newdata as $key => $val) { if (empty($val)) unset($data[$key]); else $data[$key] = $val; } $this->_savePageData($pagename, $data); // write new pagedata-file } /** * Get the current version number for a page. * * @param $pagename string Page name. * @return int The latest version number for the page. Returns zero if * no versions of a page exist. */ function get_latest_version($pagename) { return $this->_getLatestVersion($pagename); } /** * Get preceding version number. * * @param $pagename string Page name. * @param $version int Find version before this one. * @return int The version number of the version in the database which * immediately preceeds $version. * * FIXED: Check if this version really exists! */ function get_previous_version($pagename, $version) { $prev = ($version > 0 ? $version - 1 : 0); while ($prev and !file_exists($this->_pagename2filename('ver_data', $pagename, $prev))) { $prev--; } return $prev; } /** * Get revision meta-data and content. * * @param $pagename string Page name. * @param $version integer Which version to get. * @param $want_content boolean * Indicates the caller really wants the page content. If this * flag is not set, the backend is free to skip fetching of the * page content (as that may be expensive). If the backend omits * the content, the backend might still want to set the value of * '%content' to the empty string if it knows there's no content. * * @return hash The version data, or false if specified version does not * exist. * * Some keys which might be present in the $versiondata hash are: * <dl> * <dt> %content * <dd> This is a pseudo-meta-data element (since it's actually * the page data, get it?) containing the page content. * If the content was not fetched, this key may not be present. * </dl> * For description of other version meta-data see WikiDB_PageRevision::get(). * @see WikiDB_PageRevision::get */ function get_versiondata($pagename, $version, $want_content = false) { $vd = $this->_loadVersionData($pagename, $version); if ($vd == NULL) return false; return $vd; } /** * Rename all files for this page * * @access protected Via WikiDB */ function rename_page($pagename, $to) { $version = _getLatestVersion($pagename); foreach ($this->_dir_names as $type => $path) { if (is_dir($path)) { $filename = $this->_pagename2filename($type, $pagename, $version); $new = $this->_pagename2filename($type, $to, $version); @rename($filename,$new); } } $this->update_pagedata($pagename, array('pagename' => $to)); return true; } /** * See ADODB for a better delete_page(), which can be undone and is seen in RecentChanges. */ function delete_page($pagename) { $this->purge_page($pagename); } /** * Delete page from the database. * * Delete page (and all it's revisions) from the database. * * @param $pagename string Page name. */ function purge_page($pagename) { $ver = $this->get_latest_version($pagename); while ($ver > 0) { $this->_removePage('ver_data', $pagename, $ver); $ver = $this->get_previous_version($pagename, $ver); } $this->_removePage('page_data', $pagename, 0); $this->_removePage('links', $pagename, 0); // remove page from latest_version...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -