Difference between revisions of "Extension:MediaWikiLite.php"

From Organic Design wiki
(Use DatabasePostgres's code to populate interwiki from MySQL template)
m
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<?php
+
{{legacy|this is now done using the built in [[SQLite]] database layer}}
# Extension:SQLite{{Category:Extensions|SQLite}}{{php}}{{Category:Extensions in progress|SQLite}}
+
<php><?php
 +
# Extension:MediaWikiLite
 
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
 
# - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
# - Author: [http://www.organicdesign.co.nz/nad User:Nad]{{Category:Extensions created with Template:Extension}}
+
# - Author: [http://www.organicdesign.co.nz/nad User:Nad]
 +
# - Started: 2007-12-17
  
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
 
if (!defined('PDO::ATTR_SERVER_VERSION')) die('PDO::SQLite3 is not installed!');
 
if (!defined('PDO::ATTR_SERVER_VERSION')) die('PDO::SQLite3 is not installed!');
  
define('MWLITE_VERSION','0.0.0, 2008-01-09');
+
define('MWLITE_VERSION','0.1.0, 2008-01-16');
  
$wgDBtype         = 'sqlite';
+
$wgDBtype = 'sqlite';
$wgSQLiteDataDir = dirname(__FILE__);
+
 
$wgShowSQLErrors = true;
+
# Currently all the data for each wiki is in its own file in $wgSQLiteDataDir
 +
$wgSQLiteDataDir = dirname(__FILE__);
 +
 
 +
# For debugging
 +
$wgShowSQLErrors = true;
 +
$wgShowExceptionDetails = true;
 +
 
 +
# Ensure the LoadBalancer knows how to load our DB class when the time comes
 +
$wgAutoloadClasses['DatabaseSqlite'] = dirname(__FILE__)."/DatabaseSqlite.php";
  
 
$wgExtensionCredits['other'][] = array(
 
$wgExtensionCredits['other'][] = array(
Line 20: Line 30:
 
'version'    => MWLITE_VERSION
 
'version'    => MWLITE_VERSION
 
);
 
);
 
+
</php>
class DatabaseSqlite extends Database {
+
[[Category:Legacy Extensions|MediaWikiLite]]
 
 
var $mAffectedRows;
 
 
 
function DatabaseSqlite($server = false, $user = false, $password = false, $dbName = false, $failFunction = false, $flags = 0) {
 
global $wgOut;
 
# Can't get a reference if it hasn't been set yet
 
if (!isset($wgOut)) $wgOut = NULL;
 
$this->mOut =& $wgOut;
 
$this->mFailFunction = $failFunction;
 
$this->mFlags = $flags;
 
$this->open($server, $user, $password, $dbName);
 
}
 
 
 
function cascadingDeletes()  { return true; }
 
function cleanupTriggers()  { return true; }
 
function strictIPs()        { return true; }
 
function realTimestamps()    { return true; }
 
function implicitGroupby()  { return false; }
 
function implicitOrderby()  { return false; }
 
function searchableIPs()    { return true; }
 
function functionalIndexes() { return true; }
 
 
 
static function newFromParams($server, $user, $password, $dbName, $failFunction = false, $flags = 0) {
 
return new DatabaseSqlite($server, $user, $password, $dbName, $failFunction, $flags);
 
}
 
 
 
# Open an SQLite database and return a resource handle to it
 
# NOTE: only $dbName is used, the other parameters are irrelevant for SQLite databases
 
function open($server,$user,$password,$dbName) {
 
global $wgSQLiteDataDir;
 
$this->mConn = false;
 
if ($dbName) {
 
if ($this->mFlags & DBO_PERSISTENT) @$this->mConn = new PDO("sqlite:$wgSQLiteDataDir/$dbName",$user,$pass,array(PDO::ATTR_PERSISTENT => true));
 
else @$this->mConn = @$this->mConn = new PDO("sqlite:$wgSQLiteDataDir/$dbName",$user,$pass);
 
if ($this->mConn === false) wfDebug("DB connection error: $err\n");;
 
$this->mOpened = $this->mConn;
 
$this->mConn->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_SILENT); # set error codes only, dont raise exceptions
 
}
 
return $this->mConn;
 
}
 
 
 
# Close an SQLite database
 
function close() {
 
$this->mOpened = false;
 
if (is_object($this->mConn)) {
 
if ($this->trxLevel()) $this->immediateCommit();
 
$this->mConn = null;
 
}
 
return true;
 
}
 
 
 
# todo: handle buffered/unbuffered from $this->bufferResults()
 
function doQuery($sql) {
 
$ret = $this->mConn->query($sql);
 
if ($ret === false) $this->reportQueryError($this->lastError(),$this->lastErrno(),$sql,__FUNCTION__);
 
return $ret;
 
}
 
 
 
function queryIgnore($sql, $fname = '') {
 
return $this->query($sql, $fname, true);
 
}
 
 
 
function freeResult($res) {
 
if ($res instanceof ResultWrapper) $res = $res->result;
 
$res->closeCursor();
 
return;
 
}
 
 
 
function fetchObject($res) {
 
if ($res instanceof ResultWrapper) $res = $res->result;
 
$row = $res->fetch(PDO::FETCH_OBJ);
 
if ($row === false) throw new DBUnexpectedError($this,'Error in fetchObject(): '.htmlspecialchars($this->lastError()));
 
return $row;
 
}
 
 
 
function fetchRow($res) {
 
if ($res instanceof ResultWrapper) $res = $res->result;
 
$row = $res->fetch(PDO::FETCH_BOTH);
 
if ($row === false) throw new DBUnexpectedError($this,'Error in fetchRow(): '.htmlspecialchars($this->lastError()));
 
return $row;
 
}
 
 
 
function numRows($res) {
 
if ($res instanceof ResultWrapper) $res = $res->result;
 
$n = $res->rowCount();
 
return $n;
 
}
 
 
 
function numFields($res) {
 
if ($res instanceof ResultWrapper) $res = $res->result;
 
$n = $res->columnCount();
 
return $n;
 
}
 
 
 
function fieldName($res,$n) {
 
return $res->fieldName($n);
 
}
 
 
 
# SQLite doesn't like the back-tick for strings
 
function tableName($name) {
 
return ereg_replace('`','"',parent::tableName($name));
 
}
 
 
 
# This must be called after nextSequenceVal
 
function insertId() {
 
# todo: return $this->mInsertId; ?
 
}
 
 
 
function dataSeek($res, $row) {
 
$res->seek($row);
 
}
 
 
 
function lastError() {
 
if (!is_object($this->mConn)) return "Cannot return last error, no db connection";
 
$e = $this->mConn->errorInfo();
 
return $e[2];
 
}
 
 
 
function lastErrno() {
 
if (!is_object($this->mConn)) return "Cannot return last error, no db connection";
 
return $this->mConn->errorCode();
 
}
 
 
 
function affectedRows() {
 
return $this->mAffectedRows;
 
}
 
 
 
# Returns information about an index
 
# - if errors are explicitly ignored, returns NULL on failure
 
function indexInfo($table, $index, $fname = 'Database::indexExists') {
 
# todo
 
}
 
 
 
function indexUnique($table, $index, $fname = 'Database::indexUnique') {
 
# todo
 
}
 
 
 
function insert($table, $a, $fname = 'Database::insert', $options = array()) {
 
# todo
 
}
 
 
 
function insertOneRow($table, $row, $fname) {
 
# todo
 
}
 
 
# SQLite does not have a "USE INDEX" clause, so return an empty string
 
function useIndexClause($index) {
 
return '';
 
}
 
 
 
# REPLACE query wrapper
 
function replace($table, $uniqueIndexes, $rows, $fname = 'Database::replace') {
 
# todo
 
}
 
 
 
# DELETE where the condition is a join
 
function deleteJoin($delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "Database::deleteJoin") {
 
# todo
 
}
 
 
 
# Returns the size of a text field, or -1 for "unlimited"
 
function textFieldSize($table, $field) {
 
# todo
 
}
 
 
 
# No low priority option in SQLite
 
function lowPriorityOption() {
 
return '';
 
}
 
 
 
# Returns an SQL expression for a simple conditional.
 
# - uses CASE on SQLite
 
function conditional($cond, $trueVal, $falseVal) {
 
return " (CASE WHEN $cond THEN $trueVal ELSE $falseVal END) ";
 
}
 
 
 
function wasDeadlock() {
 
return $this->lastErrno() == SQLITE_BUSY;
 
}
 
 
 
# @return string wikitext of a link to the server software's web site
 
function getSoftwareLink() {
 
return "[http://sqlite.org/ SQLite]";
 
}
 
 
 
# @return string Version information from the database
 
function getServerVersion() {
 
return $this->mConn->getAttribute(PDO::ATTR_SERVER_VERSION);
 
}
 
 
 
# Query whether a given column exists in the mediawiki schema
 
function fieldExists($table, $field) { return true; }
 
 
 
function fieldInfo($table, $field) { return false; }
 
 
 
function begin($fname = 'DatabasePostgres::begin') {
 
$this->query('BEGIN', $fname);
 
$this->mTrxLevel = 1;
 
}
 
 
 
function immediateCommit($fname = 'DatabaseSqlite::immediateCommit') {
 
return true;
 
}
 
 
 
function commit($fname = 'DatabaseSqlite::commit') {
 
$this->query('COMMIT', $fname);
 
$this->mTrxLevel = 0;
 
}
 
 
 
function limitResultForUpdate($sql, $num) {
 
return $sql;
 
}
 
 
 
function strencode($s) {
 
return sqlite_escape_string($s);
 
}
 
 
 
function encodeBlob($b) {
 
return new SQLiteBlob($b);
 
}
 
 
 
function decodeBlob($b) {
 
return $b; //return $b->load();
 
}
 
 
 
function addQuotes($s) {
 
return '"'.$s.'"';
 
}
 
 
 
function quote_ident($s) { return $s; }
 
 
 
# For now, does nothing
 
function selectDB($db) { return true; }
 
 
 
# not done
 
public function setTimeout($timeout) { return; }
 
 
 
function ping() {
 
wfDebug("Function ping() not written for SQLite yet");
 
return true;
 
}
 
 
 
# How lagged is this slave?
 
public function getLag() { return 0; }
 
 
 
# Called by the installer script (when modified according to the MediaWikiLite installation instructions)
 
# - this is the same way PostgreSQL works, MySQL reads in tables.sql and interwiki.sql using dbsource (which calls db->sourceFile)
 
public function setup_database() {
 
global $IP,$wgSQLiteDataDir,$wgDBTableOptions;
 
$wgDBTableOptions = '';
 
$mysql_tmpl  = "$IP/maintenance/tables.sql";
 
$mysql_iw    = "$IP/maintenance/interwiki.sql";
 
$sqlite_tmpl = "$wgSQLiteDataDir/tables.sql";
 
 
 
# Make an SQLite template file if it doesn't exist (based on the same one MySQL uses to create a new wiki db)
 
if (1 || !file_exists($sqlite_tmpl)) {
 
$sql = file_get_contents($mysql_tmpl);
 
$sql = preg_replace('/^\\s*--.*?$/m','',$sql); # strip comments
 
$sql = preg_replace('/^\\s*(UNIQUE)?\\s*(PRIMARY)?\\s*KEY.+?$/m','',$sql);
 
$sql = preg_replace('/^\\s*(UNIQUE )?INDEX.+?$/m','',$sql); # These indexes should be created with a CREATE INDEX query
 
$sql = preg_replace('/^\\s*FULLTEXT.+?$/m','',$sql);        # Full text indexes
 
$sql = preg_replace('/ENUM\\(.+?\\)/','TEXT',$sql); # Make ENUM's into TEXT's
 
$sql = preg_replace('/ENUM\\(.+?\\)/','TEXT',$sql); # Make ENUM's into TEXT's
 
$sql = preg_replace('/binary\\(\\d+\\)/','BLOB',$sql);
 
$sql = preg_replace('/(TYPE|MAX_ROWS|AVG_ROW_LENGTH)=\\w+/','',$sql);
 
$sql = preg_replace('/,\\s*\\)/s',')',$sql); # removing previous items may leave a trailing comma
 
$sql = str_replace('binary','',$sql);
 
$sql = str_replace('auto_increment','PRIMARY KEY',$sql);
 
file_put_contents($sqlite_tmpl,$sql);
 
}
 
 
 
# Parse the SQLite template replacing inline variables such as /*$wgDBprefix*/
 
$err = $this->sourceFile($sqlite_tmpl);
 
if ($err !== true) $this->reportQueryError($err,0,$sql,__FUNCTION__);
 
 
 
# Use DatabasePostgres's code to populate interwiki from MySQL template
 
$f = fopen($mysql_iw,'r' );
 
if ($f == false ) dieout( "<li>Could not find the interwiki.sql file");
 
$SQL = "INSERT INTO interwiki(iw_prefix,iw_url,iw_local) VALUES ";
 
while (!feof($f)) {
 
$line = fgets($f,1024);
 
$matches = array();
 
if (!preg_match('/^\s*(\(.+?),(\d)\)/', $line, $matches)) continue;
 
$this->query("$SQL $matches[1],$matches[2])");
 
}
 
}
 
 
 
}
 

