*/
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
+use Wikimedia\ScopedCallback;
/**
* @brief Base class for all file backend classes (including multi-write backends).
/** @var object|string Class name or object With profileIn/profileOut methods */
protected $profiler;
+ /** @var callable */
+ protected $obResetFunc;
+ /** @var callable */
+ protected $streamMimeFunc;
/** @var callable */
protected $statusWrapper;
* This should only be called from within FileBackendGroup.
*
* @param array $config Parameters include:
- * - name : The unique name of this backend.
- * This should consist of alphanumberic, '-', and '_' characters.
- * This name should not be changed after use (e.g. with journaling).
- * Note that the name is *not* used in actual container names.
- * - domainId : Prefix to container names that is unique to this backend.
- * It should only consist of alphanumberic, '-', and '_' characters.
- * This ID is what avoids collisions if multiple logical backends
- * use the same storage system, so this should be set carefully.
+ * - name : The unique name of this backend.
+ * This should consist of alphanumberic, '-', and '_' characters.
+ * This name should not be changed after use (e.g. with journaling).
+ * Note that the name is *not* used in actual container names.
+ * - domainId : Prefix to container names that is unique to this backend.
+ * It should only consist of alphanumberic, '-', and '_' characters.
+ * This ID is what avoids collisions if multiple logical backends
+ * use the same storage system, so this should be set carefully.
* - lockManager : LockManager object to use for any file locking.
- * If not provided, then no file locking will be enforced.
+ * If not provided, then no file locking will be enforced.
* - fileJournal : FileJournal object to use for logging changes to files.
- * If not provided, then change journaling will be disabled.
- * - readOnly : Write operations are disallowed if this is a non-empty string.
- * It should be an explanation for the backend being read-only.
+ * If not provided, then change journaling will be disabled.
+ * - readOnly : Write operations are disallowed if this is a non-empty string.
+ * It should be an explanation for the backend being read-only.
* - parallelize : When to do file operations in parallel (when possible).
- * Allowed values are "implicit", "explicit" and "off".
+ * Allowed values are "implicit", "explicit" and "off".
* - concurrency : How many file operations can be done in parallel.
* - tmpDirectory : Directory to use for temporary files. If this is not set or null,
- * then the backend will try to discover a usable temporary directory.
- * - logger : Optional PSR logger object.
- * - profiler : Optional class name or object With profileIn/profileOut methods.
+ * then the backend will try to discover a usable temporary directory.
+ * - obResetFunc : alternative callback to clear the output buffer
+ * - streamMimeFunc : alternative method to determine the content type from the path
+ * - logger : Optional PSR logger object.
+ * - profiler : Optional class name or object With profileIn/profileOut methods.
* @throws InvalidArgumentException
*/
public function __construct( array $config ) {
$this->concurrency = isset( $config['concurrency'] )
? (int)$config['concurrency']
: 50;
- $this->profiler = isset( $params['profiler'] ) ? $params['profiler'] : null;
+ $this->obResetFunc = isset( $config['obResetFunc'] )
+ ? $config['obResetFunc']
+ : [ $this, 'resetOutputBuffer' ];
+ $this->streamMimeFunc = isset( $config['streamMimeFunc'] )
+ ? $config['streamMimeFunc']
+ : null;
+ $this->statusWrapper = isset( $config['statusWrapper'] ) ? $config['statusWrapper'] : null;
+
+ $this->profiler = isset( $config['profiler'] ) ? $config['profiler'] : null;
$this->logger = isset( $config['logger'] ) ? $config['logger'] : new \Psr\Log\NullLogger();
$this->statusWrapper = isset( $config['statusWrapper'] ) ? $config['statusWrapper'] : null;
$this->tmpDirectory = isset( $config['tmpDirectory'] ) ? $config['tmpDirectory'] : null;
* @return ScopedCallback|null
*/
final protected function getScopedPHPBehaviorForOps() {
- if ( PHP_SAPI != 'cli' ) { // http://bugs.php.net/bug.php?id=47540
+ if ( PHP_SAPI != 'cli' ) { // https://bugs.php.net/bug.php?id=47540
$old = ignore_user_abort( true ); // avoid half-finished operations
return new ScopedCallback( function () use ( $old ) {
ignore_user_abort( $old );
protected function scopedProfileSection( $section ) {
if ( $this->profiler ) {
call_user_func( [ $this->profiler, 'profileIn' ], $section );
- return new ScopedCallback( [ $this->profiler, 'profileOut' ] );
+ return new ScopedCallback( [ $this->profiler, 'profileOut' ], [ $section ] );
}
return null;
}
+
+ protected function resetOutputBuffer() {
+ while ( ob_get_status() ) {
+ if ( !ob_end_clean() ) {
+ // Could not remove output buffer handler; abort now
+ // to avoid getting in some kind of infinite loop.
+ break;
+ }
+ }
+ }
}