PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.7.0
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.7.0
1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 1.8.0 All 210 releases
charitable / charitable.php

charitable.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.7.0, at charitable.php

1,248 lines 34.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Charitable
4 * Plugin URI: https://www.wpcharitable.com
5 * Description: The WordPress fundraising alternative for non-profits, created to help non-profits raise money on their own website.
6 * Version: 1.7.0
7 * Author: Charitable Donations & Fundraising Team
8 * Author URI: https://wpcharitable.com
9 * Requires at least: 4.1
10 * Tested up to: 6.0.2
11 * Stable tag: 1.7.0
12 *
13 * Text Domain: charitable
14 * Domain Path: /i18n/languages/
15 *
16 * @package Charitable
17 * @author David Bisset
18 * @copyright Copyright (c) 2022, WP Charitable LLC
19 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
20 */
21
22 // Exit if accessed directly.
23 if ( ! defined( 'ABSPATH' ) ) {
24 exit;
25 }
26
27 if ( ! class_exists( 'Charitable' ) ) :
28
29 /**
30 * Main Charitable class.
31 */
32 class Charitable {
33
34 /** The product name. */
35 const NAME = 'Charitable';
36
37 /** The plugin author name. */
38 const AUTHOR = 'WP Charitable';
39
40 /* Plugin version. */
41 const VERSION = '1.7.0';
42
43 /* Version of database schema. */
44 const DB_VERSION = '20180522';
45
46 /* Campaign post type. */
47 const CAMPAIGN_POST_TYPE = 'campaign';
48
49 /* Donation post type. */
50 const DONATION_POST_TYPE = 'donation';
51
52 /**
53 * Single instance of this class.
54 *
55 * @since 1.0.0
56 *
57 * @var Charitable
58 */
59 private static $instance = null;
60
61 /**
62 * The absolute path to this plugin's directory.
63 *
64 * @since 1.0.0
65 *
66 * @var string
67 */
68 private $directory_path;
69
70 /**
71 * The URL of this plugin's directory.
72 *
73 * @since 1.0.0
74 *
75 * @var string
76 */
77 private $directory_url;
78
79 /**
80 * Directory path for the includes folder of the plugin.
81 *
82 * @since 1.0.0
83 *
84 * @var string
85 */
86 private $includes_path;
87
88 /**
89 * Store of registered objects.
90 *
91 * @since 1.0.0
92 * @since 1.5.0 Changed to Charitable_Registry object. Previously it was an array.
93 *
94 * @var Charitable_Registry
95 */
96 private $registry;
97
98 /**
99 * Classmap.
100 *
101 * @since 1.5.0
102 *
103 * @var array
104 */
105 private $classmap;
106
107 /**
108 * Create class instance.
109 *
110 * @since 1.0.0
111 */
112 public function __construct() {
113 $this->directory_path = plugin_dir_path( __FILE__ );
114 $this->directory_url = plugin_dir_url( __FILE__ );
115 $this->includes_path = $this->directory_path . 'includes/';
116
117 define( "CHARTIABLE_DIRECTORY_PATH", plugin_dir_path( __FILE__ ) );
118 define( "CHARTIABLE_PLUGIN_BASENAME", plugin_basename( __FILE__ ) );
119 define( "CHARTIABLE_MARKETING_URL", 'https://wpcharitable.com/' );
120
121 spl_autoload_register( array( $this, 'autoloader' ) );
122
123 $this->load_dependencies();
124
125 register_activation_hook( __FILE__, array( $this, 'activate' ) );
126 register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );
127
128 add_filter( 'plugin_action_links_' . CHARTIABLE_PLUGIN_BASENAME, array( $this, 'plugin_action_links' ), 99, 2 );
129 add_action( 'plugins_loaded', array( $this, 'start' ), 3 );
130
131 add_action( 'plugins_loaded', array( $this, 'check_for_version_conflicts' ), 2 );
132 }
133
134 /**
135 * Returns the original instance of this class.
136 *
137 * @since 1.0.0
138 *
139 * @return Charitable
140 */
141 public static function get_instance() {
142 return self::$instance;
143 }
144
145 /**
146 * Run the startup sequence.
147 *
148 * This is only ever executed once.
149 *
150 * @since 1.0.0
151 *
152 * @return void
153 */
154 public function start() {
155 /* If we've already started (i.e. run this function once before), do not pass go. */
156 if ( $this->started() ) {
157 return;
158 }
159
160 /* Set static instance. */
161 self::$instance = $this;
162
163 /* Set up the registry and instantiate objects we need straight away. */
164 $this->registry();
165
166 $this->setup_licensing();
167
168 $this->maybe_start_ajax();
169
170 $this->attach_hooks_and_filters();
171
172 $this->maybe_start_admin();
173
174 $this->maybe_start_public();
175
176 Charitable_Addons::load( $this );
177 }
178
179 /**
180 * Include necessary files.
181 *
182 * @since 1.0.0
183 *
184 * @return void
185 */
186 private function load_dependencies() {
187 $includes_path = $this->get_path( 'includes' );
188
189 /* Load files with hooks & functions. Classes are autoloaded. */
190 require_once( $includes_path . 'charitable-core-functions.php' );
191 require_once( $includes_path . 'api/charitable-api-functions.php' );
192 require_once( $includes_path . 'campaigns/charitable-campaign-functions.php' );
193 require_once( $includes_path . 'campaigns/charitable-campaign-hooks.php' );
194 require_once( $includes_path . 'compat/charitable-compat-functions.php' );
195 require_once( $includes_path . 'currency/charitable-currency-functions.php' );
196 require_once( $includes_path . 'deprecated/charitable-deprecated-functions.php' );
197 require_once( $includes_path . 'donations/charitable-donation-hooks.php' );
198 require_once( $includes_path . 'donations/charitable-donation-functions.php' );
199 require_once( $includes_path . 'emails/charitable-email-hooks.php' );
200 require_once( $includes_path . 'endpoints/charitable-endpoints-functions.php' );
201 require_once( $includes_path . 'privacy/charitable-privacy-functions.php' );
202 require_once( $includes_path . 'public/charitable-template-helpers.php' );
203 require_once( $includes_path . 'shortcodes/charitable-shortcodes-hooks.php' );
204 require_once( $includes_path . 'upgrades/charitable-upgrade-hooks.php' );
205 require_once( $includes_path . 'users/charitable-user-functions.php' );
206 require_once( $includes_path . 'user-management/charitable-user-management-hooks.php' );
207 require_once( $includes_path . 'utilities/charitable-utility-functions.php' );
208
209 If ( $this->load_core_stripe() ) :
210
211 /* Load Stripe SDK */
212 require_once( $this->get_path( 'directory' ) . 'vendor/autoload.php' );
213
214 /* Interfaces */
215 require_once( $includes_path . 'stripe/interfaces/interface-charitable-stripe-gateway-processor.php' );
216
217 /* Abstract classes */
218 require_once( $includes_path . 'stripe/abstracts/class-charitable-stripe-gateway-processor.php' );
219
220 /* Classes */
221 require_once( $includes_path . 'stripe/donations/class-charitable-stripe-donation-log.php' );
222 require_once( $includes_path . 'stripe/donations/class-charitable-stripe-recurring-donation-log.php' );
223 require_once( $includes_path . 'stripe/i18n/class-charitable-stripe-i18n.php' );
224 require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-connected-customer.php' );
225 require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-customer.php' );
226 require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-gateway-processor-payment-intents.php' );
227 require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-payment-intent.php' );
228
229 /* Functions & Hooks */
230 require_once( $includes_path . 'stripe/charitable-stripe-core-functions.php' );
231 require_once( $includes_path . 'stripe/donations/charitable-stripe-donation-functions.php' );
232 require_once( $includes_path . 'stripe/gateway/charitable-stripe-gateway-hooks.php' );
233
234 /* webhooks */
235 require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-webhook-api.php' );
236 require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-webhook-processor.php' );
237
238 endif;
239
240 }
241
242 /**
243 * Load the template functions after theme is loaded.
244 *
245 * This gives themes time to override the functions.
246 *
247 * @since 1.6.10
248 *
249 * @return void
250 */
251 public function load_template_files() {
252 $includes_path = $this->get_path( 'includes' );
253
254 require_once( $includes_path . 'public/charitable-template-functions.php' );
255 require_once( $includes_path . 'public/charitable-template-hooks.php' );
256 }
257
258 /**
259 * Dynamically loads the class attempting to be instantiated elsewhere in the
260 * plugin by looking at the $class_name parameter being passed as an argument.
261 *
262 * @since 1.5.0
263 *
264 * @param string $class_name The fully-qualified name of the class to load.
265 * @return boolean
266 */
267 public function autoloader( $class_name ) {
268 /* If the specified $class_name already exists, bail. */
269 if ( class_exists( $class_name ) ) {
270 return false;
271 }
272
273 /* If the specified $class_name does not include our namespace, duck out. */
274 if ( false === strpos( $class_name, 'Charitable_' ) ) {
275 return false;
276 }
277
278 /* Autogenerated class map. */
279 if ( ! isset( $this->classmap ) ) {
280 $this->classmap = include( 'includes/autoloader/charitable-class-map.php' );
281
282 $this->classmap[ 'Charitable_Gateway_Stripe_AM' ] = 'gateways/class-charitable-gateway-stripe-am.php';
283 $this->classmap[ 'Charitable_Gateway_Stripe' ] = 'gateways/class-charitable-gateway-stripe-am.php';
284 }
285
286 $file_path = isset( $this->classmap[ $class_name ] ) ? $this->get_path( 'includes' ) . $this->classmap[ $class_name ] : false;
287
288 if ( false !== $file_path && file_exists( $file_path ) && is_file( $file_path ) ) {
289 require_once( $file_path );
290 return true;
291 }
292
293 return false;
294 }
295
296 /**
297 * Returns a registered class object.
298 *
299 * @since 1.5.0
300 *
301 * @return Charitable_Registry
302 */
303 public function registry() {
304 if ( ! isset( $this->registry ) ) {
305 $this->registry = new Charitable_Registry();
306 $this->registry->register_object( Charitable_Emails::get_instance() );
307 $this->registry->register_object( Charitable_Request::get_instance() );
308 $this->registry->register_object( Charitable_Gateways::get_instance() );
309 $this->registry->register_object( Charitable_i18n::get_instance() );
310 $this->registry->register_object( Charitable_Post_Types::get_instance() );
311 $this->registry->register_object( Charitable_Cron::get_instance() );
312 $this->registry->register_object( Charitable_Widgets::get_instance() );
313 $this->registry->register_object( Charitable_Licenses::get_instance() );
314 $this->registry->register_object( Charitable_User_Dashboard::get_instance() );
315 $this->registry->register_object( Charitable_Locations::get_instance() );
316 $this->registry->register_object( Charitable_Currency::get_instance() );
317
318 $this->registry->register_object( new Charitable_Privacy );
319 $this->registry->register_object( new Charitable_Debugging );
320 $this->registry->register_object( new Charitable_Locale );
321 }
322
323 return $this->registry;
324 }
325
326 /**
327 * Set up hook and filter callback functions.
328 *
329 * @since 1.0.0
330 *
331 * @return void
332 */
333 private function attach_hooks_and_filters() {
334 add_action( 'wpmu_new_blog', array( $this, 'maybe_activate_charitable_on_new_site' ) );
335 add_action( 'plugins_loaded', array( $this, 'charitable_install' ), 100 );
336 add_action( 'plugins_loaded', array( $this, 'charitable_start' ), 100 );
337 add_action( 'plugins_loaded', array( $this, 'endpoints' ), 100 );
338 add_action( 'plugins_loaded', array( $this, 'donation_fields' ), 100 );
339 add_action( 'plugins_loaded', array( $this, 'campaign_fields' ), 100 );
340 add_action( 'plugins_loaded', array( $this, 'register_donormeta_table' ) );
341 add_action( 'plugins_loaded', 'charitable_load_compat_functions' );
342 add_action( 'setup_theme', array( 'Charitable_Customizer', 'start' ) );
343 add_action( 'after_setup_theme', array( $this, 'load_template_files' ) );
344 add_action( 'wp_enqueue_scripts', array( $this, 'maybe_start_qunit' ), 100 );
345 add_action( 'rest_api_init', 'charitable_register_api_routes' );
346
347 /**
348 * We do this on priority 20 so that any functionality that is loaded on init (such
349 * as addons) has a chance to run before the event.
350 */
351 add_action( 'init', array( $this, 'do_charitable_actions' ), 20 );
352
353 If ( $this->load_core_stripe() ) :
354
355 /**
356 * Set up scripts & stylesheets & enqueue them when appropriate.
357 */
358 // add_action( 'wp_enqueue_scripts', array( $this, 'setup_stripe_scripts' ), 11 );
359 add_action( 'charitable_form_after_fields', array( $this, 'maybe_setup_stripe_scripts_in_donation_form' ) );
360 add_action( 'charitable_campaign_loop_after', array( $this, 'maybe_setup_stripe_scripts_in_campaign_loop' ) );
361
362 endif;
363
364 }
365
366
367 /**
368 * Load Stripe JS, as well as our handling scripts.
369 *
370 * @since 1.4.0
371 *
372 * @return boolean
373 */
374 public function enqueue_stripe_scripts() {
375 if ( ! Charitable_Gateways::get_instance()->is_active_gateway( Charitable_Gateway_Stripe_AM::get_gateway_id() ) ) {
376 return false;
377 }
378
379 wp_enqueue_script( 'charitable-stripe' );
380
381 return true;
382 }
383
384 /**
385 * Load Stripe JS or Stripe Checkout, as well as our handling script.
386 *
387 * @uses Charitable_Stripe::enqueue_scripts()
388 *
389 * @since 1.4.0
390 *
391 * @param Charitable_Donation_Form $form The current form object.
392 * @return boolean
393 */
394 public function maybe_setup_stripe_scripts_in_donation_form( $form ) {
395 if ( ! is_a( $form, 'Charitable_Donation_Form' ) ) {
396 return false;
397 }
398
399 if ( 'make_donation' !== $form->get_form_action() ) {
400 return false;
401 }
402
403 return $this->enqueue_stripe_scripts();
404 }
405
406 /**
407 * Enqueue the Stripe JS/Checkout scripts after a campaign loop if modal donations are in use.
408 *
409 * @uses Charitable_Stripe::enqueue_scripts()
410 *
411 * @since 1.4.0
412 *
413 * @return boolean
414 */
415 public function maybe_setup_stripe_scripts_in_campaign_loop() {
416 if ( 'modal' !== charitable_get_option( 'donation_form_display', 'separate_page' ) ) {
417 return false;
418 }
419
420 return $this->enqueue_stripe_scripts();
421 }
422
423 /**
424 * Checks whether we're in the admin area and if so, loads the admin-only functionality.
425 *
426 * @since 1.0.0
427 *
428 * @return Charitable_Admin|false
429 */
430 private function maybe_start_admin() {
431 if ( ! is_admin() ) {
432 return false;
433 }
434
435 require_once( $this->get_path( 'admin' ) . 'class-charitable-admin.php' );
436 require_once( $this->get_path( 'admin' ) . 'charitable-admin-hooks.php' );
437
438 $admin = Charitable_Admin::get_instance();
439
440 $this->registry->register_object( $admin );
441
442 // Stripe
443
444 require_once( $this->get_path( 'includes' ) . 'stripe/admin/class-charitable-stripe-admin.php' );
445
446 new Charitable_Stripe_Admin;
447
448 return $admin;
449 }
450
451 /**
452 * Checks whether we're on the public-facing side and if so, loads the public-facing functionality.
453 *
454 * @since 1.0.0
455 *
456 * @return Charitable_Public|false
457 */
458 private function maybe_start_public() {
459 if ( is_admin() && ! $this->is_ajax() ) {
460 return false;
461 }
462
463 require_once( $this->get_path( 'public' ) . 'class-charitable-public.php' );
464
465 $public = Charitable_Public::get_instance();
466
467 $this->registry->register_object( $public );
468
469 return $public;
470 }
471
472 /**
473 * Load the QUnit tests if ?qunit is appended to the request.
474 *
475 * @since 1.4.17
476 *
477 * @return boolean
478 */
479 public function maybe_start_qunit() {
480 /* Skip out early if ?qunit isn't included in the request. */
481 if ( ! array_key_exists( 'qunit', $_GET ) ) {
482 return false;
483 }
484
485 /* The unit tests have to exist. */
486 if ( ! file_exists( $this->get_path( 'directory' ) . 'tests/qunit/tests.js' ) ) {
487 return false;
488 }
489
490 wp_register_script( 'qunit', 'https://code.jquery.com/qunit/qunit-2.3.3.js', array(), '2.3.3', true );
491
492 /* Version: '20170615-15:44' */
493 wp_register_script( 'qunit-tests', $this->get_path( 'directory', false ) . 'tests/qunit/tests.js', array( 'jquery', 'qunit' ), time(), true );
494 wp_enqueue_script( 'qunit-tests' );
495
496 wp_register_style( 'qunit', 'https://code.jquery.com/qunit/qunit-2.3.3.css', array(), '2.3.3', 'all' );
497 wp_enqueue_style( 'qunit' );
498 }
499
500 /**
501 * Checks whether the current request is an AJAX request.
502 *
503 * @since 1.5.0
504 *
505 * @return boolean
506 */
507 private function is_ajax() {
508 return false !== ( defined( 'DOING_AJAX' ) && DOING_AJAX );
509 }
510
511 /**
512 * Checks whether we're executing an AJAX hook and if so, loads some AJAX functionality.
513 *
514 * @since 1.0.0
515 *
516 * @return void
517 */
518 private function maybe_start_ajax() {
519 if ( ! $this->is_ajax() ) {
520 return;
521 }
522
523 require_once( $this->get_path( 'includes' ) . 'ajax/charitable-ajax-functions.php' );
524 require_once( $this->get_path( 'includes' ) . 'ajax/charitable-ajax-hooks.php' );
525 }
526
527 /**
528 * This method is fired after all plugins are loaded and simply fires the charitable_start hook.
529 *
530 * Extensions can use the charitable_start event to load their own functionality.
531 *
532 * @since 1.0.0
533 *
534 * @return void
535 */
536 public function charitable_start() {
537 do_action( 'charitable_start', $this );
538 }
539
540 /**
541 * Fires off an action right after Charitable is installed, allowing other
542 * plugins/themes to do something at this point.
543 *
544 * @since 1.0.1
545 *
546 * @return void
547 */
548 public function charitable_install() {
549 $install = get_transient( 'charitable_install' );
550
551 if ( ! $install ) {
552 return;
553 }
554
555 require_once( $this->get_path( 'includes' ) . 'plugin/class-charitable-install.php' );
556
557 Charitable_Install::finish_installing();
558
559 do_action( 'charitable_install' );
560
561 delete_transient( 'charitable_install' );
562 }
563
564 /**
565 * Returns whether we are currently in the start phase of the plugin.
566 *
567 * @since 1.0.0
568 *
569 * @return boolean
570 */
571 public function is_start() {
572 return current_filter() == 'charitable_start';
573 }
574
575 /**
576 * Returns whether the plugin has already started.
577 *
578 * @since 1.0.0
579 *
580 * @return boolean
581 */
582 public function started() {
583 return did_action( 'charitable_start' ) || current_filter() == 'charitable_start';
584 }
585
586 /**
587 * Returns whether the plugin is being activated.
588 *
589 * @since 1.0.0
590 *
591 * @return boolean
592 */
593 public function is_activation() {
594 return current_filter() == 'activate_charitable/charitable.php';
595 }
596
597 /**
598 * Returns whether the plugin is being deactivated.
599 *
600 * @since 1.0.0
601 *
602 * @return boolean
603 */
604 public function is_deactivation() {
605 return current_filter() == 'deactivate_charitable/charitable.php';
606 }
607
608 /**
609 * Returns plugin paths.
610 *
611 * @since 1.0.0
612 *
613 * @param string $type If empty, returns the path to the plugin.
614 * @param boolean $absolute_path If true, returns the file system path. If false, returns it as a URL.
615 * @return string
616 */
617 public function get_path( $type = '', $absolute_path = true ) {
618 $base = $absolute_path ? $this->directory_path : $this->directory_url;
619
620 switch ( $type ) {
621 case 'includes':
622 $path = $base . 'includes/';
623 break;
624
625 case 'admin':
626 $path = $base . 'includes/admin/';
627 break;
628
629 case 'public':
630 $path = $base . 'includes/public/';
631 break;
632
633 case 'assets':
634 $path = $base . 'assets/';
635 break;
636
637 case 'templates':
638 $path = $base . 'templates/';
639 break;
640
641 case 'directory':
642 $path = $base;
643 break;
644
645 default:
646 $path = __FILE__;
647
648 }//end switch
649
650 return $path;
651 }
652
653 /**
654 * Returns the plugin's version number.
655 *
656 * @since 1.0.0
657 *
658 * @return string
659 */
660 public function get_version() {
661 $version = self::VERSION;
662
663 if ( false !== strpos( $version, '-' ) ) {
664 $parts = explode( '-', $version );
665 $version = $parts[0];
666 }
667
668 return $version;
669 }
670
671 /**
672 * Get the campaign fields registry
673 *
674 * If the registry has not been set up yet, this will also
675 * perform the task of setting it up initially.
676 *
677 * This method is called on the plugins_loaded hook.
678 *
679 * @since 1.6.0
680 *
681 * @return Charitable_Campaign_Field_Registry
682 */
683 public function campaign_fields() {
684 if ( ! $this->registry->has( 'campaign_field_registry' ) ) {
685 $campaign_fields = new Charitable_Campaign_Field_Registry();
686
687 /* Register it immediately to avoid endless recursion. */
688 $this->registry->register_object( $campaign_fields );
689
690 $fields = include( $this->get_path( 'includes' ) . 'fields/default-fields/campaign-fields.php' );
691
692 foreach ( $fields as $key => $args ) {
693 $campaign_fields->register_field( new Charitable_Campaign_Field( $key, $args ) );
694 }
695 }
696
697 return $this->registry->get( 'campaign_field_registry' );
698 }
699
700 /**
701 * Get the donation fields registry
702 *
703 * If the registry has not been set up yet, this will also
704 * perform the task of setting it up initially.
705 *
706 * This method is called on the plugins_loaded hook.
707 *
708 * @since 1.5.0
709 *
710 * @return Charitable_Donation_Field_Registry
711 */
712 public function donation_fields() {
713 if ( ! $this->registry->has( 'donation_field_registry' ) ) {
714 $donation_fields = new Charitable_Donation_Field_Registry();
715
716 /* Register it immediately to avoid endless recursion. */
717 $this->registry->register_object( $donation_fields );
718
719 $fields = include( $this->get_path( 'includes' ) . 'fields/default-fields/donation-fields.php' );
720
721 foreach ( $fields as $key => $args ) {
722 $donation_fields->register_field( new Charitable_Donation_Field( $key, $args ) );
723 }
724 }
725
726 return $this->registry->get( 'donation_field_registry' );
727 }
728
729 /**
730 * Return the Endpoints API object.
731 *
732 * If the Endpoints API has not been set up yet, this will also
733 * perform the task of setting it up initially.
734 *
735 * This method is called on the plugins_loaded hook.
736 *
737 * @since 1.5.0
738 *
739 * @return Charitable_Endpoints
740 */
741 public function endpoints() {
742 if ( ! $this->registry->has( 'endpoints' ) ) {
743 /**
744 * The order in which we register endpoints is important, because
745 * it determines the order in which the endpoints are checked to
746 * find whether they are the current page.
747 *
748 * Any endpoint that builds on another endpoint should be registered
749 * BEFORE the endpoint it builds on. In other words, move from
750 * most specific to least specific.
751 */
752 $endpoints = new Charitable_Endpoints();
753 $endpoints->register( new Charitable_Campaign_Donation_Endpoint );
754 $endpoints->register( new Charitable_Campaign_Widget_Endpoint );
755 $endpoints->register( new Charitable_Campaign_Endpoint );
756 $endpoints->register( new Charitable_Donation_Cancellation_Endpoint );
757 $endpoints->register( new Charitable_Donation_Processing_Endpoint );
758 $endpoints->register( new Charitable_Donation_Receipt_Endpoint );
759 $endpoints->register( new Charitable_Email_Preview_Endpoint );
760 $endpoints->register( new Charitable_Email_Verification_Endpoint );
761 $endpoints->register( new Charitable_Forgot_Password_Endpoint );
762 $endpoints->register( new Charitable_Reset_Password_Endpoint );
763 $endpoints->register( new Charitable_Registration_Endpoint );
764 $endpoints->register( new Charitable_Login_Endpoint );
765 $endpoints->register( new Charitable_Profile_Endpoint );
766 $endpoints->register( new Charitable_Webhook_Listener_Endpoint );
767
768 $this->registry->register_object( $endpoints );
769 }
770
771 return $this->registry->get( 'endpoints' );
772 }
773
774 /**
775 * Returns a registered object.
776 *
777 * @since 1.0.0
778 *
779 * @param string $class The type of class to be retrieved.
780 * @return object
781 */
782 public function get_registered_object( $class ) {
783 return $this->registry->get( $class );
784 }
785
786 /**
787 * Registers our donormeta table as a meta data table.
788 *
789 * @since 1.6.0
790 *
791 * @global WPDB $wpdb
792 * @return void
793 */
794 public function register_donormeta_table() {
795 global $wpdb;
796
797 $wpdb->donormeta = $wpdb->prefix . 'charitable_donormeta';
798 }
799
800 /**
801 * Returns the model for one of Charitable's database tables.
802 *
803 * @since 1.0.0
804 *
805 * @param string $table The database table to retrieve.
806 * @return Charitable_DB
807 */
808 public function get_db_table( $table ) {
809 $tables = $this->get_tables();
810
811 if ( ! isset( $tables[ $table ] ) ) {
812 charitable_get_deprecated()->doing_it_wrong(
813 __METHOD__,
814 sprintf( 'Invalid table %s passed', $table ),
815 '1.0.0'
816 );
817 return null;
818 }
819
820 return $this->registry->get( $tables[ $table ] );
821 }
822
823 /**
824 * Return the filtered list of registered tables.
825 *
826 * @since 1.0.0
827 *
828 * @return string[]
829 */
830 private function get_tables() {
831 /**
832 * Filter the array of available Charitable table classes.
833 *
834 * @since 1.0.0
835 *
836 * @param array $tables List of tables as a key=>value array.
837 */
838 return apply_filters(
839 'charitable_db_tables',
840 array(
841 'campaign_donations' => 'Charitable_Campaign_Donations_DB',
842 'donors' => 'Charitable_Donors_DB',
843 'donormeta' => 'Charitable_Donormeta_DB',
844 )
845 );
846 }
847
848 /**
849 * Maybe activate Charitable when a new site is added in a multisite network.
850 *
851 * @since 1.4.6
852 *
853 * @param int $blog_id The blog to activate Charitable on.
854 * @return void
855 */
856 public function maybe_activate_charitable_on_new_site( $blog_id ) {
857 if ( is_plugin_active_for_network( basename( $this->directory_path ) . '/charitable.php' ) ) {
858 switch_to_blog( $blog_id );
859 $this->activate( false );
860 restore_current_blog();
861 }
862 }
863
864 /**
865 * Runs on plugin activation.
866 *
867 * @see register_activation_hook
868 *
869 * @since 1.0.0
870 *
871 * @param boolean $network_wide Whether to enable the plugin for all sites in the network
872 * or just the current site. Multisite only. Default is false.
873 * @return void
874 */
875 public function activate( $network_wide = false ) {
876 require_once( $this->get_path( 'includes' ) . 'plugin/class-charitable-install.php' );
877
878 if ( is_multisite() && $network_wide ) {
879 global $wpdb;
880
881 foreach ( $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" ) as $blog_id ) {
882 switch_to_blog( $blog_id );
883 new Charitable_Install( $this->includes_path );
884 restore_current_blog();
885 }
886 } else {
887 new Charitable_Install( $this->includes_path );
888 }
889
890 // create or update the install date for future reference.
891 update_option( 'wpcharitable_activated_datetime', current_time( 'timestamp' ) );
892 }
893
894 /**
895 * Runs on plugin deactivation.
896 *
897 * @see register_deactivation_hook
898 *
899 * @since 1.0.0
900 *
901 * @return void
902 */
903 public function deactivate() {
904 require_once( $this->get_path( 'includes' ) . 'plugin/class-charitable-uninstall.php' );
905 new Charitable_Uninstall();
906 }
907
908 /**
909 * If a charitable_action event is triggered, delegate the event using do_action.
910 *
911 * @since 1.0.0
912 *
913 * @return void
914 */
915 public function do_charitable_actions() {
916 if ( isset( $_REQUEST['charitable_action'] ) ) {
917
918 $action = $_REQUEST['charitable_action'];
919
920 /**
921 * Handle Charitable action.
922 *
923 * @since 1.0.0
924 */
925 do_action( 'charitable_' . $action );
926 }
927 }
928
929 /**
930 * Throw error on object clone.
931 *
932 * This class is specifically designed to be instantiated once. You can retrieve the instance using charitable()
933 *
934 * @since 1.0.0
935 *
936 * @return void
937 */
938 public function __clone() {
939 charitable_get_deprecated()->doing_it_wrong(
940 __FUNCTION__,
941 __( 'Cloning this object is forbidden.', 'charitable' ),
942 '1.0.0'
943 );
944 }
945
946 /**
947 * Disable unserializing of the class.
948 *
949 * @since 1.0.0
950 *
951 * @return void
952 */
953 public function __wakeup() {
954 charitable_get_deprecated()->doing_it_wrong(
955 __FUNCTION__,
956 __( 'Unserializing instances of this class is forbidden.', 'charitable' ),
957 '1.0.0'
958 );
959 }
960
961 /**
962 * DEPRECATED METHODS
963 */
964
965 /**
966 * Load plugin compatibility files on plugins_loaded hook.
967 *
968 * @deprecated 1.8.0
969 *
970 * @since 1.4.18
971 * @since 1.5.0 Deprecated.
972 *
973 * @return void
974 */
975 public function load_plugin_compat_files() {
976 charitable_get_deprecated()->deprecated_function(
977 __METHOD__,
978 '1.5.0.',
979 'charitable_load_compat_functions'
980 );
981
982 charitable_load_compat_functions();
983 }
984
985 /**
986 * Stores an object in the plugin's registry.
987 *
988 * @deprecated 1.8.0
989 *
990 * @since 1.0.0
991 * @since 1.5.0 Deprecated.
992 *
993 * @param mixed $object Object to be registered.
994 * @return void
995 */
996 public function register_object( $object ) {
997 charitable_get_deprecated()->deprecated_function(
998 __METHOD__,
999 '1.5.0',
1000 'charitable()->registry()->register_object()'
1001 );
1002
1003 $this->registry->register_object( $object );
1004 }
1005
1006 /**
1007 * Returns the public class.
1008 *
1009 * @deprecated 1.8.0
1010 *
1011 * @since 1.0.0
1012 * @since 1.5.0 Deprecated.
1013 *
1014 * @return Charitable_Public
1015 */
1016 public function get_public() {
1017 charitable_get_deprecated()->deprecated_function(
1018 __METHOD__,
1019 '1.5.0',
1020 'charitable_get_helper'
1021 );
1022
1023 return $this->registry->get( 'Charitable_Public' );
1024 }
1025
1026 /**
1027 * Returns the admin class.
1028 *
1029 * @deprecated 1.8.0
1030 *
1031 * @since 1.0.0
1032 * @since 1.5.0 Deprecated.
1033 *
1034 * @return Charitable_Admin
1035 */
1036 public function get_admin() {
1037 charitable_get_deprecated()->deprecated_function(
1038 __METHOD__,
1039 '1.5.0',
1040 'charitable_get_helper'
1041 );
1042
1043 return $this->registry->get( 'Charitable_Admin' );
1044 }
1045
1046 /**
1047 * Return the current request object.
1048 *
1049 * @deprecated 1.8.0
1050 *
1051 * @since 1.0.0
1052 * @since 1.5.0 Deprecated.
1053 *
1054 * @return Charitable_Request
1055 */
1056 public function get_request() {
1057 charitable_get_deprecated()->deprecated_function(
1058 __METHOD__,
1059 '1.5.0',
1060 'charitable_get_helper'
1061 );
1062
1063 return $this->registry->get( 'Charitable_Request' );
1064 }
1065
1066 /**
1067 * Returns the instance of Charitable_Currency.
1068 *
1069 * @deprecated 1.7.0
1070 *
1071 * @since 1.4.0 Deprecated.
1072 */
1073 public function get_currency_helper() {
1074 charitable_get_deprecated()->deprecated_function( __METHOD__, '1.4.0', 'charitable_get_currency_helper' );
1075 return charitable_get_currency_helper();
1076 }
1077
1078 /**
1079 * Returns the instance of Charitable_Locations.
1080 *
1081 * @deprecated 1.6.0
1082 *
1083 * @since 1.2.0 Deprecated.
1084 */
1085 public function get_location_helper() {
1086 charitable_get_deprecated()->deprecated_function( __METHOD__, '1.2.0', 'charitable_get_location_helper' );
1087 return charitable_get_location_helper();
1088 }
1089
1090 /**
1091 * Determine if we use Stripe core files or use an addon if that's installed and active. Checks for USE_NEW_STRIPE first.
1092 *
1093 * @since 1.7.0
1094 *
1095 * @return boolean
1096 */
1097 public function load_core_stripe() {
1098
1099 if ( false !== ( defined( 'USE_NEW_STRIPE' ) && USE_NEW_STRIPE ) ) {
1100 return true;
1101 }
1102
1103 // check for stripe addon
1104
1105 // if ( in_array('charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option('active_plugins' ) ) ) ) {
1106 // return false;
1107 // }
1108
1109 // if ( class_exists( 'Charitable_Stripe' ) ) {
1110 // return false;
1111 // }
1112
1113 return true;
1114 }
1115
1116 /**
1117 * Determine Stripe Connect is active.
1118 *
1119 * @since 1.7.0
1120 *
1121 * @return boolean
1122 */
1123 public function is_stripe_connect_addon() {
1124
1125 if ( in_array('charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option('active_plugins' ) ) ) ) {
1126 return true;
1127 }
1128
1129 return false;
1130 }
1131
1132 /**
1133 * Action links for the plugins page.
1134 *
1135 * @since 1.7.0
1136 *
1137 * @param array $actions An array of existing actions.
1138 * @param string $plugin_file The plugin file we are modifying.
1139 * @return array An array of action links.
1140 */
1141 public function plugin_action_links( $actions, $plugin_file, $action_links = false ) {
1142
1143 if ( ! charitable_is_pro() ) :
1144
1145 // if this isn't pro, add the upgrade link which is visible on the plugins page until the plugin name.
1146
1147 $action_links = [
1148 'proupgrade' => [
1149 // Translators: This is an action link users can click to purchase a license for All in One SEO Pro.
1150 'label' => __( 'Upgrade to Pro', 'charitable' ),
1151 'url' => 'https://wpcharitable.com/lite-vs-pro/?utm_source=WordPress&utm_campaign=WP+Charitable&utm_medium=Action+Link+Plugins+Page&utm_content=Upgrade+to+Pro',
1152 ]
1153 ];
1154
1155 endif;
1156
1157 if ( isset( $actions['edit'] ) ) {
1158 unset( $actions['edit'] );
1159 }
1160
1161 return $this->parse_action_links( $actions, $plugin_file, $action_links, 'before' );
1162 }
1163
1164 /**
1165 * Parse the action links.
1166 *
1167 * @since 1.7.0
1168 *
1169 * @param array $actions
1170 * @param string $pluginFile
1171 * @param
1172 * @return array
1173 */
1174 protected function parse_action_links( $actions, $pluginFile, $action_links = [], $position = 'after' ) {
1175 if ( empty( $this->plugin ) ) {
1176 $this->plugin = CHARTIABLE_PLUGIN_BASENAME;
1177 }
1178
1179 if ( $this->plugin === $pluginFile && ! empty( $action_links ) ) {
1180 foreach ( $action_links as $key => $value ) {
1181 $link = [
1182 $key => '<a href="' . $value['url'] . '">' . $value['label'] . '</a>'
1183 ];
1184
1185 $actions = 'after' === $position ? array_merge( $actions, $link ) : array_merge( $link, $actions );
1186 }
1187 }
1188
1189 return $actions;
1190 }
1191
1192 /**
1193 * Set up licensing for pro.
1194 *
1195 * @since 1.7.0
1196 *
1197 * @return void
1198 */
1199 public function setup_licensing() {
1200 charitable_get_helper( 'licenses' )->register_licensed_product(
1201 Charitable::NAME . ' Pro',
1202 Charitable::AUTHOR,
1203 Charitable::VERSION,
1204 __FILE__
1205 );
1206 }
1207
1208 /**
1209 * Deativates and/or warnings about any Charitable verison conflicts.
1210 *
1211 * @since 1.7.0
1212 *
1213 * @return null
1214 */
1215 public function check_for_version_conflicts() {
1216
1217 // Check for Charitable Stripe < 1.5.0
1218 if ( in_array( 'charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
1219 if ( version_compare( Charitable_Stripe::VERSION, '1.5.0', '<' ) ) {
1220 // manually deactivate plugin.
1221 $found = false;
1222 $current = get_option( 'active_plugins', array() );
1223 $key = array_search( 'charitable-stripe/charitable-stripe.php', $current, true );
1224 if ( false !== $key ) {
1225 $found = true;
1226
1227 unset( $current[ $key ] );
1228 update_option( 'active_plugins', $current );
1229
1230 $message = __( '<p><strong style="color:red;">NOTICE:</strong> <strong>Charitable</strong> detected an out-of-date and incompatible version of <strong>Charitable Stripe</strong> addon. To avoid issues with Stripe donations, <strong>Charitable Stripe</strong> ' . Charitable_Stripe::VERSION . ' was deactivated. Please update <strong>Charitable Stripe</strong> to version 1.5.0 or higher.</p><p>You can get the latest version of <strong>Charitable Stripe</strong> through your <a href="https://www.wpcharitable.com/account/" target="_blank">Charitable account at wpcharitable.com</a>. All active licenses are accessible in the "My Downloads" tab.</p>', 'charitable-stripe' );
1231
1232 wp_die( $message . ' <a href="' . admin_url( 'plugins.php' ) . '">Click here to return to the plugins screen.</a>' );
1233 }
1234 // charitable_get_notices()->add_error( $message );
1235 add_option( 'chartiable_version_warning', $message );
1236 } else {
1237 delete_option( 'chartiable_version_warning' );
1238 }
1239 }
1240 }
1241
1242
1243 }
1244
1245 $charitable = new Charitable();
1246
1247 endif;
1248