Merge "Add more type hints in comments for static code analysis"
[lhc/web/wiklou.git] / includes / filerepo / LocalRepo.php
index 965f677..aa851ff 100644 (file)
  * @ingroup FileRepo
  */
 class LocalRepo extends FileRepo {
+       /** @var array */
        protected $fileFactory = array( 'LocalFile', 'newFromTitle' );
+
+       /** @var array */
        protected $fileFactoryKey = array( 'LocalFile', 'newFromKey' );
+
+       /** @var array */
        protected $fileFromRowFactory = array( 'LocalFile', 'newFromRow' );
+
+       /** @var array */
        protected $oldFileFromRowFactory = array( 'OldLocalFile', 'newFromRow' );
+
+       /** @var array */
        protected $oldFileFactory = array( 'OldLocalFile', 'newFromTitle' );
+
+       /** @var array */
        protected $oldFileFactoryKey = array( 'OldLocalFile', 'newFromKey' );
 
        /**
         * @throws MWException
-        * @param $row
+        * @param array $row
         * @return LocalFile
         */
        function newFileFromRow( $row ) {
@@ -52,8 +63,8 @@ class LocalRepo extends FileRepo {
        }
 
        /**
-        * @param $title
-        * @param $archiveName
+        * @param Title $title
+        * @param string $archiveName
         * @return OldLocalFile
         */
        function newFromArchiveName( $title, $archiveName ) {
@@ -66,7 +77,7 @@ class LocalRepo extends FileRepo {
         * interleave database locks with file operations, which is potentially a
         * remote operation.
         *
-        * @param $storageKeys array
+        * @param array $storageKeys
         *
         * @return FileRepoStatus
         */
@@ -155,7 +166,7 @@ class LocalRepo extends FileRepo {
        /**
         * Checks if there is a redirect named as $title
         *
-        * @param $title Title of file
+        * @param Title $title Title of file
         * @return bool
         */
        function checkRedirect( Title $title ) {
@@ -208,7 +219,7 @@ class LocalRepo extends FileRepo {
         * Function link Title::getArticleID().
         * We can't say Title object, what database it should use, so we duplicate that function here.
         *
-        * @param $title Title
+        * @param Title $title
         * @return bool|int|mixed
         */
        protected function getArticleID( $title ) {
@@ -229,12 +240,96 @@ class LocalRepo extends FileRepo {
                return $id;
        }
 
+       public function findFiles( array $items ) {
+               $finalFiles = array(); // map of (DB key => corresponding File) for matches
+
+               $searchSet = array(); // map of (DB key => normalized search params)
+               foreach ( $items as $item ) {
+                       $title = is_array( $item )
+                               ? File::normalizeTitle( $item['title'] )
+                               : File::normalizeTitle( $item );
+                       if ( $title ) { // valid title
+                               $searchSet[$title->getDbKey()] = ( is_array( $item ) ? $item : array() );
+                       }
+               }
+
+               $fileMatchesSearch = function( File $file, array $search ) {
+                       // Note: file name comparison done elsewhere (to handle redirects)
+                       return (
+                               $file->exists() &&
+                               (
+                                       ( empty( $search['time'] ) && !$file->isOld() ) ||
+                                       ( !empty( $search['time'] ) && $search['time'] === $file->getTimestamp() )
+                               ) &&
+                               ( !empty( $search['private'] ) || !$file->isDeleted( File::DELETED_FILE ) ) &&
+                               $file->userCan( File::DELETED_FILE )
+                       );
+               };
+
+               $repo = $this;
+               $applyMatchingFiles = function( ResultWrapper $res, &$searchSet, &$finalFiles )
+                       use ( $repo, $fileMatchesSearch )
+               {
+                       foreach ( $res as $row ) {
+                               $possFile = $repo->newFileFromRow( $row );
+                               $dbKey = $possFile->getName();
+                               // There must have been a search for this DB Key
+                               if ( $fileMatchesSearch( $possFile, $searchSet[$dbKey] ) ) {
+                                       $finalFiles[$dbKey] = $possFile;
+                                       unset( $searchSet[$dbKey] );
+                               }
+                       }
+               };
+
+               $dbr = $this->getSlaveDB();
+
+               // Query image table
+               $imgNames = array_keys( $searchSet );
+               if ( count( $imgNames ) ) {
+                       $res = $dbr->select( 'image',
+                               LocalFile::selectFields(), array( 'img_name' => $imgNames ), __METHOD__ );
+                       $applyMatchingFiles( $res, $searchSet, $finalFiles );
+               }
+
+               // Query old image table
+               $oiConds = array(); // WHERE clause array for each file
+               foreach ( $searchSet as $dbKey => $search ) {
+                       if ( isset( $search['params']['time'] ) ) {
+                               $oiConds[] = $dbr->makeList( array( 'oi_name' => $dbKey,
+                                       'oi_timestamp' => $dbr->timestamp( $search['params']['time'] ) ), LIST_AND );
+                       }
+               }
+               if ( count( $oiConds ) ) {
+                       $res = $dbr->select( 'oldimage',
+                               OldLocalFile::selectFields(), $dbr->makeList( $oiConds, LIST_OR ), __METHOD__ );
+                       $applyMatchingFiles( $res, $searchSet, $finalFiles );
+               }
+
+               // Check for redirects...
+               foreach ( $searchSet as $dbKey => $search ) {
+                       if ( !empty( $search['ignoreRedirect'] ) ) {
+                               continue;
+                       }
+                       $title = File::normalizeTitle( $dbKey );
+                       $redir = $this->checkRedirect( $title ); // hopefully hits memcached
+                       if ( $redir && $redir->getNamespace() == NS_FILE ) {
+                               $possFile = $this->newFile( $redir );
+                               if ( $possFile && $fileMatchesSearch( $possFile, $search ) ) {
+                                       $possFile->redirectedFrom( $title->getDBkey() );
+                                       $finalFiles[$dbKey] = $possFile;
+                               }
+                       }
+               }
+
+               return $finalFiles;
+       }
+
        /**
         * Get an array or iterator of file objects for files that have a given
         * SHA-1 content hash.
         *
         * @param string $hash a sha1 hash to look for
-        * @return Array
+        * @return array
         */
        function findBySha1( $hash ) {
                $dbr = $this->getSlaveDB();
@@ -349,7 +444,7 @@ class LocalRepo extends FileRepo {
        /**
         * Invalidates image redirect cache related to that image
         *
-        * @param $title Title of page
+        * @param Title $title Title of page
         * @return void
         */
        function invalidateImageRedirect( Title $title ) {