MediaWiki  master
ThumbnailRenderJob.php
Go to the documentation of this file.
1 <?php
26 
32 class ThumbnailRenderJob extends Job {
33  public function __construct( Title $title, array $params ) {
34  parent::__construct( 'ThumbnailRender', $title, $params );
35  }
36 
37  public function run() {
38  $uploadThumbnailRenderMethod = MediaWikiServices::getInstance()
39  ->getMainConfig()->get( MainConfigNames::UploadThumbnailRenderMethod );
40 
41  $transformParams = $this->params['transformParams'];
42 
43  $file = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo()
44  ->newFile( $this->title );
45  $file->load( File::READ_LATEST );
46 
47  if ( $file && $file->exists() ) {
48  if ( $uploadThumbnailRenderMethod === 'jobqueue' ) {
49  $thumb = $file->transform( $transformParams, File::RENDER_NOW );
50 
51  if ( !$thumb || $thumb->isError() ) {
52  if ( $thumb instanceof MediaTransformError ) {
53  $this->setLastError( __METHOD__ . ': thumbnail couln\'t be generated:' .
54  $thumb->toText() );
55  } else {
56  $this->setLastError( __METHOD__ . ': thumbnail couln\'t be generated' );
57  }
58  return false;
59  }
60  return true;
61  } elseif ( $uploadThumbnailRenderMethod === 'http' ) {
62  return $this->hitThumbUrl( $file, $transformParams );
63  } else {
64  $this->setLastError( __METHOD__ . ': unknown thumbnail render method ' .
65  $uploadThumbnailRenderMethod );
66  return false;
67  }
68  } else {
69  $this->setLastError( __METHOD__ . ': file doesn\'t exist' );
70  return false;
71  }
72  }
73 
79  protected function hitThumbUrl( LocalFile $file, $transformParams ) {
80  $config = MediaWikiServices::getInstance()->getMainConfig();
81  $uploadThumbnailRenderHttpCustomHost =
82  $config->get( MainConfigNames::UploadThumbnailRenderHttpCustomHost );
83  $uploadThumbnailRenderHttpCustomDomain =
84  $config->get( MainConfigNames::UploadThumbnailRenderHttpCustomDomain );
85  $handler = $file->getHandler();
86  if ( !$handler ) {
87  $this->setLastError( __METHOD__ . ': could not get handler' );
88  return false;
89  } elseif ( !$handler->normaliseParams( $file, $transformParams ) ) {
90  $this->setLastError( __METHOD__ . ': failed to normalize' );
91  return false;
92  }
93  $thumbName = $file->thumbName( $transformParams );
94  $thumbUrl = $file->getThumbUrl( $thumbName );
95 
96  if ( $thumbUrl === null ) {
97  $this->setLastError( __METHOD__ . ': could not get thumb URL' );
98  return false;
99  }
100 
101  if ( $uploadThumbnailRenderHttpCustomDomain ) {
102  $parsedUrl = wfParseUrl( $thumbUrl );
103 
104  if ( !isset( $parsedUrl['path'] ) || $parsedUrl['path'] === '' ) {
105  $this->setLastError( __METHOD__ . ": invalid thumb URL: $thumbUrl" );
106  return false;
107  }
108 
109  $thumbUrl = '//' . $uploadThumbnailRenderHttpCustomDomain . $parsedUrl['path'];
110  }
111 
112  wfDebug( __METHOD__ . ": hitting url {$thumbUrl}" );
113 
114  // T203135 We don't wait for the request to complete, as this is mostly fire & forget.
115  // Looking at the HTTP status of requests that take less than 1s is a double check.
116  $request = MediaWikiServices::getInstance()->getHttpRequestFactory()->create(
117  $thumbUrl,
118  [ 'method' => 'HEAD', 'followRedirects' => true, 'timeout' => 1 ],
119  __METHOD__
120  );
121 
122  if ( $uploadThumbnailRenderHttpCustomHost ) {
123  $request->setHeader( 'Host', $uploadThumbnailRenderHttpCustomHost );
124  }
125 
126  $status = $request->execute();
127  $statusCode = $request->getStatus();
128  wfDebug( __METHOD__ . ": received status {$statusCode}" );
129 
130  // 400 happens when requesting a size greater or equal than the original
131  // TODO use proper error signaling. 400 could mean a number of other things.
132  if ( $statusCode === 200 || $statusCode === 301 || $statusCode === 302 || $statusCode === 400 ) {
133  return true;
134  } elseif ( $statusCode ) {
135  $this->setLastError( __METHOD__ . ": incorrect HTTP status $statusCode when hitting $thumbUrl" );
136  } elseif ( $status->hasMessage( 'http-timed-out' ) ) {
137  // T203135 we ignore timeouts, as it would be inefficient for this job to wait for
138  // minutes for the slower thumbnails to complete.
139  return true;
140  } else {
141  $this->setLastError( __METHOD__ . ': HTTP request failure: '
142  . Status::wrap( $status )->getWikiText( false, false, 'en' ) );
143  }
144  return false;
145  }
146 
151  public function allowRetries() {
152  // ThumbnailRenderJob is a warmup for the thumbnails cache,
153  // so loosing it is not a problem. Most times the job fails
154  // for non-renderable or missing images which will not be fixed
155  // by a retry, but will create additional load on the renderer.
156  return false;
157  }
158 }
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfParseUrl( $url)
parse_url() work-alike, but non-broken.
const RENDER_NOW
Force rendering in the current process.
Definition: File.php:78
Class to both describe a background job and handle jobs.
Definition: Job.php:39
Title $title
Definition: Job.php:50
setLastError( $error)
Definition: Job.php:469
array $params
Array of job parameters.
Definition: Job.php:44
Local file in the wiki's own database.
Definition: LocalFile.php:60
Basic media transform error class.
A class containing constants representing the names of configuration variables.
MediaWikiServices is the service locator for the application scope of MediaWiki.
static wrap( $sv)
Succinct helper method to wrap a StatusValue.
Definition: Status.php:62
Job for asynchronous rendering of thumbnails.
__construct(Title $title, array $params)
hitThumbUrl(LocalFile $file, $transformParams)
allowRetries()
Whether to retry the job.
Represents a title within MediaWiki.
Definition: Title.php:49
if(PHP_SAPI !='cli-server') if(!isset( $_SERVER['SCRIPT_FILENAME'])) $file
Item class for a filearchive table row.
Definition: router.php:42