Source for file geo-mashup-ui-managers.php
Documentation is available at geo-mashup-ui-managers.php
* Geo Mashup "core" implementation of location management user interfaces.
* Theoretically, everything done here could be done in a separate plugin.
* A base class for managing user interfaces for collecting and storing location.
* This could be extended to make the existing editor work for new objects in a separate plugin.
* Retrieve a single instaniated subclass by name.
* @param string $name The class name of the manager.
* @return GeoMashupUIManager The singleton object.
static $instances = array();
if ( ! isset ( $instances[$name] ) ) {
$instances[$name] = new $name();
return $instances[$name];
* Queue UI styles to match the jQuery version.
GeoMashup::register_style( 'jquery-smoothness', 'css/jquery-ui.1.7.smoothness.css', false, GEO_MASHUP_VERSION, 'screen' );
wp_enqueue_style( 'jquery-smoothness' );
* Queue styles and scripts for the location editor form.
GeoMashup::register_style( 'geo-mashup-edit-form', 'css/location-editor.css', false, GEO_MASHUP_VERSION, 'screen' );
wp_enqueue_style( 'geo-mashup-edit-form' );
$map_api = $geo_mashup_options->get( 'overall', 'map_api' );
$geonames_username = $geo_mashup_options->get( 'overall', 'geonames_username' );
$ajax_nonce = wp_create_nonce('geo-mashup-ajax-edit');
$ajax_url = admin_url( 'admin-ajax.php' );
$geo_mashup_url_path = GEO_MASHUP_URL_PATH;
wp_localize_script( 'mxn-core', 'geo_mashup_location_editor_settings', compact( 'map_api', 'ajax_url', 'geo_mashup_url_path', 'geonames_username' ) );
$required_scripts = array( 'jquery');
if ( 'google' == $map_api ) {
wp_register_script( 'google-maps-2', 'http://maps.google.com/maps?file=api&v=2&sensor=false&key=' .
GeoMashup::register_script( 'mxn-google-2', 'js/mxn/mxn.google.core.js', array( 'mxn-core', 'google-maps-2' ), GEO_MASHUP_VERSION );
GeoMashup::register_script( 'mxn-google-2-gm', 'js/mxn/mxn.google.geo-mashup.js', array( 'mxn-google-2' ), GEO_MASHUP_VERSION );
$required_scripts[] = 'mxn-google-2-gm';
} else if ( 'googlev3' == $map_api ) {
wp_register_script( 'google-maps-3', 'http://maps.google.com/maps/api/js?sensor=false&language=' . GeoMashup::get_language_code() );
GeoMashup::register_script( 'mxn-google-3', 'js/mxn/mxn.googlev3.core.js', array( 'mxn-core', 'google-maps-3' ), GEO_MASHUP_VERSION );
GeoMashup::register_script( 'mxn-google-3-gm', 'js/mxn/mxn.googlev3.geo-mashup.js', array( 'mxn-google-3' ), GEO_MASHUP_VERSION );
$required_scripts[] = 'mxn-google-3-gm';
} else if ( 'openlayers' == $map_api ) {
wp_register_script( 'openlayers', 'http://openlayers.org/api/OpenLayers.js', null, 'latest' );
wp_register_script( 'openstreetmap', 'http://www.openstreetmap.org/openlayers/OpenStreetMap.js', array( 'openlayers' ), 'latest' );
GeoMashup::register_script( 'mxn-openlayers', 'js/mxn/mxn.openlayers.core.js', array( 'mxn-core', 'openstreetmap' ), GEO_MASHUP_VERSION );
GeoMashup::register_script( 'mxn-openlayers-gm', 'js/mxn/mxn.openlayers.geo-mashup.js', array( 'mxn-openlayers' ), GEO_MASHUP_VERSION );
$required_scripts[] = 'mxn-openlayers-gm';
GeoMashup::register_script( 'geo-mashup-location-editor', 'js/location-editor.js', $required_scripts, GEO_MASHUP_VERSION );
wp_enqueue_script( 'geo-mashup-location-editor' );
GeoMashup::register_script( 'jquery-ui-datepicker', 'js/jquery-ui.1.7.3.datepicker.js', array( 'jquery', 'jquery-ui-core'), '1.7.3' );
wp_enqueue_script( 'jquery-ui-datepicker' );
if ( isset ( $geo_mashup_custom ) ) {
$custom_url = $geo_mashup_custom->file_url( 'location-editor.js' );
if ( ! empty( $custom_url ) ) {
wp_enqueue_script( 'geo-mashup-location-editor-custom', $custom_url, array( 'geo-mashup-location-editor' ) );
* Determine the appropriate action from posted data.
private function get_submit_action() {
if ( isset ( $_POST['geo_mashup_add_location'] ) or isset ( $_POST['geo_mashup_update_location'] ) ) {
// Clients without javascript may need server side geocoding
if ( ! empty( $_POST['geo_mashup_search'] ) and isset ( $_POST['geo_mashup_no_js'] ) and 'true' == $_POST['geo_mashup_no_js'] ) {
} else if ( isset ( $_POST['geo_mashup_changed'] ) and 'true' == $_POST['geo_mashup_changed'] and ! empty( $_POST['geo_mashup_location'] ) ) {
// The geo mashup submit button wasn't used, but a change was made and the post saved
} else if ( isset ( $_POST['geo_mashup_delete_location'] ) ) {
} else if ( ! empty( $_POST['geo_mashup_location_id'] ) and empty( $_POST['geo_mashup_location'] ) ) {
// There was a location, but it was cleared before this save
* Save an object location from data posted by the location editor.
* @uses GeoMashupDB::set_object_location()
* @uses GeoMashupDB::delete_location()
* @param string $object_name The name of the object being edited.
* @param string $object_id The ID of the object being edited.
* @return bool|WP_ErrorTrue or a WordPress error.
if ( empty( $_POST['geo_mashup_nonce'] ) || !wp_verify_nonce( $_POST['geo_mashup_nonce'], 'geo-mashup-edit' ) ) {
return new WP_Error( 'invalid_request', __( 'Object location not saved - invalid request.', 'GeoMashup' ) );
$action = $this->get_submit_action();
if ( 'save' == $action or 'geocode' == $action ) {
$date_string = $_POST['geo_mashup_date'] . ' ' . $_POST['geo_mashup_hour'] . ':' .
$_POST['geo_mashup_minute'] . ':00';
$post_location = array();
// If PHP has added slashes, WP will do it again before saving
$post_location['saved_name'] = stripslashes( $_POST['geo_mashup_location_name'] );
if ( 'geocode' == $action ) {
$post_location = array();
if ( ! empty( $_POST['geo_mashup_select'] ) ) {
$selected_items = explode( '|', $_POST['geo_mashup_select'] );
$post_location = intval( $selected_items[0] );
$post_location['id'] = $_POST['geo_mashup_location_id'];
list ( $lat, $lng ) = split( ',', $_POST['geo_mashup_location'] );
$post_location['lat'] = trim( $lat );
$post_location['lng'] = trim( $lng );
$post_location['geoname'] = $_POST['geo_mashup_geoname'];
$post_location['address'] = stripslashes( $_POST['geo_mashup_address'] );
$post_location['postal_code'] = $_POST['geo_mashup_postal_code'];
$post_location['country_code'] = $_POST['geo_mashup_country_code'];
$post_location['admin_code'] = $_POST['geo_mashup_admin_code'];
$post_location['sub_admin_code'] = $_POST['geo_mashup_sub_admin_code'];
$post_location['locality_name'] = $_POST['geo_mashup_locality_name'];
if ( ! empty( $post_location ) ) {
if ( is_wp_error( $error ) )
} else if ( 'delete' == $action ) {
if ( is_wp_error( $error ) )
// If geodata was manually updated but Geo Mashup location was not,
// they may be out of sync now. Allowing that for now.
* A manager for user location user interfaces.
* Singleton instantiated immediately.
* Get the single instance of this class.
* @uses parent::get_instance()
* @return GeoMashupPostUIManager The instance.
// Global $geo_mashup_options is available, but a better pattern might
// be to wait until init to be sure
add_action( 'init', array( &$this, 'init' ) );
* Initialize for use in relevant requests.
* init {@link http://codex.wordpress.org/Plugin_API/Action_Reference action}
* @global array $geo_mashup_options
* @global string $pagenow The WordPress-supplied requested filename.
* @uses apply_filters geo_mashup_load_user_editor Returns a boolean that loads the editor when true.
// Enable this interface when the option is set and we're on a destination page
$geo_mashup_options->get( 'overall', 'located_object_name', 'user' ) == 'true' &&
preg_match( '/(user-edit|user-new|profile).php/', $pagenow );
$enabled = apply_filters( 'geo_mashup_load_user_editor', $enabled );
// If enabled, register all the interface elements
add_action( 'show_user_profile', array( &$this, 'print_form' ) );
add_action( 'edit_user_profile', array( &$this, 'print_form' ) );
// MAYBEDO: add location to registration page?
add_action( 'personal_options_update', array( &$this, 'save_user'));
add_action( 'edit_user_profile_update', array( &$this, 'save_user'));
* Print the user location editor form.
include_once( GEO_MASHUP_DIR_PATH . '/edit-form.php');
if ( isset ( $_GET['user_id'] ) ) {
$object_id = $_GET['user_id'];
echo '<h3>' . __( 'Location', 'GeoMashup' ) . '</h3>';
* Save a posted user location.
* @uses parent::save_posted_object_location()
* When a user is saved, also save any posted location.
* save_user {@link http://codex.wordpress.org/Plugin_API/Action_Reference action}
if ( empty( $_POST['user_id'] ) ) {
$user_id = $_POST['user_id'];
if ( !current_user_can( 'edit_user', $user_id ) ) {
* A manager for post/page location user interfaces.
* Singleton instantiated immediately.
* Location found in geo_mashup_save_location shortcode.
private $inline_location;
* Get the single instance of this class.
* @uses parent::get_instance()
* @return GeoMashupPostUIManager The instance.
// Global $geo_mashup_options is available, but a better pattern might
// be to wait until init to be sure
add_action( 'init', array( &$this, 'init' ) );
* Initialize for use in relevant post editing requests.
* init {@link http://codex.wordpress.org/Plugin_API/Action_Reference action}
* @global array $geo_mashup_options
* @global string $pagenow The WordPress-supplied requested filename.
* @uses apply_filters geo_mashup_load_location_editor Returns a boolean that loads the editor when true.
// Uploadable geo content type expansion always enabled
add_filter( 'upload_mimes', array( &$this, 'upload_mimes' ) );
// Queue inline location handlers - these could be used in nearly any request
// Pre-save filter checks saved content for inline location tags
add_filter( 'content_save_pre', array( &$this, 'content_save_pre') );
// Save post handles both inline and form processing
add_action( 'save_post', array( &$this, 'save_post'), 10, 2 );
// Browser upload processing
add_filter( 'wp_handle_upload', array( &$this, 'wp_handle_upload' ) );
// Enable front or back end ajax edits
add_action( 'wp_ajax_nopriv_geo_mashup_edit', array( 'GeoMashup', 'ajax_edit' ) );
add_action( 'wp_ajax_geo_mashup_edit', array( 'GeoMashup', 'ajax_edit' ) );
add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
// Queue scripts later, when we can determine post type, front or back end
add_action( 'admin_enqueue_scripts', array( &$this, 'enqueue_scripts' ) );
add_action( 'wp_enqueue_scripts', array( &$this, 'enqueue_scripts' ) );
if ( 'async-upload.php' === $pagenow ) {
add_filter( 'media_meta', array( &$this, 'media_meta' ), 10, 2 );
} else if ( 'upload.php' === $pagenow or 'media-upload.php' === $pagenow ) {
// Browser upload display
add_action( 'admin_print_scripts', array( &$this, 'admin_print_scripts' ) );
* Queue scripts if the post type is enabled.
* Monitor for checking post type: http://core.trac.wordpress.org/ticket/14886
* @uses apply_filters geo_mashup_load_location_editor intended for enabling a front end interface
* @global array $geo_mashup_options
* @global string $pagenow
// The location editor works only on posts
$load_location_editor = (
preg_match( '/(post|page)(-new|).php/', $pagenow ) and
in_array( $post->post_type, $geo_mashup_options->get( 'overall', 'located_post_types' ) )
$load_location_editor = apply_filters( 'geo_mashup_load_location_editor', $load_location_editor );
// If we're on a post editing page, queue up the form interface elements
if ( $load_location_editor ) {
* Add a location meta box to the post editors.
* admin_menu {@link http://codex.wordpress.org/Plugin_API/Action_Reference action}
// Not adding a menu, but at this stage add_meta_box is defined, so we can add the location form
foreach ( $geo_mashup_options->get( 'overall', 'located_post_types' ) as $post_type ) {
add_meta_box( 'geo_mashup_post_edit', __( 'Location', 'GeoMashup' ), array( &$this, 'print_form' ), $post_type, 'advanced' );
* Print the post editor form.
include_once( GEO_MASHUP_DIR_PATH . '/edit-form.php');
* Save a posted post or page location.
* @uses parent::save_posted_object_location()
* When a post is saved, save any posted location for it.
* save_post {@link http://codex.wordpress.org/Plugin_API/Action_Reference action}
* @uses GeoMashupDB::set_object_location()
if ( 'revision' == $post->post_type ) {
// WP has already saved the post - allow location saving without added capability checks
if ( !empty( $this->inline_location ) ) {
if ( isset ( $this->inline_location['geo_date'] ) ) {
$geo_date = $this->inline_location['geo_date'];
unset ( $this->inline_location['geo_date'] );
if ( is_wp_error( $location_id ) ) {
update_post_meta( $post_id, 'geo_mashup_save_location_error', $location_id->get_error_message() );
$this->inline_location = null;
delete_transient( 'gm_uploaded_kml_url' );
* Extract inline save location shortcodes from post content before it is saved.
* content_save_pre {@link http://codex.wordpress.org/Plugin_API/Filter_Reference filter}
// Piggyback on the shortcode interface to find inline tags [geo_mashup_save_location ...]
add_shortcode( 'geo_mashup_save_location', 'is_null' );
$pattern = get_shortcode_regex( );
return preg_replace_callback('/'. $pattern. '/s', array( &$this, 'replace_save_pre_shortcode' ), $content);
* Store the inline location from a save location shortcode before it is removed.
* @param array $shortcode_match
* @return The matched content, or an empty string if it was a save location shortcode.
$content = $shortcode_match[0];
$tag_index = array_search( 'geo_mashup_save_location', $shortcode_match );
if ( $tag_index !== false ) {
// There is an inline location - save the attributes
$this->inline_location = shortcode_parse_atts( stripslashes( $shortcode_match[$tag_index+ 1] ) );
// If lat and lng are missing, try to geocode based on address
if ( ( empty( $this->inline_location['lat'] ) or empty( $this->inline_location['lng'] ) ) and !empty( $this->inline_location['address'] ) ) {
$query = $this->inline_location['address'];
$message = ( is_wp_error( GeoMashupDB::$geocode_error ) ? GeoMashupDB::$geocode_error->get_error_message() : __( 'Address not found - try making it less detailed', 'GeoMashup' ) );
$content = str_replace( ']', ' geocoding_error="' . $message . '"]', $content );
$this->inline_location = null;
* Add Flash-uploaded KML to the location editor map.
* media_meta {@link http://codex.wordpress.org/Plugin_API/Filter_Reference filter}
// Only chance to run some javascript after a flash upload?
if (strlen($post->guid) > 0) {
$content .= '<script type="text/javascript"> ' .
'if (\'GeoMashupLocationEditor\' in parent) parent.GeoMashupLocationEditor.loadKml(\''. $post->guid. '\');' .
* Add Browser-uploaded KML to the location editor map.
* admin_print_scripts {@link http://codex.wordpress.org/Plugin_API/Action_Reference action}
// Load any uploaded KML into the search map - only works with browser uploader
// See if wp_upload_handler found uploaded KML
$kml_url = get_transient( 'gm_uploaded_kml_url' );
// Load the KML in the location editor
<script type="text/javascript">
if (\'GeoMashupLocationEditor\' in parent) parent.GeoMashupLocationEditor.loadKml(\'' . $kml_url . '\');
delete_transient( 'gm_uploaded_kml_url' );
* Add geo mime types to allowable uploads.
* upload_mimes {@link http://codex.wordpress.org/Plugin_API/Filter_Reference filter}
$mimes['kml'] = 'application/vnd.google-earth.kml+xml';
$mimes['kmz'] = 'application/vnd.google-earth.kmz';
$mimes['gpx'] = 'application/octet-stream';
* If an upload is KML, put the URL in an option to be loaded in the response
* wp_handle_upload {@link http://codex.wordpress.org/Plugin_API/Filter_Reference filter}
// TODO: use transient API instead of option
delete_transient( 'gm_uploaded_kml_url' );
if ( is_array( $args ) && isset ( $args['file'] ) ) {
if ( stripos( $args['file'], '.km' ) == strlen( $args['file'] ) - 4 ) {
set_transient( 'gm_uploaded_kml_url', $args['url'] );
* A manager for comment location user interfaces.
* Singleton instantiated immediately.
* Whether to put the comment form script in the footer.
private $add_form_script = false;
* Get the single instance of this class.
* @return GeoMashupPostUIManager The instance.
if ( is_null( $instance ) ) {
$instance = new GeoMashupCommentUIManager();
// Global $geo_mashup_options is available, but a better pattern might
// be to wait until init to be sure
add_action( 'init', array( &$this, 'init' ) );
* Initialize for use in relevant requests.
* init {@link http://codex.wordpress.org/Plugin_API/Action_Reference action}
* @global array $geo_mashup_options
* @uses apply_filters geo_mashup_load_comment_editor Returns a boolean that loads the editor when true.
$load_comment_editor = ( !is_admin() && $geo_mashup_options->get( 'overall', 'located_object_name', 'comment' ) == 'true' );
$load_comment_editor = apply_filters( 'geo_mashup_load_comment_editor', $load_comment_editor );
// If enabled, register all the interface elements
if ( $load_comment_editor ) {
add_action( 'comment_form', array( &$this, 'print_form' ) );
add_action( 'wp_footer', array( &$this, 'wp_footer' ) );
add_action( 'comment_post', array( &$this, 'save_comment'), 10, 2 );
wp_enqueue_script( 'geo-mashup-loader' );
* Print the comment location editor form.
$this->add_form_script = true;
// If there's a logged in user with a location, use that as a default.
// The client-side location will override it if available
$user = wp_get_current_user();
if ( !$default_location )
$default_summary = ( empty( $default_location->locality_name ) ? '' : $default_location->locality_name . ', ' ) .
( empty( $default_location->admin_code ) ? '' : $default_location->admin_code );
printf( '<label id="geo-mashup-summary-label" for="geo-mashup-summary-input" style="display:none;">%s</label>', __( 'Written from (location)', 'GeoMashup' ) );
printf( '<input id="geo-mashup-summary-input" style="display:none;" type="text" size="25" value="%s" />', $default_summary );
printf( '<img id="geo-mashup-busy-icon" style="display:none;" src="%s" alt="%s" />', path_join( GEO_MASHUP_URL_PATH, 'images/busy_icon.gif' ), __( 'Loading...', 'GeoMashup' ) );
$input_format = '<input id="geo-mashup-%s-input" name="comment_location[%s]" type="hidden" value="%s" />';
printf( $input_format, 'lat', 'lat', $default_location->lat );
printf( $input_format, 'lng', 'lng', $default_location->lng );
* Print the form script in the footer if it's needed.
if ( $this->add_form_script ) {
GeoMashup::register_script( 'geo-mashup-comment-form', 'js/comment-form.js', array( 'jquery' ), GEO_MASHUP_VERSION, true );
wp_localize_script( 'geo-mashup-comment-form', 'geo_mashup_comment_form_settings', array( 'geonames_username' => $geo_mashup_options->get( 'overall', 'geonames_username' ) ) );
wp_print_scripts( 'geo-mashup-comment-form' );
* When a comment is saved, save any posted location with it.
* save_comment {@link http://codex.wordpress.org/Plugin_API/Filter_Reference filter}
* @uses GeoMashupDB::set_object_location()
public function save_comment( $comment_id = 0, $approval = '' ) {
if ( !$comment_id || 'spam' === $approval || empty( $_POST['comment_location'] ) || !is_array( $_POST['comment_location'] ) ) {
|