Add RepoGroup::findFiles to efficiently find many files if the repo supports it....
authorBryan Tong Minh <btongminh@users.mediawiki.org>
Tue, 20 May 2008 17:05:57 +0000 (17:05 +0000)
committerBryan Tong Minh <btongminh@users.mediawiki.org>
Tue, 20 May 2008 17:05:57 +0000 (17:05 +0000)
includes/api/ApiQueryImageInfo.php
includes/filerepo/File.php
includes/filerepo/FileRepo.php
includes/filerepo/LocalRepo.php
includes/filerepo/RepoGroup.php

index bb8aed8..e787f4c 100644 (file)
@@ -59,48 +59,47 @@ class ApiQueryImageInfo extends ApiQueryBase {
                if (!empty($pageIds[NS_IMAGE])) {
                        
                        $result = $this->getResult();
-                       foreach ($pageIds[NS_IMAGE] as $dbKey => $pageId) {
-
-                               $title = Title :: makeTitle(NS_IMAGE, $dbKey);
-                               $img = wfFindFile($title);
-
+                       $images = RepoGroup::singleton()->findFiles( array_keys( $pageIds[NS_IMAGE] ) );
+                       foreach ( $images as $img ) {
                                $data = array();
-                               if ( !$img ) {
-                                       $repository = '';
-                               } else {
-
-                                       $repository = $img->getRepoName();
-
-                                       // Get information about the current version first
-                                       // Check that the current version is within the start-end boundaries
-                                       if((is_null($params['start']) || $img->getTimestamp() <= $params['start']) &&
-                                                       (is_null($params['end']) || $img->getTimestamp() >= $params['end'])) {
-                                               $data[] = self::getInfo( $img, $prop, $result, $scale );
-                                       }
+                               
+                               // Get information about the current version first
+                               // Check that the current version is within the start-end boundaries
+                               if((is_null($params['start']) || $img->getTimestamp() <= $params['start']) &&
+                                               (is_null($params['end']) || $img->getTimestamp() >= $params['end'])) {
+                                       $data[] = self::getInfo( $img, $prop, $result, $scale );
+                               }
 
-                                       // Now get the old revisions
-                                       // Get one more to facilitate query-continue functionality
-                                       $count = count($data);
-                                       $oldies = $img->getHistory($params['limit'] - $count + 1, $params['start'], $params['end']);
-                                       foreach($oldies as $oldie) {
-                                               if(++$count > $params['limit']) {
-                                                       // We've reached the extra one which shows that there are additional pages to be had. Stop here...
-                                                       // Only set a query-continue if there was only one title
-                                                       if(count($pageIds[NS_IMAGE]) == 1)
-                                                               $this->setContinueEnumParameter('start', $oldie->getTimestamp());
-                                                       break;
-                                               }
-                                               $data[] = self::getInfo( $oldie, $prop, $result );
+                               // Now get the old revisions
+                               // Get one more to facilitate query-continue functionality
+                               $count = count($data);
+                               $oldies = $img->getHistory($params['limit'] - $count + 1, $params['start'], $params['end']);
+                               foreach($oldies as $oldie) {
+                                       if(++$count > $params['limit']) {
+                                               // We've reached the extra one which shows that there are additional pages to be had. Stop here...
+                                               // Only set a query-continue if there was only one title
+                                               if(count($pageIds[NS_IMAGE]) == 1)
+                                                       $this->setContinueEnumParameter('start', $oldie->getTimestamp());
+                                               break;
                                        }
+                                       $data[] = self::getInfo( $oldie, $prop, $result );
                                }
 
-                               $result->addValue(array(
-                                               'query', 'pages', intval($pageId)),
-                                               'imagerepository', $repository
+                               $pageId = $pageIds[NS_IMAGE][ $img->getOriginalTitle()->getDBkey() ];
+                               wfDebug("id: $pageId\n");
+                               $result->addValue(
+                                       array( 'query', 'pages', intval( $pageId ) ),
+                                       'imagerepository', $img->getRepoName()
                                );
-                               if (!empty($data))
-                                       $this->addPageSubItems($pageId, $data);
+                               $this->addPageSubItems($pageId, $data);
                        }
+                       
+                       $missing = array_diff( array_keys( $pageIds[NS_IMAGE] ), array_keys( $images ) );
+                       foreach ( $missing as $title )
+                               $result->addValue(
+                                       array( 'query', 'pages', intval( $pageIds[NS_IMAGE][$title] ) ),
+                                       'imagerepository', ''
+                               );
                }
        }
 
index 6e5c724..317ac2e 100644 (file)
@@ -46,7 +46,7 @@ abstract class File {
        /**
         * The following member variables are not lazy-initialised
         */
-       var $repo, $title, $lastError, $redirected;
+       var $repo, $title, $lastError, $redirected, $redirectedTitle;
 
        /**
         * Call this constructor from child classes
@@ -152,6 +152,15 @@ abstract class File {
         * Return the associated title object
         */
        public function getTitle() { return $this->title; }
+       
+       /**
+        * Return the title used to find this file
+        */
+       public function getOriginalTitle() {
+               if ( $this->redirected )
+                       return $this->getRedirectedTitle();
+               return $this->title;
+       }
 
        /**
         * Return the URL of the file
@@ -1214,6 +1223,14 @@ abstract class File {
        function getRedirected() {
                return $this->redirected;
        }
+       
+       function getRedirectedTitle() {
+               if ( $this->redirected ) {
+                       if ( !$this->redirectTitle )
+                               $this->redirectTitle = Title::makeTitle( NS_IMAGE, $this->redirected );
+                       return $this->redirectTitle;
+               }
+       }
 
        function redirectedFrom( $from ) {
                $this->redirected = $from;
index 61f42f4..bf06aef 100644 (file)
@@ -125,6 +125,21 @@ abstract class FileRepo {
                return false;
        }
        
+       /*
+        * Find many files at once
+        */
+       function findFiles( &$titles, $time = false, $flags ) {
+               $result = array();
+               foreach ( $titles as $index => $title ) {
+                       $file = $this->findFile( $title );
+                       if ( $file ) {
+                               $result[$file->getTitle()->getDBkey()] = $file;
+                               unset( $titles[$index] );
+                       }
+               }
+               return $result;
+       }
+       
        /**
         * Create a new File object from the local repository
         * @param mixed $sha1 SHA-1 key
index 41e70f1..452def0 100644 (file)
@@ -157,4 +157,36 @@ class LocalRepo extends FSRepo {
                $res->free();
                return $result;
        }
+       
+       function findFiles( &$titles, $time = false, $flags ) {
+               if ( count( $titles ) == 0 ) return array();            
+       
+               $dbKeys = array();
+               $indices = array();
+               
+               foreach ( $titles as $index => $title ) {
+                       if ( !( $title instanceof Title ) )
+                               $title = Title::makeTitleSafe( NS_IMAGE, $title );
+                       if ( is_object( $title ) ) {
+                               $key = $title->getDBkey();
+                               $indices[$key] = $index;
+                               $dbKeys[] = $key;
+                       }
+               }
+       
+               $dbr = $this->getSlaveDB();
+               $res = $dbr->select(
+                       'image',
+                       LocalFile::selectFields(),
+                       array( 'img_name' => $dbKeys )          
+               );
+               
+               $result = array();
+               while ( $row = $res->fetchObject() ) {
+                       $result[$row->img_name] = $this->newFileFromRow( $row );
+                       unset( $titles[$indices[$row->img_name]] );
+               }
+               $res->free();
+               return $result;
+       }
 }
index 00c1a29..2a63de9 100644 (file)
@@ -76,6 +76,18 @@ class RepoGroup {
                }
                return false;
        }
+       function findFiles( $titles, $time = false, $flags = 0 ) {
+               if ( !$this->reposInitialised ) {
+                       $this->initialiseRepos();
+               }
+
+               $images = $this->localRepo->findFiles( $titles, $time, $flags );
+
+               foreach ( $this->foreignRepos as $repo ) {
+                       $images = array_merge( $images, $repo->findFiles( $titles, $time, $flags ) );
+               }
+               return $images;
+       }
 
        /**
         * Interface for FileRepo::checkRedirect()