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:
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
|
||||
125
src/applications/files/transform/PhabricatorImageTransformer.php
Normal file
125
src/applications/files/transform/PhabricatorImageTransformer.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
12
src/applications/files/transform/__init__.php
Normal file
12
src/applications/files/transform/__init__.php
Normal 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');
|
||||
Reference in New Issue
Block a user