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