mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-27 07:50:57 +01:00
Add ability to set a header image per Phame blog
Summary: This is the backend half of uploading an image as a header for Phame Blogs. Allows you to upload image, or delete it. Ref T10901 Test Plan: Go to Manage Blog, visit Edit Header Image, Upload snarky file. See snarky file on Manage page. Edit Header Image, click delete, save, see file goes away. {F1690966} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Maniphest Tasks: T10901 Differential Revision: https://secure.phabricator.com/D16140
This commit is contained in:
parent
95d95e3fb4
commit
0d4902a0e5
10 changed files with 210 additions and 7 deletions
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
return array(
|
||||
'names' => array(
|
||||
'core.pkg.css' => '6913fe66',
|
||||
'core.pkg.css' => 'c7fc5aec',
|
||||
'core.pkg.js' => '10275c16',
|
||||
'darkconsole.pkg.js' => 'e7393ebb',
|
||||
'differential.pkg.css' => 'b3eea3f5',
|
||||
|
@ -155,7 +155,7 @@ return array(
|
|||
'rsrc/css/phui/phui-spacing.css' => '042804d6',
|
||||
'rsrc/css/phui/phui-status.css' => 'd5263e49',
|
||||
'rsrc/css/phui/phui-tag-view.css' => '6bbd83e2',
|
||||
'rsrc/css/phui/phui-timeline-view.css' => '6e342216',
|
||||
'rsrc/css/phui/phui-timeline-view.css' => '8ea41b25',
|
||||
'rsrc/css/phui/phui-two-column-view.css' => '9fb86c85',
|
||||
'rsrc/css/phui/workboards/phui-workboard-color.css' => 'ac6fe6a7',
|
||||
'rsrc/css/phui/workboards/phui-workboard.css' => 'e6d89647',
|
||||
|
@ -860,7 +860,7 @@ return array(
|
|||
'phui-status-list-view-css' => 'd5263e49',
|
||||
'phui-tag-view-css' => '6bbd83e2',
|
||||
'phui-theme-css' => '027ba77e',
|
||||
'phui-timeline-view-css' => '6e342216',
|
||||
'phui-timeline-view-css' => '8ea41b25',
|
||||
'phui-two-column-view-css' => '9fb86c85',
|
||||
'phui-workboard-color-css' => 'ac6fe6a7',
|
||||
'phui-workboard-view-css' => 'e6d89647',
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE {$NAMESPACE}_phame.phame_blog
|
||||
ADD headerImagePHID VARBINARY(64);
|
|
@ -3777,6 +3777,7 @@ phutil_register_library_map(array(
|
|||
'PhameBlogEditor' => 'applications/phame/editor/PhameBlogEditor.php',
|
||||
'PhameBlogFeedController' => 'applications/phame/controller/blog/PhameBlogFeedController.php',
|
||||
'PhameBlogFulltextEngine' => 'applications/phame/search/PhameBlogFulltextEngine.php',
|
||||
'PhameBlogHeaderPictureController' => 'applications/phame/controller/blog/PhameBlogHeaderPictureController.php',
|
||||
'PhameBlogListController' => 'applications/phame/controller/blog/PhameBlogListController.php',
|
||||
'PhameBlogListView' => 'applications/phame/view/PhameBlogListView.php',
|
||||
'PhameBlogManageController' => 'applications/phame/controller/blog/PhameBlogManageController.php',
|
||||
|
@ -8655,6 +8656,7 @@ phutil_register_library_map(array(
|
|||
'PhameBlogEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'PhameBlogFeedController' => 'PhameBlogController',
|
||||
'PhameBlogFulltextEngine' => 'PhabricatorFulltextEngine',
|
||||
'PhameBlogHeaderPictureController' => 'PhameBlogController',
|
||||
'PhameBlogListController' => 'PhameBlogController',
|
||||
'PhameBlogListView' => 'AphrontTagView',
|
||||
'PhameBlogManageController' => 'PhameBlogController',
|
||||
|
|
|
@ -67,6 +67,7 @@ final class PhabricatorPhameApplication extends PhabricatorApplication {
|
|||
'manage/(?P<id>[^/]+)/' => 'PhameBlogManageController',
|
||||
'feed/(?P<id>[^/]+)/' => 'PhameBlogFeedController',
|
||||
'picture/(?P<id>[1-9]\d*)/' => 'PhameBlogProfilePictureController',
|
||||
'header/(?P<id>[1-9]\d*)/' => 'PhameBlogHeaderPictureController',
|
||||
),
|
||||
) + $this->getResourceSubroutes(),
|
||||
);
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
final class PhameBlogHeaderPictureController
|
||||
extends PhameBlogController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
|
||||
$blog = id(new PhameBlogQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->needHeaderImage(true)
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$blog) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$blog_uri = '/phame/blog/manage/'.$id;
|
||||
|
||||
$supported_formats = PhabricatorFile::getTransformableImageFormats();
|
||||
$e_file = true;
|
||||
$errors = array();
|
||||
$delete_header = ($request->getInt('delete') == 1);
|
||||
|
||||
if ($request->isFormPost()) {
|
||||
if ($request->getFileExists('header')) {
|
||||
$file = PhabricatorFile::newFromPHPUpload(
|
||||
$_FILES['header'],
|
||||
array(
|
||||
'authorPHID' => $viewer->getPHID(),
|
||||
'canCDN' => true,
|
||||
));
|
||||
} else if (!$delete_header) {
|
||||
$e_file = pht('Required');
|
||||
$errors[] = pht(
|
||||
'You must choose a file when uploading a new blog header.');
|
||||
}
|
||||
|
||||
if (!$errors && !$delete_header) {
|
||||
if (!$file->isTransformableImage()) {
|
||||
$e_file = pht('Not Supported');
|
||||
$errors[] = pht(
|
||||
'This server only supports these image formats: %s.',
|
||||
implode(', ', $supported_formats));
|
||||
}
|
||||
}
|
||||
|
||||
if (!$errors) {
|
||||
if ($delete_header) {
|
||||
$blog->setHeaderImagePHID(null);
|
||||
} else {
|
||||
$blog->setHeaderImagePHID($file->getPHID());
|
||||
$file->attachToObject($blog->getPHID());
|
||||
}
|
||||
$blog->save();
|
||||
return id(new AphrontRedirectResponse())->setURI($blog_uri);
|
||||
}
|
||||
}
|
||||
|
||||
$title = pht('Edit Blog Header');
|
||||
|
||||
$upload_form = id(new AphrontFormView())
|
||||
->setUser($viewer)
|
||||
->setEncType('multipart/form-data')
|
||||
->appendChild(
|
||||
id(new AphrontFormFileControl())
|
||||
->setName('header')
|
||||
->setLabel(pht('Upload Header'))
|
||||
->setError($e_file)
|
||||
->setCaption(
|
||||
pht('Supported formats: %s', implode(', ', $supported_formats))))
|
||||
->appendChild(
|
||||
id(new AphrontFormCheckboxControl())
|
||||
->setName('delete')
|
||||
->setLabel(pht('Delete Header'))
|
||||
->addCheckbox(
|
||||
'delete',
|
||||
1,
|
||||
null,
|
||||
null))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->addCancelButton($blog_uri)
|
||||
->setValue(pht('Upload Header')));
|
||||
|
||||
$upload_box = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Upload New Header'))
|
||||
->setBackground(PHUIObjectBoxView::BLUE_PROPERTY)
|
||||
->setForm($upload_form);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(
|
||||
pht('Blogs'),
|
||||
$this->getApplicationURI('blog/'));
|
||||
$crumbs->addTextCrumb(
|
||||
$blog->getName(),
|
||||
$this->getApplicationURI('blog/view/'.$id));
|
||||
$crumbs->addTextCrumb(pht('Blog Header'));
|
||||
$crumbs->setBorder(true);
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Edit Blog Header'))
|
||||
->setHeaderIcon('fa-camera');
|
||||
|
||||
$view = id(new PHUITwoColumnView())
|
||||
->setHeader($header)
|
||||
->setFooter(array(
|
||||
$upload_box,
|
||||
));
|
||||
|
||||
return $this->newPage()
|
||||
->setTitle($title)
|
||||
->setCrumbs($crumbs)
|
||||
->appendChild(
|
||||
array(
|
||||
$view,
|
||||
));
|
||||
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ final class PhameBlogManageController extends PhameBlogController {
|
|||
->setViewer($viewer)
|
||||
->withIDs(array($id))
|
||||
->needProfileImage(true)
|
||||
->needHeaderImage(true)
|
||||
->executeOne();
|
||||
if (!$blog) {
|
||||
return new Aphront404Response();
|
||||
|
@ -40,6 +41,7 @@ final class PhameBlogManageController extends PhameBlogController {
|
|||
|
||||
$curtain = $this->buildCurtain($blog);
|
||||
$properties = $this->buildPropertyView($blog);
|
||||
$file = $this->buildFileView($blog);
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb(
|
||||
|
@ -62,6 +64,7 @@ final class PhameBlogManageController extends PhameBlogController {
|
|||
->setHeader($header)
|
||||
->setCurtain($curtain)
|
||||
->addPropertySection(pht('Details'), $properties)
|
||||
->addPropertySection(pht('Header'), $file)
|
||||
->setMainColumn(
|
||||
array(
|
||||
$timeline,
|
||||
|
@ -157,6 +160,14 @@ final class PhameBlogManageController extends PhameBlogController {
|
|||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-camera')
|
||||
->setHref($this->getApplicationURI('blog/header/'.$blog->getID().'/'))
|
||||
->setName(pht('Edit Blog Header'))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
$curtain->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setIcon('fa-picture-o')
|
||||
|
@ -188,4 +199,24 @@ final class PhameBlogManageController extends PhameBlogController {
|
|||
return $curtain;
|
||||
}
|
||||
|
||||
private function buildFileView(
|
||||
PhameBlog $blog) {
|
||||
$viewer = $this->getViewer();
|
||||
|
||||
$view = id(new PHUIPropertyListView())
|
||||
->setUser($viewer);
|
||||
|
||||
if ($blog->getHeaderImagePHID()) {
|
||||
$view->addImageContent(
|
||||
phutil_tag(
|
||||
'img',
|
||||
array(
|
||||
'src' => $blog->getHeaderImageURI(),
|
||||
'class' => 'phabricator-image-macro-hero',
|
||||
)));
|
||||
return $view;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,6 @@
|
|||
final class PhameBlogProfilePictureController
|
||||
extends PhameBlogController {
|
||||
|
||||
public function shouldRequireAdmin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getViewer();
|
||||
$id = $request->getURIData('id');
|
||||
|
|
|
@ -9,6 +9,7 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
|
||||
private $needBloggers;
|
||||
private $needProfileImage;
|
||||
private $needHeaderImage;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
|
@ -35,6 +36,11 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function needHeaderImage($need) {
|
||||
$this->needHeaderImage = $need;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function newResultObject() {
|
||||
return new PhameBlog();
|
||||
}
|
||||
|
@ -107,6 +113,28 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
|
|||
$blog->attachProfileImageFile($file);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->needHeaderImage) {
|
||||
$file_phids = mpull($blogs, 'getHeaderImagePHID');
|
||||
$file_phids = array_filter($file_phids);
|
||||
if ($file_phids) {
|
||||
$files = id(new PhabricatorFileQuery())
|
||||
->setParentQuery($this)
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs($file_phids)
|
||||
->execute();
|
||||
$files = mpull($files, null, 'getPHID');
|
||||
} else {
|
||||
$files = array();
|
||||
}
|
||||
|
||||
foreach ($blogs as $blog) {
|
||||
$file = idx($files, $blog->getHeaderImagePHID());
|
||||
if ($file) {
|
||||
$blog->attachHeaderImageFile($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $blogs;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,10 @@ final class PhameBlog extends PhameDAO
|
|||
protected $status;
|
||||
protected $mailKey;
|
||||
protected $profileImagePHID;
|
||||
protected $headerImagePHID;
|
||||
|
||||
private $profileImageFile = self::ATTACHABLE;
|
||||
private $headerImageFile = self::ATTACHABLE;
|
||||
|
||||
const STATUS_ACTIVE = 'active';
|
||||
const STATUS_ARCHIVED = 'archived';
|
||||
|
@ -43,6 +45,7 @@ final class PhameBlog extends PhameDAO
|
|||
'status' => 'text32',
|
||||
'mailKey' => 'bytes20',
|
||||
'profileImagePHID' => 'phid?',
|
||||
'headerImagePHID' => 'phid?',
|
||||
|
||||
// T6203/NULLABILITY
|
||||
// These policies should always be non-null.
|
||||
|
@ -212,6 +215,19 @@ final class PhameBlog extends PhameDAO
|
|||
return $this->assertAttached($this->profileImageFile);
|
||||
}
|
||||
|
||||
public function getHeaderImageURI() {
|
||||
return $this->getHeaderImageFile()->getBestURI();
|
||||
}
|
||||
|
||||
public function attachHeaderImageFile(PhabricatorFile $file) {
|
||||
$this->headerImageFile = $file;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHeaderImageFile() {
|
||||
return $this->assertAttached($this->headerImageFile);
|
||||
}
|
||||
|
||||
|
||||
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
height: 9px;
|
||||
border-radius: 2px;
|
||||
margin-left: 76px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.device-desktop .phui-timeline-wedge {
|
||||
|
|
Loading…
Reference in a new issue