| @@ -1,15 +1,17 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | /** |
| 3 | 3 | * Plugin Name: Charitable |
| 4 | 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 | |
| 5 | + * Description: The best WordPress donation plugin. Fundraising with recurring donations, and powerful features to help you raise more money online. | |
| 6 | + * Version: 1.8.13 | |
| 7 | 7 | * Author: Charitable Donations & Fundraising Team |
| 8 | 8 | * Author URI: https://wpcharitable.com |
| 9 | - * Requires at least: 4.1 | |
| 10 | - * Tested up to: 6.1.1 | |
| 11 | - * Stable tag: 1.7.0.7 | |
| 9 | + * Requires at least: 5.9 | |
| 10 | + * Requires PHP: 7.4 | |
| 11 | + * Stable tag: 1.8.13 | |
| 12 | + * License: GPLv2 or later | |
| 13 | + * License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html | |
| 12 | 14 | * |
| 13 | 15 | * Text Domain: charitable |
| 14 | 16 | * Domain Path: /i18n/languages/ |
| 15 | 17 | * |
| @@ -14,9 +16,9 @@ | ||
| 14 | 16 | * Domain Path: /i18n/languages/ |
| 15 | 17 | * |
| 16 | 18 | * @package Charitable |
| 17 | 19 | * @author David Bisset |
| 18 | - * @copyright Copyright (c) 2022, WP Charitable LLC | |
| 20 | + * @copyright Copyright (c) 2026, WP Charitable LLC | |
| 19 | 21 | * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License |
| 20 | 22 | */ |
| 21 | 23 | |
| 22 | 24 | // Exit if accessed directly. |
| @@ -37,9 +39,9 @@ | ||
| 37 | 39 | /** The plugin author name. */ |
| 38 | 40 | const AUTHOR = 'WP Charitable'; |
| 39 | 41 | |
| 40 | 42 | /* Plugin version. */ |
| 41 | - const VERSION = '1.7.0.7'; | |
| 43 | + const VERSION = '1.8.13'; | |
| 42 | 44 | |
| 43 | 45 | /* Version of database schema. */ |
| 44 | 46 | const DB_VERSION = '20180522'; |
| 45 | 47 | |
| @@ -104,8 +106,17 @@ | ||
| 104 | 106 | */ |
| 105 | 107 | private $classmap; |
| 106 | 108 | |
| 107 | 109 | /** |
| 110 | + * Plugin. | |
| 111 | + * | |
| 112 | + * @since 1.8.0 | |
| 113 | + * | |
| 114 | + * @var array | |
| 115 | + */ | |
| 116 | + private $plugin; | |
| 117 | + | |
| 118 | + /** | |
| 108 | 119 | * Create class instance. |
| 109 | 120 | * |
| 110 | 121 | * @since 1.0.0 |
| 111 | 122 | */ |
| @@ -113,12 +124,26 @@ | ||
| 113 | 124 | $this->directory_path = plugin_dir_path( __FILE__ ); |
| 114 | 125 | $this->directory_url = plugin_dir_url( __FILE__ ); |
| 115 | 126 | $this->includes_path = $this->directory_path . 'includes/'; |
| 116 | 127 | |
| 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/' ); | |
| 128 | + define( 'CHARITABLE_DIRECTORY_PATH', plugin_dir_path( __FILE__ ) ); | |
| 129 | + define( 'CHARITABLE_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); | |
| 130 | + define( 'CHARITABLE_MARKETING_URL', 'https://wpcharitable.com/' ); | |
| 131 | + if ( ! defined( 'CHARITABLE_ANALYSIS_API_URL' ) ) { | |
| 132 | + define( 'CHARITABLE_ANALYSIS_API_URL', apply_filters( 'charitable_analysis_api_url', 'https://nonprofitscore.org/api/v1/charitable/recommendations' ) ); | |
| 133 | + } | |
| 134 | + // No credential is shipped. Each site earns a runtime-minted, quota-limited per-site token from | |
| 135 | + // the register endpoint (see Charitable_Site_Analysis::register()); the token is not in plugin source. | |
| 136 | + if ( ! defined( 'CHARITABLE_ANALYSIS_REGISTER_URL' ) ) { | |
| 137 | + define( 'CHARITABLE_ANALYSIS_REGISTER_URL', apply_filters( 'charitable_analysis_register_url', 'https://nonprofitscore.org/api/v1/charitable/register' ) ); | |
| 138 | + } | |
| 139 | + // Note: CHARITABLE_ANALYSIS_SALT is intentionally NOT defined here. It would need wp_salt(), | |
| 140 | + // which lives in pluggable.php and is not loaded yet at plugin-construct time. The salt is | |
| 141 | + // resolved lazily in Charitable_Site_Analysis::gather_config() (admin-ajax time), and a host | |
| 142 | + // may still pre-define the CHARITABLE_ANALYSIS_SALT constant (e.g. in wp-config.php). | |
| 120 | 143 | |
| 144 | + define( 'CHARITABLE_BUILDER_SHOW_LEGACY_EDIT_LINKS', true ); // 1.8.0 specific. | |
| 145 | + | |
| 121 | 146 | spl_autoload_register( array( $this, 'autoloader' ) ); |
| 122 | 147 | |
| 123 | 148 | $this->load_dependencies(); |
| 124 | 149 | |
| @@ -124,12 +149,28 @@ | ||
| 124 | 149 | |
| 125 | 150 | register_activation_hook( __FILE__, array( $this, 'activate' ) ); |
| 126 | 151 | register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) ); |
| 127 | 152 | |
| 128 | - add_filter( 'plugin_action_links_' . CHARTIABLE_PLUGIN_BASENAME, array( $this, 'plugin_action_links' ), 99, 2 ); | |
| 153 | + add_filter( 'plugin_action_links_' . CHARITABLE_PLUGIN_BASENAME, array( $this, 'plugin_action_links' ), 99, 2 ); | |
| 129 | 154 | add_action( 'plugins_loaded', array( $this, 'start' ), 3 ); |
| 130 | 155 | |
| 131 | 156 | add_action( 'plugins_loaded', array( $this, 'check_for_version_conflicts' ), 2 ); |
| 157 | + | |
| 158 | + // Run upgrade-server callback before any redirect (e.g. login) can run. Request from connect-callback.php. | |
| 159 | + if ( defined( 'CHARITABLE_CONNECT_CALLBACK' ) && CHARITABLE_CONNECT_CALLBACK ) { | |
| 160 | + add_action( 'init', array( $this, 'run_connect_callback' ), -9999 ); | |
| 161 | + } | |
| 162 | + | |
| 163 | + // Initialize error handler early. | |
| 164 | + add_action( | |
| 165 | + 'plugins_loaded', | |
| 166 | + function () { | |
| 167 | + require_once $this->get_path( 'includes' ) . 'class-charitable-error-handler.php'; | |
| 168 | + $error_handler = new Charitable_Error_Handler(); | |
| 169 | + $error_handler->init(); | |
| 170 | + }, | |
| 171 | + 1 | |
| 172 | + ); | |
| 132 | 173 | } |
| 133 | 174 | |
| 134 | 175 | /** |
| 135 | 176 | * Returns the original instance of this class. |
| @@ -186,63 +227,78 @@ | ||
| 186 | 227 | private function load_dependencies() { |
| 187 | 228 | $includes_path = $this->get_path( 'includes' ); |
| 188 | 229 | |
| 189 | 230 | /* 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' ); | |
| 231 | + require_once $includes_path . 'class-charitable-log-muter.php'; | |
| 232 | + require_once $includes_path . 'charitable-core-functions.php'; | |
| 233 | + require_once $includes_path . 'api/charitable-api-functions.php'; | |
| 234 | + require_once $includes_path . 'campaigns/charitable-campaign-functions.php'; | |
| 235 | + require_once $includes_path . 'campaigns/charitable-campaign-hooks.php'; | |
| 236 | + require_once $includes_path . 'compat/charitable-compat-functions.php'; | |
| 237 | + require_once $includes_path . 'currency/charitable-currency-functions.php'; | |
| 238 | + require_once $includes_path . 'deprecated/charitable-deprecated-functions.php'; | |
| 239 | + require_once $includes_path . 'donations/charitable-donation-hooks.php'; | |
| 240 | + require_once $includes_path . 'donations/charitable-donation-functions.php'; | |
| 241 | + require_once $includes_path . 'emails/charitable-email-hooks.php'; | |
| 242 | + require_once $includes_path . 'endpoints/charitable-endpoints-functions.php'; | |
| 243 | + require_once $includes_path . 'privacy/charitable-privacy-functions.php'; | |
| 244 | + require_once $includes_path . 'public/charitable-template-helpers.php'; | |
| 245 | + require_once $includes_path . 'shortcodes/charitable-shortcodes-hooks.php'; | |
| 246 | + require_once $includes_path . 'tracking/charitable-tracking-hooks.php'; // 1.8.12 - MUST be outside the admin gate; see the file header. | |
| 247 | + require_once $includes_path . 'abilities/charitable-abilities-hooks.php'; // 1.8.13 - MUST be outside the admin gate: abilities register on REST and WP-CLI requests, neither of which is is_admin(). | |
| 248 | + require_once $includes_path . 'upgrades/charitable-upgrade-hooks.php'; | |
| 249 | + require_once $includes_path . 'users/charitable-user-functions.php'; | |
| 250 | + require_once $includes_path . 'user-management/charitable-user-management-hooks.php'; | |
| 251 | + require_once $includes_path . 'utilities/charitable-utility-functions.php'; | |
| 252 | + require_once $includes_path . 'elementor/charitable-elementor-hooks.php'; | |
| 208 | 253 | |
| 209 | - If ( $this->load_core_stripe() ) : | |
| 254 | + // Load security hooks on both admin and frontend (CAPTCHA needs to work on frontend). | |
| 255 | + require_once $this->get_path( 'includes', true ) . 'admin/security/charitable-security-hooks.php'; | |
| 210 | 256 | |
| 211 | - /* Load Stripe SDK */ | |
| 212 | - require_once( $this->get_path( 'directory' ) . 'vendor/autoload.php' ); | |
| 257 | + /* Load vendor/autoload.php - our modified platform_check.php and autoload_real.php will handle conditional loading */ | |
| 258 | + require_once $this->get_path( 'directory' ) . 'vendor/autoload.php'; | |
| 213 | 259 | |
| 260 | + /* Square Compatibility Wrapper - always load this regardless of PHP version */ | |
| 261 | + require_once $includes_path . 'square/class-charitable-square-compatibility.php'; | |
| 262 | + | |
| 263 | + /* Initialize Square conditionally - will check for compatibility internally */ | |
| 264 | + Charitable_Square_Compatibility::init(); | |
| 265 | + | |
| 266 | + if ( $this->load_core_stripe() ) : | |
| 267 | + | |
| 214 | 268 | /* Interfaces */ |
| 215 | - require_once( $includes_path . 'stripe/interfaces/interface-charitable-stripe-gateway-processor.php' ); | |
| 269 | + require_once $includes_path . 'stripe/interfaces/interface-charitable-stripe-gateway-processor.php'; | |
| 216 | 270 | |
| 217 | 271 | /* Abstract classes */ |
| 218 | - require_once( $includes_path . 'stripe/abstracts/class-charitable-stripe-gateway-processor.php' ); | |
| 272 | + require_once $includes_path . 'stripe/abstracts/class-charitable-stripe-gateway-processor.php'; | |
| 219 | 273 | |
| 220 | 274 | /* 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 | - require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-plan.php' ); | |
| 229 | - require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-product.php' ); | |
| 275 | + require_once $includes_path . 'stripe/donations/class-charitable-stripe-donation-log.php'; | |
| 276 | + require_once $includes_path . 'stripe/donations/class-charitable-stripe-recurring-donation-log.php'; | |
| 277 | + require_once $includes_path . 'stripe/i18n/class-charitable-stripe-i18n.php'; | |
| 278 | + require_once $includes_path . 'stripe/gateway/class-charitable-stripe-connected-customer.php'; | |
| 279 | + require_once $includes_path . 'stripe/gateway/class-charitable-stripe-customer.php'; | |
| 280 | + require_once $includes_path . 'stripe/gateway/class-charitable-stripe-gateway-processor-payment-intents.php'; | |
| 281 | + require_once $includes_path . 'stripe/gateway/class-charitable-stripe-payment-intent.php'; | |
| 282 | + require_once $includes_path . 'stripe/gateway/class-charitable-stripe-plan.php'; | |
| 283 | + require_once $includes_path . 'stripe/gateway/class-charitable-stripe-product.php'; | |
| 230 | 284 | |
| 231 | - require_once( $includes_path . 'stripe/connect/charitable-stripe-connect-functions.php' ); | |
| 232 | - require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-gateway-processor-checkout.php' ); | |
| 285 | + require_once $includes_path . 'stripe/connect/charitable-stripe-connect-functions.php'; | |
| 286 | + require_once $includes_path . 'stripe/gateway/class-charitable-stripe-gateway-processor-checkout.php'; | |
| 233 | 287 | |
| 234 | 288 | /* Functions & Hooks */ |
| 235 | - require_once( $includes_path . 'stripe/charitable-stripe-core-functions.php' ); | |
| 236 | - require_once( $includes_path . 'stripe/donations/charitable-stripe-donation-functions.php' ); | |
| 237 | - require_once( $includes_path . 'stripe/gateway/charitable-stripe-gateway-hooks.php' ); | |
| 289 | + require_once $includes_path . 'stripe/charitable-stripe-core-functions.php'; | |
| 290 | + require_once $includes_path . 'stripe/donations/charitable-stripe-donation-functions.php'; | |
| 291 | + require_once $includes_path . 'stripe/gateway/charitable-stripe-gateway-hooks.php'; | |
| 238 | 292 | |
| 239 | 293 | /* webhooks */ |
| 240 | - require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-webhook-api.php' ); | |
| 241 | - require_once( $includes_path . 'stripe/gateway/class-charitable-stripe-webhook-processor.php' ); | |
| 294 | + require_once $includes_path . 'stripe/gateway/class-charitable-stripe-webhook-api.php'; | |
| 295 | + require_once $includes_path . 'stripe/gateway/class-charitable-stripe-webhook-processor.php'; | |
| 242 | 296 | |
| 243 | 297 | endif; |
| 244 | 298 | |
| 299 | + /* Load PayPal Commerce Gateway */ | |
| 300 | + require_once $includes_path . 'gateways/paypal-commerce/charitable-paypal-commerce.php'; | |
| 245 | 301 | } |
| 246 | 302 | |
| 247 | 303 | /** |
| 248 | 304 | * Load the template functions after theme is loaded. |
| @@ -255,10 +311,10 @@ | ||
| 255 | 311 | */ |
| 256 | 312 | public function load_template_files() { |
| 257 | 313 | $includes_path = $this->get_path( 'includes' ); |
| 258 | 314 | |
| 259 | - require_once( $includes_path . 'public/charitable-template-functions.php' ); | |
| 260 | - require_once( $includes_path . 'public/charitable-template-hooks.php' ); | |
| 315 | + require_once $includes_path . 'public/charitable-template-functions.php'; | |
| 316 | + require_once $includes_path . 'public/charitable-template-hooks.php'; | |
| 261 | 317 | } |
| 262 | 318 | |
| 263 | 319 | /** |
| 264 | 320 | * Dynamically loads the class attempting to be instantiated elsewhere in the |
| @@ -281,18 +337,18 @@ | ||
| 281 | 337 | } |
| 282 | 338 | |
| 283 | 339 | /* Autogenerated class map. */ |
| 284 | 340 | if ( ! isset( $this->classmap ) ) { |
| 285 | - $this->classmap = include( 'includes/autoloader/charitable-class-map.php' ); | |
| 341 | + $this->classmap = include 'includes/autoloader/charitable-class-map.php'; | |
| 286 | 342 | |
| 287 | - $this->classmap[ 'Charitable_Gateway_Stripe_AM' ] = 'gateways/class-charitable-gateway-stripe-am.php'; | |
| 288 | - $this->classmap[ 'Charitable_Gateway_Stripe' ] = 'gateways/class-charitable-gateway-stripe-am.php'; | |
| 343 | + $this->classmap['Charitable_Gateway_Stripe_AM'] = 'gateways/class-charitable-gateway-stripe-am.php'; | |
| 344 | + $this->classmap['Charitable_Gateway_Stripe'] = 'gateways/class-charitable-gateway-stripe-am.php'; | |
| 289 | 345 | } |
| 290 | 346 | |
| 291 | 347 | $file_path = isset( $this->classmap[ $class_name ] ) ? $this->get_path( 'includes' ) . $this->classmap[ $class_name ] : false; |
| 292 | 348 | |
| 293 | 349 | if ( false !== $file_path && file_exists( $file_path ) && is_file( $file_path ) ) { |
| 294 | - require_once( $file_path ); | |
| 350 | + require_once $file_path; | |
| 295 | 351 | return true; |
| 296 | 352 | } |
| 297 | 353 | return false; |
| 298 | 354 | } |
| @@ -319,11 +375,11 @@ | ||
| 319 | 375 | $this->registry->register_object( Charitable_Locations::get_instance() ); |
| 320 | 376 | $this->registry->register_object( Charitable_Currency::get_instance() ); |
| 321 | 377 | $this->registry->register_object( Charitable_Notifications::get_instance() ); |
| 322 | 378 | |
| 323 | - $this->registry->register_object( new Charitable_Privacy ); | |
| 324 | - $this->registry->register_object( new Charitable_Debugging ); | |
| 325 | - $this->registry->register_object( new Charitable_Locale ); | |
| 379 | + $this->registry->register_object( new Charitable_Privacy() ); | |
| 380 | + $this->registry->register_object( new Charitable_Debugging() ); | |
| 381 | + $this->registry->register_object( new Charitable_Locale() ); | |
| 326 | 382 | } |
| 327 | 383 | |
| 328 | 384 | return $this->registry; |
| 329 | 385 | } |
| @@ -339,10 +395,10 @@ | ||
| 339 | 395 | add_action( 'wpmu_new_blog', array( $this, 'maybe_activate_charitable_on_new_site' ) ); |
| 340 | 396 | add_action( 'plugins_loaded', array( $this, 'charitable_install' ), 100 ); |
| 341 | 397 | add_action( 'plugins_loaded', array( $this, 'charitable_start' ), 100 ); |
| 342 | 398 | add_action( 'plugins_loaded', array( $this, 'endpoints' ), 100 ); |
| 343 | - add_action( 'plugins_loaded', array( $this, 'donation_fields' ), 100 ); | |
| 344 | - add_action( 'plugins_loaded', array( $this, 'campaign_fields' ), 100 ); | |
| 399 | + add_action( 'init', array( $this, 'donation_fields' ), 100 ); | |
| 400 | + add_action( 'init', array( $this, 'campaign_fields' ), 100 ); | |
| 345 | 401 | add_action( 'plugins_loaded', array( $this, 'register_donormeta_table' ) ); |
| 346 | 402 | add_action( 'plugins_loaded', 'charitable_load_compat_functions' ); |
| 347 | 403 | add_action( 'setup_theme', array( 'Charitable_Customizer', 'start' ) ); |
| 348 | 404 | add_action( 'after_setup_theme', array( $this, 'load_template_files' ) ); |
| @@ -354,19 +410,17 @@ | ||
| 354 | 410 | * as addons) has a chance to run before the event. |
| 355 | 411 | */ |
| 356 | 412 | add_action( 'init', array( $this, 'do_charitable_actions' ), 20 ); |
| 357 | 413 | |
| 358 | - If ( $this->load_core_stripe() ) : | |
| 414 | + if ( $this->load_core_stripe() ) : | |
| 359 | 415 | |
| 360 | 416 | /** |
| 361 | 417 | * Set up scripts & stylesheets & enqueue them when appropriate. |
| 362 | 418 | */ |
| 363 | - // add_action( 'wp_enqueue_scripts', array( $this, 'setup_stripe_scripts' ), 11 ); | |
| 364 | 419 | add_action( 'charitable_form_after_fields', array( $this, 'maybe_setup_stripe_scripts_in_donation_form' ) ); |
| 365 | 420 | add_action( 'charitable_campaign_loop_after', array( $this, 'maybe_setup_stripe_scripts_in_campaign_loop' ) ); |
| 366 | 421 | |
| 367 | 422 | endif; |
| 368 | - | |
| 369 | 423 | } |
| 370 | 424 | |
| 371 | 425 | |
| 372 | 426 | /** |
| @@ -436,25 +490,70 @@ | ||
| 436 | 490 | if ( ! is_admin() ) { |
| 437 | 491 | return false; |
| 438 | 492 | } |
| 439 | 493 | |
| 440 | - require_once( $this->get_path( 'admin' ) . 'class-charitable-admin.php' ); | |
| 441 | - require_once( $this->get_path( 'admin' ) . 'charitable-admin-hooks.php' ); | |
| 494 | + // load blocks/Gutenberg related. | |
| 495 | + require_once $this->get_path( 'admin' ) . 'class-charitable-admin-blocks.php'; | |
| 442 | 496 | |
| 443 | - $admin = Charitable_Admin::get_instance(); | |
| 497 | + require_once $this->get_path( 'admin' ) . 'class-charitable-admin.php'; | |
| 498 | + require_once $this->get_path( 'admin' ) . 'charitable-admin-hooks.php'; | |
| 444 | 499 | |
| 445 | - $this->registry->register_object( $admin ); | |
| 500 | + // load campaign builder. | |
| 501 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/util.php'; | |
| 502 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/functions.php'; | |
| 503 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/ajax-actions.php'; | |
| 504 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/functions-legacy.php'; | |
| 505 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/debug.php'; | |
| 506 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/access.php'; | |
| 507 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/class-builder-fields.php'; | |
| 508 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/class-builder-form-fields.php'; | |
| 446 | 509 | |
| 447 | - // Stripe | |
| 510 | + // connect for upgrade.wpcharitable.com. | |
| 511 | + require_once $this->get_path( 'admin' ) . 'class-charitable-admin-connect.php'; | |
| 448 | 512 | |
| 449 | - require_once( $this->get_path( 'includes' ) . 'stripe/admin/class-charitable-stripe-admin.php' ); | |
| 513 | + // misc. | |
| 514 | + require_once $this->get_path( 'admin' ) . 'class-charitable-admin-pointers.php'; | |
| 515 | + require_once $this->get_path( 'admin' ) . 'plugins/charitable-admin-plugin-hooks.php'; | |
| 516 | + require_once $this->get_path( 'admin' ) . 'class-charitable-admin-getting-started.php'; | |
| 450 | 517 | |
| 451 | - new Charitable_Stripe_Admin; | |
| 518 | + // Site Analysis / Recommendations tab. | |
| 519 | + require_once $this->get_path( 'admin' ) . 'site-analysis/class-charitable-site-analysis.php'; | |
| 520 | + Charitable_Site_Analysis::get_instance(); | |
| 452 | 521 | |
| 522 | + $admin = Charitable_Admin::get_instance(); | |
| 523 | + $this->registry->register_object( $admin ); | |
| 524 | + | |
| 525 | + // Stripe. | |
| 526 | + require_once $this->get_path( 'includes' ) . 'stripe/admin/class-charitable-stripe-admin.php'; | |
| 527 | + new Charitable_Stripe_Admin(); | |
| 528 | + | |
| 453 | 529 | return $admin; |
| 454 | 530 | } |
| 455 | 531 | |
| 456 | 532 | /** |
| 533 | + * Run the upgrade-server connect callback on init before any redirect (e.g. to login) can run. | |
| 534 | + * Only registered when CHARITABLE_CONNECT_CALLBACK is defined (request came from connect-callback.php). | |
| 535 | + * | |
| 536 | + * @since 1.8.9.6 | |
| 537 | + */ | |
| 538 | + public function run_connect_callback() { | |
| 539 | + ini_set( 'display_errors', '0' ); | |
| 540 | + require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 541 | + require_once ABSPATH . 'wp-admin/includes/file.php'; | |
| 542 | + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; | |
| 543 | + $connect_file = $this->get_path( 'admin' ) . 'class-charitable-admin-connect.php'; | |
| 544 | + if ( file_exists( $connect_file ) ) { | |
| 545 | + require_once $connect_file; | |
| 546 | + } | |
| 547 | + if ( ! class_exists( 'Charitable_Admin_Connect' ) ) { | |
| 548 | + header( 'Content-Type: application/json' ); | |
| 549 | + wp_send_json( array( 'success' => false, 'data' => array( 'message' => 'Charitable not loaded.' ) ) ); | |
| 550 | + } | |
| 551 | + Charitable_Admin_Connect::get_instance()->process(); | |
| 552 | + exit; | |
| 553 | + } | |
| 554 | + | |
| 555 | + /** | |
| 457 | 556 | * Checks whether we're on the public-facing side and if so, loads the public-facing functionality. |
| 458 | 557 | * |
| 459 | 558 | * @since 1.0.0 |
| 460 | 559 | * |
| @@ -464,10 +563,18 @@ | ||
| 464 | 563 | if ( is_admin() && ! $this->is_ajax() ) { |
| 465 | 564 | return false; |
| 466 | 565 | } |
| 467 | 566 | |
| 468 | - require_once( $this->get_path( 'public' ) . 'class-charitable-public.php' ); | |
| 567 | + require_once $this->get_path( 'public' ) . 'class-charitable-public.php'; | |
| 469 | 568 | |
| 569 | + // Campaign Builder related (v1.8.0). | |
| 570 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/class-campaign-builder-preview.php'; | |
| 571 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/class-builder-fields.php'; | |
| 572 | + require_once $this->get_path( 'admin' ) . 'campaign-builder/class-builder-form-fields.php'; | |
| 573 | + | |
| 574 | + // load blocks/Gutenberg related. | |
| 575 | + require_once $this->get_path( 'admin' ) . 'class-charitable-admin-blocks.php'; | |
| 576 | + | |
| 470 | 577 | $public = Charitable_Public::get_instance(); |
| 471 | 578 | |
| 472 | 579 | $this->registry->register_object( $public ); |
| 473 | 580 | |
| @@ -482,25 +589,51 @@ | ||
| 482 | 589 | * @return boolean |
| 483 | 590 | */ |
| 484 | 591 | public function maybe_start_qunit() { |
| 485 | 592 | /* Skip out early if ?qunit isn't included in the request. */ |
| 486 | - if ( ! array_key_exists( 'qunit', $_GET ) ) { | |
| 593 | + if ( ! array_key_exists( 'qunit', $_GET ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended | |
| 487 | 594 | return false; |
| 488 | 595 | } |
| 489 | 596 | |
| 490 | - /* The unit tests have to exist. */ | |
| 491 | - if ( ! file_exists( $this->get_path( 'directory' ) . 'tests/qunit/tests.js' ) ) { | |
| 492 | - return false; | |
| 493 | - } | |
| 597 | + /* The unit tests have to exist. */ | |
| 598 | + if ( ! file_exists( $this->get_path( 'directory' ) . 'tests/qunit/tests.js' ) ) { | |
| 599 | + return false; | |
| 600 | + } | |
| 494 | 601 | |
| 495 | - wp_register_script( 'qunit', 'https://code.jquery.com/qunit/qunit-2.3.3.js', array(), '2.3.3', true ); | |
| 602 | + /** | |
| 603 | + * Register QUnit testing library. | |
| 604 | + * | |
| 605 | + * Note: These files must be bundled locally for WordPress.org compliance. | |
| 606 | + * Download from: | |
| 607 | + * - JS: https://code.jquery.com/qunit/qunit-2.3.3.js | |
| 608 | + * - CSS: https://code.jquery.com/qunit/qunit-2.3.3.css | |
| 609 | + * Save to: | |
| 610 | + * - assets/js/libraries/qunit-2.3.3.js | |
| 611 | + * - assets/css/libraries/qunit-2.3.3.css | |
| 612 | + * | |
| 613 | + * @since 1.0.0 | |
| 614 | + * @version 1.8.9.1 | |
| 615 | + */ | |
| 616 | + wp_register_script( | |
| 617 | + 'qunit', | |
| 618 | + $this->get_path( 'directory', false ) . 'assets/js/libraries/qunit-2.3.3.js', | |
| 619 | + array(), | |
| 620 | + '2.3.3', | |
| 621 | + true | |
| 622 | + ); | |
| 496 | 623 | |
| 497 | - /* Version: '20170615-15:44' */ | |
| 498 | - wp_register_script( 'qunit-tests', $this->get_path( 'directory', false ) . 'tests/qunit/tests.js', array( 'jquery', 'qunit' ), time(), true ); | |
| 499 | - wp_enqueue_script( 'qunit-tests' ); | |
| 624 | + /* Version: '20170615-15:44' */ | |
| 625 | + wp_register_script( 'qunit-tests', $this->get_path( 'directory', false ) . 'tests/qunit/tests.js', array( 'jquery', 'qunit' ), time(), true ); | |
| 626 | + wp_enqueue_script( 'qunit-tests' ); | |
| 500 | 627 | |
| 501 | - wp_register_style( 'qunit', 'https://code.jquery.com/qunit/qunit-2.3.3.css', array(), '2.3.3', 'all' ); | |
| 502 | - wp_enqueue_style( 'qunit' ); | |
| 628 | + wp_register_style( | |
| 629 | + 'qunit', | |
| 630 | + $this->get_path( 'directory', false ) . 'assets/css/libraries/qunit-2.3.3.css', | |
| 631 | + array(), | |
| 632 | + '2.3.3', | |
| 633 | + 'all' | |
| 634 | + ); | |
| 635 | + wp_enqueue_style( 'qunit' ); | |
| 503 | 636 | } |
| 504 | 637 | |
| 505 | 638 | /** |
| 506 | 639 | * Checks whether the current request is an AJAX request. |
| @@ -524,10 +657,10 @@ | ||
| 524 | 657 | if ( ! $this->is_ajax() ) { |
| 525 | 658 | return; |
| 526 | 659 | } |
| 527 | 660 | |
| 528 | - require_once( $this->get_path( 'includes' ) . 'ajax/charitable-ajax-functions.php' ); | |
| 529 | - require_once( $this->get_path( 'includes' ) . 'ajax/charitable-ajax-hooks.php' ); | |
| 661 | + require_once $this->get_path( 'includes' ) . 'ajax/charitable-ajax-functions.php'; | |
| 662 | + require_once $this->get_path( 'includes' ) . 'ajax/charitable-ajax-hooks.php'; | |
| 530 | 663 | } |
| 531 | 664 | |
| 532 | 665 | /** |
| 533 | 666 | * This method is fired after all plugins are loaded and simply fires the charitable_start hook. |
| @@ -545,9 +678,11 @@ | ||
| 545 | 678 | /** |
| 546 | 679 | * Fires off an action right after Charitable is installed, allowing other |
| 547 | 680 | * plugins/themes to do something at this point. |
| 548 | 681 | * |
| 549 | - * @since 1.0.1 | |
| 682 | + * @since 1.0.1 | |
| 683 | + * @version 1.8.1.12 - Added transient for activation redirect. | |
| 684 | + * @version 1.8.3 - Added call to add version and delete notifications. | |
| 550 | 685 | * |
| 551 | 686 | * @return void |
| 552 | 687 | */ |
| 553 | 688 | public function charitable_install() { |
| @@ -556,9 +691,9 @@ | ||
| 556 | 691 | if ( ! $install ) { |
| 557 | 692 | return; |
| 558 | 693 | } |
| 559 | 694 | |
| 560 | - require_once( $this->get_path( 'includes' ) . 'plugin/class-charitable-install.php' ); | |
| 695 | + require_once $this->get_path( 'includes' ) . 'plugin/class-charitable-install.php'; | |
| 561 | 696 | |
| 562 | 697 | Charitable_Install::finish_installing(); |
| 563 | 698 | |
| 564 | 699 | do_action( 'charitable_install' ); |
| @@ -566,14 +701,25 @@ | ||
| 566 | 701 | delete_transient( 'charitable_install' ); |
| 567 | 702 | |
| 568 | 703 | // Store the date when the initial activation was performed. |
| 569 | 704 | $type = function_exists( 'charitable_is_pro' ) && charitable_is_pro() ? 'pro' : 'lite'; |
| 570 | - $activated = get_option( 'charitable_activated', array() ); | |
| 705 | + $activated = (array) get_option( 'charitable_activated', array() ); | |
| 706 | + | |
| 707 | + // If no activation date is set, assume it's a new install and set the activation redirect transient. | |
| 708 | + if ( false === $activated || empty( $activated ) ) { | |
| 709 | + // Add transient to trigger redirect to the Welcome / Getting Started screen. | |
| 710 | + set_transient( 'charitable_activation_redirect', true, 30 ); | |
| 711 | + } | |
| 712 | + | |
| 713 | + $this->add_version_to_upgraded_from(); | |
| 714 | + | |
| 571 | 715 | if ( empty( $activated[ $type ] ) ) { |
| 572 | 716 | $activated[ $type ] = time(); |
| 573 | 717 | update_option( 'charitable_activated', $activated ); |
| 574 | 718 | } |
| 575 | 719 | |
| 720 | + // Clear notifications. | |
| 721 | + delete_option( 'charitable_notifications' ); | |
| 576 | 722 | } |
| 577 | 723 | |
| 578 | 724 | /** |
| 579 | 725 | * Returns whether we are currently in the start phase of the plugin. |
| @@ -582,9 +728,9 @@ | ||
| 582 | 728 | * |
| 583 | 729 | * @return boolean |
| 584 | 730 | */ |
| 585 | 731 | public function is_start() { |
| 586 | - return current_filter() == 'charitable_start'; | |
| 732 | + return current_filter() == 'charitable_start'; // phpcs:ignore | |
| 587 | 733 | } |
| 588 | 734 | |
| 589 | 735 | /** |
| 590 | 736 | * Returns whether the plugin has already started. |
| @@ -593,9 +739,9 @@ | ||
| 593 | 739 | * |
| 594 | 740 | * @return boolean |
| 595 | 741 | */ |
| 596 | 742 | public function started() { |
| 597 | - return did_action( 'charitable_start' ) || current_filter() == 'charitable_start'; | |
| 743 | + return did_action( 'charitable_start' ) || current_filter() == 'charitable_start'; // phpcs:ignore | |
| 598 | 744 | } |
| 599 | 745 | |
| 600 | 746 | /** |
| 601 | 747 | * Returns whether the plugin is being activated. |
| @@ -604,9 +750,9 @@ | ||
| 604 | 750 | * |
| 605 | 751 | * @return boolean |
| 606 | 752 | */ |
| 607 | 753 | public function is_activation() { |
| 608 | - return current_filter() == 'activate_charitable/charitable.php'; | |
| 754 | + return current_filter() == 'activate_charitable/charitable.php'; // phpcs:ignore | |
| 609 | 755 | } |
| 610 | 756 | |
| 611 | 757 | /** |
| 612 | 758 | * Returns whether the plugin is being deactivated. |
| @@ -615,9 +761,9 @@ | ||
| 615 | 761 | * |
| 616 | 762 | * @return boolean |
| 617 | 763 | */ |
| 618 | 764 | public function is_deactivation() { |
| 619 | - return current_filter() == 'deactivate_charitable/charitable.php'; | |
| 765 | + return current_filter() == 'deactivate_charitable/charitable.php'; // phpcs:ignore | |
| 620 | 766 | } |
| 621 | 767 | |
| 622 | 768 | /** |
| 623 | 769 | * Returns plugin paths. |
| @@ -651,8 +797,12 @@ | ||
| 651 | 797 | case 'templates': |
| 652 | 798 | $path = $base . 'templates/'; |
| 653 | 799 | break; |
| 654 | 800 | |
| 801 | + case 'plugin-directory': | |
| 802 | + $path = WP_PLUGIN_DIR; | |
| 803 | + break; | |
| 804 | + | |
| 655 | 805 | case 'directory': |
| 656 | 806 | $path = $base; |
| 657 | 807 | break; |
| 658 | 808 | |
| @@ -682,8 +832,26 @@ | ||
| 682 | 832 | return $version; |
| 683 | 833 | } |
| 684 | 834 | |
| 685 | 835 | /** |
| 836 | + * Adds previous versions to the upgraded_from option. | |
| 837 | + * | |
| 838 | + * @since 1.8.3 | |
| 839 | + */ | |
| 840 | + public function add_version_to_upgraded_from() { | |
| 841 | + | |
| 842 | + $upgraded_from = get_option( 'charitable_version_upgraded_from', array() ); | |
| 843 | + | |
| 844 | + if ( ! is_array( $upgraded_from ) ) { | |
| 845 | + $upgraded_from = array(); | |
| 846 | + } | |
| 847 | + | |
| 848 | + $upgraded_from[] = $this->get_version(); | |
| 849 | + | |
| 850 | + update_option( 'charitable_version_upgraded_from', $upgraded_from, false ); | |
| 851 | + } | |
| 852 | + | |
| 853 | + /** | |
| 686 | 854 | * Get the campaign fields registry |
| 687 | 855 | * |
| 688 | 856 | * If the registry has not been set up yet, this will also |
| 689 | 857 | * perform the task of setting it up initially. |
| @@ -700,9 +868,9 @@ | ||
| 700 | 868 | |
| 701 | 869 | /* Register it immediately to avoid endless recursion. */ |
| 702 | 870 | $this->registry->register_object( $campaign_fields ); |
| 703 | 871 | |
| 704 | - $fields = include( $this->get_path( 'includes' ) . 'fields/default-fields/campaign-fields.php' ); | |
| 872 | + $fields = include $this->get_path( 'includes' ) . 'fields/default-fields/campaign-fields.php'; | |
| 705 | 873 | |
| 706 | 874 | foreach ( $fields as $key => $args ) { |
| 707 | 875 | $campaign_fields->register_field( new Charitable_Campaign_Field( $key, $args ) ); |
| 708 | 876 | } |
| @@ -729,9 +897,9 @@ | ||
| 729 | 897 | |
| 730 | 898 | /* Register it immediately to avoid endless recursion. */ |
| 731 | 899 | $this->registry->register_object( $donation_fields ); |
| 732 | 900 | |
| 733 | - $fields = include( $this->get_path( 'includes' ) . 'fields/default-fields/donation-fields.php' ); | |
| 901 | + $fields = include $this->get_path( 'includes' ) . 'fields/default-fields/donation-fields.php'; | |
| 734 | 902 | |
| 735 | 903 | foreach ( $fields as $key => $args ) { |
| 736 | 904 | $donation_fields->register_field( new Charitable_Donation_Field( $key, $args ) ); |
| 737 | 905 | } |
| @@ -763,22 +931,22 @@ | ||
| 763 | 931 | * BEFORE the endpoint it builds on. In other words, move from |
| 764 | 932 | * most specific to least specific. |
| 765 | 933 | */ |
| 766 | 934 | $endpoints = new Charitable_Endpoints(); |
| 767 | - $endpoints->register( new Charitable_Campaign_Donation_Endpoint ); | |
| 768 | - $endpoints->register( new Charitable_Campaign_Widget_Endpoint ); | |
| 769 | - $endpoints->register( new Charitable_Campaign_Endpoint ); | |
| 770 | - $endpoints->register( new Charitable_Donation_Cancellation_Endpoint ); | |
| 771 | - $endpoints->register( new Charitable_Donation_Processing_Endpoint ); | |
| 772 | - $endpoints->register( new Charitable_Donation_Receipt_Endpoint ); | |
| 773 | - $endpoints->register( new Charitable_Email_Preview_Endpoint ); | |
| 774 | - $endpoints->register( new Charitable_Email_Verification_Endpoint ); | |
| 775 | - $endpoints->register( new Charitable_Forgot_Password_Endpoint ); | |
| 776 | - $endpoints->register( new Charitable_Reset_Password_Endpoint ); | |
| 777 | - $endpoints->register( new Charitable_Registration_Endpoint ); | |
| 778 | - $endpoints->register( new Charitable_Login_Endpoint ); | |
| 779 | - $endpoints->register( new Charitable_Profile_Endpoint ); | |
| 780 | - $endpoints->register( new Charitable_Webhook_Listener_Endpoint ); | |
| 935 | + $endpoints->register( new Charitable_Campaign_Donation_Endpoint() ); | |
| 936 | + $endpoints->register( new Charitable_Campaign_Widget_Endpoint() ); | |
| 937 | + $endpoints->register( new Charitable_Campaign_Endpoint() ); | |
| 938 | + $endpoints->register( new Charitable_Donation_Cancellation_Endpoint() ); | |
| 939 | + $endpoints->register( new Charitable_Donation_Processing_Endpoint() ); | |
| 940 | + $endpoints->register( new Charitable_Donation_Receipt_Endpoint() ); | |
| 941 | + $endpoints->register( new Charitable_Email_Preview_Endpoint() ); | |
| 942 | + $endpoints->register( new Charitable_Email_Verification_Endpoint() ); | |
| 943 | + $endpoints->register( new Charitable_Forgot_Password_Endpoint() ); | |
| 944 | + $endpoints->register( new Charitable_Reset_Password_Endpoint() ); | |
| 945 | + $endpoints->register( new Charitable_Registration_Endpoint() ); | |
| 946 | + $endpoints->register( new Charitable_Login_Endpoint() ); | |
| 947 | + $endpoints->register( new Charitable_Profile_Endpoint() ); | |
| 948 | + $endpoints->register( new Charitable_Webhook_Listener_Endpoint() ); | |
| 781 | 949 | |
| 782 | 950 | $this->registry->register_object( $endpoints ); |
| 783 | 951 | } |
| 784 | 952 | |
| @@ -792,9 +960,9 @@ | ||
| 792 | 960 | * |
| 793 | 961 | * @param string $class The type of class to be retrieved. |
| 794 | 962 | * @return object |
| 795 | 963 | */ |
| 796 | - public function get_registered_object( $class ) { | |
| 964 | + public function get_registered_object( $class ) { // phpcs:ignore | |
| 797 | 965 | return $this->registry->get( $class ); |
| 798 | 966 | } |
| 799 | 967 | |
| 800 | 968 | /** |
| @@ -845,8 +1013,9 @@ | ||
| 845 | 1013 | /** |
| 846 | 1014 | * Filter the array of available Charitable table classes. |
| 847 | 1015 | * |
| 848 | 1016 | * @since 1.0.0 |
| 1017 | + * @version 1.8.1 | |
| 849 | 1018 | * |
| 850 | 1019 | * @param array $tables List of tables as a key=>value array. |
| 851 | 1020 | */ |
| 852 | 1021 | return apply_filters( |
| @@ -851,11 +1020,13 @@ | ||
| 851 | 1020 | */ |
| 852 | 1021 | return apply_filters( |
| 853 | 1022 | 'charitable_db_tables', |
| 854 | 1023 | array( |
| 855 | - 'campaign_donations' => 'Charitable_Campaign_Donations_DB', | |
| 856 | - 'donors' => 'Charitable_Donors_DB', | |
| 857 | - 'donormeta' => 'Charitable_Donormeta_DB', | |
| 1024 | + 'campaign_donations' => 'Charitable_Campaign_Donations_DB', | |
| 1025 | + 'donors' => 'Charitable_Donors_DB', | |
| 1026 | + 'donormeta' => 'Charitable_Donormeta_DB', | |
| 1027 | + 'donation_activities' => 'Charitable_Donation_Activities_DB', | |
| 1028 | + 'campaign_activities' => 'Charitable_Campaign_Activities_DB', | |
| 858 | 1029 | ) |
| 859 | 1030 | ); |
| 860 | 1031 | } |
| 861 | 1032 | |
| @@ -886,14 +1057,14 @@ | ||
| 886 | 1057 | * or just the current site. Multisite only. Default is false. |
| 887 | 1058 | * @return void |
| 888 | 1059 | */ |
| 889 | 1060 | public function activate( $network_wide = false ) { |
| 890 | - require_once( $this->get_path( 'includes' ) . 'plugin/class-charitable-install.php' ); | |
| 1061 | + require_once $this->get_path( 'includes' ) . 'plugin/class-charitable-install.php'; | |
| 891 | 1062 | |
| 892 | 1063 | if ( is_multisite() && $network_wide ) { |
| 893 | 1064 | global $wpdb; |
| 894 | 1065 | |
| 895 | - foreach ( $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" ) as $blog_id ) { | |
| 1066 | + foreach ( $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" ) as $blog_id ) { // phpcs:ignore | |
| 896 | 1067 | switch_to_blog( $blog_id ); |
| 897 | 1068 | new Charitable_Install( $this->includes_path ); |
| 898 | 1069 | restore_current_blog(); |
| 899 | 1070 | } |
| @@ -901,9 +1072,12 @@ | ||
| 901 | 1072 | new Charitable_Install( $this->includes_path ); |
| 902 | 1073 | } |
| 903 | 1074 | |
| 904 | 1075 | // create or update the install date for future reference. |
| 905 | - update_option( 'wpcharitable_activated_datetime', current_time( 'timestamp' ) ); | |
| 1076 | + update_option( 'wpcharitable_activated_datetime', current_time( 'timestamp' ) ); // phpcs:ignore WordPress.DateTime.CurrentTimeTimestamp.Requested | |
| 1077 | + | |
| 1078 | + // Set initial timestamps for rotating menu items if they're already installed | |
| 1079 | + $this->set_initial_rotating_menu_timestamps(); | |
| 906 | 1080 | } |
| 907 | 1081 | |
| 908 | 1082 | /** |
| 909 | 1083 | * Runs on plugin deactivation. |
| @@ -914,9 +1088,9 @@ | ||
| 914 | 1088 | * |
| 915 | 1089 | * @return void |
| 916 | 1090 | */ |
| 917 | 1091 | public function deactivate() { |
| 918 | - require_once( $this->get_path( 'includes' ) . 'plugin/class-charitable-uninstall.php' ); | |
| 1092 | + require_once $this->get_path( 'includes' ) . 'plugin/class-charitable-uninstall.php'; | |
| 919 | 1093 | new Charitable_Uninstall(); |
| 920 | 1094 | } |
| 921 | 1095 | |
| 922 | 1096 | /** |
| @@ -926,11 +1100,11 @@ | ||
| 926 | 1100 | * |
| 927 | 1101 | * @return void |
| 928 | 1102 | */ |
| 929 | 1103 | public function do_charitable_actions() { |
| 930 | - if ( isset( $_REQUEST['charitable_action'] ) ) { | |
| 1104 | + if ( isset( $_REQUEST['charitable_action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended | |
| 931 | 1105 | |
| 932 | - $action = $_REQUEST['charitable_action']; | |
| 1106 | + $action = esc_attr( $_REQUEST['charitable_action'] ); // phpcs:ignore | |
| 933 | 1107 | |
| 934 | 1108 | /** |
| 935 | 1109 | * Handle Charitable action. |
| 936 | 1110 | * |
| @@ -1006,9 +1180,9 @@ | ||
| 1006 | 1180 | * |
| 1007 | 1181 | * @param mixed $object Object to be registered. |
| 1008 | 1182 | * @return void |
| 1009 | 1183 | */ |
| 1010 | - public function register_object( $object ) { | |
| 1184 | + public function register_object( $object ) { // phpcs:ignore | |
| 1011 | 1185 | charitable_get_deprecated()->deprecated_function( |
| 1012 | 1186 | __METHOD__, |
| 1013 | 1187 | '1.5.0', |
| 1014 | 1188 | 'charitable()->registry()->register_object()' |
| @@ -1118,18 +1292,8 @@ | ||
| 1118 | 1292 | if ( class_exists( 'Charitable_Gateways' ) && class_exists( 'Charitable_Gateway_Stripe_AM' ) && ! Charitable_Gateways::get_instance()->is_active_gateway( Charitable_Gateway_Stripe_AM::get_gateway_id() ) ) { |
| 1119 | 1293 | return false; |
| 1120 | 1294 | } |
| 1121 | 1295 | |
| 1122 | - // check for stripe addon | |
| 1123 | - | |
| 1124 | - // if ( in_array('charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option('active_plugins' ) ) ) ) { | |
| 1125 | - // return false; | |
| 1126 | - // } | |
| 1127 | - | |
| 1128 | - // if ( class_exists( 'Charitable_Stripe' ) ) { | |
| 1129 | - // return false; | |
| 1130 | - // } | |
| 1131 | - | |
| 1132 | 1296 | return true; |
| 1133 | 1297 | } |
| 1134 | 1298 | |
| 1135 | 1299 | /** |
| @@ -1140,9 +1304,9 @@ | ||
| 1140 | 1304 | * @return boolean |
| 1141 | 1305 | */ |
| 1142 | 1306 | public function is_stripe_connect_addon() { |
| 1143 | 1307 | |
| 1144 | - if ( in_array('charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option('active_plugins' ) ) ) ) { | |
| 1308 | + if ( in_array( 'charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { // phpcs:ignore | |
| 1145 | 1309 | return true; |
| 1146 | 1310 | } |
| 1147 | 1311 | |
| 1148 | 1312 | return false; |
| @@ -1152,10 +1316,11 @@ | ||
| 1152 | 1316 | * Action links for the plugins page. |
| 1153 | 1317 | * |
| 1154 | 1318 | * @since 1.7.0 |
| 1155 | 1319 | * |
| 1156 | - * @param array $actions An array of existing actions. | |
| 1157 | - * @param string $plugin_file The plugin file we are modifying. | |
| 1320 | + * @param array $actions An array of existing actions. | |
| 1321 | + * @param string $plugin_file The plugin file we are modifying. | |
| 1322 | + * @param boolean $action_links An array of action links to add. | |
| 1158 | 1323 | * @return array An array of action links. |
| 1159 | 1324 | */ |
| 1160 | 1325 | public function plugin_action_links( $actions, $plugin_file, $action_links = false ) { |
| 1161 | 1326 | |
| @@ -1162,15 +1327,15 @@ | ||
| 1162 | 1327 | if ( ! charitable_is_pro() ) : |
| 1163 | 1328 | |
| 1164 | 1329 | // if this isn't pro, add the upgrade link which is visible on the plugins page until the plugin name. |
| 1165 | 1330 | |
| 1166 | - $action_links = [ | |
| 1167 | - 'proupgrade' => [ | |
| 1331 | + $action_links = array( | |
| 1332 | + 'proupgrade' => array( | |
| 1168 | 1333 | // Translators: This is an action link users can click to purchase a license for All in One SEO Pro. |
| 1169 | 1334 | 'label' => __( 'Upgrade to Pro', 'charitable' ), |
| 1170 | 1335 | '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', |
| 1171 | - ] | |
| 1172 | - ]; | |
| 1336 | + ), | |
| 1337 | + ); | |
| 1173 | 1338 | |
| 1174 | 1339 | endif; |
| 1175 | 1340 | |
| 1176 | 1341 | if ( isset( $actions['edit'] ) ) { |
| @@ -1184,23 +1349,24 @@ | ||
| 1184 | 1349 | * Parse the action links. |
| 1185 | 1350 | * |
| 1186 | 1351 | * @since 1.7.0 |
| 1187 | 1352 | * |
| 1188 | - * @param array $actions | |
| 1189 | - * @param string $pluginFile | |
| 1190 | - * @param | |
| 1353 | + * @param array $actions An array of existing actions. | |
| 1354 | + * @param string $plugin_file The plugin file we are modifying. | |
| 1355 | + * @param array $action_links An array of action links to add. | |
| 1356 | + * @param string $position The position to add the action links. | |
| 1191 | 1357 | * @return array |
| 1192 | 1358 | */ |
| 1193 | - protected function parse_action_links( $actions, $pluginFile, $action_links = [], $position = 'after' ) { | |
| 1359 | + protected function parse_action_links( $actions, $plugin_file, $action_links = array(), $position = 'after' ) { | |
| 1194 | 1360 | if ( empty( $this->plugin ) ) { |
| 1195 | - $this->plugin = CHARTIABLE_PLUGIN_BASENAME; | |
| 1361 | + $this->plugin = CHARITABLE_PLUGIN_BASENAME; | |
| 1196 | 1362 | } |
| 1197 | 1363 | |
| 1198 | - if ( $this->plugin === $pluginFile && ! empty( $action_links ) ) { | |
| 1364 | + if ( $this->plugin === $plugin_file && ! empty( $action_links ) ) { | |
| 1199 | 1365 | foreach ( $action_links as $key => $value ) { |
| 1200 | - $link = [ | |
| 1201 | - $key => '<a href="' . $value['url'] . '">' . $value['label'] . '</a>' | |
| 1202 | - ]; | |
| 1366 | + $link = array( | |
| 1367 | + $key => '<a href="' . $value['url'] . '">' . $value['label'] . '</a>', | |
| 1368 | + ); | |
| 1203 | 1369 | |
| 1204 | 1370 | $actions = 'after' === $position ? array_merge( $actions, $link ) : array_merge( $link, $actions ); |
| 1205 | 1371 | } |
| 1206 | 1372 | } |
| @@ -1216,11 +1382,11 @@ | ||
| 1216 | 1382 | * @return void |
| 1217 | 1383 | */ |
| 1218 | 1384 | public function setup_licensing() { |
| 1219 | 1385 | charitable_get_helper( 'licenses' )->register_licensed_product( |
| 1220 | - Charitable::NAME, // . ' Pro', | |
| 1221 | - Charitable::AUTHOR, | |
| 1222 | - Charitable::VERSION, | |
| 1386 | + self::NAME, | |
| 1387 | + self::AUTHOR, | |
| 1388 | + self::VERSION, | |
| 1223 | 1389 | __FILE__ |
| 1224 | 1390 | ); |
| 1225 | 1391 | } |
| 1226 | 1392 | |
| @@ -1227,16 +1393,14 @@ | ||
| 1227 | 1393 | /** |
| 1228 | 1394 | * Deativates and/or warnings about any Charitable verison conflicts. |
| 1229 | 1395 | * |
| 1230 | 1396 | * @since 1.7.0 |
| 1231 | - * | |
| 1232 | - * @return null | |
| 1233 | 1397 | */ |
| 1234 | 1398 | public function check_for_version_conflicts() { |
| 1235 | 1399 | |
| 1236 | - // Check for Charitable Stripe < 1.5.0 | |
| 1237 | - if ( in_array( 'charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { | |
| 1238 | - if ( class_exists( 'Charitable_Stripe') && version_compare( Charitable_Stripe::VERSION, '1.5.0', '<' ) ) { | |
| 1400 | + // Check for Charitable Stripe < 1.5.0. | |
| 1401 | + if ( in_array( 'charitable-stripe/charitable-stripe.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { // phpcs:ignore | |
| 1402 | + if ( class_exists( 'Charitable_Stripe' ) && version_compare( Charitable_Stripe::VERSION, '1.5.0', '<' ) ) { // phpcs:ignore | |
| 1239 | 1403 | // manually deactivate plugin. |
| 1240 | 1404 | $found = false; |
| 1241 | 1405 | $current = get_option( 'active_plugins', array() ); |
| 1242 | 1406 | $key = array_search( 'charitable-stripe/charitable-stripe.php', $current, true ); |
| @@ -1245,21 +1409,78 @@ | ||
| 1245 | 1409 | |
| 1246 | 1410 | unset( $current[ $key ] ); |
| 1247 | 1411 | update_option( 'active_plugins', $current ); |
| 1248 | 1412 | |
| 1249 | - $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' ); | |
| 1413 | + // translators: %s is the version number. | |
| 1414 | + $message = sprintf( __( '<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> %s 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' ), Charitable_Stripe::VERSION ); | |
| 1250 | 1415 | |
| 1251 | - wp_die( $message . ' <a href="' . admin_url( 'plugins.php' ) . '">Click here to return to the plugins screen.</a>' ); | |
| 1416 | + wp_die( $message . ' <a href="' . admin_url( 'plugins.php' ) . '">Click here to return to the plugins screen.</a>' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped | |
| 1252 | 1417 | } |
| 1253 | - // charitable_get_notices()->add_error( $message ); | |
| 1254 | - add_option( 'chartiable_version_warning', $message ); | |
| 1418 | + add_option( 'charitable_version_warning', $message ); | |
| 1255 | 1419 | } else { |
| 1256 | - delete_option( 'chartiable_version_warning' ); | |
| 1420 | + delete_option( 'charitable_version_warning' ); | |
| 1257 | 1421 | } |
| 1258 | 1422 | } |
| 1259 | 1423 | } |
| 1260 | 1424 | |
| 1425 | + /** | |
| 1426 | + * Set initial timestamps for rotating menu items if they're already installed. | |
| 1427 | + * This ensures the 7-day countdown starts immediately for already-installed plugins. | |
| 1428 | + * | |
| 1429 | + * @since 1.8.8 | |
| 1430 | + * | |
| 1431 | + * @return void | |
| 1432 | + */ | |
| 1433 | + private function set_initial_rotating_menu_timestamps() { | |
| 1434 | + // Get the rotating menu items configuration | |
| 1435 | + $admin_pages = Charitable_Admin_Pages::get_instance(); | |
| 1261 | 1436 | |
| 1437 | + try { | |
| 1438 | + $reflection = new ReflectionClass( $admin_pages ); | |
| 1439 | + $method = $reflection->getMethod( 'get_marketing_rotation_items' ); | |
| 1440 | + $method->setAccessible( true ); | |
| 1441 | + $items = $method->invoke( $admin_pages ); | |
| 1442 | + } catch ( ReflectionException $e ) { | |
| 1443 | + // Fallback if reflection fails in future PHP versions | |
| 1444 | + $items = array(); | |
| 1445 | + } | |
| 1446 | + | |
| 1447 | + $current_time = time(); | |
| 1448 | + | |
| 1449 | + foreach ( $items as $item ) { | |
| 1450 | + $option_name = $item['option_name'] ?? ''; | |
| 1451 | + $option_key = $item['option_key'] ?? ''; | |
| 1452 | + $plugin_file = $item['plugin_file'] ?? ''; | |
| 1453 | + | |
| 1454 | + if ( empty( $option_name ) || empty( $plugin_file ) ) { | |
| 1455 | + continue; | |
| 1456 | + } | |
| 1457 | + | |
| 1458 | + // Check if the plugin is installed (file exists in plugins directory) | |
| 1459 | + $plugin_path = WP_PLUGIN_DIR . '/' . $plugin_file; | |
| 1460 | + if ( file_exists( $plugin_path ) ) { | |
| 1461 | + // Plugin is installed, check if we already have a timestamp | |
| 1462 | + $existing_option = get_option( $option_name ); | |
| 1463 | + $has_timestamp = false; | |
| 1464 | + | |
| 1465 | + if ( is_array( $existing_option ) ) { | |
| 1466 | + $has_timestamp = isset( $existing_option[ $option_key ] ) && is_numeric( $existing_option[ $option_key ] ); | |
| 1467 | + } elseif ( is_numeric( $existing_option ) ) { | |
| 1468 | + $has_timestamp = true; | |
| 1469 | + } | |
| 1470 | + | |
| 1471 | + // Only set timestamp if one doesn't already exist | |
| 1472 | + if ( ! $has_timestamp ) { | |
| 1473 | + if ( is_array( $existing_option ) ) { | |
| 1474 | + $existing_option[ $option_key ] = $current_time; | |
| 1475 | + update_option( $option_name, $existing_option ); | |
| 1476 | + } else { | |
| 1477 | + update_option( $option_name, array( $option_key => $current_time ) ); | |
| 1478 | + } | |
| 1479 | + } | |
| 1480 | + } | |
| 1481 | + } | |
| 1482 | + } | |
| 1262 | 1483 | } |
| 1263 | 1484 | |
| 1264 | 1485 | $charitable = new Charitable(); |
| 1265 | 1486 | |