Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 47 |
|
0.00% |
0 / 10 |
CRAP | |
0.00% |
0 / 1 |
FlowRevisionsDb | |
0.00% |
0 / 47 |
|
0.00% |
0 / 10 |
306 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setAssociation | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getImportedId | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
30 | |||
save | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
rollback | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getCollectionId | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
6 | |||
getObjectRevision | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getUserTuple | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
getUser | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
getUUIDRange | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace Flow\Import\SourceStore; |
4 | |
5 | use Flow\Import\IImportHeader; |
6 | use Flow\Import\IImportObject; |
7 | use Flow\Import\IImportPost; |
8 | use Flow\Import\IImportSummary; |
9 | use Flow\Import\IImportTopic; |
10 | use Flow\Import\IObjectRevision; |
11 | use Flow\Import\IRevisionableObject; |
12 | use Flow\Model\UserTuple; |
13 | use Flow\Model\UUID; |
14 | use MediaWiki\User\User; |
15 | use MediaWiki\Utils\MWTimestamp; |
16 | use Wikimedia\IPUtils; |
17 | use Wikimedia\Rdbms\IReadableDatabase; |
18 | use Wikimedia\Timestamp\TimestampException; |
19 | |
20 | /** |
21 | * Unlike other source stores, this doesn't really "store" anything. This just |
22 | * does a lookup for certain types of objects to the database to figure out if |
23 | * they have already been imported. |
24 | * |
25 | * This is less versatile than other source stores (you can't just throw |
26 | * anything at it, it's tied to a specific schema and throwing new objects at it |
27 | * will prompt changes in here) but it's more reliable (if the source store is |
28 | * lost, it can use the "result" of a previous import) |
29 | */ |
30 | class FlowRevisionsDb implements SourceStoreInterface { |
31 | /** |
32 | * @var IReadableDatabase |
33 | */ |
34 | protected $dbr; |
35 | |
36 | public function __construct( IReadableDatabase $dbr ) { |
37 | $this->dbr = $dbr; |
38 | } |
39 | |
40 | public function setAssociation( UUID $objectId, $importSourceKey ) { |
41 | return ''; |
42 | } |
43 | |
44 | public function getImportedId( IImportObject $object ) { |
45 | if ( $object instanceof IImportHeader ) { |
46 | $conds = [ 'rev_type' => 'header' ]; |
47 | } elseif ( $object instanceof IImportSummary ) { |
48 | $conds = [ 'rev_type' => 'post-summary' ]; |
49 | } elseif ( $object instanceof IImportTopic ) { |
50 | $conds = [ 'rev_type' => 'post', 'tree_parent_id' => null ]; |
51 | } elseif ( $object instanceof IImportPost ) { |
52 | $conds = [ 'rev_type' => 'post', $this->dbr->expr( 'tree_parent_id', '!=', null ) ]; |
53 | } else { |
54 | throw new Exception( 'Import object of type ' . get_class( $object ) . ' not supported.' ); |
55 | } |
56 | |
57 | $revision = $this->getObjectRevision( $object ); |
58 | return $this->getCollectionId( $revision->getTimestamp(), $revision->getAuthor(), $conds ); |
59 | } |
60 | |
61 | public function save() { |
62 | } |
63 | |
64 | public function rollback() { |
65 | } |
66 | |
67 | /** |
68 | * @param string $timestamp |
69 | * @param string $author |
70 | * @param array $conds |
71 | * @return bool|UUID |
72 | * @throws Exception |
73 | * @throws \Wikimedia\Rdbms\DBUnexpectedError |
74 | * @throws \Flow\Exception\FlowException |
75 | * @throws \Flow\Exception\InvalidInputException |
76 | */ |
77 | protected function getCollectionId( $timestamp, $author, array $conds = [] ) { |
78 | $range = $this->getUUIDRange( new MWTimestamp( $timestamp ) ); |
79 | $tuple = $this->getUserTuple( $author ); |
80 | |
81 | // flow_revision will LEFT JOIN against flow_tree_revision, meaning that |
82 | // we'll also have info about the parent; or it can just be ignored if |
83 | // there is no parent |
84 | $rev_type_id = $this->dbr->newSelectQueryBuilder() |
85 | ->select( 'rev_type_id' ) |
86 | ->from( 'flow_revision' ) |
87 | ->leftJoin( 'flow_tree_revision', null, 'tree_rev_descendant_id = rev_type_id' ) |
88 | ->where( [ |
89 | $this->dbr->expr( 'rev_type_id', '>=', $range[0]->getBinary() ), |
90 | $this->dbr->expr( 'rev_type_id', '<', $range[1]->getBinary() ), |
91 | ] ) |
92 | ->andWhere( $tuple->toArray( 'rev_user_' ) ) |
93 | ->andWhere( $conds ) |
94 | ->caller( __METHOD__ ) |
95 | ->fetchField(); |
96 | |
97 | if ( $rev_type_id === false ) { |
98 | return false; |
99 | } |
100 | |
101 | return UUID::create( $rev_type_id ); |
102 | } |
103 | |
104 | /** |
105 | * @param IRevisionableObject $object |
106 | * @return IObjectRevision |
107 | */ |
108 | protected function getObjectRevision( IRevisionableObject $object ) { |
109 | $revisions = $object->getRevisions(); |
110 | $revisions->rewind(); |
111 | return $revisions->current(); |
112 | } |
113 | |
114 | /** |
115 | * @param string $name |
116 | * @return UserTuple |
117 | * @throws Exception |
118 | */ |
119 | protected function getUserTuple( $name ) { |
120 | $user = $this->getUser( $name ); |
121 | if ( $user === false ) { |
122 | throw new Exception( 'Invalid author: ' . $name ); |
123 | } |
124 | return UserTuple::newFromUser( $user ); |
125 | } |
126 | |
127 | /** |
128 | * @param string $name |
129 | * @return bool|User |
130 | */ |
131 | protected function getUser( $name ) { |
132 | if ( IPUtils::isIPAddress( $name ) ) { |
133 | return User::newFromName( $name, false ); |
134 | } |
135 | |
136 | return User::newFromName( $name ); |
137 | } |
138 | |
139 | /** |
140 | * Gets the min <= ? < max boundaries for a UUID that has a given |
141 | * timestamp. Returns an array where [0] = min & [1] is max. |
142 | * |
143 | * @param MWTimestamp $timestamp |
144 | * @return UUID[] [min, max] |
145 | * @throws TimestampException |
146 | */ |
147 | protected function getUUIDRange( MWTimestamp $timestamp ) { |
148 | return [ |
149 | UUID::getComparisonUUID( (int)$timestamp->getTimestamp( TS_UNIX ) ), |
150 | UUID::getComparisonUUID( (int)$timestamp->getTimestamp( TS_UNIX ) + 1 ), |
151 | ]; |
152 | } |
153 | } |