Issues (4138)

classes/class-admin.php (12 issues)

1
<?php
2
namespace lsx_health_plan\classes;
3
4
/**
5
 * LSX Health Plan Admin Class.
6
 *
7
 * @package lsx-health-plan
8
 */
9
class Admin {
10
11
	/**
12
	 * Holds class instance
13
	 *
14
	 * @since 1.0.0
15
	 *
16
	 * @var      object \lsx_health_plan\classes\Admin()
17
	 */
18
	protected static $instance = null;
19
20
	/**
21
	 * The post relation fields
22
	 *
23
	 * @var array
24
	 */
25
	public $connections = array();
26
27
	/**
28
	 * Stores the previous values needed to remove the post relations
29
	 *
30
	 * @var array
31
	 */
32
	public $previous_values = array();
33
34
	/**
35
	 * @var object \lsx_health_plan\classes\admin\Settings();
36
	 */
37
	public $settings;
38
39
	/**
40
	 * @var object \lsx_health_plan\classes\admin\Help_Page();
41
	 */
42
	public $help;
43
44
	/**
45
	 * Holds the settings page theme functions
46
	 *
47
	 * @var object \lsx_health_plan\classes\admin\Settings_Theme();
48
	 */
49
	public $settings_theme;
50
51
	/**
52
	 * Constructor
53
	 */
54
	public function __construct() {
55
		$this->load_classes();
56
		add_action( 'admin_menu', array( $this, 'order_menus' ), 200 );
57
		add_action( 'admin_enqueue_scripts', array( $this, 'assets' ) );
58
		add_filter( 'cmb2_override_meta_save', array( $this, 'save_previous_values' ), 20, 4 );
59
		add_filter( 'cmb2_override_meta_remove', array( $this, 'save_previous_values' ), 20, 4 );
60
		add_action( 'cmb2_save_field', array( $this, 'post_relations' ), 20, 4 );
61
		add_action( 'cmb2_save_field', array( $this, 'create_query_fields' ), 20, 4 );
62
		add_action( 'before_delete_post', array( $this, 'delete_post_meta_connections' ), 20, 1 );
63
		add_action( 'cmb2_save_post_fields', array( $this, 'extract_plan_fields' ), 10, 4 );
64
65
		//add_action( 'cmb2_save_post_fields', array( $this, 'debugger_for_cmb2' ), 10, 4 );
66
67
		// Customizer.
68
		add_filter( 'lsx_customizer_colour_selectors_body', array( $this, 'customizer_body_colours_handler' ), 15, 2 );
69
	}
70
71
	/**
72
	 * Return an instance of this class.
73
	 *
74
	 * @return object \lsx\member_directory\classes\Admin()    A single instance of this class.
75
	 */
76
	public static function get_instance() {
77
		// If the single instance hasn't been set, set it now.
78
		if ( null === self::$instance ) {
79
			self::$instance = new self();
80
		}
81
		return self::$instance;
82
	}
83
84
	/**
85
	 * Loads the admin subclasses
86
	 */
87
	private function load_classes() {
88
		require_once LSX_HEALTH_PLAN_PATH . 'classes/admin/class-settings.php';
89
		$this->settings = admin\Settings::get_instance();
90
91
		require_once LSX_HEALTH_PLAN_PATH . 'classes/admin/class-help-page.php';
92
		$this->help = admin\Help_Page::get_instance();
93
94
		require_once LSX_HEALTH_PLAN_PATH . 'classes/admin/class-settings-theme.php';
95
		$this->settings_theme = admin\Settings_Theme::get_instance();
96
	}
97
98
	/**
99
	 * Orders the HP menu Items
100
	 *
101
	 * @return void
102
	 */
103
	public function order_menus() {
104
		global $menu, $submenu;
105
		if ( ! empty( $submenu ) ) {
106
			$parent_check = array(
107
				'edit.php?post_type=plan',
108
				'edit.php?post_type=workout',
109
				'edit.php?post_type=meal',
110
			);
111
			foreach ( $submenu as $menu_id => $menu_values ) {
112
				if ( in_array( $menu_id, $parent_check ) ) {
113
					foreach ( $menu_values as $sub_menu_key => $sub_menu_values ) {
114
						switch ( $sub_menu_values[0] ) {
115
116
							case __( 'Add New', 'lsx-health-plan' ):
117
								unset( $submenu[ $menu_id ][ $sub_menu_key ] );
118
								break;
119
120
							case __( 'All', 'lsx-health-plan' ):
121
								$title = $sub_menu_values[0];
122
								// Check and change the label.
123
								switch ( $sub_menu_values[2] ) {
124
									case 'edit.php?post_type=meal':
125
										$title = esc_attr__( 'Meals', 'lsx-health-plan' );
126
										break;
127
128
									case 'edit.php?post_type=recipe':
129
										$title = esc_attr__( 'Recipes', 'lsx-health-plan' );
130
										break;
131
132
									case 'edit.php?post_type=workout':
133
										$title = esc_attr__( 'Workouts', 'lsx-health-plan' );
134
										break;
135
136
									case 'edit.php?post_type=plan':
137
										$title = esc_attr__( 'Plans', 'lsx-health-plan' );
138
										break;
139
140
									case 'edit.php?post_type=video':
141
										$title = esc_attr__( 'Videos', 'lsx-health-plan' );
142
										break;
143
144
									case 'edit.php?post_type=exercise':
145
										$title = esc_attr__( 'Exercises', 'lsx-health-plan' );
146
										break;
147
148
									case 'edit.php?post_type=tip':
149
										$title = esc_attr__( 'Tips', 'lsx-health-plan' );
150
										break;
151
152
									default:
153
										break;
154
								}
155
								$submenu[ $menu_id ][ $sub_menu_key ][0] = $title; // @codingStandardsIgnoreLine
156
								break;
157
158
							default:
159
								break;
160
						}
161
					}
162
				}
163
			}
164
		}
165
	}
166
167
	/**
168
	 * Undocumented function
169
	 *
170
	 * @return void
171
	 */
172
	public function assets() {
173
		wp_enqueue_script( 'media-upload' );
174
		wp_enqueue_script( 'thickbox' );
175
		wp_enqueue_style( 'thickbox' );
176
177
		wp_enqueue_script( 'lsx-health-plan-admin', LSX_HEALTH_PLAN_URL . 'assets/js/lsx-health-plan-admin.min.js', array( 'jquery' ), LSX_HEALTH_PLAN_VER, true );
178
		wp_enqueue_style( 'lsx-health-plan-admin', LSX_HEALTH_PLAN_URL . 'assets/css/lsx-health-plan-admin.css', array(), LSX_HEALTH_PLAN_VER );
179
	}
180
181
	/**
182
	 * Returns the registered connections.
183
	 *
184
	 * @return void
185
	 */
186
	public function get_connections() {
187
		return apply_filters( 'lsx_health_plan_connections', $this->connections );
188
	}
189
190
	/**
191
	 * Saves the previous values before they are overwritten by the new ones.
192
	 *
193
	 * @param [type] $value_to_save
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
194
	 * @param [type] $a
195
	 * @param [type] $args
196
	 * @param [type] $cmb2
197
	 * @return void
198
	 */
199
	public function save_previous_values( $value_to_save, $a, $args, $cmb2 ) {
200
		if ( isset( $cmb2->data_to_save['ID'] ) ) {
201
			$connections = $this->get_connections();
202
			$post_type   = get_post_type( $cmb2->data_to_save['ID'] );
203
			if ( isset( $connections[ $post_type ] ) && array_key_exists( $a['field_id'], $connections[ $post_type ] ) ) {
204
				// Get the previous values if the field, so we can run through them and remove the current ID from them later.
205
				$this->previous_values = get_post_meta( $a['id'], $a['field_id'], true );
0 ignored issues
show
Documentation Bug introduced by
It seems like get_post_meta($a['id'], $a['field_id'], true) can also be of type false or string. However, the property $previous_values 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...
206
			}
207
		}
208
		return $value_to_save;
209
	}
210
211
	/**
212
	 * Sets up the "post relations"
213
	 *
214
	 * @return    void
215
	 */
216
	public function post_relations( $field_id, $updated, $action, $cmb2 ) {
217
		// If the connections are empty then skip this function.
218
		$connections = $this->get_connections();
219
		if ( empty( $connections ) ) {
220
			return;
221
		}
222
223
		// If the field has been updated.
224
		if ( isset( $cmb2->data_to_save['ID'] ) ) {
225
			$post_type = get_post_type( $cmb2->data_to_save['ID'] );
226
			if ( isset( $connections[ $post_type ] ) && array_key_exists( $field_id, $connections[ $post_type ] ) ) {
227
				$saved_values = get_post_meta( $cmb2->data_to_save['ID'], $field_id, true );
228
229
				if ( 'updated' === $action ) {
230
					$this->add_connected_posts( $saved_values, $cmb2->data_to_save['ID'], $connections[ $post_type ][ $field_id ] );
231
					// Check if any posts have been removed.
232
					if ( count( $this->previous_values ) > count( $saved_values ) ) {
0 ignored issues
show
It seems like $saved_values can also be of type false and null and string; however, parameter $value of count() does only seem to accept Countable|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

232
					if ( count( $this->previous_values ) > count( /** @scrutinizer ignore-type */ $saved_values ) ) {
Loading history...
233
						$posts_to_remove = array_diff( $this->previous_values, $saved_values );
0 ignored issues
show
It seems like $saved_values can also be of type false and null and string; however, parameter $excludes of array_diff() 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

233
						$posts_to_remove = array_diff( $this->previous_values, /** @scrutinizer ignore-type */ $saved_values );
Loading history...
234
						if ( ! empty( $posts_to_remove ) ) {
235
							$this->remove_connected_posts( $posts_to_remove, $cmb2->data_to_save['ID'], $connections[ $post_type ][ $field_id ] );
236
						}
237
					}
238
				} else if ( 'removed' === $action && ! empty( $this->previous_values ) ) {
239
					$this->remove_connected_posts( $this->previous_values, $cmb2->data_to_save['ID'], $connections[ $post_type ][ $field_id ] );
240
				}
241
			}
242
		}
243
	}
244
245
	/**
246
	 * Updates the connected posts witht he current post ID
247
	 *
248
	 * @param [type] $values
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
249
	 * @param [type] $current_id
250
	 * @param [type] $connected_key
251
	 * @return void
252
	 */
253
	public function add_connected_posts( $values, $current_id, $connected_key ) {
254
		foreach ( $values as $value ) {
255
			$current_post_array = get_post_meta( $value, $connected_key, true );
256
			$previous_values    = $current_post_array;
257
258
			if ( ! empty( $current_post_array ) ) {
259
				$current_post_array = array_map( 'strval', $current_post_array );
0 ignored issues
show
It seems like $current_post_array can also be of type string; however, parameter $array of array_map() 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

259
				$current_post_array = array_map( 'strval', /** @scrutinizer ignore-type */ $current_post_array );
Loading history...
260
				array_unique( $current_post_array );
261
			}
262
263
			// If the current connected post has no saved connections then we create it.
264
			if ( false === $current_post_array || empty( $current_post_array ) ) {
265
				$current_post_array = array( $current_id );
266
			} elseif ( ! in_array( (string) $current_id, $current_post_array, true ) ) {
0 ignored issues
show
It seems like $current_post_array can also be of type string; 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

266
			} elseif ( ! in_array( (string) $current_id, /** @scrutinizer ignore-type */ $current_post_array, true ) ) {
Loading history...
267
				$current_post_array[] = $current_id;
268
			}
269
270
			// Check if the values are empty, if not update them.
271
			if ( ! empty( $current_post_array ) ) {
272
				update_post_meta( $value, $connected_key, $current_post_array, $previous_values );
273
			}
274
		}
275
	}
276
277
	/**
278
	 * Removes the post ID from the connected posts.
279
	 *
280
	 * @param [type] $values
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
281
	 * @param [type] $current_ID
282
	 * @param [type] $connected_key
283
	 * @return void
284
	 */
285
	public function remove_connected_posts( $values, $current_ID, $connected_key ) {
286
		foreach ( $values as $value ) {
287
			$current_post_array = get_post_meta( $value, $connected_key, true );
288
			$new_array          = array();
289
			// Loop through only if the current ID has been saved against the post.
290
			if ( in_array( $current_ID, $current_post_array, false ) ) {
0 ignored issues
show
It seems like $current_post_array can also be of type false and null and string; 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

290
			if ( in_array( $current_ID, /** @scrutinizer ignore-type */ $current_post_array, false ) ) {
Loading history...
291
292
				// Loop through all the connected saved IDS.
293
				foreach ( $current_post_array as $cpa ) {
294
					if ( (int) $cpa !== (int) $current_ID ) {
295
						$new_array[] = $cpa;
296
					}
297
				}
298
				if ( ! empty( $new_array ) ) {
299
					$new_array = array_unique( $new_array );
300
					delete_post_meta( $value, $connected_key );
301
					add_post_meta( $value, $connected_key, $new_array, true );
302
				} else {
303
					delete_post_meta( $value, $connected_key );
304
				}
305
			}
306
		}
307
	}
308
309
	/**
310
	 * Runs on 'before_delete_post' to run through and remove this post ID from its connected values.
311
	 *
312
	 * @param string $item_id
313
	 * @return void
314
	 */
315
	public function delete_post_meta_connections( $item_id = '' ) {
316
		if ( '' !== $item_id ) {
317
			$post_type   = get_post_type( $item_id );
0 ignored issues
show
$item_id of type string is incompatible with the type WP_Post|integer|null expected by parameter $post of get_post_type(). ( Ignorable by Annotation )

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

317
			$post_type   = get_post_type( /** @scrutinizer ignore-type */ $item_id );
Loading history...
318
			$connections = $this->get_connections();
319
			if ( isset( $connections[ $post_type ] ) && ! empty( $connections[ $post_type ] ) && is_array( $connections[ $post_type ] ) ) {
320
				foreach ( $connections[ $post_type ] as $this_key => $connected_key ) {
321
					$this->delete_connected_items( $item_id, $this_key, $connected_key );
322
				}
323
			}
324
		}
325
	}
326
327
	/**
328
	 * This function will remvoe the post id fomr its connected posts.
329
	 *
330
	 * @param string $item_id
331
	 * @param string $this_key
332
	 * @param string $connected_key
333
	 * @return void
334
	 */
335
	public function delete_connected_items( $item_id = '', $this_key, $connected_key ) {
336
		if ( '' !== $item_id ) {
337
			$connected_items = get_post_meta( $item_id, $this_key, true );
0 ignored issues
show
$item_id of type string is incompatible with the type integer expected by parameter $post_id of get_post_meta(). ( Ignorable by Annotation )

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

337
			$connected_items = get_post_meta( /** @scrutinizer ignore-type */ $item_id, $this_key, true );
Loading history...
338
			if ( ! empty( $connected_items ) ) {
339
				foreach ( $connected_items as $con_id ) {
340
					// Get the connected item array from the connected item.
341
					$their_connections = get_post_meta( $con_id, $connected_key, true );
342
					if ( ! empty( $their_connections ) ) {
343
						$new_connections = $their_connections;
344
						// Run through the array and remove the post to be deleteds ID.
345
						foreach ( $their_connections as $ckey => $cvalue ) {
346
							if ( (int) $item_id === (int) $cvalue ) {
347
								unset( $new_connections[ $ckey ] );
348
							}
349
						}
350
						// Now we save the field.
351
						update_post_meta( $con_id, $connected_key, $new_connections, $their_connections );
352
					}
353
				}
354
			}
355
		}
356
	}
357
358
	/**
359
	 * Saves the serialized post ids in singular custom fields so they are easily queried using WP_Query
360
	 *
361
	 * @return    void
362
	 */
363
	public function create_query_fields( $field_id, $updated, $action, $cmb2 ) {
364
		// If the connections are empty then skip this function.
365
		$search_fields = array(
366
			'plan_product',
367
		);
368
		if ( ! in_array( $field_id, $search_fields ) ) {
369
			return;
370
		}
371
372
		// If the field has been updated.
373
		if ( isset( $cmb2->data_to_save['ID'] ) && isset( $cmb2->data_to_save[ $field_id . '_results' ] ) && ! empty( $cmb2->data_to_save[ $field_id . '_results' ] ) ) {
374
			delete_post_meta( $cmb2->data_to_save['ID'], '_' . $field_id . '_id' );
375
			foreach ( $cmb2->data_to_save[ $field_id . '_results' ] as $temp ) {
376
				add_post_meta( $cmb2->data_to_save['ID'], '_' . $field_id . '_id', $temp, false );
377
			}
378
		}
379
	}
380
381
	/**
382
	 * Extract the plan fields so they save to an indexable array.
383
	 *
384
	 * @param [type] $object_id
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
385
	 * @param [type] $cmb_id
386
	 * @param [type] $updated
387
	 * @param [type] $cmb2
388
	 * @return void
389
	 */
390
	public function extract_plan_fields( $object_id, $cmb_id, $updated, $cmb2 ) {
391
		if ( 'plan_sections_metabox' === $cmb_id ) {
392
			// Check if our fields are available, and cycle through them.
393
			if ( isset( $cmb2->data_to_save['plan_sections'] ) && ! empty( $cmb2->data_to_save['plan_sections'] ) ) {
394
				$fields_to_save = array();
395
				// Run through each row of fields.
396
				foreach ( $cmb2->data_to_save['plan_sections'] as $field_index => $fields ) {
397
					// Run through each field in that section.
398
					foreach ( $fields as $field_key => $field_value ) {
399
						$stored_values_key = 'plan_sections_' . $field_index . '_' . $field_key . '_store';
400
						if ( isset( $cmb2->data_to_save[ $stored_values_key ] ) && ! empty( $cmb2->data_to_save[ $stored_values_key ] ) ) {
401
							$stored_values = $cmb2->data_to_save[ $stored_values_key ];
402
							$stored_values = explode( ',', $stored_values );
403
							foreach ( $stored_values as $id_to_save ) {
404
								$fields_to_save[ $field_key ][] = $id_to_save;
405
							}
406
						}
407
					}
408
				}
409
				$this->save_field_array( $object_id, $fields_to_save );
410
			}
411
		}
412
	}
413
414
	/**
415
	 * Runs through the supplied array and saved the fields to the current Object.
416
	 *
417
	 * @param integer $object_id
418
	 * @param array   $fields_to_save
419
	 * @return void
420
	 */
421
	public function save_field_array( $object_id = 0, $fields_to_save = array() ) {
422
423
		// Run through the fields and save the meta items.
424
		if ( ! empty( $fields_to_save ) ) {
425
			foreach ( $fields_to_save as $field_key => $field_values ) {
426
				delete_post_meta( $object_id, $field_key );
427
428
				$field_values = array_unique( $field_values );
429
				foreach ( $field_values as $field_value ) {
430
					add_post_meta( $object_id, $field_key, $field_value, false );
431
				}
432
			}
433
		}
434
	}
435
436
	public function debugger_for_cmb2( $object_id, $cmb_id, $updated, $cmb2 ) {
437
		if ( 'workout_section_6_metabox' === $cmb_id ) {
438
			die();
439
		}
440
	}
441
442
	/**
443
	 * Handle body colours that might be change by LSX Customizer.
444
	 */
445
	public function customizer_body_colours_handler( $css, $colors ) {
446
		$css .= '
447
			@import "' . LSX_HEALTH_PLAN_PATH . '/assets/css/scss/partials/customizer-health-plan-body-colours";
448
449
			/**
450
			 * LSX Customizer - Body (LSX Health Plan)
451
			 */
452
			@include customizer-health-plan-body-colours (
453
				$bg: 		' . $colors['background_color'] . ',
454
				$breaker: 	' . $colors['body_line_color'] . ',
455
				$color:    	' . $colors['body_text_color'] . ',
456
				$link:    	' . $colors['body_link_color'] . ',
457
				$hover:    	' . $colors['body_link_hover_color'] . ',
458
				$small:    	' . $colors['body_text_small_color'] . '
459
			);
460
		';
461
462
		return $css;
463
	}
464
}
465