phorge/src/applications/files/controller/PhabricatorFileTransformController.php
epriestley 7e365eb8ae Convert "profile" image transforms to the new pathway
Summary:
Ref T7707. This ends up being sort of complicated: to support 100x100 images in T4406, we need to scale small images //up// so they look OK when we scale them back down with `background-size` in CSS.

The rest of it is mostly straightforward.

Test Plan:
  - Did an OAuth handshake and saw a scaled-up, scaled-down profile picture that looked correct.
  - Used Pholio, edited pholio, embedded pholio.
  - Uploaded a bunch of small/weird/big images and regenerated all their transforms.
  - Uploaded some text files into Pholio.
  - Grepped for removed methods, etc.

Reviewers: chad, btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T7707

Differential Revision: https://secure.phabricator.com/D12818
2015-05-13 11:38:46 -07:00

125 lines
3.4 KiB
PHP

<?php
final class PhabricatorFileTransformController
extends PhabricatorFileController {
public function shouldRequireLogin() {
return false;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
// NOTE: This is a public/CDN endpoint, and permission to see files is
// controlled by knowing the secret key, not by authentication.
$is_regenerate = $request->getBool('regenerate');
$source_phid = $request->getURIData('phid');
$file = id(new PhabricatorFileQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($source_phid))
->executeOne();
if (!$file) {
return new Aphront404Response();
}
$secret_key = $request->getURIData('key');
if (!$file->validateSecretKey($secret_key)) {
return new Aphront403Response();
}
$transform = $request->getURIData('transform');
$xform = id(new PhabricatorTransformedFile())
->loadOneWhere(
'originalPHID = %s AND transform = %s',
$source_phid,
$transform);
if ($xform) {
if ($is_regenerate) {
$this->destroyTransform($xform);
} else {
return $this->buildTransformedFileResponse($xform);
}
}
$xforms = PhabricatorFileTransform::getAllTransforms();
if (!isset($xforms[$transform])) {
return new Aphront404Response();
}
$xform = $xforms[$transform];
// We're essentially just building a cache here and don't need CSRF
// protection.
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$xformed_file = null;
if ($xform->canApplyTransform($file)) {
try {
$xformed_file = $xforms[$transform]->applyTransform($file);
} catch (Exception $ex) {
// In normal transform mode, we ignore failures and generate a
// default transform below. If we're explicitly regenerating the
// thumbnail, rethrow the exception.
if ($is_regenerate) {
throw $ex;
}
}
}
if (!$xformed_file) {
$xformed_file = $xform->getDefaultTransform($file);
}
if (!$xformed_file) {
return new Aphront400Response();
}
$xform = id(new PhabricatorTransformedFile())
->setOriginalPHID($source_phid)
->setTransform($transform)
->setTransformedPHID($xformed_file->getPHID())
->save();
return $this->buildTransformedFileResponse($xform);
}
private function buildTransformedFileResponse(
PhabricatorTransformedFile $xform) {
$file = id(new PhabricatorFileQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($xform->getTransformedPHID()))
->executeOne();
if (!$file) {
return new Aphront404Response();
}
// TODO: We could just delegate to the file view controller instead,
// which would save the client a roundtrip, but is slightly more complex.
return $file->getRedirectResponse();
}
private function destroyTransform(PhabricatorTransformedFile $xform) {
$file = id(new PhabricatorFileQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($xform->getTransformedPHID()))
->executeOne();
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
if (!$file) {
$xform->delete();
} else {
$engine = new PhabricatorDestructionEngine();
$engine->destroyObject($file);
}
unset($unguarded);
}
}