MediaWiki  master
MemoryFileBackend.php
Go to the documentation of this file.
1 <?php
24 use Wikimedia\AtEase\AtEase;
25 use Wikimedia\Timestamp\ConvertibleTimestamp;
26 
38  protected $files = [];
39 
40  public function getFeatures() {
42  }
43 
44  public function isPathUsableInternal( $storagePath ) {
45  return ( $this->resolveHashKey( $storagePath ) !== null );
46  }
47 
48  protected function doCreateInternal( array $params ) {
49  $status = $this->newStatus();
50 
51  $dst = $this->resolveHashKey( $params['dst'] );
52  if ( $dst === null ) {
53  $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
54 
55  return $status;
56  }
57 
58  $this->files[$dst] = [
59  'data' => $params['content'],
60  'mtime' => ConvertibleTimestamp::convert( TS_MW, time() )
61  ];
62 
63  return $status;
64  }
65 
66  protected function doStoreInternal( array $params ) {
67  $status = $this->newStatus();
68 
69  $dst = $this->resolveHashKey( $params['dst'] );
70  if ( $dst === null ) {
71  $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
72 
73  return $status;
74  }
75 
76  AtEase::suppressWarnings();
77  $data = file_get_contents( $params['src'] );
78  AtEase::restoreWarnings();
79  if ( $data === false ) { // source doesn't exist?
80  $status->fatal( 'backend-fail-store', $params['src'], $params['dst'] );
81 
82  return $status;
83  }
84 
85  $this->files[$dst] = [
86  'data' => $data,
87  'mtime' => ConvertibleTimestamp::convert( TS_MW, time() )
88  ];
89 
90  return $status;
91  }
92 
93  protected function doCopyInternal( array $params ) {
94  $status = $this->newStatus();
95 
96  $src = $this->resolveHashKey( $params['src'] );
97  if ( $src === null ) {
98  $status->fatal( 'backend-fail-invalidpath', $params['src'] );
99 
100  return $status;
101  }
102 
103  $dst = $this->resolveHashKey( $params['dst'] );
104  if ( $dst === null ) {
105  $status->fatal( 'backend-fail-invalidpath', $params['dst'] );
106 
107  return $status;
108  }
109 
110  if ( !isset( $this->files[$src] ) ) {
111  if ( empty( $params['ignoreMissingSource'] ) ) {
112  $status->fatal( 'backend-fail-copy', $params['src'], $params['dst'] );
113  }
114 
115  return $status;
116  }
117 
118  $this->files[$dst] = [
119  'data' => $this->files[$src]['data'],
120  'mtime' => ConvertibleTimestamp::convert( TS_MW, time() )
121  ];
122 
123  return $status;
124  }
125 
126  protected function doDeleteInternal( array $params ) {
127  $status = $this->newStatus();
128 
129  $src = $this->resolveHashKey( $params['src'] );
130  if ( $src === null ) {
131  $status->fatal( 'backend-fail-invalidpath', $params['src'] );
132 
133  return $status;
134  }
135 
136  if ( !isset( $this->files[$src] ) ) {
137  if ( empty( $params['ignoreMissingSource'] ) ) {
138  $status->fatal( 'backend-fail-delete', $params['src'] );
139  }
140 
141  return $status;
142  }
143 
144  unset( $this->files[$src] );
145 
146  return $status;
147  }
148 
149  protected function doGetFileStat( array $params ) {
150  $src = $this->resolveHashKey( $params['src'] );
151  if ( $src === null ) {
152  return self::$RES_ERROR; // invalid path
153  }
154 
155  if ( isset( $this->files[$src] ) ) {
156  return [
157  'mtime' => $this->files[$src]['mtime'],
158  'size' => strlen( $this->files[$src]['data'] ),
159  ];
160  }
161 
162  return self::$RES_ABSENT;
163  }
164 
165  protected function doGetLocalCopyMulti( array $params ) {
166  $tmpFiles = []; // (path => TempFSFile)
167  foreach ( $params['srcs'] as $srcPath ) {
168  $src = $this->resolveHashKey( $srcPath );
169  if ( $src === null ) {
170  $fsFile = self::$RES_ERROR;
171  } elseif ( !isset( $this->files[$src] ) ) {
172  $fsFile = self::$RES_ABSENT;
173  } else {
174  // Create a new temporary file with the same extension...
176  $fsFile = $this->tmpFileFactory->newTempFSFile( 'localcopy_', $ext );
177  if ( $fsFile ) {
178  $bytes = file_put_contents( $fsFile->getPath(), $this->files[$src]['data'] );
179  if ( $bytes !== strlen( $this->files[$src]['data'] ) ) {
180  $fsFile = self::$RES_ERROR;
181  }
182  }
183  }
184  $tmpFiles[$srcPath] = $fsFile;
185  }
186 
187  return $tmpFiles;
188  }
189 
190  protected function doDirectoryExists( $container, $dir, array $params ) {
191  $prefix = rtrim( "$container/$dir", '/' ) . '/';
192  foreach ( $this->files as $path => $data ) {
193  if ( strpos( $path, $prefix ) === 0 ) {
194  return true;
195  }
196  }
197 
198  return false;
199  }
200 
201  public function getDirectoryListInternal( $container, $dir, array $params ) {
202  $dirs = [];
203  $prefix = rtrim( "$container/$dir", '/' ) . '/';
204  $prefixLen = strlen( $prefix );
205  foreach ( $this->files as $path => $data ) {
206  if ( strpos( $path, $prefix ) === 0 ) {
207  $relPath = substr( $path, $prefixLen );
208  if ( $relPath === false ) {
209  continue;
210  } elseif ( strpos( $relPath, '/' ) === false ) {
211  continue; // just a file
212  }
213  $parts = array_slice( explode( '/', $relPath ), 0, -1 ); // last part is file name
214  if ( !empty( $params['topOnly'] ) ) {
215  $dirs[$parts[0]] = 1; // top directory
216  } else {
217  $current = '';
218  foreach ( $parts as $part ) { // all directories
219  $dir = ( $current === '' ) ? $part : "$current/$part";
220  $dirs[$dir] = 1;
221  $current = $dir;
222  }
223  }
224  }
225  }
226 
227  return array_keys( $dirs );
228  }
229 
230  public function getFileListInternal( $container, $dir, array $params ) {
231  $files = [];
232  $prefix = rtrim( "$container/$dir", '/' ) . '/';
233  $prefixLen = strlen( $prefix );
234  foreach ( $this->files as $path => $data ) {
235  if ( strpos( $path, $prefix ) === 0 ) {
236  $relPath = substr( $path, $prefixLen );
237  if ( $relPath === false ) {
238  continue;
239  } elseif ( !empty( $params['topOnly'] ) && strpos( $relPath, '/' ) !== false ) {
240  continue;
241  }
242  $files[] = $relPath;
243  }
244  }
245 
246  return $files;
247  }
248 
249  protected function directoriesAreVirtual() {
250  return true;
251  }
252 
259  protected function resolveHashKey( $storagePath ) {
260  list( $fullCont, $relPath ) = $this->resolveStoragePathReal( $storagePath );
261  if ( $relPath === null ) {
262  return null; // invalid
263  }
264 
265  return ( $relPath !== '' ) ? "$fullCont/$relPath" : $fullCont;
266  }
267 }
MemoryFileBackend\doCopyInternal
doCopyInternal(array $params)
Definition: MemoryFileBackend.php:93
MemoryFileBackend\doDirectoryExists
doDirectoryExists( $container, $dir, array $params)
Definition: MemoryFileBackend.php:190
MemoryFileBackend\doDeleteInternal
doDeleteInternal(array $params)
Definition: MemoryFileBackend.php:126
MemoryFileBackend\getDirectoryListInternal
getDirectoryListInternal( $container, $dir, array $params)
Do not call this function from places outside FileBackend.
Definition: MemoryFileBackend.php:201
MemoryFileBackend\doGetFileStat
doGetFileStat(array $params)
Definition: MemoryFileBackend.php:149
FileBackend\extensionFromPath
static extensionFromPath( $path, $case='lowercase')
Get the final extension from a storage or FS path.
Definition: FileBackend.php:1602
MemoryFileBackend\doStoreInternal
doStoreInternal(array $params)
Definition: MemoryFileBackend.php:66
FileBackendStore\$RES_ERROR
static null $RES_ERROR
Idiom for "no result due to I/O errors" (since 1.34)
Definition: FileBackendStore.php:66
MemoryFileBackend\$files
array $files
Map of (file path => (data,mtime)
Definition: MemoryFileBackend.php:38
MemoryFileBackend\doGetLocalCopyMulti
doGetLocalCopyMulti(array $params)
Definition: MemoryFileBackend.php:165
FileBackend\ATTR_UNICODE_PATHS
const ATTR_UNICODE_PATHS
Definition: FileBackend.php:136
$dirs
$dirs
Definition: mergeMessageFileList.php:192
MemoryFileBackend\isPathUsableInternal
isPathUsableInternal( $storagePath)
Check if a file can be created or changed at a given storage path in the backend.
Definition: MemoryFileBackend.php:44
MemoryFileBackend
Simulation of a backend storage in memory.
Definition: MemoryFileBackend.php:36
FileBackendStore\resolveStoragePathReal
resolveStoragePathReal( $storagePath)
Like resolveStoragePath() except null values are returned if the container is sharded and the shard c...
Definition: FileBackendStore.php:1642
MemoryFileBackend\getFileListInternal
getFileListInternal( $container, $dir, array $params)
Do not call this function from places outside FileBackend.
Definition: MemoryFileBackend.php:230
MemoryFileBackend\doCreateInternal
doCreateInternal(array $params)
Definition: MemoryFileBackend.php:48
FileBackendStore
Base class for all backends using particular storage medium.
Definition: FileBackendStore.php:41
FileBackendStore\$RES_ABSENT
static false $RES_ABSENT
Idiom for "no result due to missing file" (since 1.34)
Definition: FileBackendStore.php:64
MemoryFileBackend\getFeatures
getFeatures()
Get the a bitfield of extra features supported by the backend medium Stable to override.
Definition: MemoryFileBackend.php:40
FileBackend\newStatus
newStatus(... $args)
Yields the result of the status wrapper callback on either:
Definition: FileBackend.php:1695
MemoryFileBackend\resolveHashKey
resolveHashKey( $storagePath)
Get the absolute file system path for a storage path.
Definition: MemoryFileBackend.php:259
$path
$path
Definition: NoLocalSettings.php:25
$ext
if(!is_readable( $file)) $ext
Definition: router.php:48
MemoryFileBackend\directoriesAreVirtual
directoriesAreVirtual()
Is this a key/value store where directories are just virtual? Virtual directories exists in so much a...
Definition: MemoryFileBackend.php:249