Shortcode To Display Map Associated With Current Post?

On this site: http://hometownhelp.org/listing/ace-heating-air-conditioning/

I have Google Maps plugin using a CustomPress field to generate a map for each post. The map on the left in the post is placed by the plugin's option "Automatically show the map" but can only be placed above or below the post. What code or shortcode is used to display the map that is associated with the current post? So I can replace the manually made [map id=xx] shortcde in the right hand meta with the map on the left that's automatically generated, Thanks!

  • Nomad Freelance

    So Ive noticed that Google Maps plugin creates a custom field called agm_map_created or map_created depending on your settings. This field has a value for each post that corresponds with the map id of the map that is associated with that post. So ive tried to do the following in my template:

    <?php $map_id = do_shortcode('[ct id="agm_map_created" property="value"]'); ?>
                            			[agm_map id=<?php echo $map_id; ?>]

    that should place a shortcode for the correct map associated with the post, however it returns [agm_map id=] to the page with no id. Ive noticed CustomPress does not list the custom field agm_map_created. Does the Google Maps plugin not use CustomPress for its custom field or why else is it not listed? How do I return the value of a custom field in wordpress not using CustomPress shortcodes?

  • Nomad Freelance

    @Jude ok so I tried all sorts of ways to make it work and I was able to get the shortcode placed in the meta a few different ways but none of which would allow the map to be displayed. The shortcode was correct and not showing as text, so it was being picked up as a shortcode but would not display the map, possibly something to do with the plugin. The only way I was able to get this to work was placing the map id shortcode in the meta using the CustomPress shortcode, with the following:

    <?php $map_id = get_post_meta( get_the_ID(), 'agm_map_created', true ); ?>
                            		<?php $map_shcode = "[map id=\"{$map_id}\"]" ?>
                            		<?php update_post_meta( get_the_ID(), 'ct_map_text_d5cc', $map_shcode); ?>
    
                            		<?php $st_map = do_shortcode('[ct id="ct_map_text_d5cc" property="value"]'); ?>
                            			<?php echo $st_map; ?>

    Google maps plugin makes a custom field 'agm_map_created' and makes the value = the map id of the map associated with that post. I got that map id and wrap it with the rest of the map shortcode text. Then the only way it will display is with CustomPress shortcode so I have another CustomPress field called 'ct_map_text_d5cc' and I update that with the correct map id shortcode I just made using update_post_meta.

    This all works fine, the only problem is I have this in my page template so every time the page is loaded update_post_meta is ran and the custom field gets updated unnecessarily.

    What template or file/where should I place the first part of this code so only each time the page is updated/published the first part of this is ran?

  • Nomad Freelance

    I've made some updates to the code I'm using:

    <?php $map_meta = get_post_meta( get_the_ID(), 'ct_map_text_d5cc', true ); ?>
    <?php $map_id = get_post_meta( get_the_ID(), 'agm_map_created', true ); ?>
    <?php $map_shcode = "[map id=\"{$map_id}\"]" ?>	
    
    <?php if ( $map_meta != $map_shcode ) {
    update_post_meta( get_the_ID(), 'ct_map_text_d5cc', $map_shcode); } ?>
    
    <?php echo do_shortcode('[ct id="ct_map_text_d5cc" property="value"]'); ?>

    It now checks if its necessary to update the value of the custom field or not. However its still checking this each time the page is loaded as its in the page template, don't think that's the appropriate way of doing this. Also if the meta field needs to be updated it will get updated when the page loads and then require you to reload the page to see the effect. So the first person to view the page after the custom field 'address' has been updated will see a new address and an old map that do not match up.

    I have looked into the wordpress functions save_post http://codex.wordpress.org/Plugin_API/Action_Reference/save_post and edit_post etc. Might want the above code to be run each time one or any of those functions gets called and I'm looking into how to make a quick plugin to do this. Any help is appreciated

  • Hoang Ngo

    Hi @Nomad Freelance,

    You can create a new plugin, with this code

    add_action('save_post', 'update_map_shortcode', 10, 3);
    function update_map_shortcode($post_id, $post, $update)
    {
        $map_meta = get_post_meta($post_id, 'ct_map_text_d5cc', true);
        $map_id = get_post_meta($post_id, 'agm_map_created', true);
        $map_shcode = "[map id=\"{$map_id}\"]";
        if ( $map_meta != $map_shcode ){
            update_post_meta( $post_id, 'ct_map_text_d5cc', $map_shcode);
        }
    }

    The function is similar to your code above, but instead of when loading & displaying, it will process when a post get saved. Lets see if it works for you :slight_smile:.

    Best regards,
    Hoang

    • Nomad Freelance

      @Hoang Ngo thank you for the help. However there is a problem I am having with both of our code. I now have to press update post two separate times for all of the custom fields to sync up. Does Google maps hook save_post as well and how could I determine whats going first? Can I make the post save twice or make save_post go a second round? I shouldn't have to do that right? The shortcode being made by this code is using the old data (the value of the field at the time it was published.) and not the new value thats being generated by Google maps at the time of saving.

      Here's what I've got and how it works

      A Custom Press field named 'Address'
      
      Google Maps plugin setup to use custom field 'Address' to generate map and then associate the map with that post. If 'Address' value changes a new map (with new map id) will be created.
      
      Custom field created by Google Maps plugin that stores the map id of the map that is associated with that post.
      
      Custom Press field named 'Map' used to place map shortcode in the meta sidebar.

      The code is taking they value of the custom field created by Google Maps that contains only a map id (gets updated if 'Address' changes) and makes a shortcode based on that map id. Then places that shortcode in the custom field 'Map'

      This should all work. If I change 'Address' the Google Maps plugin will generate a new map id and place it in the custom field it created. But I think the code is taking the value of that custom field at the time publish was clicked and not the new value Google maps generates as a result of 'Address' being changed.

      How does hooking save_post work? Does it execute the code right when update/publish is clicked or after the post is saved?? I need it to run after the post is saved maybe?

  • Jose

    Hey again Nomad,

    The post_save hook is supposed to work fine. CustomPress hooks on it with a priority 1, which means that it is executed first. I believe it is not updating correctly for you because the shortcode is picking a cached value.

    Anyway, I decided to go with a more specific approach by hooking in the post metadata update action: 'updated_postmeta'.
    It would look like this:

    if( !function_exists('update_map_shortcode')){
        function update_map_shortcode($meta_id, $object_id, $meta_key, $meta_value){
            $target_meta_key = 'agm_map_created';
            if( $meta_key == $target_meta_key){
                $map_shortcode = "[map id=\"{$meta_value}\"]";
                update_post_meta( $object_id, 'ct_map_text_d5cc', $map_shortcode);
            }
        }
        add_action( 'updated_postmeta', 'update_map_shortcode', 10, 4);
    }

    This will work for sure and keep the shortcode synchronized with the right ID.

    BUT, then I realized that the simpler approach is to grab the id directly from the post metadata and build the shortcode dynamically. Exactly what you were trying to achieve in the beginning :slight_smile:

    <?php $map_id = do_shortcode('[ct id="agm_map_created" property="value"]'); ?>
                            			[agm_map id=<?php echo $map_id; ?>]

    The problem with your code is that you are trying to get the agm_map_created metadata as a CustomPress field, when it is just a post metadata value.

    So, the right code would be something like this:

    <?php $map_id = get_post_meta( $post_id, 'agm_map_created', true ); ?>
    [agm_map id=<?php echo $map_id; ?>]

    Haven't had the chance to test this last snippet, but it should work.
    Please let me know if I missed something.

    Cheers,
    Jose

    • Nomad Freelance

      The problem this whole time is the Google maps plugin itself.

      Ok so Ive figured out how to get the map shortcode to work using the following

      $map_id = get_post_meta( get_the_ID(), 'agm_map_created', true );
      $map_shcode = "[map id=\"{$map_id}\"]";
      echo do_shortcode($map_shcode);

      This works perfectly. Only problem is with the Google maps plugin itself.

      Nothing was out of sync, I'm getting the value for the shortcode directly from the custom field created by the plugin. But that field is not created/updated until the post/page is loaded? Correct me if I'm wrong, Please try this out

      Install Wp
      Install Custom Press
      Install Google maps
      Place the above code into the page template somewhere, mine is in the meta.

      Make a custom field called address
      Setup Google maps to use the field 'address' for its address, and associate Maps with posts.
      Make a post and enter an address in the custom field 'address' and publish it.

      Now Without viewing the post look at its custom fields. agm_map_created is not yet there.

      If you now view the page, the page will not have a map. But it will now create the custom field 'agm_map_created' with a unique value
      Now if you reload the page the above code will place a map now that 'agm_map_created' exists.

      If you update the address and a new map is created, you will see the old map the first time you load the page. After reloading the page the map will update.

      Alternately you can update the post a second time after changing the address to have the value of 'agm_map_created' updated.

      Can this be fixed? 'agm_map_created' should be created/updated when I create/update the post, not the second time I press update and not the first time I view the page.

  • Jose

    Hey Nomad,

    I think that you are totally right. It would be a better approach to re-generate the map when the metadata is updated, instead of when the post is rendered.
    I'll discuss this with the developer to see if there is some caveat on moving this to a different hook.

    In the meantime, you can add this into your mu-plugin or functions.php:

    function update_map_meta( $post_id ) {
        if( !class_exists('AgmMapModel') ){ return; }
        $model = new AgmMapModel();
        $fields = AgmMapModel::get_config( 'custom_fields_map' );
    
        // Check if we have already done this
        $map_id = get_post_meta( $post_id, 'agm_map_created', true );
    
        $latitude = $longitude = $address = false;
        if ( $fields['latitude_field'] ) {
            $latitude = get_post_meta( $post_id, $fields['latitude_field'], true );
        }
        if ( $fields['longitude_field'] ) {
            $longitude = get_post_meta( $post_id, $fields['longitude_field'], true );
        }
        if ( $fields['address_field'] ) {
            /*
             * We allow the address-field to contain a list of field names
             * @since 2.9.0.5
             */
            $address = '';
            $address_fields = explode( ',', $fields['address_field'] );
            foreach ( $address_fields as $address_field ) {
                $address_field = trim( $address_field );
                $field_value = get_post_meta( $post_id, $address_field, true );
                $address .= $field_value . ' ';
            }
        }
    
        $latitude = apply_filters( 'agm_google_maps-post_meta-latitude', $latitude );
        $longitude = apply_filters( 'agm_google_maps-post_meta-longitude', $longitude );
        $address = apply_filters( 'agm_google_maps-post_meta-address', $address );
    
        if ( ! $map_id ) {
            // try to creatr map based on lat/lng.
            if ( ! $latitude && ! $longitude && ! $address ) {
                return; // Nothing to process
            }
            $map_id = $model->autocreate_map( $post_id, $latitude, $longitude, $address );
        } else {
            // Create map based on saved settings.
            $map = $model->get_map( $map_id );
            //TODO: can we make this condition simpler? 90% duplicate code
            if ( $address ) {
                if ( $address != $map['markers'][0]['title'] ) {
                    if ( isset( $fields['discard_old'] ) && $fields['discard_old'] ) {
                        $model->delete_map( array('id' => $map_id) );
                    }
                    $map_id = $model->autocreate_map( $post_id, $latitude, $longitude, $address );
                }
            } else if ( $latitude && $longitude ) {
                if ( $latitude != $map['markers'][0]['position'][0] || $longitude != $map['markers'][0]['position'][1] ) {
                    if ( isset( $fields['discard_old'] ) && $fields['discard_old'] ) {
                        $model->delete_map( array('id' => $map_id) );
                    }
                    $map_id = $model->autocreate_map( $post_id, $latitude, $longitude, $address );
                }
            }
        }
    }
    
    add_action( 'save_post', 'update_map_meta' );

    If this snippet works as expected -crossed fingers-, the map metadata will be updated whenever the post is created or updated.

    Please let me know if this does the trick :slight_smile:

    Cheers,
    Jose

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.