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