acf_field_relationship::validate_value()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 23

Duplication

Lines 23
Ratio 100 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 4
dl 23
loc 23
rs 9.552
c 0
b 0
f 0
1
<?php
2
3
/*
4
*  ACF Relationship Field Class
5
*
6
*  All the logic for this field type
7
*
8
*  @class 		acf_field_relationship
9
*  @extends		acf_field
10
*  @package		ACF
11
*  @subpackage	Fields
12
*/
13
14
if( ! class_exists('acf_field_relationship') ) :
15
16
class acf_field_relationship extends acf_field {
17
	
18
	
19
	/*
20
	*  __construct
21
	*
22
	*  This function will setup the field type data
23
	*
24
	*  @type	function
25
	*  @date	5/03/2014
26
	*  @since	5.0.0
27
	*
28
	*  @param	n/a
29
	*  @return	n/a
30
	*/
0 ignored issues
show
Documentation introduced by
The doc-type n/a could not be parsed: Unknown type name "n/a" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
31
	
32
	function __construct() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
33
		
34
		// vars
35
		$this->name = 'relationship';
36
		$this->label = __("Relationship",'acf');
0 ignored issues
show
Bug introduced by
The property label does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
37
		$this->category = 'relational';
38
		$this->defaults = array(
39
			'post_type'			=> array(),
40
			'taxonomy'			=> array(),
41
			'min' 				=> 0,
42
			'max' 				=> 0,
43
			'filters'			=> array('search', 'post_type', 'taxonomy'),
44
			'elements' 			=> array(),
45
			'return_format'		=> 'object'
46
		);
47
		$this->l10n = array(
48
			'min'		=> __("Minimum values reached ( {min} values )",'acf'),
49
			'max'		=> __("Maximum values reached ( {max} values )",'acf'),
50
			'loading'	=> __('Loading','acf'),
51
			'empty'		=> __('No matches found','acf'),
52
		);
53
		
54
		
55
		// extra
56
		add_action('wp_ajax_acf/fields/relationship/query',			array($this, 'ajax_query'));
57
		add_action('wp_ajax_nopriv_acf/fields/relationship/query',	array($this, 'ajax_query'));
58
		
59
		
60
		// do not delete!
61
    	parent::__construct();
62
    	
63
	}
64
	
65
	
66
	/*
67
	*  get_choices
68
	*
69
	*  This function will return an array of data formatted for use in a select2 AJAX response
70
	*
71
	*  @type	function
72
	*  @date	15/10/2014
73
	*  @since	5.0.9
74
	*
75
	*  @param	$options (array)
76
	*  @return	(array)
77
	*/
78
	
