Passed
Push — debug-mode-set-log-settings ( 6a55cc...f7be62 )
by Jonathan
03:05
created

Object_Sync_Sf_Logging::setup()   B

Complexity

Conditions 11
Paths 22

Size

Total Lines 29
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 21
nc 22
nop 5
dl 0
loc 29
rs 7.3166
c 1
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Log events based on plugin settings. Extend the WP_Logging class for the purposes of Object Sync for Salesforce.
4
 *
5
 * @class   Object_Sync_Sf_Logging
6
 * @package Object_Sync_Salesforce
7
 */
8
9
defined( 'ABSPATH' ) || exit;
10
11
/**
12
 * Object_Sync_Sf_Logging class.
13
 */
14
class Object_Sync_Sf_Logging extends WP_Logging {
15
16
	/**
17
	 * Current version of the plugin
18
	 *
19
	 * @var string
20
	 */
21
	public $version;
22
23
	/**
24
	 * The main plugin file
25
	 *
26
	 * @var string
27
	 */
28
	public $file;
29
30
	/**
31
	 * Global object of `$wpdb`, the WordPress database
32
	 *
33
	 * @var object
34
	 */
35
	public $wpdb;
36
37
	/**
38
	 * The plugin's slug so we can include it when necessary
39
	 *
40
	 * @var string
41
	 */
42
	public $slug;
43
44
	/**
45
	 * The plugin's prefix when saving options to the database
46
	 *
47
	 * @var string
48
	 */
49
	public $option_prefix;
50
51
	/**
52
	 * The setting value for whether logging is enabled
53
	 *
54
	 * @var bool
55
	 */
56
	public $enabled;
57
58
	/**
59
	 * Which statuses to log, from the settings value
60
	 *
61
	 * @var array
62
	 */
63
	public $statuses_to_log;
64
65
	/**
66
	 * The name of the schedule to prune logs
67
	 *
68
	 * @var string
69
	 */
70
	public $schedule_name;
71
72
	/**
73
	 * Whether the plugin is in debug mode
74
	 *
75
	 * @var bool
76
	 */
77
	public $debug;
78
79
	/**
80
	 * Constructor for logging class
81
	 */
82
	public function __construct() {
83
		$this->version       = object_sync_for_salesforce()->version;
84
		$this->file          = object_sync_for_salesforce()->file;
85
		$this->wpdb          = object_sync_for_salesforce()->wpdb;
86
		$this->slug          = object_sync_for_salesforce()->slug;
87
		$this->option_prefix = object_sync_for_salesforce()->option_prefix;
88
89
		$this->enabled         = filter_var( get_option( $this->option_prefix . 'enable_logging', false ), FILTER_VALIDATE_BOOLEAN );
90
		$this->statuses_to_log = maybe_unserialize( get_option( $this->option_prefix . 'statuses_to_log', array() ) );
0 ignored issues
show
Documentation Bug introduced by
It seems like maybe_unserialize(get_op...uses_to_log', array())) can also be of type false. However, the property $statuses_to_log is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
91
92
		$this->schedule_name = 'wp_logging_prune_routine';
93
94
		$this->capability = 'configure_salesforce';
0 ignored issues
show
Bug Best Practice introduced by
The property capability does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
95
96
		// use the option value for whether we're in debug mode.
97
		$this->debug = filter_var( get_option( $this->option_prefix . 'debug_mode', false ), FILTER_VALIDATE_BOOLEAN );
98
99
		add_action( 'plugins_loaded', array( $this, 'init' ) );
100
101
	}
102
103
	/**
104
	 * Initialize. This creates a schedule for pruning logs, and also the custom content type
105
	 */
106
	public function init() {
107
		$this->configure_debugging();
108
		if ( true === $this->enabled ) {
109
			add_filter( 'cron_schedules', array( $this, 'add_prune_interval' ) );
110
			add_filter( 'wp_log_types', array( $this, 'set_log_types' ), 10, 1 );
111
			add_filter( 'wp_logging_should_we_prune', array( $this, 'set_prune_option' ), 10, 1 );
112
			add_filter( 'wp_logging_prune_when', array( $this, 'set_prune_age' ), 10, 1 );
113
			add_filter( 'wp_logging_prune_query_args', array( $this, 'set_prune_args' ), 10, 1 );
114
			add_filter( 'wp_logging_post_type_args', array( $this, 'set_log_visibility' ), 10, 1 );
115
			add_filter( 'pre_wp_unique_post_slug', array( $this, 'set_log_slug' ), 10, 5 );
116
117
			// add a filter to check for other plugins that might be filtering the log screen.
118
			$are_logs_filtered = apply_filters( 'wp_logging_manage_logs_filtered', false );
0 ignored issues
show
Unused Code introduced by
The call to __return_true() has too many arguments starting with false. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

118
			$are_logs_filtered = /** @scrutinizer ignore-call */ apply_filters( 'wp_logging_manage_logs_filtered', false );

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
119
			add_filter( 'wp_logging_manage_logs_filtered', '__return_true' );
120
121
			if ( false === $are_logs_filtered ) {
0 ignored issues
show
introduced by
The condition false === $are_logs_filtered is always false.
Loading history...
122
				// add a sortable Type column to the posts admin.
123
				add_filter( 'manage_edit-wp_log_columns', array( $this, 'type_column' ), 10, 1 );
124
				add_filter( 'manage_edit-wp_log_sortable_columns', array( $this, 'sortable_columns' ), 10, 1 );
125
				add_action( 'manage_wp_log_posts_custom_column', array( $this, 'type_column_content' ), 10, 2 );
126
127
				// filter the log posts admin by log type.
128
				add_filter( 'parse_query', array( $this, 'posts_filter' ), 10, 1 );
129
				add_action( 'restrict_manage_posts', array( $this, 'restrict_logs_by_type' ), 10, 1 );
130
			}
131
132
			// when the schedule might change.
133
			add_action( 'update_option_' . $this->option_prefix . 'logs_how_often_unit', array( $this, 'check_log_schedule' ), 10, 3 );
134
			add_action( 'update_option_' . $this->option_prefix . 'logs_how_often_number', array( $this, 'check_log_schedule' ), 10, 3 );
135
136
			$this->save_log_schedule();
137
		}
138
	}
139
140
	/**
141
	 * Configure log settings based on debug status.
142
	 */
143
	private function configure_debugging() {
144
		// set debug log status based on the plugin's debug mode setting.
145
		if ( true === $this->debug ) {
146
			$this->statuses_to_log[] = 'debug';
147
			$this->enabled           = true;
148
		} else {
149
			if ( in_array( 'debug', $this->statuses_to_log, true ) ) {
150
				$delete_value          = 'debug';
151
				$this->statuses_to_log = array_filter(
152
					$this->statuses_to_log,
153
					function( $e ) use ( $delete_value ) {
154
						return ( $e !== $delete_value );
155
					}
156
				);
157
				update_option( $this->option_prefix . 'statuses_to_log', $this->statuses_to_log );
158
			}
159
		}
160
	}
161
162
	/**
163
	 * Set visibility for the post type
164
	 *
165
	 * @param array $log_args The post arguments.
166
	 * @return array $log_args
167
	 */
168
	public function set_log_visibility( $log_args ) {
169
		// set public to true overrides the WP_DEBUG setting that is the default on the class
170
		// capabilities makes it so (currently) only admin users can see the log posts in their admin view
171
		// note: a public value of true is required to show Logs as a nav menu item on the admin.
172
		// however, if we don't set exclude_from_search to true and publicly_queryable to false, logs *can* appear in search results.
173
		$log_args['public']              = true;
174
		$log_args['publicly_queryable']  = false;
175
		$log_args['exclude_from_search'] = true;
176
		$log_args['capabilities']        = array(
177
			'edit_post'          => $this->capability,
178
			'read_post'          => $this->capability,
179
			'delete_post'        => $this->capability,
180
			'edit_posts'         => $this->capability,
181
			'edit_others_posts'  => $this->capability,
182
			'delete_posts'       => $this->capability,
183
			'publish_posts'      => $this->capability,
184
			'read_private_posts' => $this->capability,
185
		);
186
187
		$log_args = apply_filters( $this->option_prefix . 'logging_post_type_args', $log_args );
188
189
		return $log_args;
190
	}
191
192
	/**
193
	 * Create a (probably unique) post name for logs in a more performant manner than wp_unique_post_slug().
194
	 *
195
	 * @param string $override_slug Short-circuit return value.
196
	 * @param string $slug The desired slug (post_name).
197
	 * @param int    $post_ID The post ID.
198
	 * @param string $post_status The post status.
199
	 * @param string $post_type The post type.
200
	 * @return string
201
	 */
202
	public function set_log_slug( $override_slug, $slug, $post_ID, $post_status, $post_type ) {
203
		if ( 'wp_log' === $post_type ) {
204
			$override_slug = uniqid( $post_type . '-', true ) . '-' . wp_generate_password( 32, false );
205
		}
206
		return $override_slug;
207
	}
208
209
	/**
210
	 * Add a Type column to the posts admin for this post type
211
	 *
212
	 * @param array $columns the columns for the post list table.
213
	 * @return array $columns
214
	 */
215
	public function type_column( $columns ) {
216
		$columns['type'] = __( 'Type', 'object-sync-for-salesforce' );
217
		return $columns;
218
	}
219
220
	/**
221
	 * Make the Type column in the posts admin for this post type sortable
222
	 *
223
	 * @param array $columns the sortable columns for the post list table.
224
	 * @return array $columns
225
	 */
226
	public function sortable_columns( $columns ) {
227
		$columns['type'] = 'type';
228
		return $columns;
229
	}
230
231
	/**
232
	 * Add the content for the Type column in the posts admin for this post type
233
	 *
234
	 * @param string $column_name the value for the type column on the list table.
235
	 * @param int    $post_id the ID of the currently listed post in the table.
236
	 */
237
	public function type_column_content( $column_name, $post_id ) {
238
		if ( 'type' !== $column_name ) {
239
			return;
240
		}
241
		// get wp_log_type.
242
		$terms = wp_get_post_terms(
243
			$post_id,
244
			'wp_log_type',
245
			array(
246
				'fields' => 'names',
247
			)
248
		);
249
		if ( is_array( $terms ) ) {
250
			echo esc_attr( $terms[0] );
251
		}
252
	}
253
254
	/**
255
	 * Filter log posts by the taxonomy from the dropdown when a value is present
256
	 *
257
	 * @param object $query the current WP query for the list table.
258
	 */
259
	public function posts_filter( $query ) {
260
		global $pagenow;
261
		$type     = 'wp_log';
262
		$taxonomy = 'wp_log_type';
263
		if ( is_admin() && 'edit.php' === $pagenow ) {
264
			if ( isset( $_GET['post_type'] ) && esc_attr( $_GET['post_type'] ) === $type ) {
265
				if ( isset( $_GET[ $taxonomy ] ) && '' !== $_GET[ $taxonomy ] ) {
266
					$query->post_type = $type;
267
					$query->tax_query = array(
268
						array(
269
							'taxonomy' => $taxonomy,
270
							'field'    => 'slug',
271
							'terms'    => esc_attr( $_GET[ $taxonomy ] ),
272
						),
273
					);
274
				}
275
			}
276
		}
277
	}
278
279
	/**
280
	 * Add a filter form for the log admin so we can filter by wp_log_type taxonomy values
281
	 *
282
	 * @param string $post_type what type of log we want to show.
283
	 */
284
	public function restrict_logs_by_type( $post_type ) {
285
		$type     = 'wp_log';
286
		$taxonomy = 'wp_log_type';
287
		// only add filter to post type you want.
288
		if ( 'wp_log' === $post_type ) {
289
			// get wp_log_type.
290
			$terms = get_terms(
291
				array(
292
					'taxonomy'   => $taxonomy,
293
					'hide_empty' => true,
294
				)
295
			);
296
			if ( is_wp_error( $terms ) || empty( $terms ) ) {
297
				// no terms, or the taxonomy doesn't exist, skip.
298
				return;
299
			}
300
			?>
301
			<select name="wp_log_type">
302
				<option value=""><?php esc_html_e( 'All log types ', 'object-sync-for-salesforce' ); ?></option>
303
				<?php
304
				$current_log_type = isset( $_GET[ $taxonomy ] ) ? esc_attr( $_GET[ $taxonomy ] ) : '';
305
				foreach ( $terms as $key => $term ) {
306
					printf(
307
						'<option value="%s"%s>%s</option>',
308
						esc_attr( $term->slug ),
309
						selected( $term->slug, $current_log_type, false ),
310
						esc_html( $term->name )
311
					);
312
				}
313
				?>
314
			</select>
315
			<?php
316
		}
317
	}
318
319
	/**
320
	 * When the cron settings change, clear the relevant schedule
321
	 *
322
	 * @param string $old_value Previous option value.
323
	 * @param string $new_value New option value.
324
	 * @param string $option Name of option.
325
	 */
326
	public function check_log_schedule( $old_value, $new_value, $option ) {
327
		$clear_schedule  = false;
328
		$schedule_unit   = get_option( $this->option_prefix . 'logs_how_often_unit', '' );
329
		$schedule_number = get_option( $this->option_prefix . 'logs_how_often_number', '' );
330
		if ( $this->option_prefix . 'logs_how_often_unit' === $option ) {
331
			$old_frequency = $this->get_schedule_frequency( $old_value, $schedule_number );
0 ignored issues
show
Bug introduced by
It seems like $schedule_number can also be of type false; however, parameter $number of Object_Sync_Sf_Logging::get_schedule_frequency() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

331
			$old_frequency = $this->get_schedule_frequency( $old_value, /** @scrutinizer ignore-type */ $schedule_number );
Loading history...
332
			$new_frequency = $this->get_schedule_frequency( $new_value, $schedule_number );
333
			$old_key       = $old_frequency['key'];
334
			$new_key       = $new_frequency['key'];
335
			if ( $old_key !== $new_key ) {
336
				$clear_schedule = true;
337
			}
338
		}
339
		if ( $this->option_prefix . 'logs_how_often_number' === $option ) {
340
			$old_frequency = $this->get_schedule_frequency( $schedule_unit, $old_value );
0 ignored issues
show
Bug introduced by
It seems like $schedule_unit can also be of type false; however, parameter $unit of Object_Sync_Sf_Logging::get_schedule_frequency() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

340
			$old_frequency = $this->get_schedule_frequency( /** @scrutinizer ignore-type */ $schedule_unit, $old_value );
Loading history...
341
			$new_frequency = $this->get_schedule_frequency( $schedule_unit, $new_value );
342
			$old_key       = $old_frequency['key'];
343
			$new_key       = $new_frequency['key'];
344
			if ( $old_key !== $new_key ) {
345
				$clear_schedule = true;
346
			}
347
		}
348
		if ( true === $clear_schedule ) {
349
			wp_clear_scheduled_hook( $this->schedule_name );
350
			$this->save_log_schedule();
351
		}
352
	}
353
354
	/**
355
	 * Save a cron schedule
356
	 */
357
	public function save_log_schedule() {
358
		global $pagenow;
359
		if ( ( 'options.php' !== $pagenow ) && ( ! isset( $_GET['page'] ) || $this->slug . '-admin' !== $_GET['page'] ) ) {
360
			return;
361
		}
362
		$schedule_unit   = get_option( $this->option_prefix . 'logs_how_often_unit', '' );
363
		$schedule_number = get_option( $this->option_prefix . 'logs_how_often_number', '' );
364
		$frequency       = $this->get_schedule_frequency( $schedule_unit, $schedule_number );
0 ignored issues
show
Bug introduced by
It seems like $schedule_number can also be of type false; however, parameter $number of Object_Sync_Sf_Logging::get_schedule_frequency() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

364
		$frequency       = $this->get_schedule_frequency( $schedule_unit, /** @scrutinizer ignore-type */ $schedule_number );
Loading history...
Bug introduced by
It seems like $schedule_unit can also be of type false; however, parameter $unit of Object_Sync_Sf_Logging::get_schedule_frequency() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

364
		$frequency       = $this->get_schedule_frequency( /** @scrutinizer ignore-type */ $schedule_unit, $schedule_number );
Loading history...
365
		$key             = $frequency['key'];
366
		if ( ! wp_next_scheduled( $this->schedule_name ) ) {
367
			wp_schedule_event( time(), $key, $this->schedule_name );
368
		}
369
	}
370
371
	/**
372
	 * Add interval to wp schedules based on admin settings
373
	 *
374
	 * @param array $schedules An array of scheduled cron items.
375
	 * @return array $frequency
376
	 */
377
	public function add_prune_interval( $schedules ) {
378
379
		$schedule_unit   = get_option( $this->option_prefix . 'logs_how_often_unit', '' );
380
		$schedule_number = get_option( $this->option_prefix . 'logs_how_often_number', '' );
381
		$frequency       = $this->get_schedule_frequency( $schedule_unit, $schedule_number );
0 ignored issues
show
Bug introduced by
It seems like $schedule_unit can also be of type false; however, parameter $unit of Object_Sync_Sf_Logging::get_schedule_frequency() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

381
		$frequency       = $this->get_schedule_frequency( /** @scrutinizer ignore-type */ $schedule_unit, $schedule_number );
Loading history...
Bug introduced by
It seems like $schedule_number can also be of type false; however, parameter $number of Object_Sync_Sf_Logging::get_schedule_frequency() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

381
		$frequency       = $this->get_schedule_frequency( $schedule_unit, /** @scrutinizer ignore-type */ $schedule_number );
Loading history...
382
		$key             = $frequency['key'];
383
		$seconds         = $frequency['seconds'];
384
385
		$schedules[ $key ] = array(
386
			'interval' => $seconds * $schedule_number,
387
			'display'  => 'Every ' . $schedule_number . ' ' . $schedule_unit,
0 ignored issues
show
Bug introduced by
Are you sure $schedule_unit of type false|mixed|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

387
			'display'  => 'Every ' . $schedule_number . ' ' . /** @scrutinizer ignore-type */ $schedule_unit,
Loading history...
Bug introduced by
Are you sure $schedule_number of type false|mixed|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

387
			'display'  => 'Every ' . /** @scrutinizer ignore-type */ $schedule_number . ' ' . $schedule_unit,
Loading history...
388
		);
389
390
		return $schedules;
391
392
	}
393
394
	/**
395
	 * Convert the schedule frequency from the admin settings into an array
396
	 * interval must be in seconds for the class to use it
397
	 *
398
	 * @param string $unit A unit of time.
399
	 * @param string $number The number of those units.
400
	 * @return array
401
	 */
402
	public function get_schedule_frequency( $unit, $number ) {
403
404
		switch ( $unit ) {
405
			case 'minutes':
406
				$seconds = 60;
407
				break;
408
			case 'hours':
409
				$seconds = 3600;
410
				break;
411
			case 'days':
412
				$seconds = 86400;
413
				break;
414
			default:
415
				$seconds = 0;
416
		}
417
418
		$key = $unit . '_' . $number;
419
420
		return array(
421
			'key'     => $key,
422
			'seconds' => $seconds,
423
		);
424
425
	}
426
427
	/**
428
	 * Set terms for Salesforce logs
429
	 *
430
	 * @param array $terms An array of string log types in the WP_Logging class.
431
	 * @return array $terms
432
	 */
433
	public function set_log_types( $terms ) {
434
		$terms[] = 'salesforce';
435
		return $terms;
436
	}
437
438
	/**
439
	 * Should logs be pruned at all?
440
	 *
441
	 * @param string $should_we_prune Whether to prune old log items.
442
	 * @return string $should_we_prune Whether to prune old log items.
443
	 */
444
	public function set_prune_option( $should_we_prune ) {
445
		$should_we_prune = get_option( $this->option_prefix . 'prune_logs', $should_we_prune );
446
		$should_we_prune = filter_var( $should_we_prune, FILTER_VALIDATE_BOOLEAN );
447
		return $should_we_prune;
448
	}
449
450
	/**
451
	 * Set how often to prune the Salesforce logs
452
	 *
453
	 * @param string $how_old How old the oldest non-pruned log items should be allowed to be.
454
	 * @return string $how_old
455
	 */
456
	public function set_prune_age( $how_old ) {
457
		$value = get_option( $this->option_prefix . 'logs_how_old', '' ) . ' ago';
0 ignored issues
show
Bug introduced by
Are you sure get_option($this->option...x . 'logs_how_old', '') of type false|mixed|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

457
		$value = /** @scrutinizer ignore-type */ get_option( $this->option_prefix . 'logs_how_old', '' ) . ' ago';
Loading history...
458
		if ( '' !== $value ) {
459
			return $value;
460
		} else {
461
			return $how_old;
462
		}
463
	}
464
465
	/**
466
	 * Set arguments for only getting the Salesforce logs
467
	 *
468
	 * @param array $args Argument array for get_posts determining what posts are eligible for pruning.
469
	 * @return array $args
470
	 */
471
	public function set_prune_args( $args ) {
472
		$args['wp_log_type'] = 'salesforce';
473
		$number_to_prune     = get_option( $this->option_prefix . 'logs_how_many_number', '' );
474
		if ( '' !== $number_to_prune ) {
475
			$args['posts_per_page'] = filter_var( $number_to_prune, FILTER_SANITIZE_NUMBER_INT );
476
		}
477
		return $args;
478
	}
479
480
	/**
481
	 * Setup new log entry
482
	 *
483
	 * Check and see if we should log anything, and if so, send it to add()
484
	 *
485
	 * @access      public
486
	 * @since       1.0
487
	 *
488
	 * @param       string|array $title_or_params A log post title, or the full array of parameters.
489
	 * @param       string       $message The log message.
490
	 * @param       string|0     $trigger The type of log triggered. Usually one of: debug, notice, warning, error.
0 ignored issues
show
Documentation Bug introduced by
The doc comment string|0 at position 2 could not be parsed: Unknown type name '0' at position 2 in string|0.
Loading history...
491
	 * @param       int          $parent The parent WordPress object.
492
	 * @param       string       $status The log status.
493
	 *
494
	 * @uses        self::add()
495
	 * @see         Object_Sync_Sf_Mapping::__construct()    the location of the parameters that define the logging triggers.
496
	 *
497
	 * @return      void
498
	 */
499
	public function setup( $title_or_params, $message = '', $trigger = 0, $parent = 0, $status = '' ) {
500
501
		if ( is_array( $title_or_params ) ) {
502
			$title   = $title_or_params['title'];
503
			$message = $title_or_params['message'];
504
			$trigger = $title_or_params['trigger'];
505
			$parent  = $title_or_params['parent'];
506
			$status  = $title_or_params['status'];
507
		} else {
508
			$title = $title_or_params;
509
		}
510
511
		if ( ! is_array( $this->statuses_to_log ) ) {
0 ignored issues
show
introduced by
The condition is_array($this->statuses_to_log) is always true.
Loading history...
512
			if ( $status === $this->statuses_to_log ) {
513
				$this->add( $title, $message, $parent );
514
			} else {
515
				return;
516
			}
517
		}
518
519
		if ( true === $this->enabled && in_array( $status, $this->statuses_to_log, true ) ) {
520
			$triggers_to_log = maybe_unserialize( get_option( $this->option_prefix . 'triggers_to_log', array() ) );
521
			if ( in_array( $trigger, $triggers_to_log, true ) || 0 === $trigger ) {
0 ignored issues
show
Bug introduced by
It seems like $triggers_to_log can also be of type false; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

521
			if ( in_array( $trigger, /** @scrutinizer ignore-type */ $triggers_to_log, true ) || 0 === $trigger ) {
Loading history...
522
				$this->add( $title, $message, $parent );
523
			} elseif ( is_array( $trigger ) && array_intersect( $trigger, $triggers_to_log ) ) {
0 ignored issues
show
Bug introduced by
It seems like $triggers_to_log can also be of type false; however, parameter $arrays of array_intersect() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

523
			} elseif ( is_array( $trigger ) && array_intersect( $trigger, /** @scrutinizer ignore-type */ $triggers_to_log ) ) {
Loading history...
524
				$this->add( $title, $message, $parent );
525
			} elseif ( true === $this->debug ) {
526
				// if the plugin is in debug mode, treat all triggers as triggers to log.
527
				$this->add( $title, $message, $parent );
528
			}
529
		}
530
	}
531
532
	/**
533
	 * Create new log entry
534
	 *
535
	 * This is just a simple and fast way to log something. Use self::insert_log()
536
	 * if you need to store custom meta data
537
	 *
538
	 * @access      public
539
	 * @since       1.0
540
	 *
541
	 * @param       string $title A log post title.
542
	 *
543
	 * @uses        self::insert_log()
544
	 * @param       string $message The log message.
545
	 * @param       int    $parent The parent WordPress object.
546
	 * @param       string $type The type of log message; defaults to 'salesforce'.
547
	 *
548
	 * @return      int The ID of the new log entry
549
	 */
550
	public static function add( $title = '', $message = '', $parent = 0, $type = 'salesforce' ) {
551
552
		$log_data = array(
553
			'post_title'   => esc_html( $title ),
554
			'post_content' => wp_kses_post( $message ),
555
			'post_parent'  => absint( $parent ),
556
			'log_type'     => esc_attr( $type ),
557
		);
558
559
		return self::insert_log( $log_data );
560
561
	}
562
563
564
	/**
565
	 * Easily retrieves log items for a particular object ID
566
	 *
567
	 * @access      private
568
	 * @since       1.0
569
	 *
570
	 * @param       int    $object_id A WordPress object ID.
571
	 * @param       string $type The type of log item; defaults to 'salesforce' because that's the type of logs we create.
572
	 * @param       int    $paged show which page of results we want.
573
	 *
574
	 * @uses        self::get_connected_logs()
575
	 *
576
	 * @return      array
577
	 */
578
	public static function get_logs( $object_id = 0, $type = 'salesforce', $paged = null ) {
579
		return self::get_connected_logs(
580
			array(
581
				'post_parent' => (int) $object_id,
582
				'paged'       => (int) $paged,
583
				'log_type'    => (string) $type,
584
			)
585
		);
586
	}
587
588
589
	/**
590
	 * Retrieve all connected logs
591
	 *
592
	 * Used for retrieving logs related to particular items, such as a specific purchase.
593
	 *
594
	 * @access  private
595
	 * @since   1.0
596
	 *
597
	 * @param   Array $args An array of arguments for get_posts().
598
	 *
599
	 * @uses    wp_parse_args()
600
	 * @uses    get_posts()
601
	 * @uses    get_query_var()
602
	 * @uses    self::valid_type()
603
	 *
604
	 * @return  array / false
605
	 */
606
	public static function get_connected_logs( $args = array() ) {
607
608
		$defaults = array(
609
			'post_parent'    => 0,
610
			'post_type'      => 'wp_log',
611
			'posts_per_page' => 10,
612
			'post_status'    => 'publish',
613
			'paged'          => get_query_var( 'paged' ),
614
			'log_type'       => 'salesforce',
615
		);
616
617
		$query_args = wp_parse_args( $args, $defaults );
618
619
		if ( $query_args['log_type'] && self::valid_type( $query_args['log_type'] ) ) {
620
621
			$query_args['tax_query'] = array(
622
				array(
623
					'taxonomy' => 'wp_log_type',
624
					'field'    => 'slug',
625
					'terms'    => $query_args['log_type'],
626
				),
627
			);
628
629
		}
630
631
		$logs = get_posts( $query_args );
632
633
		if ( $logs ) {
634
			return $logs;
635
		}
636
637
		// no logs found.
638
		return false;
639
640
	}
641
642
643
	/**
644
	 * Retrieves number of log entries connected to particular object ID
645
	 *
646
	 * @access  private
647
	 * @since   1.0
648
	 *
649
	 * @param       int    $object_id A WordPress object ID.
650
	 * @param       string $type The type of log item; defaults to 'salesforce' because that's the type of logs we create.
651
	 * @param       array  $meta_query A WordPress meta query, parseable by WP_Meta_Query.
652
	 *
653
	 * @uses    WP_Query()
654
	 * @uses    self::valid_type()
655
	 *
656
	 * @return  int
657
	 */
658
	public static function get_log_count( $object_id = 0, $type = 'salesforce', $meta_query = null ) {
659
660
		$query_args = array(
661
			'post_parent'    => (int) $object_id,
662
			'post_type'      => 'wp_log',
663
			'posts_per_page' => 100,
664
			'post_status'    => 'publish',
665
		);
666
667
		if ( ! empty( $type ) && self::valid_type( $type ) ) {
668
669
			$query_args['tax_query'] = array(
670
				array(
671
					'taxonomy' => 'wp_log_type',
672
					'field'    => 'slug',
673
					'terms'    => sanitize_key( $type ),
674
				),
675
			);
676
677
		}
678
679
		if ( ! empty( $meta_query ) ) {
680
			$query_args['meta_query'] = $meta_query;
681
		}
682
683
		$logs = new WP_Query( $query_args );
684
685
		return (int) $logs->post_count;
686
687
	}
688
689
}
690