MediaWiki
master
|
00001 <?php 00030 abstract class ORMTable implements IORMTable { 00031 00039 protected abstract function getFieldPrefix(); 00040 00047 protected static $instanceCache = array(); 00048 00056 protected $readDb = DB_SLAVE; 00057 00065 protected $wiki = false; 00066 00075 public function getDefaults() { 00076 return array(); 00077 } 00078 00088 public function getSummaryFields() { 00089 return array(); 00090 } 00091 00105 public function select( $fields = null, array $conditions = array(), 00106 array $options = array(), $functionName = null ) { 00107 return new ORMResult( $this, $this->rawSelect( $fields, $conditions, $options, $functionName ) ); 00108 } 00109 00123 public function selectObjects( $fields = null, array $conditions = array(), 00124 array $options = array(), $functionName = null ) { 00125 $result = $this->selectFields( $fields, $conditions, $options, false, $functionName ); 00126 00127 $objects = array(); 00128 00129 foreach ( $result as $record ) { 00130 $objects[] = $this->newRow( $record ); 00131 } 00132 00133 return $objects; 00134 } 00135 00148 public function rawSelect( $fields = null, array $conditions = array(), 00149 array $options = array(), $functionName = null ) { 00150 if ( is_null( $fields ) ) { 00151 $fields = array_keys( $this->getFields() ); 00152 } 00153 else { 00154 $fields = (array)$fields; 00155 } 00156 00157 $dbr = $this->getReadDbConnection(); 00158 $result = $dbr->select( 00159 $this->getName(), 00160 $this->getPrefixedFields( $fields ), 00161 $this->getPrefixedValues( $conditions ), 00162 is_null( $functionName ) ? __METHOD__ : $functionName, 00163 $options 00164 ); 00165 00166 $this->releaseConnection( $dbr ); 00167 return $result; 00168 } 00169 00192 public function selectFields( $fields = null, array $conditions = array(), 00193 array $options = array(), $collapse = true, $functionName = null ) { 00194 $objects = array(); 00195 00196 $result = $this->rawSelect( $fields, $conditions, $options, $functionName ); 00197 00198 foreach ( $result as $record ) { 00199 $objects[] = $this->getFieldsFromDBResult( $record ); 00200 } 00201 00202 if ( $collapse ) { 00203 if ( count( $fields ) === 1 ) { 00204 $objects = array_map( 'array_shift', $objects ); 00205 } 00206 elseif ( count( $fields ) === 2 ) { 00207 $o = array(); 00208 00209 foreach ( $objects as $object ) { 00210 $o[array_shift( $object )] = array_shift( $object ); 00211 } 00212 00213 $objects = $o; 00214 } 00215 } 00216 00217 return $objects; 00218 } 00219 00233 public function selectRow( $fields = null, array $conditions = array(), 00234 array $options = array(), $functionName = null ) { 00235 $options['LIMIT'] = 1; 00236 00237 $objects = $this->select( $fields, $conditions, $options, $functionName ); 00238 00239 return $objects->isEmpty() ? false : $objects->current(); 00240 } 00241 00255 public function rawSelectRow( array $fields, array $conditions = array(), 00256 array $options = array(), $functionName = null ) { 00257 $dbr = $this->getReadDbConnection(); 00258 00259 $result = $dbr->selectRow( 00260 $this->getName(), 00261 $fields, 00262 $conditions, 00263 is_null( $functionName ) ? __METHOD__ : $functionName, 00264 $options 00265 ); 00266 00267 $this->releaseConnection( $dbr ); 00268 return $result; 00269 } 00270 00288 public function selectFieldsRow( $fields = null, array $conditions = array(), 00289 array $options = array(), $collapse = true, $functionName = null ) { 00290 $options['LIMIT'] = 1; 00291 00292 $objects = $this->selectFields( $fields, $conditions, $options, $collapse, $functionName ); 00293 00294 return empty( $objects ) ? false : $objects[0]; 00295 } 00296 00307 public function has( array $conditions = array() ) { 00308 return $this->selectRow( array( 'id' ), $conditions ) !== false; 00309 } 00310 00325 public function count( array $conditions = array(), array $options = array() ) { 00326 $res = $this->rawSelectRow( 00327 array( 'rowcount' => 'COUNT(*)' ), 00328 $this->getPrefixedValues( $conditions ), 00329 $options 00330 ); 00331 00332 return $res->rowcount; 00333 } 00334 00345 public function delete( array $conditions, $functionName = null ) { 00346 $dbw = $this->getWriteDbConnection(); 00347 00348 $result = $dbw->delete( 00349 $this->getName(), 00350 $conditions === array() ? '*' : $this->getPrefixedValues( $conditions ), 00351 $functionName 00352 ) !== false; // DatabaseBase::delete does not always return true for success as documented... 00353 00354 $this->releaseConnection( $dbw ); 00355 return $result; 00356 } 00357 00368 public function getAPIParams( $requireParams = false, $setDefaults = false ) { 00369 $typeMap = array( 00370 'id' => 'integer', 00371 'int' => 'integer', 00372 'float' => 'NULL', 00373 'str' => 'string', 00374 'bool' => 'integer', 00375 'array' => 'string', 00376 'blob' => 'string', 00377 ); 00378 00379 $params = array(); 00380 $defaults = $this->getDefaults(); 00381 00382 foreach ( $this->getFields() as $field => $type ) { 00383 if ( $field == 'id' ) { 00384 continue; 00385 } 00386 00387 $hasDefault = array_key_exists( $field, $defaults ); 00388 00389 $params[$field] = array( 00390 ApiBase::PARAM_TYPE => $typeMap[$type], 00391 ApiBase::PARAM_REQUIRED => $requireParams && !$hasDefault 00392 ); 00393 00394 if ( $type == 'array' ) { 00395 $params[$field][ApiBase::PARAM_ISMULTI] = true; 00396 } 00397 00398 if ( $setDefaults && $hasDefault ) { 00399 $default = is_array( $defaults[$field] ) ? implode( '|', $defaults[$field] ) : $defaults[$field]; 00400 $params[$field][ApiBase::PARAM_DFLT] = $default; 00401 } 00402 } 00403 00404 return $params; 00405 } 00406 00416 public function getFieldDescriptions() { 00417 return array(); 00418 } 00419 00427 public function getReadDb() { 00428 return $this->readDb; 00429 } 00430 00438 public function setReadDb( $db ) { 00439 $this->readDb = $db; 00440 } 00441 00449 public function getTargetWiki() { 00450 return $this->wiki; 00451 } 00452 00460 public function setTargetWiki( $wiki ) { 00461 $this->wiki = $wiki; 00462 } 00463 00474 public function getReadDbConnection() { 00475 return $this->getLoadBalancer()->getConnection( $this->getReadDb(), array(), $this->getTargetWiki() ); 00476 } 00477 00488 public function getWriteDbConnection() { 00489 return $this->getLoadBalancer()->getConnection( DB_MASTER, array(), $this->getTargetWiki() ); 00490 } 00491 00501 public function getLoadBalancer() { 00502 return wfGetLB( $this->getTargetWiki() ); 00503 } 00504 00515 public function releaseConnection( DatabaseBase $db ) { 00516 if ( $this->wiki !== false ) { 00517 // recycle connection to foreign wiki 00518 $this->getLoadBalancer()->reuseConnection( $db ); 00519 } 00520 } 00521 00534 public function update( array $values, array $conditions = array() ) { 00535 $dbw = $this->getWriteDbConnection(); 00536 00537 $result = $dbw->update( 00538 $this->getName(), 00539 $this->getPrefixedValues( $values ), 00540 $this->getPrefixedValues( $conditions ), 00541 __METHOD__ 00542 ) !== false; // DatabaseBase::update does not always return true for success as documented... 00543 00544 $this->releaseConnection( $dbw ); 00545 return $result; 00546 } 00547 00556 public function updateSummaryFields( $summaryFields = null, array $conditions = array() ) { 00557 $slave = $this->getReadDb(); 00558 $this->setReadDb( DB_MASTER ); 00559 00563 foreach ( $this->select( null, $conditions ) as $item ) { 00564 $item->loadSummaryFields( $summaryFields ); 00565 $item->setSummaryMode( true ); 00566 $item->save(); 00567 } 00568 00569 $this->setReadDb( $slave ); 00570 } 00571 00583 public function getPrefixedValues( array $values ) { 00584 $prefixedValues = array(); 00585 00586 foreach ( $values as $field => $value ) { 00587 if ( is_integer( $field ) ) { 00588 if ( is_array( $value ) ) { 00589 $field = $value[0]; 00590 $value = $value[1]; 00591 } 00592 else { 00593 $value = explode( ' ', $value, 2 ); 00594 $value[0] = $this->getPrefixedField( $value[0] ); 00595 $prefixedValues[] = implode( ' ', $value ); 00596 continue; 00597 } 00598 } 00599 00600 $prefixedValues[$this->getPrefixedField( $field )] = $value; 00601 } 00602 00603 return $prefixedValues; 00604 } 00605 00616 public function getPrefixedFields( array $fields ) { 00617 foreach ( $fields as &$field ) { 00618 $field = $this->getPrefixedField( $field ); 00619 } 00620 00621 return $fields; 00622 } 00623 00633 public function getPrefixedField( $field ) { 00634 return $this->getFieldPrefix() . $field; 00635 } 00636 00646 public function unprefixFieldNames( array $fieldNames ) { 00647 return array_map( array( $this, 'unprefixFieldName' ), $fieldNames ); 00648 } 00649 00659 public function unprefixFieldName( $fieldName ) { 00660 return substr( $fieldName, strlen( $this->getFieldPrefix() ) ); 00661 } 00662 00670 public static function singleton() { 00671 $class = get_called_class(); 00672 00673 if ( !array_key_exists( $class, self::$instanceCache ) ) { 00674 self::$instanceCache[$class] = new $class; 00675 } 00676 00677 return self::$instanceCache[$class]; 00678 } 00679 00691 public function getFieldsFromDBResult( stdClass $result ) { 00692 $result = (array)$result; 00693 return array_combine( 00694 $this->unprefixFieldNames( array_keys( $result ) ), 00695 array_values( $result ) 00696 ); 00697 } 00698 00709 public function newFromDBResult( stdClass $result ) { 00710 return self::newRowFromDBResult( $result ); 00711 } 00712 00722 public function newRowFromDBResult( stdClass $result ) { 00723 return $this->newRow( $this->getFieldsFromDBResult( $result ) ); 00724 } 00725 00737 public function newFromArray( array $data, $loadDefaults = false ) { 00738 return static::newRow( $data, $loadDefaults ); 00739 } 00740 00751 public function newRow( array $data, $loadDefaults = false ) { 00752 $class = $this->getRowClass(); 00753 return new $class( $this, $data, $loadDefaults ); 00754 } 00755 00763 public function getFieldNames() { 00764 return array_keys( $this->getFields() ); 00765 } 00766 00776 public function canHaveField( $name ) { 00777 return array_key_exists( $name, $this->getFields() ); 00778 } 00779 00780 }