79
	function get_choices( $options = array() ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
80
		
81
   		// defaults
82
   		$options = acf_parse_args($options, array(
83
			'post_id'			=> 0,
84
			's'					=> '',
85
			'post_type'			=> '',
86
			'taxonomy'			=> '',
87
			'lang'				=> false,
88
			'field_key'			=> '',
89
			'paged'				=> 1
90
		));
91
		
92
		
93
		// vars
94
   		$r = array();
95
   		$args = array();
96
   		
97
   		
98
   		// paged
99
   		$args['posts_per_page'] = 20;
100
   		$args['paged'] = $options['paged'];
101
   		
102
		
103
		// load field
104
		$field = acf_get_field( $options['field_key'] );
105
		
106
		if( !$field ) {
107
		
108
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by acf_field_relationship::get_choices of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
109
			
110
		}
111
		
112
		
113
		// update $args
114
		if( !empty($options['post_type']) ) {
115
			
116
			$args['post_type'] = acf_get_array( $options['post_type'] );
117
		
118
		} elseif( !empty($field['post_type']) ) {
119
		
120
			$args['post_type'] = acf_get_array( $field['post_type'] );
121
			
122
		} else {
123
			
124
			$args['post_type'] = acf_get_post_types();
125
		}
126
		
127
		
128
		// update taxonomy
129
		$taxonomies = array();
0 ignored issues
show
Unused Code introduced by
$taxonomies is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
130
		
131
		if( !empty($options['taxonomy']) ) {
132
			
133
			$term = acf_decode_taxonomy_term($options['taxonomy']);
134
			
135
			// append to $args
136
			$args['tax_query'] = array(
137
				
138
				array(
139
					'taxonomy'	=> $term['taxonomy'],
140
					'field'		=> 'slug',
141
					'terms'		=> $term['term'],
142
				)
143
				
144
			);
145
			
146
			
147 View Code Duplication
		} elseif( !empty($field['taxonomy']) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
148
			
149
			$taxonomies = acf_decode_taxonomy_terms( $field['taxonomy'] );
150
			
151
			// append to $args
152
			$args['tax_query'] = array();
153
			
154
			
155
			// now create the tax queries
156
			foreach( $taxonomies as $taxonomy => $terms ) {
157
			
158
				$args['tax_query'][] = array(
159
					'taxonomy'	=> $taxonomy,
160
					'field'		=> 'slug',
161
					'terms'		=> $terms,
162
				);
163
				
164
			}
165
			
166
		}	
167
		
168
		
169
		// search
170
		if( $options['s'] ) {
171
		
172
			$args['s'] = $options['s'];
173
			
174
		}
175
		
176
		
177
		// filters
178
		$args = apply_filters('acf/fields/relationship/query', $args, $field, $options['post_id']);
179
		$args = apply_filters('acf/fields/relationship/query/name=' . $field['name'], $args, $field, $options['post_id'] );
180
		$args = apply_filters('acf/fields/relationship/query/key=' . $field['key'], $args, $field, $options['post_id'] );
181
		
182
		
183
		// get posts grouped by post type
184
		$groups = acf_get_grouped_posts( $args );
185
		
186 View Code Duplication
		if( !empty($groups) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
187
			
188
			foreach( array_keys($groups) as $group_title ) {
189
				
190
				// vars
191
				$posts = acf_extract_var( $groups, $group_title );
192
				$titles = array();
0 ignored issues
show
Unused Code introduced by
$titles is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
193
				
194
				
195
				// data
196
				$data = array(
197
					'text'		=> $group_title,
198
					'children'	=> array()
199
				);
200
				
201
				
202
				foreach( array_keys($posts) as $post_id ) {
203
					
204
					// override data
205
					$posts[ $post_id ] = $this->get_post_title( $posts[ $post_id ], $field, $options['post_id'] );
206
					
207
				};
208
				
209
				
210
				// order by search
211
				if( !empty($args['s']) ) {
212
					
213
					$posts = acf_order_by_search( $posts, $args['s'] );
214
					
215
				}
216
				
217
				
218
				// append to $data
219
				foreach( array_keys($posts) as $post_id ) {
220
					
221
					$data['children'][] = array(
222
						'id'	=> $post_id,
223
						'text'	=> $posts[ $post_id ]
224
					);
225
					
226
				}
227
				
228
				
229
				// append to $r
230
				$r[] = $data;
231
				
232
			}
233
			
234
			
235
			// add as optgroup or results
236
			if( count($args['post_type']) == 1 ) {
237
				
238
				$r = $r[0]['children'];
239
				
240
			}
241
			
242
		}
243
		
244
		
245
		// return
246
		return $r;
247
			
248
	}
249
	
250
	
251
	/*
252
	*  ajax_query
253
	*
254
	*  description
255
	*
256
	*  @type	function
257
	*  @date	24/10/13
258
	*  @since	5.0.0
259
	*
260
	*  @param	$post_id (int)
261
	*  @return	$post_id (int)
262
	*/
0 ignored issues
show
Documentation introduced by
The doc-type $post_id could not be parsed: Unknown type name "$post_id" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
263
	
264 View Code Duplication
	function ajax_query() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
265
		
