abstract class FileBackendBase {
protected $name; // unique backend name
protected $wikiId; // unique wiki name
+ protected $readOnly; // string
/** @var LockManager */
protected $lockManager;
* This should only be called from within FileBackendGroup.
*
* $config includes:
- * 'name' : The name of this backend
+ * 'name' : The unique name of this backend
* 'wikiId' : Prefix to container names that is unique to this wiki
- * 'lockManager' : Registered name of the file lock manager to use
+ * 'lockManager' : Registered name of a file lock manager to use
+ * 'readOnly' : Write operations are disallowed if this is a non-empty string.
+ * It should be an explanation for the backend being read-only.
*
* @param $config Array
*/
? $config['wikiId']
: wfWikiID();
$this->lockManager = LockManagerGroup::singleton()->get( $config['lockManager'] );
+ $this->readOnly = isset( $config['readOnly'] )
+ ? (string)$config['readOnly']
+ : '';
}
/**
* @return Status
*/
final public function doOperations( array $ops, array $opts = array() ) {
+ if ( $this->readOnly != '' ) {
+ return Status::newFatal( 'backend-fail-readonly', $this->name, $this->readOnly );
+ }
if ( empty( $opts['ignoreErrors'] ) ) { // sanity
unset( $opts['nonLocking'] );
unset( $opts['allowStale'] );
abstract public function fileExists( array $params );
/**
- * Get a SHA-1 hash of the file at a storage path in the backend.
+ * Get the last-modified timestamp of the file at a storage path.
*
* $params include:
* src : source storage path
* latest : use the latest available data
*
* @param $params Array
- * @return string|false Hash string or false on failure
+ * @return string|false TS_MW timestamp or false on failure
*/
- abstract public function getFileSha1Base36( array $params );
+ abstract public function getFileTimestamp( array $params );
/**
- * Get the last-modified timestamp of the file at a storage path.
+ * Get the contents of a file at a storage path in the backend.
+ * This should be avoided for potentially large files.
*
* $params include:
* src : source storage path
* latest : use the latest available data
*
* @param $params Array
- * @return string|false TS_MW timestamp or false on failure
+ * @return string|false Returns false on failure
*/
- abstract public function getFileTimestamp( array $params );
+ abstract public function getFileContents( array $params );
+
+ /**
+ * Get a SHA-1 hash of the file at a storage path in the backend.
+ *
+ * $params include:
+ * src : source storage path
+ * latest : use the latest available data
+ *
+ * @param $params Array
+ * @return string|false Hash string or false on failure
+ */
+ abstract public function getFileSha1Base36( array $params );
/**
* Get the properties of the file at a storage path in the backend.
return Status::newGood();
}
+ /**
+ * @see FileBackendBase::getFileContents()
+ */
+ public function getFileContents( array $params ) {
+ $tmpFile = $this->getLocalReference( $params );
+ if ( !$tmpFile ) {
+ return false;
+ }
+ wfSuppressWarnings();
+ $data = file_get_contents( $tmpFile->getPath() );
+ wfRestoreWarnings();
+ return $data;
+ }
+
/**
* @see FileBackendBase::getFileSha1Base36()
*/
return $cases;
}
+ /**
+ * @dataProvider provider_testGetFileContents
+ */
+ public function testGetFileContents( $src, $content ) {
+ $this->pathsToPrune[] = $src;
+
+ $status = $this->backend->doOperation(
+ array( 'op' => 'create', 'content' => $content, 'dst' => $src ) );
+ $this->assertEquals( true, $status->isOK(), "Creation of file at $src succeeded." );
+
+ $newContents = $this->backend->getFileContents( array( 'src' => $src ) );
+ $this->assertNotEquals( false, $newContents, "Read of file at $src succeeded." );
+
+ $this->assertEquals( $content, $newContents, "Contents read match data at $src." );
+ }
+
+ function provider_testGetFileContents() {
+ $cases = array();
+
+ $base = $this->singleBasePath();
+ $cases[] = array( "$base/cont1/b/z/some_file.txt", "some file contents" );
+ $cases[] = array( "$base/cont1/b/some-other_file.txt", "more file contents" );
+
+ return $cases;
+ }
+
/**
* @dataProvider provider_testGetLocalCopy
*/
}
/**
- * @dataProvider provider_testGetReference
+ * @dataProvider provider_testGetLocalReference
*/
public function testGetLocalReference( $src, $content ) {
$this->pathsToPrune[] = $src;
$this->assertNotEquals( false, $contents, "Local copy of $src exists." );
}
- function provider_testGetReference() {
+ function provider_testGetLocalReference() {
$cases = array();
$base = $this->singleBasePath();