Merge "mediawiki.searchSuggest: Unbreak browser blacklist"
[lhc/web/wiklou.git] / includes / filebackend / FileOp.php
index 3c5b7b2..4e03675 100644 (file)
  * @since 1.19
  */
 abstract class FileOp {
-       /** @var Array */
+       /** @var array */
        protected $params = array();
+
        /** @var FileBackendStore */
        protected $backend;
 
-       protected $state = self::STATE_NEW; // integer
-       protected $failed = false; // boolean
-       protected $async = false; // boolean
-       protected $batchId; // string
+       /** @var int */
+       protected $state = self::STATE_NEW;
+
+       /** @var bool */
+       protected $failed = false;
+
+       /** @var bool */
+       protected $async = false;
+
+       /** @var string */
+       protected $batchId;
+
+       /** @var bool Operation is not a no-op */
+       protected $doOperation = true;
+
+       /** @var string */
+       protected $sourceSha1;
+
+       /** @var bool */
+       protected $overwriteSameCase;
 
-       protected $doOperation = true; // boolean; operation is not a no-op
-       protected $sourceSha1; // string
-       protected $overwriteSameCase; // boolean
-       protected $destExists; // boolean
+       /** @var bool */
+       protected $destExists;
 
        /* Object life-cycle */
        const STATE_NEW = 1;
@@ -58,8 +73,8 @@ abstract class FileOp {
         * Build a new batch file operation transaction
         *
         * @param FileBackendStore $backend
-        * @param Array $params
-        * @throws MWException
+        * @param array $params
+        * @throws FileBackendError
         */
        final public function __construct( FileBackendStore $backend, array $params ) {
                $this->backend = $backend;
@@ -68,7 +83,7 @@ abstract class FileOp {
                        if ( isset( $params[$name] ) ) {
                                $this->params[$name] = $params[$name];
                        } else {
-                               throw new MWException( "File operation missing parameter '$name'." );
+                               throw new FileBackendError( "File operation missing parameter '$name'." );
                        }
                }
                foreach ( $optional as $name ) {
@@ -84,7 +99,6 @@ abstract class FileOp {
                }
        }
 
-
        /**
         * Normalize a string if it is a valid storage path
         *
@@ -94,8 +108,10 @@ abstract class FileOp {
        protected static function normalizeIfValidStoragePath( $path ) {
                if ( FileBackend::isStoragePath( $path ) ) {
                        $res = FileBackend::normalizeStoragePath( $path );
+
                        return ( $res !== null ) ? $res : $path;
                }
+
                return $path;
        }
 
@@ -103,7 +119,6 @@ abstract class FileOp {
         * Set the batch UUID this operation belongs to
         *
         * @param string $batchId
-        * @return void
         */
        final public function setBatchId( $batchId ) {
                $this->batchId = $batchId;
@@ -131,7 +146,7 @@ abstract class FileOp {
        /**
         * Get a new empty predicates array for precheck()
         *
-        * @return Array
+        * @return array
         */
        final public static function newPredicates() {
                return array( 'exists' => array(), 'sha1' => array() );
@@ -140,7 +155,7 @@ abstract class FileOp {
        /**
         * Get a new empty dependency tracking array for paths read/written to
         *
-        * @return Array
+        * @return array
         */
        final public static function newDependencies() {
                return array( 'read' => array(), 'write' => array() );
@@ -150,18 +165,19 @@ abstract class FileOp {
         * Update a dependency tracking array to account for this operation
         *
         * @param array $deps Prior path reads/writes; format of FileOp::newPredicates()
-        * @return Array
+        * @return array
         */
        final public function applyDependencies( array $deps ) {
                $deps['read'] += array_fill_keys( $this->storagePathsRead(), 1 );
                $deps['write'] += array_fill_keys( $this->storagePathsChanged(), 1 );
+
                return $deps;
        }
 
        /**
         * Check if this operation changes files listed in $paths
         *
-        * @param array $paths Prior path reads/writes; format of FileOp::newPredicates()
+        * @param array $deps Prior path reads/writes; format of FileOp::newPredicates()
         * @return boolean
         */
        final public function dependsOn( array $deps ) {
@@ -175,6 +191,7 @@ abstract class FileOp {
                                return true; // "flow" dependency
                        }
                }
+
                return false;
        }
 
@@ -183,7 +200,7 @@ abstract class FileOp {
         *
         * @param array $oPredicates Pre-op info about files (format of FileOp::newPredicates)
         * @param array $nPredicates Post-op info about files (format of FileOp::newPredicates)
-        * @return Array
+        * @return array
         */
        final public function getJournalEntries( array $oPredicates, array $nPredicates ) {
                if ( !$this->doOperation ) {
@@ -215,6 +232,7 @@ abstract class FileOp {
                                );
                        }
                }
+
                return array_merge( $nullEntries, $updateEntries, $deleteEntries );
        }
 
@@ -223,7 +241,7 @@ abstract class FileOp {
         * This must update $predicates for each path that the op can change
         * except when a failing status object is returned.
         *
-        * @param Array $predicates
+        * @param array $predicates
         * @return Status
         */
        final public function precheck( array &$predicates ) {
@@ -235,10 +253,12 @@ abstract class FileOp {
                if ( !$status->isOK() ) {
                        $this->failed = true;
                }
+
                return $status;
        }
 
        /**
+        * @param array $predicates
         * @return Status
         */
        protected function doPrecheck( array &$predicates ) {
@@ -266,6 +286,7 @@ abstract class FileOp {
                } else { // no-op
                        $status = Status::newGood();
                }
+
                return $status;
        }
 
@@ -285,13 +306,14 @@ abstract class FileOp {
                $this->async = true;
                $result = $this->attempt();
                $this->async = false;
+
                return $result;
        }
 
        /**
         * Get the file operation parameters
         *
-        * @return Array (required params list, optional params list, list of params that are paths)
+        * @return array (required params list, optional params list, list of params that are paths)
         */
        protected function allowedParams() {
                return array( array(), array(), array() );
@@ -300,8 +322,8 @@ abstract class FileOp {
        /**
         * Adjust params to FileBackendStore internal file calls
         *
-        * @param Array $params
-        * @return Array (required params list, optional params list)
+        * @param array $params
+        * @return array (required params list, optional params list)
         */
        protected function setFlags( array $params ) {
                return array( 'async' => $this->async ) + $params;
@@ -310,7 +332,7 @@ abstract class FileOp {
        /**
         * Get a list of storage paths read from for this operation
         *
-        * @return Array
+        * @return array
         */
        public function storagePathsRead() {
                return array();
@@ -319,7 +341,7 @@ abstract class FileOp {
        /**
         * Get a list of storage paths written to for this operation
         *
-        * @return Array
+        * @return array
         */
        public function storagePathsChanged() {
                return array();
@@ -330,7 +352,7 @@ abstract class FileOp {
         * Also set the destExists, overwriteSameCase and sourceSha1 member variables.
         * A bad status will be returned if there is no chance it can be overwritten.
         *
-        * @param Array $predicates
+        * @param array $predicates
         * @return Status
         */
        protected function precheckDestExistence( array $predicates ) {
@@ -356,12 +378,15 @@ abstract class FileOp {
                                } else {
                                        $this->overwriteSameCase = true; // OK
                                }
+
                                return $status; // do nothing; either OK or bad status
                        } else {
                                $status->fatal( 'backend-fail-alreadyexists', $this->params['dst'] );
+
                                return $status;
                        }
                }
+
                return $status;
        }
 
@@ -379,7 +404,7 @@ abstract class FileOp {
         * Check if a file will exist in storage when this operation is attempted
         *
         * @param string $source Storage path
-        * @param Array $predicates
+        * @param array $predicates
         * @return bool
         */
        final protected function fileExists( $source, array $predicates ) {
@@ -387,6 +412,7 @@ abstract class FileOp {
                        return $predicates['exists'][$source]; // previous op assures this
                } else {
                        $params = array( 'src' => $source, 'latest' => true );
+
                        return $this->backend->fileExists( $params );
                }
        }
@@ -395,7 +421,7 @@ abstract class FileOp {
         * Get the SHA-1 of a file in storage when this operation is attempted
         *
         * @param string $source Storage path
-        * @param Array $predicates
+        * @param array $predicates
         * @return string|bool False on failure
         */
        final protected function fileSha1( $source, array $predicates ) {
@@ -405,6 +431,7 @@ abstract class FileOp {
                        return false; // previous op assures this
                } else {
                        $params = array( 'src' => $source, 'latest' => true );
+
                        return $this->backend->getFileSha1Base36( $params );
                }
        }
@@ -422,7 +449,6 @@ abstract class FileOp {
         * Log a file operation failure and preserve any temp files
         *
         * @param string $action
-        * @return void
         */
        final public function logFailure( $action ) {
                $params = $this->params;
@@ -456,11 +482,13 @@ class CreateFileOp extends FileOp {
                        $status->fatal( 'backend-fail-maxsize',
                                $this->params['dst'], $this->backend->maxFileSizeInternal() );
                        $status->fatal( 'backend-fail-create', $this->params['dst'] );
+
                        return $status;
                // Check if a file can be placed/changed at the destination
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['dst'] );
                        $status->fatal( 'backend-fail-create', $this->params['dst'] );
+
                        return $status;
                }
                // Check if destination file exists
@@ -471,6 +499,7 @@ class CreateFileOp extends FileOp {
                        $predicates['exists'][$this->params['dst']] = true;
                        $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
                }
+
                return $status; // safe to call attempt()
        }
 
@@ -479,6 +508,7 @@ class CreateFileOp extends FileOp {
                        // Create the file at the destination
                        return $this->backend->createInternal( $this->setFlags( $this->params ) );
                }
+
                return Status::newGood();
        }
 
@@ -509,17 +539,20 @@ class StoreFileOp extends FileOp {
                // Check if the source file exists on the file system
                if ( !is_file( $this->params['src'] ) ) {
                        $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                        return $status;
                // Check if the source file is too big
                } elseif ( filesize( $this->params['src'] ) > $this->backend->maxFileSizeInternal() ) {
                        $status->fatal( 'backend-fail-maxsize',
                                $this->params['dst'], $this->backend->maxFileSizeInternal() );
                        $status->fatal( 'backend-fail-store', $this->params['src'], $this->params['dst'] );
+
                        return $status;
                // Check if a file can be placed/changed at the destination
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['dst'] );
                        $status->fatal( 'backend-fail-store', $this->params['src'], $this->params['dst'] );
+
                        return $status;
                }
                // Check if destination file exists
@@ -530,6 +563,7 @@ class StoreFileOp extends FileOp {
                        $predicates['exists'][$this->params['dst']] = true;
                        $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
                }
+
                return $status; // safe to call attempt()
        }
 
@@ -538,6 +572,7 @@ class StoreFileOp extends FileOp {
                        // Store the file at the destination
                        return $this->backend->storeInternal( $this->setFlags( $this->params ) );
                }
+
                return Status::newGood();
        }
 
@@ -548,6 +583,7 @@ class StoreFileOp extends FileOp {
                if ( $hash !== false ) {
                        $hash = wfBaseConvert( $hash, 16, 36, 31 );
                }
+
                return $hash;
        }
 
@@ -578,15 +614,18 @@ class CopyFileOp extends FileOp {
                                // Update file existence predicates (cache 404s)
                                $predicates['exists'][$this->params['src']] = false;
                                $predicates['sha1'][$this->params['src']] = false;
+
                                return $status; // nothing to do
                        } else {
                                $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                                return $status;
                        }
-               // Check if a file can be placed/changed at the destination
+                       // Check if a file can be placed/changed at the destination
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['dst'] );
                        $status->fatal( 'backend-fail-copy', $this->params['src'], $this->params['dst'] );
+
                        return $status;
                }
                // Check if destination file exists
@@ -597,6 +636,7 @@ class CopyFileOp extends FileOp {
                        $predicates['exists'][$this->params['dst']] = true;
                        $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
                }
+
                return $status; // safe to call attempt()
        }
 
@@ -613,6 +653,7 @@ class CopyFileOp extends FileOp {
                        // Copy the file to the destination
                        $status = $this->backend->copyInternal( $this->setFlags( $this->params ) );
                }
+
                return $status;
        }
 
@@ -647,15 +688,18 @@ class MoveFileOp extends FileOp {
                                // Update file existence predicates (cache 404s)
                                $predicates['exists'][$this->params['src']] = false;
                                $predicates['sha1'][$this->params['src']] = false;
+
                                return $status; // nothing to do
                        } else {
                                $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                                return $status;
                        }
                // Check if a file can be placed/changed at the destination
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['dst'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['dst'] );
                        $status->fatal( 'backend-fail-move', $this->params['src'], $this->params['dst'] );
+
                        return $status;
                }
                // Check if destination file exists
@@ -668,6 +712,7 @@ class MoveFileOp extends FileOp {
                        $predicates['exists'][$this->params['dst']] = true;
                        $predicates['sha1'][$this->params['dst']] = $this->sourceSha1;
                }
+
                return $status; // safe to call attempt()
        }
 
@@ -692,6 +737,7 @@ class MoveFileOp extends FileOp {
                        // Move the file to the destination
                        $status = $this->backend->moveInternal( $this->setFlags( $this->params ) );
                }
+
                return $status;
        }
 
@@ -722,20 +768,24 @@ class DeleteFileOp extends FileOp {
                                // Update file existence predicates (cache 404s)
                                $predicates['exists'][$this->params['src']] = false;
                                $predicates['sha1'][$this->params['src']] = false;
+
                                return $status; // nothing to do
                        } else {
                                $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                                return $status;
                        }
                // Check if a file can be placed/changed at the source
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['src'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['src'] );
                        $status->fatal( 'backend-fail-delete', $this->params['src'] );
+
                        return $status;
                }
                // Update file existence predicates
                $predicates['exists'][$this->params['src']] = false;
                $predicates['sha1'][$this->params['src']] = false;
+
                return $status; // safe to call attempt()
        }
 
@@ -763,11 +813,13 @@ class DescribeFileOp extends FileOp {
                // Check if the source file exists
                if ( !$this->fileExists( $this->params['src'], $predicates ) ) {
                        $status->fatal( 'backend-fail-notexists', $this->params['src'] );
+
                        return $status;
                // Check if a file can be placed/changed at the source
                } elseif ( !$this->backend->isPathUsableInternal( $this->params['src'] ) ) {
                        $status->fatal( 'backend-fail-usable', $this->params['src'] );
                        $status->fatal( 'backend-fail-describe', $this->params['src'] );
+
                        return $status;
                }
                // Update file existence predicates
@@ -775,6 +827,7 @@ class DescribeFileOp extends FileOp {
                        $this->fileExists( $this->params['src'], $predicates );
                $predicates['sha1'][$this->params['src']] =
                        $this->fileSha1( $this->params['src'], $predicates );
+
                return $status; // safe to call attempt()
        }
 
@@ -791,4 +844,5 @@ class DescribeFileOp extends FileOp {
 /**
  * Placeholder operation that has no params and does nothing
  */
-class NullFileOp extends FileOp {}
+class NullFileOp extends FileOp {
+}