266
		// validate
267
		if( !acf_verify_ajax() ) {
268
		
269
			die();
270
			
271
		}
272
		
273
		
274
		// get posts
275
		$posts = $this->get_choices( $_POST );
276
		
277
		
278
		// validate
279
		if( !$posts ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $posts of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
280
			
281
			die();
282
			
283
		}
284
		
285
		
286
		// return JSON
287
		echo json_encode( $posts );
288
		die();
289
			
290
	}
291
	
292
	
293
	/*
294
	*  get_post_title
295
	*
296
	*  This function returns the HTML for a result
297
	*
298
	*  @type	function
299
	*  @date	1/11/2013
300
	*  @since	5.0.0
301
	*
302
	*  @param	$post (object)
303
	*  @param	$field (array)
304
	*  @param	$post_id (int) the post_id to which this value is saved to
305
	*  @return	(string)
306
	*/
307
	
308
	function get_post_title( $post, $field, $post_id = 0 ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
309
		
310
		// get post_id
311
		if( !$post_id ) {
312
			
313
			$post_id = acf_get_setting('form_data/post_id', get_the_ID());
314
			
315
		}
316
		
317
		
318
		// vars
319
		$title = acf_get_post_title( $post );
320
		
321
		
322
		// elements
323
		if( !empty($field['elements']) ) {
324
			
325
			if( in_array('featured_image', $field['elements']) ) {
326
				
327
				$image = '';
0 ignored issues
show
Unused Code introduced by
$image is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
328
				
329
				if( $post->post_type == 'attachment' ) {
330
					
331
					$image = wp_get_attachment_image( $post->ID, array(17, 17) );
332
					
333
				} else {
334
					
335
					$image = get_the_post_thumbnail( $post->ID, array(17, 17) );
336
					
337
				}
338
				
339
				
340
				$title = '<div class="thumbnail">' . $image . '</div>' . $title;
341
			}
342
			
343
		}
344
		
345
		
346
		// filters
347
		$title = apply_filters('acf/fields/relationship/result', $title, $post, $field, $post_id);
348
		$title = apply_filters('acf/fields/relationship/result/name=' . $field['_name'], $title, $post, $field, $post_id);
349
		$title = apply_filters('acf/fields/relationship/result/key=' . $field['key'], $title, $post, $field, $post_id);
350
		
351
		
352
		// return
353
		return $title;
354
		
355
	}
356
	
357
	
358
	/*
359
	*  render_field()
360
	*
361
	*  Create the HTML interface for your field
362
	*
363
	*  @param	$field - an array holding all the field's data
364
	*
365
	*  @type	action
366
	*  @since	3.6
367
	*  @date	23/01/13
368
	*/
369
	
