Skip to content

Instantly share code, notes, and snippets.

@mfields
Created January 8, 2011 01:11
Show Gist options
  • Save mfields/770404 to your computer and use it in GitHub Desktop.
Save mfields/770404 to your computer and use it in GitHub Desktop.
WordPress Taxonomy Map Plugin
<?php
/*
Plugin Name: Taxonomy Map
Plugin URI: http://wordpress.mfields.org/plugins/taxonomy-images/
Description: Use a hierarchical taxonomy system to display Goole map.
Version: 0.1
Author: Michael Fields
Author URI: http://wordpress.mfields.org/
License: GPLv2
Copyright 2010 Michael Fields michael@mfields.org
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as published by
the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
define( 'TAXONOMY_MAP_URI', plugin_dir_url( __FILE__ ) );
define( 'TAXONOMY_MAP_VERSION', '0.1' );
define( 'TAXONOMY_MAP_TAXONOMY', 'location' );
$taxonomy_map = array();
/**
* Default settings.
* @global array $taxonomy_map_settings_default
* @see http://code.google.com/apis/maps/documentation/javascript/reference.html#MapOptions
* @since 2010-09-10
*/
$taxonomy_map_settings_default = array(
'zoom' => 17, /* int */
'scrollwheel' => false, /* bool */
);
function taxonomy_map_get( $key ) {
global $taxonomy_map;
if( isset( $taxonomy_map[$key] ) ) {
return $taxonomy_map[$key];
}
return null;
}
function taxonomy_map_set( $key, $value ) {
global $taxonomy_map;
$taxonomy_map[$key] = $value;
}
function taxonomy_map_get_setting( $key ) {
global $taxonomy_map_settings_default;
if( isset( $taxonomy_map_settings_default[$key] ) ) {
return $taxonomy_map_settings_default[$key];
}
return null;
}
$taxonomy_map_metabox = new Taxonomy_Checklist( TAXONOMY_MAP_TAXONOMY );
add_action( 'init', 'taxonomy_map_register_taxonomy' );
add_action( 'wp_head', 'taxonomy_map_print_meta_tags' );
add_filter( 'script_loader_src', 'taxonomy_map_filter_google_map_api_uri' );
add_action( 'wp_print_scripts', 'taxonomy_map_js' );
add_action( 'get_header', 'taxonomy_map_set_location' );
add_filter( 'the_content', 'taxonomy_map_append_map_to_content' );
if( !function_exists( 'pr' ) ) {
function pr( $var ) {
print '<pre>' . print_r( $var, true ) . '</pre>';
}
}
if( !function_exists( 'taxonomy_map_has_location' ) ) {
/**
* Should a map be generated for the current view?
* @uses $taxonomy_map
* @since 2010-07-02
* @return bool true if view is a single resource that has a latitude and longitude; false if not.
*/
function taxonomy_map_has_location() {
if( is_single() && null !== taxonomy_map_get( 'lat' ) && null !== taxonomy_map_get( 'lng' ) ) {
return true;
}
return false;
}
}
if( !function_exists( 'taxonomy_map_register_taxonomy' ) ) {
function taxonomy_map_register_taxonomy() {
/**
* Registers "Locations" taxonomy
* @since 2010-07-02
* @alter 2010-09-10
* @todo Check to see if taxonomy already exists before registering.
* @todo Provide a way for users to change the name + labels.
*/
register_taxonomy( TAXONOMY_MAP_TAXONOMY, 'post', array(
'hierarchical' => true,
'label' => 'Locations',
'singular' => 'Location',
# 'update_count_callback' => $tax['update_count_callback'],
) );
}
}
if( !function_exists( 'taxonomy_map_js' ) ) {
/**
* Required scripts.
* @uses $taxonomy_map
* @uses TAXONOMY_MAP_URI
* @uses TAXONOMY_MAP_VERSION
* @return void
* @since 2010-09-09
* @alter 2010-09-09
*/
function taxonomy_map_js() {
if( taxonomy_map_has_location() ) {
wp_enqueue_script( 'taxonomy-map-api', 'http://maps.google.com/maps/api/js', array(), TAXONOMY_MAP_VERSION );
wp_enqueue_script( 'taxonomy-map', TAXONOMY_MAP_URI . '/taxonomy-map.js', array( 'taxonomy-map-api' ), TAXONOMY_MAP_VERSION );
global $taxonomy_map;
wp_localize_script( 'taxonomy-map', 'taxonomyMapPlugin', array (
'location' => taxonomy_map_get( 'location' ),
'lat' => taxonomy_map_get( 'lat' ),
'lng' => taxonomy_map_get( 'lng' ),
'zoom' => taxonomy_map_get_setting( 'zoom' ),
'scrollwheel' => taxonomy_map_get_setting( 'scrollwheel' ),
) );
}
}
}
if( !function_exists( 'taxonomy_map_filter_google_map_api_uri' ) ) {
/**
* Add sensor parameter to the url string for Google Maps URI.
* @param string
* @return string
* @since 2010-09-09
* @alter 2010-09-09
*/
function taxonomy_map_filter_google_map_api_uri( $url ) {
if ( false === strpos( $url, 'http://maps.google.com/maps/api/js' ) ) {
return $url;
}
list( $url ) = explode( '?', $url );
return $url . '?sensor=false';
}
}
if( !function_exists( 'taxonomy_map_print_meta_tags' ) ) {
/**
* Add sensor parameter to the url string for Google Maps URI.
* @uses taxonomy_map_has_location()
* @return void
* @since 2010-09-09
* @alter 2010-09-09
* @todo Remove CSS.
*/
function taxonomy_map_print_meta_tags() {
if( taxonomy_map_has_location() ) {
print '<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />';
print '<style type="text/css">#map_canvas { width:660px; height:450px; }</style>';
}
}
}
if( !function_exists( 'taxonomy_map_find_country' ) ) {
function taxonomy_map_find_country( $locations ) {
$o = array();
foreach( $locations as $location => $values ) {
$values = get_object_vars( $values );
if( $values['parent'] == '0' ) {
$o = array(
'id' => $values['term_id'],
'name' => $values['name']
);
}
}
return $o;
}
}
if( !function_exists( 'taxonomy_map_find_child' ) ) {
function taxonomy_map_find_child( $locations, $parent ) {
$o = array();
foreach( $locations as $location => $values ) {
$values = get_object_vars( $values );
if( $values['parent'] == $parent['id'] ) {
$o = array(
'id' => $values['term_id'],
'name' => $values['name']
);
}
}
return $o;
}
}
if( !function_exists( 'taxonomy_map_append_map_to_content' ) ) {
/**
* Appends a map to the_content on single templates
* where the queried object is associated with a 'location'.
* @uses taxonomy_map_has_location()
* @return string
* @since 2010-07-02
* @alter 2010-09-09
*/
function taxonomy_map_append_map_to_content( $content ) {
if( taxonomy_map_has_location() ) {
global $post;
$terms = wp_get_object_terms( (int) $post->ID, TAXONOMY_MAP_TAXONOMY );
# pr( $terms );
# $uri = get_term_link( , TAXONOMY_MAP_TAXONOMY );
return $content . "\n" . '<div id="map_canvas"></div>';
}
return $content;
}
}
// FIX THIS STUFF BELOW!!!!
if( !function_exists( 'taxonomy_map_google_map_geocoding_request_url' ) ) {
/**
* Generate a url to a Google's geocoding service.
* @param array
* @return string
* @since 2010-07-02
* @alter 2010-09-09
*/
function taxonomy_map_google_map_geocoding_request_url( $args ) {
$url = 'http://maps.google.com/maps/api/geocode/json';
$defaults = array( 'sensor' => 'false', 'filter' => 'display' );
$query = '';
$count = 1;
$args = array_merge( $defaults, $args );
$amp = ( $args['filter'] === 'display' ) ? '&amp;' : '&';
foreach( $args as $key => $value ) {
$key = urlencode( $key );
$value = urlencode( $value );
$query.= ( $count === 1 ) ? '?' : $amp;
$query.= $key . '=' . $value;
$count++;
}
if( !empty( $query ) ) {
return $url . $query;
}
return '';
}
}
if( !function_exists( 'taxonomy_map_get_location_coords' ) ) {
function taxonomy_map_get_location_coords( $location_name ) {
global $taxonomy_map;
$options = get_option( 'taxonomy_map_coords' );
if( !empty( $location_name ) ) {
$taxonomy_map['location']['name'] = $location_name;
/* Look in setttings. */
if( is_array( $options ) ) {
$key = sanitize_title_with_dashes( $location_name );
if( array_key_exists( $key, $options ) ) {
return $options[$key];
}
}
/* Get coords from Google */
$url = taxonomy_map_google_map_geocoding_request_url( array(
'address' => $taxonomy_map['location']['name'],
'filter' => 'entity'
) );
$file = file_get_contents( $url );
if( $file !== false )
$json = taxonomy_map_google_map_geocoding_parse_json( $file );
if( is_array( $json ) ) {
$key = sanitize_title_with_dashes( $location_name );
$options[$key] = $json;
update_option( 'taxonomy_map_coords', $options );
return $json;
}
}
return array();
}
}
if( !function_exists( 'taxonomy_map_set_location' ) ) {
function taxonomy_map_set_location() {
global $post;
$location_name = taxonomy_map_get_location_name( $post );
if( !empty( $location_name ) ) {
taxonomy_map_set( 'location', $location_name );
$options = get_option( 'taxonomy_map_coords' );
/* Look in setttings. */
if( is_array( $options ) ) {
$key = sanitize_title_with_dashes( $location_name );
if( array_key_exists( $key, $options ) ) {
taxonomy_map_set( 'lat', $options[$key][0] );
taxonomy_map_set( 'lng', $options[$key][1] );
return;
}
}
$url = taxonomy_map_google_map_geocoding_request_url( array(
'address' => taxonomy_map_get( 'location' ),
'filter' => 'entity'
) );
$file = file_get_contents( $url );
if( $file !== false ) {
$json = taxonomy_map_google_map_geocoding_parse_json( $file );
}
if( is_array( $json ) ) {
$key = sanitize_title_with_dashes( $location_name );
$options[$key] = $json;
update_option( 'taxonomy_map_coords', $options );
taxonomy_map_set( 'lat', $json[0]);
taxonomy_map_set( 'lng', $json[1] );
}
}
}
}
if( !function_exists( 'taxonomy_map_google_map_geocoding_parse_json' ) ) {
function taxonomy_map_google_map_geocoding_parse_json( $file ) {
$responses = array(
'OK', /* At least one geocode was returned. */
'ZERO_RESULTS', /* Geocode was successful but returned no results. */
'OVER_QUERY_LIMIT', /* Over quota. */
'REQUEST_DENIED', /* Request was denied, generally because of lack of a sensor parameter. */
'INVALID_REQUEST' /* Generally indicates that the query (address or latlng) is missing. */
);
$defaults = array( 'status' => null, 'results' => array() );
$json = json_decode( $file, true );
if( !is_array( $json ) ) {
return false;
}
$json = array_merge( $defaults, $json );
if( $json['status'] !== $responses[0] ) {
return false;
}
if( empty( $json['results'] ) ) {
return false;
}
return array(
$json['results'][0]['geometry']['location']['lat'],
$json['results'][0]['geometry']['location']['lng']
);
}
}
/**
* Force a taxonomy meta box to retain term hierarchy.
* Derived from: http://scribu.net/wordpress/category-checklist-tree
* @author Michael Fields http://wordpress.mfields.org/
* @author Scribu http://scribu.net
*
* @since 2009-11-01
* @alter 2010-09-10
*
* 2010-09-09
* - Changed name of class.
* - Added $taxonomy_slug property.
* - Obsesive compulsive syntax modifications.
* - Allowed class to be used for any registered taxonomy.
* - Replaced meta_box() with code post_categories_meta_box() from WordPress v3.0.1.
*/
class Taxonomy_Checklist {
public $taxonomy_slug = null;
public function __construct( $taxonomy_slug = 'category' ) {
$this->taxonomy_slug = $taxonomy_slug;
add_action( '_admin_menu', array( $this, 'get_taxonomy' ), 100 );
}
public function get_taxonomy() {
$taxonomy = get_taxonomy( $this->taxonomy_slug );
if( $taxonomy ) {
$this->taxonomy = $taxonomy;
add_action( 'admin_menu', array( $this, 'replace_box' ), 100 );
}
}
public function replace_box() {
$div = $this->taxonomy->name . 'div';
remove_meta_box( $div, 'post', 'normal' );
add_meta_box( $div, __( 'Location' ), array( $this, 'meta_box' ), 'post', 'side', 'high' );
}
public function meta_box( $post ) {
$tax = $this->taxonomy;
$taxonomy = $this->taxonomy_slug;
?>
<div id="taxonomy-<?php echo $taxonomy; ?>" class="categorydiv">
<ul id="<?php echo $taxonomy; ?>-tabs" class="category-tabs">
<li class="tabs"><a href="#<?php echo $taxonomy; ?>-all" tabindex="3"><?php echo $tax->labels->all_items; ?></a></li>
<li class="hide-if-no-js"><a href="#<?php echo $taxonomy; ?>-pop" tabindex="3"><?php _e( 'Most Used' ); ?></a></li>
</ul>
<div id="<?php echo $taxonomy; ?>-pop" class="tabs-panel" style="display: none;">
<ul id="<?php echo $taxonomy; ?>checklist-pop" class="categorychecklist form-no-clear" >
<?php $popular_ids = wp_popular_terms_checklist($taxonomy); ?>
</ul>
</div>
<div id="<?php echo $taxonomy; ?>-all" class="tabs-panel">
<?php
$name = ( $taxonomy == 'category' ) ? 'post_category' : 'tax_input[' . $taxonomy . ']';
echo "<input type='hidden' name='{$name}[]' value='0' />"; // Allows for an empty term set to be sent. 0 is an invalid Term ID and will be ignored by empty() checks.
?>
<ul id="<?php echo $taxonomy; ?>checklist" class="list:<?php echo $taxonomy?> categorychecklist form-no-clear">
<?php
wp_terms_checklist($post->ID, array(
'taxonomy' => $taxonomy,
'popular_cats' => $popular_ids,
'checked_ontop' => false,
)
); ?>
</ul>
</div>
<?php if ( !current_user_can($tax->cap->assign_terms) ) : ?>
<p><em><?php _e('You cannot modify this taxonomy.'); ?></em></p>
<?php endif; ?>
<?php if ( current_user_can($tax->cap->edit_terms) ) : ?>
<div id="<?php echo $taxonomy; ?>-adder" class="wp-hidden-children">
<h4>
<a id="<?php echo $taxonomy; ?>-add-toggle" href="#<?php echo $taxonomy; ?>-add" class="hide-if-no-js" tabindex="3">
<?php
/* translators: %s: add new taxonomy label */
printf( __( '+ %s' ), $tax->labels->add_new_item );
?>
</a>
</h4>
<p id="<?php echo $taxonomy; ?>-add" class="category-add wp-hidden-child">
<label class="screen-reader-text" for="new<?php echo $taxonomy; ?>"><?php echo $tax->labels->add_new_item; ?></label>
<input type="text" name="new<?php echo $taxonomy; ?>" id="new<?php echo $taxonomy; ?>" class="form-required form-input-tip" value="<?php echo esc_attr( $tax->labels->new_item_name ); ?>" tabindex="3" aria-required="true"/>
<label class="screen-reader-text" for="new<?php echo $taxonomy; ?>_parent">
<?php echo $tax->labels->parent_item_colon; ?>
</label>
<?php wp_dropdown_categories( array( 'taxonomy' => $taxonomy, 'hide_empty' => 0, 'name' => 'new'.$taxonomy.'_parent', 'orderby' => 'name', 'hierarchical' => 1, 'show_option_none' => '&mdash; ' . $tax->labels->parent_item . ' &mdash;', 'tab_index' => 3 ) ); ?>
<input type="button" id="<?php echo $taxonomy; ?>-add-submit" class="add:<?php echo $taxonomy ?>checklist:<?php echo $taxonomy ?>-add button category-add-sumbit" value="<?php echo esc_attr( $tax->labels->add_new_item ); ?>" tabindex="3" />
<?php wp_nonce_field( 'add-'.$taxonomy, '_ajax_nonce-add-'.$taxonomy, false ); ?>
<span id="<?php echo $taxonomy; ?>-ajax-response"></span>
</p>
</div>
<?php endif; ?>
</div>
<?php
}
}
if( !function_exists( 'taxonomy_map_get_location_name' ) ) {
/**
*
* @uses TAXONOMY_MAP_TAXONOMY
* @uses taxonomy_map_get_term_parents()
* return mixed string location on siccess false on failure.
* @since 2010-07-02
* @since 2010-09-10
* @todo add_support for multiple locations.
*/
function taxonomy_map_get_location_name( $post ) {
$locations = get_the_terms( $post->ID, TAXONOMY_MAP_TAXONOMY );
$locations = array_values( (array) $locations ); /* Rey key the array */
if( isset( $locations[0]->term_id ) ) {
return taxonomy_map_get_term_parents( (int) $locations[0]->term_id );
}
return false;
}
}
if( !function_exists( 'taxonomy_map_get_term_parents' ) ) {
/**
* Reverse the output of _taxonomy_map_get_term_parents().
* @uses _taxonomy_map_get_term_parents()
* @since 2010-09-10
* @since 2010-09-10
*/
function taxonomy_map_get_term_parents( $id, $sep = ', ' ) {
$parents = _taxonomy_map_get_term_parents( $id, $sep );
$parents = explode( $sep, trim( $parents, $sep ) );
$parents = array_reverse( $parents );
return implode( $sep, $parents );
}
}
if( !function_exists( '_taxonomy_map_get_term_parents' ) ) {
/**
* @since 2010-09-10
* @since 2010-09-10
*/
function _taxonomy_map_get_term_parents( $id, $sep = ', ', $visited = array() ) {
$chain = '';
$parent = get_term( $id, TAXONOMY_MAP_TAXONOMY );
if ( is_wp_error( $parent ) ) {
return $parent;
}
if ( $parent->parent && ( $parent->parent != $parent->term_id ) && !in_array( $parent->parent, $visited ) ) {
$visited[] = $parent->parent;
$chain .= _taxonomy_map_get_term_parents( $parent->parent, $sep, $visited ) . $sep;
}
$chain .= $parent->name;
return $chain;
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment