(bug 26548) Make multi-paged documents (PDFs) work with ForeignAPIRepo (aka InstantCo...
authorBrian Wolff <bawolff@users.mediawiki.org>
Sat, 5 Feb 2011 08:49:48 +0000 (08:49 +0000)
committerBrian Wolff <bawolff@users.mediawiki.org>
Sat, 5 Feb 2011 08:49:48 +0000 (08:49 +0000)
This adds a new parameter to the query=imageinfo (and query=stashimageinfo) that takes rendering
parameters other than width and height. This could be page for pdf's and DjVu, or thumbtime for ogg's, etc.
Syntax is &iiurlparam=param1=value1|param2=value2|... I'm not sure if that really fits with the normal way
of doing things in the api, but couldn't think of anything better since the parameters are arbitrary.

I also noticed that some of the pre-existing error codes in query=imageinfo seem to duplicate the module prefix. I'm
not sure what the deal with that is, but i did not follow that example in the new error codes i introduced.

Note: In order for this to work, both the foreign repo and the local wiki have to be running this code.

RELEASE-NOTES
includes/api/ApiQueryImageInfo.php
includes/api/ApiQueryStashImageInfo.php
includes/filerepo/ForeignAPIFile.php
includes/filerepo/ForeignAPIRepo.php

index 8842420..96a7da6 100644 (file)
@@ -115,6 +115,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * (bug 19751) Filesystem is now checked during image undeletion
 * Send last modified headers for Special:Recentchanges when RC patrol is
   enabled, but user cannot see rc patrol links.
+* (bug 26548) ForeignAPIRepo (InstantCommons) now works with PDF files
+  and other multi-paged file formats.
 
 === API changes in 1.18 ===
 * (bug 26339) Throw warning when truncating an overlarge API result
@@ -140,6 +142,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * (bug 26650) Remove $wgAPICacheHelp in favour of $wgAPICacheHelpTimeout
 * (bug 24650) Fix API to work with categorylinks changes
 * Expose list of skins in meta=siteinfo
+* (bug 26548) Add iiurlparam param to query=imageinfo and query=stashimageinfo
 
 === Languages updated in 1.18 ===
 
index 02def1a..355d172 100644 (file)
@@ -50,7 +50,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
 
                $prop = array_flip( $params['prop'] );
 
-               $scale = $this->getScale( $params );
+               $thumbParams = $this->makeThumbParams( $params );
 
                $pageIds = $this->getPageSet()->getAllTitlesByNamespace();
                if ( !empty( $pageIds[NS_FILE] ) ) {
@@ -117,8 +117,9 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                )
                                {
                                        $gotOne = true;
+                                       $this->validateThumbParams( $img, $thumbParams );
                                        $fit = $this->addPageSubItem( $pageId,
-                                               self::getInfo( $img, $prop, $result, $scale ) );
+                                               self::getInfo( $img, $prop, $result, $thumbParams ) );
                                        if ( !$fit ) {
                                                if ( count( $pageIds[NS_IMAGE] ) == 1 ) {
                                                        // See the 'the user is screwed' comment above
@@ -184,9 +185,25 @@ class ApiQueryImageInfo extends ApiQueryBase {
         * @return Array or Null: key-val array of 'width' and 'height', or null
         */
        public function getScale( $params ) {
+               wfDeprecated( __METHOD__ );
+               if ( !isset( $params['urlparam'] ) ) {
+                       // In case there are subclasses that
+                       // don't have this param set to anything.
+                       $params['urlparam'] = null;
+               }
+               return $this->makeThumbParams( $params );
+       }
+
+       /* Take parameters for transforming thumbnail, validate and turn into array.
+        * @param $params Array: Parameters from the request.
+        * @return Array or null: If array, suitable to passing to $file->transform.
+        */
+       public function makeThumbParams( $params ) {
                $p = $this->getModulePrefix();
+
+               // Height and width.
                if ( $params['urlheight'] != -1 && $params['urlwidth'] == -1 ) {
-                       $this->dieUsage( "${p}urlheight cannot be used without {$p}urlwidth", "{$p}urlwidth" );
+                       $this->dieUsage( "{$p}urlheight cannot be used without {$p}urlwidth", "{$p}urlwidth" );
                }
 
                if ( $params['urlwidth'] != -1 ) {
@@ -195,10 +212,56 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        $scale['height'] = $params['urlheight'];
                } else {
                        $scale = null;
+                       if ( $params['urlparam'] ) {
+                               $this->dieUsage( "{$p}urlparam requires {$p}urlwidth", "urlparam_no_width" );
+                       }
+                       return $scale;
+               }
+
+               // Other parameters.
+               if ( is_array( $params['urlparam'] ) ) {
+                       foreach( $params['urlparam'] as $item ) {
+                               $parameter = explode( '=', $item, 2 );
+
+                               if ( count( $parameter ) !== 2
+                                       || $parameter[0] === 'width'
+                                       || $parameter[0] === 'height'
+                               ) {
+                                       $this->dieUsage( "Invalid value for {$p}urlparam ($item)", "urlparam" );
+                               }
+                               $scale[$parameter[0]] = $parameter[1];
+                       }
                }
                return $scale;
        }
 
+       /** Validate the thumb parameters, give error if invalid.
+        *
+        * We do this later than makeThumbParams, since we need the image
+        * to know which handler, since handlers can make their own parameters.
+        * @param File $image Image that params are for.
+        * @param Array $thumbParams thumbnail parameters
+        */
+       protected function validateThumbParams ( $image, $thumbParams ) {
+               if ( !$thumbParams ) return;
+               $p = $this->getModulePrefix();
+
+               $h = $image->getHandler();
+               if ( !h ) {
+                       // No handler, so no value for iiurlparam is valid.
+                       $this->dieUsage( "Invalid value for {$p}urlparam", "urlparam" );
+               }
+               foreach ( $thumbParams as $name => $value ) {
+                       if ( !$h->validateParam( $name, $value ) ) {
+                               /* This doesn't work well with height=-1 placeholder */
+                               if ( $name === 'height' ) continue;
+                               $this->dieUsage( "Invalid value for {$p}urlparam ($name=$value)", "urlparam" );
+                       }
+               }
+               // This could also potentially check normaliseParams as well, However that seems
+               // to fall more into a thumbnail rendering error than a user input error, and
+               // will be checked by the transform functions.
+       }
 
        /**
         * Get result information for an image revision
@@ -206,10 +269,10 @@ class ApiQueryImageInfo extends ApiQueryBase {
         * @param $file File object
         * @param $prop Array of properties to get (in the keys)
         * @param $result ApiResult object
-        * @param $scale Array containing 'width' and 'height' items, or null
+        * @param $thumbParams Array containing 'width' and 'height' items, or null
         * @return Array: result array
         */
-       static function getInfo( $file, $prop, $result, $scale = null ) {
+       static function getInfo( $file, $prop, $result, $thumbParams = null ) {
                $vals = array();
                if ( isset( $prop['timestamp'] ) ) {
                        $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $file->getTimestamp() );
@@ -237,8 +300,8 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        }
                }
                if ( isset( $prop['url'] ) ) {
-                       if ( !is_null( $scale ) && !$file->isOld() ) {
-                               $mto = $file->transform( array( 'width' => $scale['width'], 'height' => $scale['height'] ) );
+                       if ( !is_null( $thumbParams ) && !$file->isOld() ) {
+                               $mto = $file->transform( $thumbParams );
                                if ( $mto && !$mto->isError() ) {
                                        $vals['thumburl'] = wfExpandUrl( $mto->getUrl() );
 
@@ -352,6 +415,9 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                ApiBase::PARAM_TYPE => 'integer',
                                ApiBase::PARAM_DFLT => -1
                        ),
+                       'urlparam' => array(
+                               ApiBase::PARAM_ISMULTI => true,
+                       ),
                        'continue' => null,
                );
        }
@@ -406,6 +472,8 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        'urlwidth' => array( "If {$p}prop=url is set, a URL to an image scaled to this width will be returned.",
                                            'Only the current version of the image can be scaled' ),
                        'urlheight' => "Similar to {$p}urlwidth. Cannot be used without {$p}urlwidth",
+                       'urlparam' => array( "Other rending parameters, such as page=2 for multipaged documents.",
+                                       "Multiple parameters should be seperated with a |. {$p}urlwidth must also be used"),
                        'limit' => 'How many image revisions to return',
                        'start' => 'Timestamp to start listing from',
                        'end' => 'Timestamp to stop listing at',
@@ -418,8 +486,11 @@ class ApiQueryImageInfo extends ApiQueryBase {
        }
 
        public function getPossibleErrors() {
+               $p = $this->getModulePrefix();
                return array_merge( parent::getPossibleErrors(), array(
                        array( 'code' => 'iiurlwidth', 'info' => 'iiurlheight cannot be used without iiurlwidth' ),
+                       array( 'code' => 'urlparam', 'info' => "Invalid value for {$p}urlparam" ),
+                       array( 'code' => 'urlparam_no_width', 'info' => "iiurlparam requires {$p}urlwidth" ),
                ) );
        }
 
index bcd8196..84f7560 100644 (file)
@@ -37,7 +37,7 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
 
                $prop = array_flip( $params['prop'] );
 
-               $scale = $this->getScale( $params );
+               $scale = $this->makeThumbParams( $params );
 
                $result = $this->getResult();
 
@@ -46,6 +46,7 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
 
                        foreach ( $params['sessionkey'] as $sessionkey ) {
                                $file = $stash->getFile( $sessionkey );
+                               $this->validateThumbParams( $file, $scale );
                                $imageInfo = self::getInfo( $file, $prop, $result, $scale );
                                $result->addValue( array( 'query', $this->getModuleName() ), null, $imageInfo );
                                $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), $modulePrefix );
@@ -97,7 +98,10 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
                        'urlheight' => array(
                                ApiBase::PARAM_TYPE => 'integer',
                                ApiBase::PARAM_DFLT => -1
-                       )
+                       ),
+                       'urlparam' => array(
+                               ApiBase::PARAM_ISMULTI => true,
+                       ),
                );
        }
 
@@ -122,7 +126,9 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
                        ),
                        'sessionkey' => 'Session key that identifies a previous upload that was stashed temporarily.',
                        'urlwidth' => "If {$p}prop=url is set, a URL to an image scaled to this width will be returned.",
