MediaWiki master
ExternalStoreFactory.php
Go to the documentation of this file.
1<?php
2
4use Psr\Log\LoggerAwareInterface;
5use Psr\Log\LoggerInterface;
6use Psr\Log\NullLogger;
7
14class ExternalStoreFactory implements LoggerAwareInterface {
16 private $protocols;
18 private $writeBaseUrls;
20 private $localDomainId;
22 private $logger;
24 private $stores = [];
25
32 public function __construct(
33 array $externalStores,
34 array $defaultStores,
35 string $localDomainId,
36 ?LoggerInterface $logger = null
37 ) {
38 $this->protocols = array_map( 'strtolower', $externalStores );
39 $this->writeBaseUrls = $defaultStores;
40 $this->localDomainId = $localDomainId;
41 $this->logger = $logger ?: new NullLogger();
42 }
43
44 public function setLogger( LoggerInterface $logger ) {
45 $this->logger = $logger;
46 }
47
52 public function getProtocols() {
53 return $this->protocols;
54 }
55
60 public function getWriteBaseUrls() {
61 return $this->writeBaseUrls;
62 }
63
76 public function getStore( $proto, array $params = [] ) {
77 $cacheKey = $proto . ':' . json_encode( $params );
78 if ( isset( $this->stores[$cacheKey] ) ) {
79 return $this->stores[$cacheKey];
80 }
81 $protoLowercase = strtolower( $proto ); // normalize
82 if ( !$this->protocols || !in_array( $protoLowercase, $this->protocols ) ) {
83 throw new ExternalStoreException( "Protocol '$proto' is not enabled." );
84 }
85
86 if ( $protoLowercase === 'db' ) {
87 $class = 'ExternalStoreDB';
88 } else {
89 $class = 'ExternalStore' . ucfirst( $proto );
90 }
91 if ( isset( $params['wiki'] ) ) {
92 $params += [ 'domain' => $params['wiki'] ]; // b/c
93 }
94 if ( !isset( $params['domain'] ) || $params['domain'] === false ) {
95 $params['domain'] = $this->localDomainId; // default
96 $params['isDomainImplicit'] = true; // b/c for ExternalStoreDB
97 }
98 // @TODO: ideally, this class should not hardcode what classes need what backend factory
99 // objects. For now, inject the factory instances into __construct() for those that do.
100 if ( $protoLowercase === 'db' ) {
101 $params['lbFactory'] = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
102 } elseif ( $protoLowercase === 'mwstore' ) {
103 $params['fbGroup'] = MediaWikiServices::getInstance()->getFileBackendGroup();
104 }
105 $params['logger'] = $this->logger;
106
107 if ( !class_exists( $class ) ) {
108 throw new ExternalStoreException( "Class '$class' is not defined." );
109 }
110
111 // Any custom modules should be added to $wgAutoLoadClasses for on-demand loading
112 $this->stores[$cacheKey] = new $class( $params );
113 return $this->stores[$cacheKey];
114 }
115
129 public function getStoreForUrl( $url, array $params = [] ) {
130 [ $proto, $path ] = self::splitStorageUrl( $url );
131 if ( $path == '' ) { // bad URL
132 throw new ExternalStoreException( "Invalid URL '$url'" );
133 }
134
135 return $this->getStore( $proto, $params );
136 }
137
146 public function getStoreLocationFromUrl( $url ) {
147 [ , $location ] = self::splitStorageUrl( $url );
148 if ( $location == '' ) { // bad URL
149 throw new ExternalStoreException( "Invalid URL '$url'" );
150 }
151
152 return $location;
153 }
154
161 public function getUrlsByProtocol( array $urls ) {
162 $urlsByProtocol = [];
163 foreach ( $urls as $url ) {
164 [ $proto, ] = self::splitStorageUrl( $url );
165 $urlsByProtocol[$proto][] = $url;
166 }
167
168 return $urlsByProtocol;
169 }
170
176 private static function splitStorageUrl( $storeUrl ) {
177 $parts = explode( '://', $storeUrl );
178 if ( count( $parts ) != 2 || $parts[0] === '' || $parts[1] === '' ) {
179 throw new ExternalStoreException( "Invalid storage URL '$storeUrl'" );
180 }
181
182 return $parts;
183 }
184}
setLogger(LoggerInterface $logger)
getStore( $proto, array $params=[])
Get an external store object of the given type, with the given parameters.
__construct(array $externalStores, array $defaultStores, string $localDomainId, ?LoggerInterface $logger=null)
getStoreForUrl( $url, array $params=[])
Get the ExternalStoreMedium for a given URL.
getStoreLocationFromUrl( $url)
Get the location within the appropriate store for a given a URL.
Base class for external storage.
Service locator for MediaWiki core services.