]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/externalstore/ExternalStoreMwstore.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / includes / externalstore / ExternalStoreMwstore.php
1 <?php
2 /**
3  * External storage in a file backend.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  * http://www.gnu.org/copyleft/gpl.html
19  *
20  * @file
21  */
22
23 /**
24  * File backend accessable external objects.
25  *
26  * In this system, each store "location" maps to the name of a file backend.
27  * The file backends must be defined in $wgFileBackends and must be global
28  * and fully qualified with a global "wikiId" prefix in the configuration.
29  *
30  * @ingroup ExternalStorage
31  * @since 1.21
32  */
33 class ExternalStoreMwstore extends ExternalStoreMedium {
34         /**
35          * The URL returned is of the form of the form mwstore://backend/container/wiki/id
36          *
37          * @see ExternalStoreMedium::fetchFromURL()
38          * @param string $url
39          * @return bool
40          */
41         public function fetchFromURL( $url ) {
42                 $be = FileBackendGroup::singleton()->backendFromPath( $url );
43                 if ( $be instanceof FileBackend ) {
44                         // We don't need "latest" since objects are immutable and
45                         // backends should at least have "read-after-create" consistency.
46                         return $be->getFileContents( [ 'src' => $url ] );
47                 }
48
49                 return false;
50         }
51
52         /**
53          * Fetch data from given external store URLs.
54          * The URL returned is of the form of the form mwstore://backend/container/wiki/id
55          *
56          * @param array $urls An array of external store URLs
57          * @return array A map from url to stored content. Failed results are not represented.
58          */
59         public function batchFetchFromURLs( array $urls ) {
60                 $pathsByBackend = [];
61                 foreach ( $urls as $url ) {
62                         $be = FileBackendGroup::singleton()->backendFromPath( $url );
63                         if ( $be instanceof FileBackend ) {
64                                 $pathsByBackend[$be->getName()][] = $url;
65                         }
66                 }
67                 $blobs = [];
68                 foreach ( $pathsByBackend as $backendName => $paths ) {
69                         $be = FileBackendGroup::singleton()->get( $backendName );
70                         $blobs = $blobs + $be->getFileContentsMulti( [ 'srcs' => $paths ] );
71                 }
72
73                 return $blobs;
74         }
75
76         /**
77          * @see ExternalStoreMedium::store()
78          * @param string $backend
79          * @param string $data
80          * @return string|bool
81          * @throws MWException
82          */
83         public function store( $backend, $data ) {
84                 $be = FileBackendGroup::singleton()->get( $backend );
85                 if ( $be instanceof FileBackend ) {
86                         // Get three random base 36 characters to act as shard directories
87                         $rand = Wikimedia\base_convert( mt_rand( 0, 46655 ), 10, 36, 3 );
88                         // Make sure ID is roughly lexicographically increasing for performance
89                         $id = str_pad( UIDGenerator::newTimestampedUID128( 32 ), 26, '0', STR_PAD_LEFT );
90                         // Segregate items by wiki ID for the sake of bookkeeping
91                         $wiki = isset( $this->params['wiki'] ) ? $this->params['wiki'] : wfWikiID();
92
93                         $url = $be->getContainerStoragePath( 'data' ) . '/' . rawurlencode( $wiki );
94                         $url .= ( $be instanceof FSFileBackend )
95                                 ? "/{$rand[0]}/{$rand[1]}/{$rand[2]}/{$id}" // keep directories small
96                                 : "/{$rand[0]}/{$rand[1]}/{$id}"; // container sharding is only 2-levels
97
98                         $be->prepare( [ 'dir' => dirname( $url ), 'noAccess' => 1, 'noListing' => 1 ] );
99                         if ( $be->create( [ 'dst' => $url, 'content' => $data ] )->isOK() ) {
100                                 return $url;
101                         }
102                 }
103
104                 return false;
105         }
106 }