certainlyakey
6/23/2014 - 11:50 AM

Add labelled metabox with dynamically added key-value custom field sets (Wordpress)

Add labelled metabox with dynamically added key-value custom field sets (Wordpress)

<?
//Display both simple custom fields and key-value fields - OPTIONAL
$member_metas = array(
	'my_partic_email' => true,
	'my_partic_phone' => true,
	'my_partic_links' => false //key-value meta
);
$atleastonemeta = false;
$meta_arr = array();
$urls = array();
foreach ($member_metas as $meta_key => $is_string) {
	$current_meta_value = get_post_meta($post->ID, $meta_key, $is_string);
	if (is_array($current_meta_value)) { 
		$current_meta_value = array_filter($current_meta_value); //Clean array from empty values
	}
	if ($current_meta_value) { //Check if string or array are empty
		$meta_arr[$meta_key] = $current_meta_value;
	}
	if( count( array_filter($meta_arr)) != 0) {
		$atleastonemeta = true;
	}
}

if ($atleastonemeta) {
	echo '<section class="profile-links"><h1>Connections</h1><ul>';
		foreach ($meta_arr as $meta_key => $meta_value) {
			if (is_array($meta_value)) {
				$urls = $meta_value[0];
				foreach ($urls as $k => $v) {
					echo '<li><a href="'.$v['url'].'">'.$v['name'].'</a></li>';
				}
			} else if ($meta_key == 'my_partic_email') {
				echo '<li><a href="mailto:'.$meta_value.'">'.$meta_value.'</a></li>';
			} else {
				echo '<li>'.$meta_value.'</li>';
			}
		}
	echo '</ul></section>';
}
<?php
//Add metabox with dynamically added key-value custom fields
//Good if you want to save a set of paired characteristics for the post, where both key and value are different in each pair. 
//For example: metabox name is Associated events, key is the name of the event and the value is its date. 
//All key-values pairs are saved in one single custom field as an array.
//Usage: 
//foreach ($calendar as $event) { echo '<li>'.$event[title].' - '.$event[date].'</li>';} 
//Based on http://wordpress.stackexchange.com/questions/19838/create-more-meta-boxes-as-needed/19852#19852

// Caution, there're 2 set of options below
//Variables used in the following functions should be mentioned in the 'global' statement of each of them appropriately
//=======Options 1=======
$dmb_post_type = 'participant';
$dmb_metabox_label = 'Social links';
$dmb_cf_name = 'my_partic_links';

// Add actions, initialise functions
add_action( 'add_meta_boxes', 'dynamic_add_custom_box' );
add_action( 'save_post', 'dynamic_save_postdata' );

$dmb_cf_nonce = $dmb_cf_name.'_nonce';

//Function to add a meta box 
function dynamic_add_custom_box() {
	global $dmb_post_type, $dmb_metabox_label, $dmb_cf_name;

	add_meta_box($dmb_cf_name.'_section', $dmb_metabox_label, 'dynamic_inner_custom_box', $dmb_post_type);
}

//Function that defines metabox contents
function dynamic_inner_custom_box() {

	//=======Options 2=======
	$dmb_label_addnew = 'Add an event';
	$dmb_label_remove = 'Delete';
	$dmb_key_name = 'title'; 
	$dmb_value_name = 'date';
	$dmb_key_label = 'The title of event';
	$dmb_value_label = 'Date';

	global $post, $dmb_cf_name, $dmb_cf_nonce;

	// Use nonce for verification
	wp_nonce_field( plugin_basename( __FILE__ ), $dmb_cf_nonce );

	//OPTIONAL
	//Load admin scripts & styles for JS datepicker via the class from Meta Box plugin. This requires Meta Box plugin by Rilwis installed http://x.co/1YgqA
	//$loadJqUIfromMetaboxPlugin = new RWMB_Date_Field();
	//$loadJqUIfromMetaboxPlugin->admin_enqueue_scripts();

	?>
	<div id="dynamic_inner_custom_box">
	<?php
	$dmb_items = get_post_meta($post->ID,$dmb_cf_name,true);
	$c = 0;
	if ( count( $dmb_items ) > 0 && is_array($dmb_items) ) {
		foreach( $dmb_items as $dmb_item ) {
			if ( isset( $dmb_item[$dmb_key_name] ) || isset( $dmb_item[$dmb_value_name] ) ) {
				printf( '<p>%8$s <input type="text" name="%6$s[%1$s][%4$s]" value="%2$s" size="45"> &nbsp; %9$s <input type="text" name="%6$s[%1$s][%5$s]" value="%3$s" class="choosedate"> &nbsp; <a href="#" class="remove">%7$s</a></p>', 
			/*1*/   $c, 
			/*2*/   $dmb_item[$dmb_key_name], 
			/*3*/   $dmb_item[$dmb_value_name], 
			/*4*/   $dmb_key_name, 
			/*5*/   $dmb_value_name, 
			/*6*/   $dmb_cf_name, 
			/*7*/   $dmb_label_remove,
			/*8*/   $dmb_key_label,
			/*9*/   $dmb_value_label
				);
				$c = $c +1;
			}
		}
	}
	?>
	<span id="here"></span>
	<a href="#" class="add button-secondary"><?php echo $dmb_label_addnew; ?></a>
	<script>
		var $ =jQuery.noConflict();
		$(document).ready(function() {
			
			//OPTIONAL
			//Add datepicker to an input
			//$('body').on('focus',".choosedate", function(){ //Allows to init datepicker on non existing yet elements
			//	$(this).datepicker({ dateFormat: "dd.mm.yy" });
			//});

			var count = <?php echo $c; ?>;
			$(".add").on('click',function(e) {
				e.preventDefault();
				count = count + 1;
				$('#here').append('<p><?php echo $dmb_key_label; ?> <input size="45" type="text" name="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_key_name; ?>]" value=""> &nbsp; <?php echo $dmb_value_label; ?> <input type="text" name="<?php echo $dmb_cf_name; ?>['+count+'][<?php echo $dmb_value_name; ?>]" value="" class="choosedate"> &nbsp; <a href="#" class="remove"><?php echo $dmb_label_remove; ?></a></p>');
				return false;
			});
			$("#dynamic_inner_custom_box").on('click', '.remove', function(e) { //Replacement for live(). Selector is existing parent of not existing element
				e.preventDefault();
				$(this).parent().remove();
			});
		});
		</script>
	</div><?php
}

/* When the post is saved, saves our custom data */
function dynamic_save_postdata( $post_id ) {
  global $dmb_cf_name,$dmb_cf_nonce;

	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
		return;
	if ( empty( $_POST[$dmb_cf_name] ) )
		return;
	if ( !wp_verify_nonce( $_POST[$dmb_cf_nonce], plugin_basename( __FILE__ ) ) )
		return;
	$data2post = $_POST[$dmb_cf_name];
	update_post_meta($post_id,$dmb_cf_name,$data2post);
}
?>