<?php
namespace fuel;
/**
 * Metabox
 *
 * @author Kyeong Jun Lee<eric@fuelmultimedia.ca>
 *
 * Usage:
 *
 * require get_template_directory() . '/inc/metabox.php';
 * $_html = function() { 
 * ?>
    <p>
        <label for="_my_first_metavalue"><strong><?php _e( 'Website', 'association_contact_information' ); ?></strong></label><br>
        <input style="width:100%;" type="text" name="_my_first_metavalue" id="_my_first_metavalue" value="<?php echo \fuel\Metabox::get( '_my_first_metavalue' ); ?>">
    </p>    <p>
    <label for="_my_second_metavalue"><strong><?php _e( 'Phone', 'association_contact_information' ); ?></strong></label><br>
        <input style="width:100%;" type="text" name="_my_second_metavalue" id="_my_second_metavalue" value="<?php echo \fuel\Metabox::get( '_my_second_metavalue' ); ?>">
    </p>
    <?php
   }
 *    }
 * $_mymetabox = new \fuel\Metabox('_my_first_metabox', __('My First Meta Box','textdomain'), $_html,  array('_my_first_metavalue','_my_second_metavalue'), array('post','page','metatest'), 'advanced', 'default', );
 *
 */
class Metabox
{
    /**
     * @var {string}                        $meta_id     - Unique meta ID
     * @var {string}                        $meta_title  - Title for the metabox (translatable with text domain)
     * @var {callable}                      $callable    - HTML render callable
     * @var {string | array() | WP_Sreen}   $screen      - (Optional) The screen or screens on which to show the box (such as a post type, 'link', or 'comment'). Accepts a single screen ID, WP_Screen object, or array of screen IDs. Default is the current screen.
     * @var {string}                        $context     - (Optional) The context within the screen where the boxes should display. Available contexts vary from screen to screen. Post edit screen contexts include 'normal', 'side', and 'advanced'. Comments screen contexts include 'normal' and 'side'. Menus meta boxes (accordion sections) all use the 'side' context. Global Default value: 'advanced'
     * @var {string}                        $priority    - (Optional) The priority within the context where the boxes should show ('high', 'low', 'default').
     * @var {array()}                       $variables   - Array of variable names
     */
    public $meta_id;
    public $meta_title;
    public $text_domain;
    public $callable;
    public $variables;
    public $screen;
    public $context;
    public $priority;

    /**
     * @param {string}                          $meta_id     - Unique meta ID
     * @param {string}                          $meta_title  - Title for the metabox (translatable with text domain)
     * @param {callable}                        $callable    - HTML render callable
     * @param {array()}                       $variables   - Array of variable names
     * @param {string | array() | WP_Sreen}     $screen      - (Optional) The screen or screens on which to show the box (such as a post type, 'link', or 'comment'). Accepts a single screen ID, WP_Screen object, or array of screen IDs. Default is the current screen.
     * @param {string}                          $context     - (Optional) The context within the screen where the boxes should display. Available contexts vary from screen to screen. Post edit screen contexts include 'normal', 'side', and 'advanced'. Comments screen contexts include 'normal' and 'side'. Menus meta boxes (accordion sections) all use the 'side' context. Global Default value: 'advanced'
     * @param {string}                        $priority      - (Optional) The priority within the context where the boxes should show ('high', 'low', 'default').
     */
    public function __construct($meta_id, $meta_title, $callable, $variables = array(), $screen = array('post','page'), $context = 'advanced', $priority = 'default' ) {
        $this->meta_id       = $meta_id;
        $this->meta_title    = $meta_title;
        $this->callable      = $callable;
        $this->variables     = $variables;
        $this->screen        = $screen;
        $this->context       = $context;
        $this->priority      = $priority;

        $this->addAction();
    }
    /**
     * Static Method to get meta value
     * @param  {string}           $key              Key for the meta value
     * @param  {integer}          $_current_post_id (optional) if specific post meta value is needed.
     * @return {string}                             the value for the key
     */
    public static function get( $key, $_current_post_id = false) {
        $field = null;

        if( !$_current_post_id) {
            global $post;
            $field = get_post_meta( $post->ID, $key, true );
        } else {
            $field = get_post_meta( $_current_post_id, $key, true );
        }

        if ( ! empty( $field ) ) {
            return is_array( $field ) ? stripslashes_deep( $field ) : stripslashes( wp_kses_decode_entities( $field ) );
        } else {
            return false;
        }
    }

    function addAction() {
        //Add Metaboxes
        add_action( 'add_meta_boxes', array( $this, 'meta_add_meta_boxes'), 0 );
        add_action( 'save_post', array( $this, 'on_meta_boxes_save') );
    }

    function meta_add_meta_boxes() {
        add_meta_box(
            $this->meta_id,
            $this->meta_title,
            //Render HTML
            array( $this, 'meta_html'),
            $this->screen,
            $this->context,
            $this->priority
        );
    }

    function meta_html() {
        wp_nonce_field( $this->meta_id, $this->meta_id );
        call_user_func($this->callable);
    }

    function on_meta_boxes_save( $post_id ) {
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
        if ( ! isset( $_POST[$this->meta_id] ) || ! wp_verify_nonce( $_POST[$this->meta_id], $this->meta_id ) ) return;
        if ( ! current_user_can( 'edit_post', $post_id ) ) return;

        foreach( $this->variables as $var) {
            if ( isset( $_POST[$var] ) )
                update_post_meta( $post_id, $var, esc_attr( $_POST[$var] ) );
        }
    }
}
