From 06c09e9835292afd5fbd97e1a3094821ca86e6f1 Mon Sep 17 00:00:00 2001 From: Bryan Tong Minh Date: Tue, 20 May 2008 17:05:57 +0000 Subject: [PATCH] Add RepoGroup::findFiles to efficiently find many files if the repo supports it. Added support for this in ApiQueryImageInfo. --- includes/api/ApiQueryImageInfo.php | 69 +++++++++++++++--------------- includes/filerepo/File.php | 19 +++++++- includes/filerepo/FileRepo.php | 15 +++++++ includes/filerepo/LocalRepo.php | 32 ++++++++++++++ includes/filerepo/RepoGroup.php | 12 ++++++ 5 files changed, 111 insertions(+), 36 deletions(-) diff --git a/includes/api/ApiQueryImageInfo.php b/includes/api/ApiQueryImageInfo.php index bb8aed8a09..e787f4c593 100644 --- a/includes/api/ApiQueryImageInfo.php +++ b/includes/api/ApiQueryImageInfo.php @@ -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', '' + ); } } diff --git a/includes/filerepo/File.php b/includes/filerepo/File.php index 6e5c72489a..317ac2ef96 100644 --- a/includes/filerepo/File.php +++ b/includes/filerepo/File.php @@ -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; diff --git a/includes/filerepo/FileRepo.php b/includes/filerepo/FileRepo.php index 61f42f4a10..bf06aefee8 100644 --- a/includes/filerepo/FileRepo.php +++ b/includes/filerepo/FileRepo.php @@ -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 diff --git a/includes/filerepo/LocalRepo.php b/includes/filerepo/LocalRepo.php index 41e70f1fc0..452def0a35 100644 --- a/includes/filerepo/LocalRepo.php +++ b/includes/filerepo/LocalRepo.php @@ -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; + } } diff --git a/includes/filerepo/RepoGroup.php b/includes/filerepo/RepoGroup.php index 00c1a29f95..2a63de99d0 100644 --- a/includes/filerepo/RepoGroup.php +++ b/includes/filerepo/RepoGroup.php @@ -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() -- 2.20.1