GeoMashup y Wpml – Solución incompatibilidad sin modificar el código de los plugins

El plugin WPML no es compatible con Geomashup.
El siguiente error es devuelto y el mapa no aparece:

Fatal error: Call to a member function is_attachment() on a non-object in ../wp-content/plugins/sitepress-multilingual-cms/sitepress.class.php

En este hilo dan una solución que no es muy útil, ya que implica modificar el core del plugin, lo que significa perder el cambio en la primera actualización.

Así que decidí buscar una solución más ‘ortodoxa’. Conseguir que funcionen con hooks y mantener mis cambios incluso después de actualizar.

Para ello he tenido que crear tres nuevos objetos de las siguientes clases
SitePress -> de WMPL
GeoMashup -> de Geomashup
GeoMashupDB -> de Geomashup

Puedes bajarte los tres archivos aquí o copiarlos de las siguientes líneas.
Aquí los pasos a seguir.

1- crear el archivo Class-MyNewSitepress.php con el siguiente contenido


<?php
/**
* Create new class MyNewSitepress
* wich will be use from Geomashup in Class MyGeoMashupDBext
* All this just to delete is_attachment which creates conflict with Geomashup plugin
**/
class MyNewSitepress extends SitePress {
private $this_lang;
function __construct()
{
global $wpdb, $pagenow;
remove_filter ( 'posts_join', array( $this, 'posts_join_filter' ),10,1);
remove_filter ( 'posts_where', array( $this, 'posts_where_filter' ),10,2);
}

function posts_join_filter($join, $query) {


global $wpdb, $pagenow, $wp_taxonomies, $sitepress_settings;
$attachment_is_translatable = $this->is_translated_post_type( 'attachment' );
if ( (($pagenow == 'upload.php' || $pagenow == 'media-upload.php') && !$attachment_is_translatable) || ( isset( $query->queried_object ) && isset( $query->queried_object->ID ) && $query->queried_object->ID == $sitepress_settings[ 'urls' ][ 'root_page' ] ) ) {
return $join;
}

// determine post type
$debug_backtrace = $this->get_backtrace( 0, true, false ); //Limit to a maximum level?
$post_type = false;
foreach ( $debug_backtrace as $o ) {
if ( $o[ 'function' ] == 'apply_filters_ref_array' && $o[ 'args' ][ 0 ] == 'posts_join' ) {
$post_type = esc_sql( $o[ 'args' ][ 1 ][ 1 ]->query_vars[ 'post_type' ] );
break;
}
}

if ( $post_type == 'any' || 'all' == $this->this_lang ) {
$left_join = "LEFT";
} else {
$left_join = "";
}

if ( is_array( $post_type ) ) {
$post_types = array();
foreach ( $post_type as $ptype ) {
if ( $this->is_translated_post_type( $ptype ) ) {
$post_types[ ] = esc_sql( 'post_' . $ptype );
}
}
if ( !empty( $post_types ) ) {
$join .= " {$left_join} JOIN {$wpdb->prefix}icl_translations t ON {$wpdb->posts}.ID = t.element_id
AND t.element_type IN ('" . join( "','", $post_types ) . "') JOIN {$wpdb->prefix}icl_languages l ON t.language_code=l.code AND l.active=1";
}
} elseif ( $post_type ) {
if ( $this->is_translated_post_type( $post_type ) ) {
$join .= " {$left_join} JOIN {$wpdb->prefix}icl_translations t ON {$wpdb->posts}.ID = t.element_id
AND t.element_type = 'post_{$post_type}' JOIN {$wpdb->prefix}icl_languages l ON t.language_code=l.code AND l.active=1";
} elseif ( $post_type == 'any' ) {
$join .= " {$left_join} JOIN {$wpdb->prefix}icl_translations t ON {$wpdb->posts}.ID = t.element_id
AND t.element_type LIKE 'post\\_%' {$left_join} JOIN {$wpdb->prefix}icl_languages l ON t.language_code=l.code AND l.active=1";
}
} else {

if ( is_tax() && is_main_query() ) {
$tax    = get_query_var( 'taxonomy' );
$taxonomy_post_types = $wp_taxonomies[ $tax ]->object_type;

foreach ( $taxonomy_post_types as $k => $v ) {
if ( !$this->is_translated_post_type( $v ) ) {
unset( $taxonomy_post_types[ $k ] );
}
}
} else {
$taxonomy_post_types = array_keys( $this->get_translatable_documents( false ) );
}

if ( !empty( $taxonomy_post_types ) ) {
foreach ( $taxonomy_post_types as $k => $v ) {
$taxonomy_post_types[ $k ] = 'post_' . $v;
}
$post_types = "'" . join( "','", $taxonomy_post_types ) . "'";
$join .= " {$left_join} JOIN {$wpdb->prefix}icl_translations t ON {$wpdb->posts}.ID = t.element_id
AND t.element_type IN ({$post_types}) JOIN {$wpdb->prefix}icl_languages l ON t.language_code=l.code AND l.active=1";
}
}


return $join;
}
function posts_where_filter( $where, $query )
{
global $pagenow, $wp_taxonomies, $sitepress, $sitepress_settings;
//exceptions

$post_type = false;

if ( isset( $query->queried_object ) && isset( $query->queried_object->ID ) && $query->queried_object->ID == $sitepress_settings[ 'urls' ][ 'root_page' ] ) {
return $where;
}

// determine post type
$debug_backtrace = $this->get_backtrace( 0, true, false ); //Limit to a maximum level?
foreach ( $debug_backtrace as $o ) {
if ( $o[ 'function' ] == 'apply_filters_ref_array' && $o[ 'args' ][ 0 ] == 'posts_where' ) {
$post_type = $o[ 'args' ][ 1 ][ 1 ]->query_vars[ 'post_type' ];
break;
}
}

// case of taxonomy archive
if ( empty( $post_type ) && is_tax() ) {
$tax       = get_query_var( 'taxonomy' );
$post_type = $wp_taxonomies[ $tax ]->object_type;
foreach ( $post_type as $k => $v ) {
if ( !$this->is_translated_post_type( $v ) ) {
unset( $post_type[ $k ] );
}
}
if ( empty( $post_type ) ) {
return $where;
} // don't filter
}

if ( !$post_type ) {
$post_type = 'post';
}

if ( is_array( $post_type ) && !empty( $post_type ) ) {
$none_translated = true;
foreach ( $post_type as $ptype ) {
if ( $this->is_translated_post_type( $ptype ) ) {
$none_translated = false;
}
}
if ( $none_translated ) {
return $where;
}
} else {
if ( !$this->is_translated_post_type( $post_type ) && 'any' != $post_type ) {
return $where;
}
}

$attachment_is_translatable = $sitepress->is_translated_post_type( 'attachment' );
if ( ($pagenow == 'upload.php' || $pagenow == 'media-upload.php') && !$attachment_is_translatable) {
return $where;
}

$current_language = $sitepress->get_current_language();
$requested_id = false;
// Fix for when $sitepress->get_current_language() does not return the correct value (e.g. when request is made for an attachment, an iframe or an ajax call)
if ( isset( $_REQUEST[ 'attachment_id' ] ) && $_REQUEST[ 'attachment_id' ] ) {
$requested_id        = $_REQUEST[ 'attachment_id' ];
}
if ( isset( $_REQUEST[ 'post_id' ] ) && $_REQUEST[ 'post_id' ] ) {
$requested_id        = $_REQUEST[ 'post_id' ];
}

if($requested_id) {
$post_type        = get_post_type( $requested_id );
$current_language = $sitepress->get_language_for_element( $requested_id, 'post_' . $post_type );

if(!$current_language) {
$current_language = $sitepress->get_current_language();
}
}

if ( 'all' != $this->this_lang ) {
if ( 'any' == $post_type ) {
$condition = " AND (t.language_code='" . esc_sql( $current_language ) . "' OR t.language_code IS NULL )";
} else {
$condition = " AND t.language_code='" . esc_sql( $current_language ) . "'";
}
} else {
$condition = '';
}

$where .= $condition;

return $where;
}
}

