0

Is there a way to only do a section of code on a template if the post has just been published or updated?

What do I need to wrap around that code?

UPDATE:

I need to check if any of my custom-post types called "members" have been saved. The template I'm using to display the posts is single-members.php.

If the post has been saved, then on my single-members.php template, I need to call get_template_part('geocode'); - but only if the post has been saved.

I DON'T WANT THIS TO HAPPEN IN THE ADMIN AREA, THIS NEEDS TO HAPPEN FRONT-END OF THE WEBSITE. OBVIOUSLY THE ONLY THING I WANT TO DO IN THE ADMIN AREA IS TO CLICK PUBLISH/UPDATE.

Here's what's in the geocode.php file:

<?php 

require("database.php");
// Opens a connection to a MySQL server
$con = mysql_connect("localhost", $username, $password);

if (!$con)
{
    die('Could not connect: ' . mysql_error());
}

mysql_select_db("medicom_wp", $con);


    $company = get_field('company_name');
    $address = get_field('address');
    $city = get_field('city');
    $post_code = get_field('post_code');

    $sql = sprintf("select count('x') as cnt from markers where `name` = '%s'", mysql_real_escape_string($company));
    $row_dup = mysql_fetch_assoc(mysql_query($sql,$con));
    if ($row_dup['cnt'] == 0) {
        mysql_query("INSERT INTO markers (`name`, `address`, `lat`, `lng`, `type`) VALUES ('".$company."', '".$address.", ".$city.", ".$post_code."', '0.0', '0.0', '')");
}
wp_reset_query();


define("MAPS_HOST", "maps.google.com");
define("KEY", "");

// Opens a connection to a MySQL server
$connection = mysql_connect("localhost", $username, $password);
if (!$connection) {
  die("Not connected : " . mysql_error());
}

// Set the active MySQL database
$db_selected = mysql_select_db($database, $connection);
if (!$db_selected) {
  die("Can\'t use db : " . mysql_error());
}

// Select all the rows in the markers table
$query = "SELECT * FROM markers WHERE 1";
$result = mysql_query($query);
if (!$result) {
  die("Invalid query: " . mysql_error());
}

// Initialize delay in geocode speed
$delay = 0;
$base_url = "http://" . MAPS_HOST . "/maps/geo?output=xml" . "&key=" . KEY;

// Iterate through the rows, geocoding each address
while ($row = @mysql_fetch_assoc($result)) {
  $geocode_pending = true;

  while ($geocode_pending) {
    $address = $row["address"];
    $id = $row["id"];
    $request_url = $base_url . "&q=" . urlencode($address);
    $xml = simplexml_load_file($request_url) or die("url not loading");

    $status = $xml->Response->Status->code;
    if (strcmp($status, "200") == 0) {
      // Successful geocode
      $geocode_pending = false;
      $coordinates = $xml->Response->Placemark->Point->coordinates;
      $coordinatesSplit = split(",", $coordinates);
      // Format: Longitude, Latitude, Altitude
      $lat = $coordinatesSplit[1];
      $lng = $coordinatesSplit[0];

      $query = sprintf("UPDATE markers " .
             " SET lat = '%s', lng = '%s' " .
             " WHERE id = '%s' LIMIT 1;",
             mysql_real_escape_string($lat),
             mysql_real_escape_string($lng),
             mysql_real_escape_string($id));
      $update_result = mysql_query($query);
      if (!$update_result) {
        die("Invalid query: " . mysql_error());
      }
    } else if (strcmp($status, "620") == 0) {
      // sent geocodes too fast
      $delay += 1000;
    } else {
      // failure to geocode
      $geocode_pending = false;
      echo "Address " . $address . " failed to geocoded. ";
      echo "Received status " . $status . "
\n";
    }
    usleep($delay);
  }
}


?>
4
  • What are you exactly trying to do? Commented Jun 20, 2012 at 13:46
  • @RutwickGangurde When a post is published or updated I want it to trigger some code. To be specific when a custom-post (i.e a company profile) is published or updated then it triggers a Google geocode script.
    – Rob
    Commented Jun 20, 2012 at 13:48
  • 1
    You'll need to use the action hooks mentioned in the answer below! Commented Jun 20, 2012 at 13:49
  • 1
    The post will never be saved when the single-members.php template is being loaded. Saving only happens in the wp-admin, which doesn't display any of your theme's templates.
    – jessica
    Commented Jun 20, 2012 at 14:14

2 Answers 2

4

