<?php
/**
* Abstract base class for representing a single database table.
+ * Documentation inline and at https://www.mediawiki.org/wiki/Manual:ORMTable
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
protected static $instanceCache = array();
/**
- * The database connection to use for read operations.
+ * ID of the database connection to use for read operations.
* Can be changed via @see setReadDb.
*
* @since 1.20
*/
protected $readDb = DB_SLAVE;
+ /**
+ * The ID of any foreign wiki to use as a target for database operations,
+ * or false to use the local wiki.
+ *
+ * @since 1.20
+ * @var String|bool
+ */
+ protected $wiki = false;
+
/**
* Returns a list of default field values.
* field name => field value
$fields = (array)$fields;
}
- return wfGetDB( $this->getReadDb() )->select(
+ $dbr = $this->getReadDbConnection();
+ $result = $dbr->select(
$this->getName(),
$this->getPrefixedFields( $fields ),
$this->getPrefixedValues( $conditions ),
is_null( $functionName ) ? __METHOD__ : $functionName,
$options
);
+
+ $this->releaseConnection( $dbr );
+ return $result;
}
/**
*/
public function rawSelectRow( array $fields, array $conditions = array(),
array $options = array(), $functionName = null ) {
- $dbr = wfGetDB( $this->getReadDb() );
+ $dbr = $this->getReadDbConnection();
- return $dbr->selectRow(
+ $result = $dbr->selectRow(
$this->getName(),
$fields,
$conditions,
is_null( $functionName ) ? __METHOD__ : $functionName,
$options
);
+
+ $this->releaseConnection( $dbr );
+ return $result;
}
/**
*/
public function count( array $conditions = array(), array $options = array() ) {
$res = $this->rawSelectRow(
- array( 'COUNT(*) AS rowcount' ),
+ array( 'rowcount' => 'COUNT(*)' ),
$this->getPrefixedValues( $conditions ),
$options
);
* @return boolean Success indicator
*/
public function delete( array $conditions, $functionName = null ) {
- return wfGetDB( DB_MASTER )->delete(
+ $dbw = $this->getWriteDbConnection();
+
+ $result = $dbw->delete(
$this->getName(),
- $this->getPrefixedValues( $conditions ),
+ $conditions === array() ? '*' : $this->getPrefixedValues( $conditions ),
$functionName
) !== false; // DatabaseBase::delete does not always return true for success as documented...
+
+ $this->releaseConnection( $dbw );
+ return $result;
}
/**
}
/**
- * Get the database type used for read operations.
+ * Get the database ID used for read operations.
*
* @since 1.20
*
}
/**
- * Set the database type to use for read operations.
+ * Set the database ID to use for read operations, use DB_XXX constants or an index to the load balancer setup.
*
* @param integer $db
*
$this->readDb = $db;
}
+ /**
+ * Get the ID of the any foreign wiki to use as a target for database operations
+ *
+ * @since 1.20
+ *
+ * @return String|bool The target wiki, in a form that LBFactory understands (or false if the local wiki is used)
+ */
+ public function getTargetWiki() {
+ return $this->wiki;
+ }
+
+ /**
+ * Set the ID of the any foreign wiki to use as a target for database operations
+ *
+ * @param String|bool $wiki The target wiki, in a form that LBFactory understands (or false if the local wiki shall be used)
+ *
+ * @since 1.20
+ */
+ public function setTargetWiki( $wiki ) {
+ $this->wiki = $wiki;
+ }
+
+ /**
+ * Get the database type used for read operations.
+ * This is to be used instead of wfGetDB.
+ *
+ * @see LoadBalancer::getConnection
+ *
+ * @since 1.20
+ *
+ * @return DatabaseBase The database object
+ */
+ public function getReadDbConnection() {
+ return $this->getLoadBalancer()->getConnection( $this->getReadDb(), array(), $this->getTargetWiki() );
+ }
+
+ /**
+ * Get the database type used for read operations.
+ * This is to be used instead of wfGetDB.
+ *
+ * @see LoadBalancer::getConnection
+ *
+ * @since 1.20
+ *
+ * @return DatabaseBase The database object
+ */
+ public function getWriteDbConnection() {
+ return $this->getLoadBalancer()->getConnection( DB_MASTER, array(), $this->getTargetWiki() );
+ }
+
+ /**
+ * Get the database type used for read operations.
+ *
+ * @see wfGetLB
+ *
+ * @since 1.20
+ *
+ * @return LoadBalancer The database load balancer object
+ */
+ public function getLoadBalancer() {
+ return wfGetLB( $this->getTargetWiki() );
+ }
+
+ /**
+ * Releases the lease on the given database connection. This is useful mainly
+ * for connections to a foreign wiki. It does nothing for connections to the local wiki.
+ *
+ * @see LoadBalancer::reuseConnection
+ *
+ * @param DatabaseBase $db the database
+ *
+ * @since 1.20
+ */
+ public function releaseConnection( DatabaseBase $db ) {
+ if ( $this->wiki !== false ) {
+ // recycle connection to foreign wiki
+ $this->getLoadBalancer()->reuseConnection( $db );
+ }
+ }
+
/**
* Update the records matching the provided conditions by
* setting the fields that are keys in the $values param to
* @return boolean Success indicator
*/
public function update( array $values, array $conditions = array() ) {
- $dbw = wfGetDB( DB_MASTER );
+ $dbw = $this->getWriteDbConnection();
- return $dbw->update(
+ $result = $dbw->update(
$this->getName(),
$this->getPrefixedValues( $values ),
$this->getPrefixedValues( $conditions ),
__METHOD__
) !== false; // DatabaseBase::update does not always return true for success as documented...
+
+ $this->releaseConnection( $dbw );
+ return $result;
}
/**
* @param array $conditions
*/
public function updateSummaryFields( $summaryFields = null, array $conditions = array() ) {
+ $slave = $this->getReadDb();
$this->setReadDb( DB_MASTER );
- foreach ( $this->select( null, $conditions ) as /* IORMRow */ $item ) {
+ /**
+ * @var IORMRow $item
+ */
+ foreach ( $this->select( null, $conditions ) as $item ) {
$item->loadSummaryFields( $summaryFields );
$item->setSummaryMode( true );
$item->save();
}
- $this->setReadDb( DB_SLAVE );
+ $this->setReadDb( $slave );
}
/**
* @return IORMTable
*/
public static function singleton() {
- $class = function_exists( 'get_called_class' ) ? get_called_class() : self::get_called_class();
+ $class = get_called_class();
if ( !array_key_exists( $class, self::$instanceCache ) ) {
self::$instanceCache[$class] = new $class;
return self::$instanceCache[$class];
}
- /**
- * Compatibility fallback function so the singleton method works on PHP < 5.3.
- * Code borrowed from http://www.php.net/manual/en/function.get-called-class.php#107445
- *
- * @since 1.20
- *
- * @return string
- */
- protected static function get_called_class() {
- $bt = debug_backtrace();
- $l = count($bt) - 1;
- $matches = array();
- while(empty($matches) && $l > -1){
- $lines = file($bt[$l]['file']);
- $callerLine = $lines[$bt[$l]['line']-1];
- preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l--]['function'].'/',
- $callerLine,
- $matches);
- }
- if (!isset($matches[1])) $matches[1]=NULL; //for notices
- if ($matches[1] == 'self') {
- $line = $bt[$l]['line']-1;
- while ($line > 0 && strpos($lines[$line], 'class') === false) {
- $line--;
- }
- preg_match('/class[\s]+(.+?)[\s]+/si', $lines[$line], $matches);
- }
- return $matches[1];
- }
-
/**
* Get an array with fields from a database result,
* that can be fed directly to the constructor or
/**
* @see ORMTable::newRowFromFromDBResult
*
- * @deprecated use newRowFromFromDBResult instead
+ * @deprecated use newRowFromDBResult instead
* @since 1.20
*
* @param stdClass $result