PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
← All changes | includes/admin/reports/class-charitable-reports.php +68 -0 1.8.12.3 → 1.8.13 View file →
@@ -3629,8 +3629,69 @@
3629 3629 return false;
3630 3630 }
3631 3631
3632 3632 /**
3633 + * Get the date of the earliest donation on the site.
3634 + *
3635 + * Used to build the "All Time" preset in the reporting date picker, so that
3636 + * lifetime figures are one click away rather than a hand-typed range.
3637 + *
3638 + * Every valid donation status is considered, not just completed ones, because
3639 + * the reports can be filtered by status and a narrower floor would hide the
3640 + * earliest refunded or cancelled donation.
3641 + *
3642 + * @since 1.8.12.4
3643 + *
3644 + * @return string Date in Y/m/d format. Falls back to one month ago when the
3645 + * site has no donations yet.
3646 + */
3647 + public function get_earliest_donation_date() {
3648 +
3649 + $cached = get_transient( 'charitable-reports-earliest-donation-date' );
3650 +
3651 + if ( false !== $cached ) {
3652 + return $cached;
3653 + }
3654 +
3655 + global $wpdb;
3656 +
3657 + $statuses = array_keys( charitable_get_valid_donation_statuses() );
3658 +
3659 + // `charitable_donation_statuses` is a public filter, and an empty list would
3660 + // build `IN ( )`. Nothing to measure in that case, so use the fallback.
3661 + if ( empty( $statuses ) ) {
3662 + return gmdate( 'Y/m/d', strtotime( '-1 month' ) );
3663 + }
3664 +
3665 + $placeholders = implode( ', ', array_fill( 0, count( $statuses ), '%s' ) );
3666 +
3667 + $earliest = $wpdb->get_var( // phpcs:ignore
3668 + $wpdb->prepare(
3669 + "SELECT MIN( post_date ) FROM {$wpdb->posts}
3670 + WHERE post_type = 'donation'
3671 + AND post_status IN ( {$placeholders} )", // phpcs:ignore
3672 + $statuses
3673 + )
3674 + );
3675 +
3676 + if ( empty( $earliest ) || '0000-00-00 00:00:00' === $earliest ) {
3677 + /*
3678 + * Deliberately not cached. A site with no donations today may be one
3679 + * import away from four years of history, and a cached fallback would
3680 + * leave "All Time" starting a month ago for a full day afterwards -
3681 + * which is the exact wrong-figure trap this preset exists to close.
3682 + */
3683 + return gmdate( 'Y/m/d', strtotime( '-1 month' ) );
3684 + }
3685 +
3686 + $date = gmdate( 'Y/m/d', strtotime( $earliest ) );
3687 +
3688 + set_transient( 'charitable-reports-earliest-donation-date', $date, DAY_IN_SECONDS );
3689 +
3690 + return $date;
3691 + }
3692 +
3693 + /**
3633 3694 * Get localized strings.
3634 3695 *
3635 3696 * @since 1.8.1
3636 3697 *
@@ -3689,8 +3750,15 @@
3689 3750 'payment_keys' => (array) array_reverse( $this->payment_keys ),
3690 3751 ),
3691 3752 'default_start_date' => current_time( gmdate( 'Y-m-d', strtotime( '-1 month' ) ) ),
3692 3753 'default_end_date' => current_time( gmdate( 'Y-m-d' ) ),
3754 + 'earliest_donation_date' => $this->get_earliest_donation_date(),
3755 + // The date picker uses each preset's label as its object key, so the
3756 + // label has to travel to JS rather than being written there. It rides
3757 + // this same array as `earliest_donation_date` on purpose: the
3758 + // reporting JS contains no wp.i18n calls, so a second localization
3759 + // mechanism for one string would be the inconsistent choice.
3760 + 'all_time_label' => __( 'All Time', 'charitable' ),
3693 3761 'advanced_reports' => $charitable_reports_advanced_report_strings,
3694 3762 'i18n_report_timeout' => __( 'This report took too long to load and was stopped by the server. The figures have been cleared so they are not mistaken for the range you asked for. Try a shorter date range.', 'charitable' ),
3695 3763 'i18n_report_error' => __( 'This report could not be loaded. The figures have been cleared so they are not mistaken for the range you asked for. Please try again.', 'charitable' ),
3696 3764 );