_meta_box = $meta_box;
// Cast pages to array
$this->_meta_box['pages'] = (array) $meta_box['pages'];
$this->_fields = $this->_meta_box['fields'];
$this->add_missed_values();
$this->register_scripts_and_styles();
add_action( 'add_meta_boxes', array( $this, 'add' ) ); // add meta box, using 'add_meta_boxes' for WP 3.0+
add_action( 'save_post', array( $this, 'save' ) ); // save meta box's data
// check for some special fields and add needed actions for them
$this->check_field_upload();
$this->check_field_color();
$this->check_field_date();
$this->check_field_time();
// load common js, css files
// must enqueue for all pages as we need js for the media upload, too
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'js_css' ) );
}
public function register_scripts_and_styles() {
// change '\' to '/' in case using Windows
$content_dir = str_replace( '\\', '/', WP_CONTENT_DIR );
$script_dir = str_replace( '\\', '/', dirname( __FILE__ ) );
// get URL of the directory of current file, this works in both theme or plugin
$base_url = trailingslashit( str_replace( $content_dir, WP_CONTENT_URL, $script_dir ) );
$resources_url = apply_filters( 'tribe_apm_resources_url', $base_url . 'resources' );
$resources_url = trailingslashit( $resources_url );
wp_register_style( 'tribe-meta-box', $resources_url . 'meta-box.css' );
wp_register_script( 'tribe-meta-box', $resources_url . 'meta-box.js', array( 'jquery' ), null, true );
wp_register_style( 'tribe-jquery-ui-css', 'https://ajax.googleapis.com/ajax/libs/jqueryui/' . self::get_jqueryui_ver() . '/themes/base/jquery-ui.css' );
wp_register_script( 'tribe-jquery-ui', 'https://ajax.googleapis.com/ajax/libs/jqueryui/' . self::get_jqueryui_ver() . '/jquery-ui.min.js', array( 'jquery' ) );
wp_register_script( 'tribe-timepicker', 'https://github.com/trentrichardson/jQuery-Timepicker-Addon/raw/master/jquery-ui-timepicker-addon.js', array( 'tribe-jquery-ui' ) );
}
// Load common js, css files for the script
public static function js_css() {
wp_enqueue_script( 'tribe-meta-box' );
wp_enqueue_style( 'tribe-meta-box' );
}
/******************** BEGIN UPLOAD **********************/
// Check field upload and add needed actions
public function check_field_upload() {
if ( ! $this->has_field( 'image' ) && ! $this->has_field( 'file' ) ) {
return;
}
add_action( 'post_edit_form_tag', array( $this, 'add_enctype' ) ); // add data encoding type for file uploading
// make upload feature works even when custom post type doesn't support 'editor'
wp_enqueue_script( 'media-upload' );
add_thickbox();
wp_enqueue_script( 'jquery-ui-core' );
wp_enqueue_script( 'jquery-ui-sortable' );
add_filter( 'media_upload_gallery', array( $this, 'insert_images' ) ); // process adding multiple images to image meta field
add_filter( 'media_upload_library', array( $this, 'insert_images' ) );
add_filter( 'media_upload_image', array( $this, 'insert_images' ) );
add_action( 'wp_ajax_tribe_delete_file', array( $this, 'delete_file' ) ); // ajax delete files
add_action( 'wp_ajax_tribe_reorder_images', array( $this, 'reorder_images' ) ); // ajax reorder images
}
// Add data encoding type for file uploading
public function add_enctype() {
echo ' enctype="multipart/form-data"';
}
// Process adding images to image meta field, modifiy from 'Faster image insert' plugin
public function insert_images() {
if ( ! isset( $_POST['tribe-insert'] ) || empty( $_POST['attachments'] ) ){
return;
}
check_admin_referer( 'media-form' );
$nonce = wp_create_nonce( 'tribe_ajax_delete' );
$post_id = $_POST['post_id'];
$id = $_POST['field_id'];
// modify the insertion string
$html = '';
foreach ( $_POST['attachments'] as $attachment_id => $attachment ) {
$attachment = stripslashes_deep( $attachment );
if ( empty( $attachment['selected'] ) || empty( $attachment['url'] ) ) {
continue;
}
$li = "
";
$li .= "
";
$li .= "" . __( 'Delete', 'advanced-post-manager' ) . '';
$li .= "";
$li .= '';
$html .= $li;
}
media_send_to_editor( $html );
}
// Delete all attachments when delete post
public function delete_attachments( $post_id ) {
$attachments = get_posts( array(
'numberposts' => -1,
'post_type' => 'attachment',
'post_parent' => $post_id,
) );
if ( ! empty( $attachments ) ) {
foreach ( $attachments as $att ) {
wp_delete_attachment( $att->ID );
}
}
}
// Ajax callback for deleting files. Modified from a function used by "Verve Meta Boxes" plugin (http://goo.gl/LzYSq)
public function delete_file() {
if ( ! isset( $_POST['data'] ) ) {
die();
}
list( $nonce, $post_id, $key, $attach_id ) = explode( '|', $_POST['data'] );
if ( ! wp_verify_nonce( $nonce, 'tribe_ajax_delete' ) ) {
die( '1' );
}
$post = get_post( $post_id );
if ( ! $post instanceof WP_Post ) {
die( '1' );
}
$cap = get_post_type_object( $post->post_type )->cap->edit_post;
// Check if the user can edit the post by ID
if ( ! current_user_can( $cap, $post->ID ) ) {
die( '1' );
}
delete_post_meta( $post_id, $key, $attach_id );
die( '0' );
}
// Ajax callback for reordering images
public function reorder_images() {
if ( ! isset( $_POST['data'] ) ) {
die();
}
list( $order, $post_id, $key, $nonce ) = explode( '|', $_POST['data'] );
if ( ! wp_verify_nonce( $nonce, 'tribe_ajax_reorder' ) ) {
die( '1' );
}
$post = get_post( $post_id );
if ( ! $post instanceof WP_Post ) {
die( '1' );
}
$cap = get_post_type_object( $post->post_type )->cap->edit_posts;
// Check if the user can edit the post by ID
if ( ! current_user_can( $cap ) ) {
die( '1' );
}
parse_str( $order, $items );
$items = $items['item'];
$order = 1;
foreach ( $items as $item ) {
wp_update_post( array(
'ID' => $item,
'post_parent' => $post_id,
'menu_order' => $order,
) );
$order++;
}
die( '0' );
}
/******************** END UPLOAD **********************/
/******************** BEGIN OTHER FIELDS **********************/
// Check field color
public function check_field_color() {
if ( $this->has_field( 'color' ) && self::is_edit_page() ) {
wp_enqueue_style( 'farbtastic' ); // enqueue built-in script and style for color picker
wp_enqueue_script( 'farbtastic' );
}
}
// Check field date
public function check_field_date() {
if ( $this->has_field( 'date' ) && self::is_edit_page() ) {
wp_enqueue_style( 'tribe-jquery-ui-css' );
wp_enqueue_script( 'tribe-jquery-ui' );
}
}
// Check field time
public function check_field_time() {
if ( $this->has_field( 'time' ) && self::is_edit_page() ) {
// add style and script, use proper jQuery UI version
wp_enqueue_style( 'tribe-jquery-ui-css' );
wp_enqueue_script( 'tribe-jquery-ui' );
wp_enqueue_script( 'tribe-timepicker' );
}
}
/******************** END OTHER FIELDS **********************/
/******************** BEGIN META BOX PAGE **********************/
// Add meta box for multiple post types
public function add() {
foreach ( (array) $this->_meta_box['pages'] as $page ) {
add_meta_box( $this->_meta_box['id'], $this->_meta_box['title'], array( $this, 'show' ), $page, $this->_meta_box['context'], $this->_meta_box['priority'] );
}
}
// Callback function to show fields in meta box
public function show() {
global $post;
wp_nonce_field( basename( __FILE__ ), 'tribe_meta_box_nonce' );
echo '';
}
public function retrieve_meta_for_field( $field, $post ) {
$meta = get_post_meta( $post->ID, $field['meta'], ! $field['multiple'] );
$meta = ! empty( $meta ) ? $meta : $field['std'];
$meta = ( is_array( $meta ) ) ? self::array_map_deep( 'esc_attr', $meta ) : esc_attr( $meta );
return $meta;
}
public function array_map_deep( $callback, $data ) {
$results = array();
$args = array();
if ( func_num_args() > 2 ) {
$args = (array) array_shift( array_slice( func_get_args(), 2 ) );
}
foreach ( $data as $key => $value ) {
if ( is_array( $value ) ) {
array_unshift( $args, $value );
array_unshift( $args, $callback );
$results[ $key ] = call_user_func_array( array( 'self', 'array_map_deep' ), $args );
}
else {
array_unshift( $args, $value );
$results[ $key ] = call_user_func_array( $callback, $args );
}
}
return $results;
}
/******************** END META BOX PAGE **********************/
/******************** BEGIN META BOX FIELDS **********************/
public function show_field_begin( $field, $meta ) {
if ( isset( $field['span'] ) && 'full' === $field['span'] ) {
echo "";
} else {
echo " | | ";
}
}
public function show_field_end( $field, $meta ) {
if ( isset( $field['desc'] ) ) {
echo " {$field['desc']} ";
}
echo ' | ';
}
public function show_field_text( $field, $meta ) {
$this->show_field_begin( $field, $meta );
echo "";
$this->show_field_end( $field, $meta );
}
public function show_field_textarea( $field, $meta ) {
$this->show_field_begin( $field, $meta );
echo "";
$this->show_field_end( $field, $meta );
}
public function show_field_select( $field, $meta ) {
if ( ! is_array( $meta ) ) {
$meta = (array) $meta;
}
$this->show_field_begin( $field, $meta );
echo "';
$this->show_field_end( $field, $meta );
}
public function show_field_radio( $field, $meta ) {
$this->show_field_begin( $field, $meta );
foreach ( $field['options'] as $key => $value ) {
echo " $value ";
}
$this->show_field_end( $field, $meta );
}
public function show_field_checkbox( $field, $meta ) {
$this->show_field_begin( $field, $meta );
echo "";
}
public function show_field_wysiwyg( $field, $meta ) {
$this->show_field_begin( $field, $meta );
$content = get_post_meta( get_the_ID(), $field['meta'], true );
$content = empty( $content ) || ! is_string( $content ) ? '' : $content;
$settings = array(
'media_buttons' => isset( $field['media_buttons'] ) ? (bool) $field['meta_buttons'] : false,
);
wp_editor( $content, $field['meta'], $settings );
$this->show_field_end( $field, $meta );
}
public function show_field_file( $field, $meta ) {
global $post;
if ( ! is_array( $meta ) ) {
$meta = (array) $meta;
}
$this->show_field_begin( $field, $meta );
if ( isset( $field['desc'] ) ) {
echo "{$field['desc']}
";
}
if ( ! empty( $meta ) ) {
$nonce = wp_create_nonce( 'tribe_ajax_delete' );
echo '' . esc_html__( 'Uploaded files', 'advanced-post-manager' ) . '
';
echo '';
foreach ( $meta as $att ) {
echo '- ' . wp_get_attachment_link( $att, '', false, false, ' ' ) . " (" . esc_html__( 'Delete', 'advanced-post-manager' ) . ')
';
}
echo '
';
}
// show form upload
echo '' . esc_html__( 'Upload new files', 'advanced-post-manager' ) . "
';
}
public function show_field_image( $field, $meta ) {
global $wpdb, $post;
if ( ! is_array( $meta ) ) {
$meta = (array) $meta;
}
$this->show_field_begin( $field, $meta );
if ( isset( $field['desc'] ) ) {
echo "{$field['desc']}
";
}
$nonce_delete = wp_create_nonce( 'tribe_ajax_delete' );
$nonce_sort = wp_create_nonce( 'tribe_ajax_reorder' );
echo "
";
// re-arrange images with 'menu_order', thanks Onur
if ( ! empty( $meta ) ) {
$meta = implode( ',', $meta );
$images = $wpdb->get_col( "
SELECT ID FROM $wpdb->posts
WHERE post_type = 'attachment'
AND ID in ($meta)
ORDER BY menu_order ASC
" );
foreach ( $images as $image ) {
$src = wp_get_attachment_image_src( $image );
$src = $src[0];
echo "-
" . esc_html__( 'Delete', 'advanced-post-manager' ) . "
";
}
}
echo '
';
echo "" . esc_html__( 'Add more images', 'advanced-post-manager' ) . '';
echo '';
}
public function show_field_color( $field, $meta ) {
if ( empty( $meta ) ) {
$meta = '#';
}
$this->show_field_begin( $field, $meta );
echo "
" . esc_html__( 'Select a color', 'advanced-post-manager' ) . "
";
$this->show_field_end( $field, $meta );
}
public function show_field_checkbox_list( $field, $meta ) {
if ( ! is_array( $meta ) ) {
$meta = (array) $meta;
}
$this->show_field_begin( $field, $meta );
$html = array();
foreach ( $field['options'] as $key => $value ) {
$html[] = " $value";
}
echo implode( '
', $html );
$this->show_field_end( $field, $meta );
}
public function show_field_date( $field, $meta ) {
$this->show_field_begin( $field, $meta );
echo "";
$this->show_field_end( $field, $meta );
}
public function show_field_time( $field, $meta ) {
$this->show_field_begin( $field, $meta );
echo "";
$this->show_field_end( $field, $meta );
}
public function show_field_text_multi( $field, $meta ) {
$this->show_field_begin( $field, $meta );
$meta = (array) $meta;
$hide_remove = ( count( $meta ) < 2 ) ? ' hide-remove' : '';
$size = floor( 36 / count( $field['ids'] ) );
echo '';
foreach ( $meta as $k => $v ) {
echo '
";
}
echo '
';
$this->show_field_end( $field, $meta );
}
public function show_field_html( $field, $meta ) {
$this->show_field_begin( $field, $meta );
echo $field['html'];
$this->show_field_end( $field, $meta );
}
public function show_field_post2post( $field, $meta ) {
$this->show_field_begin( $field, $meta );
if ( ! isset( $field['dropdown_title'] ) ) {
$post_type_object = get_post_type_object( $field['post_type'] );
$field['dropdown_title'] = sprintf( 'Select %s', $post_type_object->labels->singular_name );
}
$this->dropdown_posts( array(
'post_type' => $field['post_type'],
'show_option_none' => $field['dropdown_title'],
'name' => $field['meta'],
'class' => 'p2p-drop',
) );
$list_items = '';
$list_item_template = '';
if ( ! empty( $meta ) ) {
foreach ( (array) $meta as $post_id ) {
$p = get_post( $post_id );
$list_items .= sprintf( $list_item_template, $p->ID, $p->post_title );
}
}
echo '';
$this->show_field_end( $field, $meta );
}
/******************** END META BOX FIELDS **********************/
/******************** BEGIN META BOX SAVE **********************/
// Save data from meta box
public function save( $post_id ) {
global $post_type;
$post_type_object = get_post_type_object( $post_type );
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) // check autosave
|| ( ! isset( $_POST['post_ID'] ) || $post_id != $_POST['post_ID'] ) // check revision
|| ( ! in_array( $post_type, $this->_meta_box['pages'] ) ) // check if current post type is supported
|| ( ! check_admin_referer( basename( __FILE__ ), 'tribe_meta_box_nonce' ) ) // verify nonce
|| ( ! current_user_can( $post_type_object->cap->edit_post, $post_id ) ) ) { // check permission
return $post_id;
}
foreach ( $this->_fields as $field ) {
$name = $field['meta'];
$type = $field['type'];
$old = get_post_meta( $post_id, $name, ! $field['multiple'] );
$new = isset( $_POST[ $name ] ) ? $_POST[ $name ] : ( $field['multiple'] ? array() : '' );
// validate meta value
if ( class_exists( 'Tribe_Meta_Box_Validate' ) && method_exists( 'Tribe_Meta_Box_Validate', $field['validate_func'] ) ) {
$new = call_user_func( array( 'Tribe_Meta_Box_Validate', $field['validate_func'] ), $new );
}
// call defined method to save meta value, if there's no methods, call common one
$save_func = 'save_field_' . $type;
if ( method_exists( $this, $save_func ) ) {
call_user_func( array( $this, 'save_field_' . $type ), $post_id, $field, $old, $new );
} else {
$this->save_field( $post_id, $field, $old, $new );
}
}
}
// Common functions for saving field
public function save_field( $post_id, $field, $old, $new ) {
$name = $field['meta'];
delete_post_meta( $post_id, $name );
if ( $new === '' || $new === array() ) {
return;
}
if ( $field['multiple'] ) {
foreach ( $new as $add_new ) {
add_post_meta( $post_id, $name, $add_new, false );
}
} else {
update_post_meta( $post_id, $name, $new );
}
}
public function save_field_wysiwyg( $post_id, $field, $old, $new ) {
$new = wpautop( $new );
$this->save_field( $post_id, $field, $old, $new );
}
public function save_field_file( $post_id, $field, $old, $new ) {
$name = $field['meta'];
if ( empty( $_FILES[ $name ] ) ) {
return;
}
self::fix_file_array( $_FILES[ $name ] );
foreach ( $_FILES[ $name ] as $position => $fileitem ) {
$file = wp_handle_upload( $fileitem, array( 'test_form' => false ) );
if ( empty( $file['file'] ) ){
continue;
}
$filename = $file['file'];
$attachment = array(
'post_mime_type' => $file['type'],
'guid' => $file['url'],
'post_parent' => $post_id,
'post_title' => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
'post_content' => '',
);
$id = wp_insert_attachment( $attachment, $filename, $post_id );
if ( ! is_wp_error( $id ) ) {
wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $filename ) );
add_post_meta( $post_id, $name, $id, false ); // save file's url in meta fields
}
}
}
public function save_field_text_multi( $post_id, $field, $old, $new ) {
$data = array();
$new = (array) $new;
foreach ( $field['ids'] as $id ) {
foreach ( $new[ $id ] as $key => $value ) {
$data[ $key ][ $id ] = $value;
}
}
if ( ! empty( $data ) ) {
update_post_meta( $post_id, $field['meta'], $data );
}
}
public function save_field_html() {
// do nothing
}
public function save_field_post2post( $post_id, $field, $old, $new ) {
delete_post_meta( $post_id, $field['meta'] );
$new = (array) $new;
$new = array_unique( $new );
foreach ( $new as $id ) {
add_post_meta( $post_id, $field['meta'], $id );
}
}
/******************** END META BOX SAVE **********************/
/******************** BEGIN HELPER FUNCTIONS **********************/
public function dropdown_posts( $args = '' ) {
$defaults = array(
'numberposts' => -1,
'post_type' => 'post',
'depth' => 0,
'selected' => 0,
'echo' => 1,
'name' => 'page_id',
'id' => '',
'class' => '',
'show_option_none' => '',
'show_option_no_change' => '',
'option_none_value' => '',
);
$r = wp_parse_args( $args, $defaults );
extract( $r, EXTR_SKIP );
$get_posts_args = compact( 'post_type', 'numberposts' );
$pages = get_posts( $get_posts_args );
$output = '';
$name = esc_attr( $name );
// Back-compat with old system where both id and name were based on $name argument
if ( empty( $id ) )
$id = $name;
if ( ! empty( $pages ) ) {
$output = "\n";
}
$output = apply_filters( 'dropdown_posts-' . $post_type, $output );
if ( $echo ) {
echo $output;
}
return $output;
}
// Add missed values for meta box
public function add_missed_values() {
// default values for meta box
$this->_meta_box = array_merge( array(
'context' => 'normal',
'priority' => 'high',
'pages' => array( 'post' ),
), $this->_meta_box );
// default values for fields
foreach ( $this->_fields as &$field ) {
$multiple = in_array( $field['type'], array( 'checkbox_list', 'file', 'image' ) );
$std = $multiple ? array() : '';
$format = 'date' == $field['type'] ? 'yy-mm-dd' : ( 'time' == $field['type'] ? 'hh:mm' : '' );
$field = array_merge( array(
'multiple' => $multiple,
'std' => $std,
'desc' => '',
'format' => $format,
'validate_func' => '',
), $field );
}
}
// Check if field with $type exists
public function has_field( $type ) {
foreach ( $this->_fields as $field ) {
if ( $type == $field['type'] ) {
return true;
}
}
return false;
}
// Check if current page is edit page
public static function is_edit_page() {
global $pagenow;
return in_array( $pagenow, array( 'post.php', 'post-new.php' ) );
}
/**
* Fixes the odd indexing of multiple file uploads from the format:
* $_FILES['field']['key']['index']
* To the more standard and appropriate:
* $_FILES['field']['index']['key']
*/
public static function fix_file_array( &$files ) {
$output = array();
foreach ( $files as $key => $list ) {
foreach ( $list as $index => $value ) {
$output[ $index ][ $key ] = $value;
}
}
$files = $output;
}
// Get proper jQuery UI version to not conflict with WP admin scripts
public static function get_jqueryui_ver() {
global $wp_version;
if ( version_compare( $wp_version, '3.5', '>=' ) ) {
return '1.9.2';
}
if ( version_compare( $wp_version, '3.1', '>=' ) ) {
return '1.8.10';
}
return '1.7.3';
}
/******************** END HELPER FUNCTIONS **********************/
}