Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.04% covered (success)
98.04%
50 / 51
80.00% covered (warning)
80.00%
4 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
RevisionStoreFactory
98.04% covered (success)
98.04%
50 / 51
80.00% covered (warning)
80.00%
4 / 5
9
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
1
 getRevisionStore
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getRevisionStoreForImport
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getRevisionStoreForUndelete
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getStore
96.00% covered (success)
96.00%
24 / 25
0.00% covered (danger)
0.00%
0 / 1
5
1<?php
2
3/**
4 * @license GPL-2.0-or-later
5 * Attribution notice: when this file was created, much of its content was taken
6 * from the Revision.php file as present in release 1.30. Refer to the history
7 * of that file for original authorship (that file was removed entirely in 1.37,
8 * but its history can still be found in prior versions of MediaWiki).
9 *
10 * @file
11 */
12
13namespace MediaWiki\Revision;
14
15use MediaWiki\CommentStore\CommentStore;
16use MediaWiki\Content\IContentHandlerFactory;
17use MediaWiki\DAO\WikiAwareEntity;
18use MediaWiki\HookContainer\HookContainer;
19use MediaWiki\Page\PageStoreFactory;
20use MediaWiki\RecentChanges\RecentChangeLookup;
21use MediaWiki\Storage\BlobStoreFactory;
22use MediaWiki\Storage\NameTableStoreFactory;
23use MediaWiki\Title\TitleFactory;
24use MediaWiki\User\ActorStore;
25use MediaWiki\User\ActorStoreFactory;
26use MediaWiki\WikiMap\WikiMap;
27use Psr\Log\LoggerInterface;
28use Wikimedia\Assert\Assert;
29use Wikimedia\ObjectCache\BagOStuff;
30use Wikimedia\ObjectCache\WANObjectCache;
31use Wikimedia\Rdbms\ILBFactory;
32
33/**
34 * Factory service for RevisionStore instances. This allows RevisionStores to be created for
35 * cross-wiki access.
36 *
37 * @warning Beware compatibility issues with schema migration in the context of cross-wiki access!
38 * This class assumes that all wikis are at compatible migration stages for all relevant schemas.
39 * Relevant schemas are: revision storage (MCR), the revision comment table, and the actor table.
40 * Migration stages are compatible as long as a) there are no wikis in the cluster that only write
41 * the old schema or b) there are no wikis that read only the new schema.
42 *
43 * @since 1.32
44 */
45class RevisionStoreFactory {
46
47    private BlobStoreFactory $blobStoreFactory;
48    private ILBFactory $dbLoadBalancerFactory;
49    private WANObjectCache $cache;
50    private BagOStuff $localCache;
51    private LoggerInterface $logger;
52    private CommentStore $commentStore;
53    private ActorStoreFactory $actorStoreFactory;
54    private NameTableStoreFactory $nameTables;
55    private SlotRoleRegistry $slotRoleRegistry;
56    private IContentHandlerFactory $contentHandlerFactory;
57    private PageStoreFactory $pageStoreFactory;
58    private TitleFactory $titleFactory;
59    private HookContainer $hookContainer;
60    private RecentChangeLookup $recentChangeLookup;
61
62    public function __construct(
63        ILBFactory $dbLoadBalancerFactory,
64        BlobStoreFactory $blobStoreFactory,
65        NameTableStoreFactory $nameTables,
66        SlotRoleRegistry $slotRoleRegistry,
67        WANObjectCache $cache,
68        BagOStuff $localCache,
69        CommentStore $commentStore,
70        ActorStoreFactory $actorStoreFactory,
71        LoggerInterface $logger,
72        IContentHandlerFactory $contentHandlerFactory,
73        PageStoreFactory $pageStoreFactory,
74        TitleFactory $titleFactory,
75        HookContainer $hookContainer,
76        RecentChangeLookup $recentChangeLookup
77    ) {
78        $this->dbLoadBalancerFactory = $dbLoadBalancerFactory;
79        $this->blobStoreFactory = $blobStoreFactory;
80        $this->slotRoleRegistry = $slotRoleRegistry;
81        $this->nameTables = $nameTables;
82        $this->cache = $cache;
83        $this->localCache = $localCache;
84        $this->commentStore = $commentStore;
85        $this->actorStoreFactory = $actorStoreFactory;
86        $this->logger = $logger;
87        $this->contentHandlerFactory = $contentHandlerFactory;
88        $this->pageStoreFactory = $pageStoreFactory;
89        $this->titleFactory = $titleFactory;
90        $this->hookContainer = $hookContainer;
91        $this->recentChangeLookup = $recentChangeLookup;
92    }
93
94    /**
95     * @since 1.32
96     *
97     * @param false|string $dbDomain DB domain of the relevant wiki or false for the current one
98     *
99     * @return RevisionStore for the given wikiId with all necessary services
100     */
101    public function getRevisionStore( $dbDomain = false ): RevisionStore {
102        return $this->getStore(
103            $dbDomain,
104            $this->actorStoreFactory->getActorStore( $dbDomain )
105        );
106    }
107
108    /**
109     * @since 1.42
110     *
111     * @param false|string $dbDomain DB domain of the relevant wiki or false for the current one
112     *
113     * @return RevisionStore for the given wikiId with all necessary services
114     */
115    public function getRevisionStoreForImport( $dbDomain = false ): RevisionStore {
116        return $this->getStore(
117            $dbDomain,
118            $this->actorStoreFactory->getActorStoreForImport( $dbDomain )
119        );
120    }
121
122    /**
123     * @since 1.43
124     *
125     * @param false|string $dbDomain DB domain of the relevant wiki or false for the current one
126     *
127     * @return RevisionStore for the given wikiId with all necessary services
128     */
129    public function getRevisionStoreForUndelete( $dbDomain = false ): RevisionStore {
130        return $this->getStore(
131            $dbDomain,
132            $this->actorStoreFactory->getActorStoreForUndelete( $dbDomain )
133        );
134    }
135
136    /**
137     * @param false|string $dbDomain
138     * @param ActorStore $actorStore
139     *
140     * @return RevisionStore
141     */
142    private function getStore( $dbDomain, ActorStore $actorStore ) {
143        Assert::parameterType( [ 'string', 'false' ], $dbDomain, '$dbDomain' );
144        if (
145            // FIXME: We can't normalize the domain in tests, as RevisionStoreDbTest relies on this behaviour to test
146            // cross-wikiness, in absence of a better way (T261848).
147            !defined( 'MW_PHPUNIT_TEST' ) &&
148            is_string( $dbDomain ) &&
149            (
150                $this->dbLoadBalancerFactory->getLocalDomainID() === $dbDomain ||
151                WikiMap::getWikiIdFromDbDomain( $this->dbLoadBalancerFactory->getLocalDomainID() ) === $dbDomain
152            )
153        ) {
154            $dbDomain = WikiAwareEntity::LOCAL;
155        }
156
157        $store = new RevisionStore(
158            $this->dbLoadBalancerFactory->getMainLB( $dbDomain ),
159            $this->blobStoreFactory->newSqlBlobStore( $dbDomain ),
160            $this->cache, // Pass cache local to wiki; Leave cache sharing to RevisionStore.
161            $this->localCache,
162            $this->commentStore,
163            $this->nameTables->getContentModels( $dbDomain ),
164            $this->nameTables->getSlotRoles( $dbDomain ),
165            $this->slotRoleRegistry,
166            $actorStore,
167            $this->contentHandlerFactory,
168            $this->pageStoreFactory->getPageStore( $dbDomain ),
169            $this->titleFactory,
170            $this->hookContainer,
171            $this->recentChangeLookup,
172            $dbDomain
173        );
174
175        $store->setLogger( $this->logger );
176
177        return $store;
178    }
179}