MediaWiki  master
ORMTable.php
Go to the documentation of this file.
00001 <?php
00030 abstract class ORMTable implements IORMTable {
00031 
00039         protected abstract function getFieldPrefix();
00040 
00047         protected static $instanceCache = array();
00048 
00056         protected $readDb = DB_SLAVE;
00057 
00065         protected $wiki = false;
00066 
00075         public function getDefaults() {
00076                 return array();
00077         }
00078 
00088         public function getSummaryFields() {
00089                 return array();
00090         }
00091 
00105         public function select( $fields = null, array $conditions = array(),
00106                                                         array $options = array(), $functionName  = null ) {
00107                 return new ORMResult( $this, $this->rawSelect( $fields, $conditions, $options, $functionName ) );
00108         }
00109 
00123         public function selectObjects( $fields = null, array $conditions = array(),
00124                                                                    array $options = array(), $functionName  = null ) {
00125                 $result = $this->selectFields( $fields, $conditions, $options, false, $functionName );
00126 
00127                 $objects = array();
00128 
00129                 foreach ( $result as $record ) {
00130                         $objects[] = $this->newRow( $record );
00131                 }
00132 
00133                 return $objects;
00134         }
00135 
00148         public function rawSelect( $fields = null, array $conditions = array(),
00149                                                            array $options = array(), $functionName  = null ) {
00150                 if ( is_null( $fields ) ) {
00151                         $fields = array_keys( $this->getFields() );
00152                 }
00153                 else {
00154                         $fields = (array)$fields;
00155                 }
00156 
00157                 $dbr = $this->getReadDbConnection();
00158                 $result = $dbr->select(
00159                         $this->getName(),
00160                         $this->getPrefixedFields( $fields ),
00161                         $this->getPrefixedValues( $conditions ),
00162                         is_null( $functionName ) ? __METHOD__ : $functionName,
00163                         $options
00164                 );
00165 
00166                 $this->releaseConnection( $dbr );
00167                 return $result;
00168         }
00169 
00192         public function selectFields( $fields = null, array $conditions = array(),
00193                                                                   array $options = array(), $collapse = true, $functionName  = null ) {
00194                 $objects = array();
00195 
00196                 $result = $this->rawSelect( $fields, $conditions, $options, $functionName );
00197 
00198                 foreach ( $result as $record ) {
00199                         $objects[] = $this->getFieldsFromDBResult( $record );
00200                 }
00201 
00202                 if ( $collapse ) {
00203                         if ( count( $fields ) === 1 ) {
00204                                 $objects = array_map( 'array_shift', $objects );
00205                         }
00206                         elseif ( count( $fields ) === 2 ) {
00207                                 $o = array();
00208 
00209                                 foreach ( $objects as $object ) {
00210                                         $o[array_shift( $object )] = array_shift( $object );
00211                                 }
00212 
00213                                 $objects = $o;
00214                         }
00215                 }
00216 
00217                 return $objects;
00218         }
00219 
00233         public function selectRow( $fields = null, array $conditions = array(),
00234                                                            array $options = array(), $functionName = null ) {
00235                 $options['LIMIT'] = 1;
00236 
00237                 $objects = $this->select( $fields, $conditions, $options, $functionName );
00238 
00239                 return $objects->isEmpty() ? false : $objects->current();
00240         }
00241 
00255         public function rawSelectRow( array $fields, array $conditions = array(),
00256                                                                   array $options = array(), $functionName = null ) {
00257                 $dbr = $this->getReadDbConnection();
00258 
00259                 $result = $dbr->selectRow(
00260                         $this->getName(),
00261                         $fields,
00262                         $conditions,
00263                         is_null( $functionName ) ? __METHOD__ : $functionName,
00264                         $options
00265                 );
00266 
00267                 $this->releaseConnection( $dbr );
00268                 return $result;
00269         }
00270 
00288         public function selectFieldsRow( $fields = null, array $conditions = array(),
00289                                                                          array $options = array(), $collapse = true, $functionName = null ) {
00290                 $options['LIMIT'] = 1;
00291 
00292                 $objects = $this->selectFields( $fields, $conditions, $options, $collapse, $functionName );
00293 
00294                 return empty( $objects ) ? false : $objects[0];
00295         }
00296 
00307         public function has( array $conditions = array() ) {
00308                 return $this->selectRow( array( 'id' ), $conditions ) !== false;
00309         }
00310 
00325         public function count( array $conditions = array(), array $options = array() ) {
00326                 $res = $this->rawSelectRow(
00327                         array( 'rowcount' => 'COUNT(*)' ),
00328                         $this->getPrefixedValues( $conditions ),
00329                         $options
00330                 );
00331 
00332                 return $res->rowcount;
00333         }
00334 
00345         public function delete( array $conditions, $functionName = null ) {
00346                 $dbw = $this->getWriteDbConnection();
00347 
00348                 $result = $dbw->delete(
00349                         $this->getName(),
00350                         $conditions === array() ? '*' : $this->getPrefixedValues( $conditions ),
00351                         $functionName
00352                 ) !== false; // DatabaseBase::delete does not always return true for success as documented...
00353 
00354                 $this->releaseConnection( $dbw );
00355                 return $result;
00356         }
00357 
00368         public function getAPIParams( $requireParams = false, $setDefaults = false ) {
00369                 $typeMap = array(
00370                         'id' => 'integer',
00371                         'int' => 'integer',
00372                         'float' => 'NULL',
00373                         'str' => 'string',
00374                         'bool' => 'integer',
00375                         'array' => 'string',
00376                         'blob' => 'string',
00377                 );
00378 
00379                 $params = array();
00380                 $defaults = $this->getDefaults();
00381 
00382                 foreach ( $this->getFields() as $field => $type ) {
00383                         if ( $field == 'id' ) {
00384                                 continue;
00385                         }
00386 
00387                         $hasDefault = array_key_exists( $field, $defaults );
00388 
00389                         $params[$field] = array(
00390                                 ApiBase::PARAM_TYPE => $typeMap[$type],
00391                                 ApiBase::PARAM_REQUIRED => $requireParams && !$hasDefault
00392                         );
00393 
00394                         if ( $type == 'array' ) {
00395                                 $params[$field][ApiBase::PARAM_ISMULTI] = true;
00396                         }
00397 
00398                         if ( $setDefaults && $hasDefault ) {
00399                                 $default = is_array( $defaults[$field] ) ? implode( '|', $defaults[$field] ) : $defaults[$field];
00400                                 $params[$field][ApiBase::PARAM_DFLT] = $default;
00401                         }
00402                 }
00403 
00404                 return $params;
00405         }
00406 
00416         public function getFieldDescriptions() {
00417                 return array();
00418         }
00419 
00427         public function getReadDb() {
00428                 return $this->readDb;
00429         }
00430 
00438         public function setReadDb( $db ) {
00439                 $this->readDb = $db;
00440         }
00441 
00449         public function getTargetWiki() {
00450                 return $this->wiki;
00451         }
00452 
00460         public function setTargetWiki( $wiki ) {
00461                 $this->wiki = $wiki;
00462         }
00463 
00474         public function getReadDbConnection() {
00475                 return $this->getLoadBalancer()->getConnection( $this->getReadDb(), array(), $this->getTargetWiki() );
00476         }
00477 
00488         public function getWriteDbConnection() {
00489                 return $this->getLoadBalancer()->getConnection( DB_MASTER, array(), $this->getTargetWiki() );
00490         }
00491 
00501         public function getLoadBalancer() {
00502                 return wfGetLB( $this->getTargetWiki() );
00503         }
00504 
00515         public function releaseConnection( DatabaseBase $db ) {
00516                 if ( $this->wiki !== false ) {
00517                         // recycle connection to foreign wiki
00518                         $this->getLoadBalancer()->reuseConnection( $db );
00519                 }
00520         }
00521 
00534         public function update( array $values, array $conditions = array() ) {
00535                 $dbw = $this->getWriteDbConnection();
00536 
00537                 $result = $dbw->update(
00538                         $this->getName(),
00539                         $this->getPrefixedValues( $values ),
00540                         $this->getPrefixedValues( $conditions ),
00541                         __METHOD__
00542                 ) !== false; // DatabaseBase::update does not always return true for success as documented...
00543 
00544                 $this->releaseConnection( $dbw );
00545                 return $result;
00546         }
00547 
00556         public function updateSummaryFields( $summaryFields = null, array $conditions = array() ) {
00557                 $slave = $this->getReadDb();
00558                 $this->setReadDb( DB_MASTER );
00559 
00563                 foreach ( $this->select( null, $conditions ) as $item ) {
00564                         $item->loadSummaryFields( $summaryFields );
00565                         $item->setSummaryMode( true );
00566                         $item->save();
00567                 }
00568 
00569                 $this->setReadDb( $slave );
00570         }
00571 
00583         public function getPrefixedValues( array $values ) {
00584                 $prefixedValues = array();
00585 
00586                 foreach ( $values as $field => $value ) {
00587                         if ( is_integer( $field ) ) {
00588                                 if ( is_array( $value ) ) {
00589                                         $field = $value[0];
00590                                         $value = $value[1];
00591                                 }
00592                                 else {
00593                                         $value = explode( ' ', $value, 2 );
00594                                         $value[0] = $this->getPrefixedField( $value[0] );
00595                                         $prefixedValues[] = implode( ' ', $value );
00596                                         continue;
00597                                 }
00598                         }
00599 
00600                         $prefixedValues[$this->getPrefixedField( $field )] = $value;
00601                 }
00602 
00603                 return $prefixedValues;
00604         }
00605 
00616         public function getPrefixedFields( array $fields ) {
00617                 foreach ( $fields as &$field ) {
00618                         $field = $this->getPrefixedField( $field );
00619                 }
00620 
00621                 return $fields;
00622         }
00623 
00633         public function getPrefixedField( $field ) {
00634                 return $this->getFieldPrefix() . $field;
00635         }
00636 
00646         public function unprefixFieldNames( array $fieldNames ) {
00647                 return array_map( array( $this, 'unprefixFieldName' ), $fieldNames );
00648         }
00649 
00659         public function unprefixFieldName( $fieldName ) {
00660                 return substr( $fieldName, strlen( $this->getFieldPrefix() ) );
00661         }
00662 
00670         public static function singleton() {
00671                 $class = get_called_class();
00672 
00673                 if ( !array_key_exists( $class, self::$instanceCache ) ) {
00674                         self::$instanceCache[$class] = new $class;
00675                 }
00676 
00677                 return self::$instanceCache[$class];
00678         }
00679 
00691         public function getFieldsFromDBResult( stdClass $result ) {
00692                 $result = (array)$result;
00693                 return array_combine(
00694                         $this->unprefixFieldNames( array_keys( $result ) ),
00695                         array_values( $result )
00696                 );
00697         }
00698 
00709         public function newFromDBResult( stdClass $result ) {
00710                 return self::newRowFromDBResult( $result );
00711         }
00712 
00722         public function newRowFromDBResult( stdClass $result ) {
00723                 return $this->newRow( $this->getFieldsFromDBResult( $result ) );
00724         }
00725 
00737         public function newFromArray( array $data, $loadDefaults = false ) {
00738                 return static::newRow( $data, $loadDefaults );
00739         }
00740 
00751         public function newRow( array $data, $loadDefaults = false ) {
00752                 $class = $this->getRowClass();
00753                 return new $class( $this, $data, $loadDefaults );
00754         }
00755 
00763         public function getFieldNames() {
00764                 return array_keys( $this->getFields() );
00765         }
00766 
00776         public function canHaveField( $name ) {
00777                 return array_key_exists( $name, $this->getFields() );
00778         }
00779 
00780 }