[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/db/ -> ORMRow.php (source)

   1  <?php
   2  /**
   3   * Abstract base class for representing objects that are stored in some DB table.
   4   * This is basically an ORM-like wrapper around rows in database tables that
   5   * aims to be both simple and very flexible. It is centered around an associative
   6   * array of fields and various methods to do common interaction with the database.
   7   *
   8   * Documentation inline and at https://www.mediawiki.org/wiki/Manual:ORMTable
   9   *
  10   * This program is free software; you can redistribute it and/or modify
  11   * it under the terms of the GNU General Public License as published by
  12   * the Free Software Foundation; either version 2 of the License, or
  13   * (at your option) any later version.
  14   *
  15   * This program is distributed in the hope that it will be useful,
  16   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18   * GNU General Public License for more details.
  19   *
  20   * You should have received a copy of the GNU General Public License along
  21   * with this program; if not, write to the Free Software Foundation, Inc.,
  22   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  23   * http://www.gnu.org/copyleft/gpl.html
  24   *
  25   * @since 1.20
  26   *
  27   * @file ORMRow.php
  28   * @ingroup ORM
  29   *
  30   * @license GNU GPL v2 or later
  31   * @author Jeroen De Dauw < [email protected] >
  32   */
  33  
  34  class ORMRow implements IORMRow {
  35      /**
  36       * The fields of the object.
  37       * field name (w/o prefix) => value
  38       *
  39       * @since 1.20
  40       * @var array
  41       */
  42      protected $fields = array( 'id' => null );
  43  
  44      /**
  45       * If the object should update summaries of linked items when changed.
  46       * For example, update the course_count field in universities when a course in courses is deleted.
  47       * Settings this to false can prevent needless updating work in situations
  48       * such as deleting a university, which will then delete all it's courses.
  49       *
  50       * @deprecated since 1.22
  51       * @since 1.20
  52       * @var bool
  53       */
  54      protected $updateSummaries = true;
  55  
  56      /**
  57       * Indicates if the object is in summary mode.
  58       * This mode indicates that only summary fields got updated,
  59       * which allows for optimizations.
  60       *
  61       * @deprecated since 1.22
  62       * @since 1.20
  63       * @var bool
  64       */
  65      protected $inSummaryMode = false;
  66  
  67      /**
  68       * @deprecated since 1.22
  69       * @since 1.20
  70       * @var ORMTable|null
  71       */
  72      protected $table;
  73  
  74      /**
  75       * Constructor.
  76       *
  77       * @since 1.20
  78       *
  79       * @param IORMTable|null $table Deprecated since 1.22
  80       * @param array|null $fields
  81       * @param bool $loadDefaults Deprecated since 1.22
  82       */
  83  	public function __construct( IORMTable $table = null, $fields = null, $loadDefaults = false ) {
  84          $this->table = $table;
  85  
  86          if ( !is_array( $fields ) ) {
  87              $fields = array();
  88          }
  89  
  90          if ( $loadDefaults ) {
  91              $fields = array_merge( $this->table->getDefaults(), $fields );
  92          }
  93  
  94          $this->setFields( $fields );
  95      }
  96  
  97      /**
  98       * Load the specified fields from the database.
  99       *
 100       * @since 1.20
 101       * @deprecated since 1.22
 102       *
 103       * @param array|null $fields
 104       * @param bool $override
 105       * @param bool $skipLoaded
 106       *
 107       * @return bool Success indicator
 108       */
 109  	public function loadFields( $fields = null, $override = true, $skipLoaded = false ) {
 110          if ( is_null( $this->getId() ) ) {
 111              return false;
 112          }
 113  
 114          if ( is_null( $fields ) ) {
 115              $fields = array_keys( $this->table->getFields() );
 116          }
 117  
 118          if ( $skipLoaded ) {
 119              $fields = array_diff( $fields, array_keys( $this->fields ) );
 120          }
 121  
 122          if ( !empty( $fields ) ) {
 123              $result = $this->table->rawSelectRow(
 124                  $this->table->getPrefixedFields( $fields ),
 125                  array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
 126                  array( 'LIMIT' => 1 ),
 127                  __METHOD__
 128              );
 129  
 130              if ( $result !== false ) {
 131                  $this->setFields( $this->table->getFieldsFromDBResult( $result ), $override );
 132  
 133                  return true;
 134              }
 135  
 136              return false;
 137          }
 138  
 139          return true;
 140      }
 141  
 142      /**
 143       * Gets the value of a field.
 144       *
 145       * @since 1.20
 146       *
 147       * @param string $name Field name
 148       * @param mixed $default Default value to return when none is found
 149       * (default: null)
 150       *
 151       * @throws MWException
 152       * @return mixed
 153       */
 154  	public function getField( $name, $default = null ) {
 155          if ( $this->hasField( $name ) ) {
 156              return $this->fields[$name];
 157          } elseif ( !is_null( $default ) ) {
 158              return $default;
 159          } else {
 160              throw new MWException( 'Attempted to get not-set field ' . $name );
 161          }
 162      }
 163  
 164      /**
 165       * Gets the value of a field but first loads it if not done so already.
 166       *
 167       * @since 1.20
 168       * @deprecated since 1.22
 169       *
 170       * @param string $name
 171       *
 172       * @return mixed
 173       */
 174  	public function loadAndGetField( $name ) {
 175          if ( !$this->hasField( $name ) ) {
 176              $this->loadFields( array( $name ) );
 177          }
 178  
 179          return $this->getField( $name );
 180      }
 181  
 182      /**
 183       * Remove a field.
 184       *
 185       * @since 1.20
 186       *
 187       * @param string $name
 188       */
 189  	public function removeField( $name ) {
 190          unset( $this->fields[$name] );
 191      }
 192  
 193      /**
 194       * Returns the objects database id.
 195       *
 196       * @since 1.20
 197       *
 198       * @return int|null
 199       */
 200  	public function getId() {
 201          return $this->getField( 'id' );
 202      }
 203  
 204      /**
 205       * Sets the objects database id.
 206       *
 207       * @since 1.20
 208       *
 209       * @param int|null $id
 210       */
 211  	public function setId( $id ) {
 212          $this->setField( 'id', $id );
 213      }
 214  
 215      /**
 216       * Gets if a certain field is set.
 217       *
 218       * @since 1.20
 219       *
 220       * @param string $name
 221       *
 222       * @return bool
 223       */
 224  	public function hasField( $name ) {
 225          return array_key_exists( $name, $this->fields );
 226      }
 227  
 228      /**
 229       * Gets if the id field is set.
 230       *
 231       * @since 1.20
 232       *
 233       * @return bool
 234       */
 235  	public function hasIdField() {
 236          return $this->hasField( 'id' ) && !is_null( $this->getField( 'id' ) );
 237      }
 238  
 239      /**
 240       * Gets the fields => values to write to the table.
 241       *
 242       * @since 1.20
 243       * @deprecated since 1.22
 244       *
 245       * @return array
 246       */
 247  	protected function getWriteValues() {
 248          $values = array();
 249  
 250          foreach ( $this->table->getFields() as $name => $type ) {
 251              if ( array_key_exists( $name, $this->fields ) ) {
 252                  $value = $this->fields[$name];
 253  
 254                  // Skip null id fields so that the DBMS can set the default.
 255                  if ( $name === 'id' && is_null( $value ) ) {
 256                      continue;
 257                  }
 258  
 259                  switch ( $type ) {
 260                      case 'array':
 261                          $value = (array)$value;
 262                      // fall-through!
 263                      case 'blob':
 264                          $value = serialize( $value );
 265                      // fall-through!
 266                  }
 267  
 268                  $values[$this->table->getPrefixedField( $name )] = $value;
 269              }
 270          }
 271  
 272          return $values;
 273      }
 274  
 275      /**
 276       * Sets multiple fields.
 277       *
 278       * @since 1.20
 279       *
 280       * @param array $fields The fields to set
 281       * @param bool $override Override already set fields with the provided values?
 282       */
 283  	public function setFields( array $fields, $override = true ) {
 284          foreach ( $fields as $name => $value ) {
 285              if ( $override || !$this->hasField( $name ) ) {
 286                  $this->setField( $name, $value );
 287              }
 288          }
 289      }
 290  
 291      /**
 292       * Serializes the object to an associative array which
 293       * can then easily be converted into JSON or similar.
 294       *
 295       * @since 1.20
 296       *
 297       * @param null|array $fields
 298       * @param bool $incNullId
 299       *
 300       * @return array
 301       */
 302  	public function toArray( $fields = null, $incNullId = false ) {
 303          $data = array();
 304          $setFields = array();
 305  
 306          if ( !is_array( $fields ) ) {
 307              $setFields = $this->getSetFieldNames();
 308          } else {
 309              foreach ( $fields as $field ) {
 310                  if ( $this->hasField( $field ) ) {
 311                      $setFields[] = $field;
 312                  }
 313              }
 314          }
 315  
 316          foreach ( $setFields as $field ) {
 317              if ( $incNullId || $field != 'id' || $this->hasIdField() ) {
 318                  $data[$field] = $this->getField( $field );
 319              }
 320          }
 321  
 322          return $data;
 323      }
 324  
 325      /**
 326       * Load the default values, via getDefaults.
 327       *
 328       * @since 1.20
 329       * @deprecated since 1.22
 330       *
 331       * @param bool $override
 332       */
 333  	public function loadDefaults( $override = true ) {
 334          $this->setFields( $this->table->getDefaults(), $override );
 335      }
 336  
 337      /**
 338       * Writes the answer to the database, either updating it
 339       * when it already exists, or inserting it when it doesn't.
 340       *
 341       * @since 1.20
 342       * @deprecated since 1.22 Use IORMTable->updateRow or ->insertRow
 343       *
 344       * @param string|null $functionName
 345       *
 346       * @return bool Success indicator
 347       */
 348  	public function save( $functionName = null ) {
 349          if ( $this->hasIdField() ) {
 350              return $this->table->updateRow( $this, $functionName );
 351          } else {
 352              return $this->table->insertRow( $this, $functionName );
 353          }
 354      }
 355  
 356      /**
 357       * Updates the object in the database.
 358       *
 359       * @since 1.20
 360       * @deprecated since 1.22
 361       *
 362       * @param string|null $functionName
 363       *
 364       * @return bool Success indicator
 365       */
 366  	protected function saveExisting( $functionName = null ) {
 367          $dbw = $this->table->getWriteDbConnection();
 368  
 369          $success = $dbw->update(
 370              $this->table->getName(),
 371              $this->getWriteValues(),
 372              $this->table->getPrefixedValues( $this->getUpdateConditions() ),
 373              is_null( $functionName ) ? __METHOD__ : $functionName
 374          );
 375  
 376          $this->table->releaseConnection( $dbw );
 377  
 378          // DatabaseBase::update does not always return true for success as documented...
 379          return $success !== false;
 380      }
 381  
 382      /**
 383       * Returns the WHERE considtions needed to identify this object so
 384       * it can be updated.
 385       *
 386       * @since 1.20
 387       *
 388       * @return array
 389       */
 390  	protected function getUpdateConditions() {
 391          return array( 'id' => $this->getId() );
 392      }
 393  
 394      /**
 395       * Inserts the object into the database.
 396       *
 397       * @since 1.20
 398       * @deprecated since 1.22
 399       *
 400       * @param string|null $functionName
 401       * @param array|null $options
 402       *
 403       * @return bool Success indicator
 404       */
 405  	protected function insert( $functionName = null, array $options = null ) {
 406          $dbw = $this->table->getWriteDbConnection();
 407  
 408          $success = $dbw->insert(
 409              $this->table->getName(),
 410              $this->getWriteValues(),
 411              is_null( $functionName ) ? __METHOD__ : $functionName,
 412              $options
 413          );
 414  
 415          // DatabaseBase::insert does not always return true for success as documented...
 416          $success = $success !== false;
 417  
 418          if ( $success ) {
 419              $this->setField( 'id', $dbw->insertId() );
 420          }
 421  
 422          $this->table->releaseConnection( $dbw );
 423  
 424          return $success;
 425      }
 426  
 427      /**
 428       * Removes the object from the database.
 429       *
 430       * @since 1.20
 431       * @deprecated since 1.22, use IORMTable->removeRow
 432       *
 433       * @return bool Success indicator
 434       */
 435  	public function remove() {
 436          $this->beforeRemove();
 437  
 438          $success = $this->table->removeRow( $this, __METHOD__ );
 439  
 440          if ( $success ) {
 441              $this->onRemoved();
 442          }
 443  
 444          return $success;
 445      }
 446  
 447      /**
 448       * Gets called before an object is removed from the database.
 449       *
 450       * @since 1.20
 451       * @deprecated since 1.22
 452       */
 453  	protected function beforeRemove() {
 454          $this->loadFields( $this->getBeforeRemoveFields(), false, true );
 455      }
 456  
 457      /**
 458       * Before removal of an object happens, @see beforeRemove gets called.
 459       * This method loads the fields of which the names have been returned by
 460       * this one (or all fields if null is returned). This allows for loading
 461       * info needed after removal to get rid of linked data and the like.
 462       *
 463       * @since 1.20
 464       *
 465       * @return array|null
 466       */
 467  	protected function getBeforeRemoveFields() {
 468          return array();
 469      }
 470  
 471      /**
 472       * Gets called after successful removal.
 473       * Can be overridden to get rid of linked data.
 474       *
 475       * @since 1.20
 476       * @deprecated since 1.22
 477       */
 478  	protected function onRemoved() {
 479          $this->setField( 'id', null );
 480      }
 481  
 482      /**
 483       * Return the names and values of the fields.
 484       *
 485       * @since 1.20
 486       *
 487       * @return array
 488       */
 489  	public function getFields() {
 490          return $this->fields;
 491      }
 492  
 493      /**
 494       * Return the names of the fields.
 495       *
 496       * @since 1.20
 497       *
 498       * @return array
 499       */
 500  	public function getSetFieldNames() {
 501          return array_keys( $this->fields );
 502      }
 503  
 504      /**
 505       * Sets the value of a field.
 506       * Strings can be provided for other types,
 507       * so this method can be called from unserialization handlers.
 508       *
 509       * @since 1.20
 510       *
 511       * @param string $name
 512       * @param mixed $value
 513       *
 514       * @throws MWException
 515       */
 516  	public function setField( $name, $value ) {
 517          $this->fields[$name] = $value;
 518      }
 519  
 520      /**
 521       * Add an amount (can be negative) to the specified field (needs to be numeric).
 522       *
 523       * @since 1.20
 524       * @deprecated since 1.22, use IORMTable->addToField
 525       *
 526       * @param string $field
 527       * @param int $amount
 528       *
 529       * @return bool Success indicator
 530       */
 531  	public function addToField( $field, $amount ) {
 532          return $this->table->addToField( $this->getUpdateConditions(), $field, $amount );
 533      }
 534  
 535      /**
 536       * Return the names of the fields.
 537       *
 538       * @since 1.20
 539       * @deprecated since 1.22
 540       *
 541       * @return array
 542       */
 543  	public function getFieldNames() {
 544          return array_keys( $this->table->getFields() );
 545      }
 546  
 547      /**
 548       * Computes and updates the values of the summary fields.
 549       *
 550       * @since 1.20
 551       * @deprecated since 1.22
 552       *
 553       * @param array|string|null $summaryFields
 554       */
 555  	public function loadSummaryFields( $summaryFields = null ) {
 556      }
 557  
 558      /**
 559       * Sets the value for the @see $updateSummaries field.
 560       *
 561       * @since 1.20
 562       * @deprecated since 1.22
 563       *
 564       * @param bool $update
 565       */
 566  	public function setUpdateSummaries( $update ) {
 567          $this->updateSummaries = $update;
 568      }
 569  
 570      /**
 571       * Sets the value for the @see $inSummaryMode field.
 572       *
 573       * @since 1.20
 574       * @deprecated since 1.22
 575       *
 576       * @param bool $summaryMode
 577       */
 578  	public function setSummaryMode( $summaryMode ) {
 579          $this->inSummaryMode = $summaryMode;
 580      }
 581  
 582      /**
 583       * Returns the table this IORMRow is a row in.
 584       *
 585       * @since 1.20
 586       * @deprecated since 1.22
 587       *
 588       * @return IORMTable
 589       */
 590  	public function getTable() {
 591          return $this->table;
 592      }
 593  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1