$GeoMUSitepress = new MyNewSitepress();
?>

2- Crear el archivo Class-MyGeoMashupDBext.php con el siguiente contenido


<?php
/**
* Class used to query posts from DB
*
**/
class MyGeoMashupDBext extends GeoMashupDB {
	public static function get_object_locations( $query_args = '' ) {
		global $wpdb;

		$default_args = array( 
			'minlat' => null, 
			'maxlat' => null, 
			'minlon' => null, 
			'maxlon' => null,
			'radius_km' => null,
			'radius_mi' => null,
			'map_cat' => null,
			'tax_query' => null,
			'map_post_type' => 'any',
			'object_name' => 'post',
			'show_future' => 'false', 
			'suppress_filters' => false,
	 		'limit' => 0,
			'map_offset' => 0,
		);
		$query_args = wp_parse_args( $query_args, $default_args );
		
		// Construct the query 
		$object_name = $query_args['object_name'];
		$object_store = self::object_storage( $object_name );
		if ( empty( $object_store ) ) {
			return null;
		}

		// Giving tables an alias was a mistake, now filters depend on them
		$field_string = "gmlr.object_id, gmlr.geo_date, o.{$object_store['label_column']} as label, gml.*";
		$table_string = "{$wpdb->prefix}geo_mashup_locations gml " . 
			"INNER JOIN {$wpdb->prefix}geo_mashup_location_relationships gmlr " .
			$wpdb->prepare( 'ON gmlr.object_name = %s AND gmlr.location_id = gml.id ', $object_name ) .
			"INNER JOIN {$object_store['table']} o ON o.{$object_store['id_column']} = gmlr.object_id";
		$wheres = array( );
		$groupby = '';
		$having = '';

		if ( 'post' == $object_name ) {
			$field_string .= ', o.post_author';
			if ( $query_args['show_future'] == 'true' ) {
				$wheres[] = 'post_status in ( \'publish\',\'future\' )';
			} else if ( $query_args['show_future'] == 'only' ) {
				$wheres[] = 'post_status = \'future\'';
			} else {
				$wheres[] = 'post_status = \'publish\'';
			}

		} else if ( 'comment' == $object_name ) {
			$wheres[] = 'comment_approved = \'1\'';
		}

		$location_args = wp_array_slice_assoc( $query_args, array_keys( GM_Location_Query::get_defaults() ) );
		$location_query = new GM_Location_Query( $location_args );

		// Handle inclusion and exclusion of terms
		if ( ! empty( $query_args['tax_query'] ) and is_array( $query_args['tax_query'] ) )
			$tax_query = $query_args['tax_query'];
		else
			$tax_query = array();

		if ( ! empty( $query_args['map_cat'] ) ) {

			$cats = preg_split( '/[,\s]+/', $query_args['map_cat'] );

			$escaped_include_ids = array();
			$escaped_exclude_ids = array();

			foreach( $cats as $cat ) {

				if ( is_numeric( $cat ) ) {

					if ( $cat < 0 ) {
						$escaped_exclude_ids[] = abs( $cat );
						$escaped_exclude_ids = array_merge( $escaped_exclude_ids, get_term_children( $cat, 'category' ) );
					} else {
						$escaped_include_ids[] = intval( $cat );
						$escaped_include_ids = array_merge( $escaped_include_ids, get_term_children( $cat, 'category' ) );
					}

				} else {

					// Slugs might begin with a dash, so we only include them
					$term = get_term_by( 'slug', $cat, 'category' );
					if ( $term ) {
						$escaped_include_ids[] = $term->term_id;
						$escaped_include_ids = array_merge( $escaped_include_ids, get_term_children( $term->term_id, 'category' ) );
					}
				}
			} 

			if ( ! empty( $escaped_include_ids ) ) {
				$tax_query[] = array(
					'taxonomy' => 'category',
					'terms' => $escaped_include_ids,
					'field' => 'term_id',
				);
			}

			if ( ! empty( $escaped_exclude_ids ) ) {
				$tax_query[] = array(
					'taxonomy' => 'category',
					'terms' => $escaped_exclude_ids,
					'operator' => 'NOT IN',
					'field' => 'term_id',
				);
			}

		} // end if map_cat exists 

		if ( !empty( $tax_query ) ) {
			$tax_clauses = get_tax_sql( $tax_query, 'o', $object_store['id_column'] );
			$table_string .= $tax_clauses['join'];
			$wheres[] = preg_replace( '/^ AND/', '', $tax_clauses['where'] );
			$groupby = 'GROUP BY gmlr.object_id';
		}

		if ( 'post' == $object_name ) {
			// Handle inclusion and exclusion of post types
			if ( 'any' == $query_args['map_post_type'] ) {
				$include_post_types = '';
				$searchable_post_types = GeoMashup::get_searchable_post_types();

				if ( ! empty( $searchable_post_types ) )
					$include_post_types .= "o.post_type IN ('" . join("', '", array_map( 'esc_sql', $searchable_post_types ) ) . "')";

				$wheres[] = $include_post_types;
			} else {
				if ( !is_array( $query_args['map_post_type'] ) ) 
					$query_args['map_post_type'] = preg_split( '/[,\s]+/', $query_args['map_post_type'] );
				$wheres[] = "o.post_type IN ('" . join("', '", $query_args['map_post_type']) . "')";
			}
		} 

		if ( ! empty( $query_args['object_id'] ) ) {
			$wheres[] = 'gmlr.object_id = ' . esc_sql( $query_args['object_id'] );
		} else if ( ! empty( $query_args['object_ids'] ) ) {
			$wheres[] = 'gmlr.object_id IN ( ' . esc_sql( $query_args['object_ids'] ) .' )';
		}

		if ( ! empty( $query_args['exclude_object_ids'] ) ) 
			$wheres[] = 'gmlr.object_id NOT IN ( ' . esc_sql( $query_args['exclude_object_ids'] ) . ' )';

		list( $l_cols, $l_join, $l_where, $l_groupby ) = $location_query->get_sql( 'o', $object_store['id_column'] );
		$field_string .= $l_cols;
		$table_string .= $l_join;
		if ( empty( $groupby ) and !empty( $l_groupby ) )
			$groupby = 'GROUP BY ' . $l_groupby;
		$where = ( empty( $wheres ) ) ? '' :  'WHERE ' . implode( ' AND ', $wheres ) . $l_where;
		$sort = ( isset( $query_args['sort'] ) ) ? $query_args['sort'] : $object_store['sort'];
		$sort = ( empty( $sort ) ) ? '' : 'ORDER BY ' . esc_sql( $sort );
		$offset = absint( $query_args['map_offset'] );
		$limit = absint( $query_args['limit'] );
		if ( $limit or $offset )
			$limit = " LIMIT {$offset},{$limit}";
		else
			$limit = '';

		if ( ! $query_args['suppress_filters'] ) {
			$field_string = apply_filters( 'geo_mashup_locations_fields', $field_string );
			$table_string = apply_filters( 'geo_mashup_locations_join', $table_string );
			$where = apply_filters( 'geo_mashup_locations_where', $where );
			$sort = apply_filters( 'geo_mashup_locations_orderby', $sort );
			$groupby = apply_filters( 'geo_mashup_locations_groupby', $groupby );
			$limit = apply_filters( 'geo_mashup_locations_limits', $limit );

			$suppress_post_filters = defined( 'GEO_MASHUP_SUPPRESS_POST_FILTERS' ) && GEO_MASHUP_SUPPRESS_POST_FILTERS;
			if ( 'post' === $object_name and ! $suppress_post_filters and isset( $GLOBALS['sitepress'] ) ) {
				// Ok, we're catering to WPML here. If we ever integrate with a WP_Query object for posts,
				// this could be made more general

				// This filter will include all translatable post types, I hope
				add_filter( 'get_translatable_documents', array( __CLASS__, 'wpml_filter_get_translatable_documents' ) );

				// Apply post query filters, changing posts table references to our alias
				// As of WPML 2.9 these calls can trigger undefined variable notices
   				global $GeoMUSitepress;
				$table_string = $GeoMUSitepress->posts_join_filter( $table_string, null );
				$table_string = str_replace( $wpdb->posts . '.', 'o.', $table_string );
				$where = $GeoMUSitepress->posts_where_filter( $where, null );
				$where = str_replace( $wpdb->posts . '.', 'o.', $where );

				remove_filter( 'get_translatable_documents', array( __CLASS__, 'wpml_filter_get_translatable_documents' ) );
			}
		}
		
		$query_string = "SELECT $field_string FROM $table_string $where $groupby $having $sort $limit";

		$wpdb->query( $query_string );
		
		return $wpdb->last_result;
	}
}


