| Current File : /home/jvzmxxx/wiki1/extensions/Flow/includes/Import/SourceStore/FlowRevisionsDb.php |
<?php
namespace Flow\Import\SourceStore;
use DatabaseBase;
use IP;
use Flow\Import\IImportHeader;
use Flow\Import\IImportObject;
use Flow\Import\IImportPost;
use Flow\Import\IImportSummary;
use Flow\Import\IImportTopic;
use Flow\Import\IObjectRevision;
use Flow\Import\IRevisionableObject;
use Flow\Model\UserTuple;
use Flow\Model\UUID;
use MWTimestamp;
use User;
/**
* Unlike other source stores, this doesn't really "store" anything. This just
* does a lookup for certain types of objects to the database to figure out if
* they have already been imported.
*
* This is less versatile than other source stores (you can't just throw
* anything at it, it's tied to a specific schema and throwing new objects at it
* will prompt changes in here) but it's more reliable (if the source store is
* lost, it can use the "result" of a previous import)
*/
class FlowRevisionsDb implements SourceStoreInterface {
/**
* @var DatabaseBase
*/
protected $dbr;
/**
* @param DatabaseBase $dbr
*/
public function __construct( DatabaseBase $dbr ) {
$this->dbr = $dbr;
}
public function setAssociation( UUID $objectId, $importSourceKey ) {
return '';
}
public function getImportedId( IImportObject $object ) {
if ( $object instanceof IImportHeader ) {
$conds = array( 'rev_type' => 'header' );
} elseif ( $object instanceof IImportSummary ) {
$conds = array( 'rev_type' => 'post-summary' );
} elseif ( $object instanceof IImportTopic ) {
$conds = array( 'rev_type' => 'post', 'tree_parent_id' => null );
} elseif ( $object instanceof IImportPost ) {
$conds = array( 'rev_type' => 'post', 'tree_parent_id IS NOT NULL' );
} else {
throw new Exception( 'Import object of type ' . get_class( $object ) . ' not supported.' );
}
$revision = $this->getObjectRevision( $object );
return $this->getCollectionId( $revision->getTimestamp(), $revision->getAuthor(), $conds );
}
public function save() {
}
public function rollback() {
}
/**
* @param string $timestamp
* @param string $author
* @param array $conds
* @return bool|UUID
* @throws Exception
* @throws \DBUnexpectedError
* @throws \Flow\Exception\FlowException
* @throws \Flow\Exception\InvalidInputException
*/
protected function getCollectionId( $timestamp, $author, array $conds = array() ) {
$range = $this->getUUIDRange( new MWTimestamp( $timestamp ) );
$tuple = $this->getUserTuple( $author );
// flow_revision will LEFT JOIN against flow_tree_revision, meaning that
// we'll also have info about the parent; or it can just be ignored if
// there is no parent
$rows = $this->dbr->select(
array( 'flow_revision', 'flow_tree_revision' ),
array( 'rev_type_id' ),
array_merge(
array(
'rev_type_id >= ' . $this->dbr->addQuotes( $range[0]->getBinary() ),
'rev_type_id < ' . $this->dbr->addQuotes( $range[1]->getBinary() ),
),
$tuple->toArray( 'rev_user_' ),
$conds
),
__METHOD__,
array( 'LIMIT' => 1 ),
array(
'flow_tree_revision' => array(
'LEFT OUTER JOIN',
array( 'tree_rev_descendant_id = rev_type_id' )
),
)
);
if ( $rows->numRows() === 0 ) {
return false;
}
return UUID::create( $rows->fetchObject()->rev_type_id );
}
/**
* @param IRevisionableObject $object
* @return IObjectRevision
*/
protected function getObjectRevision( IRevisionableObject $object ) {
$revisions = $object->getRevisions();
$revisions->rewind();
return $revisions->current();
}
/**
* @param string $name
* @return UserTuple
* @throws Exception
*/
protected function getUserTuple( $name ) {
$user = $this->getUser( $name );
if ( $user === false ) {
throw new Exception( 'Invalid author: ' . $name );
}
return UserTuple::newFromUser( $user );
}
/**
* @param string $name
* @return bool|User
*/
protected function getUser( $name ) {
if ( IP::isIPAddress( $name ) ) {
return User::newFromName( $name, false );
}
return User::newFromName( $name );
}
/**
* Gets the min <= ? < max boundaries for a UUID that has a given
* timestamp. Returns an array where [0] = min & [1] is max.
*
* @param MWTimestamp $timestamp
* @return UUID[] [min, max]
* @throws \TimestampException
*/
protected function getUUIDRange( MWTimestamp $timestamp ) {
return array(
UUID::getComparisonUUID( (int) $timestamp->getTimestamp( TS_UNIX ) ),
UUID::getComparisonUUID( (int) $timestamp->getTimestamp( TS_UNIX ) + 1 ),
);
}
}