370
	function render_field( $field ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
371
		
372
		// vars
373
		$values = array();
0 ignored issues
show
Unused Code introduced by
$values is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
374
		$atts = array(
375
			'id'				=> $field['id'],
376
			'class'				=> "acf-relationship {$field['class']}",
377
			'data-min'			=> $field['min'],
378
			'data-max'			=> $field['max'],
379
			'data-s'			=> '',
380
			'data-post_type'	=> '',
381
			'data-taxonomy'		=> '',
382
			'data-paged'		=> 1,
383
		);
384
		
385
		
386
		// Lang
387
		if( defined('ICL_LANGUAGE_CODE') ) {
388
		
389
			$atts['data-lang'] = ICL_LANGUAGE_CODE;
390
			
391
		}
392
		
393
		
394
		// data types
395
		$field['post_type'] = acf_get_array( $field['post_type'] );
396
		$field['taxonomy'] = acf_get_array( $field['taxonomy'] );
397
		
398
		
399
		// width for select filters
400
		$width = array(
401
			'search'	=> 0,
402
			'post_type'	=> 0,
403
			'taxonomy'	=> 0
404
		);
405
		
406
		if( !empty($field['filters']) ) {
407
			
408
			$width = array(
409
				'search'	=> 50,
410
				'post_type'	=> 25,
411
				'taxonomy'	=> 25
412
			);
413
			
414
			foreach( array_keys($width) as $k ) {
415
				
416
				if( ! in_array($k, $field['filters']) ) {
417
				
418
					$width[ $k ] = 0;
419
					
420
				}
421
				
422
			}
423
			
424
			
425
			// search
426
			if( $width['search'] == 0 ) {
427
			
428
				$width['post_type'] = ( $width['post_type'] == 0 ) ? 0 : 50;
429
				$width['taxonomy'] = ( $width['taxonomy'] == 0 ) ? 0 : 50;
430
				
431
			}
432
			
433
			// post_type
434 View Code Duplication
			if( $width['post_type'] == 0 ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
435
			
436
				$width['taxonomy'] = ( $width['taxonomy'] == 0 ) ? 0 : 50;
437
				
438
			}
439
			
440
			
441
			// taxonomy
442 View Code Duplication
			if( $width['taxonomy'] == 0 ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
443
			
444
				$width['post_type'] = ( $width['post_type'] == 0 ) ? 0 : 50;
445
				
446
			}
447
			
448
			
449
			// search
450 View Code Duplication
			if( $width['post_type'] == 0 && $width['taxonomy'] == 0 ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
451
			
452
				$width['search'] = ( $width['search'] == 0 ) ? 0 : 100;
453
				
454
			}
455
		}
456
		
457
		
458
		// post type filter
459
		$post_types = array();
460
		
461
		if( $width['post_type'] ) {
462
			
463
			if( !empty($field['post_type']) ) {
464
			
465
				$post_types = $field['post_type'];
466
	
467
	
468
			} else {
469
				
470
				$post_types = acf_get_post_types();
471
				
472
			}
473
			
474
			$post_types = acf_get_pretty_post_types($post_types);
475
			
476
		}
477
		
478
		
479
		// taxonomy filter
480
		$taxonomies = array();
481
		$term_groups = array();
482
		
483
		if( $width['taxonomy'] ) {
484
			
485
			// taxonomies
486
			if( !empty($field['taxonomy']) ) {
487
				
488
				// get the field's terms
489
				$term_groups = acf_get_array( $field['taxonomy'] );
0 ignored issues
show
Documentation introduced by
$field['taxonomy'] is of type array, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
490
				$term_groups = acf_decode_taxonomy_terms( $term_groups );
0 ignored issues
show
Documentation introduced by
$term_groups is of type array, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
491
				
492
				
493
				// update taxonomies
494
				$taxonomies = array_keys($term_groups);
495
			
496
			} elseif( !empty($field['post_type']) ) {
497
				
498
				// loop over post types and find connected taxonomies
499
				foreach( $field['post_type'] as $post_type ) {
500
					
501
					$post_taxonomies = get_object_taxonomies( $post_type );
502
					
503
					// bail early if no taxonomies
504
					if( empty($post_taxonomies) ) {
505
						
506
						continue;
507
						
508
					}
509
						
510
					foreach( $post_taxonomies as $post_taxonomy ) {
511
						
512
						if( !in_array($post_taxonomy, $taxonomies) ) {
513
							
514
							$taxonomies[] = $post_taxonomy;
515
							
516
						}
517
						
518
					}
519
								
520
				}
521
				
522
			} else {
523
				
524
				$taxonomies = acf_get_taxonomies();
525
				
526
			}
527
			
528
			
529
			// terms
530
			$term_groups = acf_get_taxonomy_terms( $taxonomies );
531
			
532
			
533
			// update $term_groups with specific terms
534
			if( !empty($field['taxonomy']) ) {
535
				
536
				foreach( array_keys($term_groups) as $taxonomy ) {
537
					
538
					foreach( array_keys($term_groups[ $taxonomy ]) as $term ) {
539
						
540
						if( ! in_array($term, $field['taxonomy']) ) {
541
							
542
							unset($term_groups[ $taxonomy ][ $term ]);
543
							
544
						}
545
						
546
					}
547
					
548
				}
549
				
550
			}
551
			
552
		}
553
		// end taxonomy filter
554
			
555
		?>
556
<div <?php acf_esc_attr_e($atts); ?>>
557
	
558
	<div class="acf-hidden">
559
		<input type="hidden" name="<?php echo $field['name']; ?>" value="" />
560
	</div>
561
	
562
	<?php if( $width['search'] || $width['post_type'] || $width['taxonomy'] ): ?>
563
	<div class="filters">
564
		
565
		<ul class="acf-hl">
566
		
567
			<?php if( $width['search'] ): ?>
568
			<li style="width:<?php echo $width['search']; ?>%;">
569
				<div class="inner">
570
				<input class="filter" data-filter="s" placeholder="<?php _e("Search...",'acf'); ?>" type="text" />
571
				</div>
572
			</li>
573
			<?php endif; ?>
574
			
575
			<?php if( $width['post_type'] ): ?>
576
			<li style="width:<?php echo $width['post_type']; ?>%;">
577
				<div class="inner">
578
				<select class="filter" data-filter="post_type">
579
					<option value=""><?php _e('Select post type','acf'); ?></option>
580
					<?php foreach( $post_types as $k => $v ): ?>
581
						<option value="<?php echo $k; ?>"><?php echo $v; ?></option>
582
					<?php endforeach; ?>
583
				</select>
584
				</div>
585
			</li>
586
			<?php endif; ?>
587
			
588
			<?php if( $width['taxonomy'] ): ?>
589
			<li style="width:<?php echo $width['taxonomy']; ?>%;">
590
				<div class="inner">
591
				<select class="filter" data-filter="taxonomy">
592
					<option value=""><?php _e('Select taxonomy','acf'); ?></option>
593
					<?php foreach( $term_groups as $k_opt => $v_opt ): ?>
594
						<optgroup label="<?php echo $k_opt; ?>">
595
							<?php foreach( $v_opt as $k => $v ): ?>
596
								<option value="<?php echo $k; ?>"><?php echo $v; ?></option>
597
							<?php endforeach; ?>
598
						</optgroup>
599
					<?php endforeach; ?>
600
				</select>
601
				</div>
602
			</li>
603
			<?php endif; ?>
604
		</ul>
605
		
606
	</div>
607
	<?php endif; ?>
608
	
609
	<div class="selection acf-cf">
610
	
611
		<div class="choices">
612
		
613
			<ul class="acf-bl list"></ul>
614
			
615
		</div>
616
		
617
		<div class="values">
618
		
619
			<ul class="acf-bl list">
620
			
621
				<?php if( !empty($field['value']) ): 
622
					
623
					// get posts
624
					$posts = acf_get_posts(array(
625
						'post__in' => $field['value'],
626
						'post_type'	=> $field['post_type']
627
					));
628
					
629
					
630
					// set choices
631
					if( !empty($posts) ):
632
						
633
						foreach( array_keys($posts) as $i ):
634
							
635
							// vars
636
							$post = acf_extract_var( $posts, $i );
637
							
638
							
639
							?><li>
640
								<input type="hidden" name="<?php echo $field['name']; ?>[]" value="<?php echo $post->ID; ?>" />
641
								<span data-id="<?php echo $post->ID; ?>" class="acf-rel-item">
642
									<?php echo $this->get_post_title( $post, $field ); ?>
643
									<a href="#" class="acf-icon -minus small dark" data-name="remove_item"></a>
644
								</span>
645
							</li><?php
646
							
647
						endforeach;
648
						
649
					endif;
650
				
651
				endif; ?>
652
				
653
			</ul>
654
			
655
			
656
			
657
		</div>
658
		
659
	</div>
660
	
661
</div>
662
		<?php
663
	}
