From c3809b0d593d25a53d12f5502d53a78b82e16ce1 Mon Sep 17 00:00:00 2001 From: Chad Little Date: Fri, 28 Oct 2016 13:55:55 -0700 Subject: [PATCH] Add a Merchant logo to Phortune Summary: Is a logo. For merchants. Test Plan: Set a new logo, remove it. See on list. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin Maniphest Tasks: T7607 Differential Revision: https://secure.phabricator.com/D16751 --- resources/builtin/merchant.png | Bin 0 -> 5344 bytes .../20161025.phortune.merchant.image.1.sql | 2 + src/__phutil_library_map__.php | 2 + .../PhabricatorPhortuneApplication.php | 1 + .../PhortuneMerchantPictureController.php | 234 ++++++++++++++++++ .../PhortuneMerchantViewController.php | 11 +- .../editor/PhortuneMerchantEditor.php | 8 + .../phortune/query/PhortuneMerchantQuery.php | 35 +++ .../query/PhortuneMerchantSearchEngine.php | 5 +- .../phortune/storage/PhortuneMerchant.php | 20 ++ .../storage/PhortuneMerchantTransaction.php | 1 + 11 files changed, 316 insertions(+), 3 deletions(-) create mode 100644 resources/builtin/merchant.png create mode 100644 resources/sql/autopatches/20161025.phortune.merchant.image.1.sql create mode 100644 src/applications/phortune/controller/PhortuneMerchantPictureController.php diff --git a/resources/builtin/merchant.png b/resources/builtin/merchant.png new file mode 100644 index 0000000000000000000000000000000000000000..c8381eb00fd59eff93fb0a28242ad81f360331d4 GIT binary patch literal 5344 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 WC2As(@YP@c9M2kA7*^}MM*koGgm{tw literal 0 HcmV?d00001 diff --git a/resources/sql/autopatches/20161025.phortune.merchant.image.1.sql b/resources/sql/autopatches/20161025.phortune.merchant.image.1.sql new file mode 100644 index 0000000000..995a4a8fd6 --- /dev/null +++ b/resources/sql/autopatches/20161025.phortune.merchant.image.1.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_phortune.phortune_merchant + ADD profileImagePHID VARBINARY(64); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index cb4a6c15df..dcb61c6342 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4185,6 +4185,7 @@ phutil_register_library_map(array( 'PhortuneMerchantInvoiceCreateController' => 'applications/phortune/controller/PhortuneMerchantInvoiceCreateController.php', 'PhortuneMerchantListController' => 'applications/phortune/controller/PhortuneMerchantListController.php', 'PhortuneMerchantPHIDType' => 'applications/phortune/phid/PhortuneMerchantPHIDType.php', + 'PhortuneMerchantPictureController' => 'applications/phortune/controller/PhortuneMerchantPictureController.php', 'PhortuneMerchantQuery' => 'applications/phortune/query/PhortuneMerchantQuery.php', 'PhortuneMerchantSearchEngine' => 'applications/phortune/query/PhortuneMerchantSearchEngine.php', 'PhortuneMerchantTransaction' => 'applications/phortune/storage/PhortuneMerchantTransaction.php', @@ -9434,6 +9435,7 @@ phutil_register_library_map(array( 'PhortuneMerchantInvoiceCreateController' => 'PhortuneMerchantController', 'PhortuneMerchantListController' => 'PhortuneMerchantController', 'PhortuneMerchantPHIDType' => 'PhabricatorPHIDType', + 'PhortuneMerchantPictureController' => 'PhortuneMerchantController', 'PhortuneMerchantQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhortuneMerchantSearchEngine' => 'PhabricatorApplicationSearchEngine', 'PhortuneMerchantTransaction' => 'PhabricatorApplicationTransaction', diff --git a/src/applications/phortune/application/PhabricatorPhortuneApplication.php b/src/applications/phortune/application/PhabricatorPhortuneApplication.php index 470ceb10ab..313328e41e 100644 --- a/src/applications/phortune/application/PhabricatorPhortuneApplication.php +++ b/src/applications/phortune/application/PhabricatorPhortuneApplication.php @@ -81,6 +81,7 @@ final class PhabricatorPhortuneApplication extends PhabricatorApplication { ), 'merchant/' => array( '(?:query/(?P[^/]+)/)?' => 'PhortuneMerchantListController', + 'picture/(?:(?P\d+)/)?' => 'PhortuneMerchantPictureController', 'edit/(?:(?P\d+)/)?' => 'PhortuneMerchantEditController', 'orders/(?P\d+)/(?:query/(?P[^/]+)/)?' => 'PhortuneCartListController', diff --git a/src/applications/phortune/controller/PhortuneMerchantPictureController.php b/src/applications/phortune/controller/PhortuneMerchantPictureController.php new file mode 100644 index 0000000000..74d7ea061c --- /dev/null +++ b/src/applications/phortune/controller/PhortuneMerchantPictureController.php @@ -0,0 +1,234 @@ +getViewer(); + $id = $request->getURIData('id'); + + $merchant = id(new PhortuneMerchantQuery()) + ->setViewer($viewer) + ->withIDs(array($id)) + ->needProfileImage(true) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->executeOne(); + if (!$merchant) { + return new Aphront404Response(); + } + + $uri = $merchant->getViewURI(); + + $supported_formats = PhabricatorFile::getTransformableImageFormats(); + $e_file = true; + $errors = array(); + + if ($request->isFormPost()) { + $phid = $request->getStr('phid'); + $is_default = false; + if ($phid == PhabricatorPHIDConstants::PHID_VOID) { + $phid = null; + $is_default = true; + } else if ($phid) { + $file = id(new PhabricatorFileQuery()) + ->setViewer($viewer) + ->withPHIDs(array($phid)) + ->executeOne(); + } else { + if ($request->getFileExists('picture')) { + $file = PhabricatorFile::newFromPHPUpload( + $_FILES['picture'], + array( + 'authorPHID' => $viewer->getPHID(), + 'canCDN' => true, + )); + } else { + $e_file = pht('Required'); + $errors[] = pht( + 'You must choose a file when uploading a merchant logo.'); + } + } + + if (!$errors && !$is_default) { + if (!$file->isTransformableImage()) { + $e_file = pht('Not Supported'); + $errors[] = pht( + 'This server only supports these image formats: %s.', + implode(', ', $supported_formats)); + } else { + $xform = PhabricatorFileTransform::getTransformByKey( + PhabricatorFileThumbnailTransform::TRANSFORM_PROFILE); + $xformed = $xform->executeTransform($file); + } + } + + if (!$errors) { + if ($is_default) { + $new_value = null; + } else { + $xformed->attachToObject($merchant->getPHID()); + $new_value = $xformed->getPHID(); + } + + $xactions = array(); + $xactions[] = id(new PhortuneMerchantTransaction()) + ->setTransactionType(PhortuneMerchantTransaction::TYPE_PICTURE) + ->setNewValue($new_value); + + $editor = id(new PhortuneMerchantEditor()) + ->setActor($viewer) + ->setContentSourceFromRequest($request) + ->setContinueOnMissingFields(true) + ->setContinueOnNoEffect(true); + + $editor->applyTransactions($merchant, $xactions); + + return id(new AphrontRedirectResponse())->setURI($uri); + } + } + + $title = pht('Edit Merchant Picture'); + + $form = id(new PHUIFormLayoutView()) + ->setUser($viewer); + + $default_image = PhabricatorFile::loadBuiltin($viewer, 'merchant.png'); + + $images = array(); + + $current = $merchant->getProfileImagePHID(); + $has_current = false; + if ($current) { + $file = id(new PhabricatorFileQuery()) + ->setViewer($viewer) + ->withPHIDs(array($current)) + ->executeOne(); + if ($file) { + if ($file->isTransformableImage()) { + $has_current = true; + $images[$current] = array( + 'uri' => $file->getBestURI(), + 'tip' => pht('Current Picture'), + ); + } + } + } + + $images[PhabricatorPHIDConstants::PHID_VOID] = array( + 'uri' => $default_image->getBestURI(), + 'tip' => pht('Default Picture'), + ); + + require_celerity_resource('people-profile-css'); + Javelin::initBehavior('phabricator-tooltips', array()); + + $buttons = array(); + foreach ($images as $phid => $spec) { + $button = javelin_tag( + 'button', + array( + 'class' => 'grey profile-image-button', + 'sigil' => 'has-tooltip', + 'meta' => array( + 'tip' => $spec['tip'], + 'size' => 300, + ), + ), + phutil_tag( + 'img', + array( + 'height' => 50, + 'width' => 50, + 'src' => $spec['uri'], + ))); + + $button = array( + phutil_tag( + 'input', + array( + 'type' => 'hidden', + 'name' => 'phid', + 'value' => $phid, + )), + $button, + ); + + $button = phabricator_form( + $viewer, + array( + 'class' => 'profile-image-form', + 'method' => 'POST', + ), + $button); + + $buttons[] = $button; + } + + if ($has_current) { + $form->appendChild( + id(new AphrontFormMarkupControl()) + ->setLabel(pht('Current Logo')) + ->setValue(array_shift($buttons))); + } + + $form->appendChild( + id(new AphrontFormMarkupControl()) + ->setLabel(pht('Use Logo')) + ->setValue($buttons)); + + $form_box = id(new PHUIObjectBoxView()) + ->setHeaderText($title) + ->setFormErrors($errors) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->setForm($form); + + $upload_form = id(new AphrontFormView()) + ->setUser($viewer) + ->setEncType('multipart/form-data') + ->appendChild( + id(new AphrontFormFileControl()) + ->setName('picture') + ->setLabel(pht('Upload Logo')) + ->setError($e_file) + ->setCaption( + pht('Supported formats: %s', implode(', ', $supported_formats)))) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->addCancelButton($uri) + ->setValue(pht('Upload Logo'))); + + $upload_box = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Upload New Logo')) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) + ->setForm($upload_form); + + $crumbs = $this->buildApplicationCrumbs(); + $crumbs->addTextCrumb($merchant->getName(), $uri); + $crumbs->addTextCrumb(pht('Merchant Logo')); + $crumbs->setBorder(true); + + $header = id(new PHUIHeaderView()) + ->setHeader(pht('Edit Merchant Logo')) + ->setHeaderIcon('fa-camera'); + + $view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setFooter(array( + $form_box, + $upload_box, + )); + + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild( + array( + $view, + )); + + } +} diff --git a/src/applications/phortune/controller/PhortuneMerchantViewController.php b/src/applications/phortune/controller/PhortuneMerchantViewController.php index cc94da6f4f..6c74ce8a06 100644 --- a/src/applications/phortune/controller/PhortuneMerchantViewController.php +++ b/src/applications/phortune/controller/PhortuneMerchantViewController.php @@ -10,6 +10,7 @@ final class PhortuneMerchantViewController $merchant = id(new PhortuneMerchantQuery()) ->setViewer($viewer) ->withIDs(array($id)) + ->needProfileImage(true) ->executeOne(); if (!$merchant) { return new Aphront404Response(); @@ -28,7 +29,7 @@ final class PhortuneMerchantViewController ->setHeader($merchant->getName()) ->setUser($viewer) ->setPolicyObject($merchant) - ->setHeaderIcon('fa-bank'); + ->setImage($merchant->getProfileImageURI()); $providers = id(new PhortunePaymentProviderConfigQuery()) ->setViewer($viewer) @@ -171,6 +172,14 @@ final class PhortuneMerchantViewController ->setWorkflow(!$can_edit) ->setHref($this->getApplicationURI("merchant/edit/{$id}/"))); + $curtain->addAction( + id(new PhabricatorActionView()) + ->setName(pht('Edit Logo')) + ->setIcon('fa-camera') + ->setDisabled(!$can_edit) + ->setWorkflow(!$can_edit) + ->setHref($this->getApplicationURI("merchant/picture/{$id}/"))); + $curtain->addAction( id(new PhabricatorActionView()) ->setName(pht('View Orders')) diff --git a/src/applications/phortune/editor/PhortuneMerchantEditor.php b/src/applications/phortune/editor/PhortuneMerchantEditor.php index 20f329b202..2d35ddabfd 100644 --- a/src/applications/phortune/editor/PhortuneMerchantEditor.php +++ b/src/applications/phortune/editor/PhortuneMerchantEditor.php @@ -17,6 +17,7 @@ final class PhortuneMerchantEditor $types[] = PhortuneMerchantTransaction::TYPE_NAME; $types[] = PhortuneMerchantTransaction::TYPE_DESCRIPTION; $types[] = PhortuneMerchantTransaction::TYPE_CONTACTINFO; + $types[] = PhortuneMerchantTransaction::TYPE_PICTURE; $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; $types[] = PhabricatorTransactions::TYPE_EDGE; @@ -33,6 +34,8 @@ final class PhortuneMerchantEditor return $object->getDescription(); case PhortuneMerchantTransaction::TYPE_CONTACTINFO: return $object->getContactInfo(); + case PhortuneMerchantTransaction::TYPE_PICTURE: + return $object->getProfileImagePHID(); } return parent::getCustomTransactionOldValue($object, $xaction); @@ -46,6 +49,7 @@ final class PhortuneMerchantEditor case PhortuneMerchantTransaction::TYPE_NAME: case PhortuneMerchantTransaction::TYPE_DESCRIPTION: case PhortuneMerchantTransaction::TYPE_CONTACTINFO: + case PhortuneMerchantTransaction::TYPE_PICTURE: return $xaction->getNewValue(); } @@ -66,6 +70,9 @@ final class PhortuneMerchantEditor case PhortuneMerchantTransaction::TYPE_CONTACTINFO: $object->setContactInfo($xaction->getNewValue()); return; + case PhortuneMerchantTransaction::TYPE_PICTURE: + $object->setProfileImagePHID($xaction->getNewValue()); + return; } return parent::applyCustomInternalTransaction($object, $xaction); @@ -79,6 +86,7 @@ final class PhortuneMerchantEditor case PhortuneMerchantTransaction::TYPE_NAME: case PhortuneMerchantTransaction::TYPE_DESCRIPTION: case PhortuneMerchantTransaction::TYPE_CONTACTINFO: + case PhortuneMerchantTransaction::TYPE_PICTURE: return; } diff --git a/src/applications/phortune/query/PhortuneMerchantQuery.php b/src/applications/phortune/query/PhortuneMerchantQuery.php index aa730393ff..c91267b73c 100644 --- a/src/applications/phortune/query/PhortuneMerchantQuery.php +++ b/src/applications/phortune/query/PhortuneMerchantQuery.php @@ -6,6 +6,7 @@ final class PhortuneMerchantQuery private $ids; private $phids; private $memberPHIDs; + private $needProfileImage; public function withIDs(array $ids) { $this->ids = $ids; @@ -22,6 +23,11 @@ final class PhortuneMerchantQuery return $this; } + public function needProfileImage($need) { + $this->needProfileImage = $need; + return $this; + } + protected function loadPage() { $table = new PhortuneMerchant(); $conn = $table->establishConnection('r'); @@ -50,6 +56,35 @@ final class PhortuneMerchantQuery $merchant->attachMemberPHIDs($member_phids); } + if ($this->needProfileImage) { + $default = null; + $file_phids = mpull($merchants, 'getProfileImagePHID'); + $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 ($merchants as $merchant) { + $file = idx($files, $merchant->getProfileImagePHID()); + if (!$file) { + if (!$default) { + $default = PhabricatorFile::loadBuiltin( + $this->getViewer(), + 'merchant.png'); + } + $file = $default; + } + $merchant->attachProfileImageFile($file); + } + } + return $merchants; } diff --git a/src/applications/phortune/query/PhortuneMerchantSearchEngine.php b/src/applications/phortune/query/PhortuneMerchantSearchEngine.php index d37c1455b3..a818f37d28 100644 --- a/src/applications/phortune/query/PhortuneMerchantSearchEngine.php +++ b/src/applications/phortune/query/PhortuneMerchantSearchEngine.php @@ -18,7 +18,8 @@ final class PhortuneMerchantSearchEngine } public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) { - $query = id(new PhortuneMerchantQuery()); + $query = id(new PhortuneMerchantQuery()) + ->needProfileImage(true); return $query; } @@ -74,7 +75,7 @@ final class PhortuneMerchantSearchEngine ->setHeader($merchant->getName()) ->setHref('/phortune/merchant/'.$merchant->getID().'/') ->setObject($merchant) - ->setImageIcon('fa-bank'); + ->setImageURI($merchant->getProfileImageURI()); $list->addItem($item); } diff --git a/src/applications/phortune/storage/PhortuneMerchant.php b/src/applications/phortune/storage/PhortuneMerchant.php index fef1728014..7d202eeaf0 100644 --- a/src/applications/phortune/storage/PhortuneMerchant.php +++ b/src/applications/phortune/storage/PhortuneMerchant.php @@ -9,8 +9,10 @@ final class PhortuneMerchant extends PhortuneDAO protected $viewPolicy; protected $description; protected $contactInfo; + protected $profileImagePHID; private $memberPHIDs = self::ATTACHABLE; + private $profileImageFile = self::ATTACHABLE; public static function initializeNewMerchant(PhabricatorUser $actor) { return id(new PhortuneMerchant()) @@ -25,6 +27,7 @@ final class PhortuneMerchant extends PhortuneDAO 'name' => 'text255', 'description' => 'text', 'contactInfo' => 'text', + 'profileImagePHID' => 'phid?', ), ) + parent::getConfiguration(); } @@ -43,6 +46,23 @@ final class PhortuneMerchant extends PhortuneDAO return $this; } + public function getViewURI() { + return '/phortune/merchant/'.$this->getID().'/'; + } + + public function getProfileImageURI() { + return $this->getProfileImageFile()->getBestURI(); + } + + public function attachProfileImageFile(PhabricatorFile $file) { + $this->profileImageFile = $file; + return $this; + } + + public function getProfileImageFile() { + return $this->assertAttached($this->profileImageFile); + } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ diff --git a/src/applications/phortune/storage/PhortuneMerchantTransaction.php b/src/applications/phortune/storage/PhortuneMerchantTransaction.php index 9c284ca7fd..48895d85ec 100644 --- a/src/applications/phortune/storage/PhortuneMerchantTransaction.php +++ b/src/applications/phortune/storage/PhortuneMerchantTransaction.php @@ -6,6 +6,7 @@ final class PhortuneMerchantTransaction const TYPE_NAME = 'merchant:name'; const TYPE_DESCRIPTION = 'merchant:description'; const TYPE_CONTACTINFO = 'merchant:contactinfo'; + const TYPE_PICTURE = 'merchant:picture'; public function getApplicationName() { return 'phortune';