PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.0.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.0.0
2.0.0 1.11.2 1.11.1 1.11.0 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.6 1.9.5 trunk 1.3.0 1.3.1 1.3.2 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 All 61 releases
subscription / includes / Installer.php

Installer.php in Subscriptions for WooCommerce with Stripe Recurring Payments 2.0.0, at includes/Installer.php

304 lines 10.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SpringDevs\Subscription;
4
5 use SpringDevs\Subscription\Illuminate\Gateways\Paypal\PaypalDB;
6
7 /**
8 * Class Installer
9 *
10 * @package SpringDevs\Subscription
11 */
12 class Installer {
13
14 /**
15 * Database schema version. Bump whenever a custom table changes.
16 *
17 * @var string
18 */
19 const DB_VERSION = '1.3.0';
20
21 /**
22 * Run the installer
23 *
24 * @return void
25 */
26 public function run() {
27 $this->add_version();
28 $this->register_schedules();
29 $this->create_tables();
30 }
31
32 /**
33 * Create/upgrade custom tables when the stored schema version is outdated.
34 *
35 * Lets existing installs pick up new tables on update without a manual
36 * deactivate/reactivate. A single option read short-circuits once current.
37 *
38 * @return void
39 */
40 public static function maybe_upgrade() {
41 if ( get_option( 'subscrpt_db_version' ) === self::DB_VERSION ) {
42 return;
43 }
44
45 ( new self() )->create_tables();
46 }
47
48 /**
49 * Add time and version on DB
50 */
51 public function add_version() {
52 $installed = get_option( 'subscrpt_installed' );
53
54 if ( ! $installed ) {
55 update_option( 'subscrpt_installed', time() );
56 }
57
58 update_option( 'subscrpt_version', SUBSCRPT_VERSION );
59
60 update_option( 'subscrpt_manual_renew_cart_notice', 'Subscriptional product added to cart. Please complete the checkout to renew subscription.' );
61 }
62
63 /**
64 * Register cron events.
65 *
66 * @return void
67 */
68 public function register_schedules() {
69 if ( ! wp_next_scheduled( 'subscrpt_hourly_cron' ) ) {
70 wp_schedule_event( strtotime( 'tomorrow midnight' ), 'hourly', 'subscrpt_hourly_cron' );
71 }
72 }
73
74 /**
75 * Create necessary database tables
76 *
77 * @return void
78 */
79 public function create_tables() {
80 if ( ! function_exists( 'dbDelta' ) ) {
81 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
82 }
83
84 $this->create_histories_table();
85 $this->create_stats_snapshot_table();
86 $this->create_cancellation_feedback_table();
87 $this->create_plan_group_table();
88 $this->create_plan_table();
89 $this->create_plan_relation_table();
90 PaypalDB::maybe_create_tables();
91
92 update_option( 'subscrpt_db_version', self::DB_VERSION );
93 }
94
95 /**
96 * Create the daily stats snapshot table.
97 *
98 * One row per calendar day holding the subscription status counts and the
99 * total monthly recurring revenue (MRR) at snapshot time. Powers MRR/
100 * subscription "over time" charts in reports and the recovery report.
101 *
102 * @return void
103 */
104 public function create_stats_snapshot_table() {
105 global $wpdb;
106
107 $charset_collate = $wpdb->get_charset_collate();
108 $table_name = $wpdb->prefix . 'subscrpt_stats_snapshot';
109
110 $schema = "CREATE TABLE IF NOT EXISTS `{$table_name}` (
111 `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
112 `snapshot_date` DATE NOT NULL,
113 `active_count` INT(11) NOT NULL DEFAULT 0,
114 `pending_count` INT(11) NOT NULL DEFAULT 0,
115 `on_hold_count` INT(11) NOT NULL DEFAULT 0,
116 `cancelled_count` INT(11) NOT NULL DEFAULT 0,
117 `expired_count` INT(11) NOT NULL DEFAULT 0,
118 `pe_cancelled_count` INT(11) NOT NULL DEFAULT 0,
119 `active_mrr` DECIMAL(14,2) NOT NULL DEFAULT 0,
120 `created_at` DATETIME NOT NULL,
121 PRIMARY KEY (`id`),
122 UNIQUE KEY `snapshot_date` (`snapshot_date`)
123 ) $charset_collate";
124
125 dbDelta( $schema );
126 }
127
128 /**
129 * Create the cancellation survey table.
130 *
131 * One row per subscription — the latest cancellation survey (a re-cancel after
132 * reactivation overwrites the previous row rather than accumulating a log, so
133 * churn-by-reason reports never double-count a subscription). Stores the
134 * customer's stated reason (key + a label snapshot that survives later reason
135 * edits/deletes) and optional comment. Consumed for churn tracking — the recovery
136 * plugin joins its recovery log to this table on subscription_id.
137 *
138 * @return void
139 */
140 public function create_cancellation_feedback_table() {
141 global $wpdb;
142
143 $charset_collate = $wpdb->get_charset_collate();
144 $table_name = $wpdb->prefix . 'subscrpt_cancellation_feedback';
145
146 $schema = "CREATE TABLE IF NOT EXISTS `{$table_name}` (
147 `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
148 `subscription_id` BIGINT(20) UNSIGNED NOT NULL,
149 `customer_id` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
150 `reason_key` VARCHAR(60) NOT NULL DEFAULT '',
151 `reason_label` VARCHAR(191) NOT NULL DEFAULT '',
152 `comment` TEXT NULL,
153 `created_at` DATETIME NOT NULL,
154 PRIMARY KEY (`id`),
155 KEY `subscription_id` (`subscription_id`),
156 KEY `created_at` (`created_at`)
157 ) $charset_collate";
158
159 dbDelta( $schema );
160 }
161
162 /**
163 * Create the subscription plan group table.
164 *
165 * A plan group is a named, reusable subscription plan (e.g. "Premium
166 * Membership") attached to one or more products. This is the free base
167 * schema; Pro adds columns on top via versioned migrations keyed on
168 * `subscrpt_db_version`.
169 *
170 * type: 1 = Subscribe & Save, 2 = Recurring, 3 = Installment (free writes 2).
171 * product_type: 1 = specific products, 2 = taxonomy (free writes 1).
172 * data: JSON (group-level settings).
173 *
174 * @return void
175 */
176 public function create_plan_group_table() {
177 global $wpdb;
178
179 $charset_collate = $wpdb->get_charset_collate();
180 $table_name = $wpdb->prefix . 'subscrpt_plan_group';
181
182 $schema = "CREATE TABLE IF NOT EXISTS `{$table_name}` (
183 `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
184 `type` TINYINT(2) NOT NULL DEFAULT 2,
185 `product_type` TINYINT(2) NOT NULL DEFAULT 1,
186 `title` VARCHAR(255) NOT NULL DEFAULT '',
187 `status` VARCHAR(20) NOT NULL DEFAULT 'active',
188 `data` LONGTEXT NULL,
189 `created_at` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
190 `updated_at` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
191 PRIMARY KEY (`id`),
192 KEY `type` (`type`),
193 KEY `status` (`status`)
194 ) $charset_collate";
195
196 dbDelta( $schema );
197 }
198
199 /**
200 * Create the subscription plan (term) table.
201 *
202 * A plan is one billing term inside a group (e.g. "every 1 month"). There is
203 * no price column — pricing lives per product on the relation.
204 *
205 * billing_interval: 1 = day, 2 = week, 3 = month, 4 = year.
206 * billing_length: expiry in cycles, 0 = unlimited.
207 * price_mode: snapshot (default) | live (free always snapshot).
208 *
209 * @return void
210 */
211 public function create_plan_table() {
212 global $wpdb;
213
214 $charset_collate = $wpdb->get_charset_collate();
215 $table_name = $wpdb->prefix . 'subscrpt_plan';
216
217 $schema = "CREATE TABLE IF NOT EXISTS `{$table_name}` (
218 `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
219 `plan_group_id` BIGINT(20) UNSIGNED NOT NULL,
220 `title` VARCHAR(255) NOT NULL DEFAULT '',
221 `type` TINYINT(2) NOT NULL DEFAULT 2,
222 `billing_frequency` INT(11) NOT NULL DEFAULT 1,
223 `billing_interval` TINYINT(2) NOT NULL DEFAULT 3,
224 `billing_length` INT(11) NOT NULL DEFAULT 0,
225 `signup_fee` LONGTEXT NULL,
226 `free_trial` VARCHAR(50) NOT NULL DEFAULT '',
227 `prepaid` TINYINT(1) NOT NULL DEFAULT 0,
228 `offer` LONGTEXT NULL,
229 `price_mode` VARCHAR(20) NOT NULL DEFAULT 'snapshot',
230 `status` VARCHAR(20) NOT NULL DEFAULT 'active',
231 `data` LONGTEXT NULL,
232 `created_at` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
233 `updated_at` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
234 PRIMARY KEY (`id`),
235 KEY `plan_group_id` (`plan_group_id`),
236 KEY `status` (`status`)
237 ) $charset_collate";
238
239 dbDelta( $schema );
240 }
241
242 /**
243 * Create the subscription plan relation table.
244 *
245 * The many-to-many join between a plan term and a product, carrying the
246 * per-product price in its `data` JSON.
247 *
248 * oid: product id (type 1) or term id (type 2).
249 * vid: variation id; 0 for simple products (free always 0).
250 * type: 1 = product, 2 = taxonomy.
251 * data: JSON price override (regular_price, sale_price, discount_type,
252 * discount_value).
253 * exclude: per-row toggle to hide one term for one product.
254 *
255 * @return void
256 */
257 public function create_plan_relation_table() {
258 global $wpdb;
259
260 $charset_collate = $wpdb->get_charset_collate();
261 $table_name = $wpdb->prefix . 'subscrpt_plan_relation';
262
263 $schema = "CREATE TABLE IF NOT EXISTS `{$table_name}` (
264 `id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
265 `plan_id` BIGINT(20) UNSIGNED NOT NULL,
266 `oid` BIGINT(20) UNSIGNED NOT NULL,
267 `vid` BIGINT(20) UNSIGNED NOT NULL DEFAULT 0,
268 `type` TINYINT(2) NOT NULL DEFAULT 1,
269 `data` LONGTEXT NULL,
270 `exclude` TINYINT(1) NOT NULL DEFAULT 0,
271 `status` VARCHAR(20) NOT NULL DEFAULT 'active',
272 PRIMARY KEY (`id`),
273 KEY `plan_id` (`plan_id`),
274 KEY `plan_lookup` (`plan_id`,`type`,`oid`,`vid`),
275 KEY `product_lookup` (`type`,`oid`,`vid`)
276 ) $charset_collate";
277
278 dbDelta( $schema );
279 }
280
281 /**
282 * Create histories table
283 *
284 * @return void
285 */
286 public function create_histories_table() {
287 global $wpdb;
288
289 $charset_collate = $wpdb->get_charset_collate();
290 $table_name = $wpdb->prefix . 'subscrpt_order_relation';
291
292 $schema = "CREATE TABLE IF NOT EXISTS `{$table_name}` (
293 `id` INT(255) NOT NULL AUTO_INCREMENT,
294 `subscription_id` INT(100) NOT NULL,
295 `order_id` INT(100) NOT NULL,
296 `order_item_id` INT(100) NOT NULL,
297 `type` VARCHAR(50) NOT NULL,
298 PRIMARY KEY (`id`)
299 ) $charset_collate";
300
301 dbDelta( $schema );
302 }
303 }
304