Correct a parameter order swap in "diffusion.historyquery" for Mercurial
[phabricator.git] / src / applications / phortune / storage / PhortuneSubscription.php
blob84fa23a812f2b8afc5f345b93f057d0759fda911
1 <?php
3 /**
4 * A subscription bills users regularly.
5 */
6 final class PhortuneSubscription
7 extends PhortuneDAO
8 implements
9 PhabricatorPolicyInterface,
10 PhabricatorExtendedPolicyInterface,
11 PhabricatorPolicyCodexInterface,
12 PhabricatorApplicationTransactionInterface {
14 const STATUS_ACTIVE = 'active';
15 const STATUS_CANCELLED = 'cancelled';
17 protected $accountPHID;
18 protected $merchantPHID;
19 protected $triggerPHID;
20 protected $authorPHID;
21 protected $defaultPaymentMethodPHID;
22 protected $subscriptionClassKey;
23 protected $subscriptionClass;
24 protected $subscriptionRefKey;
25 protected $subscriptionRef;
26 protected $status;
27 protected $metadata = array();
29 private $merchant = self::ATTACHABLE;
30 private $account = self::ATTACHABLE;
31 private $implementation = self::ATTACHABLE;
32 private $trigger = self::ATTACHABLE;
34 protected function getConfiguration() {
35 return array(
36 self::CONFIG_AUX_PHID => true,
37 self::CONFIG_SERIALIZATION => array(
38 'metadata' => self::SERIALIZATION_JSON,
40 self::CONFIG_COLUMN_SCHEMA => array(
41 'defaultPaymentMethodPHID' => 'phid?',
42 'subscriptionClassKey' => 'bytes12',
43 'subscriptionClass' => 'text128',
44 'subscriptionRefKey' => 'bytes12',
45 'subscriptionRef' => 'text128',
46 'status' => 'text32',
48 self::CONFIG_KEY_SCHEMA => array(
49 'key_subscription' => array(
50 'columns' => array('subscriptionClassKey', 'subscriptionRefKey'),
51 'unique' => true,
53 'key_account' => array(
54 'columns' => array('accountPHID'),
56 'key_merchant' => array(
57 'columns' => array('merchantPHID'),
60 ) + parent::getConfiguration();
63 public function getPHIDType() {
64 return PhortuneSubscriptionPHIDType::TYPECONST;
67 public static function initializeNewSubscription(
68 PhortuneAccount $account,
69 PhortuneMerchant $merchant,
70 PhabricatorUser $author,
71 PhortuneSubscriptionImplementation $implementation,
72 PhabricatorTriggerClock $clock) {
74 $trigger = id(new PhabricatorWorkerTrigger())
75 ->setClock($clock);
77 return id(new PhortuneSubscription())
78 ->setStatus(self::STATUS_ACTIVE)
79 ->setAccountPHID($account->getPHID())
80 ->attachAccount($account)
81 ->setMerchantPHID($merchant->getPHID())
82 ->attachMerchant($merchant)
83 ->setAuthorPHID($author->getPHID())
84 ->setSubscriptionClass(get_class($implementation))
85 ->setSubscriptionRef($implementation->getRef())
86 ->attachImplementation($implementation)
87 ->attachTrigger($trigger);
90 public function attachImplementation(
91 PhortuneSubscriptionImplementation $impl) {
92 $this->implementation = $impl;
93 return $this;
96 public function getImplementation() {
97 return $this->assertAttached($this->implementation);
100 public function attachAccount(PhortuneAccount $account) {
101 $this->account = $account;
102 return $this;
105 public function getAccount() {
106 return $this->assertAttached($this->account);
109 public function attachMerchant(PhortuneMerchant $merchant) {
110 $this->merchant = $merchant;
111 return $this;
114 public function getMerchant() {
115 return $this->assertAttached($this->merchant);
118 public function attachTrigger(PhabricatorWorkerTrigger $trigger) {
119 $this->trigger = $trigger;
120 return $this;
123 public function getTrigger() {
124 return $this->assertAttached($this->trigger);
127 public function save() {
128 $this->subscriptionClassKey = PhabricatorHash::digestForIndex(
129 $this->subscriptionClass);
131 $this->subscriptionRefKey = PhabricatorHash::digestForIndex(
132 $this->subscriptionRef);
134 $is_new = (!$this->getID());
136 $this->openTransaction();
138 // If we're saving this subscription for the first time, we're also
139 // going to set up the trigger for it.
140 if ($is_new) {
141 $trigger_phid = PhabricatorPHID::generateNewPHID(
142 PhabricatorWorkerTriggerPHIDType::TYPECONST);
143 $this->setTriggerPHID($trigger_phid);
146 $result = parent::save();
148 if ($is_new) {
149 $trigger_action = new PhabricatorScheduleTaskTriggerAction(
150 array(
151 'class' => 'PhortuneSubscriptionWorker',
152 'data' => array(
153 'subscriptionPHID' => $this->getPHID(),
155 'options' => array(
156 'objectPHID' => $this->getPHID(),
157 'priority' => PhabricatorWorker::PRIORITY_BULK,
161 $trigger = $this->getTrigger();
162 $trigger->setPHID($trigger_phid);
163 $trigger->setAction($trigger_action);
164 $trigger->save();
166 $this->saveTransaction();
168 $account = $this->getAccount();
169 $merchant = $this->getMerchant();
170 $account->writeMerchantEdge($merchant);
172 return $result;
175 public function getSubscriptionName() {
176 return $this->getImplementation()->getName($this);
179 public function getSubscriptionFullName() {
180 return $this->getImplementation()->getFullName($this);
183 public function getSubscriptionCrumbName() {
184 return $this->getImplementation()->getCrumbName($this);
187 public function getCartName(PhortuneCart $cart) {
188 return $this->getImplementation()->getCartName($this, $cart);
191 public function getURI() {
192 return urisprintf(
193 '/phortune/account/%d/subscriptions/%d/',
194 $this->getAccount()->getID(),
195 $this->getID());
198 public function getEditURI() {
199 $account_id = $this->getAccount()->getID();
200 $id = $this->getID();
202 return "/phortune/{$account_id}/subscription/edit/{$id}/";
205 public function getMerchantURI() {
206 $merchant_id = $this->getMerchant()->getID();
207 $id = $this->getID();
208 return "/phortune/merchant/{$merchant_id}/subscription/view/{$id}/";
211 public function getCostForBillingPeriodAsCurrency($start_epoch, $end_epoch) {
212 return $this->getImplementation()->getCostForBillingPeriodAsCurrency(
213 $this,
214 $start_epoch,
215 $end_epoch);
218 public function shouldInvoiceForBillingPeriod($start_epoch, $end_epoch) {
219 return $this->getImplementation()->shouldInvoiceForBillingPeriod(
220 $this,
221 $start_epoch,
222 $end_epoch);
225 public function getPurchaseName(
226 PhortuneProduct $product,
227 PhortunePurchase $purchase) {
228 return $this->getImplementation()->getPurchaseName(
229 $this,
230 $product,
231 $purchase);
234 public function getPurchaseURI(
235 PhortuneProduct $product,
236 PhortunePurchase $purchase) {
237 return $this->getImplementation()->getPurchaseURI(
238 $this,
239 $product,
240 $purchase);
243 public function didPurchaseProduct(
244 PhortuneProduct $product,
245 PhortunePurchase $purchase) {
246 return $this->getImplementation()->didPurchaseProduct(
247 $this,
248 $product,
249 $purchase);
252 /* -( PhabricatorApplicationTransactionInterface )------------------------- */
255 public function getApplicationTransactionEditor() {
256 return new PhortuneSubscriptionEditor();
259 public function getApplicationTransactionTemplate() {
260 return new PhortuneSubscriptionTransaction();
263 /* -( PhabricatorPolicyInterface )----------------------------------------- */
266 public function getCapabilities() {
267 return array(
268 PhabricatorPolicyCapability::CAN_VIEW,
269 PhabricatorPolicyCapability::CAN_EDIT,
273 public function getPolicy($capability) {
274 return PhabricatorPolicies::getMostOpenPolicy();
277 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
278 // See T13366. If you can edit the merchant associated with this
279 // subscription, you can view the subscription.
280 if ($capability === PhabricatorPolicyCapability::CAN_VIEW) {
281 $any_edit = PhortuneMerchantQuery::canViewersEditMerchants(
282 array($viewer->getPHID()),
283 array($this->getMerchantPHID()));
284 if ($any_edit) {
285 return true;
289 return false;
293 /* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
296 public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
297 if ($this->hasAutomaticCapability($capability, $viewer)) {
298 return array();
301 // See T13366. For blanket view and edit permissions on all subscriptions,
302 // you must be able to edit the associated account.
303 return array(
304 array(
305 $this->getAccount(),
306 PhabricatorPolicyCapability::CAN_EDIT,
312 /* -( PhabricatorPolicyCodexInterface )------------------------------------ */
315 public function newPolicyCodex() {
316 return new PhortuneSubscriptionPolicyCodex();