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 / logger / charitable-log-functions.php

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

241 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Charitable Log Functions.
4 *
5 * Global logging function with dual-write bridge.
6 *
7 * @package Charitable/Functions/Logger
8 * @author David Bisset
9 * @copyright Copyright (c) 2023, WP Charitable LLC
10 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11 * @since 1.8.11
12 */
13
14 // Exit if accessed directly.
15 if ( ! defined( 'ABSPATH' ) ) {
16 exit;
17 }
18
19 /**
20 * Log a message to the Charitable logging system.
21 *
22 * @since 1.8.11
23 *
24 * @param string $title Log title (required, non-empty).
25 * @param string|array $message Log message or data.
26 * @param array $args {
27 * Optional. Additional arguments.
28 *
29 * @type string|array $type Log type(s). Default 'log'.
30 * @type string $level Log level: 'error', 'warning', 'info', 'debug'. Default 'info'.
31 * @type string $source Log source. Default 'core'.
32 * @type int $campaign_id Campaign ID. Default 0.
33 * @type int $donation_id Donation ID. Default 0.
34 * @type int $donor_id Donor ID. Default 0.
35 * @type int $user_id User ID. Default 0.
36 * @type int $object_id Object ID. Default 0.
37 * @type string $object_type Object type. Default ''.
38 * @type bool $force Bypass disabled logging. Default false.
39 * }
40 */
41 function charitable_log( $title, $message = '', $args = array() ) {
42 // Check if logging is enabled (unless forced).
43 $force = ! empty( $args['force'] );
44 if ( ! $force && ! Charitable_Log::is_enabled() ) {
45 return;
46 }
47
48 // Require non-empty title.
49 if ( empty( $title ) ) {
50 return;
51 }
52
53 // Set defaults.
54 $defaults = array(
55 'type' => 'log',
56 'level' => 'info',
57 'source' => 'core',
58 'campaign_id' => 0,
59 'donation_id' => 0,
60 'donor_id' => 0,
61 'user_id' => 0,
62 'object_id' => 0,
63 'object_type' => '',
64 'force' => false,
65 );
66
67 $args = wp_parse_args( $args, $defaults );
68
69 // Map 'type' key to 'types' for the record.
70 $types = $args['type'];
71 unset( $args['type'], $args['force'] );
72
73 // Validate types against registered list.
74 $valid_types = array_keys( Charitable_Log::get_log_types() );
75 if ( is_array( $types ) ) {
76 $types = array_filter(
77 $types,
78 function ( $t ) use ( $valid_types ) {
79 return in_array( $t, $valid_types, true );
80 }
81 );
82 if ( empty( $types ) ) {
83 $types = array( 'log' );
84 }
85 } else {
86 if ( ! in_array( $types, $valid_types, true ) ) {
87 $types = 'log';
88 }
89 }
90
91 $args['types'] = $types;
92
93 // Validate level.
94 $valid_levels = array_keys( Charitable_Log::get_log_levels() );
95 if ( ! in_array( $args['level'], $valid_levels, true ) ) {
96 $args['level'] = 'info';
97 }
98
99 // Sanitize source.
100 $args['source'] = sanitize_key( $args['source'] );
101
102 /**
103 * Filter the log message before saving.
104 *
105 * @since 1.8.11
106 *
107 * @param string|array $message The log message.
108 * @param string $title The log title.
109 * @param array $args Additional arguments.
110 */
111 $message = apply_filters( 'charitable_log_message', $message, $title, $args );
112
113 // Create the record data.
114 $record = Charitable_Log_Record::create( $title, $message, $args );
115
116 // Queue for batch insert.
117 Charitable_Log::get_instance()->add( $record );
118
119 // Dual-write bridge: also write to error_log if debug mode is on.
120 if ( charitable_is_debug() ) {
121 $level_upper = strtoupper( $args['level'] );
122 $source = $args['source'];
123
124 // Format message for error_log.
125 $log_message = $title;
126 if ( ! empty( $message ) ) {
127 if ( is_array( $message ) || is_object( $message ) ) {
128 $log_message .= ': ' . print_r( $message, true ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
129 } else {
130 $log_message .= ': ' . wp_strip_all_tags( (string) $message );
131 }
132 }
133
134 error_log( "[Charitable][{$level_upper}][{$source}] {$log_message}" ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
135 }
136 }
137
138 /**
139 * Log a message immediately (bypasses the queue, writes directly to DB).
140 *
141 * Identical API to charitable_log() but skips the shutdown-hook queue and
142 * calls the DB insert directly. This ensures the record is persisted even
143 * if PHP terminates abnormally before the shutdown hook fires (e.g. a fatal
144 * error during IPN processing).
145 *
146 * @since 1.8.11
147 *
148 * @param string $title Log title (required, non-empty).
149 * @param string|array $message Log message or data.
150 * @param array $args Same arguments as charitable_log().
151 */
152 function charitable_log_immediate( $title, $message = '', $args = array() ) {
153 // Check if logging is enabled (unless forced).
154 $force = ! empty( $args['force'] );
155 if ( ! $force && ! Charitable_Log::is_enabled() ) {
156 return;
157 }
158
159 // Require non-empty title.
160 if ( empty( $title ) ) {
161 return;
162 }
163
164 // Set defaults.
165 $defaults = array(
166 'type' => 'log',
167 'level' => 'info',
168 'source' => 'core',
169 'campaign_id' => 0,
170 'donation_id' => 0,
171 'donor_id' => 0,
172 'user_id' => 0,
173 'object_id' => 0,
174 'object_type' => '',
175 'force' => false,
176 );
177
178 $args = wp_parse_args( $args, $defaults );
179
180 // Map 'type' key to 'types' for the record.
181 $types = $args['type'];
182 unset( $args['type'], $args['force'] );
183
184 // Validate types against registered list.
185 $valid_types = array_keys( Charitable_Log::get_log_types() );
186 if ( is_array( $types ) ) {
187 $types = array_filter(
188 $types,
189 function ( $t ) use ( $valid_types ) {
190 return in_array( $t, $valid_types, true );
191 }
192 );
193 if ( empty( $types ) ) {
194 $types = array( 'log' );
195 }
196 } else {
197 if ( ! in_array( $types, $valid_types, true ) ) {
198 $types = 'log';
199 }
200 }
201
202 $args['types'] = $types;
203
204 // Validate level.
205 $valid_levels = array_keys( Charitable_Log::get_log_levels() );
206 if ( ! in_array( $args['level'], $valid_levels, true ) ) {
207 $args['level'] = 'info';
208 }
209
210 // Sanitize source.
211 $args['source'] = sanitize_key( $args['source'] );
212
213 /** This filter is documented in charitable-log-functions.php */
214 $message = apply_filters( 'charitable_log_message', $message, $title, $args );
215
216 // Create the record data.
217 $record = Charitable_Log_Record::create( $title, $message, $args );
218
219 // Write directly to DB — bypass the queue.
220 $log = Charitable_Log::get_instance();
221 $log->ensure_table_exists();
222 $log->get_db()->insert( $record );
223
224 // Dual-write bridge: also write to error_log if debug mode is on.
225 if ( charitable_is_debug() ) {
226 $level_upper = strtoupper( $args['level'] );
227 $source = $args['source'];
228
229 $log_message = $title;
230 if ( ! empty( $message ) ) {
231 if ( is_array( $message ) || is_object( $message ) ) {
232 $log_message .= ': ' . print_r( $message, true ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_print_r
233 } else {
234 $log_message .= ': ' . wp_strip_all_tags( (string) $message );
235 }
236 }
237
238 error_log( "[Charitable][{$level_upper}][{$source}] {$log_message}" ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
239 }
240 }
241