664
	
665
	
666
	
667
	/*
668
	*  render_field_settings()
669
	*
670
	*  Create extra options for your field. This is rendered when editing a field.
671
	*  The value of $field['name'] can be used (like bellow) to save extra data to the $field
672
	*
673
	*  @type	action
674
	*  @since	3.6
675
	*  @date	23/01/13
676
	*
677
	*  @param	$field	- an array holding all the field's data
678
	*/
679
	
680
	function render_field_settings( $field ) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
681
		
682
		// vars
683
		$field['min'] = empty($field['min']) ? '' : $field['min'];
684
		$field['max'] = empty($field['max']) ? '' : $field['max'];
685
		
686
		
687
		// post_type
688
		acf_render_field_setting( $field, array(
689
			'label'			=> __('Filter by Post Type','acf'),
690
			'instructions'	=> '',
691
			'type'			=> 'select',
692
			'name'			=> 'post_type',
693
			'choices'		=> acf_get_pretty_post_types(),
694
			'multiple'		=> 1,
695
			'ui'			=> 1,
696
			'allow_null'	=> 1,
697
			'placeholder'	=> __("All post types",'acf'),
698
		));
699
		
700
		
701
		// taxonomy
702
		acf_render_field_setting( $field, array(
703
			'label'			=> __('Filter by Taxonomy','acf'),
704
			'instructions'	=> '',
705
			'type'			=> 'select',
706
			'name'			=> 'taxonomy',
707
			'choices'		=> acf_get_taxonomy_terms(),
708
			'multiple'		=> 1,
709
			'ui'			=> 1,
710
			'allow_null'	=> 1,
711
			'placeholder'	=> __("All taxonomies",'acf'),
712
		));
