MediaWiki  REL1_21
ORMRow.php
Go to the documentation of this file.
00001 <?php
00034 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                                 __METHOD__
00125                         );
00126 
00127                         if ( $result !== false ) {
00128                                 $this->setFields( $this->table->getFieldsFromDBResult( $result ), $override );
00129                                 return true;
00130                         }
00131                         return false;
00132                 }
00133 
00134                 return true;
00135         }
00136 
00149         public function getField( $name, $default = null ) {
00150                 if ( $this->hasField( $name ) ) {
00151                         return $this->fields[$name];
00152                 } elseif ( !is_null( $default ) ) {
00153                         return $default;
00154                 } else {
00155                         throw new MWException( 'Attempted to get not-set field ' . $name );
00156                 }
00157         }
00158 
00168         public function loadAndGetField( $name ) {
00169                 if ( !$this->hasField( $name ) ) {
00170                         $this->loadFields( array( $name ) );
00171                 }
00172 
00173                 return $this->getField( $name );
00174         }
00175 
00183         public function removeField( $name ) {
00184                 unset( $this->fields[$name] );
00185         }
00186 
00194         public function getId() {
00195                 return $this->getField( 'id' );
00196         }
00197 
00205         public function setId( $id ) {
00206                 $this->setField( 'id', $id );
00207         }
00208 
00218         public function hasField( $name ) {
00219                 return array_key_exists( $name, $this->fields );
00220         }
00221 
00229         public function hasIdField() {
00230                 return $this->hasField( 'id' )
00231                         && !is_null( $this->getField( 'id' ) );
00232         }
00233 
00242         public function setFields( array $fields, $override = true ) {
00243                 foreach ( $fields as $name => $value ) {
00244                         if ( $override || !$this->hasField( $name ) ) {
00245                                 $this->setField( $name, $value );
00246                         }
00247                 }
00248         }
00249 
00257         protected function getWriteValues() {
00258                 $values = array();
00259 
00260                 foreach ( $this->table->getFields() as $name => $type ) {
00261                         if ( array_key_exists( $name, $this->fields ) ) {
00262                                 $value = $this->fields[$name];
00263 
00264                                 // Skip null id fields so that the DBMS can set the default.
00265                                 if ( $name === 'id' && is_null ( $value ) ) {
00266                                         continue;
00267                                 }
00268 
00269                                 switch ( $type ) {
00270                                         case 'array':
00271                                                 $value = (array)$value;
00272                                                 // fall-through!
00273                                         case 'blob':
00274                                                 $value = serialize( $value );
00275                                                 // fall-through!
00276                                 }
00277 
00278                                 $values[$this->table->getPrefixedField( $name )] = $value;
00279                         }
00280                 }
00281 
00282                 return $values;
00283         }
00284 
00296         public function toArray( $fields = null, $incNullId = false ) {
00297                 $data = array();
00298                 $setFields = array();
00299 
00300                 if ( !is_array( $fields ) ) {
00301                         $setFields = $this->getSetFieldNames();
00302                 } else {
00303                         foreach ( $fields as $field ) {
00304                                 if ( $this->hasField( $field ) ) {
00305                                         $setFields[] = $field;
00306                                 }
00307                         }
00308                 }
00309 
00310                 foreach ( $setFields as $field ) {
00311                         if ( $incNullId || $field != 'id' || $this->hasIdField() ) {
00312                                 $data[$field] = $this->getField( $field );
00313                         }
00314                 }
00315 
00316                 return $data;
00317         }
00318 
00326         public function loadDefaults( $override = true ) {
00327                 $this->setFields( $this->table->getDefaults(), $override );
00328         }
00329 
00340         public function save( $functionName = null ) {
00341                 if ( $this->hasIdField() ) {
00342                         return $this->saveExisting( $functionName );
00343                 } else {
00344                         return $this->insert( $functionName );
00345                 }
00346         }
00347 
00357         protected function saveExisting( $functionName = null ) {
00358                 $dbw = $this->table->getWriteDbConnection();
00359 
00360                 $success = $dbw->update(
00361                         $this->table->getName(),
00362                         $this->getWriteValues(),
00363                         $this->table->getPrefixedValues( $this->getUpdateConditions() ),
00364                         is_null( $functionName ) ? __METHOD__ : $functionName
00365                 );
00366 
00367                 $this->table->releaseConnection( $dbw );
00368 
00369                 // DatabaseBase::update does not always return true for success as documented...
00370                 return $success !== false;
00371         }
00372 
00381         protected function getUpdateConditions() {
00382                 return array( 'id' => $this->getId() );
00383         }
00384 
00395         protected function insert( $functionName = null, array $options = null ) {
00396                 $dbw = $this->table->getWriteDbConnection();
00397 
00398                 $success = $dbw->insert(
00399                         $this->table->getName(),
00400                         $this->getWriteValues(),
00401                         is_null( $functionName ) ? __METHOD__ : $functionName,
00402                         $options
00403                 );
00404 
00405                 // DatabaseBase::insert does not always return true for success as documented...
00406                 $success = $success !== false;
00407 
00408                 if ( $success ) {
00409                         $this->setField( 'id', $dbw->insertId() );
00410                 }
00411 
00412                 $this->table->releaseConnection( $dbw );
00413 
00414                 return $success;
00415         }
00416 
00424         public function remove() {
00425                 $this->beforeRemove();
00426 
00427                 $success = $this->table->delete( array( 'id' => $this->getId() ), __METHOD__ );
00428 
00429                 // DatabaseBase::delete does not always return true for success as documented...
00430                 $success = $success !== false;
00431 
00432                 if ( $success ) {
00433                         $this->onRemoved();
00434                 }
00435 
00436                 return $success;
00437         }
00438 
00444         protected function beforeRemove() {
00445                 $this->loadFields( $this->getBeforeRemoveFields(), false, true );
00446         }
00447 
00457         protected function getBeforeRemoveFields() {
00458                 return array();
00459         }
00460 
00467         protected function onRemoved() {
00468                 $this->setField( 'id', null );
00469         }
00470 
00478         public function getFields() {
00479                 return $this->fields;
00480         }
00481 
00489         public function getSetFieldNames() {
00490                 return array_keys( $this->fields );
00491         }
00492 
00505         public function setField( $name, $value ) {
00506                 $fields = $this->table->getFields();
00507 
00508                 if ( array_key_exists( $name, $fields ) ) {
00509                         switch ( $fields[$name] ) {
00510                                 case 'int':
00511                                         $value = (int)$value;
00512                                         break;
00513                                 case 'float':
00514                                         $value = (float)$value;
00515                                         break;
00516                                 case 'bool':
00517                                         $value = (bool)$value;
00518                                         break;
00519                                 case 'array':
00520                                         if ( is_string( $value ) ) {
00521                                                 $value = unserialize( $value );
00522                                         }
00523 
00524                                         if ( !is_array( $value ) ) {
00525                                                 $value = array();
00526                                         }
00527                                         break;
00528                                 case 'blob':
00529                                         if ( is_string( $value ) ) {
00530                                                 $value = unserialize( $value );
00531                                         }
00532                                         break;
00533                                 case 'id':
00534                                         if ( is_string( $value ) ) {
00535                                                 $value = (int)$value;
00536                                         }
00537                                         break;
00538                         }
00539 
00540                         $this->fields[$name] = $value;
00541                 } else {
00542                         throw new MWException( 'Attempted to set unknown field ' . $name );
00543                 }
00544         }
00545 
00557         public function addToField( $field, $amount ) {
00558                 if ( $amount == 0 ) {
00559                         return true;
00560                 }
00561 
00562                 if ( !$this->hasIdField() ) {
00563                         return false;
00564                 }
00565 
00566                 $absoluteAmount = abs( $amount );
00567                 $isNegative = $amount < 0;
00568 
00569                 $dbw = $this->table->getWriteDbConnection();
00570 
00571                 $fullField = $this->table->getPrefixedField( $field );
00572 
00573                 $success = $dbw->update(
00574                         $this->table->getName(),
00575                         array( "$fullField=$fullField" . ( $isNegative ? '-' : '+' ) . $absoluteAmount ),
00576                         array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
00577                         __METHOD__
00578                 );
00579 
00580                 if ( $success && $this->hasField( $field ) ) {
00581                         $this->setField( $field, $this->getField( $field ) + $amount );
00582                 }
00583 
00584                 $this->table->releaseConnection( $dbw );
00585 
00586                 return $success;
00587         }
00588 
00596         public function getFieldNames() {
00597                 return array_keys( $this->table->getFields() );
00598         }
00599 
00607         public function loadSummaryFields( $summaryFields = null ) {
00608 
00609         }
00610 
00618         public function setUpdateSummaries( $update ) {
00619                 $this->updateSummaries = $update;
00620         }
00621 
00629         public function setSummaryMode( $summaryMode ) {
00630                 $this->inSummaryMode = $summaryMode;
00631         }
00632 
00645         protected function fieldsChanged( IORMRow $object, $excludeSummaryFields = false ) {
00646                 $exclusionFields = array();
00647 
00648                 if ( $excludeSummaryFields !== false ) {
00649                         $exclusionFields = is_array( $excludeSummaryFields ) ? $excludeSummaryFields : $this->table->getSummaryFields();
00650                 }
00651 
00652                 foreach ( $this->fields as $name => $value ) {
00653                         $excluded = $excludeSummaryFields && in_array( $name, $exclusionFields );
00654 
00655                         if ( !$excluded && $object->getField( $name ) !== $value ) {
00656                                 return true;
00657                         }
00658                 }
00659 
00660                 return false;
00661         }
00662 
00670         public function getTable() {
00671                 return $this->table;
00672         }
00673 
00674 }