diff --git a/resources/builtin/merchant.png b/resources/builtin/merchant.png new file mode 100644 index 0000000000000000000000000000000000000000..c8381eb00fd59eff93fb0a28242ad81f360331d4 GIT binary patch literal 5344 zcmeAS@N?(olHy`uVBq!ia0y~yU`PRB4mJh`hJr^^Ll_tsBuiW)N`mv#O3D+9QW+dm z@{>{(JaZG%Q-e|yQz{EjrrIztFt=rfM3hAM`dB6B=jtVb)aX^@7BGN-jeSKyVsdtB zi9%9pdS;%j()-=}l@u~lY?Z=IeGPmIoKrJ0J*tXQgRA^PlB=?lEmM^2?G$V(tSWK~ za#KqZ6)JLb@`|l0Y?Z*~TICg6frRyy6u?SKvTcwn`Gt*5rG&WK& zx70Hucp-l$oBHmzd*{pIn-onpfiKVyje< zTcDScnPQccnwnyfW@)OMnwny+YhspSs+(kHn4+6xW@2P+Y+`PiYLEmo2b+Eib0>2{ zLvsU5V-q(+Lsv5kCo>Z_V+#{U6H{k13j;@(UeCPZlEl2^RG8hFnJHEfy=HEB^;$U> zr6!i-7lq{K=fF}yKt_H^esM;Afr7I$DAr9CG<*}2GxI=#nxKdR$AXnhYEfocYKmJ? zey##Iq^&ZsxWdfR$kHUm)J)gF$ka^NBq=df*U}=*P&YZ*$igBqB{|W|!axbCKLsfS zAt^N_KRGkSssQF7D|6G7B$E_#BVEfRQ!`ydLvu@AOT#pC-K1nQgS13bOEcp{b0vK{ z1si=(;z3GGFrgq9HxLt??m>CLP63g*Qu9)5m5P+??Jl>^`Om;0@WIo?F{I+wn^?{O zk#MPZl58x3M+2{~(3sAlw&>lW>_;0{rvwTb$}Lpd6}K^H^)Z*t$0}HSG@H_GR+-4H z3|hVE)vB$tyS!MAYG-V^*L5nF;b?PcOdjLGoBxkrztLxW`ET5Q$zykauCD7!s`~Z! z|Np)JtKOF`Ub%8*W}1Nn3)`g=u?~gtyk`$Ad$;;xMns8$y7KL_78CqJj!pXbWQytc z*qy(n?#G|I@aVbM`_&n00e8AZOQIZjgbtdBI7!6qTN7y5%-Q6Ft%Ly1Exl9<`G=gJol0x2&z_0ymsfn8m1Y)=dIiy zZLovUF+{k{;;GQ=rjK3iAA}AxEx)1TcKKd+XxcG@OgVwYjJ!R}dy5u^t)5yp|Kue$ zD_>q4hrsCERjlsES2I1dIL(`N+CREYLMSeN6~k4A#gkWSEZKM`BcL}WfLY&Rsu;7) zZ`JH6=hy6dedUZz@MgyP=X1GxL?_?5pRld(sm$%nl+a*_munJDk{5}b=TL$e*XLSZ}INZ*JauU1|QbN ztzR#Ae8uY3#cUH;s+G@PUhZGI<>NJ%&ntF4Q=fN%!O7RRx8UU^)%jPhT={prUtWIF zv}xCtuUK(H-tJSvmCb9M+xd3xt@>(ZU-98V@PYK|@9$!7tcl#*)+CU7!1{{O?M7As zxt&f?3LOqhmM`CadwYKTk?;5G|Nr~?`a1i8`8I1)x{ouQxVd7*irVDkeZG8LTvaXg zEb9w5mfovWwU=T{TI+QzA*<7w$6MWRPDSzIHr~sVCQn|Rot19*K>= zANSkeGfg=$A&04F^V$Z*#~HIk1U_*1TwvpHZ;Y@1`}MhdpUljTZJCcg#PS`eG0(rZ z=j+0S3wO%oChu=Z*u=K({JC>^qQb(){|_`W&tG+d``V&OoxQoe$4#vYXak>f3JLJo7J+0M)5uqTRna6H6|CIJ2x&k zuKO_GEcezr>+*LzAu}63Gcz%5T5$YC&Fi(>xfs6uzK}lU$FE=49zCzDtkm1NbLZN` zGv;~s_Pk`a^-l2f^LsE^-M{8a5BJ|Qo%#F!esk8C&TY^VY5Y)G!SC7$=^eMY8?NNu z-Bl`}a>_O|G&GJUIi&Rcy}!>lY}laue&6rBtn>41H}BcA=hT76BDInw!V4O6D&OAP z>M%p3-ow+Av;Em8*&iz`*DAbw_pb8xw%qQvKSg}I>sCJ%Woems_L+ddHO};lpPrs} zpLlMjR^9fzyH?q!rf7Ei&$GG7o3>rynS9EOg?`UIO_}mhYERg&*gfJ6mvTQnIT>G7 zRh4G^WZHif6_plY%aqiFMAL>DDS|yacI+s;QF2*h&Gpy$Ix#yw9RBm?kC>3N)kiG@ zmzxt5_iT;WkZ`bs;Xj+IM(B#!TOBfI6c+g~x*dKbJEe!i&9rq=|8l>%R`N;vc4rt^ z>OTqndT@rW!v5Muqkt39ybJd9-#`B0=w_!-mJXqS2wUbNmq!;DyEFGT6g=YWSSq02 zSN-P3MuiDa-MIp?R2Eo#WO30>R0~i^=vn%q=NG52nvR~H-ZhV+=1@t7iq50^yLUdj zxY&Kx$H&L(J2wSZoXX(TST&PNAlPkkgP{~l%_0+*wUL|CL}t#F%4SaF5(%E)d9P_x zB2)N^)57x>toS5gm@Z%-Qpq;u@b?AG@6^iBfa8 zj2Gzd+@5`X-MvK*iXH}J);&JE==%FRJ2#u3sF{B#_@41nY2SHbR~j6D@hnYTRr2}S z+4mZZhvytf`Ie>GvnrIE>r~GsZQag;Y7>)oo-mm; z5E-dCW%_h;vyP%;Yu2vK&EbknTU#;z$B&9NGV?Ds9WqiARY9GYuBpshDM5{%(h> zySx6k4U%rU6aowOMkul}(@9*rFn-r_ugMxw@c2={qv;XIqr&RV$>SDF9kkFwApSgnX zOWM`^$P$Y@V#iwY(sQ-_jT{z6*NYLn;!#O~fip@Unj~^b-m#hICXwtA6cogyBgx=k zIcf6b%R-;MTwPl?gwvXk-QD}t?T~mn7{L;o>9x@*|OGUK5Z9fsBD)r&APH;?wU^>MzK4KT-RTI$))MI z(nVTp=A4Q~w?oektXL4cs_n*q%hlx`3@=>*i%uCad@?s}=!j$5bv9ihe&X^OEH1hd zdU|@U)Ai%?7MGdLv#-B*`Q*u$_xCU~X1%vIHR>#C%*zdQ7Yle|^HkK~N>igv$%_lT zS$mvAY?PH3*LI8Pc2zP8NlESU*I~L+{_jVbkzpK z>5Lk^>QPI+=NZg+(zA|HkEgq{^QXGy5g*^Tx3}+~Hgl%rqn9ru^)2&LUcHQSj*Og{ z_Uz2e`A)4*mRA<)iSl2(>frd{cvDl;_O%UUphc~2UyZ(~+e$uN(I8ZNXOU}n-y)t~c6FZ$x0$mdE%NT{nCfZeYdW>&FINS`q_e5K50p5JOKmv=O9>@I)LcQCj*YwE2X zg^vw{8!~#FlAS9gOfoK*e=BpyJ3URee!}GVD~u(w=Mv9M+FSj-t>fXQg9ee2kpbtb zSJ?TkxSHjyAGha5Ag99fb8}xaeEs9>*S1FGeA|kB;p^k}etUFls*r3z_?5`FGjyZ3 z`LOdunYHNtF|7Ud<>;Kg__)d+9~Opn8hKCGlU<&+=GocV;x%6`x*I;YnIFHS;Nbr& zD}(Poe)MQj!Cdd9a;5G3^6yr;w7d7qWd^3pZJTXVS(L-95D>h*xV&8dLE&Y)+Fx&` zhiHpUJ$dfjw+~;x-aT%_r*gUW2KS6rlUA)>-O9=>*3;hAr72$a?#|CQz0&4iybkNV zsA*__8xtG*e(Cb%uUq}?ex|6c{~;|Yxif0b=cz{$RveqSzJUAdLGOsaVkE6Ezt23wTnAv!4tZSWdfA-^zSA=do zSNik!@9W^8AUhe$q9^7>*T28M{{DDJM@P-h;-eWFHqkcK-`>1US$Fa5;bxY0MCw%YPI^oLtqB&3J@gztrP?F-> z6Z`Jhl`B^aYL+;>?BY0|wwrW0!-H=D^=m!0W;DjU1SDq879rqS$8Z>~;gE<3C_ z?dNNSd;DRSl&4IYlCfvco^u*gWve!RS?u1=rm=RDO6vQpb*cGradH-(*0asp7F|4` z?UXtFr>%|6ro?CEW~O}^OIEGYQnazDVO{%&;gs%*ZB0{7`AZ%C8zX&qYxZ?6Mn=Z& zoV_JQzrJL~cQKzmc3Lg+fo9^;rAybByxRZglehbe>}@L}CY|*5@!<(s#Qf@1?aLN{ zceQu6JbjcD6%}Qz@mX$#B>$|PlP_MpXjuIG+~3bVlE!IH$~%NpG=f$i-;{b#6_VmyD3Z4D=x3*-?c(P`Ss+gMZERp>D)9+yq~{kck7w_@Q95`t{NrxP8O|iI?VO@-{0RmwtTeQ(7pEyqr$g!n!(FL zCaYF7tNzrF*HGYU>#deuDZZ^@I@O`X@zM=A7tuh_(L|3t8l)ob=G z&ktA_t`pF%t&uJbnQVV5@l%^*_|j<(iFZ#O?foxs>iOM`(~eJ{xRo`}*JcZQ!M3S9 z{mc2;8Tl1=DYZ{BoEpS&^MCrutxq>@+{l}7<;sh9y5gKk?ig%ihpMG8>zkruNO7{AjlY)2D{ueObOG zOW2xkd{O=NpqXEaabow^lPVX(gSh@kKgiq@mSXWNr>4@!oA3Kfw~{3by^>C+cyq7z znv^fJGf;FX!+g$~xQpozcsgz!b?{##%`M^SrN!!~s1Z12!Glw8YWUpNO#JyrJ)uVM zR?Gw6qG-ND-R3hkU9#!&@=-AB4q{^C4zxYxw(jl1qBFW;@BVM*)Q`z{SjA%Q(5jPf z^uj*q-7;ZyzmPdsd;?n?zKdM+Pf6Q!Nyhm5-W0_?{S65V^t8V9`31j-boof;*aUk(&RNIiwuz%r)Ump(`dmdid=Ei->e^>a$hJ(TaDzn7d9~?@xfB1Fr{a~G4c8X?# zv$zD7eAg)A+GoAwdNvE2T~@*LL&o=#C0ooD7A+46Zn*T_lwmRdhD+_%t0Qd=&uX~P zw*I&Z`%Ud$747q3+`-!zTEs+rCUw6N=xG&My<^qE4Q2{VE0<-&)m2LDm@UiDsC}AU z^U1ojvy$7`SUR7D*0Tx86+GXd8F!*T`Cn+oK1Vm^V-ayoH<$!224`4RJ$Zc~n6*t@ z)|knV)uK1(nEIS5t=Y^?CLs%||E@X_sj|OhYm-l1N~UVFdNrzv_PcV)c&g(W`v-g!~8Z4pem94qwV=KQUmI`X7G5cg{z+-{jk8XdQFE zHY@V7K@k7Or=Jyn?72T(WqnL7ubRNTCr7^TJtO|a{N#?nV4DraG7|A7V%~>(_X^6@ zA9~AFGez;_wPy3H!XY!(d|W!IVq2!Mp;NH%v=_HeN?j9r_%qS*;eS>E$4N`lCv#~v zs$@kA>nW^LGy217;a(7+oY*SD`-eI8xzFGJ$Oe8!f1w|9<*Rc~#Yr9NU9h*MFkE1J z-p3C0yqt#*S*{s}O4NO*7oNv%$5<0qvG07Mc+3B+FqOLvjLdJYMt_*{(4IrNa-yEJ zxKgdh`o`ytwk_hz1+zULw`V8s=%1%=V=rIhU9oX{V!4Qn%$*;*k6ru!`>Nx&xmRSL zFdSj*XqIWPU?`lxEWob7SH$p$;fN!jgN(}3|6B$PeQKRnMn(o7Kx2-cu6{1-oD!M< D|Acsw 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';