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
30 public function __construct(
31 array $externalStores,
32 array $defaultStores,
33 string $localDomainId,
34 LoggerInterface $logger = null
35 ) {
36 $this->protocols = array_map( 'strtolower', $externalStores );
37 $this->writeBaseUrls = $defaultStores;
38 $this->localDomainId = $localDomainId;
39 $this->logger = $logger ?: new NullLogger();
40 }
41
42 public function setLogger( LoggerInterface $logger ) {
43 $this->logger = $logger;
44 }
45
50 public function getProtocols() {
51 return $this->protocols;
52 }
53
58 public function getWriteBaseUrls() {
59 return $this->writeBaseUrls;
60 }
61
74 public function getStore( $proto, array $params = [] ) {
75 $protoLowercase = strtolower( $proto ); // normalize
76 if ( !$this->protocols || !in_array( $protoLowercase, $this->protocols ) ) {
77 throw new ExternalStoreException( "Protocol '$proto' is not enabled." );
78 }
79
80 if ( $protoLowercase === 'db' ) {
81 $class = 'ExternalStoreDB';
82 } else {
83 $class = 'ExternalStore' . ucfirst( $proto );
84 }
85 if ( isset( $params['wiki'] ) ) {
86 $params += [ 'domain' => $params['wiki'] ]; // b/c
87 }
88 if ( !isset( $params['domain'] ) || $params['domain'] === false ) {
89 $params['domain'] = $this->localDomainId; // default
90 $params['isDomainImplicit'] = true; // b/c for ExternalStoreDB
91 }
92 // @TODO: ideally, this class should not hardcode what classes need what backend factory
93 // objects. For now, inject the factory instances into __construct() for those that do.
94 if ( $protoLowercase === 'db' ) {
95 $params['lbFactory'] = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
96 } elseif ( $protoLowercase === 'mwstore' ) {
97 $params['fbGroup'] = MediaWikiServices::getInstance()->getFileBackendGroup();
98 }
99 $params['logger'] = $this->logger;
100
101 if ( !class_exists( $class ) ) {
102 throw new ExternalStoreException( "Class '$class' is not defined." );
103 }
104
105 // Any custom modules should be added to $wgAutoLoadClasses for on-demand loading
106 return new $class( $params );
107 }
108
122 public function getStoreForUrl( $url, array $params = [] ) {
123 [ $proto, $path ] = self::splitStorageUrl( $url );
124 if ( $path == '' ) { // bad URL
125 throw new ExternalStoreException( "Invalid URL '$url'" );
126 }
127
128 return $this->getStore( $proto, $params );
129 }
130
139 public function getStoreLocationFromUrl( $url ) {
140 [ , $location ] = self::splitStorageUrl( $url );
141 if ( $location == '' ) { // bad URL
142 throw new ExternalStoreException( "Invalid URL '$url'" );
143 }
144
145 return $location;
146 }
147
154 public function getUrlsByProtocol( array $urls ) {
155 $urlsByProtocol = [];
156 foreach ( $urls as $url ) {
157 [ $proto, ] = self::splitStorageUrl( $url );
158 $urlsByProtocol[$proto][] = $url;
159 }
160
161 return $urlsByProtocol;
162 }
163
169 private static function splitStorageUrl( $storeUrl ) {
170 $parts = explode( '://', $storeUrl );
171 if ( count( $parts ) != 2 || $parts[0] === '' || $parts[1] === '' ) {
172 throw new ExternalStoreException( "Invalid storage URL '$storeUrl'" );
173 }
174
175 return $parts;
176 }
177}
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.