Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.32% covered (success)
90.32%
28 / 31
77.78% covered (warning)
77.78%
7 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
ActorStoreFactory
90.32% covered (success)
90.32%
28 / 31
77.78% covered (warning)
77.78%
7 / 9
18.29
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 getActorNormalization
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActorNormalizationForImport
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getActorStore
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActorStoreForImport
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getActorStoreForUndelete
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStore
89.47% covered (warning)
89.47%
17 / 19
0.00% covered (danger)
0.00%
0 / 1
8.07
 getUserIdentityLookup
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLoadBalancerForTable
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 */
6
7namespace MediaWiki\User;
8
9use MediaWiki\Block\HideUserUtils;
10use MediaWiki\Config\ServiceOptions;
11use MediaWiki\DAO\WikiAwareEntity;
12use MediaWiki\MainConfigNames;
13use MediaWiki\User\TempUser\TempUserConfig;
14use MediaWiki\WikiMap\WikiMap;
15use Psr\Log\LoggerInterface;
16use Wikimedia\Rdbms\ILBFactory;
17use Wikimedia\Rdbms\ILoadBalancer;
18
19/**
20 * ActorStore factory for any wiki domain.
21 *
22 * @since 1.36
23 * @ingroup User
24 */
25class ActorStoreFactory {
26
27    /** @internal */
28    public const CONSTRUCTOR_OPTIONS = [
29        MainConfigNames::SharedDB,
30        MainConfigNames::SharedTables,
31    ];
32
33    /** @var string|false */
34    private $sharedDB;
35
36    /** @var string[] */
37    private $sharedTables;
38
39    /** @var ActorStore[] */
40    private array $storeCache = [];
41
42    public function __construct(
43        ServiceOptions $options,
44        private readonly ILBFactory $loadBalancerFactory,
45        private readonly UserNameUtils $userNameUtils,
46        private readonly TempUserConfig $tempUserConfig,
47        private readonly LoggerInterface $logger,
48        private readonly HideUserUtils $hideUserUtils,
49    ) {
50        $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
51        $this->sharedDB = $options->get( MainConfigNames::SharedDB );
52        $this->sharedTables = $options->get( MainConfigNames::SharedTables );
53    }
54
55    /**
56     * @param string|false $wikiId
57     * @return ActorNormalization
58     */
59    public function getActorNormalization( $wikiId = WikiAwareEntity::LOCAL ): ActorNormalization {
60        return $this->getActorStore( $wikiId );
61    }
62
63    /**
64     * @since 1.42
65     * @param string|false $wikiId
66     * @return ActorNormalization
67     */
68    public function getActorNormalizationForImport(
69        $wikiId = WikiAwareEntity::LOCAL
70    ): ActorNormalization {
71        return $this->getActorStoreForImport( $wikiId );
72    }
73
74    /**
75     * @param string|false $wikiId
76     * @return ActorStore
77     */
78    public function getActorStore( $wikiId = WikiAwareEntity::LOCAL ): ActorStore {
79        return $this->getStore( $wikiId, false );
80    }
81
82    /**
83     * @since 1.42
84     * @param string|false $wikiId
85     * @return ActorStore
86     */
87    public function getActorStoreForImport( $wikiId = WikiAwareEntity::LOCAL ): ActorStore {
88        return $this->getStore( $wikiId, true );
89    }
90
91    /**
92     * @since 1.43
93     * @param string|false $wikiId
94     * @return ActorStore
95     */
96    public function getActorStoreForUndelete( $wikiId = WikiAwareEntity::LOCAL ): ActorStore {
97        return $this->getStore( $wikiId, true );
98    }
99
100    /**
101     * @param string|false $wikiId
102     * @param bool $allowingIpActorCreation
103     * @return ActorStore
104     */
105    private function getStore( $wikiId, bool $allowingIpActorCreation ): ActorStore {
106        // During the transition from User, we still have old User objects
107        // representing users from a different wiki, so we still have IDatabase::getDomainId
108        // passed as $wikiId, so we need to remap it back to LOCAL.
109        if (
110            is_string( $wikiId ) &&
111            (
112                $this->loadBalancerFactory->getLocalDomainID() === $wikiId ||
113                WikiMap::getWikiIdFromDbDomain( $this->loadBalancerFactory->getLocalDomainID() ) === $wikiId
114            )
115        ) {
116            $wikiId = WikiAwareEntity::LOCAL;
117        }
118
119        $storeCacheKey = ( $allowingIpActorCreation ? 'allowing-ip-actor-creation-' : '' ) .
120            ( $wikiId === WikiAwareEntity::LOCAL ? 'LOCAL' : $wikiId );
121
122        if ( !isset( $this->storeCache[$storeCacheKey] ) ) {
123            $store = new ActorStore(
124                $this->getLoadBalancerForTable( 'actor', $wikiId ),
125                $this->userNameUtils,
126                $this->tempUserConfig,
127                $this->logger,
128                $this->hideUserUtils,
129                $wikiId
130            );
131            if ( $allowingIpActorCreation ) {
132                $store->setAllowCreateIpActors( true );
133            }
134            $this->storeCache[$storeCacheKey] = $store;
135        }
136        return $this->storeCache[$storeCacheKey];
137    }
138
139    /**
140     * @param string|false $wikiId
141     * @return UserIdentityLookup
142     */
143    public function getUserIdentityLookup(
144        $wikiId = WikiAwareEntity::LOCAL
145    ): UserIdentityLookup {
146        return $this->getActorStore( $wikiId );
147    }
148
149    /**
150     * Returns a load balancer for the database that has the $table
151     * for the given $wikiId.
152     *
153     * @param string $table
154     * @param string|false $wikiId
155     * @return ILoadBalancer
156     */
157    private function getLoadBalancerForTable(
158        string $table,
159        $wikiId = WikiAwareEntity::LOCAL
160    ): ILoadBalancer {
161        if ( $this->sharedDB && in_array( $table, $this->sharedTables ) ) {
162            // The main LB is already properly set up for shared databases early in Setup.php
163            return $this->loadBalancerFactory->getMainLB();
164        }
165        return $this->loadBalancerFactory->getMainLB( $wikiId );
166    }
167}