0

I'm trying to build a little plugin for wp that add a button to custom post type page http://example.com/events that have a link to another custom post type page that I can choose from a dropdown menu in admin pages.

The metabox display properly but the option choosed is not saved when I update the page.

metabox dropdwon menu closed

metabox dropdwon menu closed

this is my code:

class eca_metabox {

    public function __construct()
  {

        add_action( 'add_meta_boxes', array( $this, 'eca_add_meta_box' ) );
        add_action( 'save_post', array( $this, 'save' ), 10, 2 );

    }

    public function eca_add_meta_box()
  {

        add_meta_box(
      'eca-meta',
          'Scegli a quale corso deve linkare questo evento',
          array(
        $this,
        'eca_meta_box_function'
      ),
          'tribe_events',
          'normal',
          'high'
    );

    }

    public function eca_meta_box_function( $post )
  {

    wp_nonce_field( 'eca_nonce_check', 'eca_nonce_check_value' );
    $mv = get_post_meta( $post->ID, '_ec-addons-course', true );
    $post_type_object = get_post_type_object('course');
    $name = $post_type_object->name;
    $label = $post_type_object->label;
    $posts = get_posts(
      array(
        'post_type'=>           'course',
        'post_status'=>         'publish',
        'suppress_filters' =>   false,
        'posts_per_page'=>      -1,
      )
    ); ?>

    <select name="eca-addons-course" id="eca-addons-<?php echo $name; ?>">
      <option value = "" >Tutti i <?php echo strtolower( $label ); ?></option>
    <?php foreach ( $posts as $post ) { ?>
      <option value="<?php echo $post->ID; ?>_<?php echo preg_replace('#[ -]+#', '-' ,$post->post_title ); ?>" <?php selected( $mv, $post->ID ); ?>><?php echo $post->post_title; ?></option>
    <?php } ?>
    </select>

  <?php

  }

    public function save( $post_id )
  {

        if( !isset($_POST['eca_nonce_check_value'] ) )
            return $post_id;

        $nonce = $_POST['eca_nonce_check_value'];
        if( !wp_verify_nonce( 'eca_nonce_check_value', 'eca_nonce_check' ) )
            return $post_id;

        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
            return $post_id;

    $post_type = get_post_type_object( $post->post_type );

        if (!current_user_can( $post_type->cap->edit_post, $post_id ))
        return $post_id;

    $new_meta_value = ( isset( $_POST['ec-addons-course'] ) ? sanitize_text_field( $_POST['ec-addons-course'] ) : '' );
    $mk = 'ec-addons-course';

    update_post_meta( $post->ID, $mk, $new_meta_value );
}

}

$eca_course = new eca_metabox();

add_action( 'tribe_events_single_event_after_the_content', 'ec_addons_single_course_button_link' );
function ec_addons_single_course_button_link()
{
  $output = "<a id ='courseLink' class='tribe-events-course-detail tribe-events-button' href='#' title='Vai al corso'>Vai al dettaglio del corso </a>";
  var_dump($eca_course);

    echo '
        <script type="text/javascript">
            jQuery(document).ready(function($){
                var course = $("' . $output . '");
                $(".tribe-events-cal-links").append(course);
            });
        </script>
    ';
}

On frontend side, th button display properly, but the href not work: now the page redirect itself, I want that link to url of the course that I've choosed in dropdown menu in admin metabox.

Thank for help. Have a nice day.

  • Why are you saving the meta value in this format: {post ID}_{post title escaped} ? Why not just save the post ID? And there are other issues with your code, such as mismatched meta key - _ec-addons-course vs ec-addons-course. – Sally CJ Sep 26 '18 at 13:49
  • Thanks for your reply. You are right about the value, in fact I've follow your hint and I've replaced it only with ID. At this moment, sadly, I'don't know why the choosed input in dropdown menu is not saved when upload the page. Can you help me to find where I'm failing? Thanks. – Sago Sep 26 '18 at 20:00
0

