MediaWiki  REL1_20
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 
00147         public function getField( $name, $default = null ) {
00148                 if ( $this->hasField( $name ) ) {
00149                         return $this->fields[$name];
00150                 } elseif ( !is_null( $default ) ) {
00151                         return $default;
00152                 } else {
00153                         throw new MWException( 'Attempted to get not-set field ' . $name );
00154                 }
00155         }
00156 
00166         public function loadAndGetField( $name ) {
00167                 if ( !$this->hasField( $name ) ) {
00168                         $this->loadFields( array( $name ) );
00169                 }
00170 
00171                 return $this->getField( $name );
00172         }
00173 
00181         public function removeField( $name ) {
00182                 unset( $this->fields[$name] );
00183         }
00184 
00192         public function getId() {
00193                 return $this->getField( 'id' );
00194         }
00195 
00203         public function setId( $id ) {
00204                 $this->setField( 'id', $id );
00205         }
00206 
00216         public function hasField( $name ) {
00217                 return array_key_exists( $name, $this->fields );
00218         }
00219 
00227         public function hasIdField() {
00228                 return $this->hasField( 'id' )
00229                         && !is_null( $this->getField( 'id' ) );
00230         }
00231 
00240         public function setFields( array $fields, $override = true ) {
00241                 foreach ( $fields as $name => $value ) {
00242                         if ( $override || !$this->hasField( $name ) ) {
00243                                 $this->setField( $name, $value );
00244                         }
00245                 }
00246         }
00247 
00255         protected function getWriteValues() {
00256                 $values = array();
00257 
00258                 foreach ( $this->table->getFields() as $name => $type ) {
00259                         if ( array_key_exists( $name, $this->fields ) ) {
00260                                 $value = $this->fields[$name];
00261 
00262                                 switch ( $type ) {
00263                                         case 'array':
00264                                                 $value = (array)$value;
00265                                         case 'blob':
00266                                                 $value = serialize( $value );
00267                                 }
00268 
00269                                 $values[$this->table->getPrefixedField( $name )] = $value;
00270                         }
00271                 }
00272 
00273                 return $values;
00274         }
00275 
00287         public function toArray( $fields = null, $incNullId = false ) {
00288                 $data = array();
00289                 $setFields = array();
00290 
00291                 if ( !is_array( $fields ) ) {
00292                         $setFields = $this->getSetFieldNames();
00293                 } else {
00294                         foreach ( $fields as $field ) {
00295                                 if ( $this->hasField( $field ) ) {
00296                                         $setFields[] = $field;
00297                                 }
00298                         }
00299                 }
00300 
00301                 foreach ( $setFields as $field ) {
00302                         if ( $incNullId || $field != 'id' || $this->hasIdField() ) {
00303                                 $data[$field] = $this->getField( $field );
00304                         }
00305                 }
00306 
00307                 return $data;
00308         }
00309 
00317         public function loadDefaults( $override = true ) {
00318                 $this->setFields( $this->table->getDefaults(), $override );
00319         }
00320 
00331         public function save( $functionName = null ) {
00332                 if ( $this->hasIdField() ) {
00333                         return $this->saveExisting( $functionName );
00334                 } else {
00335                         return $this->insert( $functionName );
00336                 }
00337         }
00338 
00348         protected function saveExisting( $functionName = null ) {
00349                 $dbw = wfGetDB( DB_MASTER );
00350 
00351                 $success = $dbw->update(
00352                         $this->table->getName(),
00353                         $this->getWriteValues(),
00354                         $this->table->getPrefixedValues( $this->getUpdateConditions() ),
00355                         is_null( $functionName ) ? __METHOD__ : $functionName
00356                 );
00357 
00358                 // DatabaseBase::update does not always return true for success as documented...
00359                 return $success !== false;
00360         }
00361 
00370         protected function getUpdateConditions() {
00371                 return array( 'id' => $this->getId() );
00372         }
00373 
00384         protected function insert( $functionName = null, array $options = null ) {
00385                 $dbw = wfGetDB( DB_MASTER );
00386 
00387                 $success = $dbw->insert(
00388                         $this->table->getName(),
00389                         $this->getWriteValues(),
00390                         is_null( $functionName ) ? __METHOD__ : $functionName,
00391                         is_null( $options ) ? array( 'IGNORE' ) : $options
00392                 );
00393 
00394                 // DatabaseBase::insert does not always return true for success as documented...
00395                 $success = $success !== false;
00396 
00397                 if ( $success ) {
00398                         $this->setField( 'id', $dbw->insertId() );
00399                 }
00400 
00401                 return $success;
00402         }
00403 
00411         public function remove() {
00412                 $this->beforeRemove();
00413 
00414                 $success = $this->table->delete( array( 'id' => $this->getId() ) );
00415 
00416                 // DatabaseBase::delete does not always return true for success as documented...
00417                 $success = $success !== false;
00418 
00419                 if ( $success ) {
00420                         $this->onRemoved();
00421                 }
00422 
00423                 return $success;
00424         }
00425 
00431         protected function beforeRemove() {
00432                 $this->loadFields( $this->getBeforeRemoveFields(), false, true );
00433         }
00434 
00444         protected function getBeforeRemoveFields() {
00445                 return array();
00446         }
00447 
00454         protected function onRemoved() {
00455                 $this->setField( 'id', null );
00456         }
00457 
00465         public function getFields() {
00466                 return $this->fields;
00467         }
00468 
00476         public function getSetFieldNames() {
00477                 return array_keys( $this->fields );
00478         }
00479 
00492         public function setField( $name, $value ) {
00493                 $fields = $this->table->getFields();
00494 
00495                 if ( array_key_exists( $name, $fields ) ) {
00496                         switch ( $fields[$name] ) {
00497                                 case 'int':
00498                                         $value = (int)$value;
00499                                         break;
00500                                 case 'float':
00501                                         $value = (float)$value;
00502                                         break;
00503                                 case 'bool':
00504                                         if ( is_string( $value ) ) {
00505                                                 $value = $value !== '0';
00506                                         } elseif ( is_int( $value ) ) {
00507                                                 $value = $value !== 0;
00508                                         }
00509                                         break;
00510                                 case 'array':
00511                                         if ( is_string( $value ) ) {
00512                                                 $value = unserialize( $value );
00513                                         }
00514 
00515                                         if ( !is_array( $value ) ) {
00516                                                 $value = array();
00517                                         }
00518                                         break;
00519                                 case 'blob':
00520                                         if ( is_string( $value ) ) {
00521                                                 $value = unserialize( $value );
00522                                         }
00523                                         break;
00524                                 case 'id':
00525                                         if ( is_string( $value ) ) {
00526                                                 $value = (int)$value;
00527                                         }
00528                                         break;
00529                         }
00530 
00531                         $this->fields[$name] = $value;
00532                 } else {
00533                         throw new MWException( 'Attempted to set unknown field ' . $name );
00534                 }
00535         }
00536 
00548         public function addToField( $field, $amount ) {
00549                 if ( $amount == 0 ) {
00550                         return true;
00551                 }
00552 
00553                 if ( !$this->hasIdField() ) {
00554                         return false;
00555                 }
00556 
00557                 $absoluteAmount = abs( $amount );
00558                 $isNegative = $amount < 0;
00559 
00560                 $dbw = wfGetDB( DB_MASTER );
00561 
00562                 $fullField = $this->table->getPrefixedField( $field );
00563 
00564                 $success = $dbw->update(
00565                         $this->table->getName(),
00566                         array( "$fullField=$fullField" . ( $isNegative ? '-' : '+' ) . $absoluteAmount ),
00567                         array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
00568                         __METHOD__
00569                 );
00570 
00571                 if ( $success && $this->hasField( $field ) ) {
00572                         $this->setField( $field, $this->getField( $field ) + $amount );
00573                 }
00574 
00575                 return $success;
00576         }
00577 
00585         public function getFieldNames() {
00586                 return array_keys( $this->table->getFields() );
00587         }
00588 
00596         public function loadSummaryFields( $summaryFields = null ) {
00597 
00598         }
00599 
00607         public function setUpdateSummaries( $update ) {
00608                 $this->updateSummaries = $update;
00609         }
00610 
00618         public function setSummaryMode( $summaryMode ) {
00619                 $this->inSummaryMode = $summaryMode;
00620         }
00621 
00634         protected function fieldsChanged( IORMRow $object, $excludeSummaryFields = false ) {
00635                 $exclusionFields = array();
00636 
00637                 if ( $excludeSummaryFields !== false ) {
00638                         $exclusionFields = is_array( $excludeSummaryFields ) ? $excludeSummaryFields : $this->table->getSummaryFields();
00639                 }
00640 
00641                 foreach ( $this->fields as $name => $value ) {
00642                         $excluded = $excludeSummaryFields && in_array( $name, $exclusionFields );
00643 
00644                         if ( !$excluded && $object->getField( $name ) !== $value ) {
00645                                 return true;
00646                         }
00647                 }
00648 
00649                 return false;
00650         }
00651 
00659         public function getTable() {
00660                 return $this->table;
00661         }
00662 
00663 }