?>

3- Crear el archivo Class-GeoMashupINA.php con el siguiente contenido

<?php
/**
* class to be called instead of Geomashup:map
* to avoid WPML Conflict
**/
class GeoMashupINA extends GeoMashup {


	/**
	 * Convert deprecated attribute names.
	 *
	 * @since 1.3
	 * 
	 * @param array $atts Attributes to modify.
	 */
	private static function convert_map_attributes( &$atts ) {
		$attribute_conversions = array( 
			'auto_open_info_window' => 'auto_info_open',
			'open_post_id' => 'open_object_id'
		);
		foreach ( $attribute_conversions as $old_key => $new_key ) {
			if ( isset( $atts[$old_key] ) ) {
				if ( ! isset( $atts[$new_key] ) ) {
					$atts[$new_key] = $atts[$old_key];
				}
				unset( $atts[$old_key] );
			}
		}
	}
	/**
	 * Process an iframe map request.
	 *
	 * @since 1.3
	 * @uses render-map.php
	 */
	private static function render_map() {
		require_once( 'render-map.php' );
		GeoMashupRenderMap::render_map();
		exit();
	}
	public static function init() {
		if ( GEO_MASHUP_DB_VERSION != GeoMashupDB::installed_version() ) {
			// We're active but not installed - try once more to install
			MyGeoMashupDBext::install();
		}
		GeoMashup::load_styles();
		GeoMashup::load_scripts();
	}