Latest revision as of 14:58, 22 October 2014

Legacy.svg Legacy: This article describes a concept that has been superseded in the course of ongoing development on the Organic Design wiki. Please do not develop this any further or base work on this concept, this is only useful for a historic record of work done. You may find a link to the currently used concept or function in this article, if not you can contact the author to find out what has taken the place of this legacy item.

Please refer to [[this is now done using the built in SQLite database layer]] instead.

<php><?php

  1. Extension:MediaWikiLite
  2. - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
  3. - Author: User:Nad
  4. - Started: 2007-12-17

if (!defined('MEDIAWIKI')) die('Not an entry point.'); if (!defined('PDO::ATTR_SERVER_VERSION')) die('PDO::SQLite3 is not installed!');

define('MWLITE_VERSION','0.1.0, 2008-01-16');

$wgDBtype = 'sqlite';

  1. Currently all the data for each wiki is in its own file in $wgSQLiteDataDir

$wgSQLiteDataDir = dirname(__FILE__);

  1. For debugging

$wgShowSQLErrors = true; $wgShowExceptionDetails = true;

  1. Ensure the LoadBalancer knows how to load our DB class when the time comes

$wgAutoloadClasses['DatabaseSqlite'] = dirname(__FILE__)."/DatabaseSqlite.php";

$wgExtensionCredits['other'][] = array( 'name' => 'MediaWikiLite', 'author' => 'User:Nad', 'description' => 'Allow MediaWiki installations to store content in an SQLite database instead of MySQL, and to run as a daemon independently of a web-server.', 'url' => 'http://www.organicdesign.co.nz/Extension:SQLite.php', 'version' => MWLITE_VERSION ); </php>