]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - includes/ExternalStore.php
MediaWiki 1.17.0
[autoinstalls/mediawiki.git] / includes / ExternalStore.php
1 <?php
2 /**
3  * @defgroup ExternalStorage ExternalStorage
4  */
5
6 /**
7  * Constructor class for data kept in external repositories
8  *
9  * External repositories might be populated by maintenance/async
10  * scripts, thus partial moving of data may be possible, as well
11  * as possibility to have any storage format (i.e. for archives)
12  *
13  * @ingroup ExternalStorage
14  */
15 class ExternalStore {
16         var $mParams;
17         
18         function __construct( $params = array() ) {
19                 $this->mParams = $params;
20         }
21         
22         /**
23          * Fetch data from given URL
24          *
25          * @param $url String: The URL of the text to get
26          * @param $params Array: associative array of parameters for the ExternalStore object.
27          * @return The text stored or false on error
28          */
29         static function fetchFromURL( $url, $params = array() ) {
30                 global $wgExternalStores;
31
32                 if( !$wgExternalStores )
33                         return false;
34
35                 $parts = explode( '://', $url, 2 );
36
37                 if ( count( $parts ) != 2 ) {
38                         return false;
39                 }
40
41                 list( $proto, $path ) = $parts;
42
43                 if ( $path == '' ) { // Bad URL
44                         return false;
45                 }
46
47                 $store = self::getStoreObject( $proto, $params );
48                 if ( $store === false )
49                         return false;
50                 return $store->fetchFromURL( $url );
51         }
52
53         /**
54          * Get an external store object of the given type, with the given parameters
55          *
56          * @param $proto String: type of external storage, should be a value in $wgExternalStores
57          * @param $params Array: associative array of parameters for the ExternalStore object.
58          * @return ExternalStore subclass or false on error
59          */
60         static function getStoreObject( $proto, $params = array() ) {
61                 global $wgExternalStores;
62                 if( !$wgExternalStores )
63                         return false;
64                 /* Protocol not enabled */
65                 if( !in_array( $proto, $wgExternalStores ) )
66                         return false;
67
68                 $class = 'ExternalStore' . ucfirst( $proto );
69                 /* Any custom modules should be added to $wgAutoLoadClasses for on-demand loading */
70                 if( !class_exists( $class ) ) {
71                         return false;
72                 }
73
74                 return new $class($params);
75         }
76
77         /**
78          * Store a data item to an external store, identified by a partial URL
79          * The protocol part is used to identify the class, the rest is passed to the
80          * class itself as a parameter.
81          * @return The URL of the stored data item, or false on error
82          */
83         static function insert( $url, $data, $params = array() ) {
84                 list( $proto, $params ) = explode( '://', $url, 2 );
85                 $store = self::getStoreObject( $proto, $params );
86                 if ( $store === false ) {
87                         return false;
88                 } else {
89                         return $store->store( $params, $data );
90                 }
91         }
92         
93         /**
94          * Like insert() above, but does more of the work for us.
95          * This function does not need a url param, it builds it by
96          * itself. It also fails-over to the next possible clusters.
97          *
98          * @param $data String
99          * @param $storageParams Array: associative array of parameters for the ExternalStore object.
100          * @return The URL of the stored data item, or false on error
101          */
102         public static function insertToDefault( $data, $storageParams = array() ) {
103                 global $wgDefaultExternalStore;
104                 $tryStores = (array)$wgDefaultExternalStore;
105                 $error = false;
106                 while ( count( $tryStores ) > 0 ) {
107                         $index = mt_rand(0, count( $tryStores ) - 1);
108                         $storeUrl = $tryStores[$index];
109                         wfDebug( __METHOD__.": trying $storeUrl\n" );
110                         list( $proto, $params ) = explode( '://', $storeUrl, 2 );
111                         $store = self::getStoreObject( $proto, $storageParams );
112                         if ( $store === false ) {
113                                 throw new MWException( "Invalid external storage protocol - $storeUrl" );
114                         }
115                         try {
116                                 $url = $store->store( $params, $data ); // Try to save the object
117                         } catch ( DBConnectionError $error ) {
118                                 $url = false;
119                         } catch( DBQueryError $error ) {
120                                 $url = false;
121                         }
122                         if ( $url ) {
123                                 return $url; // Done!
124                         } else {
125                                 unset( $tryStores[$index] ); // Don't try this one again!
126                                 $tryStores = array_values( $tryStores ); // Must have consecutive keys
127                                 wfDebugLog( 'ExternalStorage', "Unable to store text to external storage $storeUrl" );
128                         }
129                 }
130                 // All stores failed
131                 if ( $error ) {
132                         // Rethrow the last connection error
133                         throw $error;
134                 } else {
135                         throw new MWException( "Unable to store text to external storage" );
136                 }
137         }
138         
139         /** Like insertToDefault, but inserts on another wiki */
140         public static function insertToForeignDefault( $data, $wiki ) {
141                 return self::insertToDefault( $data, array( 'wiki' => $wiki ) );
142         }
143 }