load_dependencies();
$this->donation_actions = new Charitable_Donation_Admin_Actions();
// Initialize About page.
new Charitable_About();
do_action( 'charitable_admin_loaded' );
add_action( 'wp_ajax_charitable_lite_settings_upgrade', array( $this, 'dismiss_lite_cta' ) );
add_action( 'wp_ajax_charitable_lite_reports_upgrade', array( $this, 'dismiss_lite_reports_cta' ) );
// Addon management AJAX handlers.
add_action( 'wp_ajax_charitable_install_addon', array( $this, 'install_addon' ) );
add_action( 'wp_ajax_charitable_activate_addon', array( $this, 'activate_addon' ) );
add_action( 'wp_ajax_charitable_deactivate_addon', array( $this, 'deactivate_addon' ) );
// Dedicated About/Addons handlers to avoid conflicts with legacy hooks.
add_action( 'wp_ajax_charitable_addons_install_wporg', array( $this, 'install_addon' ) );
add_action( 'wp_ajax_charitable_addons_activate', array( $this, 'activate_addon' ) );
add_action( 'wp_ajax_charitable_addons_deactivate', array( $this, 'deactivate_addon' ) );
add_filter( 'post_row_actions', array( $this, 'campaign_action_row' ), 10, 2 );
add_filter( 'get_edit_post_link', array( $this, 'campaign_link' ), 99, 3 );
add_filter( 'preview_post_link', array( $this, 'campaign_preview_link' ), 10, 2 );
add_filter( 'admin_init', array( $this, 'update_dashboard_url' ), 10 );
/* third party plugins */
add_filter( 'elementor/settings/controls/checkbox_list_cpt/post_type_objects', array( $this, 'elementor_post_types' ), 10, 1 );
}
/**
* Redirect from the old dashboard to the new, unless legacy campaigns are being used and defined.
*
* @since 1.8.1
* @version 1.8.4
*
* @return void
*/
public function update_dashboard_url() {
global $pagenow;
if ( function_exists( 'charitable_use_legacy_dashboard' ) && charitable_use_legacy_dashboard() ) {
return;
}
if ( $pagenow === 'admin.php' && isset( $_GET['page'] ) && $_GET['page'] === 'charitable' ) { // phpcs:ignore
// Check and see if this has to do with onboarding.
if ( isset( $_GET['wpchar_lite'] ) && isset( $_GET['setup'] ) ) { // phpcs:ignore
switch ( sanitize_text_field( wp_unslash( $_GET['setup'] ) ) ) { // phpcs:ignore
case 'welcome':
if ( empty( $_GET['wpchar_lite'] ) || 'lite' !== $_GET['wpchar_lite'] ) { // phpcs:ignore
wp_safe_redirect( admin_url( 'admin.php?page=charitable-dashboard' ) );
exit;
}
break;
case 'return':
// The wizard finishes by POSTing the user's choices from the
// hosted app straight into this admin, cross-site and
// top-level. Browsers drop that body when a SameSite=Lax auth
// cookie forces a trip through wp-login.php, or when a
// canonical / http-to-https / security-plugin redirect turns
// the POST into a GET. The user is logged in the whole time;
// the cookie simply did not ride along.
// Applying onboarding choices writes plugin options and
// third-party activation flags, so it is an administrator
// action. This previously ran for any user who could reach
// wp-admin.
if ( ! charitable_current_user_can( 'administrator' ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=charitable-dashboard' ) );
exit;
}
$charitable_return_data = wp_unslash( $_POST ); // phpcs:ignore
if ( empty( $charitable_return_data ) && is_admin() ) {
// Body dropped in transit. Recover the choices with a
// server-to-server read: no browser, no cookies, no
// redirects, so nothing that drops the POST applies.
$charitable_return_data = $this->pull_onboarding_return_data();
}
if ( empty( $charitable_return_data ) ) {
wp_safe_redirect( admin_url( 'admin.php?page=charitable&wpchar_lite=lite&setup=welcome&resume=true&lostconnection=1' ) );
exit;
}
$this->process_onboarding_return_data( $charitable_return_data );
wp_safe_redirect( admin_url( 'admin.php?page=charitable-setup&setup=1' ) );
exit;
case 'cancelled':
// Either user is going "back" to the checklist page or (if the checklist is disabled) the welcome page.
// https://mydomain.com/wp-admin/admin.php?page=charitable&wpchar_lite=lite&setup=cancelled.
$checklist_class = Charitable_Checklist::get_instance();
$checklist_possible = $checklist_class->is_checklist_skipped() || $checklist_class->is_checklist_completed();
$welcome_go_back_url = $checklist_possible ? admin_url( 'admin.php?page=charitable-dashboard' ) : admin_url( 'admin.php?page=charitable-setup-checklist' );
// Clear the transient.
delete_transient( 'charitable_activation_redirect' );
// Clear the option.
delete_option( 'charitable_started_onboarding' );
wp_safe_redirect( $welcome_go_back_url );
exit;
default:
wp_safe_redirect( admin_url( 'admin.php?page=charitable-dashboard' ) );
exit;
}
} else {
wp_safe_redirect( admin_url( 'admin.php?page=charitable-dashboard' ) );
exit;
}
}
}
/**
* Apply a set of onboarding choices handed back by the setup wizard.
*
* Extracted verbatim from the `setup=return` branch so the same logic
* serves both routes into it: the cross-site POST the wizard sends, and
* the server-to-server pull used when that POST body is dropped. Keeping
* one implementation is the point - a second decoder would drift.
*
* Expects the same keys and encodings as the POST: `meta`, `pm`,
* `features`, `plugins` and `license_key` base64-encoded, and `template`
* plus the `campaign_*` fields plain. Every field is optional.
*
* @since 1.8.12.4
*
* @param array $data Onboarding fields, already unslashed.
* @return void
*/
private function process_onboarding_return_data( $data ) {
if ( ! is_array( $data ) ) {
return;
}
$charitable_field = function ( $key ) use ( $data ) {
return isset( $data[ $key ] ) && ! is_array( $data[ $key ] )
? sanitize_text_field( $data[ $key ] )
: '';
};
$plugins = '' !== $charitable_field( 'plugins' ) ? base64_decode( $charitable_field( 'plugins' ) ) : '';
$features = '' !== $charitable_field( 'features' ) ? base64_decode( $charitable_field( 'features' ) ) : '';
$meta = '' !== $charitable_field( 'meta' ) ? base64_decode( $charitable_field( 'meta' ) ) : '';
$pm = '' !== $charitable_field( 'pm' ) ? base64_decode( $charitable_field( 'pm' ) ) : '';
$license_key = '' !== $charitable_field( 'license_key' ) ? base64_decode( $charitable_field( 'license_key' ) ) : '';
// process meta.
if ( ! empty( $meta ) ) {
$meta = str_replace( '\\"', '"', $meta );
if ( ! empty( $meta ) ) {
$meta = json_decode( $meta, true );
}
}
// process plugins.
if ( ! empty( $plugins ) ) {
$plugins = json_decode( $plugins );
$plugins = str_replace( array( '"', '[', ']' ), '', $plugins );
if ( ! empty( $plugins ) ) {
$plugins = explode( ',', $plugins );
}
}
// process payment methods.
// NOTE: the inner guard tests $plugins, not $pm. That is how this has
// always behaved, so it is preserved here rather than quietly changed
// during a refactor whose whole value is being behaviour-identical.
// Worth fixing on its own, separately.
if ( ! empty( $pm ) ) {
$pm = json_decode( $pm );
if ( $pm ) {
$pm = str_replace( array( '"', '[', ']' ), '', $pm );
if ( ! empty( $plugins ) ) {
$pm = explode( ',', $pm );
}
}
}
// process features.
if ( ! empty( $features ) ) {
$features = json_decode( $features );
$features = str_replace( array( '"', '[', ']' ), '', $features );
if ( ! empty( $features ) ) {
$features = explode( ',', $features );
}
}
// clean license (remove quotes).
$license_key = str_replace( '"', '', $license_key );
// process campaign.
$campaign = array(
'template' => $charitable_field( 'template' ),
'title' => $charitable_field( 'campaign_title' ),
'description' => $charitable_field( 'campaign_description' ),
'goal' => $charitable_field( 'campaign_goal' ),
'end_date' => $charitable_field( 'campaign_end_date' ),
);
// store server side setups.
$serverside = new Charitable_Setup();
$serverside->store_meta( $meta );
$serverside->store_plugins( $plugins );
$serverside->store_features( $features );
$serverside->store_payment_methods( $pm );
$serverside->store_campaign( $campaign );
// Guarded, so a payload without a licence key never overwrites one
// already stored. The pull payload deliberately never carries one.
if ( $license_key ) {
$serverside->store_license_key( $license_key );
}
// If this is a select few addons that we need to disable their auto-activation, do so.
if ( ! empty( $plugins ) && is_array( $plugins ) ) {
foreach ( $plugins as $plugin ) {
if ( $plugin === 'all-in-one-seo-pack' ) {
update_option( 'aioseo_activation_redirect', true );
} elseif ( $plugin === 'wp-mail-smtp' ) {
update_option( 'wp_mail_smtp_activation_prevent_redirect', true );
}
}
}
// add a transient to indicate that the server side onboarding has moved to the plugin.
set_transient( 'charitable_ss_onboarding', 1, 0 );
delete_option( 'charitable_started_onboarding' );
}
/**
* Read the onboarding choices back from the wizard, server to server.
*
* Used only when the wizard's cross-site POST arrived with no body. A
* plain server-side GET has no browser, no cookies and no redirects, so
* none of the mechanisms that drop that POST can affect it.
*
* Returns an empty array on any doubt at all - disabled, missing
* helpers, transport error, non-200, unparseable body, or a payload that
* does not say `status: ok`. The caller then falls back to exactly the
* behaviour that shipped before this existed.
*
* @since 1.8.12.4
*
* @return array Onboarding fields, or an empty array.
*/
private function pull_onboarding_return_data() {
// Field kill switch: both of these turn the fallback off without
// needing a release, reverting to the previous behaviour exactly.
if ( ! apply_filters( 'charitable_onboarding_pull_enabled', true ) ) {
return array();
}
if ( defined( 'CHARITABLE_ONBOARDING_DISABLE_PULL' ) && CHARITABLE_ONBOARDING_DISABLE_PULL ) {
return array();
}
if ( ! function_exists( 'charitable_onboarding_app_url' ) || ! function_exists( 'charitable_get_site_token' ) ) {
return array();
}
$site_token = charitable_get_site_token();
if ( empty( $site_token ) ) {
return array();
}
$response = wp_remote_get(
charitable_onboarding_app_url() . '/setup-wizard-charitable_lite/pull/' . rawurlencode( $site_token ),
array(
'timeout' => 10,
'sslverify' => true,
)
);
if ( is_wp_error( $response ) || 200 !== (int) wp_remote_retrieve_response_code( $response ) ) {
return array();
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( ! is_array( $body ) || empty( $body['status'] ) || 'ok' !== $body['status'] ) {
return array();
}
return $body;
}
/**
* Returns and/or create the single instance of this class.
*
* @since 1.2.0
*
* @return Charitable_Admin
*/
public static function get_instance() {
if ( is_null( self::$instance ) ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Include admin-only files.
*
* @since 1.0.0
*
* @return void
*/
private function load_dependencies() {
$admin_dir = charitable()->get_path( 'includes' ) . 'admin/';
require_once $admin_dir . 'charitable-core-admin-functions.php';
require_once $admin_dir . 'campaigns/charitable-admin-campaign-hooks.php';
require_once $admin_dir . 'dashboard/class-charitable-dashboard-ajax.php';
require_once $admin_dir . 'charitable-dashboard-hooks.php';
require_once $admin_dir . 'dashboard-widgets/charitable-dashboard-widgets-hooks.php';
require_once $admin_dir . 'donations/charitable-admin-donation-hooks.php';
require_once $admin_dir . 'settings/charitable-settings-admin-hooks.php';
// Security hooks are now loaded in charitable.php to ensure CAPTCHA works on frontend.
// require_once $admin_dir . 'security/charitable-security-hooks.php';
require_once $admin_dir . 'activities/charitable-admin-activity-hooks.php';
require_once $admin_dir . 'reports/charitable-core-reports-functions.php';
require_once $admin_dir . 'reports/charitable-admin-reports-hooks.php';
require_once $admin_dir . 'plugins/class-charitable-admin-plugins-third-party.php';
require_once $admin_dir . 'tools/charitable-tools-admin-hooks.php';
require_once $admin_dir . 'growth-tools/charitable-growth-tools-admin-hooks.php';
require_once $admin_dir . 'onboarding/charitable-onboarding-admin-hooks.php';
require_once $admin_dir . 'tracking/charitable-tracking-admin-hooks.php';
require_once $admin_dir . 'smtp/charitable-smtp-admin-hooks.php';
require_once $admin_dir . 'class-charitable-about.php';
require_once $admin_dir . 'charitable-admin-addons-functions.php';
require_once $admin_dir . 'privacy-compliance/charitable-privacy-compliance-admin-hooks.php';
require_once $admin_dir . 'intergrations/charitable-privacy-compliance-admin-hooks.php';
require_once $admin_dir . 'intergrations/charitable-backups-admin-hooks.php';
require_once $admin_dir . 'intergrations/charitable-seo-admin-hooks.php';
require_once $admin_dir . 'intergrations/charitable-automation-admin-hooks.php';
}
/**
* Get Charitable_Donation_Admin_Actions class.
*
* @since 1.5.0
*
* @return Charitable_Donation_Admin_Actions
*/
public function get_donation_actions() {
return $this->donation_actions;
}
/**
* Do an admin action.
*
* @since 1.5.0
*
* @return boolean|WP_Error WP_Error in case of error. Mixed results if the action was performed.
*/
public function maybe_do_admin_action() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! array_key_exists( 'charitable_admin_action', $_GET ) ) {
return false;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Check for required keys only
if ( count( array_diff( array( 'action_type', '_nonce', 'object_id' ), array_keys( $_GET ) ) ) ) {
return new WP_Error( __( 'Action could not be executed.', 'charitable' ) );
}
if ( ! isset( $_GET['_nonce'] ) || ! wp_verify_nonce( $_GET['_nonce'], 'donation_action' ) ) { // phpcs:ignore.
return new WP_Error( __( 'Action could not be executed. Nonce check failed.', 'charitable' ) );
}
if ( ! isset( $_GET['action_type'] ) || 'donation' !== $_GET['action_type'] ) {
return new WP_Error( __( 'Action from an unknown action type executed.', 'charitable' ) );
}
return $this->donation_actions->do_action( esc_html( $_GET['charitable_admin_action'] ), esc_html( $_GET['object_id'] ) ); // phpcs:ignore.
}
/**
* Loads admin-only scripts and stylesheets.
*
* @since 1.0.0
* @version 1.8.8.6
*
* @return void
*/
public function admin_enqueue_scripts() {
$min = charitable_get_min_suffix(); // 1.8.3
$version = charitable_is_break_cache() ? charitable()->get_version() . '.' . time() : charitable()->get_version();
$assets_dir = charitable()->get_path( 'assets', false );
$localized_vars = array(
'suggested_amount_placeholder' => __( 'Amount', 'charitable' ),
'suggested_amount_description_placeholder' => __( 'Optional Description', 'charitable' ),
'ajax_url' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'charitable_admin_nonce' ),
'heads_up' => __( 'Heads Up!', 'charitable' ),
'square_legacy_modal_message' => __( 'Square (Legacy) is currently active. Activating the Square (Core) payment method will deactivate the Square (Legacy) payment and you will need to reconnect your Square account.
Click Ok to deactivate Square (Legacy) and activate Square (Core) payment. Click Cancel to keep Square (Legacy) payment active.
Read our documentation', 'charitable' ),
'square_core_modal_message' => __( 'Square (Core) is currently active. Activating the Square (Legacy) payment method will deactivate the Square (Core) payment and you will need to reconnect your Square account.
Click Ok to deactivate Square (Core) and activate Square (Legacy) payment. Click Cancel to keep Square (Core) payment active.
Read our documentation', 'charitable' ),
'oops' => __( 'Oops!', 'charitable' ),
'square_legacy_switch_error' => __( 'There was an error switching the payment gateways. Please try again.', 'charitable' ),
'ok' => __( 'OK', 'charitable' ),
'cancel' => __( 'Cancel', 'charitable' ),
'square_legacy_active' => charitable_get_helper( 'gateways' )->is_active_gateway( 'square' ),
'square_core_active' => charitable_get_helper( 'gateways' )->is_active_gateway( 'square_core' ),
);
/* Menu styles are loaded everywhere in the WordPress dashboard. */
wp_register_style(
'charitable-admin-menu',
$assets_dir . 'css/admin/charitable-admin-menu' . $min . '.css',
array(),
$version
);
wp_enqueue_style( 'charitable-admin-menu' );
wp_register_script(
'charitable-admin-pages-all',
$assets_dir . 'js/admin/charitable-admin-pages' . $min . '.js',
array( 'jquery' ),
$version,
false
);
wp_enqueue_script( 'charitable-admin-pages-all' );
/* Admin page styles are registered but only enqueued when necessary. */
wp_register_style(
'charitable-admin-pages',
$assets_dir . 'css/admin/charitable-admin-pages' . $min . '.css',
array(),
$version
);
/* The following styles are only loaded on Charitable screens. */
$screen = get_current_screen();
/* This check covers the category and tags pages, only load the main admin css (upgrade banner, etc.) */
if ( ! is_null( $screen ) && ( in_array( $screen->id, array( 'edit-campaign_category', 'edit-campaign_tag' ), true ) || ( in_array( $screen->base, array( 'edit-tags', 'edit-categories' ), true ) ) ) ) {
wp_register_style(
'charitable-admin',
$assets_dir . 'css/admin/charitable-admin-legacy' . $min . '.css',
array(),
$version
);
wp_enqueue_style( 'charitable-admin' );
wp_register_script(
'charitable-admin-notice',
$assets_dir . 'js/admin/charitable-admin-notice' . $min . '.js',
array( 'jquery' ),
$version,
false
);
}
// v 1.8.0.
wp_register_style(
'charitable-admin-2.0',
$assets_dir . 'css/admin/charitable-admin' . $min . '.css',
array(),
$version
);
wp_enqueue_style( 'charitable-admin-2.0' );
wp_enqueue_style(
'charitable-notifications-v2',
$assets_dir . 'css/admin/notifications-v2' . $min . '.css',
array(),
$version
);
wp_register_style(
'charitable-admin',
$assets_dir . 'css/admin/charitable-admin-legacy' . $min . '.css',
array(),
$version
);
wp_enqueue_style( 'charitable-admin' );
if ( ! is_null( $screen ) && in_array( $screen->id, charitable_get_charitable_screens() ) ) {
$dependencies = array( 'jquery-ui-datepicker', 'jquery-ui-tabs', 'jquery-ui-sortable' );
if ( 'donation' === $screen->id ) {
wp_register_script(
'accounting',
$assets_dir . 'js/libraries/accounting' . $min . '.js',
array( 'jquery' ),
$version,
true
);
$dependencies[] = 'accounting';
$localized_vars = array_merge(
$localized_vars,
array(
'currency_format_num_decimals' => esc_attr( charitable_get_currency_helper()->get_decimals() ),
'currency_format_decimal_sep' => esc_attr( charitable_get_currency_helper()->get_decimal_separator() ),
'currency_format_thousand_sep' => esc_attr( charitable_get_currency_helper()->get_thousands_separator() ),
'currency_format' => esc_attr( charitable_get_currency_helper()->get_accounting_js_format() ),
)
);
}
wp_register_script(
'charitable-admin',
$assets_dir . 'js/admin/charitable-admin' . $min . '.js',
$dependencies,
$version,
false
);
wp_enqueue_script( 'charitable-admin' );
// v 1.8.0.
wp_enqueue_style(
'jquery-confirm',
charitable()->get_path( 'directory', false ) . 'assets/lib/jquery.confirm/jquery-confirm.min.css',
null,
'3.3.4'
);
wp_enqueue_style(
'charitable-font-awesome',
charitable()->get_path( 'directory', false ) . 'assets/lib/font-awesome/font-awesome.min.css',
null,
'4.7.0'
);
wp_enqueue_script(
'jquery-confirm',
charitable()->get_path( 'directory', false ) . 'assets/lib/jquery.confirm/jquery-confirm.min.js',
array( 'jquery' ),
'3.3.4',
false
);
wp_enqueue_style(
'lity',
charitable()->get_path( 'directory', false ) . 'assets/lib/lity/lity.min.css',
null,
'3.0.0'
);
// Add custom CSS for lity image sizing
wp_add_inline_style( 'lity', '
.lity-image img {
max-width: 90vw !important;
max-height: 90vh !important;
width: auto !important;
height: auto !important;
margin: 0 auto !important;
}
.lity-image .lity-container {
max-width: 90vw !important;
max-height: 90vh !important;
}
' );
wp_enqueue_script(
'lity',
charitable()->get_path( 'directory', false ) . 'assets/lib/lity/lity.min.js',
array( 'jquery' ),
'3.0.0',
false
);
wp_register_script(
'charitable-admin-2.0',
$assets_dir . 'js/admin/charitable-admin-2.0' . $min . '.js',
$dependencies,
$version,
false
);
wp_enqueue_script( 'charitable-admin-2.0' );
/**
* Filter the admin Javascript vars.
*
* @since 1.0.0
*
* @param array $localized_vars The vars.
*/
$localized_vars = (array) apply_filters( 'charitable_localized_javascript_vars', $localized_vars );
wp_localize_script( 'charitable-admin', 'CHARITABLE', $localized_vars );
// Localize script for charitable-admin-2.0.js
wp_localize_script( 'charitable-admin-2.0', 'charitable_admin', array(
'autoshow_plugin_notifications' => charitable_get_autoshow_plugin_notifications(),
) );
/* color picker for admin settings */
wp_enqueue_script( 'wp-color-picker', false, false, false, true ); // phpcs:ignore.
wp_enqueue_style( 'wp-color-picker' );
} // end if
wp_enqueue_script(
'charitable-admin-utils',
charitable()->get_path( 'directory', false ) . "assets/js/admin/charitable-admin-utils{$min}.js",
array( 'jquery' ),
charitable()->get_version(),
false
);
// Register these scripts only for reports and dashboard pages.
if ( ! is_null( $screen ) && ( $screen->id === 'charitable_page_charitable-reports' || $screen->id === 'charitable_page_charitable-dashboard' ) ) {
// Specific styles for the "overview" and main reporting tabs.
if ( empty( $_GET['tab'] ) || ( ! empty( $_GET['tab'] ) && charitable_reports_allow_tab_load_scripts( strtolower( sanitize_text_field( wp_unslash( $_GET['tab'] ) ) ) ) ) ) { // phpcs:ignore
wp_register_script(
'charitable-apex-charts',
charitable()->get_path( 'assets', false ) . 'js/libraries/apexcharts.min.js',
array( 'jquery' ),
$version,
true
);
/**
* Use WordPress core's Moment.js library.
*
* WordPress core includes Moment.js and exposes it via wp_enqueue_script('moment').
* This library is required as a dependency for daterangepicker.min.js, which powers
* the date range picker functionality in the reporting interface.
*
* @see https://github.com/moment/moment
* @since 1.0.0
* @version 1.8.8.6
*/
wp_enqueue_script( 'moment' );
wp_register_script(
'charitable-report-date-range-picker',
charitable()->get_path( 'assets', false ) . 'js/libraries/daterangepicker.min.js',
array( 'jquery', 'moment' ),
$version,
true
);
wp_register_script(
'charitable-reporting',
$assets_dir . 'js/admin/charitable-admin-reporting' . $min . '.js',
array( 'jquery', 'charitable-apex-charts', 'charitable-report-date-range-picker' ),
$version,
true
);
wp_enqueue_style(
'charitable-report-date-range-picker',
charitable()->get_path( 'assets', false ) . 'css/libraries/daterangepicker.css',
null,
'4.7.0'
);
wp_enqueue_script( 'charitable-apex-charts' );
wp_enqueue_script( 'charitable-report-date-range-picker' );
wp_enqueue_script( 'charitable-reporting' );
} elseif ( ! empty( $_GET['tab'] ) && 'analytics' === $_GET['tab'] ) { // phpcs:ignore
// this loads a specific script for the analytics tab.
do_action( 'charitable_admin_enqueue_analytics_scripts' );
}
}
// Register v2 dashboard specific assets
if ( ! is_null( $screen ) && $screen->id === 'charitable_page_charitable-dashboard' && ! charitable_use_legacy_dashboard() ) {
// Register ApexCharts for the v2 dashboard chart
wp_register_script(
'charitable-apex-charts',
charitable()->get_path( 'assets', false ) . 'js/libraries/apexcharts.min.js',
array( 'jquery' ),
$version,
true
);
// Enqueue dashboard specific CSS
wp_enqueue_style(
'charitable-admin-dashboard',
charitable()->get_path( 'assets', false ) . 'css/admin/charitable-admin-dashboard.css',
array(),
charitable()->get_version()
);
// Enqueue dashboard specific JavaScript with ApexCharts dependency
wp_enqueue_script(
'charitable-admin-dashboard',
$assets_dir . 'js/admin/charitable-admin-dashboard.js',
array( 'jquery', 'charitable-apex-charts' ),
charitable()->get_version(),
true
);
// Enqueue ApexCharts
wp_enqueue_script( 'charitable-apex-charts' );
}
// Register these scripts only for checklist, onboarding, and similar pages.
if ( ! is_null( $screen ) && ( $screen->id === 'charitable_page_charitable-setup-checklist' ) ) {
// v 1.8.1.10.
wp_register_script(
'charitable-onboarding',
$assets_dir . 'js/admin/charitable-admin-onboarding' . $min . '.js',
array( 'jquery' ),
$version,
true
);
wp_enqueue_script( 'charitable-onboarding' );
}
wp_register_script(
'charitable-admin-plugins',
$assets_dir . 'js/plugins/charitable-admin-plugins' . $min . '.js',
array( 'jquery' ),
$version,
true
);
wp_enqueue_script( 'charitable-admin-plugins' );
wp_register_script(
'charitable-admin-notice',
$assets_dir . 'js/admin/charitable-admin-notice' . $min . '.js',
array( 'jquery' ),
$version,
false
);
wp_register_script(
'charitable-admin-media',
$assets_dir . 'js/admin/charitable-admin-media' . $min . '.js',
array( 'jquery' ),
$version,
false
);
wp_register_script(
'lean-modal',
$assets_dir . 'js/libraries/leanModal' . $min . '.js',
array( 'jquery' ),
$version,
true
);
wp_register_style(
'lean-modal-css',
$assets_dir . 'css/modal' . $min . '.css',
array(),
$version
);
wp_register_script(
'charitable-admin-tables',
$assets_dir . 'js/admin/charitable-admin-tables' . $min . '.js',
array( 'jquery', 'lean-modal' ),
$version,
true
);
wp_register_script(
'select2',
$assets_dir . 'js/libraries/select2' . $min . '.js',
array( 'jquery' ),
$version,
true
);
wp_register_style(
'select2-css',
$assets_dir . 'css/libraries/select2' . $min . '.css',
array(),
$version
);
do_action( 'after_charitable_admin_enqueue_scripts', $min, $version, $assets_dir ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Hook name is already in use by other code (charitable-admin-hooks.php). Changing it would break existing functionality.
}
/**
* Set admin body classes.
*
* @since 1.5.0
* @version 1.8.1.6
* @version 1.8.1.16 Added pro/lite check.
* @version 1.8.3
* @version 1.8.5 Added dashboard and reports classes.
*
* @param string $classes Existing list of classes.
* @return string
*/
public function set_body_class( $classes ) {
$screen = get_current_screen();
if ( 'donation' === $screen->post_type && ( 'add' === $screen->action || isset( $_GET['show_form'] ) ) ) { // phpcs:ignore.
$classes .= ' charitable-admin-donation-form';
}
if ( isset( $_GET['page'] ) && ( 'charitable-tools' === $_GET['page'] || 'charitable-settings' === $_GET['page'] ) ) { // phpcs:ignore.
$classes .= ' charitable-admin-settings';
}
if ( isset( $_GET['page'] ) && 'charitable-settings' === $_GET['page'] && isset( $_GET['tab'] ) && '' !== $_GET['tab'] ) { // phpcs:ignore.
$classes .= ' charitable-admin-settings-' . esc_attr( $_GET['tab'] ); // phpcs:ignore.
}
if ( isset( $_GET['page'] ) && 'charitable-settings' === $_GET['page'] && isset( $_GET['tab'] ) && 'gateways' === $_GET['tab'] && empty( $_GET['group'] ) ) { // phpcs:ignore.
$classes .= ' charitable-admin-settings-gateways-main'; // phpcs:ignore.
}
if ( isset( $_GET['page'] ) && 'charitable-reports' === $_GET['page'] ) { // phpcs:ignore.
$classes .= ' charitable-admin-reports';
}
if ( isset( $_GET['page'] ) && 'charitable-dashboard' === $_GET['page'] && ! isset( $_GET['tab'] ) ) { // phpcs:ignore.
$classes .= ' charitable-admin-reports-dashboard';
}
if ( isset( $_GET['page'] ) && 'charitable-reports' === $_GET['page'] && isset( $_GET['tab'] ) && '' !== $_GET['tab'] ) { // phpcs:ignore.
$classes .= ' charitable-admin-reports charitable-admin-reports-' . esc_attr( $_GET['tab'] ); // phpcs:ignore.
}
if ( function_exists( 'charitable_use_legacy_dashboard' ) && charitable_use_legacy_dashboard() ) {
$classes .= ' charitable_legacy_dashboard';
}
if ( charitable_show_promotion_footer() ) {
$classes .= ' charitable-admin-promotion-footer';
}
$classes .= function_exists( 'charitable_is_pro' ) && charitable_is_pro() ? ' charitable-pro' : ' charitable';
return $classes;
}
/**
* Add notices to the dashboard.
*
* @since 1.4.0
* @version 1.8.3 Added check for PHP Version deprecation.
*
* @return void
*/
public function add_notices() {
if ( charitable_is_debug( 'square' ) ) {
error_log( 'Charitable_Admin::add_notices() - Starting to render admin notices' ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
}
// Render notices.
charitable_get_admin_notices()->render();
if ( charitable_is_debug( 'square' ) ) {
error_log( 'Charitable_Admin::add_notices() - Current admin notices: ' . print_r( charitable_get_admin_notices()->get_notices(), true ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log,WordPress.PHP.DevelopmentFunctions.error_log_print_r
}
// Check for PHP version deprecation.
if ( version_compare( PHP_VERSION, '7.4', '<' ) ) {
$this->php_notice_deprecated();
}
// Add third party notices.
$this->add_third_party_notices();
// Add version update notices.
$this->add_version_update_notices();
}
/**
* Add notices for potential third party warnings.
*
* @since 1.7.0.8
*/
public function add_third_party_notices() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
// Allow this feature to be disabled in case unforeseen problems come up.
if ( false === apply_filters( 'charitable_donations_export_args', true ) ) {
return;
}
$notices = array(
/* translators: %s: link */
'code-snippets/code-snippets.php' => sprintf(
// Translators: %s: link.
__( "You appear to be using a code snippet plugin. Please review best practices when using snippets to avoid problems when upgrading or deactivating Charitable.", 'charitable' ),
'https://wpcharitable.com/code-snippet-best-practices/'
),
);
// Allow this list to be altered by a third party or charitable addon.
$notices = apply_filters( 'charitable_admin_third_party_notices', $notices );
$helper = charitable_get_admin_notices();
foreach ( $notices as $notice => $message ) {
if ( false === charitable_get_third_party_warning_option( 'code-snippets/code-snippets.php' ) || 'dismissed' === charitable_get_third_party_warning_option( 'code-snippets/code-snippets.php' ) ) {
continue;
}
$helper->add_third_party_warning( $message, $notice );
}
}
/**
* Add version update notices to the dashboard.
*
* @since 1.4.6 (deprecated in 1.8.0)
*
* @return void
*/
public function add_version_update_notices() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$notices = array(
'release-150' => sprintf(
/* translators: %s: link */
__( "Charitable 1.5 is packed with new features and improvements. Find out what's new.", 'charitable' ),
'https://wpcharitable.com/charitable-1-5-release-notes/?utm_source=WordPress&utm_campaign=WP+Charitable&utm_medium=Admin+Notice&utm_content=Version+One+Five+Whats+New'
),
'release-160' => sprintf(
/* translators: %s: link */
__( 'Charitable 1.6 introduces important new user privacy features and other improvements. Find out what\'s new.', 'charitable' ),
'https://www.wpcharitable.com/charitable-1-6-user-privacy-gdpr-better-refunds-and-a-new-shortcode/?utm_source=WordPress&utm_campaign=WP+Charitable&utm_medium=Admin+Notice&utm_content=Version+One+Six+Whats+New'
),
);
$helper = charitable_get_admin_notices();
foreach ( $notices as $notice => $message ) {
if ( ! get_transient( 'charitable_' . $notice . '_notice' ) ) {
continue;
}
$helper->add_version_update( $message, $notice );
}
}
/**
* Add php decpreation notices.
*
* @since 1.8.3
*
* @return void
*/
public function php_notice_deprecated() {
$medium = charitable_is_pro() ? 'proplugin' : 'liteplugin';
?>
',
'',
'Charitable',
'',
''
),
array(
'a' => array(
'href' => array(),
'target' => array(),
'rel' => array(),
),
'strong' => array(),
)
);
?>
',
'',
PHP_VERSION,
gmdate( 'Y' ),
'Charitable',
'', // phpcs:ignore Generic.Files.LineLength.MaxExceeded
''
),
array(
'a' => array(
'href' => array(),
'target' => array(),
'rel' => array(),
),
'strong' => array(),
)
);
?>