PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.12.2
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.12.2
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
charitable / includes / admin / reports / charitable-core-reports-functions.php

charitable-core-reports-functions.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.12.2, at includes/admin/reports/charitable-core-reports-functions.php

356 lines 12.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Charitable Core Reporting Functions
4 *
5 * General core functions available only within the admin area.
6 *
7 * @package Charitable/Functions/Admin
8 * @version 1.8.1
9 * @author David Bisset
10 * @copyright Copyright (c) 2023, WP Charitable LLC
11 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
12 */
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Detects what tabs in reporting can load the scripts.
21 *
22 * @since 1.8.1
23 *
24 * @param string $tab_slug Tab slug.
25 *
26 * @return boolean
27 */
28 function charitable_reports_allow_tab_load_scripts( $tab_slug = false ) {
29
30 if ( ! $tab_slug ) {
31 return false;
32 }
33
34 $allowed_tabs = array( 'overview', 'advanced', 'activity', 'donors' );
35
36 return in_array( strtolower( $tab_slug ), $allowed_tabs, true );
37 }
38
39 /**
40 * Get the advanced report args, perhaps checking a transient if the report has been run before.
41 * This is useful if the user selected a report, then navigated away from the page, then came back.
42 * Cache is limited to 60 * 60 * 24 seconds. See charitable_reports_get_advanced_report_arg_defaults() for more info.
43 *
44 * @since 1.8.1
45 * @since 1.8.1.3 Added order_by and order.
46 *
47 * @param array $postdata Post data.
48 *
49 * @return array
50 */
51 function charitable_reports_get_advanced_report_args( $postdata = array() ) {
52
53 if ( ! empty( $postdata ) ) :
54
55 return apply_filters(
56 'charitable_report_advanced_arg_postdata',
57 array(
58 'start_date' => ! empty( $postdata['start_date'] ) ? esc_html( $postdata['start_date'] ) : gmdate( 'Y/m/d', current_time( 'timestamp', 0 ) ),
59 'end_date' => ! empty( $postdata['end_date'] ) ? esc_html( $postdata['end_date'] ) : gmdate( 'Y/m/d', strtotime( '-7 days', current_time( 'timestamp', 0 ) ) ),
60 'start_date_compare_from' => ! empty( $postdata['compare_from_start_date'] ) ? esc_html( $postdata['compare_from_start_date'] ) : false,
61 'end_date_compare_from' => ! empty( $postdata['compare_from_end_date'] ) ? esc_html( $postdata['compare_from_end_date'] ) : false,
62 'start_date_compare_to' => ! empty( $postdata['compare_to_start_date'] ) ? esc_html( $postdata['compare_to_start_date'] ) : false,
63 'end_date_compare_to' => ! empty( $postdata['compare_to_end_date'] ) ? esc_html( $postdata['compare_to_end_date'] ) : false,
64 'filter' => ! empty( $postdata['filter'] ) ? esc_html( $postdata['filter'] ) : false,
65 'campaign_id' => ! empty( $postdata['campaign_id'] ) ? esc_html( $postdata['campaign_id'] ) : false,
66 'report_type' => ! empty( $postdata['report_type'] ) ? esc_html( $postdata['report_type'] ) : 'lybunt',
67 'order_by' => ! empty( $postdata['order_by'] ) ? esc_html( $postdata['order_by'] ) : 'total_life_amount',
68 'order' => ! empty( $postdata['order'] ) ? esc_html( $postdata['order'] ) : 'DESC',
69 )
70 );
71 endif;
72
73 $charitable_report_advanced_args = charitable_reports_maybe_cache( false ) ? get_transient( 'charitable-report-advanced-args' ) : false;
74
75 if ( ! charitable_is_pro() || false === $charitable_report_advanced_args ) {
76
77 $charitable_report_advanced_args = charitable_reports_get_advanced_report_arg_defaults();
78
79 set_transient( 'charitable-report-advanced-args', $charitable_report_advanced_args, 60 * 60 * 24 );
80 }
81
82 return $charitable_report_advanced_args;
83 }
84
85 /**
86 * Get the advanced report default args.
87 *
88 * @since 1.8.1
89 * @since 1.8.1.3 Added order_by and order.
90 *
91 * @return array
92 */
93 function charitable_reports_get_advanced_report_arg_defaults() {
94
95 // get today's date in Y/m/d format from WordPress server using current_time().
96 $today = gmdate( 'Y/m/d', current_time( 'timestamp', 0 ) );
97 // subtract one week from today's date using current_time().
98 $one_week_ago = gmdate( 'Y/m/d', strtotime( '-7 days', current_time( 'timestamp', 0 ) ) );
99 // get date Y/m/d from Jan 1st of last year.
100 $first_day_last_year = gmdate( 'Y/m/d', strtotime( 'first day of January last year', current_time( 'timestamp', 0 ) ) );
101 $last_day_last_year = gmdate( 'Y/m/d', strtotime( 'last day of December last year', current_time( 'timestamp', 0 ) ) );
102 $first_day_this_year = gmdate( 'Y/m/d', strtotime( 'first day of January this year', current_time( 'timestamp', 0 ) ) );
103 $last_day_this_year = gmdate( 'Y/m/d', strtotime( 'last day of December this year', current_time( 'timestamp', 0 ) ) );
104
105 return apply_filters(
106 'charitable_report_advanced_arg_defaults',
107 array(
108 'start_date' => $today,
109 'end_date' => $one_week_ago,
110 'start_date_compare_from' => $first_day_last_year,
111 'end_date_compare_from' => $last_day_last_year,
112 'start_date_compare_to' => $first_day_this_year,
113 'end_date_compare_to' => $last_day_this_year,
114 'filter' => false,
115 'campaign_id' => false,
116 'report_type' => 'lybunt',
117 'order_by' => 'total_life_amount',
118 'order' => 'DESC',
119 )
120 );
121 }
122
123 /**
124 * Get the donor report args, mainly checking a transient if the report has been run before.
125 * This is useful if the user selected a report, then navigated away from the page, then came back.
126 * Cache is limited to 1 hour. See Charitable_Reports_Ajax::get_donor_data() for more info.
127 *
128 * @since 1.8.1
129 *
130 * @return array
131 */
132 function charitable_reports_get_donor_reports_arg() {
133
134 if ( ! charitable_reports_maybe_cache( false ) ) {
135 return false;
136 }
137
138 $charitable_report_donor_args = get_transient( 'charitable-report-donor-args' );
139
140 return $charitable_report_donor_args;
141 }
142
143 /**
144 * Get the donor report type.
145 *
146 * @since 1.8.1
147 *
148 * @param string $report_default Default report type, if none is set is 'donors-top'.
149 *
150 * @return string
151 */
152 function charitable_reports_get_donor_report_type( $report_default = 'donors-top' ) {
153
154 $charitable_report_donor_args = charitable_reports_get_donor_reports_arg();
155
156 // If the transient is set it probably looks like: Array ( [donor_report_type] => donors-recurring [limit] => ) .
157
158 if ( false !== $charitable_report_donor_args && ! empty( $charitable_report_donor_args['donor_report_type'] ) ) {
159 return $charitable_report_donor_args['donor_report_type'];
160 }
161
162 return $report_default;
163 }
164
165 /**
166 * Check if the report or args should be cached.
167 *
168 * @since 1.8.1
169 *
170 * @param bool $force_cache Force cache. Default is false.
171 *
172 * @return bool
173 */
174 function charitable_reports_maybe_cache( $force_cache = false ) {
175
176 // Check the globals to see if caching is enabled specifically for reports.
177 if ( charitable_is_debug() ) {
178 return false;
179 }
180 if ( defined( 'CHARITABLE_REPORTS_NO_CACHE' ) && CHARITABLE_REPORTS_NO_CACHE ) {
181 return false;
182 }
183 if ( ! $force_cache ) {
184 return false;
185 }
186
187 return true;
188 }
189
190 /**
191 * Get the report data.
192 *
193 * @since 1.8.1
194 *
195 * @param string $report_type Report type.
196 *
197 * @return array
198 */
199 function charitable_reports_get_advanced_data_report( $report_type = 'lybunt' ) {
200
201 // type check.
202 if ( ! isset( $_POST['report_type'] ) || 'lybunt' !== $_POST['report_type'] ) {
203 return;
204 }
205
206 // phpcs:disable WordPress.Security.NonceVerification.Missing
207 // security check.
208 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- wp_verify_nonce handles validation
209 if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( wp_unslash( $_POST['nonce'] ), 'charitable-reporting' ) ) {
210 wp_send_json_error( 'Invalid nonce.' );
211 exit;
212 }
213
214 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Array data, sanitized in function
215 $charitable_report_advanced_args = charitable_reports_get_advanced_report_args( $_POST );
216
217 $report_type = isset( $_POST['report_type'] ) ? esc_html( wp_unslash( $_POST['report_type'] ) ) : $charitable_report_advanced_args['report_type']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized by esc_html
218 // phpcs:enable WordPress.Security.NonceVerification.Missing
219
220 $charitable_reports = Charitable_Reports::get_instance();
221
222 $args = array();
223
224 $charitable_reports->init_with_array( $report_type, $args );
225
226 $advanced_report_data = $charitable_reports->get_advanced_data_by_report_type( $charitable_report_advanced_args );
227
228 $data = array();
229
230 $data['html'] = $charitable_reports->generate_advanced_breakdown_report_html( $report_type, $advanced_report_data, $charitable_report_advanced_args );
231
232 wp_send_json_success( $data );
233
234 exit;
235 }
236 add_action( 'wp_ajax_charitable_report_advanced_data', 'charitable_reports_get_advanced_data_report' );
237
238 /**
239 * Get the default pagination per page, perhaps based on report type.
240 *
241 * @since 1.8.1
242 *
243 * @param string $report_type Report type.
244 *
245 * @return int
246 */
247 function charitable_reports_get_pagination_per_page( $report_type = 'donors-top ' ) {
248
249 return apply_filters( 'charitable_report_pagination_per_page', 20, $report_type );
250 }
251
252 /**
253 * A function that accepts an array of results and an array of fields and formats the fields using charitable_format_money.
254 * This is useful for formatting money fields after calculating averages or getting raw data from the database.
255 *
256 * @since 1.8.1
257 *
258 * @param array $results The results to be formatted.
259 * @param array $fields The fields to be formatted.
260 * @param int|false $decimal_count Optional. If not set, default decimal count will be used.
261 * @param boolean $db_format Optional. Whether the amount is in db format (i.e. using decimals for cents, regardless of site settings).
262 * @param string $currency Optional. If passed, will use the given currency's formatting, not the default currency.
263 * @param boolean $add_currency_symbol Optional. If true, will add the currency symbol to the formatted field.
264 * @param boolean $convert_currency_symbol Optional. If true, will convert the currency symbol to proper HTML.
265 *
266 * @return array
267 */
268 function charitable_reports_format_money( $results = array(), $fields = array(), $decimal_count = false, $db_format = false, $currency = '', $add_currency_symbol = false, $convert_currency_symbol = false ) {
269
270 if ( ! is_array( $results ) || empty( $results ) ) {
271 return array();
272 }
273
274 if ( ! is_array( $fields ) || empty( $fields ) ) {
275 return $results;
276 }
277
278 // if $convert_currency_symbol is true, we need to decode the currency symbol.
279 $currency_symbol = $convert_currency_symbol ? html_entity_decode( charitable_get_currency_helper()->get_currency_symbol() ) : charitable_get_currency_helper()->get_currency_symbol();
280
281 foreach ( $results as $key => $result ) {
282
283 foreach ( $fields as $field ) {
284
285 if ( ! isset( $result[ $field ] ) ) {
286 continue;
287 }
288
289 $formatted_field = str_replace( charitable_get_currency_helper()->get_currency_symbol(), '', trim( charitable_format_money( $result[ $field ], $decimal_count, $db_format, $currency ) ) );
290 $results[ $key ][ $field ] = 1 === intval( $add_currency_symbol ) ? $currency_symbol . $formatted_field : $formatted_field;
291 }
292 }
293
294 return $results;
295 }
296
297 /**
298 * A function that accepts an array of results and an array of fields and formats the fields using date().
299 *
300 * @since 1.8.1
301 *
302 * @param array $results The results to be formatted.
303 * @param array $fields The fields to be formatted.
304 * @param string $date_format Optional. If not set, default date format will be used.
305 *
306 * @return array
307 */
308 function charitable_reports_format_date( $results = array(), $fields = array(), $date_format = false ) {
309
310 if ( ! is_array( $results ) || empty( $results ) ) {
311 return array();
312 }
313
314 if ( ! is_array( $fields ) || empty( $fields ) ) {
315 return $results;
316 }
317
318 foreach ( $results as $key => $result ) {
319
320 foreach ( $fields as $field ) {
321
322 if ( ! isset( $result[ $field ] ) ) {
323 continue;
324 }
325
326 // convert to date format example: March 31, 2023 1:30 pm.
327 $date_format = empty( $date_format ) ? get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) : $date_format;
328 $formatted_field = gmdate( $date_format, strtotime( $result[ $field ] ) );
329 $results[ $key ][ $field ] = $formatted_field;
330
331 }
332 }
333
334 return $results;
335 }
336
337 /**
338 * Check if the request is an AJAX request.
339 * The actions in $ajax_actions what might be possible in an action request to determine if the request for get_donor_data is an AJAX request.
340 *
341 * @since 1.8.1.3
342 *
343 * @return boolan
344 */
345 function charitable_reports_is_ajax() {
346
347 $ajax_actions = array(
348 'charitable_get_donor_data',
349 'charitable_report_donor_data_pagination',
350 );
351
352 $is_ajax = isset( $_POST['action'] ) && in_array( $_POST['action'], $ajax_actions, true ) ? true : false; // phpcs:ignore
353
354 return $is_ajax;
355 }
356