    	public static function map( $atts = null ) {
		global $wp_query, $in_comment_loop, $geo_mashup_options;
		static $map_number = 1;

		$atts = wp_parse_args( $atts );
		$static = (bool)( !empty( $atts['static'] ) and 'true' == $atts['static'] );
		unset( $atts['static'] );
		if ( empty( $atts['lang'] ) ) {
			if ( function_exists( 'qtrans_getLanguage' ) ) {
				// qTranslate integration
				$atts['lang'] = qtrans_getLanguage();
			} else if ( defined( 'ICL_LANGUAGE_CODE' ) ) {
				// WPML integration
				$atts['lang'] = ICL_LANGUAGE_CODE;
			}
		}
		$click_to_load_options = array( 'click_to_load', 'click_to_load_text' );

		self::convert_map_attributes( $atts );

		// Default query is for posts
		$object_name = ( isset( $atts['object_name'] ) ) ? $atts['object_name'] : 'post';

		// Map content type isn't required, if empty we'll choose one
		$map_content = isset( $atts['map_content'] ) ? $atts['map_content'] : null;

		// Find the ID and location of the container object if it exists
		if ( 'post' == $object_name and $wp_query->in_the_loop ) {

			$context_object_id = $wp_query->post->ID;

		} else if ( 'comment' == $object_name and $in_comment_loop ) {
			
			$context_object_id = get_comment_ID();

		} else if ( 'user' == $object_name and $wp_query->post ) {

			$context_object_id = $wp_query->post->post_author;

		}

		if ( empty( $atts['object_id'] ) ) {

			if ( ! empty( $context_object_id ) ) {

				// If we found a context object, we'll query for that by default
				$atts['object_id'] = $context_object_id;
				$context_location = MyGeoMashupDBext::get_object_location( $object_name, $context_object_id );

			} else if ( 'single' == $map_content and 'post' == $object_name ) {

				// In secondary post loops we won't find a context object
				// but can at least allow explicit single maps
				$atts['object_id'] = get_the_ID();
			}

		}

		if ( empty ( $map_content ) ) {

			if ( empty( $context_object_id ) ) {
				$map_content = 'contextual';
			} else if ( empty( $context_location ) ) {
				// Not located, go global
				$map_content = 'global';
			} else {
				// Located, go single
				$map_content = 'single';
			}

		} else if ( $map_content instanceof WP_Query ) {

			// We've been given a post query, put its contents in a global map
			$atts['object_ids'] = implode( ',', wp_list_pluck( $map_content->posts, 'ID' ) );
			$map_content = 'global';

		}

		switch ($map_content) {
			case 'contextual':
				$atts['map_content'] = 'contextual';
				$atts += $geo_mashup_options->get( 'context_map', $click_to_load_options );
				$object_ids = array();
				if ( 'comment' == $object_name ) {
					$context_objects = $wp_query->comments;
				} else {
					$context_objects = $wp_query->posts;
				}
				if ( !is_array( $context_objects ) ) {
					return '<!-- ' . __( 'Geo Mashup found no objects to map in this context', 'GeoMashup' ) . '-->';
				}
				foreach ( $context_objects as $context_object ) {
					if ( 'post' == $object_name ) {
						$object_ids[] = $context_object->ID;
					} else if ( 'user' == $object_name ) {
						$object_ids[] = $context_object->post_author;
					} else if ( 'comment' == $object_name ) {
						$object_ids[] = $context_object->comment_ID;
					}
				}
				$atts['object_ids'] = implode( ',', $object_ids );
				break;

			case 'single':
				$atts['map_content'] = 'single';
				$atts += $geo_mashup_options->get( 'single_map', $click_to_load_options );
				if ( empty( $atts['object_id'] ) ) {
					return '<!-- ' . __( 'Geo Mashup found no current object to map', 'GeoMashup' ) . '-->';
				}
				$single_location = MyGeoMashupDBext::get_object_location( $object_name, $atts['object_id'] );
				if ( empty( $single_location ) ) {
					return '<!-- ' . __( 'Geo Mashup omitted a map for an object with no location', 'GeoMashup' ) . '-->';
				}
				break;

			case 'global':
				if ( isset( $_GET['template'] ) and 'full-post' == $_GET['template'] ) {
					// Global maps tags in response to a full-post query can infinitely nest, prevent this
					return '<!-- ' . __( 'Geo Mashup map omitted to avoid nesting maps', 'GeoMashup' ) . '-->';
				}
				$atts['map_content'] = 'global';

				// Global maps on a page will make use of query string arguments unless directed otherwise
				$ignore_url = false;
				if ( isset( $atts['ignore_url'] ) && 'true' == $atts['ignore_url'] ) {
					$ignore_url = true;
					unset( $atts['ignore_url'] );
				}
				if ( isset($_SERVER['QUERY_STRING']) and !$ignore_url ) 
					$atts = wp_parse_args( $_SERVER['QUERY_STRING'], $atts );

				$atts += $geo_mashup_options->get( 'global_map', $click_to_load_options );

				// Don't query more than max_posts
				$max_posts = $geo_mashup_options->get( 'global', 'max_posts' );
				if ( empty( $atts['limit'] ) and !empty( $max_posts ) )
					$atts['limit'] = $max_posts;
				break;

			default:
				return '<div class="gm-map"><p>Unrecognized value for map_content: "'.$map_content.'".</p></div>';
		}
		
		$click_to_load = $atts['click_to_load'];
		unset( $atts['click_to_load'] );
		$click_to_load_text = $atts['click_to_load_text'];
		unset( $atts['click_to_load_text'] );
		if ( !isset( $atts['name'] ) )
			$atts['name'] = 'gm-map-' . $map_number;

		$map_data = self::build_map_data( $atts );
		if ( empty( $map_data['object_data']['objects'] ) and !isset( $map_data['load_empty_map'] ) )
			return '<!-- ' . __( 'Geo Mashup omitted a map with no located objects found.', 'GeoMashup' ) . '-->';
		unset( $map_data['load_empty_map'] );

		$width_units = ( '%' === substr( $map_data['width'], -1 ) ) ? '%' : 'px';
		$width = intval( $map_data['width'] );
		$width_style = $width . $width_units;
		$height_units = ( '%' === substr( $map_data['height'], -1 ) ) ? '%' : 'px';
		$height = intval( $map_data['height'] );
		$height_style = $height . $height_units;

		$map_image = '';
		if ( $static ) {
			// Static maps have a limit of 50 markers: http://code.google.com/apis/maps/documentation/staticmaps/#Markers
			$atts['limit'] = empty( $atts['limit'] ) ? 50 : $atts['limit'];

			if ( !empty( $map_data['object_data']['objects'] ) ) {
				$map_image = '<img src="http://maps.google.com/maps/api/staticmap?size='.$width.'x'.$height;
				if ( count( $map_data['object_data']['objects'] ) == 1) {
					$map_image .= '&amp;center=' . $map_data['object_data']['objects'][0]['lat'] . ',' .
						$map_data['object_data']['objects'][0]['lng'];
				}
				$map_image .= '&amp;sensor=false&amp;zoom=' . $map_data['zoom'] . '&amp;markers=size:small|color:red';
				foreach( $map_data['object_data']['objects'] as $location ) {
					// TODO: Try to use the correct color for the category? Draw category lines?
					$map_image .= '|' . $location['lat'] . ',' . $location['lng'];
				}
				$map_image .= '" alt="geo_mashup_map"';
				if ($click_to_load == 'true') {
					$map_image .= '" title="'.$click_to_load_text.'"';
				}
				$map_image .= ' />';
				$map_image = apply_filters('geo_mashup_static_map', $map_image, $map_data, array('click_to_load' => $click_to_load, 'click_to_load_text' => $click_to_load_text));
			}
		}

		$atts_md5 =  md5( serialize( $atts ) );
		set_transient( 'gmm' . $atts_md5, $map_data, 20 );

		$src_args = array(
			'geo_mashup_content' => 'render-map',
			'map_data_key' => $atts_md5,
		);

		if ( !empty( $atts['lang'] ) )
			$src_args['lang'] = $atts['lang'];

		if ( isset( $atts['object_ids'] ) and strlen( $atts['object_ids'] ) > 1800 ) {
			// Try to shorten the URL a bit
			if ( !class_exists( 'GM_Int_list' ) )
				include GEO_MASHUP_DIR_PATH . '/gm-int-list.php';
			$id_list = new GM_Int_List( $atts['object_ids'] );
			$atts['oids'] = $id_list->compressed();
			unset( $atts['object_ids'] );
		}

		$iframe_src = self::build_home_url( $src_args + $atts );

		$content = "";

		if ($click_to_load == 'true') {
			if ( is_feed() ) {
				$content .= "<a href=\"{$iframe_src}\">$click_to_load_text</a>";
			} else {
				self::$add_loader_script = true;
				$style = "height: {$height_style}; width: {$width_style}; background-color: #ddd;".
					"background-image: url(".GEO_MASHUP_URL_PATH."/images/wp-gm-pale.png);".
					"background-repeat: no-repeat;background-position:center; cursor: pointer;";
				$content = "<div class=\"gm-map\" style=\"$style\" " .
					"onclick=\"GeoMashupLoader.addMapFrame(this,'$iframe_src','{$height_style}','{$width_style}','{$map_data['name']}')\">";
				if ( $static ) {
					// TODO: test whether click to load really works with a static map
					$content .= $map_image . '</div>';
				} else {
					$content .= "<p style=\"text-align:center;\">$click_to_load_text</p></div>";
				}
			}
		} else if ( $static ) {
			$content = "<div class=\"gm-map\">$map_image</div>";
		} else {
			$content =  "<div class=\"gm-map\"><iframe name=\"{$map_data['name']}\" src=\"{$iframe_src}\" " .
				"style=\"height: $height_style; width: $width_style; border: none; overflow: hidden;\"></iframe></div>";
		}
		$map_number++;
		echo "<script>";
		echo "jQuery( document ).ready(function() {";
		echo "jQuery('.gm-map' ).find('iframe').attr('title', 'Mapa de centros');";
		echo "});";
		echo "</script>";
		return apply_filters( 'geo_mashup_map_content', $content, $map_data );

	}
private static function augment_map_object_location( $object_name, $object_location ) {
		global $geo_mashup_options;

		$term_ids_by_taxonomy = array();
		$author_name = '';
		if ( 'post' == $object_name ) {

			// Filter the title
			$object_location->label = sanitize_text_field( apply_filters( 'the_title', $object_location->label, $object_location->object_id ) );

			// Add terms
			if ( defined( 'GEO_MASHUP_DISABLE_CATEGORIES' ) and GEO_MASHUP_DISABLE_CATEGORIES ) 
				$include_taxonomies = array();
			else
				$include_taxonomies = $geo_mashup_options->get( 'overall', 'include_taxonomies' );
			
			foreach( $include_taxonomies as $include_taxonomy ) {
				$term_ids_by_taxonomy[$include_taxonomy] = array();
				// Not using wp_get_object_terms(), which doesn't allow for persistent caching
				$tax_terms = get_the_terms( $object_location->object_id, $include_taxonomy );
				if ( $tax_terms ) {
					// terms are sometimes indexed in order, sometimes by id, so wp_list_pluck() doesn't work
					foreach ( $tax_terms as $term ) {
						$term_ids_by_taxonomy[$include_taxonomy][] = $term->term_id;
					}
				}
			}

			// Add post author name
			if ( defined( 'GEO_MASHUP_DISABLE_AUTHOR_NAME' ) and GEO_MASHUP_DISABLE_AUTHOR_NAME ) 
				$author = null;
			else
				$author = get_userdata( $object_location->post_author );

			if ( empty( $author ) ) 
				$author_name = '';
			else 
				$author_name = $author->display_name;
		}

		$augmented_object = array(
			'object_name' => $object_name,
			'object_id' => $object_location->object_id,
			// We should be able to use real UTF-8 characters in titles
			// Helps with the spelling-out of entities in tooltips
			'title' => html_entity_decode( $object_location->label, ENT_COMPAT, 'UTF-8' ),
			'lat' => $object_location->lat,
			'lng' => $object_location->lng,
			'author_name' => $author_name,
			'terms' => $term_ids_by_taxonomy,
		);

		// Allow companion plugins to add data with legacy filter name
		return apply_filters( 'geo_mashup_locations_json_object', $augmented_object, $object_location );
	}
public static function build_map_data( $query ) {
		global $geo_mashup_options, $geo_mashup_custom;
		$defaults = array(
			'map_api' => $geo_mashup_options->get( 'overall', 'map_api' )
		);
		$query = wp_parse_args( $query, $defaults );
		$object_id = isset( $query['object_id'] ) ? $query['object_id'] : 0;
		unset( $query['object_id'] );

		$map_data = $query + array(
			'ajaxurl' => admin_url( 'admin-ajax.php' ),
			'siteurl' => home_url( '/' ), // qTranslate doesn't work with get_option( 'home' )
			'url_path' => GEO_MASHUP_URL_PATH,
			'template_url_path' => get_stylesheet_directory_uri()
		);
		if ( isset( $geo_mashup_custom ) ) {
			$map_data['custom_url_path'] = $geo_mashup_custom->url_path;
		}

		$map_content = ( isset( $query['map_content'] ) ) ? $query['map_content'] : null;
		$object_name = ( isset( $query['object_name'] ) ) ? $query['object_name'] : 'post';

		if ( $map_content == 'single') {

			$object_location = MyGeoMashupDBext::get_object_location( $object_name, $object_id );
			if ( !empty( $object_location ) ) {
				$augmented_location = self::augment_map_object_location( $object_name, $object_location );
				$map_data['object_data'] = array( 'objects' => array( $augmented_location ) );
			}

			$options = $geo_mashup_options->get( 'single_map' );
			$map_data = array_merge ( $options, $map_data );

			if ( 'post' == $object_name ) {
				$kml_urls = self::get_kml_attachment_urls( $object_id );
				if (count($kml_urls)>0) {
					$map_data['load_kml'] = array_pop( $kml_urls );
				}
			}

		} else { // $map_content != 'single'

			$map_data['context_object_id'] = $object_id;

			if ( $map_content == 'contextual' ) {

				$options = $geo_mashup_options->get( 'context_map' );
				// If desired we could make these real options
				$options['auto_info_open'] = 'false';

			} else { // $map_content == 'global'

				$options = $geo_mashup_options->get( 'global_map' );

				// Term options handled during render
				unset( $options['term_options'] );

				if ( empty( $query['show_future'] ) )
					$query['show_future'] = $options['show_future'];

				if ( is_null( $map_content ) ) 
					$options['map_content'] = 'global';

			}

			// Determine which taxonomies to include, if any
			if ( ( defined( 'GEO_MASHUP_DISABLE_CATEGORIES' ) and GEO_MASHUP_DISABLE_CATEGORIES ) )
				$options['include_taxonomies'] = array();
			else
				$options['include_taxonomies'] = $geo_mashup_options->get( 'overall', 'include_taxonomies' );

			if ( isset( $options['add_google_bar'] ) and 'true' == $options['add_google_bar'] ) {
				$options['adsense_code'] = $geo_mashup_options->get( 'overall', 'adsense_code' );
			}

			// We have a lot map control parameters that don't effect the locations query,
			// but only the relevant ones are used
			$map_data['object_data'] = self::get_locations_json( $query, ARRAY_A );

			// Incorporate parameters from the query and options
			$map_data = array_merge( $query, $map_data );
			$map_data = array_merge( $options, $map_data );

		} // $map_content != 'single'

		return $map_data;
	}
	public static function get_locations_json( $query_args, $format = 'JSON' ) {
		$default_args = array( 'object_name' => 'post' );
		$query_args = wp_parse_args( $query_args, $default_args );
		$json_objects = array();
		$objects = MyGeoMashupDBext::get_object_locations( $query_args );
		if ( $objects ) {
			foreach ($objects as $object) {
				$json_objects[] = self::augment_map_object_location( $query_args['object_name'], $object );
			}
		}
		if ( ARRAY_A == $format ) 
			return array( 'objects' => $json_objects );
		else
			return json_encode( array( 'objects' => $json_objects ) );
	}

}
?>

