1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Wikibase\Api\Service; |
4
|
|
|
|
5
|
|
|
use Deserializers\Deserializer; |
6
|
|
|
use InvalidArgumentException; |
7
|
|
|
use Mediawiki\Api\MediawikiApi; |
8
|
|
|
use Mediawiki\Api\SimpleRequest; |
9
|
|
|
use Mediawiki\DataModel\PageIdentifier; |
10
|
|
|
use Mediawiki\DataModel\Revision; |
11
|
|
|
use Mediawiki\DataModel\Revisions; |
12
|
|
|
use RuntimeException; |
13
|
|
|
use Wikibase\DataModel\Entity\EntityId; |
14
|
|
|
use Wikibase\DataModel\Entity\Item; |
15
|
|
|
use Wikibase\DataModel\Entity\Property; |
16
|
|
|
use Wikibase\DataModel\ItemContent; |
17
|
|
|
use Wikibase\DataModel\PropertyContent; |
18
|
|
|
use Wikibase\DataModel\SiteLink; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @access private |
22
|
|
|
* |
23
|
|
|
* @author Addshore |
24
|
|
|
*/ |
25
|
|
|
class RevisionsGetter { |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var MediawikiApi |
29
|
|
|
*/ |
30
|
|
|
protected $api; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var Deserializer |
34
|
|
|
*/ |
35
|
|
|
private $entityDeserializer; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @param MediawikiApi $api |
39
|
|
|
* @param Deserializer $entityDeserializer |
40
|
|
|
*/ |
41
|
|
|
public function __construct( MediawikiApi $api, Deserializer $entityDeserializer ) { |
42
|
|
|
$this->api = $api; |
43
|
|
|
$this->entityDeserializer = $entityDeserializer; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* Get revisions for the entities identified using as few requests as possible. |
48
|
|
|
* |
49
|
|
|
* @param array $identifyingInfoArray Can include the following: |
50
|
|
|
* EntityId EntityId objects |
51
|
|
|
* SiteLink SiteLink objects |
52
|
|
|
* string Serialized entity ids (these are not validated before passing to the api) |
53
|
|
|
* |
54
|
|
|
* @since 0.4 |
55
|
|
|
* |
56
|
|
|
* @return Revisions |
57
|
|
|
*/ |
58
|
|
|
public function getRevisions( array $identifyingInfoArray ) { |
59
|
|
|
$entityIdStrings = []; |
60
|
|
|
$siteLinksStringMapping = []; |
61
|
|
|
|
62
|
|
|
foreach ( $identifyingInfoArray as $someInfo ) { |
63
|
|
|
if ( $someInfo instanceof EntityId ) { |
64
|
|
|
$entityIdStrings[] = $someInfo->getSerialization(); |
65
|
|
|
} elseif ( $someInfo instanceof SiteLink ) { |
66
|
|
|
$siteLinksStringMapping[ $someInfo->getSiteId() ][] = $someInfo->getPageName(); |
67
|
|
|
} elseif ( is_string( $someInfo ) ) { |
68
|
|
|
$entityIdStrings[] = $someInfo; |
69
|
|
|
} else { |
70
|
|
|
throw new InvalidArgumentException( 'Unexpected $identifyingInfoArray in RevisionsGetter::getRevisions' ); |
71
|
|
|
} |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
// The below makes as few requests as possible to get the Revisions required! |
75
|
|
|
$gotRevisionsFromIds = false; |
76
|
|
|
$revisions = new Revisions(); |
77
|
|
|
if ( !empty( $siteLinksStringMapping ) ) { |
78
|
|
|
foreach ( $siteLinksStringMapping as $site => $siteLinkStrings ) { |
79
|
|
|
$params = [ 'sites' => $site ]; |
80
|
|
|
if ( !$gotRevisionsFromIds && !empty( $entityIdStrings ) ) { |
81
|
|
|
$params['ids'] = implode( '|', $entityIdStrings ); |
82
|
|
|
$gotRevisionsFromIds = true; |
83
|
|
|
} |
84
|
|
|
$params['titles'] = implode( '|', $siteLinkStrings ); |
85
|
|
|
$result = $this->api->getRequest( new SimpleRequest( 'wbgetentities', $params ) ); |
86
|
|
|
$resultRevisions = $this->newRevisionsFromResult( $result['entities'] ); |
87
|
|
|
$revisions->addRevisions( $resultRevisions ); |
88
|
|
|
|
89
|
|
|
} |
90
|
|
|
} else { |
91
|
|
|
$params = [ 'ids' => implode( '|', $entityIdStrings ) ]; |
92
|
|
|
$result = $this->api->getRequest( new SimpleRequest( 'wbgetentities', $params ) ); |
93
|
|
|
$resultRevisions = $this->newRevisionsFromResult( $result['entities'] ); |
94
|
|
|
$revisions->addRevisions( $resultRevisions ); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return $revisions; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* @param array $entitiesResult |
102
|
|
|
* @return Revisions |
103
|
|
|
* @todo this could be factored into a different class? |
104
|
|
|
*/ |
105
|
|
|
private function newRevisionsFromResult( array $entitiesResult ) { |
106
|
|
|
$revisions = new Revisions(); |
107
|
|
|
foreach ( $entitiesResult as $entityResult ) { |
108
|
|
|
if ( array_key_exists( 'missing', $entityResult ) ) { |
109
|
|
|
continue; |
110
|
|
|
} |
111
|
|
|
$revisions->addRevision( new Revision( |
112
|
|
|
$this->getContentFromEntity( $this->entityDeserializer->deserialize( $entityResult ) ), |
113
|
|
|
new PageIdentifier( null, $entityResult['pageid'] ), |
114
|
|
|
$entityResult['lastrevid'], |
115
|
|
|
null, |
116
|
|
|
null, |
117
|
|
|
$entityResult['modified'] |
118
|
|
|
) ); |
119
|
|
|
} |
120
|
|
|
return $revisions; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* @param Item|Property $entity |
125
|
|
|
* |
126
|
|
|
* @throws RuntimeException |
127
|
|
|
* @return ItemContent|PropertyContent |
128
|
|
|
* @todo this could be factored into a different class? |
129
|
|
|
*/ |
130
|
|
View Code Duplication |
private function getContentFromEntity( $entity ) { |
|
|
|
|
131
|
|
|
switch ( $entity->getType() ) { |
132
|
|
|
case Item::ENTITY_TYPE: |
133
|
|
|
return new ItemContent( $entity ); |
|
|
|
|
134
|
|
|
case Property::ENTITY_TYPE: |
135
|
|
|
return new PropertyContent( $entity ); |
|
|
|
|
136
|
|
|
default: |
137
|
|
|
throw new RuntimeException( 'I cant get a content for this type of entity' ); |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
} |
142
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.