MediaWiki
REL1_20
|
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 }