Completed
Push — master ( add22c...fb4c0b )
by Mike
02:33
created

Metaboxes::get_acf_free_metaboxes()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 32
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
cc 5
eloc 12
c 2
b 1
f 1
nc 5
nop 1
dl 0
loc 32
rs 8.439
1
<?php
2
namespace testContent;
3
4
/**
5
 * Class for handling CMB data
6
 *
7
 * @package    WordPress
8
 * @subpackage Evans
9
 * @author     Old Town Media
10
 */
11
class Metaboxes{
12
13
	/**
14
	 * Decide which cmb library to try and loop to get our metaboxes.
15
	 *
16
	 * Due to supporting multiple CMB libraries, we need to check which library
17
	 * is used on our site and then run the appropriate function. Currently
18
	 * supported libraries are CMB2 & Custom Metaboxes and Fields.
19
	 *
20
	 * @see get_cmb2_metaboxes, get_cmb1_metaboxes
21
	 *
22
	 * @param string $slug Post Type slug ID.
23
	 * @return array Fields to fill in for our post object.
24
	 */
25
	public function get_metaboxes( $slug ){
26
		$cmb2_fields = $cmb_fields = $acf_fields = array();
27
28
		// CMB2
29
		if ( class_exists( 'CMB2', false ) ) {
30
			$cmb2_fields = $this->get_cmb2_metaboxes( $slug );
31
		}
32
33
		// Custom Metaboxes and Fields (CMB1)
34
		if ( class_exists( 'cmb_Meta_Box', false ) ) {
35
			$cmb_fields = $this->get_cmb1_metaboxes( $slug );
36
		}
37
38
		// Advanced Custom Fields (ACF Free)
39
		if ( class_exists( 'acf', false ) ) {
40
			$acf_fields = $this->get_acf_free_metaboxes( $slug );
41
		}
42
43
		// Return our array
44
		return array_merge( $cmb2_fields, $cmb_fields, $acf_fields );
45
46
	}
47
48
49
	/**
50
	 * Gets the metaboxes assigned to a custom post type in ACF.
51
	 *
52
	 * @access private
53
	 *
54
	 * @see get_all_acf_field_groups, is_acf_field_in_post_type
55
	 *
56
	 * @param string $slug Post type.
57
	 * @return array Fields array.
58
	 */
59
	private function get_acf_free_metaboxes( $slug ){
60
61
		$fields = array();
62
63
		// This damn plugin. Is. A. Freaking. Nightmare.
64
		$fieldsets = $this->get_all_acf_field_groups();
65
66
		// Return empty array if there are no fieldsets at all
67
		if ( empty( $fieldsets ) ){
68
			return $fields;
69
		}
70
71
		// Loop through each fieldset for possible matches
72
		foreach ( $fieldsets as $fieldset ){
73
74
			if ( $this->is_acf_field_in_post_type( $slug, $fieldset ) ){
75
76
				// If this is the first group of fields, simply set the value
77
				// Else, merge this group with the previous one
78
				if ( empty( $fields ) ){
79
					$fields = $fieldset->fields;
80
				} else {
81
					$fields = array_merge( $fields, $fieldset->fields );
82
				}
83
84
			}
85
86
		}
87
88
		return $fields;
89
90
	}
91
92
93
	/**
94
	 * Check if a group of fields is in a custom post type.
95
	 *
96
	 * @access private
97
	 *
98
	 * @param string $slug Post type slug.
99
	 * @param object $fieldset Fieldset group.
100
	 * @return boolean Whether or not the grouping is assigned to the post type.
101
	 */
102
	private function is_acf_field_in_post_type( $slug, $fieldset ){
103
104
		// Make sure we have something to parse
105
		if ( empty( $fieldset ) ){
106
			return false;
107
		}
108
109
		// Loop through the rules to check for post type matches
110
		foreach ( $fieldset->rules as $rule ){
111
			if ( $rule['param'] === 'post_type' && $rule['value'] === $slug ){
112
				return true;
113
			}
114
		}
115
116
		// Everything passed, yay!
117
		return false;
118
119
	}
120
121
122
	/**
123
	 * Loop through and retrive all acf cpts and cmb.
124
	 *
125
	 * ACF stores their data in custom post types and unfortunately named cmbs.
126
	 * Therefore, we have to loop through all acfs and sort through the mish-mash
127
	 * of messy data and make something clean of it.
128
	 *
129
	 * @access private
130
	 *
131
	 * @return array All acf fieldsets.
132
	 */
133
	private function get_all_acf_field_groups(){
134
		$info = $rules = $fields = array();
135
136
		$args = array(
137
			'post_type'		=> 'acf',
138
			'posts_per_page'=> 500
139
		);
140
141
		$objects = new \WP_Query( $args );
142
143
		if ( $objects->have_posts() ) :
144
			while ( $objects->have_posts() ) : $objects->the_post();
145
146
				$data = get_metadata( 'post', get_the_id() );
147
148
				foreach ( $data['rule'] as $rule ){
149
					$rules[] = unserialize( $rule );
150
				}
151
152
				foreach ( $data as $key => $value ){
153
					if ( substr( $key, 0, 6 ) == 'field_' ) :
154
						$field_detail = unserialize( $value[0] );
155
						$fields[] = array(
156
							'key'	 => $field_detail['key'],
157
							'type'	 => $field_detail['type'],
158
							'name'	 => $field_detail['label'],
159
							'id'	 => $field_detail['name'],
160
							'source' =>'acf'
161
						);
162
					endif;
163
				}
164
165
				$info[] = (object) array(
166
					'rules'		=> $rules,
167
					'fields'	=> $fields
168
				);
169
170
			endwhile;
171
		endif;
172
173
		return $info;
174
175
	}
176
177
178
	/**
179
	 * Gets all CMB2 custom metaboxes associated with a post type.
180
	 *
181
	 * Loops through all custom metabox fields registered with CMB2 and
182
	 * looks through them for matches on the given post type ID. Returns a single
183
	 * array of all boxes associated with the post type.
184
	 *
185
	 * @access private
186
	 *
187
	 * @see cmb2_meta_boxes
188
	 *
189
	 * @param string $slug a custom post type ID.
190
	 * @return array Array of fields.
191
	 */
192
	private function get_cmb2_metaboxes( $slug ){
193
194
		$fields = array();
195
196
		// Get all metaboxes from CMB2 library
197
		$all_metaboxes = apply_filters( 'cmb2_meta_boxes', array() );
198
199
		// Loop through all possible sets of metaboxes added the old way
200
		foreach ( $all_metaboxes as $metabox_array ){
201
202
			// If the custom post type ID matches this set of fields, set & stop
203
			if ( in_array( $slug, $metabox_array['object_types'] ) ) {
204
205
				// If this is the first group of fields, simply set the value
206
				// Else, merge this group with the previous one
207
				if ( empty( $fields ) ){
208
					$fields = $metabox_array['fields'];
209
				} else {
210
					$fields = array_merge( $fields, $metabox_array['fields'] );
211
				}
212
			}
213
214
		}
215
216
		// Loop through all metaboxes added the new way
217
		foreach ( \CMB2_Boxes::get_all() as $cmb ) {
218
219
			// Create the default
220
			$match = false;
221
222
			// Establish correct cmb types
223
			if ( is_string( $cmb->meta_box['object_types'] ) ){
224
				if ( $cmb->meta_box['object_types'] == $slug ){
225
					$match = true;
226
				}
227
			} else {
228
				if ( in_array( $slug, $cmb->meta_box['object_types'] ) ){
229
					$match = true;
230
				}
231
			}
232
233
			if ( $match !== true ){
234
				continue;
235
			}
236
237
			if ( empty( $fields ) ){
238
				$fields = $cmb->meta_box['fields'];
239
			} else {
240
				$fields = array_merge( $fields, $cmb->meta_box['fields'] );
241
			}
242
243
		}
244
245
		return $fields;
246
247
	}
248
249
250
	/**
251
	 * Gets all CMB1 custom metaboxes associated with a post type.
252
	 *
253
	 * Loops through all custom metabox fields registered with CMB2 and
254
	 * looks through them for matches on the given post type ID. Returns a single
255
	 * array of all boxes associated with the post type.
256
	 *
257
	 * @access private
258
	 *
259
	 * @see cmb_meta_boxes
260
	 *
261
	 * @param string $slug a custom post type ID.
262
	 * @return array Array of fields.
263
	 */
264
	private function get_cmb1_metaboxes( $slug ){
265
266
		$fields = array();
267
268
		// Get all metaboxes from CMB2 library
269
		$all_metaboxes = apply_filters( 'cmb_meta_boxes', array() );
270
271
		// Loop through all possible sets of metaboxes
272
		foreach ( $all_metaboxes as $metabox_array ){
273
274
			// If the custom post type ID matches this set of fields, set & stop
275
			if ( in_array( $slug, $metabox_array['pages'] ) ) {
276
277
				// If this is the first group of fields, simply set the value
278
				// Else, merge this group with the previous one
279
				if ( empty( $fields ) ){
280
					$fields = $metabox_array['fields'];
281
				} else {
282
					$fields = array_merge( $fields, $metabox_array['fields'] );
283
				}
284
			}
285
286
		}
287
288
		return $fields;
289
290
	}
291
292
293
	/**
294
	 * Assigns the proper testing data to a custom metabox.
295
	 *
296
	 * Swaps through the possible types of CMB2 supported fields and
297
	 * insert the appropriate data based on type & id.
298
	 * Some types are not yet supported due to low frequency of use.
299
	 *
300
	 * @see TestContent, add_post_meta
301
	 *
302
	 * @param int $post_id Single post ID.
303
	 * @param array $cmb custom metabox array from CMB2.
304
	 */
305
	public function random_metabox_content( $post_id, $cmb, $connected ){
306
		$value = '';
307
308
		// First check that our post ID & cmb array aren't empty
309
		if ( empty( $cmb ) || empty( $post_id ) ){
310
			return;
311
		}
312
313
		// Fetch the appropriate type of data and return
314
		switch( $cmb['type'] ){
315
316
			case 'text':
317
			case 'text_small':
318
			case 'text_medium':
319
320
				// If phone is in the id, fetch a phone #
321
				if ( stripos( $cmb['id'], 'phone' ) ){
322
					$value = TestContent::phone();
323
324
				// If email is in the id, fetch an email address
325
				} elseif ( stripos( $cmb['id'], 'email' ) ){
326
					$value = TestContent::email();
327
328
				// If time is in the id, fetch a time string
329
				} elseif ( stripos( $cmb['id'], 'time' ) ){
330
					$value = TestContent::time();
331
332
				// Otherwise, just a random text string
333
				} else {
334
					$value = TestContent::title( rand( 10, 50 ) );
335
				}
336
337
				break;
338
339
			case 'text_url':
340
341
				$value = TestContent::link();
342
343
				break;
344
345
			case 'text_email' :
346
			case 'email':
347
348
				$value = TestContent::email();
349
350
				break;
351
352
			case 'number' :
353
354
				$value = rand( 1, 10000000 );
355
356
				break;
357
358
			case 'text_time':
359
360
				$value = TestContent::time();
361
362
				break;
363
364
			case 'select_timezone':
365
366
				$value = TestContent::timezone();
367
368
				break;
369
370
			case 'text_date':
371
372
				$value = TestContent::date( 'm/d/Y' );
373
374
				break;
375
376
			case 'text_date_timestamp':
377
			case 'text_datetime_timestamp':
378
379
				$value = TestContent::date( 'U' );
380
381
				break;
382
383
			// case 'text_datetime_timestamp_timezone': break;
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
384
385
			case 'text_money':
386
387
				$value = rand( 0, 100000 );
388
389
				break;
390
391
			case 'test_colorpicker':
392
393
				$value = '#' . str_pad( dechex( mt_rand( 0, 0xFFFFFF ) ), 6, '0', STR_PAD_LEFT );
394
395
				break;
396
397
			case 'textarea':
398
			case 'textarea_small':
399
			case 'textarea_code':
400
401
				$value = TestContent::plain_text();
402
403
				break;
404
405
			case 'select':
406
			case 'radio_inline':
407
			case 'radio':
408
409
				// Grab a random item out of the array and return the key
410
				$new_val = array_slice( $cmb['options'], rand( 0, count( $cmb['options'] ) ), 1 );
411
				$value = key( $new_val );
412
413
				break;
414
415
			// case 'taxonomy_radio': break;
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
416
			// case 'taxonomy_select': break;
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
417
			// case 'taxonomy_multicheck': break;
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
418
419
			case 'checkbox':
420
421
				// 50/50 odds of being turned on
422
				if ( rand( 0, 1 ) == 1 ){
423
					$value = 'on';
424
				}
425
426
				break;
427
428
			case 'multicheck':
429
430
				$new_option = array();
431
432
				// Loop through each of our options
433
				foreach ( $cmb['options'] as $key => $value ){
434
435
					// 50/50 chance of being included
436
					if ( rand( 0, 1 ) ){
437
						$new_option[] = $key;
438
					}
439
440
				}
441
442
				$value = $new_option;
443
444
				break;
445
446
			case 'wysiwyg':
447
448
				$value = TestContent::paragraphs();
449
450
				break;
451
452
			case 'file':
453
454
				if ( true == $connected ){
455
					$value = TestContent::image( $post_id );
456
				}
457
458
				break;
459
460
			// case 'file_list': break;
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
461
462
			case 'oembed':
463
464
				$value = TestContent::oembed();
465
466
				break;
467
468
		}
469
470
		// Value must exist to attempt to insert
471
		if ( ! empty( $value ) && ! is_wp_error( $value ) ){
472
473
			$this->update_meta( $post_id, $value, $cmb );
474
475
		// If we're dealing with a WP Error object, just return the message for debugging
476
		} elseif ( is_wp_error( $value ) ){
477
			return $value->get_error_message();
478
		}
479
480
	} // end random_metabox_content
481
482
483
	/**
484
	 * Update the metabox with new data.
485
	 *
486
	 * @access private
487
	 *
488
	 * @see add_post_meta
489
	 *
490
	 * @param int $post_id Post ID.
491
	 * @param string $value Value to add into the database.
492
	 * @param array $cmb SMB data.
493
	 */
494
	private function update_meta( $post_id, $value, $cmb ){
495
496
		$type 	= $cmb['type'];
497
		$id		= $cmb['id'];
498
		$value = apply_filters( "tc_{$type}_metabox", $value );	// Filter by metabox type
499
		$value = apply_filters( "tc_{$id}_metabox", $value ); // Filter by metabox ID
500
501
		// Files must be treated separately - they use the attachment ID
502
		// & url of media for separate cmb values.
503
		if ( $cmb['type'] != 'file' ){
504
			add_post_meta( $post_id, $cmb['id'], $value, true );
505
		} else {
506
			add_post_meta( $post_id, $cmb['id'].'_id', $value, true );
507
			add_post_meta( $post_id, $cmb['id'], wp_get_attachment_url( $value ), true );
508
		}
509
510
		// Add extra, redundant meta. Because, why not have rows for the price of one?
511
		if ( isset( $cmb['source'] ) && $cmb['source'] === 'acf' ){
512
			add_post_meta( $post_id, '_' . $cmb['id'], $cmb['key'], true );
513
		}
514
515
	}
516
517
}
518