Una vez tengamos los archivos creados, hay que llamarlos desde functions.php.
En mi caso los he colocado en la carpeta /inc/classes de mi tema activo.
Cambiaréis la ruta /inc/classes con la de la ubicación de vuestros archivos en el caso fuera diferente.
En functions.php copiamos las siguientes líneas

 /**new classes for map compatibility with WPML. Change /inc/classes/ with the path of your new files */
    require_once(STYLESHEETPATH . '/inc/classes/Class-MyNewSitepress.php');
    require_once(STYLESHEETPATH . '/inc/classes/Class-MyGeoMashupDBext.php');
    require_once(STYLESHEETPATH . '/inc/classes/Class-GeoMashupINA.php');

Ahora, solo falta llamar el mapa en el template que deseamos. Lo llamaremos con php utilizando la nueva clase que hemos creado de la siguiente manera

<?php echo GeoMashupINA::map(); ?>

Tamnién se puede crear el shortcode, si fuera necesario llamarlo desde el editor.

Y esto es todo.
En mi instalación ha funcionado.

Es la primera vez que utilizo WPML y todavía no lo he configurado del todo.
Espero no hayan más sorpresa :-P

Tuneando el plugin ‘Users Submitted Post’ de WordPress para custom post type y custom taxonomy

El plugin ‘Users Submitted Post’ permite que los usuarios puedan publicar posts en nuestra web desde el front end y nos da la posibilidad de configurar varias opciones (moderación, campos etc). Aquí más información sobre este fantástico plugin.

