@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Build a very basic subscription detail page in Phortune

Summary:
Ref T6881.

- Add a subscription detail page.

Minor cosmetics:

- Fix glyph, from "X" (old "X marks the spot" icon) to "diamond" (new gem icon).
- Name the initial account "Default Account" instead of "Personal Account", since this seems more general.

Test Plan:
{F278623}

And I got two full days to test that Jan 30/31 -> Feb 28 billing logic!

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T6881

Differential Revision: https://secure.phabricator.com/D11576

+164 -17
+2
src/__phutil_library_map__.php
··· 2815 2815 'PhortuneSubscriptionQuery' => 'applications/phortune/query/PhortuneSubscriptionQuery.php', 2816 2816 'PhortuneSubscriptionSearchEngine' => 'applications/phortune/query/PhortuneSubscriptionSearchEngine.php', 2817 2817 'PhortuneSubscriptionTableView' => 'applications/phortune/view/PhortuneSubscriptionTableView.php', 2818 + 'PhortuneSubscriptionViewController' => 'applications/phortune/controller/PhortuneSubscriptionViewController.php', 2818 2819 'PhortuneTestPaymentProvider' => 'applications/phortune/provider/PhortuneTestPaymentProvider.php', 2819 2820 'PhortuneWePayPaymentProvider' => 'applications/phortune/provider/PhortuneWePayPaymentProvider.php', 2820 2821 'PhragmentBrowseController' => 'applications/phragment/controller/PhragmentBrowseController.php', ··· 6168 6169 'PhortuneSubscriptionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 6169 6170 'PhortuneSubscriptionSearchEngine' => 'PhabricatorApplicationSearchEngine', 6170 6171 'PhortuneSubscriptionTableView' => 'AphrontView', 6172 + 'PhortuneSubscriptionViewController' => 'PhortuneController', 6171 6173 'PhortuneTestPaymentProvider' => 'PhortunePaymentProvider', 6172 6174 'PhortuneWePayPaymentProvider' => 'PhortunePaymentProvider', 6173 6175 'PhragmentBrowseController' => 'PhragmentController',
+13 -5
src/applications/phortune/application/PhabricatorPhortuneApplication.php
··· 23 23 } 24 24 25 25 public function getTitleGlyph() { 26 - return "\xE2\x9C\x98"; 26 + return "\xE2\x97\x87"; 27 27 } 28 28 29 29 public function getApplicationGroup() { ··· 45 45 ), 46 46 'order/(?:query/(?P<queryKey>[^/]+)/)?' 47 47 => 'PhortuneCartListController', 48 - 'subscription/(?:query/(?P<queryKey>[^/]+)/)?' 49 - => 'PhortuneSubscriptionListController', 48 + 'subscription/' => array( 49 + '(?:query/(?P<queryKey>[^/]+)/)?' 50 + => 'PhortuneSubscriptionListController', 51 + 'view/(?P<id>\d+)/' 52 + => 'PhortuneSubscriptionViewController', 53 + ), 50 54 'charge/(?:query/(?P<queryKey>[^/]+)/)?' 51 55 => 'PhortuneChargeListController', 52 56 ), ··· 81 85 'edit/(?:(?P<id>\d+)/)?' => 'PhortuneMerchantEditController', 82 86 'orders/(?P<merchantID>\d+)/(?:query/(?P<queryKey>[^/]+)/)?' 83 87 => 'PhortuneCartListController', 84 - 'subscription/(?P<merchantID>\d+)/(?:query/(?P<queryKey>[^/]+)/)?' 85 - => 'PhortuneSubscriptionListController', 88 + '(?P<merchantID>\d+)/subscription/' => array( 89 + '(?:query/(?P<queryKey>[^/]+)/)?' 90 + => 'PhortuneSubscriptionListController', 91 + 'view/(?P<id>\d+)/' 92 + => 'PhortuneSubscriptionViewController', 93 + ), 86 94 '(?P<id>\d+)/' => 'PhortuneMerchantViewController', 87 95 ), 88 96 ),
+1 -3
src/applications/phortune/controller/PhortuneAccountViewController.php
··· 35 35 $title = $account->getName(); 36 36 37 37 $crumbs = $this->buildApplicationCrumbs(); 38 - $crumbs->addTextCrumb( 39 - $account->getName(), 40 - $request->getRequestURI()); 38 + $this->addAccountCrumb($crumbs, $account, $link = false); 41 39 42 40 $header = id(new PHUIHeaderView()) 43 41 ->setHeader($title);
+21 -1
src/applications/phortune/controller/PhortuneController.php
··· 7 7 PhortuneAccount $account, 8 8 $link = true) { 9 9 10 - $name = pht('Account'); 10 + $name = $account->getName(); 11 11 $href = null; 12 12 13 13 if ($link) { 14 14 $href = $this->getApplicationURI($account->getID().'/'); 15 + $crumbs->addTextCrumb($name, $href); 16 + } else { 17 + $crumbs->addTextCrumb($name); 18 + } 19 + } 20 + 21 + protected function addMerchantCrumb( 22 + $crumbs, 23 + PhortuneMerchant $merchant, 24 + $link = true) { 25 + 26 + $name = $merchant->getName(); 27 + $href = null; 28 + 29 + $crumbs->addTextCrumb( 30 + pht('Merchants'), 31 + $this->getApplicationURI('merchant/')); 32 + 33 + if ($link) { 34 + $href = $this->getApplicationURI('merchant/'.$merchant->getID().'/'); 15 35 $crumbs->addTextCrumb($name, $href); 16 36 } else { 17 37 $crumbs->addTextCrumb($name);
+1 -1
src/applications/phortune/controller/PhortuneMerchantViewController.php
··· 190 190 id(new PhabricatorActionView()) 191 191 ->setName(pht('View Subscriptions')) 192 192 ->setIcon('fa-moon-o') 193 - ->setHref($this->getApplicationURI("merchant/subscription/{$id}/")) 193 + ->setHref($this->getApplicationURI("merchant/{$id}/subscription/")) 194 194 ->setDisabled(!$can_edit) 195 195 ->setWorkflow(!$can_edit)); 196 196
+2 -6
src/applications/phortune/controller/PhortuneSubscriptionListController.php
··· 85 85 $merchant = $this->merchant; 86 86 if ($merchant) { 87 87 $id = $merchant->getID(); 88 - $crumbs->addTextCrumb( 89 - $merchant->getName(), 90 - $this->getApplicationURI("merchant/{$id}/")); 88 + $this->addMerchantCrumb($crumbs, $merchant); 91 89 $crumbs->addTextCrumb( 92 90 pht('Subscriptions'), 93 91 $this->getApplicationURI("merchant/subscriptions/{$id}/")); ··· 96 94 $account = $this->account; 97 95 if ($account) { 98 96 $id = $account->getID(); 99 - $crumbs->addTextCrumb( 100 - $account->getName(), 101 - $this->getApplicationURI("{$id}/")); 97 + $this->addAccountCrumb($crumbs, $account); 102 98 $crumbs->addTextCrumb( 103 99 pht('Subscriptions'), 104 100 $this->getApplicationURI("{$id}/subscription/"));
+59
src/applications/phortune/controller/PhortuneSubscriptionViewController.php
··· 1 + <?php 2 + 3 + final class PhortuneSubscriptionViewController extends PhortuneController { 4 + 5 + public function handleRequest(AphrontRequest $request) { 6 + $viewer = $this->getViewer(); 7 + 8 + $subscription = id(new PhortuneSubscriptionQuery()) 9 + ->setViewer($viewer) 10 + ->withIDs(array($request->getURIData('id'))) 11 + ->needTriggers(true) 12 + ->executeOne(); 13 + if (!$subscription) { 14 + return new Aphront404Response(); 15 + } 16 + 17 + $is_merchant = (bool)$request->getURIData('merchantID'); 18 + 19 + $title = pht('Subscription: %s', $subscription->getSubscriptionName()); 20 + 21 + $header = id(new PHUIHeaderView()) 22 + ->setHeader($subscription->getSubscriptionName()); 23 + 24 + $actions = id(new PhabricatorActionListView()) 25 + ->setUser($viewer) 26 + ->setObjectURI($request->getRequestURI()); 27 + 28 + $crumbs = $this->buildApplicationCrumbs(); 29 + if ($is_merchant) { 30 + $this->addMerchantCrumb($crumbs, $subscription->getMerchant()); 31 + } else { 32 + $this->addAccountCrumb($crumbs, $subscription->getAccount()); 33 + } 34 + $crumbs->addTextCrumb(pht('Subscription %d', $subscription->getID())); 35 + 36 + $properties = id(new PHUIPropertyListView()) 37 + ->setUser($viewer) 38 + ->setActionList($actions); 39 + 40 + $next_invoice = $subscription->getTrigger()->getNextEventPrediction(); 41 + $properties->addProperty( 42 + pht('Next Invoice'), 43 + phabricator_datetime($next_invoice, $viewer)); 44 + 45 + $object_box = id(new PHUIObjectBoxView()) 46 + ->setHeader($header) 47 + ->addPropertyList($properties); 48 + 49 + return $this->buildApplicationPage( 50 + array( 51 + $crumbs, 52 + $object_box, 53 + ), 54 + array( 55 + 'title' => $title, 56 + )); 57 + } 58 + 59 + }
+25
src/applications/phortune/query/PhortuneSubscriptionQuery.php
··· 9 9 private $merchantPHIDs; 10 10 private $statuses; 11 11 12 + private $needTriggers; 13 + 12 14 public function withIDs(array $ids) { 13 15 $this->ids = $ids; 14 16 return $this; ··· 31 33 32 34 public function withStatuses(array $statuses) { 33 35 $this->statuses = $statuses; 36 + return $this; 37 + } 38 + 39 + public function needTriggers($need_triggers) { 40 + $this->needTriggers = $need_triggers; 34 41 return $this; 35 42 } 36 43 ··· 100 107 continue; 101 108 } 102 109 $subscription->attachImplementation($implementation); 110 + } 111 + 112 + if ($this->needTriggers) { 113 + $trigger_phids = mpull($subscriptions, 'getTriggerPHID'); 114 + $triggers = id(new PhabricatorWorkerTriggerQuery()) 115 + ->setViewer($this->getViewer()) 116 + ->withPHIDs($trigger_phids) 117 + ->needEvents(true) 118 + ->execute(); 119 + $triggers = mpull($triggers, null, 'getPHID'); 120 + foreach ($subscriptions as $key => $subscription) { 121 + $trigger = idx($triggers, $subscription->getTriggerPHID()); 122 + if (!$trigger) { 123 + unset($subscriptions[$key]); 124 + continue; 125 + } 126 + $subscription->attachTrigger($trigger); 127 + } 103 128 } 104 129 105 130 return $subscriptions;
+1
src/applications/phortune/query/PhortuneSubscriptionSearchEngine.php
··· 144 144 $merchant = $this->getMerchant(); 145 145 if ($merchant) { 146 146 $header = pht('Subscriptions for %s', $merchant->getName()); 147 + $table->setIsMerchantView(true); 147 148 } else { 148 149 $header = pht('Your Subscriptions'); 149 150 }
+1 -1
src/applications/phortune/storage/PhortuneAccount.php
··· 32 32 $xactions = array(); 33 33 $xactions[] = id(new PhortuneAccountTransaction()) 34 34 ->setTransactionType(PhortuneAccountTransaction::TYPE_NAME) 35 - ->setNewValue(pht('Personal Account')); 35 + ->setNewValue(pht('Default Account')); 36 36 37 37 $xactions[] = id(new PhortuneAccountTransaction()) 38 38 ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
+14
src/applications/phortune/storage/PhortuneSubscription.php
··· 153 153 ), 154 154 )); 155 155 156 + $trigger->setPHID($trigger_phid); 156 157 $trigger->setAction($trigger_action); 157 158 $trigger->save(); 158 159 } ··· 163 164 164 165 public function getSubscriptionName() { 165 166 return $this->getImplementation()->getName($this); 167 + } 168 + 169 + public function getURI() { 170 + $account_id = $this->getAccount()->getID(); 171 + $id = $this->getID(); 172 + 173 + return "/phortune/{$account_id}/subscription/view/{$id}/"; 174 + } 175 + 176 + public function getMerchantURI() { 177 + $merchant_id = $this->getMerchant()->getID(); 178 + $id = $this->getID(); 179 + return "/phortune/merchant/{$merchant_id}/subscription/view/{$id}/"; 166 180 } 167 181 168 182
+24
src/applications/phortune/view/PhortuneSubscriptionTableView.php
··· 4 4 5 5 private $subscriptions; 6 6 private $handles; 7 + private $isMerchantView; 7 8 8 9 public function setHandles(array $handles) { 9 10 $this->handles = $handles; ··· 23 24 return $this->subscriptions; 24 25 } 25 26 27 + public function setIsMerchantView($is_merchant_view) { 28 + $this->isMerchantView = $is_merchant_view; 29 + return $this; 30 + } 31 + 32 + public function getIsMerchantView() { 33 + return $this->isMerchantView; 34 + } 35 + 26 36 public function render() { 27 37 $subscriptions = $this->getSubscriptions(); 28 38 $handles = $this->getHandles(); ··· 31 41 $rows = array(); 32 42 $rowc = array(); 33 43 foreach ($subscriptions as $subscription) { 44 + if ($this->getIsMerchantView()) { 45 + $uri = $subscription->getMerchantURI(); 46 + } else { 47 + $uri = $subscription->getURI(); 48 + } 49 + 34 50 $subscription_link = $handles[$subscription->getPHID()]->renderLink(); 35 51 $rows[] = array( 36 52 $subscription->getID(), 53 + phutil_tag( 54 + 'a', 55 + array( 56 + 'href' => $uri, 57 + ), 58 + $subscription->getSubscriptionName()), 37 59 phabricator_datetime($subscription->getDateCreated(), $viewer), 38 60 ); 39 61 } ··· 42 64 ->setHeaders( 43 65 array( 44 66 pht('ID'), 67 + pht('Name'), 45 68 pht('Created'), 46 69 )) 47 70 ->setColumnClasses( 48 71 array( 49 72 '', 73 + 'wide', 50 74 'right', 51 75 )); 52 76