MediaWiki  master
ORMRow.php
Go to the documentation of this file.
00001 <?php
00034 abstract class ORMRow implements IORMRow {
00035 
00043         protected $fields = array( 'id' => null );
00044 
00049         protected $table;
00050 
00060         protected $updateSummaries = true;
00061 
00070         protected $inSummaryMode = false;
00071 
00081         public function __construct( IORMTable $table, $fields = null, $loadDefaults = false ) {
00082                 $this->table = $table;
00083 
00084                 if ( !is_array( $fields ) ) {
00085                         $fields = array();
00086                 }
00087 
00088                 if ( $loadDefaults ) {
00089                         $fields = array_merge( $this->table->getDefaults(), $fields );
00090                 }
00091 
00092                 $this->setFields( $fields );
00093         }
00094 
00106         public function loadFields( $fields = null, $override = true, $skipLoaded = false ) {
00107                 if ( is_null( $this->getId() ) ) {
00108                         return false;
00109                 }
00110 
00111                 if ( is_null( $fields ) ) {
00112                         $fields = array_keys( $this->table->getFields() );
00113                 }
00114 
00115                 if ( $skipLoaded ) {
00116                         $fields = array_diff( $fields, array_keys( $this->fields ) );
00117                 }
00118 
00119                 if ( !empty( $fields ) ) {
00120                         $result = $this->table->rawSelectRow(
00121                                 $this->table->getPrefixedFields( $fields ),
00122                                 array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
00123                                 array( 'LIMIT' => 1 )
00124                         );
00125 
00126                         if ( $result !== false ) {
00127                                 $this->setFields( $this->table->getFieldsFromDBResult( $result ), $override );
00128                                 return true;
00129                         }
00130                         return false;
00131                 }
00132 
00133                 return true;
00134         }
00135 
00148         public function getField( $name, $default = null ) {
00149                 if ( $this->hasField( $name ) ) {
00150                         return $this->fields[$name];
00151                 } elseif ( !is_null( $default ) ) {
00152                         return $default;
00153                 } else {
00154                         throw new MWException( 'Attempted to get not-set field ' . $name );
00155                 }
00156         }
00157 
00167         public function loadAndGetField( $name ) {
00168                 if ( !$this->hasField( $name ) ) {
00169                         $this->loadFields( array( $name ) );
00170                 }
00171 
00172                 return $this->getField( $name );
00173         }
00174 
00182         public function removeField( $name ) {
00183                 unset( $this->fields[$name] );
00184         }
00185 
00193         public function getId() {
00194                 return $this->getField( 'id' );
00195         }
00196 
00204         public function setId( $id ) {
00205                 $this->setField( 'id', $id );
00206         }
00207 
00217         public function hasField( $name ) {
00218                 return array_key_exists( $name, $this->fields );
00219         }
00220 
00228         public function hasIdField() {
00229                 return $this->hasField( 'id' )
00230                         && !is_null( $this->getField( 'id' ) );
00231         }
00232 
00241         public function setFields( array $fields, $override = true ) {
00242                 foreach ( $fields as $name => $value ) {
00243                         if ( $override || !$this->hasField( $name ) ) {
00244                                 $this->setField( $name, $value );
00245                         }
00246                 }
00247         }
00248 
00256         protected function getWriteValues() {
00257                 $values = array();
00258 
00259                 foreach ( $this->table->getFields() as $name => $type ) {
00260                         if ( array_key_exists( $name, $this->fields ) ) {
00261                                 $value = $this->fields[$name];
00262 
00263                                 switch ( $type ) {
00264                                         case 'array':
00265                                                 $value = (array)$value;
00266                                                 // fall-through!
00267                                         case 'blob':
00268                                                 $value = serialize( $value );
00269                                                 // fall-through!
00270                                 }
00271 
00272                                 $values[$this->table->getPrefixedField( $name )] = $value;
00273                         }
00274                 }
00275 
00276                 return $values;
00277         }
00278 
00290         public function toArray( $fields = null, $incNullId = false ) {
00291                 $data = array();
00292                 $setFields = array();
00293 
00294                 if ( !is_array( $fields ) ) {
00295                         $setFields = $this->getSetFieldNames();
00296                 } else {
00297                         foreach ( $fields as $field ) {
00298                                 if ( $this->hasField( $field ) ) {
00299                                         $setFields[] = $field;
00300                                 }
00301                         }
00302                 }
00303 
00304                 foreach ( $setFields as $field ) {
00305                         if ( $incNullId || $field != 'id' || $this->hasIdField() ) {
00306                                 $data[$field] = $this->getField( $field );
00307                         }
00308                 }
00309 
00310                 return $data;
00311         }
00312 
00320         public function loadDefaults( $override = true ) {
00321                 $this->setFields( $this->table->getDefaults(), $override );
00322         }
00323 
00334         public function save( $functionName = null ) {
00335                 if ( $this->hasIdField() ) {
00336                         return $this->saveExisting( $functionName );
00337                 } else {
00338                         return $this->insert( $functionName );
00339                 }
00340         }
00341 
00351         protected function saveExisting( $functionName = null ) {
00352                 $dbw = $this->table->getWriteDbConnection();
00353 
00354                 $success = $dbw->update(
00355                         $this->table->getName(),
00356                         $this->getWriteValues(),
00357                         $this->table->getPrefixedValues( $this->getUpdateConditions() ),
00358                         is_null( $functionName ) ? __METHOD__ : $functionName
00359                 );
00360 
00361                 $this->table->releaseConnection( $dbw );
00362 
00363                 // DatabaseBase::update does not always return true for success as documented...
00364                 return $success !== false;
00365         }
00366 
00375         protected function getUpdateConditions() {
00376                 return array( 'id' => $this->getId() );
00377         }
00378 
00389         protected function insert( $functionName = null, array $options = null ) {
00390                 $dbw = $this->table->getWriteDbConnection();
00391 
00392                 $success = $dbw->insert(
00393                         $this->table->getName(),
00394                         $this->getWriteValues(),
00395                         is_null( $functionName ) ? __METHOD__ : $functionName,
00396                         $options
00397                 );
00398 
00399                 // DatabaseBase::insert does not always return true for success as documented...
00400                 $success = $success !== false;
00401 
00402                 if ( $success ) {
00403                         $this->setField( 'id', $dbw->insertId() );
00404                 }
00405 
00406                 $this->table->releaseConnection( $dbw );
00407 
00408                 return $success;
00409         }
00410 
00418         public function remove() {
00419                 $this->beforeRemove();
00420 
00421                 $success = $this->table->delete( array( 'id' => $this->getId() ) );
00422 
00423                 // DatabaseBase::delete does not always return true for success as documented...
00424                 $success = $success !== false;
00425 
00426                 if ( $success ) {
00427                         $this->onRemoved();
00428                 }
00429 
00430                 return $success;
00431         }
00432 
00438         protected function beforeRemove() {
00439                 $this->loadFields( $this->getBeforeRemoveFields(), false, true );
00440         }
00441 
00451         protected function getBeforeRemoveFields() {
00452                 return array();
00453         }
00454 
00461         protected function onRemoved() {
00462                 $this->setField( 'id', null );
00463         }
00464 
00472         public function getFields() {
00473                 return $this->fields;
00474         }
00475 
00483         public function getSetFieldNames() {
00484                 return array_keys( $this->fields );
00485         }
00486 
00499         public function setField( $name, $value ) {
00500                 $fields = $this->table->getFields();
00501 
00502                 if ( array_key_exists( $name, $fields ) ) {
00503                         switch ( $fields[$name] ) {
00504                                 case 'int':
00505                                         $value = (int)$value;
00506                                         break;
00507                                 case 'float':
00508                                         $value = (float)$value;
00509                                         break;
00510                                 case 'bool':
00511                                         if ( is_string( $value ) ) {
00512                                                 $value = $value !== '0';
00513                                         } elseif ( is_int( $value ) ) {
00514                                                 $value = $value !== 0;
00515                                         }
00516                                         break;
00517                                 case 'array':
00518                                         if ( is_string( $value ) ) {
00519                                                 $value = unserialize( $value );
00520                                         }
00521 
00522                                         if ( !is_array( $value ) ) {
00523                                                 $value = array();
00524                                         }
00525                                         break;
00526                                 case 'blob':
00527                                         if ( is_string( $value ) ) {
00528                                                 $value = unserialize( $value );
00529                                         }
00530                                         break;
00531                                 case 'id':
00532                                         if ( is_string( $value ) ) {
00533                                                 $value = (int)$value;
00534                                         }
00535                                         break;
00536                         }
00537 
00538                         $this->fields[$name] = $value;
00539                 } else {
00540                         throw new MWException( 'Attempted to set unknown field ' . $name );
00541                 }
00542         }
00543 
00555         public function addToField( $field, $amount ) {
00556                 if ( $amount == 0 ) {
00557                         return true;
00558                 }
00559 
00560                 if ( !$this->hasIdField() ) {
00561                         return false;
00562                 }
00563 
00564                 $absoluteAmount = abs( $amount );
00565                 $isNegative = $amount < 0;
00566 
00567                 $dbw = $this->table->getWriteDbConnection();
00568 
00569                 $fullField = $this->table->getPrefixedField( $field );
00570 
00571                 $success = $dbw->update(
00572                         $this->table->getName(),
00573                         array( "$fullField=$fullField" . ( $isNegative ? '-' : '+' ) . $absoluteAmount ),
00574                         array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
00575                         __METHOD__
00576                 );
00577 
00578                 if ( $success && $this->hasField( $field ) ) {
00579                         $this->setField( $field, $this->getField( $field ) + $amount );
00580                 }
00581 
00582                 $this->table->releaseConnection( $dbw );
00583 
00584                 return $success;
00585         }
00586 
00594         public function getFieldNames() {
00595                 return array_keys( $this->table->getFields() );
00596         }
00597 
00605         public function loadSummaryFields( $summaryFields = null ) {
00606 
00607         }
00608 
00616         public function setUpdateSummaries( $update ) {
00617                 $this->updateSummaries = $update;
00618         }
00619 
00627         public function setSummaryMode( $summaryMode ) {
00628                 $this->inSummaryMode = $summaryMode;
00629         }
00630 
00643         protected function fieldsChanged( IORMRow $object, $excludeSummaryFields = false ) {
00644                 $exclusionFields = array();
00645 
00646                 if ( $excludeSummaryFields !== false ) {
00647                         $exclusionFields = is_array( $excludeSummaryFields ) ? $excludeSummaryFields : $this->table->getSummaryFields();
00648                 }
00649 
00650                 foreach ( $this->fields as $name => $value ) {
00651                         $excluded = $excludeSummaryFields && in_array( $name, $exclusionFields );
00652 
00653                         if ( !$excluded && $object->getField( $name ) !== $value ) {
00654                                 return true;
00655                         }
00656                 }
00657 
00658                 return false;
00659         }
00660 
00668         public function getTable() {
00669                 return $this->table;
00670         }
00671 
00672 }