Par poder utilizar este plugin con Custom post type y custom taxonomy no encontré otra opción que retocar el código, lo que no es la mejor manera si en el futuro tenemos que actualizar el plugin. Pero de momento es la solución más rápida que encontré.

Para esto tendremos que editar 2 archivos del mismo plugin.

1-wp-content/plugins/user-submitted-posts/user-submitted-posts.php en la línea 251

$postData = array();
$postData['post_title']   = $title;
$postData['post_content'] = $content;
$postData['post_status']  = 'pending';
$postData['post_author']  = $authorID;
//Add here the custom post type name you want to save the post as
//Añade aquí el tipo de post
$postData['post_type']  = 'My_custom_post_type'';
$numberApproved           = $usp_options['number-approved'];

Dónde sustituiremos My_custom_post_typepor el nombre que hemos asignado al custom post type que hemos creado previamente.

Si además hemos creado custom taxonomies, tendremos que cambiar la función que viene con el submit post del plugin, que está escrita para guardar las categorías pero no las custom taxonomies.
Para esto, en el mismo archivo cambiaremos la línea 278

wp_set_post_categories($newPost, array($category));

por lo siguiente

wp_set_object_terms($newPost, array($category), 'My_cutom_taxonomy');

Dónde sustituiremos My_cutom_taxonomy por el nombre que hemos asignado a las categorías personalizadas.

