width; } /** * @return int Height of the output box */ public function getHeight() { return $this->height; } /** * @return File */ public function getFile() { return $this->file; } /** * Get the final extension of the thumbnail. * Returns false for scripted transformations. * @return string|bool */ public function getExtension() { return $this->path ? FileBackend::extensionFromPath( $this->path ) : false; } /** * @return string|bool The thumbnail URL */ public function getUrl() { return $this->url; } /** * @return string|bool The permanent thumbnail storage path */ public function getStoragePath() { return $this->storagePath; } /** * @param string $storagePath The permanent storage path * @return void */ public function setStoragePath( $storagePath ) { $this->storagePath = $storagePath; if ( $this->path === false ) { $this->path = $storagePath; } } /** * Fetch HTML for this transform output * * @param array $options Associative array of options. Boolean options * should be indicated with a value of true for true, and false or * absent for false. * * alt Alternate text or caption * desc-link Boolean, show a description link * file-link Boolean, show a file download link * custom-url-link Custom URL to link to * custom-title-link Custom Title object to link to * valign vertical-align property, if the output is an inline element * img-class Class applied to the "" tag, if there is such a tag * * For images, desc-link and file-link are implemented as a click-through. For * sounds and videos, they may be displayed in other ways. * * @return string */ abstract public function toHtml( $options = [] ); /** * This will be overridden to return true in error classes * @return bool */ public function isError() { return false; } /** * Check if an output thumbnail file actually exists. * * This will return false if there was an error, the * thumbnail is to be handled client-side only, or if * transformation was deferred via TRANSFORM_LATER. * This file may exist as a new file in /tmp, a file * in permanent storage, or even refer to the original. * * @return bool */ public function hasFile() { // If TRANSFORM_LATER, $this->path will be false. // Note: a null path means "use the source file". return ( !$this->isError() && ( $this->path || $this->path === null ) ); } /** * Check if the output thumbnail is the same as the source. * This can occur if the requested width was bigger than the source. * * @return bool */ public function fileIsSource() { return ( !$this->isError() && $this->path === null ); } /** * Get the path of a file system copy of the thumbnail. * Callers should never write to this path. * * @return string|bool Returns false if there isn't one */ public function getLocalCopyPath() { if ( $this->isError() ) { return false; } elseif ( $this->path === null ) { return $this->file->getLocalRefPath(); // assume thumb was not scaled } elseif ( FileBackend::isStoragePath( $this->path ) ) { $be = $this->file->getRepo()->getBackend(); // The temp file will be process cached by FileBackend $fsFile = $be->getLocalReference( [ 'src' => $this->path ] ); return $fsFile ? $fsFile->getPath() : false; } else { return $this->path; // may return false } } /** * Stream the file if there were no errors * * @param array $headers Additional HTTP headers to send on success * @return Status * @since 1.27 */ public function streamFileWithStatus( $headers = [] ) { if ( !$this->path ) { return Status::newFatal( 'backend-fail-stream', '' ); } elseif ( FileBackend::isStoragePath( $this->path ) ) { $be = $this->file->getRepo()->getBackend(); return $be->streamFile( [ 'src' => $this->path, 'headers' => $headers ] ); } else { // FS-file $success = StreamFile::stream( $this->getLocalCopyPath(), $headers ); return $success ? Status::newGood() : Status::newFatal( 'backend-fail-stream', $this->path ); } } /** * Stream the file if there were no errors * * @deprecated since 1.26, use streamFileWithStatus * @param array $headers Additional HTTP headers to send on success * @return bool Success */ public function streamFile( $headers = [] ) { return $this->streamFileWithStatus( $headers )->isOK(); } /** * Wrap some XHTML text in an anchor tag with the given attributes * * @param array $linkAttribs * @param string $contents * @return string */ protected function linkWrap( $linkAttribs, $contents ) { if ( $linkAttribs ) { return Xml::tags( 'a', $linkAttribs, $contents ); } else { return $contents; } } /** * @param string|null $title * @param string|array $params Query parameters to add * @return array */ public function getDescLinkAttribs( $title = null, $params = [] ) { if ( is_array( $params ) ) { $query = $params; } else { $query = []; } if ( $this->page && $this->page !== 1 ) { $query['page'] = $this->page; } if ( $this->lang ) { $query['lang'] = $this->lang; } if ( is_string( $params ) && $params !== '' ) { $query = $params . '&' . wfArrayToCgi( $query ); } $attribs = [ 'href' => $this->file->getTitle()->getLocalURL( $query ), 'class' => 'image', ]; if ( $title ) { $attribs['title'] = $title; } return $attribs; } }