Why don't you wrap it in post save_post and post_publish hooks?

You have examples here: http://codex.wordpress.org/Function_Reference/add_action

How to do it: Add this to your functions.php file:

function my_data_update () {
 $company = get_field('company_name');
 $address = get_field('address');
 $city = get_field('city');
 $post_code = get_field('post_code');
 //etc etc...
}
add_action('publish_post', 'my_data_update');
add_action('save_post', 'my_data_update');
9
  • I believe not. Why do you need it called inside of page template? Commented Jun 20, 2012 at 13:49
  • functions.php is the perfect place for this. Commented Jun 20, 2012 at 13:50
  • I edited my answer with the solution. Commented Jun 20, 2012 at 14:01
  • I have never tried that, but I believe yes, it can, I don't see why not. ===== I see your update. I believe you can use that, yes, don't see why. Commented Jun 20, 2012 at 14:13
  • Can you explain better? This part: "but it wasn't on the single-members.php template." Commented Jun 20, 2012 at 14:23
1

I recently had almost the exact same use case:

  • On saving a custom post type, check for the existance of some meta data.
  • If it exists, geocode it using the Google Geocode API.
  • Save the result as a new meta field (this one hidden so the user can't screw it up).
  • Note: What I do with the data on the front end of the site is handled in a template file using javascript and the Google Maps API.

It looks like you're assembling multiple fields to get the address (I stored it in one) and you're saving the resulting format differently, but hopefully this serves as a good example that you can borrow from. As I always try to do, I used the WordPress API functions for querying and saving to the database. It's mores secure and future-proof.

Just as @OriginalEXE suggests, I used the save_post hook. I don't think you need publish_post:

save_post is an action triggered whenever a post or page is created or updated, which could be from an import, post/page edit form, xmlrpc, or post by email.

A few more notes:

  • Note the lower priority of the action. I found that leaving it as the default priority left it looking at the previously saved data (which is saved using Advanced Custom Fields which it looks like you're using).
  • The geocoding class was not mine and saved me a huge amount of time. I modified what Sergiy published to use the wp_remote_get() function that has better server support than either curl or file_get_contents. It uses the JSON (Google-recommended) request rather than XML.

I put this in a functionality plugin, but it would work the same in functions.php:

/* function wc_add_latlong()
 * take address from post, geocode it, and save as a custom meta field
 * @parameter $post_id, id of the post being saved, passed by save_post hook
 * @returns nothing
 **************************************/
function wc_add_latlong( $post_id ) {
    // get the address from ACF field
    $address = get_field( 'wc_map_address', $post_id );
    // Check to see if the post type is right, it's not a revision, and there is an address to geocode
    if( get_post_type( $post_id ) == 'wc_biz' && !wp_is_post_revision( $post_id ) && $address ) {
        // call the geocoder class below
        $coords = geocoder::getLocation( $address );
        // split latLngObject with a comma and space
        $lat_long_string = $coords['lat'] . ', ' . $coords['lng'];
        // either add that value as a new post meta field OR update the existing one
        add_post_meta( $post_id, '_wc_lat_long', $lat_long_string, true ) || update_post_meta( $post_id, '_wc_lat_long', $lat_long_string );
    }
}
// This runs on the save_post hook
add_action( 'save_post', 'wc_add_latlong', 11 );

// Thank you Sergiy!
// http://erlycoder.com/45/php-server-side-geocoding-with-google-maps-api-v3
// a class to get the lat and long of an address _server-side_
class geocoder{
    // The base URL for a non-sensor json Google Geocode API request
    static private $url = "http://maps.google.com/maps/api/geocode/json?sensor=false&address=";

    static public function getLocation($address){
        // append URL-friendly address to base URL
        $url = self::$url.urlencode($address);
            // request the Geocode JSON object from Google
        $resp_json = wp_remote_get($url);
            // decode the body of the response
        $resp = json_decode( wp_remote_retrieve_body($resp_json), true );
            // make sure the remove_get was successful and it geocoded the address
        if( !is_wp_error( $resp_json ) && $resp['status']='OK' ) {
                // success! return the lat and long
            return $resp['results'][0]['geometry']['location'];
        }else{
                // we failed, return false
            return false;
        }
    }
}

UPDATE: I've commented all the code so you can understand what's going on. You'll have to adapt it from there.

1
  • Ok thanks. I've updated my question with the actual script that geocodes the addresses. Is there a way to incorporate that?
    – Rob
    Commented Jun 21, 2012 at 10:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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