713
		
714
		
715
		// filters
716
		acf_render_field_setting( $field, array(
717
			'label'			=> __('Filters','acf'),
718
			'instructions'	=> '',
719
			'type'			=> 'checkbox',
720
			'name'			=> 'filters',
721
			'choices'		=> array(
722
				'search'		=> __("Search",'acf'),
723
				'post_type'		=> __("Post Type",'acf'),
724
				'taxonomy'		=> __("Taxonomy",'acf'),
725
			),
726
		));
727
		
728
		
729
		// filters
730
		acf_render_field_setting( $field, array(
731
			'label'			=> __('Elements','acf'),
732
			'instructions'	=> __('Selected elements will be displayed in each result','acf'),
733
			'type'			=> 'checkbox',
734
			'name'			=> 'elements',
735
			'choices'		=> array(
736
				'featured_image'	=> __("Featured Image",'acf'),
737
			),
738
		));
739
		
740
		
741
		// min
742
		acf_render_field_setting( $field, array(
743
			'label'			=> __('Minimum posts','acf'),
744
			'instructions'	=> '',
745
			'type'			=> 'number',
746
			'name'			=> 'min',
747
		));
748
		
749
		
750
		// max
751
		acf_render_field_setting( $field, array(
752
			'label'			=> __('Maximum posts','acf'),
753
			'instructions'	=> '',
754
			'type'			=> 'number',
755
			'name'			=> 'max',
756
		));
757
		
758
		
759
		
760
		
761
		// return_format
762
		acf_render_field_setting( $field, array(
763
			'label'			=> __('Return Format','acf'),
764
			'instructions'	=> '',
765
			'type'			=> 'radio',
766
			'name'			=> 'return_format',
767
			'choices'		=> array(
768
				'object'		=> __("Post Object",'acf'),
769
				'id'			=> __("Post ID",'acf'),
770
			),
771
			'layout'	=>	'horizontal',
772
		));
773
		
774
		
775
	}
776
	
777
	