-                       'urlheight' => "Similar to {$p}urlwidth. Cannot be used without {$p}urlwidth"
+                       'urlheight' => "Similar to {$p}urlwidth. Cannot be used without {$p}urlwidth",
+                       'urlparam' => array( "Other rending parameters, such as page=2 for multipaged documents.",
+                                       "Multiple parameters should be seperated with a |. {$p}urlwidth must also be used" ),
                );
        }
 
index 56fed75..f78a2a3 100644 (file)
@@ -76,10 +76,25 @@ class ForeignAPIFile extends File {
                        // show icon
                        return parent::transform( $params, $flags );
                }
+
+               $otherParams = "";
+               // Not using implode, since associative array.
+               foreach ( $params as $name => $value ) {
+                       if ( $name === 'width' || $name === 'height' ) {
+                               continue;
+                       }
+                       $otherParams .= "{$name}={$value}|";
+               }
+               // Remove the last |
+               if ( $otherParams !== "" ) {
+                       $otherParams = substr( $otherParams, 0, -1 );
+               }
+
                $thumbUrl = $this->repo->getThumbUrlFromCache(
                        $this->getName(),
                        isset( $params['width'] ) ? $params['width'] : -1,
-                       isset( $params['height'] ) ? $params['height'] : -1 );
+                       isset( $params['height'] ) ? $params['height'] : -1,
+                       $otherParams );
                return $this->handler->getTransform( $this, 'bogus', $thumbUrl, $params );
        }
 