Para que nos aparezcan estas categorías en las opciones generales del ‘general form options’ del plugin y poder de esta manera asignar una custom category por defecto, a la hora de crear una nueva entrada, cambiaremos las siguientes líneas (725 del mismo archivo)

											<?php $categories = get_categories(array('hide_empty'=> 0)); ?>
											<?php foreach($categories as $category) { ?>
											
											<div class="mm-radio-inputs">
												<label class="description">
													<input <?php checked(true, in_array($category->term_id, $usp_options['categories'])); ?> type="checkbox" name="usp_options[categories][]" value="<?php echo $category->term_id; ?>" /> 
													<span><?php echo htmlentities($category->name); ?></span>
												</label>
											</div>
											
											<?php } ?>

por estas

											<?php $categories = get_terms('My_cutom_taxonomy',array('hide_empty'=> 0)); ?>
											<?php foreach($categories as $category) { ?>
											
											<div class="mm-radio-inputs">
												<label class="description">
													<input <?php checked(true, in_array($category->term_id, $usp_options['categories'])); ?> type="checkbox" name="usp_options[categories][]" value="<?php echo $category->term_id; ?>" /> 
													<span><?php echo htmlentities($category->name); ?></span>
												</label>
											</div>
											
											<?php } ?>

Dónde otra vez sustituiremos My_cutom_taxonomy por el nombre que hemos asignado a las categorías personalizadas.

