PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.3.2
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.3.2
2.3.2 2.3.1 2.3.0 2.2.2 2.2.1 2.2.0 2.1.2 2.1.1 trunk 0.0.1 0.0.2 0.0.3 0.0.4 0.0.5 0.0.6 0.0.7 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 All 64 releases
better-payment / better-payment.php

better-payment.php in Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More 2.3.2, at better-payment.php

361 lines 13.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Plugin Name: Better Payment
5 * Description: Better Payment allows you to automate payment transactions to manage donations, make payments, sell products, and more on your Elementor and Gutenberg website.
6 * Plugin URI: https://wpdeveloper.com/
7 * Author: WPDeveloper
8 * Version: 2.3.2
9 * Requires at least: 6.0
10 * Requires PHP: 7.4
11 * Author URI: https://wpdeveloper.com/
12 * Text Domain: better-payment
13 * Domain Path: /languages
14 */
15
16 if (!defined('ABSPATH')) {
17 exit;
18 } // Exit if accessed directly
19
20 require_once __DIR__ . '/vendor/autoload.php';
21
22 /**
23 * The plugin main class
24 *
25 * @since 0.0.1
26 */
27 final class Better_Payment {
28
29 use Better_Payment\Lite\Traits\Helper;
30
31 /**
32 * Plugin version
33 *
34 * @var string
35 * @since 0.0.1
36 */
37 const version = '2.3.2';
38
39 /**
40 * Class construcotr
41 *
42 * @since 0.0.1
43 */
44 private function __construct() {
45 $this->define_constants();
46
47 register_activation_hook(__FILE__, [$this, 'activate']);
48
49 add_action('plugins_loaded', [$this, 'init_plugin']);
50 }
51
52 /**
53 * Initialize a singleton instance
54 *
55 * @return \Better_Payment
56 * @since 0.0.1
57 */
58 public static function init() {
59 static $instance = false;
60
61 if (!$instance) {
62 $instance = new self();
63 }
64
65 return $instance;
66 }
67
68 /**
69 * Define the required plugin constants
70 *
71 * @return void
72 * @since 0.0.1
73 */
74 public function define_constants() {
75 define('BETTER_PAYMENT_VERSION', self::version);
76 // Bump this whenever the campaign CPT rewrite rules change (slug, etc.) to
77 // trigger a one-time flush_rewrite_rules() on the next init for existing installs.
78 define('BETTER_PAYMENT_CAMPAIGN_REWRITE_VERSION', '1');
79 define('BETTER_PAYMENT_FILE', __FILE__);
80 define('BETTER_PAYMENT_BASENAME', plugin_basename(__FILE__));
81 define('BETTER_PAYMENT_PATH', __DIR__);
82 define('BETTER_PAYMENT_URL', plugins_url('', BETTER_PAYMENT_FILE));
83 define('BETTER_PAYMENT_ASSETS', BETTER_PAYMENT_URL . '/assets');
84 define('BETTER_PAYMENT_ASSETS_PATH', BETTER_PAYMENT_PATH . '/assets');
85 define('BETTER_PAYMENT_DEV_ASSETS', BETTER_PAYMENT_URL . '/bpbuild');
86 define('BETTER_PAYMENT_DEV_ASSETS_PATH', BETTER_PAYMENT_PATH . '/bpbuild');
87 define('BETTER_PAYMENT_INCLUDES_PATH', BETTER_PAYMENT_PATH . '/includes');
88 define('BETTER_PAYMENT_ADMIN_PATH', BETTER_PAYMENT_INCLUDES_PATH . '/Admin');
89 define('BETTER_PAYMENT_ADMIN_VIEWS_PATH', BETTER_PAYMENT_ADMIN_PATH . '/views');
90 }
91
92 /**
93 * Do stuff upon plugin activation
94 *
95 * @return void
96 * @since 0.0.1
97 */
98 public function activate() {
99 $installer = new Better_Payment\Lite\Installer();
100 $installer->run();
101
102 // Register the campaign CPT and flush rewrite rules so campaign permalinks
103 // (/bp-campaign/{slug}/) resolve immediately, without needing a manual
104 // Settings → Permalinks re-save. Mark the rewrite version so the init-time
105 // self-heal flush (see init_campaign_module) does not run redundantly.
106 ( new Better_Payment\Lite\Campaign\CPT() )->register();
107 flush_rewrite_rules();
108 update_option( 'better_payment_campaign_rewrite_version', BETTER_PAYMENT_CAMPAIGN_REWRITE_VERSION );
109
110 if (get_option('better_payment_plugin_installed_fresh') !== 'yes' && get_option('better_payment_plugin_installed_time_fresh') === false) {
111 update_option('better_payment_plugin_installed_fresh', 'yes');
112
113 $now = time();
114 update_option('better_payment_plugin_installed_time_fresh', $now);
115 update_option('better_payment_progress_bar_dismissed_expiry_date', $now + 7 * DAY_IN_SECONDS);
116 }
117 }
118
119 /**
120 * Initialize the plugin
121 *
122 * @return void
123 * @since 0.0.1
124 */
125 public function init_plugin() {
126 new Better_Payment\Lite\Assets();
127
128 if (defined('DOING_AJAX') && DOING_AJAX) {
129 new Better_Payment\Lite\Ajax();
130 }
131
132 if (is_admin()) {
133 $adminObj = new Better_Payment\Lite\Admin();
134 $adminObj->init();
135
136 if ( !$this->bp_section_dismissed() ) {
137 add_action('save_post', array($this, 'bp_widget_usage_on_save'), 10, 1);
138 }
139 } else {
140 new Better_Payment\Lite\Frontend();
141 }
142
143 /**
144 * Usage tracking must be registered on CRON requests too, not just admin.
145 *
146 * This used to be wired only from Admin::init(), which runs solely under
147 * is_admin(). But WP-Cron executes wp-cron.php as a NON-admin request, so
148 * Plugin_Usage_Tracker::init() never ran there and its do_tracking()
149 * callback was never attached. The daily event was scheduled and fired on
150 * time — into an empty hook. The tracker therefore never sent anything on
151 * its own schedule; the only payloads that ever went out were the forced
152 * ones from the setup wizard's opt-in. Silent, and invisible from the
153 * cron listing, which shows the event as perfectly healthy.
154 *
155 * Not registered on front-end requests: nothing here is needed to render a
156 * page, and this is a payment plugin whose public pages should carry no
157 * avoidable work. Admin + cron is the complete set of contexts the tracker
158 * acts in (notice, action links, AJAX, and the scheduled send).
159 *
160 * @since 2.3.2
161 */
162 if ( is_admin() || wp_doing_cron() ) {
163 add_action( 'init', array( $this, 'start_plugin_tracking' ) );
164 }
165
166 new Better_Payment\Lite\API();
167
168 // Initialize Gutenberg blocks
169 Better_Payment\Lite\Blocks\BlockManager::get_instance();
170 Better_Payment\Lite\Blocks\StyleHandler::init();
171
172 // Initialize Block Actions for payment processing (runs before Elementor Actions)
173 new Better_Payment\Lite\Blocks\BlockActions();
174
175 // Always register PayPal IPN listener + verification poll. These must run even
176 // when Elementor is inactive, because PayPal payments also flow through the
177 // block/campaign path. (Previously registered only inside the Elementor gate
178 // via Classes\Actions, so non-Elementor sites never confirmed PayPal payments.)
179 add_action( 'admin_post_better_payment_paypal_ipn', [ 'Better_Payment\Lite\Classes\Handler', 'handle_paypal_ipn' ] );
180 add_action( 'admin_post_nopriv_better_payment_paypal_ipn', [ 'Better_Payment\Lite\Classes\Handler', 'handle_paypal_ipn' ] );
181 add_action( 'wp_ajax_better_payment_check_paypal_status', [ 'Better_Payment\Lite\Classes\Handler', 'check_paypal_status' ] );
182 add_action( 'wp_ajax_nopriv_better_payment_check_paypal_status', [ 'Better_Payment\Lite\Classes\Handler', 'check_paypal_status' ] );
183
184 if (defined('ELEMENTOR_VERSION')) {
185 new Better_Payment\Lite\Classes\Actions();
186 $el_integration = new Better_Payment\Lite\Admin\Elementor\EL_Integration();
187 $el_integration->init();
188
189 Better_Payment\Lite\Admin\Settings::save_default_settings();
190 }
191
192 // ── Campaign Builder module ────────────────────────────────────
193 $this->init_campaign_module();
194
195 // ── AI module (AI-native Campaign Builder) ─────────────────────
196 $this->init_ai_module();
197
198 // ── WooCommerce gateway module (Better Payment as a WC gateway) ─
199 $this->init_woocommerce_module();
200 }
201
202 /**
203 * Initialize the WooCommerce integration module.
204 *
205 * Registers the "Better Payment (Stripe)" WooCommerce payment gateway,
206 * which consumes the existing Better Payment payment engine (Stripe
207 * checkout creation, transaction persistence, verification, hooks).
208 * No-op when WooCommerce is not active — none of the module's classes
209 * load, and core never depends on WooCommerce.
210 *
211 * @return void
212 */
213 private function init_woocommerce_module() {
214 if ( ! class_exists( 'WooCommerce' ) ) {
215 return;
216 }
217
218 Better_Payment\Lite\WooCommerce\Loader::register();
219 }
220
221 /**
222 * Initialize the AI module (providers, operations, REST endpoints).
223 *
224 * @return void
225 */
226 private function init_ai_module() {
227 // Register providers + resolve settings-driven config.
228 ( new Better_Payment\Lite\AI\AIManager() )->init();
229
230 // REST API for AI (chat/generate/analyze/image/conversations/config).
231 new Better_Payment\Lite\API\AIAPI();
232 }
233
234 /**
235 * Initialize the Campaign Builder module.
236 *
237 * @return void
238 */
239 private function init_campaign_module() {
240 $cpt = new Better_Payment\Lite\Campaign\CPT();
241
242 // CPT registration (runs on init)
243 add_action( 'init', [ $cpt, 'register' ] );
244
245 // Self-heal rewrite rules for installs that updated into this version
246 // (the activation hook does NOT re-run on plugin update). Runs after the
247 // CPT is registered (priority 11 > default 10) so the new rule is present
248 // when we flush, then records the version so it flushes only once.
249 add_action( 'init', static function () {
250 if ( get_option( 'better_payment_campaign_rewrite_version' ) !== BETTER_PAYMENT_CAMPAIGN_REWRITE_VERSION ) {
251 flush_rewrite_rules();
252 update_option( 'better_payment_campaign_rewrite_version', BETTER_PAYMENT_CAMPAIGN_REWRITE_VERSION );
253 }
254 }, 11 );
255
256 // Admin-only: builder page, submenu, asset enqueue
257 if ( is_admin() ) {
258 add_action( 'admin_menu', [ $cpt, 'register_builder_page' ], 20 );
259 add_action( 'admin_enqueue_scripts', [ $cpt, 'enqueue_builder_assets' ] );
260 add_action( 'admin_enqueue_scripts', [ $cpt, 'enqueue_list_assets' ] );
261 add_action( 'load-post-new.php', [ $cpt, 'redirect_new_post' ] );
262 add_action( 'load-post.php', [ $cpt, 'redirect_edit_post' ] );
263 add_filter( 'get_edit_post_link', [ $cpt, 'filter_edit_link' ], 10, 3 );
264 add_action( 'admin_init', [ $cpt, 'redirect_cpt_list' ] );
265
266 // Save post meta when post is saved via standard WP (rare path)
267 add_action( 'save_post_bp_campaign', [ new Better_Payment\Lite\Campaign\MetaBox(), 'save' ] );
268
269 // Custom columns on campaign list table
270 $admin_list = new Better_Payment\Lite\Campaign\CampaignListColumns();
271 add_filter( 'manage_bp_campaign_posts_columns', [ $admin_list, 'add_columns' ] );
272 add_action( 'manage_bp_campaign_posts_custom_column', [ $admin_list, 'render_column' ], 10, 2 );
273 }
274
275 // Serve a custom template for bp_campaign single pages so RendererService renders
276 // the campaign content instead of the theme's empty single.php.
277 add_filter( 'template_include', static function ( $template ) {
278 if ( is_singular( 'bp_campaign' ) ) {
279 $custom = BETTER_PAYMENT_PATH . '/templates/single-bp_campaign.php';
280 return file_exists( $custom ) ? $custom : $template;
281 }
282 return $template;
283 } );
284
285 // Register element types and templates (must run before CPT enqueue_builder_assets).
286 // Deferred to init so __() calls don't trigger translation loading during plugins_loaded.
287 add_action( 'init', [ 'Better_Payment\Lite\Campaign\Elements\CampaignElements', 'register_all' ], 5 );
288
289 // Campaign display block (server-side render)
290 $block = new Better_Payment\Lite\Campaign\CampaignBlock();
291 add_action( 'init', [ $block, 'register' ], 20 );
292
293 // Shortcode [bp_campaign id="42"]
294 $shortcode = new Better_Payment\Lite\Campaign\Shortcode();
295 $shortcode->register();
296
297 // REST API for campaigns
298 new Better_Payment\Lite\API\CampaignAPI();
299
300 // Bust campaign stats cache when a payment is confirmed by any gateway.
301 Better_Payment\Lite\Campaign\CampaignStats::register_hooks();
302 }
303 }
304
305 /**
306 * Initializes the main plugin
307 *
308 * @return \Better_Payment
309 * @since 0.0.1
310 */
311
312 Better_Payment::init();
313
314 /**
315 * Plugin migrator
316 *
317 * @since 0.0.2
318 */
319 function better_payment_migrator() {
320 Better_Payment\Lite\Classes\Migrator::migrator();
321 }
322
323
324 /**
325 * On wp load
326 *
327 * @return void
328 * @since 0.0.1
329 */
330 add_action('wp_loaded', function () {
331 if (get_option('better_payment_version') != BETTER_PAYMENT_VERSION) {
332 better_payment_migrator();
333 update_option('better_payment_version', BETTER_PAYMENT_VERSION);
334 }
335
336 $setup_wizard = get_option('better_payment_setup_wizard');
337
338 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
339 $is_from_better_payment = (isset( $_POST['form_data'] ) && isset( $_POST['form_data'][0] ) && isset( $_POST['form_data'][0]['name'] ) && strpos( $_POST['form_data'][0]['name'], 'better_payment_' ) !== false) || (isset( $_POST['is_tracking'] ) && $_POST['is_tracking'] === 'true') || (isset( $_POST['action'] ) && $_POST['action'] === 'save_setup_wizard_data');
340
341 if ( ! $is_from_better_payment ) {
342 return;
343 }
344 }
345
346 if ($setup_wizard == 'redirect') {
347 Better_Payment\Lite\Admin\Setup_Wizard::redirect();
348 }
349
350 if ($setup_wizard == 'init') {
351 new Better_Payment\Lite\Admin\Setup_Wizard();
352 }
353 });
354
355 /**
356 * Dispatch actions
357 *
358 * @since 0.0.1
359 */
360 \Better_Payment\Lite\Admin::dispatch_actions();
361