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