Ahora hemos que hacer aparecer nuestras custom taxonomies en el dropdown del form, en lugar de las categorías de los posts de wordpress. El plugin viene con dos tipos de form, el clasic y el html5. Según cual usemos abriremos y editaremos el archivo correspondiente (o ambos por si no hemos decidido todavía). en este caso editaremos el archivo wp-content/plugins/user-submitted-posts/views/submission-form.php, que corresponde al HTML5 form.
Buscamos este código (está por la línea 54)

		<fieldset class="usp-category">
			<label for="user-submitted-category"><?php _e('Post Category'); ?></label>
			<select name="user-submitted-category">
				<?php foreach($usp_options['categories'] as $categoryId) { $category = get_category($categoryId); if(!$category) { continue; } ?>
				<option value="<?php echo $categoryId; ?>"><?php $category = get_category($categoryId); echo htmlentities($category->name); ?></option>
				<?php } ?>
			</select>
		</fieldset>

Y lo sostituimos por lo siguiente

		<fieldset class="usp-category">
<?php
function get_terms_dropdown($taxonomies, $args){
    $myterms = get_terms($taxonomies, $args);
    $output ="<select name='user-submitted-category' id='user-submitted-category' class='usp_select'>";
    $output .="<option value='#'>Please select a business category</option>";
    foreach($myterms as $term){
        $term_name =$term->name;
        $term_id =$term->term_id;
        $output .="<option class='usp_option' value='".$term_id."'>".$term_name."</option>";
    }
    $output .="</select>";
return $output;
}
$taxonomies = array('My-custom-tazonomy);
$args = array('orderby'=>'name','hide_empty'=>true);
$select = get_terms_dropdown($taxonomies, $args);
 
$select = preg_replace("#<select([^>]*)>#", "<select$1>", $select);
echo $select;?>
		</fieldset>

Otra vez cambiaremos My-custom-taxonomy por nuestra categoría