MediaWiki  master
ExternalStoreFactory.php
Go to the documentation of this file.
1 <?php
11 
15 class ExternalStoreFactory implements LoggerAwareInterface {
17  private $protocols;
19  private $writeBaseUrls;
21  private $localDomainId;
23  private $logger;
24 
31  public function __construct(
32  array $externalStores,
33  array $defaultStores,
35  LoggerInterface $logger = null
36  ) {
37  Assert::parameterType( 'string', $localDomainId, '$localDomainId' );
38 
39  $this->protocols = array_map( 'strtolower', $externalStores );
40  $this->writeBaseUrls = $defaultStores;
41  $this->localDomainId = $localDomainId;
42  $this->logger = $logger ?: new NullLogger();
43  }
44 
45  public function setLogger( LoggerInterface $logger ) {
46  $this->logger = $logger;
47  }
48 
53  public function getProtocols() {
54  return $this->protocols;
55  }
56 
61  public function getWriteBaseUrls() {
62  return $this->writeBaseUrls;
63  }
64 
77  public function getStore( $proto, array $params = [] ) {
78  $protoLowercase = strtolower( $proto ); // normalize
79  if ( !$this->protocols || !in_array( $protoLowercase, $this->protocols ) ) {
80  throw new ExternalStoreException( "Protocol '$proto' is not enabled." );
81  }
82 
83  $class = 'ExternalStore' . ucfirst( $proto );
84  if ( isset( $params['wiki'] ) ) {
85  $params += [ 'domain' => $params['wiki'] ]; // b/c
86  }
87  if ( !isset( $params['domain'] ) || $params['domain'] === false ) {
88  $params['domain'] = $this->localDomainId; // default
89  $params['isDomainImplicit'] = true; // b/c for ExternalStoreDB
90  }
91  // @TODO: ideally, this class should not hardcode what classes need what backend factory
92  // objects. For now, inject the factory instances into __construct() for those that do.
93  if ( $protoLowercase === 'db' ) {
94  $params['lbFactory'] = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
95  } elseif ( $protoLowercase === 'mwstore' ) {
96  $params['fbGroup'] = MediaWikiServices::getInstance()->getFileBackendGroup();
97  }
98  $params['logger'] = $this->logger;
99 
100  if ( !class_exists( $class ) ) {
101  throw new ExternalStoreException( "Class '$class' is not defined." );
102  }
103 
104  // Any custom modules should be added to $wgAutoLoadClasses for on-demand loading
105  return new $class( $params );
106  }
107 
121  public function getStoreForUrl( $url, array $params = [] ) {
122  list( $proto, $path ) = self::splitStorageUrl( $url );
123  if ( $path == '' ) { // bad URL
124  throw new ExternalStoreException( "Invalid URL '$url'" );
125  }
126 
127  return $this->getStore( $proto, $params );
128  }
129 
138  public function getStoreLocationFromUrl( $url ) {
139  list( , $location ) = self::splitStorageUrl( $url );
140  if ( $location == '' ) { // bad URL
141  throw new ExternalStoreException( "Invalid URL '$url'" );
142  }
143 
144  return $location;
145  }
146 
153  public function getUrlsByProtocol( array $urls ) {
154  $urlsByProtocol = [];
155  foreach ( $urls as $url ) {
156  list( $proto, ) = self::splitStorageUrl( $url );
157  $urlsByProtocol[$proto][] = $url;
158  }
159 
160  return $urlsByProtocol;
161  }
162 
168  private static function splitStorageUrl( $storeUrl ) {
169  $parts = explode( '://', $storeUrl );
170  if ( count( $parts ) != 2 || $parts[0] === '' || $parts[1] === '' ) {
171  throw new ExternalStoreException( "Invalid storage URL '$storeUrl'" );
172  }
173 
174  return $parts;
175  }
176 }
setLogger(LoggerInterface $logger)
getStoreForUrl( $url, array $params=[])
Get the ExternalStoreMedium for a given URL.
string [] $protocols
List of storage access protocols.
string $localDomainId
Default database domain to store content under.
__construct(array $externalStores, array $defaultStores, $localDomainId, LoggerInterface $logger=null)
getStoreLocationFromUrl( $url)
Get the location within the appropriate store for a given a URL.
getStore( $proto, array $params=[])
Get an external store object of the given type, with the given parameters.
string [] $writeBaseUrls
List of base storage URLs that define locations for writes.
static splitStorageUrl( $storeUrl)