The issues with your code

  1. In the eca_meta_box_function() function, the selected option is not being selected because the option's value is not the post ID which is being used with the selected() function in WordPress: (wrapped for clarity)

    <option value="<?php echo $post->ID; ?>_<?php echo preg_replace('#[ -]+#', '-' ,$post->post_title ); ?>" <!-- wrapped -->
      <?php selected( $mv, $post->ID ); ?>><?php echo $post->post_title; ?></option>
    

    so that should be: (wrapped for clarity)

    <option value="<?php echo $post->ID; ?>" <!-- wrapped -->
      <?php selected( $mv, $post->ID ); ?>><?php echo $post->post_title; ?></option>
    
  2. In the save() function, you should capture two parameters (which WordPress passes to your function via the save_post hook) — 1) $post_id (the post ID); and 2) $post (the post data/object), like so:

    public function save( $post_id, $post )
    
  3. Also in the save() function, you already captured the submitted nonce (which you store in the $nonce variable), but you're not using that variable:

    wp_verify_nonce( 'eca_nonce_check_value', 'eca_nonce_check' )
    

    and that prevents the selected option (or meta value) from being saved into the database! So change that to:

    wp_verify_nonce( $nonce, 'eca_nonce_check' )
    
  4. Also in the save() function, you used the wrong field name — the <select> in the eca_meta_box_function() function has its name set to eca-addons-course as in <select name="eca-addons-course"...>. And yet, in the save() function, you used:

    $_POST['ec-addons-course']
    

    when it should really be:

    $_POST['eca-addons-course']
    

    that mistake also prevents the selected option from being saved, obviously!

  5. Also in the save() function, I believe the meta key you should use is _ec-addons-course (which is used in the eca_meta_box_function() function) and not ec-addons-course:

    $mk = 'ec-addons-course';  // before; incorrect
    $mk = '_ec-addons-course'; // after; correct
    
  6. In the ec_addons_single_course_button_link() function, you're not actually retrieving the saved meta data (and the $eca_course was not accessible from the function/context — you need to do global $eca_course; to get into that variable).

    So you can retrieve the saved meta data like so:

    $course_ID = get_post_meta( get_the_ID(), '_ec-addons-course', true );
    

    and use get_permalink() to retrieve the correct course URL address like so:

    $url = esc_url( get_permalink( $course_ID ) );
    

THE CORRECTED CODE

I didn't re-indent the code (so that you could just compare it with yours, as in the current question). However, I renamed the $mv to $course_ID since that makes more meaningful..

class eca_metabox {

    public function __construct()
  {

        add_action( 'add_meta_boxes', array( $this, 'eca_add_meta_box' ) );
        add_action( 'save_post', array( $this, 'save' ), 10, 2 );

    }

    public function eca_add_meta_box()
  {

        add_meta_box(
      'eca-meta',
          'Scegli a quale corso deve linkare questo evento',
          array(
        $this,
        'eca_meta_box_function'
      ),
          'tribe_events',
          'normal',
          'high'
    );

    }

    public function eca_meta_box_function( $post )
  {

    wp_nonce_field( 'eca_nonce_check', 'eca_nonce_check_value' );
    $course_ID = get_post_meta( $post->ID, '_ec-addons-course', true );
    $post_type_object = get_post_type_object('course');
    $name = $post_type_object->name;
    $label = $post_type_object->label;
    $posts = get_posts(
      array(
        'post_type'=>           'course',
        'post_status'=>         'publish',
        'suppress_filters' =>   false,
        'posts_per_page'=>      -1,
      )
    ); ?>

    <select name="eca-addons-course" id="eca-addons-<?php echo $name; ?>">
      <option value = "" >Tutti i <?php echo strtolower( $label ); ?></option>
    <?php foreach ( $posts as $post ) { ?>
      <option value="<?php echo $post->ID; ?>" <?php selected( $course_ID, $post->ID ); ?>><?php echo $post->post_title; ?></option>
    <?php } ?>
    </select>

  <?php

  }

    public function save( $post_id, $post )
  {

        if( !isset($_POST['eca_nonce_check_value'] ) )
            return $post_id;

        $nonce = $_POST['eca_nonce_check_value'];
        if( !wp_verify_nonce( $nonce, 'eca_nonce_check' ) )
            return $post_id;

        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
            return $post_id;

    $post_type = get_post_type_object( $post->post_type );

        if (!current_user_can( $post_type->cap->edit_post, $post_id ))
        return $post_id;

    $new_meta_value = ( isset( $_POST['eca-addons-course'] ) ? sanitize_text_field( $_POST['eca-addons-course'] ) : '' );
    $mk = '_ec-addons-course';

    update_post_meta( $post->ID, $mk, $new_meta_value );
}

}

$eca_course = new eca_metabox();

add_action( 'tribe_events_single_event_after_the_content', 'ec_addons_single_course_button_link' );
function ec_addons_single_course_button_link()
{
  $course_ID = get_post_meta( get_the_ID(), '_ec-addons-course', true );
  $url = esc_url( get_permalink( $course_ID ) );

  $output = "<a id='courseLink' class='tribe-events-course-detail tribe-events-button' href='$url' title='Vai al corso'>Vai al dettaglio del corso </a>";

    echo '
        <script type="text/javascript">
            jQuery(document).ready(function($){
                var course = $("' . $output . '");
                $(".tribe-events-cal-links").append(course);
            });
        </script>
    ';
}
  • Thanks a lot, you are the man. Now understand better where I was wrong. You helped me a lot. Thanks for your disponibility. Have a nice day – Sago Oct 1 '18 at 4:45
  • I'm glad it helped you @Sago. Have a nice day, too. :) – Sally CJ Oct 2 '18 at 2:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.