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