mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 00:42:41 +01:00
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:
parent
63436ad74a
commit
e0e6ec9117
19 changed files with 266 additions and 114 deletions
2
resources/sql/patches/049.projectowner.sql
Normal file
2
resources/sql/patches/049.projectowner.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE phabricator_project.project_affiliation
|
||||||
|
ADD isOwner bool NOT NULL;
|
|
@ -354,6 +354,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorIRCMessage' => 'infrastructure/daemon/irc/message',
|
'PhabricatorIRCMessage' => 'infrastructure/daemon/irc/message',
|
||||||
'PhabricatorIRCObjectNameHandler' => 'infrastructure/daemon/irc/handler/objectname',
|
'PhabricatorIRCObjectNameHandler' => 'infrastructure/daemon/irc/handler/objectname',
|
||||||
'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/irc/handler/protocol',
|
'PhabricatorIRCProtocolHandler' => 'infrastructure/daemon/irc/handler/protocol',
|
||||||
|
'PhabricatorImageTransformer' => 'applications/files/transform',
|
||||||
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/javelin',
|
'PhabricatorJavelinLinter' => 'infrastructure/lint/linter/javelin',
|
||||||
'PhabricatorLintEngine' => 'infrastructure/lint/engine',
|
'PhabricatorLintEngine' => 'infrastructure/lint/engine',
|
||||||
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
|
'PhabricatorLiskDAO' => 'applications/base/storage/lisk',
|
||||||
|
@ -428,12 +429,12 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorProjectAffiliation' => 'applications/project/storage/affiliation',
|
'PhabricatorProjectAffiliation' => 'applications/project/storage/affiliation',
|
||||||
'PhabricatorProjectAffiliationEditController' => 'applications/project/controller/editaffiliation',
|
'PhabricatorProjectAffiliationEditController' => 'applications/project/controller/editaffiliation',
|
||||||
'PhabricatorProjectController' => 'applications/project/controller/base',
|
'PhabricatorProjectController' => 'applications/project/controller/base',
|
||||||
|
'PhabricatorProjectCreateController' => 'applications/project/controller/create',
|
||||||
'PhabricatorProjectDAO' => 'applications/project/storage/base',
|
'PhabricatorProjectDAO' => 'applications/project/storage/base',
|
||||||
'PhabricatorProjectListController' => 'applications/project/controller/list',
|
'PhabricatorProjectListController' => 'applications/project/controller/list',
|
||||||
'PhabricatorProjectProfile' => 'applications/project/storage/profile',
|
'PhabricatorProjectProfile' => 'applications/project/storage/profile',
|
||||||
'PhabricatorProjectProfileController' => 'applications/project/controller/profile',
|
'PhabricatorProjectProfileController' => 'applications/project/controller/profile',
|
||||||
'PhabricatorProjectProfileEditController' => 'applications/project/controller/profileedit',
|
'PhabricatorProjectProfileEditController' => 'applications/project/controller/profileedit',
|
||||||
'PhabricatorProjectQuickCreateController' => 'applications/project/controller/quickcreate',
|
|
||||||
'PhabricatorProjectStatus' => 'applications/project/constants/status',
|
'PhabricatorProjectStatus' => 'applications/project/constants/status',
|
||||||
'PhabricatorProjectTransactionSearch' => 'applications/project/transactions/search',
|
'PhabricatorProjectTransactionSearch' => 'applications/project/transactions/search',
|
||||||
'PhabricatorRedirectController' => 'applications/base/controller/redirect',
|
'PhabricatorRedirectController' => 'applications/base/controller/redirect',
|
||||||
|
@ -900,12 +901,12 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO',
|
'PhabricatorProjectAffiliation' => 'PhabricatorProjectDAO',
|
||||||
'PhabricatorProjectAffiliationEditController' => 'PhabricatorProjectController',
|
'PhabricatorProjectAffiliationEditController' => 'PhabricatorProjectController',
|
||||||
'PhabricatorProjectController' => 'PhabricatorController',
|
'PhabricatorProjectController' => 'PhabricatorController',
|
||||||
|
'PhabricatorProjectCreateController' => 'PhabricatorProjectController',
|
||||||
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorProjectDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorProjectListController' => 'PhabricatorProjectController',
|
'PhabricatorProjectListController' => 'PhabricatorProjectController',
|
||||||
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
|
'PhabricatorProjectProfile' => 'PhabricatorProjectDAO',
|
||||||
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
|
'PhabricatorProjectProfileController' => 'PhabricatorProjectController',
|
||||||
'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController',
|
'PhabricatorProjectProfileEditController' => 'PhabricatorProjectController',
|
||||||
'PhabricatorProjectQuickCreateController' => 'PhabricatorProjectController',
|
|
||||||
'PhabricatorRedirectController' => 'PhabricatorController',
|
'PhabricatorRedirectController' => 'PhabricatorController',
|
||||||
'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName',
|
'PhabricatorRemarkupRuleDifferential' => 'PhabricatorRemarkupRuleObjectName',
|
||||||
'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule',
|
'PhabricatorRemarkupRuleDiffusion' => 'PhutilRemarkupRule',
|
||||||
|
|
|
@ -198,12 +198,12 @@ class AphrontDefaultApplicationConfiguration
|
||||||
|
|
||||||
'/project/' => array(
|
'/project/' => array(
|
||||||
'$' => 'PhabricatorProjectListController',
|
'$' => 'PhabricatorProjectListController',
|
||||||
'edit/(?:(?P<id>\d+)/)?$' => 'PhabricatorProjectProfileEditController',
|
'edit/(?P<id>\d+)/$' => 'PhabricatorProjectProfileEditController',
|
||||||
'view/(?P<id>\d+)/(?:(?P<page>\w+)/)?$'
|
'view/(?P<id>\d+)/(?:(?P<page>\w+)/)?$'
|
||||||
=> 'PhabricatorProjectProfileController',
|
=> 'PhabricatorProjectProfileController',
|
||||||
'affiliation/(?P<id>\d+)/$'
|
'affiliation/(?P<id>\d+)/$'
|
||||||
=> 'PhabricatorProjectAffiliationEditController',
|
=> 'PhabricatorProjectAffiliationEditController',
|
||||||
'quickcreate/$' => 'PhabricatorProjectQuickCreateController',
|
'create/$' => 'PhabricatorProjectCreateController',
|
||||||
),
|
),
|
||||||
|
|
||||||
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)$'
|
'/r(?P<callsign>[A-Z]+)(?P<commit>[a-z0-9]+)$'
|
||||||
|
|
|
@ -56,9 +56,6 @@ class PhabricatorFileTransformController extends PhabricatorFileController {
|
||||||
case 'thumb-60x45':
|
case 'thumb-60x45':
|
||||||
$xformed_file = $this->executeThumbTransform($file, 60, 45);
|
$xformed_file = $this->executeThumbTransform($file, 60, 45);
|
||||||
break;
|
break;
|
||||||
case 'profile-50x50':
|
|
||||||
$xformed_file = $this->executeProfile50x50Transform($file);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
return new Aphront400Response();
|
return new Aphront400Response();
|
||||||
}
|
}
|
||||||
|
@ -118,61 +115,9 @@ class PhabricatorFileTransformController extends PhabricatorFileController {
|
||||||
PhabricatorFileURI::getViewURIForPHID($xform->getTransformedPHID()));
|
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) {
|
private function executeThumbTransform(PhabricatorFile $file, $x, $y) {
|
||||||
$data = $file->loadFileData();
|
$xformer = new PhabricatorImageTransformer();
|
||||||
$jpeg = $this->crudelyScaleTo($data, $x, $y);
|
return $xformer->executeThumbTransform($file, $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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||||
phutil_require_module('phabricator', 'applications/files/storage/transformed');
|
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('phabricator', 'applications/files/uri');
|
||||||
|
|
||||||
phutil_require_module('phutil', 'utils');
|
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');
|
|
@ -252,13 +252,15 @@ class ManiphestTaskEditController extends ManiphestController {
|
||||||
javelin_render_tag(
|
javelin_render_tag(
|
||||||
'a',
|
'a',
|
||||||
array(
|
array(
|
||||||
'href' => '/project/quickcreate/',
|
'href' => '/project/create/',
|
||||||
'mustcapture' => true,
|
'mustcapture' => true,
|
||||||
'sigil' => 'project-create',
|
'sigil' => 'project-create',
|
||||||
),
|
),
|
||||||
'Create New Project'))
|
'Create New Project'))
|
||||||
->setDatasource('/typeahead/common/projects/'));
|
->setDatasource('/typeahead/common/projects/'));
|
||||||
|
|
||||||
|
require_celerity_resource('aphront-error-view-css');
|
||||||
|
|
||||||
Javelin::initBehavior('maniphest-project-create', array(
|
Javelin::initBehavior('maniphest-project-create', array(
|
||||||
'tokenizerID' => $project_tokenizer_id,
|
'tokenizerID' => $project_tokenizer_id,
|
||||||
));
|
));
|
||||||
|
|
|
@ -43,7 +43,13 @@ class PhabricatorPeopleProfileEditController
|
||||||
$file = PhabricatorFile::newFromPHPUpload($_FILES['image']);
|
$file = PhabricatorFile::newFromPHPUpload($_FILES['image']);
|
||||||
$okay = $file->isTransformableImage();
|
$okay = $file->isTransformableImage();
|
||||||
if ($okay) {
|
if ($okay) {
|
||||||
$profile->setProfileImagePHID($file->getPHID());
|
$xformer = new PhabricatorImageTransformer();
|
||||||
|
$xformed = $xformer->executeProfileTransform(
|
||||||
|
$file,
|
||||||
|
$width = 280,
|
||||||
|
$min_height = 140,
|
||||||
|
$max_height = 420);
|
||||||
|
$profile->setProfileImagePHID($xformed->getPHID());
|
||||||
} else {
|
} else {
|
||||||
$errors[] =
|
$errors[] =
|
||||||
'Only valid image files (jpg, jpeg, png or gif) '.
|
'Only valid image files (jpg, jpeg, png or gif) '.
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||||
|
phutil_require_module('phabricator', 'applications/files/transform');
|
||||||
phutil_require_module('phabricator', 'applications/people/controller/base');
|
phutil_require_module('phabricator', 'applications/people/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/people/storage/profile');
|
phutil_require_module('phabricator', 'applications/people/storage/profile');
|
||||||
phutil_require_module('phabricator', 'view/form/base');
|
phutil_require_module('phabricator', 'view/form/base');
|
||||||
|
@ -21,4 +22,4 @@ phutil_require_module('phabricator', 'view/layout/panel');
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorPeopleProfileEditController.php');
|
phutil_require_source('PhabricatorPeopleProfileEditController.php');
|
||||||
|
|
|
@ -119,9 +119,14 @@ class PhabricatorUserSettingsController extends PhabricatorPeopleController {
|
||||||
if ($err != UPLOAD_ERR_NO_FILE) {
|
if ($err != UPLOAD_ERR_NO_FILE) {
|
||||||
$file = PhabricatorFile::newFromPHPUpload($_FILES['profile']);
|
$file = PhabricatorFile::newFromPHPUpload($_FILES['profile']);
|
||||||
$okay = $file->isTransformableImage();
|
$okay = $file->isTransformableImage();
|
||||||
|
|
||||||
if ($okay) {
|
if ($okay) {
|
||||||
$user->setProfileImagePHID($file->getPHID());
|
$xformer = new PhabricatorImageTransformer();
|
||||||
|
$xformed = $xformer->executeProfileTransform(
|
||||||
|
$file,
|
||||||
|
$width = 50,
|
||||||
|
$min_height = 50,
|
||||||
|
$max_height = 50);
|
||||||
|
$user->setProfileImagePHID($xformed->getPHID());
|
||||||
} else {
|
} else {
|
||||||
$errors[] =
|
$errors[] =
|
||||||
'Only valid image files (jpg, jpeg, png or gif) '.
|
'Only valid image files (jpg, jpeg, png or gif) '.
|
||||||
|
@ -339,8 +344,7 @@ class PhabricatorUserSettingsController extends PhabricatorPeopleController {
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormFileControl())
|
id(new AphrontFormFileControl())
|
||||||
->setLabel('Change Image')
|
->setLabel('Change Image')
|
||||||
->setName('profile')
|
->setName('profile'))
|
||||||
->setCaption('Upload a 50x50px image.'))
|
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormMarkupControl())
|
id(new AphrontFormMarkupControl())
|
||||||
->setValue('<hr />'))
|
->setValue('<hr />'))
|
||||||
|
|
|
@ -12,6 +12,7 @@ phutil_require_module('phabricator', 'aphront/response/dialog');
|
||||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||||
phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
|
phutil_require_module('phabricator', 'applications/auth/oauth/provider/base');
|
||||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||||
|
phutil_require_module('phabricator', 'applications/files/transform');
|
||||||
phutil_require_module('phabricator', 'applications/files/uri');
|
phutil_require_module('phabricator', 'applications/files/uri');
|
||||||
phutil_require_module('phabricator', 'applications/people/controller/base');
|
phutil_require_module('phabricator', 'applications/people/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/people/storage/user');
|
phutil_require_module('phabricator', 'applications/people/storage/user');
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PhabricatorProjectQuickCreateController
|
class PhabricatorProjectCreateController
|
||||||
extends PhabricatorProjectController {
|
extends PhabricatorProjectController {
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,13 +28,14 @@ class PhabricatorProjectQuickCreateController
|
||||||
$project = new PhabricatorProject();
|
$project = new PhabricatorProject();
|
||||||
$project->setAuthorPHID($user->getPHID());
|
$project->setAuthorPHID($user->getPHID());
|
||||||
$profile = new PhabricatorProjectProfile();
|
$profile = new PhabricatorProjectProfile();
|
||||||
$options = PhabricatorProjectStatus::getStatusMap();
|
|
||||||
|
|
||||||
$e_name = true;
|
$e_name = true;
|
||||||
$errors = array();
|
$errors = array();
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
|
|
||||||
$project->setName($request->getStr('name'));
|
$project->setName($request->getStr('name'));
|
||||||
|
$project->setStatus(PhabricatorProjectStatus::ONGOING);
|
||||||
|
|
||||||
$profile->setBlurb($request->getStr('blurb'));
|
$profile->setBlurb($request->getStr('blurb'));
|
||||||
|
|
||||||
if (!strlen($project->getName())) {
|
if (!strlen($project->getName())) {
|
||||||
|
@ -49,11 +50,23 @@ class PhabricatorProjectQuickCreateController
|
||||||
$profile->setProjectPHID($project->getPHID());
|
$profile->setProjectPHID($project->getPHID());
|
||||||
$profile->save();
|
$profile->save();
|
||||||
|
|
||||||
return id(new AphrontAjaxResponse())
|
id(new PhabricatorProjectAffiliation())
|
||||||
->setContent(array(
|
->setUserPHID($user->getPHID())
|
||||||
'phid' => $project->getPHID(),
|
->setProjectPHID($project->getPHID())
|
||||||
'name' => $project->getName(),
|
->setRole('Owner')
|
||||||
));
|
->setIsOwner(true)
|
||||||
|
->save();
|
||||||
|
|
||||||
|
if ($request->isAjax()) {
|
||||||
|
return id(new AphrontAjaxResponse())
|
||||||
|
->setContent(array(
|
||||||
|
'phid' => $project->getPHID(),
|
||||||
|
'name' => $project->getName(),
|
||||||
|
));
|
||||||
|
} else {
|
||||||
|
return id(new AphrontRedirectResponse())
|
||||||
|
->setURI('/project/view/'.$project->getID().'/');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,11 +74,17 @@ class PhabricatorProjectQuickCreateController
|
||||||
if ($errors) {
|
if ($errors) {
|
||||||
$error_view = new AphrontErrorView();
|
$error_view = new AphrontErrorView();
|
||||||
$error_view->setTitle('Form Errors');
|
$error_view->setTitle('Form Errors');
|
||||||
$error_view->setWidth(AphrontErrorView::WIDTH_DIALOG);
|
|
||||||
$error_view->setErrors($errors);
|
$error_view->setErrors($errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
$form = id(new AphrontFormLayoutView())
|
if ($request->isAjax()) {
|
||||||
|
$form = new AphrontFormLayoutView();
|
||||||
|
} else {
|
||||||
|
$form = new AphrontFormView();
|
||||||
|
$form->setUser($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
$form
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormTextControl())
|
id(new AphrontFormTextControl())
|
||||||
->setLabel('Name')
|
->setLabel('Name')
|
||||||
|
@ -79,15 +98,44 @@ class PhabricatorProjectQuickCreateController
|
||||||
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
|
->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
|
||||||
->setValue($profile->getBlurb()));
|
->setValue($profile->getBlurb()));
|
||||||
|
|
||||||
$dialog = id(new AphrontDialogView())
|
if ($request->isAjax()) {
|
||||||
->setUser($user)
|
|
||||||
->setWidth(AphrontDialogView::WIDTH_FORM)
|
|
||||||
->setTitle('Create a New Project')
|
|
||||||
->appendChild($error_view)
|
|
||||||
->appendChild($form)
|
|
||||||
->addSubmitButton('Create Project')
|
|
||||||
->addCancelButton('/project/');
|
|
||||||
|
|
||||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
if ($error_view) {
|
||||||
|
$error_view->setWidth(AphrontErrorView::WIDTH_DIALOG);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dialog = id(new AphrontDialogView())
|
||||||
|
->setUser($user)
|
||||||
|
->setWidth(AphrontDialogView::WIDTH_FORM)
|
||||||
|
->setTitle('Create a New Project')
|
||||||
|
->appendChild($error_view)
|
||||||
|
->appendChild($form)
|
||||||
|
->addSubmitButton('Create Project')
|
||||||
|
->addCancelButton('/project/');
|
||||||
|
|
||||||
|
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$form
|
||||||
|
->appendChild(
|
||||||
|
id(new AphrontFormSubmitControl())
|
||||||
|
->setValue('Create')
|
||||||
|
->addCancelButton('/project/'));
|
||||||
|
|
||||||
|
$panel = new AphrontPanelView();
|
||||||
|
$panel
|
||||||
|
->setWidth(AphrontPanelView::WIDTH_FORM)
|
||||||
|
->setHeader('Create a New Project')
|
||||||
|
->appendChild($form);
|
||||||
|
|
||||||
|
return $this->buildStandardPageResponse(
|
||||||
|
array(
|
||||||
|
$error_view,
|
||||||
|
$panel,
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'title' => 'Create new Project',
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,17 +8,22 @@
|
||||||
|
|
||||||
phutil_require_module('phabricator', 'aphront/response/ajax');
|
phutil_require_module('phabricator', 'aphront/response/ajax');
|
||||||
phutil_require_module('phabricator', 'aphront/response/dialog');
|
phutil_require_module('phabricator', 'aphront/response/dialog');
|
||||||
|
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||||
phutil_require_module('phabricator', 'applications/project/constants/status');
|
phutil_require_module('phabricator', 'applications/project/constants/status');
|
||||||
phutil_require_module('phabricator', 'applications/project/controller/base');
|
phutil_require_module('phabricator', 'applications/project/controller/base');
|
||||||
|
phutil_require_module('phabricator', 'applications/project/storage/affiliation');
|
||||||
phutil_require_module('phabricator', 'applications/project/storage/profile');
|
phutil_require_module('phabricator', 'applications/project/storage/profile');
|
||||||
phutil_require_module('phabricator', 'applications/project/storage/project');
|
phutil_require_module('phabricator', 'applications/project/storage/project');
|
||||||
phutil_require_module('phabricator', 'view/dialog');
|
phutil_require_module('phabricator', 'view/dialog');
|
||||||
|
phutil_require_module('phabricator', 'view/form/base');
|
||||||
|
phutil_require_module('phabricator', 'view/form/control/submit');
|
||||||
phutil_require_module('phabricator', 'view/form/control/text');
|
phutil_require_module('phabricator', 'view/form/control/text');
|
||||||
phutil_require_module('phabricator', 'view/form/control/textarea');
|
phutil_require_module('phabricator', 'view/form/control/textarea');
|
||||||
phutil_require_module('phabricator', 'view/form/error');
|
phutil_require_module('phabricator', 'view/form/error');
|
||||||
phutil_require_module('phabricator', 'view/form/layout');
|
phutil_require_module('phabricator', 'view/form/layout');
|
||||||
|
phutil_require_module('phabricator', 'view/layout/panel');
|
||||||
|
|
||||||
phutil_require_module('phutil', 'utils');
|
phutil_require_module('phutil', 'utils');
|
||||||
|
|
||||||
|
|
||||||
phutil_require_source('PhabricatorProjectQuickCreateController.php');
|
phutil_require_source('PhabricatorProjectCreateController.php');
|
|
@ -52,7 +52,12 @@ class PhabricatorProjectAffiliationEditController
|
||||||
|
|
||||||
if (!strlen($affiliation->getRole())) {
|
if (!strlen($affiliation->getRole())) {
|
||||||
if ($affiliation->getID()) {
|
if ($affiliation->getID()) {
|
||||||
$affiliation->delete();
|
if ($affiliation->getIsOwner()) {
|
||||||
|
$affiliation->setRole('Owner');
|
||||||
|
$affiliation->save();
|
||||||
|
} else {
|
||||||
|
$affiliation->delete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$affiliation->save();
|
$affiliation->save();
|
||||||
|
|
|
@ -121,7 +121,7 @@ class PhabricatorProjectListController
|
||||||
$panel = new AphrontPanelView();
|
$panel = new AphrontPanelView();
|
||||||
$panel->appendChild($table);
|
$panel->appendChild($table);
|
||||||
$panel->setHeader('Project');
|
$panel->setHeader('Project');
|
||||||
$panel->setCreateButton('Create New Project', '/project/edit/');
|
$panel->setCreateButton('Create New Project', '/project/create/');
|
||||||
|
|
||||||
return $this->buildStandardPageResponse(
|
return $this->buildStandardPageResponse(
|
||||||
$panel,
|
$panel,
|
||||||
|
|
|
@ -19,10 +19,8 @@
|
||||||
class PhabricatorProjectProfileEditController
|
class PhabricatorProjectProfileEditController
|
||||||
extends PhabricatorProjectController {
|
extends PhabricatorProjectController {
|
||||||
|
|
||||||
private $id;
|
|
||||||
|
|
||||||
public function willProcessRequest(array $data) {
|
public function willProcessRequest(array $data) {
|
||||||
$this->id = idx($data, 'id');
|
$this->id = $data['id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processRequest() {
|
public function processRequest() {
|
||||||
|
@ -30,16 +28,11 @@ class PhabricatorProjectProfileEditController
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$user = $request->getUser();
|
$user = $request->getUser();
|
||||||
|
|
||||||
if ($this->id) {
|
$project = id(new PhabricatorProject())->load($this->id);
|
||||||
$project = id(new PhabricatorProject())->load($this->id);
|
if (!$project) {
|
||||||
if (!$project) {
|
return new Aphront404Response();
|
||||||
return new Aphront404Response();
|
|
||||||
}
|
|
||||||
$profile = $project->loadProfile();
|
|
||||||
} else {
|
|
||||||
$project = new PhabricatorProject();
|
|
||||||
$project->setAuthorPHID($user->getPHID());
|
|
||||||
}
|
}
|
||||||
|
$profile = $project->loadProfile();
|
||||||
|
|
||||||
if (empty($profile)) {
|
if (empty($profile)) {
|
||||||
$profile = new PhabricatorProjectProfile();
|
$profile = new PhabricatorProjectProfile();
|
||||||
|
@ -67,7 +60,13 @@ class PhabricatorProjectProfileEditController
|
||||||
$file = PhabricatorFile::newFromPHPUpload($_FILES['image']);
|
$file = PhabricatorFile::newFromPHPUpload($_FILES['image']);
|
||||||
$okay = $file->isTransformableImage();
|
$okay = $file->isTransformableImage();
|
||||||
if ($okay) {
|
if ($okay) {
|
||||||
$profile->setProfileImagePHID($file->getPHID());
|
$xformer = new PhabricatorImageTransformer();
|
||||||
|
$xformed = $xformer->executeProfileTransform(
|
||||||
|
$file,
|
||||||
|
$width = 280,
|
||||||
|
$min_height = 140,
|
||||||
|
$max_height = 420);
|
||||||
|
$profile->setProfileImagePHID($xformed->getPHID());
|
||||||
} else {
|
} else {
|
||||||
$errors[] =
|
$errors[] =
|
||||||
'Only valid image files (jpg, jpeg, png or gif) '.
|
'Only valid image files (jpg, jpeg, png or gif) '.
|
||||||
|
@ -92,15 +91,9 @@ class PhabricatorProjectProfileEditController
|
||||||
$error_view->setErrors($errors);
|
$error_view->setErrors($errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($project->getID()) {
|
$header_name = 'Edit Project';
|
||||||
$header_name = 'Edit Project';
|
$title = 'Edit Project';
|
||||||
$title = 'Edit Project';
|
$action = '/project/edit/'.$project->getID().'/';
|
||||||
$action = '/project/edit/'.$project->getID().'/';
|
|
||||||
} else {
|
|
||||||
$header_name = 'Create Project';
|
|
||||||
$title = 'Create Project';
|
|
||||||
$action = '/project/edit/';
|
|
||||||
}
|
|
||||||
|
|
||||||
$form = new AphrontFormView();
|
$form = new AphrontFormView();
|
||||||
$form
|
$form
|
||||||
|
@ -127,8 +120,7 @@ class PhabricatorProjectProfileEditController
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormFileControl())
|
id(new AphrontFormFileControl())
|
||||||
->setLabel('Change Image')
|
->setLabel('Change Image')
|
||||||
->setName('image')
|
->setName('image'))
|
||||||
->setCaption('Upload a 280px-wide image.'))
|
|
||||||
->appendChild(
|
->appendChild(
|
||||||
id(new AphrontFormSubmitControl())
|
id(new AphrontFormSubmitControl())
|
||||||
->addCancelButton('/project/view/'.$project->getID().'/')
|
->addCancelButton('/project/view/'.$project->getID().'/')
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
phutil_require_module('phabricator', 'aphront/response/404');
|
phutil_require_module('phabricator', 'aphront/response/404');
|
||||||
phutil_require_module('phabricator', 'aphront/response/redirect');
|
phutil_require_module('phabricator', 'aphront/response/redirect');
|
||||||
phutil_require_module('phabricator', 'applications/files/storage/file');
|
phutil_require_module('phabricator', 'applications/files/storage/file');
|
||||||
|
phutil_require_module('phabricator', 'applications/files/transform');
|
||||||
phutil_require_module('phabricator', 'applications/project/constants/status');
|
phutil_require_module('phabricator', 'applications/project/constants/status');
|
||||||
phutil_require_module('phabricator', 'applications/project/controller/base');
|
phutil_require_module('phabricator', 'applications/project/controller/base');
|
||||||
phutil_require_module('phabricator', 'applications/project/storage/profile');
|
phutil_require_module('phabricator', 'applications/project/storage/profile');
|
||||||
|
|
|
@ -21,7 +21,8 @@ class PhabricatorProjectAffiliation extends PhabricatorProjectDAO {
|
||||||
protected $projectPHID;
|
protected $projectPHID;
|
||||||
protected $userPHID;
|
protected $userPHID;
|
||||||
protected $role;
|
protected $role;
|
||||||
protected $status;
|
protected $status = '';
|
||||||
|
protected $isOwner = 0;
|
||||||
|
|
||||||
public static function loadAllForProjectPHIDs($phids) {
|
public static function loadAllForProjectPHIDs($phids) {
|
||||||
if (!$phids) {
|
if (!$phids) {
|
||||||
|
|
Loading…
Reference in a new issue