PluginProbe
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More / 2.4.0
Better Payment – Instant Payments, Donations, Fundraising with Subscriptions & More v2.4.0
2.4.1 2.4.0 2.3.4 2.3.3 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 All 68 releases
better-payment / better-payment.php

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

360 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.4.0
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.4.0';
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 (is_admin()) {
129 $adminObj = new Better_Payment\Lite\Admin();
130 $adminObj->init();
131
132 // Warn when the installed Pro predates what this Lite supports.
133 Better_Payment\Lite\Classes\ProCompatibility::register();
134
135 if ( !$this->bp_section_dismissed() ) {
136 add_action('save_post', array($this, 'bp_widget_usage_on_save'), 10, 1);
137 }
138 } else {
139 new Better_Payment\Lite\Frontend();
140 }
141
142 /**
143 * Usage tracking must be registered on CRON requests too, not just admin.
144 *
145 * This used to be wired only from Admin::init(), which runs solely under
146 * is_admin(). But WP-Cron executes wp-cron.php as a NON-admin request, so
147 * Plugin_Usage_Tracker::init() never ran there and its do_tracking()
148 * callback was never attached. The daily event was scheduled and fired on
149 * time — into an empty hook. The tracker therefore never sent anything on
150 * its own schedule; the only payloads that ever went out were the forced
151 * ones from the setup wizard's opt-in. Silent, and invisible from the
152 * cron listing, which shows the event as perfectly healthy.
153 *
154 * Not registered on front-end requests: nothing here is needed to render a
155 * page, and this is a payment plugin whose public pages should carry no
156 * avoidable work. Admin + cron is the complete set of contexts the tracker
157 * acts in (notice, action links, AJAX, and the scheduled send).
158 *
159 * @since 2.3.2
160 */
161 if ( is_admin() || wp_doing_cron() ) {
162 add_action( 'init', array( $this, 'start_plugin_tracking' ) );
163 }
164
165 new Better_Payment\Lite\API();
166
167 // Initialize Gutenberg blocks
168 Better_Payment\Lite\Blocks\BlockManager::get_instance();
169 Better_Payment\Lite\Blocks\StyleHandler::init();
170
171 // Initialize Block Actions for payment processing (runs before Elementor Actions)
172 new Better_Payment\Lite\Blocks\BlockActions();
173
174 // Always register PayPal IPN listener + verification poll. These must run even
175 // when Elementor is inactive, because PayPal payments also flow through the
176 // block/campaign path. (Previously registered only inside the Elementor gate
177 // via Classes\Actions, so non-Elementor sites never confirmed PayPal payments.)
178 add_action( 'admin_post_better_payment_paypal_ipn', [ 'Better_Payment\Lite\Classes\Handler', 'handle_paypal_ipn' ] );
179 add_action( 'admin_post_nopriv_better_payment_paypal_ipn', [ 'Better_Payment\Lite\Classes\Handler', 'handle_paypal_ipn' ] );
180 add_action( 'wp_ajax_better_payment_check_paypal_status', [ 'Better_Payment\Lite\Classes\Handler', 'check_paypal_status' ] );
181 add_action( 'wp_ajax_nopriv_better_payment_check_paypal_status', [ 'Better_Payment\Lite\Classes\Handler', 'check_paypal_status' ] );
182
183 if (defined('ELEMENTOR_VERSION')) {
184 new Better_Payment\Lite\Classes\Actions();
185 $el_integration = new Better_Payment\Lite\Admin\Elementor\EL_Integration();
186 $el_integration->init();
187
188 Better_Payment\Lite\Admin\Settings::save_default_settings();
189 }
190
191 // ── Campaign Builder module ────────────────────────────────────
192 $this->init_campaign_module();
193
194 // ── AI module (AI-native Campaign Builder) ─────────────────────
195 $this->init_ai_module();
196
197 // ── WooCommerce gateway module (Better Payment as a WC gateway) ─
198 $this->init_woocommerce_module();
199 }
200
201 /**
202 * Initialize the WooCommerce integration module.
203 *
204 * Registers the "Better Payment (Stripe)" WooCommerce payment gateway,
205 * which consumes the existing Better Payment payment engine (Stripe
206 * checkout creation, transaction persistence, verification, hooks).
207 * No-op when WooCommerce is not active — none of the module's classes
208 * load, and core never depends on WooCommerce.
209 *
210 * @return void
211 */
212 private function init_woocommerce_module() {
213 if ( ! class_exists( 'WooCommerce' ) ) {
214 return;
215 }
216
217 Better_Payment\Lite\WooCommerce\Loader::register();
218 }
219
220 /**
221 * Initialize the AI module (providers, operations, REST endpoints).
222 *
223 * @return void
224 */
225 private function init_ai_module() {
226 // Register providers + resolve settings-driven config.
227 ( new Better_Payment\Lite\AI\AIManager() )->init();
228
229 // REST API for AI (chat/generate/analyze/image/conversations/config).
230 new Better_Payment\Lite\API\AIAPI();
231 }
232
233 /**
234 * Initialize the Campaign Builder module.
235 *
236 * @return void
237 */
238 private function init_campaign_module() {
239 $cpt = new Better_Payment\Lite\Campaign\CPT();
240
241 // CPT registration (runs on init)
242 add_action( 'init', [ $cpt, 'register' ] );
243
244 // Self-heal rewrite rules for installs that updated into this version
245 // (the activation hook does NOT re-run on plugin update). Runs after the
246 // CPT is registered (priority 11 > default 10) so the new rule is present
247 // when we flush, then records the version so it flushes only once.
248 add_action( 'init', static function () {
249 if ( get_option( 'better_payment_campaign_rewrite_version' ) !== BETTER_PAYMENT_CAMPAIGN_REWRITE_VERSION ) {
250 flush_rewrite_rules();
251 update_option( 'better_payment_campaign_rewrite_version', BETTER_PAYMENT_CAMPAIGN_REWRITE_VERSION );
252 }
253 }, 11 );
254
255 // Admin-only: builder page, submenu, asset enqueue
256 if ( is_admin() ) {
257 add_action( 'admin_menu', [ $cpt, 'register_builder_page' ], 20 );
258 add_action( 'admin_enqueue_scripts', [ $cpt, 'enqueue_builder_assets' ] );
259 add_action( 'admin_enqueue_scripts', [ $cpt, 'enqueue_list_assets' ] );
260 add_action( 'load-post-new.php', [ $cpt, 'redirect_new_post' ] );
261 add_action( 'load-post.php', [ $cpt, 'redirect_edit_post' ] );
262 add_filter( 'get_edit_post_link', [ $cpt, 'filter_edit_link' ], 10, 3 );
263 add_action( 'admin_init', [ $cpt, 'redirect_cpt_list' ] );
264
265 // Save post meta when post is saved via standard WP (rare path)
266 add_action( 'save_post_bp_campaign', [ new Better_Payment\Lite\Campaign\MetaBox(), 'save' ] );
267
268 // Custom columns on campaign list table
269 $admin_list = new Better_Payment\Lite\Campaign\CampaignListColumns();
270 add_filter( 'manage_bp_campaign_posts_columns', [ $admin_list, 'add_columns' ] );
271 add_action( 'manage_bp_campaign_posts_custom_column', [ $admin_list, 'render_column' ], 10, 2 );
272 }
273
274 // Serve a custom template for bp_campaign single pages so RendererService renders
275 // the campaign content instead of the theme's empty single.php.
276 add_filter( 'template_include', static function ( $template ) {
277 if ( is_singular( 'bp_campaign' ) ) {
278 $custom = BETTER_PAYMENT_PATH . '/templates/single-bp_campaign.php';
279 return file_exists( $custom ) ? $custom : $template;
280 }
281 return $template;
282 } );
283
284 // Register element types and templates (must run before CPT enqueue_builder_assets).
285 // Deferred to init so __() calls don't trigger translation loading during plugins_loaded.
286 add_action( 'init', [ 'Better_Payment\Lite\Campaign\Elements\CampaignElements', 'register_all' ], 5 );
287
288 // Campaign display block (server-side render)
289 $block = new Better_Payment\Lite\Campaign\CampaignBlock();
290 add_action( 'init', [ $block, 'register' ], 20 );
291
292 // Shortcode [bp_campaign id="42"]
293 $shortcode = new Better_Payment\Lite\Campaign\Shortcode();
294 $shortcode->register();
295
296 // REST API for campaigns
297 new Better_Payment\Lite\API\CampaignAPI();
298
299 // Bust campaign stats cache when a payment is confirmed by any gateway.
300 Better_Payment\Lite\Campaign\CampaignStats::register_hooks();
301 }
302 }
303
304 /**
305 * Initializes the main plugin
306 *
307 * @return \Better_Payment
308 * @since 0.0.1
309 */
310
311 Better_Payment::init();
312
313 /**
314 * Plugin migrator
315 *
316 * @since 0.0.2
317 */
318 function better_payment_migrator() {
319 Better_Payment\Lite\Classes\Migrator::migrator();
320 }
321
322
323 /**
324 * On wp load
325 *
326 * @return void
327 * @since 0.0.1
328 */
329 add_action('wp_loaded', function () {
330 if (get_option('better_payment_version') != BETTER_PAYMENT_VERSION) {
331 better_payment_migrator();
332 update_option('better_payment_version', BETTER_PAYMENT_VERSION);
333 }
334
335 $setup_wizard = get_option('better_payment_setup_wizard');
336
337 if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
338 $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');
339
340 if ( ! $is_from_better_payment ) {
341 return;
342 }
343 }
344
345 if ($setup_wizard == 'redirect') {
346 Better_Payment\Lite\Admin\Setup_Wizard::redirect();
347 }
348
349 if ($setup_wizard == 'init') {
350 new Better_Payment\Lite\Admin\Setup_Wizard();
351 }
352 });
353
354 /**
355 * Dispatch actions
356 *
357 * @since 0.0.1
358 */
359 \Better_Payment\Lite\Admin::dispatch_actions();
360