index f465273..3b46f14 100644 (file)
@@ -197,12 +197,13 @@ class ForeignAPIRepo extends FileRepo {
                return $ret;
        }
 
-       function getThumbUrl( $name, $width = -1, $height = -1, &$result = null ) {
+       function getThumbUrl( $name, $width = -1, $height = -1, &$result = null, $otherParams = '' ) {
                $data = $this->fetchImageQuery( array(
                        'titles' => 'File:' . $name,
                        'iiprop' => 'url|timestamp',
                        'iiurlwidth' => $width,
                        'iiurlheight' => $height,
+                       'iiurlparam'  => $otherParams,
                        'prop' => 'imageinfo' ) );
                $info = $this->getImageInfo( $data );
 
@@ -224,15 +225,16 @@ class ForeignAPIRepo extends FileRepo {
         * @param $name String is a dbkey form of a title
         * @param $width
         * @param $height
+        * @param String $param Other rendering parameters (page number, etc). | separated.
         */
-       function getThumbUrlFromCache( $name, $width, $height ) {
+       function getThumbUrlFromCache( $name, $width, $height, $params="" ) {
                global $wgMemc;
 
                if ( !$this->canCacheThumbs() ) {
-                       return $this->getThumbUrl( $name, $width, $height );
+                       return $this->getThumbUrl( $name, $width, $height, null, $params );
                }
                $key = $this->getLocalCacheKey( 'ForeignAPIRepo', 'ThumbUrl', $name );
-               $sizekey = "$width:$height";
+               $sizekey = "$width:$height:$params";
 
                /* Get the array of urls that we already know */
                $knownThumbUrls = $wgMemc->get($key);
@@ -248,7 +250,7 @@ class ForeignAPIRepo extends FileRepo {
                }
 
                $metadata = null;
-               $foreignUrl = $this->getThumbUrl( $name, $width, $height, $metadata );
+               $foreignUrl = $this->getThumbUrl( $name, $width, $height, $metadata, $params );
 
                if( !$foreignUrl ) {
                        wfDebug( __METHOD__ . " Could not find thumburl\n" );
@@ -273,7 +275,7 @@ class ForeignAPIRepo extends FileRepo {
                        $diff = abs( $modified - $current );
                        if( $remoteModified < $modified && $diff < $this->fileCacheExpiry ) {
                                /* Use our current and already downloaded thumbnail */
-                               $knownThumbUrls["$width:$height"] = $localUrl;
+                               $knownThumbUrls[$sizekey] = $localUrl;
                                $wgMemc->set( $key, $knownThumbUrls, $this->apiThumbCacheExpiry );
                                return $localUrl;
                        }