1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* This software may be modified and distributed under the terms |
7
|
|
|
* of the MIT license. See the LICENSE file for details. |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace Shapin\Stripe\Configuration; |
11
|
|
|
|
12
|
|
|
use Shapin\Stripe\Model\Subscription\Subscription; |
13
|
|
|
use Symfony\Component\Config\Definition\Builder\TreeBuilder; |
14
|
|
|
use Symfony\Component\Config\Definition\ConfigurationInterface; |
15
|
|
|
|
16
|
|
|
class SubscriptionCreate implements ConfigurationInterface |
17
|
|
|
{ |
18
|
3 |
|
public function getConfigTreeBuilder() |
19
|
|
|
{ |
20
|
3 |
|
$treeBuilder = new TreeBuilder('shapin_stripe'); |
21
|
3 |
|
$rootNode = $treeBuilder->getRootNode(); |
22
|
|
|
|
23
|
|
|
$rootNode |
24
|
3 |
|
->children() |
25
|
3 |
|
->scalarNode('customer') |
26
|
3 |
|
->isRequired() |
27
|
3 |
|
->info('The identifier of the customer to subscribe.') |
28
|
3 |
|
->end() |
29
|
3 |
|
->floatNode('application_fee_percent') |
30
|
3 |
|
->info('A non-negative decimal between 0 and 100, with at most two decimal places. This represents the percentage of the subscription invoice subtotal that will be transferred to the application owner’s Stripe account. The request must be made with an OAuth key in order to set an application fee percentage. For more information, see the application fees documentation.') |
31
|
3 |
|
->end() |
32
|
3 |
|
->enumNode('billing') |
33
|
3 |
|
->values([Subscription::BILLING_CHARGE_AUTOMATICALLY, Subscription::BILLING_SEND_INVOICE]) |
34
|
3 |
|
->info('Either charge_automatically, or send_invoice. When charging automatically, Stripe will attempt to pay this subscription at the end of the cycle using the default source attached to the customer. When sending an invoice, Stripe will email your customer an invoice with payment instructions. Defaults to charge_automatically.') |
35
|
3 |
|
->end() |
36
|
3 |
|
->integerNode('billing_cycle_anchor') |
37
|
3 |
|
->info('A future timestamp to anchor the subscription’s billing cycle. This is used to determine the date of the first full invoice, and, for plans with month or year intervals, the day of the month for subsequent invoices.') |
38
|
3 |
|
->end() |
39
|
3 |
|
->arrayNode('billing_thresholds') |
40
|
3 |
|
->children() |
41
|
3 |
|
->integerNode('amount_gte') |
42
|
3 |
|
->info('Monetary threshold that triggers the subscription to advance to a new billing period') |
43
|
3 |
|
->end() |
44
|
3 |
|
->booleanNode('reset_billing_cycle_anchor') |
45
|
3 |
|
->info('Indicates if the billing_cycle_anchor should be reset when a threshold is reached. If true, billing_cycle_anchor will be updated to the date/time the threshold was last reached; otherwise, the value will remain unchanged.') |
46
|
3 |
|
->end() |
47
|
3 |
|
->end() |
48
|
3 |
|
->info('Define thresholds at which an invoice will be sent, and the subscription advanced to a new billing period. Pass an empty string to remove previously-defined thresholds.') |
49
|
3 |
|
->end() |
50
|
3 |
|
->booleanNode('cancel_at_period_end') |
51
|
3 |
|
->info('Boolean indicating whether this subscription should cancel at the end of the current period.') |
52
|
3 |
|
->end() |
53
|
3 |
|
->scalarNode('coupon') |
54
|
3 |
|
->info('The code of the coupon to apply to this subscription. A coupon applied to a subscription will only affect invoices created for that particular subscription. This will be unset if you POST an empty value.') |
55
|
3 |
|
->end() |
56
|
3 |
|
->integerNode('days_until_due') |
57
|
3 |
|
->info('Number of days a customer has to pay invoices generated by this subscription. Valid only for subscriptions where billing is set to send_invoice.') |
58
|
3 |
|
->end() |
59
|
3 |
|
->scalarNode('default_source') |
60
|
3 |
|
->info('ID of the default payment source for the subscription. It must belong to the customer associated with the subscription and be in a chargeable state. If not set, defaults to the customer’s default source.') |
61
|
3 |
|
->end() |
62
|
3 |
|
->arrayNode('default_tax_rates') |
63
|
3 |
|
->beforeNormalization()->castToArray()->end() |
64
|
3 |
|
->scalarPrototype()->end() |
65
|
3 |
|
->info('The tax rates that will apply to any subscription item that does not have tax_rates set. Invoices created will have their default_tax_rates populated from the subscription.') |
66
|
3 |
|
->end() |
67
|
3 |
|
->arrayNode('items') |
68
|
3 |
|
->isRequired() |
69
|
3 |
|
->requiresAtLeastOneElement() |
70
|
3 |
|
->arrayPrototype() |
71
|
3 |
|
->children() |
72
|
3 |
|
->scalarNode('plan') |
73
|
3 |
|
->isRequired() |
74
|
3 |
|
->info('Plan ID for this item, as a string.') |
75
|
3 |
|
->end() |
76
|
3 |
|
->arrayNode('billing_thresholds') |
77
|
3 |
|
->children() |
78
|
3 |
|
->integerNode('usage_gte') |
79
|
3 |
|
->isRequired() |
80
|
3 |
|
->info('Usage threshold that triggers the subscription to advance to a new billing period') |
81
|
3 |
|
->end() |
82
|
3 |
|
->end() |
83
|
3 |
|
->info('Define thresholds at which an invoice will be sent, and the subscription advanced to a new billing period') |
84
|
3 |
|
->end() |
85
|
3 |
|
->arrayNode('metadata') |
86
|
3 |
|
->scalarPrototype()->end() |
87
|
3 |
|
->info('Set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format.') |
88
|
3 |
|
->end() |
89
|
3 |
|
->integerNode('quantity') |
90
|
3 |
|
->info('Quantity for this item.') |
91
|
3 |
|
->end() |
92
|
3 |
|
->end() |
93
|
3 |
|
->end() |
94
|
3 |
|
->info('Define thresholds at which an invoice will be sent, and the subscription advanced to a new billing period. Pass an empty string to remove previously-defined thresholds.') |
95
|
3 |
|
->end() |
96
|
3 |
|
->arrayNode('metadata') |
97
|
3 |
|
->scalarPrototype()->end() |
98
|
3 |
|
->info('Set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format. Individual keys can be unset by posting an empty value to them. All keys can be unset by posting an empty value to metadata.') |
99
|
3 |
|
->end() |
100
|
3 |
|
->booleanNode('prorate') |
101
|
3 |
|
->info('Boolean (defaults to true) telling us whether to credit for unused time when the billing cycle changes (e.g. when switching plans, resetting billing_cycle_anchor=now, or starting a trial), or if an item’s quantity changes. If false, the anchor period will be free (similar to a trial) and no proration adjustments will be created.') |
102
|
3 |
|
->end() |
103
|
3 |
|
->integerNode('trial_end') |
104
|
3 |
|
->info('Unix timestamp representing the end of the trial period the customer will get before being charged for the first time. This will always overwrite any trials that might apply via a subscribed plan. If set, trial_end will override the default trial period of the plan the customer is being subscribed to. The special value now can be provided to end the customer’s trial immediately.') |
105
|
3 |
|
->end() |
106
|
3 |
|
->booleanNode('trial_from_plan') |
107
|
3 |
|
->info('Indicates if a plan’s trial_period_days should be applied to the subscription. Setting trial_end per subscription is preferred, and this defaults to false. Setting this flag to true together with trial_end is not allowed.') |
108
|
3 |
|
->end() |
109
|
3 |
|
->integerNode('trial_period_days') |
110
|
3 |
|
->info('Integer representing the number of trial period days before the customer is charged for the first time. This will always overwrite any trials that might apply via a subscribed plan.') |
111
|
3 |
|
->end() |
112
|
3 |
|
->end() |
113
|
|
|
; |
114
|
|
|
|
115
|
|
|
$rootNode |
116
|
3 |
|
->validate() |
117
|
|
View Code Duplication |
->ifTrue(function ($v) { |
|
|
|
|
118
|
2 |
|
return isset($v['billing']) && Subscription::BILLING_SEND_INVOICE !== $v['billing'] && isset($v['days_until_due']); |
119
|
3 |
|
}) |
120
|
3 |
|
->thenInvalid('You can only set "days_until_due" for "send_invoice" billing type.') |
121
|
3 |
|
->end() |
122
|
3 |
|
->validate() |
123
|
|
|
->ifTrue(function ($v) { |
124
|
1 |
|
return isset($v['trial_from_plan']) && true === $v['trial_from_plan'] && isset($v['trial_period_days']); |
125
|
3 |
|
}) |
126
|
3 |
|
->thenInvalid('You cannot specify "trial_period_days" when "trial_from_plan" is true.') |
127
|
3 |
|
->end() |
128
|
|
|
; |
129
|
|
|
|
130
|
3 |
|
return $treeBuilder; |
131
|
|
|
} |
132
|
|
|
} |
133
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.