778
	/*
779
	*  format_value()
780
	*
781
	*  This filter is appied to the $value after it is loaded from the db and before it is returned to the template
782
	*
783
	*  @type	filter
784
	*  @since	3.6
785
	*  @date	23/01/13
786
	*
787
	*  @param	$value (mixed) the value which was loaded from the database
788
	*  @param	$post_id (mixed) the $post_id from which the value was loaded
789
	*  @param	$field (array) the field array holding all the field options
790
	*
791
	*  @return	$value (mixed) the modified value
792
	*/
0 ignored issues
show
Documentation introduced by
The doc-type $value could not be parsed: Unknown type name "$value" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
793
	
794
	function format_value( $value, $post_id, $field ) {
0 ignored issues
show
Unused Code introduced by
The parameter $post_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
795
		
796
		// bail early if no value
797
		if( empty($value) ) {
798
		
799
			return $value;
800
			
801
		}
802
		
803
		
804
		// force value to array
805
		$value = acf_get_array( $value );
806
		
807
		
808
		// convert to int
809
		$value = array_map('intval', $value);
810
		
811
		
812
		// load posts if needed
813 View Code Duplication
		if( $field['return_format'] == 'object' ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
814
			
815
			// get posts
816
			$value = acf_get_posts(array(
817
				'post__in' => $value,
818
				'post_type'	=> $field['post_type']
819
			));
820
			
821
		}
822
		
823
		
824
		// return
825
		return $value;
826
		
827
	}
828
	
829
	
830
	/*
831
	*  validate_value
832
	*
833
	*  description
834
	*
835
	*  @type	function
836
	*  @date	11/02/2014
837
	*  @since	5.0.0
838
	*
839
	*  @param	$post_id (int)
840
	*  @return	$post_id (int)
841
	*/
0 ignored issues
show
Documentation introduced by
The doc-type $post_id could not be parsed: Unknown type name "$post_id" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
842
	
843 View Code Duplication
	function validate_value( $valid, $value, $field, $input ){
0 ignored issues
show
Unused Code introduced by
The parameter $input is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
844
		
845
		// default
846
		if( empty($value) || !is_array($value) ) {
847
		
848
			$value = array();
849
			
850
		}
851
		
852
		
853
		// min
854
		if( count($value) < $field['min'] ) {
855
		
856
			$valid = _n( '%s requires at least %s selection', '%s requires at least %s selections', $field['min'], 'acf' );
857
			$valid = sprintf( $valid, $field['label'], $field['min'] );
858
			
859
		}
860
		
861
		
862
		// return		
863
		return $valid;
864
		
865
	}
866
		
867
	
868
	/*
869
	*  update_value()
870
	*
871
	*  This filter is appied to the $value before it is updated in the db
872
	*
873
	*  @type	filter
874
	*  @since	3.6
875
	*  @date	23/01/13
876
	*
877
	*  @param	$value - the value which will be saved in the database
878
	*  @param	$post_id - the $post_id of which the value will be saved
879
	*  @param	$field - the field array holding all the field options
880
	*
881
	*  @return	$value - the modified value
882
	*/
0 ignored issues
show
Documentation introduced by
The doc-type $value could not be parsed: Unknown type name "$value" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
883
	
884
	function update_value( $value, $post_id, $field ) {
0 ignored issues
show
Unused Code introduced by
The parameter $post_id is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $field is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
885
		
886
		// validate
887
		if( empty($value) ) {
888
			
889
			return $value;
890
			
891
		}
892
		
893
		
894
		// force value to array
895
		$value = acf_get_array( $value );
896
		
897
					
898
		// array
899
		foreach( $value as $k => $v ){
900
		
901
			// object?
902
			if( is_object($v) && isset($v->ID) ) {
903
			
904
				$value[ $k ] = $v->ID;
905
				
906
			}
907
			
908
		}
909
		
910
		
911
		// save value as strings, so we can clearly search for them in SQL LIKE statements
912
		$value = array_map('strval', $value);
913
		
914
	
915
		// return
916
		return $value;
917
		
918
	}
919
		
920
}
921
922
new acf_field_relationship();
923
924
endif;
925
926
?>
927