Allow affiliations to carry project ownership information; transform profile

images correctly

Summary:
This is sort of doing two things at once:

  - Add an "isOwner" flag to Project Affiliation to lay the groundwork for T237.
  - Rename the "QuickCreate" workflow to "Create" and funnel all creation
through it.
  - Reorganize the image transformation stuff and use it to correctly
crop/resize uploaded images.

Test Plan:
Created and edited projects and affailiations. Uploaded project, user, and
profile photos. Verified existing thumbnailing in Maniphest still works
properly.

Reviewed By: cadamo
Reviewers: cadamo, aran, jungejason, tuomaspelkonen
CC: aran, epriestley, cadamo
Differential Revision: 529
This commit is contained in:
epriestley
2011-06-26 08:37:47 -07:00
parent 63436ad74a
commit e0e6ec9117
19 changed files with 266 additions and 114 deletions

View File

@@ -56,9 +56,6 @@ class PhabricatorFileTransformController extends PhabricatorFileController {
case 'thumb-60x45':
$xformed_file = $this->executeThumbTransform($file, 60, 45);
break;
case 'profile-50x50':
$xformed_file = $this->executeProfile50x50Transform($file);
break;
default:
return new Aphront400Response();
}
@@ -118,61 +115,9 @@ class PhabricatorFileTransformController extends PhabricatorFileController {
PhabricatorFileURI::getViewURIForPHID($xform->getTransformedPHID()));
}
private function executeProfile50x50Transform(PhabricatorFile $file) {
$data = $file->loadFileData();
$jpeg = $this->crudelyScaleTo($data, 50, 50);
return PhabricatorFile::newFromFileData($jpeg, array(
'name' => 'profile-'.$file->getName(),
));
}
private function executeThumbTransform(PhabricatorFile $file, $x, $y) {
$data = $file->loadFileData();
$jpeg = $this->crudelyScaleTo($data, $x, $y);
return PhabricatorFile::newFromFileData($jpeg, array(
'name' => 'thumb-'.$file->getName(),
));
}
/**
* Very crudely scale an image up or down to an exact size.
*/
private function crudelyScaleTo($data, $dx, $dy) {
$src = imagecreatefromstring($data);
$x = imagesx($src);
$y = imagesy($src);
$scale = min($x / $dx, $y / $dy);
$dst = imagecreatetruecolor($dx, $dy);
imagecopyresampled(
$dst,
$src,
0, 0,
0, 0,
$dx, $dy,
$scale * $dx, $scale * $dy);
$img = null;
if (function_exists('imagejpeg')) {
ob_start();
imagejpeg($dst);
$img = ob_get_clean();
} else if (function_exists('imagepng')) {
ob_start();
imagepng($dst);
$img = ob_get_clean();
} else if (function_exists('imagegif')) {
ob_start();
imagegif($dst);
$img = ob_get_clean();
} else {
throw new Exception("No image generation functions exist!");
}
return $img;
$xformer = new PhabricatorImageTransformer();
return $xformer->executeThumbTransform($file, $x, $y);
}
}

View File

@@ -12,6 +12,7 @@ phutil_require_module('phabricator', 'aphront/response/redirect');
phutil_require_module('phabricator', 'applications/files/controller/base');
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_module('phabricator', 'applications/files/storage/transformed');
phutil_require_module('phabricator', 'applications/files/transform');
phutil_require_module('phabricator', 'applications/files/uri');
phutil_require_module('phutil', 'utils');

View File

@@ -0,0 +1,125 @@
<?php
/*
* Copyright 2011 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final class PhabricatorImageTransformer {
public function executeThumbTransform(
PhabricatorFile $file,
$x,
$y) {
$data = $file->loadFileData();
$image = $this->crudelyScaleTo($data, $x, $y);
return PhabricatorFile::newFromFileData(
$image,
array(
'name' => 'thumb-'.$file->getName(),
));
}
public function executeProfileTransform(
PhabricatorFile $file,
$x,
$min_y,
$max_y) {
$data = $file->loadFileData();
$image = $this->crudelyCropTo($data, $x, $min_y, $max_y);
return PhabricatorFile::newFromFileData(
$image,
array(
'name' => 'profile-'.$file->getName(),
));
}
private function crudelyCropTo($data, $x, $min_y, $max_y) {
$img = imagecreatefromstring($data);
$sx = imagesx($img);
$sy = imagesy($img);
$scaled_y = ($x / $sx) * $sy;
if ($scaled_y > $max_y) {
// This image is very tall and thin.
$scaled_y = $max_y;
} else if ($scaled_y < $min_y) {
// This image is very short and wide.
$scaled_y = $min_y;
}
$img = $this->applyScaleTo(
$img,
$x,
$scaled_y);
return $this->saveImageDataInAnyFormat($img);
}
/**
* Very crudely scale an image up or down to an exact size.
*/
private function crudelyScaleTo($data, $dx, $dy) {
$src = imagecreatefromstring($data);
$dst = $this->applyScaleTo($src, $dx, $dy);
return $this->saveImageDataInAnyFormat($dst);
}
private function applyScaleTo($src, $dx, $dy) {
$x = imagesx($src);
$y = imagesy($src);
$scale = min($x / $dx, $y / $dy);
$dst = imagecreatetruecolor($dx, $dy);
imagecopyresampled(
$dst,
$src,
0, 0,
0, 0,
$dx, $dy,
$scale * $dx, $scale * $dy);
return $dst;
}
private function saveImageDataInAnyFormat($data) {
$img = null;
if (function_exists('imagejpeg')) {
ob_start();
imagejpeg($data);
$img = ob_get_clean();
} else if (function_exists('imagepng')) {
ob_start();
imagepng($data);
$img = ob_get_clean();
} else if (function_exists('imagegif')) {
ob_start();
imagegif($data);
$img = ob_get_clean();
} else {
throw new Exception("No image generation functions exist!");
}
return $img;
}
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* This file is automatically generated. Lint this module to rebuild it.
* @generated
*/
phutil_require_module('phabricator', 'applications/files/storage/file');
phutil_require_source('PhabricatorImageTransformer.php');