MediaWiki
REL1_19
|
00001 <?php 00014 abstract class MediaHandler { 00015 const TRANSFORM_LATER = 1; 00016 const METADATA_GOOD = true; 00017 const METADATA_BAD = false; 00018 const METADATA_COMPATIBLE = 2; // for old but backwards compatible. 00022 static $handlers = array(); 00023 00031 static function getHandler( $type ) { 00032 global $wgMediaHandlers; 00033 if ( !isset( $wgMediaHandlers[$type] ) ) { 00034 wfDebug( __METHOD__ . ": no handler found for $type.\n"); 00035 return false; 00036 } 00037 $class = $wgMediaHandlers[$type]; 00038 if ( !isset( self::$handlers[$class] ) ) { 00039 self::$handlers[$class] = new $class; 00040 if ( !self::$handlers[$class]->isEnabled() ) { 00041 self::$handlers[$class] = false; 00042 } 00043 } 00044 return self::$handlers[$class]; 00045 } 00046 00051 abstract function getParamMap(); 00052 00061 abstract function validateParam( $name, $value ); 00062 00068 abstract function makeParamString( $params ); 00069 00075 abstract function parseParamString( $str ); 00076 00084 abstract function normaliseParams( $image, &$params ); 00085 00094 abstract function getImageSize( $image, $path ); 00095 00104 function getMetadata( $image, $path ) { return ''; } 00105 00121 static function getMetadataVersion () { 00122 $version = Array( '2' ); // core metadata version 00123 wfRunHooks('GetMetadataVersion', Array(&$version)); 00124 return implode( ';', $version); 00125 } 00126 00137 function convertMetadataVersion( $metadata, $version = 1 ) { 00138 if ( !is_array( $metadata ) ) { 00139 00140 //unserialize to keep return parameter consistent. 00141 wfSuppressWarnings(); 00142 $ret = unserialize( $metadata ); 00143 wfRestoreWarnings(); 00144 return $ret; 00145 } 00146 return $metadata; 00147 } 00148 00154 function getMetadataType( $image ) { return false; } 00155 00164 function isMetadataValid( $image, $metadata ) { 00165 return self::METADATA_GOOD; 00166 } 00167 00168 00177 function getScriptedTransform( $image, $script, $params ) { 00178 return false; 00179 } 00180 00190 final function getTransform( $image, $dstPath, $dstUrl, $params ) { 00191 return $this->doTransform( $image, $dstPath, $dstUrl, $params, self::TRANSFORM_LATER ); 00192 } 00193 00206 abstract function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ); 00207 00212 function getThumbType( $ext, $mime, $params = null ) { 00213 $magic = MimeMagic::singleton(); 00214 if ( !$ext || $magic->isMatchingExtension( $ext, $mime ) === false ) { 00215 // The extension is not valid for this mime type and we do 00216 // recognize the mime type 00217 $extensions = $magic->getExtensionsForType( $mime ); 00218 if ( $extensions ) { 00219 return array( strtok( $extensions, ' ' ), $mime ); 00220 } 00221 } 00222 00223 // The extension is correct (true) or the mime type is unknown to 00224 // MediaWiki (null) 00225 return array( $ext, $mime ); 00226 } 00227 00231 function canRender( $file ) { return true; } 00236 function mustRender( $file ) { return false; } 00240 function isMultiPage( $file ) { return false; } 00244 function pageCount( $file ) { return false; } 00248 function isVectorized( $file ) { return false; } 00252 function isEnabled() { return true; } 00253 00262 function getPageDimensions( $image, $page ) { 00263 $gis = $this->getImageSize( $image, $image->getLocalRefPath() ); 00264 return array( 00265 'width' => $gis[0], 00266 'height' => $gis[1] 00267 ); 00268 } 00269 00274 function getPageText( $image, $page ) { 00275 return false; 00276 } 00277 00304 function formatMetadata( $image ) { 00305 return false; 00306 } 00307 00317 function formatMetadataHelper( $metadataArray ) { 00318 $result = array( 00319 'visible' => array(), 00320 'collapsed' => array() 00321 ); 00322 00323 $formatted = FormatMetadata::getFormattedData( $metadataArray ); 00324 // Sort fields into visible and collapsed 00325 $visibleFields = $this->visibleMetadataFields(); 00326 foreach ( $formatted as $name => $value ) { 00327 $tag = strtolower( $name ); 00328 self::addMeta( $result, 00329 in_array( $tag, $visibleFields ) ? 'visible' : 'collapsed', 00330 'exif', 00331 $tag, 00332 $value 00333 ); 00334 } 00335 return $result; 00336 } 00337 00345 function visibleMetadataFields() { 00346 $fields = array(); 00347 $lines = explode( "\n", wfMsgForContent( 'metadata-fields' ) ); 00348 foreach( $lines as $line ) { 00349 $matches = array(); 00350 if( preg_match( '/^\\*\s*(.*?)\s*$/', $line, $matches ) ) { 00351 $fields[] = $matches[1]; 00352 } 00353 } 00354 $fields = array_map( 'strtolower', $fields ); 00355 return $fields; 00356 } 00357 00358 00382 protected static function addMeta( &$array, $visibility, $type, $id, $value, $param = false ) { 00383 $msg = wfMessage( "$type-$id", $param ); 00384 if ( $msg->exists() ) { 00385 $name = $msg->text(); 00386 } else { 00387 // This is for future compatibility when using instant commons. 00388 // So as to not display as ugly a name if a new metadata 00389 // property is defined that we don't know about 00390 // (not a major issue since such a property would be collapsed 00391 // by default). 00392 wfDebug( __METHOD__ . ' Unknown metadata name: ' . $id . "\n" ); 00393 $name = wfEscapeWikiText( $id ); 00394 } 00395 $array[$visibility][] = array( 00396 'id' => "$type-$id", 00397 'name' => $name, 00398 'value' => $value 00399 ); 00400 } 00401 00406 function getShortDesc( $file ) { 00407 global $wgLang; 00408 return htmlspecialchars( $wgLang->formatSize( $file->getSize() ) ); 00409 } 00410 00415 function getLongDesc( $file ) { 00416 global $wgLang; 00417 return wfMessage( 'file-info', htmlspecialchars( $wgLang->formatSize( $file->getSize() ) ), 00418 $file->getMimeType() )->parse(); 00419 } 00420 00425 static function getGeneralShortDesc( $file ) { 00426 global $wgLang; 00427 return $wgLang->formatSize( $file->getSize() ); 00428 } 00429 00434 static function getGeneralLongDesc( $file ) { 00435 global $wgLang; 00436 return wfMessage( 'file-info', $wgLang->formatSize( $file->getSize() ), 00437 $file->getMimeType() )->parse(); 00438 } 00439 00448 public static function fitBoxWidth( $boxWidth, $boxHeight, $maxHeight ) { 00449 $idealWidth = $boxWidth * $maxHeight / $boxHeight; 00450 $roundedUp = ceil( $idealWidth ); 00451 if( round( $roundedUp * $boxHeight / $boxWidth ) > $maxHeight ) { 00452 return floor( $idealWidth ); 00453 } else { 00454 return $roundedUp; 00455 } 00456 } 00457 00458 function getDimensionsString( $file ) { 00459 return ''; 00460 } 00461 00465 function parserTransformHook( $parser, $file ) {} 00466 00477 function verifyUpload( $fileName ) { 00478 return Status::newGood(); 00479 } 00480 00489 function removeBadFile( $dstPath, $retval = 0 ) { 00490 if( file_exists( $dstPath ) ) { 00491 $thumbstat = stat( $dstPath ); 00492 if( $thumbstat['size'] == 0 || $retval != 0 ) { 00493 $result = unlink( $dstPath ); 00494 00495 if ( $result ) { 00496 wfDebugLog( 'thumbnail', 00497 sprintf( 'Removing bad %d-byte thumbnail "%s". unlink() succeeded', 00498 $thumbstat['size'], $dstPath ) ); 00499 } else { 00500 wfDebugLog( 'thumbnail', 00501 sprintf( 'Removing bad %d-byte thumbnail "%s". unlink() failed', 00502 $thumbstat['size'], $dstPath ) ); 00503 } 00504 return true; 00505 } 00506 } 00507 return false; 00508 } 00509 00516 public function filterThumbnailPurgeList( &$files, $options ) { 00517 // Do nothing 00518 } 00519 } 00520 00526 abstract class ImageHandler extends MediaHandler { 00527 00532 function canRender( $file ) { 00533 return ( $file->getWidth() && $file->getHeight() ); 00534 } 00535 00536 function getParamMap() { 00537 return array( 'img_width' => 'width' ); 00538 } 00539 00540 function validateParam( $name, $value ) { 00541 if ( in_array( $name, array( 'width', 'height' ) ) ) { 00542 if ( $value <= 0 ) { 00543 return false; 00544 } else { 00545 return true; 00546 } 00547 } else { 00548 return false; 00549 } 00550 } 00551 00552 function makeParamString( $params ) { 00553 if ( isset( $params['physicalWidth'] ) ) { 00554 $width = $params['physicalWidth']; 00555 } elseif ( isset( $params['width'] ) ) { 00556 $width = $params['width']; 00557 } else { 00558 throw new MWException( 'No width specified to '.__METHOD__ ); 00559 } 00560 # Removed for ProofreadPage 00561 #$width = intval( $width ); 00562 return "{$width}px"; 00563 } 00564 00565 function parseParamString( $str ) { 00566 $m = false; 00567 if ( preg_match( '/^(\d+)px$/', $str, $m ) ) { 00568 return array( 'width' => $m[1] ); 00569 } else { 00570 return false; 00571 } 00572 } 00573 00574 function getScriptParams( $params ) { 00575 return array( 'width' => $params['width'] ); 00576 } 00577 00583 function normaliseParams( $image, &$params ) { 00584 $mimeType = $image->getMimeType(); 00585 00586 if ( !isset( $params['width'] ) ) { 00587 return false; 00588 } 00589 00590 if ( !isset( $params['page'] ) ) { 00591 $params['page'] = 1; 00592 } else { 00593 $params['page'] = intval( $params['page'] ); 00594 if ( $params['page'] > $image->pageCount() ) { 00595 $params['page'] = $image->pageCount(); 00596 } 00597 00598 if ( $params['page'] < 1 ) { 00599 $params['page'] = 1; 00600 } 00601 } 00602 00603 $srcWidth = $image->getWidth( $params['page'] ); 00604 $srcHeight = $image->getHeight( $params['page'] ); 00605 00606 if ( isset( $params['height'] ) && $params['height'] != -1 ) { 00607 # Height & width were both set 00608 if ( $params['width'] * $srcHeight > $params['height'] * $srcWidth ) { 00609 # Height is the relative smaller dimension, so scale width accordingly 00610 $params['width'] = self::fitBoxWidth( $srcWidth, $srcHeight, $params['height'] ); 00611 00612 if ( $params['width'] == 0 ) { 00613 # Very small image, so we need to rely on client side scaling :( 00614 $params['width'] = 1; 00615 } 00616 00617 $params['physicalWidth'] = $params['width']; 00618 } else { 00619 # Height was crap, unset it so that it will be calculated later 00620 unset( $params['height'] ); 00621 } 00622 } 00623 00624 if ( !isset( $params['physicalWidth'] ) ) { 00625 # Passed all validations, so set the physicalWidth 00626 $params['physicalWidth'] = $params['width']; 00627 } 00628 00629 # Because thumbs are only referred to by width, the height always needs 00630 # to be scaled by the width to keep the thumbnail sizes consistent, 00631 # even if it was set inside the if block above 00632 $params['physicalHeight'] = File::scaleHeight( $srcWidth, $srcHeight, 00633 $params['physicalWidth'] ); 00634 00635 # Set the height if it was not validated in the if block higher up 00636 if ( !isset( $params['height'] ) || $params['height'] == -1 ) { 00637 $params['height'] = $params['physicalHeight']; 00638 } 00639 00640 00641 if ( !$this->validateThumbParams( $params['physicalWidth'], 00642 $params['physicalHeight'], $srcWidth, $srcHeight, $mimeType ) ) { 00643 return false; 00644 } 00645 return true; 00646 } 00647 00658 function validateThumbParams( &$width, &$height, $srcWidth, $srcHeight, $mimeType ) { 00659 $width = intval( $width ); 00660 00661 # Sanity check $width 00662 if( $width <= 0) { 00663 wfDebug( __METHOD__.": Invalid destination width: $width\n" ); 00664 return false; 00665 } 00666 if ( $srcWidth <= 0 ) { 00667 wfDebug( __METHOD__.": Invalid source width: $srcWidth\n" ); 00668 return false; 00669 } 00670 00671 $height = File::scaleHeight( $srcWidth, $srcHeight, $width ); 00672 if ( $height == 0 ) { 00673 # Force height to be at least 1 pixel 00674 $height = 1; 00675 } 00676 return true; 00677 } 00678 00685 function getScriptedTransform( $image, $script, $params ) { 00686 if ( !$this->normaliseParams( $image, $params ) ) { 00687 return false; 00688 } 00689 $url = $script . '&' . wfArrayToCGI( $this->getScriptParams( $params ) ); 00690 $page = isset( $params['page'] ) ? $params['page'] : false; 00691 00692 if( $image->mustRender() || $params['width'] < $image->getWidth() ) { 00693 return new ThumbnailImage( $image, $url, $params['width'], $params['height'], $page ); 00694 } 00695 } 00696 00697 function getImageSize( $image, $path ) { 00698 wfSuppressWarnings(); 00699 $gis = getimagesize( $path ); 00700 wfRestoreWarnings(); 00701 return $gis; 00702 } 00703 00704 function isAnimatedImage( $image ) { 00705 return false; 00706 } 00707 00712 function getShortDesc( $file ) { 00713 global $wgLang; 00714 $nbytes = htmlspecialchars( $wgLang->formatSize( $file->getSize() ) ); 00715 $widthheight = wfMessage( 'widthheight' )->numParams( $file->getWidth(), $file->getHeight() )->escaped(); 00716 00717 return "$widthheight ($nbytes)"; 00718 } 00719 00724 function getLongDesc( $file ) { 00725 global $wgLang; 00726 $pages = $file->pageCount(); 00727 $size = htmlspecialchars( $wgLang->formatSize( $file->getSize() ) ); 00728 if ( $pages === false || $pages <= 1 ) { 00729 $msg = wfMessage( 'file-info-size' )->numParams( $file->getWidth(), 00730 $file->getHeight() )->params( $size, 00731 $file->getMimeType() )->parse(); 00732 } else { 00733 $msg = wfMessage( 'file-info-size-pages' )->numParams( $file->getWidth(), 00734 $file->getHeight() )->params( $size, 00735 $file->getMimeType() )->numParams( $pages )->parse(); 00736 } 00737 return $msg; 00738 } 00739 00744 function getDimensionsString( $file ) { 00745 $pages = $file->pageCount(); 00746 if ( $pages > 1 ) { 00747 return wfMessage( 'widthheightpage' )->numParams( $file->getWidth(), $file->getHeight(), $pages )->text(); 00748 } else { 00749 return wfMessage( 'widthheight' )->numParams( $file->getWidth(), $file->getHeight() )->text(); 00750 } 00751 } 00752 }