GeoMashup
[ class tree: GeoMashup ] [ index: GeoMashup ] [ all elements ]

Source for file geo-mashup.php

Documentation is available at geo-mashup.php

  1. <?php 
  2. /*
  3. Plugin Name: Geo Mashup
  4. Plugin URI: http://code.google.com/p/wordpress-geo-mashup/ 
  5. Description: Save location for posts and pages, or even users and comments. Display these locations on Google maps. Make WordPress into your GeoCMS.
  6. Version: 1.4beta5
  7. Author: Dylan Kuhn
  8. Author URI: http://www.cyberhobo.net/
  9. Minimum WordPress Version Required: 3.0
  10. License: GPL2+
  11. */
  12.  
  13. /*  Copyright 2011  Dylan Kuhn  (email : cyberhobo@cyberhobo.net)
  14.  
  15.     This program is free software; you can redistribute it and/or modify
  16.     it under the terms of the GNU General Public License, version 2 or later, as
  17.     published by the Free Software Foundation.
  18.  
  19.     This program is distributed in the hope that it will be useful,
  20.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  21.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22.     GNU General Public License for more details.
  23.  
  24.     You should have received a copy of the GNU General Public License
  25.     along with this program; if not, write to the Free Software
  26.     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  27. */
  28.  
  29. /**
  30.  * The main Geo Mashup plugin file loaded by WordPress.
  31.  *
  32.  * @package GeoMashup
  33.  */
  34.  
  35. if !class_exists'GeoMashup' ) ) {
  36. /**
  37.  * The Geo Mashup static class.
  38.  *
  39.  * Used primarily for namespace, with methods called using the scope operator,
  40.  * like echo GeoMashup::map();
  41.  *
  42.  * @package GeoMashup
  43.  * @since 1.0
  44.  * @access public
  45.  * @static
  46.  */
  47. class GeoMashup {
  48.     /**
  49.      * Whether to add the click-to-load map script.
  50.      *
  51.      * @since 1.4
  52.      */
  53.     private static $add_loader_script false;
  54.  
  55.     /**
  56.      * Load Geo Mashup.
  57.      * 
  58.      * Initializations that can be done before init().
  59.      *
  60.      * @since 1.2
  61.      */
  62.     public static function load({
  63.         GeoMashup::load_constants();
  64.         load_plugin_textdomain'GeoMashup'''path_joinGEO_MASHUP_DIRECTORY'lang' ) );
  65.  
  66.         GeoMashup::load_dependencies();
  67.         GeoMashup::load_hooks();
  68.     }
  69.  
  70.     /**
  71.      *    Test to see if the current request is for the Geo Mashup options page.
  72.      *
  73.      * @since 1.4
  74.      *
  75.      * @return bool Whether this is a an options page request.
  76.      */
  77.     public static function is_options_page({
  78.         // We may need this before $pagenow is set, but maybe this method won't always work?
  79.         return is_admin(and isset($_GET['page']and GEO_MASHUP_PLUGIN_NAME === $_GET['page');
  80.     }
  81.  
  82.     /**
  83.      * WordPress init action.
  84.      *
  85.      * init {@link http://codex.wordpress.org/Plugin_API/Action_Reference#Advanced_Actions action},
  86.      * called by WordPress.
  87.      *
  88.      * @since 1.2
  89.      */
  90.     public static function init({
  91.         GeoMashup::load_styles();
  92.         GeoMashup::load_scripts();
  93.     }
  94.  
  95.     /**
  96.      * Load relevant dependencies.
  97.      * 
  98.      * @since 1.2
  99.      */
  100.     private static function load_dependencies({
  101.         include_onceGEO_MASHUP_DIR_PATH '/geo-mashup-options.php' );
  102.         include_onceGEO_MASHUP_DIR_PATH '/geo-mashup-db.php' );
  103.         include_onceGEO_MASHUP_DIR_PATH '/geo-mashup-ui-managers.php' );
  104.     if !is_admin() ) {
  105.             include_onceGEO_MASHUP_DIR_PATH '/shortcodes.php');
  106.         }
  107.     }
  108.  
  109.     /**
  110.      * Load relevant hooks.
  111.      * 
  112.      * @since 1.2
  113.      */
  114.     private static function load_hooks({
  115.         global $geo_mashup_options;
  116.  
  117.         add_action'init'array__CLASS__'init' ) );
  118.  
  119.         add_action'plugins_loaded'array__CLASS__'dependent_init' )-);
  120.         add_action'wp_ajax_geo_mashup_query'array__CLASS__'geo_query') );
  121.         add_action'wp_ajax_nopriv_geo_mashup_query'array__CLASS__'geo_query') );
  122.         add_action'wp_ajax_geo_mashup_kml_attachments'array__CLASS__'ajax_kml_attachments') );
  123.         add_action'wp_ajax_nopriv_geo_mashup_kml_attachments'array__CLASS__'ajax_kml_attachments') );
  124.         add_action'wp_ajax_geo_mashup_suggest_custom_keys'array'GeoMashupDB''post_meta_key_suggest' ) );
  125.  
  126.         if (is_admin()) {
  127.  
  128.             register_activation_hook__FILE__array__CLASS__'activation_hook' ) );
  129.  
  130.             // To add Geo Mashup settings page
  131.             add_action('admin_menu'array(__CLASS__'admin_menu'));
  132.  
  133.             // To make important announcements
  134.             add_action'admin_notices'array__CLASS__'admin_notices' ) );
  135.  
  136.             // To add plugin listing links
  137.             add_filter'plugin_action_links'array__CLASS__'plugin_action_links' )10);
  138.             add_filter'plugin_row_meta'array__CLASS__'plugin_row_meta' )10);
  139.  
  140.         else {
  141.  
  142.             // This is a non-admin request
  143.  
  144.             if ($geo_mashup_options->get('overall','add_category_links'== 'true'{
  145.                 // To add map links to a category list - flaky, requires non-empty category description
  146.                 add_filter('list_cats'array(__CLASS__'list_cats')102);
  147.             }
  148.  
  149.             // To output location meta tags in the page head
  150.             add_action('wp_head'array(__CLASS__'wp_head'));
  151.  
  152.             // To add footer output (like scripts)
  153.             add_action'wp_footer'array__CLASS__'wp_footer' ) );
  154.  
  155.             // To allow shortcodes in the text widget
  156.             if has_filter'widget_text''do_shortcode' ) ) {
  157.                 add_filter'widget_text''do_shortcode'11 );
  158.             }
  159.  
  160.             // To add the GeoRSS namespace to feeds (not available for RSS 0.92)
  161.             add_action('rss2_ns'array(__CLASS__'rss_ns'));
  162.             add_action('atom_ns'array(__CLASS__'rss_ns'));
  163.  
  164.             // To add GeoRSS location to feeds
  165.             add_action('rss2_item'array(__CLASS__'rss_item'));
  166.             add_action('atom_entry'array(__CLASS__'rss_item'));
  167.  
  168.             // To add custom renderings
  169.             add_filter'query_vars'array__CLASS__'query_vars' ) );
  170.             add_action'template_redirect'array__CLASS__'template_redirect' ) );
  171.  
  172.         }
  173.     }
  174.  
  175.     /**
  176.      * Define Geo Mashup constants.
  177.      * 
  178.      * @since 1.2
  179.      */
  180.     private static function load_constants({
  181.         define('GEO_MASHUP_PLUGIN_NAME'plugin_basename(__FILE__));
  182.         define('GEO_MASHUP_DIR_PATH'dirname__FILE__ ));
  183.         define('GEO_MASHUP_DIRECTORY'dirnameGEO_MASHUP_PLUGIN_NAME ) );
  184.         define('GEO_MASHUP_URL_PATH'trimplugin_dir_url__FILE__ )'/' ) );
  185.         define('GEO_MASHUP_MAX_ZOOM'20);
  186.         // Make numeric versions: -.02 for alpha, -.01 for beta
  187.         define('GEO_MASHUP_VERSION''1.3.99.5');
  188.         define('GEO_MASHUP_DB_VERSION''1.3');
  189.     }
  190.  
  191.     /**
  192.      * Load relevant scripts.
  193.      * 
  194.      * @since 1.2
  195.      */
  196.     private static function load_scripts({
  197.         if self::is_options_page() )
  198.             wp_enqueue_script'jquery-ui-tabs' );
  199.     }
  200.  
  201.     /**
  202.      * Load relevant styles.
  203.      * 
  204.      * @since 1.2
  205.      */
  206.     private static function load_styles({
  207.         if self::is_options_page() ) {
  208.             self::register_style'jquery-smoothness''css/jquery-ui.1.7.smoothness.css'array()GEO_MASHUP_VERSION'screen' );
  209.             wp_enqueue_style'jquery-smoothness' );
  210.             wp_enqueue_script'suggest' );
  211.         }
  212.     }
  213.  
  214.     /**
  215.      * WordPress hook to perform activation tasks.
  216.      * 
  217.      * @since 1.4
  218.      */
  219.     public static function activation_hook({
  220.         global $geo_mashup_options;
  221.         GeoMashupDB::install();
  222.         if '' == $geo_mashup_options->get'overall''version' and '' != $geo_mashup_options->get'overall''google_key' ) ) {
  223.             // Upgrading from a pre-1.4 version - don't set the default provider to Google v3
  224.             $geo_mashup_options->set_valid_options(
  225.                 array(
  226.                     'overall' => array(
  227.                         'map_api' => 'google',
  228.                         'version' => GEO_MASHUP_VERSION
  229.                     )
  230.                 )
  231.             );
  232.             $geo_mashup_options->save();
  233.         }
  234.     }
  235.  
  236.     /**
  237.      * WordPress action to supply an init action for plugins that would like to use Geo Mashup APIs.
  238.      * 
  239.      * @since 1.4
  240.      * @uses do_action() geo_mashup_init Fired when Geo Mashup is loaded and ready.
  241.      */
  242.     public static function dependent_init({
  243.         do_action'geo_mashup_init' );
  244.     }
  245.  
  246.     /**
  247.      * Register the Geo Mashup script appropriate for the request.
  248.      *
  249.      * @since 1.4
  250.      * 
  251.      * @param string $handle Global tag for the script.
  252.      * @param string $src Path to the script from the root directory of Geo Mashup.
  253.      * @param array $deps Array of dependency handles.
  254.      * @param string $ver Script version.
  255.      * @param bool $in_footer Whether the script can be loaded in the footer.
  256.      */
  257.     public static function register_script$handle$src$deps array()$ver false$in_footer false {
  258.         // Use the .dev version if SCRIPT_DEBUG is set or there is no minified version
  259.         if ( ( defined'SCRIPT_DEBUG' and SCRIPT_DEBUG or !is_readablepath_joinGEO_MASHUP_DIR_PATH$src ) ) )
  260.             $src preg_replace'/(\.\w*)$/''.dev$1'$src );
  261.         wp_register_script$handleplugins_url$src__FILE__ )$deps$ver$in_footer );
  262.     }
  263.  
  264.     /**
  265.      * Register the Geo Mashup style appropriate for the request.
  266.      *
  267.      * @since 1.4
  268.      *
  269.      * @param string $handle Global tag for the style.
  270.      * @param string $src Path to the stylesheet from the root directory of Geo Mashup.
  271.      * @param array $deps Array of dependency handles.
  272.      * @param string $ver Script version.
  273.      * @param bool $media Stylesheet media target.
  274.      */
  275.     public static function register_style$handle$src$deps array()$ver false$media 'all' {
  276.         // Use the .dev version if SCRIPT_DEBUG is set or there is no minified version
  277.         if ( ( defined'SCRIPT_DEBUG' and SCRIPT_DEBUG or !is_readablepath_joinGEO_MASHUP_DIR_PATH$src ) ) )
  278.             $src preg_replace'/(\.\w*)$/''.dev$1'$src );
  279.  
  280.         wp_register_style$handleplugins_url$src__FILE__ )$deps$ver$media );
  281.     }
  282.  
  283.     /**
  284.      * WordPress action to add things like scripts to the footer.
  285.      * 
  286.      * @since 1.4
  287.      */
  288.     public static function wp_footer({
  289.         if self::$add_loader_script {
  290.             self::register_script'geo-mashup-loader''js/loader.js'array()GEO_MASHUP_VERSIONtrue );
  291.             wp_print_scripts'geo-mashup-loader' );
  292.         }
  293.     }
  294.  
  295.     /**
  296.      * WordPress filter to add Geo Mashup query variables.
  297.      *
  298.      * @since 1.3
  299.      */
  300.     public static function query_vars$public_query_vars {
  301.         $public_query_vars['geo_mashup_content';
  302.         return $public_query_vars;
  303.     }
  304.  
  305.     /**
  306.      *    Locate a Geo Mashup template.
  307.      * 
  308.      * Geo Mashup looks for templates given a certain base name. Given a base
  309.      * name of 'info-window', it will return the first of:
  310.      *     'geo-mashup-info-window.php' in the active theme directory
  311.      *     'info-window.php' in the geo-mashup-custom plugin directory
  312.      *     'default-templates/info-window.php' in the geo-mashup plugin directory
  313.      *
  314.      * @since 1.4
  315.      * 
  316.      * @param string $template_base The base name of the template.
  317.      * @return string The file path of the template found.
  318.      */
  319.     public static function locate_template$template_base {
  320.         global $geo_mashup_custom;
  321.         $template locate_templatearray("geo-mashup-$template_base.php") );
  322.         if empty$template and isset$geo_mashup_custom and $geo_mashup_custom->file_url$template_base '.php' ) ) {
  323.             $template path_join$geo_mashup_custom->dir_path$template_base '.php' );
  324.         }
  325.         if empty$template or !is_readable$template ) ) {
  326.             $template path_joinGEO_MASHUP_DIR_PATH"default-templates/$template_base.php);
  327.         }
  328.         if empty$template or !is_readable$template ) ) {
  329.             // If all else fails, just use the default info window template
  330.             $template path_joinGEO_MASHUP_DIR_PATH'default-templates/info-window.php' );
  331.         }
  332.         return $template;
  333.     }
  334.  
  335.     /**
  336.      * WordPress action to deliver templated Geo Mashup content.
  337.      *
  338.      * @since 1.3
  339.      *
  340.      * @uses geo_query
  341.      * @uses render_map
  342.      */
  343.     public static function template_redirect({
  344.         $geo_mashup_content get_query_var'geo_mashup_content' );
  345.         if empty$geo_mashup_content ) ) {
  346.  
  347.             // The parameter's purpose is to get us here, we can remove it now
  348.             unset$_GET['geo_mashup_content');
  349.  
  350.             // Call the function corresponding to the content request
  351.             // This provides some security, as only implemented methods will be executed
  352.             $method str_replace'-''_'$geo_mashup_content );
  353.             call_user_funcarray__CLASS__$method ) );
  354.             exit();
  355.         }
  356.     }
  357.  
  358.     /**
  359.      * Process an AJAX geo query.
  360.      *
  361.      * @since 1.3
  362.      * @uses geo-query.php
  363.      */
  364.     public static function geo_query({
  365.         require_once'geo-query.php' );
  366.         exit();
  367.     }
  368.  
  369.     /**
  370.      * Process an iframe map request.
  371.      *
  372.      * @since 1.3
  373.      * @uses render-map.php
  374.      */
  375.     private static function render_map({
  376.         require_once'render-map.php' );
  377.         GeoMashupRenderMap::render_map();
  378.         exit();
  379.     }
  380.  
  381.     /**
  382.      * WordPress action to perform an ajax edit operation and echo results.
  383.      *
  384.      * @since 1.3
  385.      */
  386.     public static function ajax_edit({
  387.         check_ajax_referer'geo-mashup-edit''geo_mashup_nonce' );
  388.         unset$_GET['_wpnonce');
  389.  
  390.         $status array'request' => 'ajax-edit''code' => 200 );
  391.         if isset$_POST['geo_mashup_object_id') ) {
  392.             $status['object_id'$_POST['geo_mashup_object_id'];
  393.         else {
  394.             $status['code'400;
  395.             $status['message'__'No object id posted.''GeoMashup' );
  396.             $status['object_id''?';
  397.         }
  398.  
  399.         /** @todo add an option for a user capability check here? */
  400.  
  401.         if 200 == $status['code'and empty$_POST['geo_mashup_ui_manager') ) {
  402.             $ui_manager GeoMashupUIManager::get_instance$_POST['geo_mashup_ui_manager');
  403.             $result $ui_manager->save_posted_object_location$status['object_id');
  404.             if is_wp_error$result ) ) {
  405.                 $status['code'500;
  406.                 $status['message'$result->get_error_message();
  407.             }
  408.         }
  409.  
  410.         if 200 == $status['code'{
  411.             if empty$_REQUEST['geo_mashup_update_location') ) {
  412.                 $status['message'__'Location updated.''GeoMashup' );
  413.             else if empty$_REQUEST['geo_mashup_delete_location') ) {
  414.                 $status['message'__'Location deleted.''GeoMashup' );
  415.             else if empty$_REQUEST['geo_mashup_add_location') ) {
  416.                 $status['message'__'Location added.''GeoMashup' );
  417.             }
  418.         
  419.  
  420.         echo json_encodearray'status' => $status ) );
  421.         exit();
  422.     }
  423.  
  424.     /**
  425.      * Toggle limiting of query_posts to located posts only,
  426.      * with Geo Mashup query extensions.
  427.      *
  428.      * When enabled, only posts with locations will be returned from
  429.      * WordPress query_posts() and related functions. Also adds Geo Mashup
  430.      * public query variables.
  431.      *
  432.      * Caution - what if a future Geo Mashup incorporates multiple locations per object?
  433.      *
  434.      * @since 1.3
  435.      *
  436.      * @param bool $yes_or_no Whether to activate the join or not.
  437.      */
  438.     public static function join_post_queries$yes_or_no {
  439.         GeoMashupDB::join_post_queries$yes_or_no );
  440.     }
  441.  
  442.     /**
  443.      * Helper to turn a string of key-value pairs into an associative array.
  444.      *
  445.      * @since 1.0
  446.      *
  447.      * @param string $glue1 Pair separator.
  448.      * @param string $glue2 Key/value separator.
  449.      * @param string $str String to explode.
  450.      * @return array The associative array.
  451.      */
  452.     public static function explode_assoc($glue1$glue2$str{
  453.         $array2=explode($glue2$str);
  454.         foreach($array2 as  $val{
  455.             $pos=strpos($val,$glue1);
  456.             $key=substr($val,0,$pos);
  457.             $array3[$key=substr($val,$pos+1,strlen($val));
  458.         }
  459.         return $array3;
  460.     }
  461.  
  462.     /**
  463.      * Helper to turn an associative array into a string of key-value pairs.
  464.      * 
  465.      * @since 1.0
  466.      *
  467.      * @param string $inner_glue Key/value separator.
  468.      * @param string $outer_glue Pair separator.
  469.      * @param array $array Array to implode.
  470.      * @param mixed $skip_empty Whether to include empty values in output.
  471.      * @param mixed $urlencoded Whetern to URL encode the output.
  472.      * @return string The imploded string.
  473.      */
  474.     public static function implode_assoc($inner_glue$outer_glue$array$skip_empty=false$urlencoded=false{
  475.     $output array();
  476.         foreach($array as $key=>$item{
  477.             if (!$skip_empty || isset($item)) {
  478.                 if ($urlencoded)
  479.                     $output[preg_replace('/\s/'' '$key.$inner_glue.urlencode($item));
  480.                 else
  481.                     $output[preg_replace('/\s/'' '$key.$inner_glue.$item);
  482.             }
  483.         }
  484.         return implode($outer_glue$output);
  485.     }
  486.  
  487.     /**
  488.      * Guess the best language code for the current context.
  489.      * 
  490.      * Takes some plugins and common practices into account.
  491.      * 
  492.      * @since 1.4
  493.      * 
  494.      * @return string Language code.
  495.      */
  496.     public static function get_language_code({
  497.         $language_code '';
  498.         if isset$_GET['lang') ) {
  499.             // A language override technique is to use this querystring parameter
  500.             $language_code $_GET['lang'];
  501.         else if function_exists'qtrans_getLanguage' ) ) {
  502.             // qTranslate integration
  503.             $language_code qtrans_getLanguage();
  504.         else if defined'ICL_LANGUAGE_CODE' ) ) {
  505.             // WPML integration
  506.             $language_code ICL_LANGUAGE_CODE;
  507.         else {
  508.             $language_code get_locale();
  509.         }
  510.         return $language_code;
  511.     }
  512.  
  513.     /**
  514.      * Get an array of URLs of KML or KMZ attachments for a post.
  515.      * 
  516.      * @since 1.1
  517.      *
  518.      * @param id $post_id 
  519.      * @return array Array of URL strings.
  520.      */
  521.     public static function get_kml_attachment_urls($post_id{
  522.         if empty$post_id ) ) {
  523.             return array();
  524.         }
  525.         $args array(
  526.             'post_type' => 'attachment',
  527.             'numberposts' => null,
  528.             'post_status' => null,
  529.             'post_mime_type' => array(
  530.                 'application/vnd.google-earth.kml+xml',
  531.                 'application/vnd.google-earth.kmz',
  532.                 'application/octet-stream'
  533.             ),
  534.             'post_parent' => $post_id
  535.             )
  536.         $attachments get_posts($args);
  537.         $urls array();
  538.         if ($attachments{
  539.             foreach ($attachments as $attachment{
  540.                 $url wp_get_attachment_url$attachment->ID )
  541.                 // Backwards compatibility: include KML attachments with the incorrect octet-stream mime type
  542.                 if 'application/octet-stream' != $attachment->post_mime_type or 'kml' == substr$url-) ) {
  543.                     array_push$urls$url );
  544.                 }
  545.             }
  546.         }
  547.         return $urls;
  548.     }
  549.  
  550.     /**
  551.      * Echo a JSONP array of URLs of KML or KMZ attachments for posts.
  552.      *
  553.      * since 1.4
  554.      */
  555.     public static function ajax_kml_attachments({
  556.         $urls array()
  557.         if !empty$_REQUEST['post_ids') ) {
  558.             $post_ids array_map'intval'explode','$_REQUEST['post_ids') );
  559.             foreach$post_ids as $post_id {
  560.                 $urls array_merge$urlsself::get_kml_attachment_urls$post_id ) );
  561.             }
  562.         }
  563.         $json json_encode$urls );
  564.         if isset$_REQUEST['callback') )
  565.             $json $_REQUEST['callback''(' $json ')';
  566.         echo $json;
  567.         exit();
  568.     }
  569.  
  570. /**
  571.  * WordPress action to add relevant geo meta tags to the document head.
  572.  *
  573.  * wp_head {@link http://codex.wordpress.org/Plugin_API/Action_Reference#TemplateActions action},
  574.  * called by WordPress.
  575.  *
  576.  * @since 1.0
  577.  */
  578. public static function wp_head({
  579.     global $wp_query;
  580.  
  581.     if (is_single())
  582.     {
  583.         $loc GeoMashupDB::get_object_location'post'$wp_query->post->ID );
  584.         if (!empty($loc)) {
  585.             $title esc_html(convert_chars(strip_tags(get_bloginfo('name'))." - ".$wp_query->post->post_title));
  586.             echo '<meta name="ICBM" content="' esc_attr$loc->lat ', ' $loc->lng '" />' "\n";
  587.             echo '<meta name="DC.title" content="' esc_attr$title '" />' "\n";
  588.             echo '<meta name="geo.position" content="' .  esc_attr$loc->lat ';' $loc->lng '" />' "\n";
  589.         }
  590.     }
  591. }
  592.  
  593. /**
  594.  * Query object locations and return JSON.
  595.  *
  596.  * Offers customization per object location via a filter, geo_mashup_locations_json_object.
  597.  *
  598.      * @since 1.2
  599.      * @uses GeoMashupDB::get_object_locations()
  600.      * @uses apply_filters() the_title Filter post titles.
  601.      * @uses apply_filters() geo_mashup_locations_json_object Filter each location associative array before conversion to JSON.
  602.      *
  603.      * @param string|array$query_args Query variables for GeoMashupDB::get_object_locations().
  604.      * @param string $format (optional) 'JSON' (default) or ARRAY_A
  605.      * @return string Queried object locations JSON ( { "object" : [...] } ).
  606.      */
  607.     public static function get_locations_json$query_args$format 'JSON' {
  608.         $default_args array'object_name' => 'post' );
  609.         $query_args wp_parse_args$query_args$default_args );
  610.         $json_objects array();
  611.         $objects GeoMashupDB::get_object_locations$query_args );
  612.         if $objects {
  613.             foreach ($objects as $object{
  614.                 $category_ids array();
  615.                 $author_name '';
  616.                 $attachments array();
  617.                 if 'post' == $query_args['object_name'{
  618.  
  619.                     // Filter the title
  620.                     $object->label sanitize_text_fieldapply_filters'the_title'$object->label$object->object_id ) );
  621.  
  622.                     // Only know about post categories now, but could abstract to objects
  623.                     if !defined'GEO_MASHUP_DISABLE_CATEGORIES' ) )
  624.                         $category_ids wp_get_object_terms$object->object_id'category'array'fields' => 'ids' ) );
  625.  
  626.                     // Include post author
  627.                     $author get_userdata$object->post_author );
  628.                     if empty$author ) ) {
  629.                         $author_name '';
  630.                     else {
  631.                         $author_name $author->display_name;
  632.                     }
  633.                 }
  634.  
  635.                 $json_object array(
  636.                     'object_name' => $query_args['object_name'],
  637.                     'object_id' => $object->object_id,
  638.                     // We should be able to use real UTF-8 characters in titles
  639.                     // Helps with the spelling-out of entities in tooltips
  640.                     'title' => html_entity_decode$object->labelENT_COMPAT'UTF-8' ),
  641.                     'lat' => $object->lat,
  642.                     'lng' => $object->lng,
  643.                     'author_name' => $author_name,
  644.                     'categories' => $category_ids
  645.                 );
  646.  
  647.                 // Allow companion plugins to add data
  648.                 $json_object apply_filters'geo_mashup_locations_json_object'$json_object$object );
  649.                 $json_objects[$json_object;
  650.             }
  651.         }
  652.         if ARRAY_A == $format 
  653.             return array'objects' => $json_objects );
  654.         else
  655.             return json_encodearray'objects' => $json_objects ) );
  656.     }
  657.  
  658.     /**
  659.      * Convert depricated attribute names.
  660.      *
  661.      * @since 1.3
  662.      * 
  663.      * @param array $atts Attributes to modify.
  664.      */
  665.     private static function convert_map_attributes&$atts {
  666.         $attribute_conversions array
  667.             'auto_open_info_window' => 'auto_info_open',
  668.             'open_post_id' => 'open_object_id'
  669.         );
  670.         foreach $attribute_conversions as $old_key => $new_key {
  671.             if isset$atts[$old_key) ) {
  672.                 if isset$atts[$new_key) ) {
  673.                     $atts[$new_key$atts[$old_key];
  674.                 }
  675.                 unset$atts[$old_key);
  676.             }
  677.         }
  678.     }
  679.  
  680.     /**
  681.      * Build the data for a javascript map.
  682.      *
  683.      * Parameters are used both to retrieve data and as options to
  684.      * eventually pass to the javascript.
  685.      *
  686.      * @since 1.4
  687.      * @uses GeoMashup::get_locations_json()
  688.      *
  689.      * @global array $geo_mashup_options 
  690.      * @global object $geo_mashup_custom 
  691.      * @param array $query Query parameters
  692.      * @return array Map data ready to be rendered.
  693.      */
  694.     public static function build_map_data$query {
  695.         global $geo_mashup_options$geo_mashup_custom;
  696.         $defaults array(
  697.             'map_api' => $geo_mashup_options->get'overall''map_api' )
  698.         );
  699.         $query wp_parse_args$query$defaults );
  700.         $object_id = isset$query['object_id'$query['object_id'0;
  701.         unset$query['object_id');
  702.  
  703.         $map_data $query array(
  704.             'ajaxurl' => admin_url'admin-ajax.php' ),
  705.             'siteurl' => home_url()// qTranslate doesn't work with get_option( 'home' )
  706.             'url_path' => GEO_MASHUP_URL_PATH,
  707.             'template_url_path' => get_stylesheet_directory_uri()
  708.         );
  709.         if isset$geo_mashup_custom ) ) {
  710.             $map_data['custom_url_path'$geo_mashup_custom->url_path;
  711.         }
  712.  
  713.         $map_content isset$query['map_content') ) $query['map_content'null;
  714.         $object_name isset$query['object_name') ) $query['object_name''post';
  715.  
  716.         if $map_content == 'single'{
  717.             $location GeoMashupDB::get_object_location$object_name$object_idARRAY_A );
  718.             $options $geo_mashup_options->get'single_map' );
  719.             if !empty$location ) ) {
  720.                 $map_data['object_data'array'objects' => array$location ) );
  721.                 $map_data['center_lat'$location['lat'];
  722.                 $map_data['center_lng'$location['lng'];
  723.             }
  724.             $map_data array_merge $options$map_data );
  725.             if 'post' == $object_name {
  726.                 $kml_urls self::get_kml_attachment_urls$object_id );
  727.                 if (count($kml_urls)>0{
  728.                     $map_data['load_kml'array_pop$kml_urls );
  729.                 }
  730.             }
  731.         else {
  732.             // Map content is not single
  733.             $map_data['context_object_id'$object_id;
  734.  
  735.             if $map_content == 'contextual' {
  736.                 $options $geo_mashup_options->get'context_map' );
  737.                 // If desired we could make these real options
  738.                 $options['auto_info_open''false';
  739.             else {
  740.                 $options $geo_mashup_options->get'global_map' );
  741.                 // Category options done during render
  742.                 unset$options['category_color');
  743.                 unset$options['category_line_zoom');
  744.                 if empty$query['show_future') )
  745.                     $query['show_future'$options['show_future'];
  746.                 if is_null$map_content ) ) 
  747.                     $options['map_content''global';
  748.             }
  749.  
  750.             if isset$options['add_google_bar'and 'true' == $options['add_google_bar'{
  751.                 $options['adsense_code'$geo_mashup_options->get'overall''adsense_code' );
  752.             }
  753.  
  754.             // We have a lot map control parameters that don't effect the locations query,
  755.             // but only the relevant ones are used
  756.             $map_data['object_data'self::get_locations_json$queryARRAY_A );
  757.  
  758.             // Incorporate parameters from the query and options
  759.             $map_data array_merge$query$map_data );
  760.             $map_data array_merge$options$map_data );
  761.         }
  762.         return $map_data;
  763.     }
  764.  
  765.     /**
  766.      * The map template tag.
  767.      *
  768.      * Returns HTML for a Google map. Must use with echo in a template: echo GeoMashup::map();.
  769.      *
  770.      * @since 1.0
  771.      * @link http://code.google.com/p/wordpress-geo-mashup/wiki/TagReference#Map tag parameter documentation
  772.      * @uses $_SERVER['QUERY_STRING'] The first global map on a page uses query string parameters like tag parameters.
  773.      * @staticvar $map_number Used to index maps per request.
  774.      *
  775.      * @param string|array$atts Template tag parameters.
  776.      * @return string The HTML for the requested map.
  777.      */
  778.     public static function map$atts null {
  779.         global $wp_query$in_comment_loop$geo_mashup_options;
  780.         static $map_number 0;
  781.  
  782.         $map_number++;
  783.         $atts wp_parse_args$atts );
  784.         $static = (bool)!empty$atts['static'and 'true' == $atts['static');
  785.         unset$atts['static');
  786.         if empty$atts['lang') ) {
  787.             if function_exists'qtrans_getLanguage' ) ) {
  788.                 // qTranslate integration
  789.                 $atts['lang'qtrans_getLanguage();
  790.             else if defined'ICL_LANGUAGE_CODE' ) ) {
  791.                 // WPML integration
  792.                 $atts['lang'ICL_LANGUAGE_CODE;
  793.             }
  794.         }
  795.         $click_to_load_options array'click_to_load''click_to_load_text' );
  796.  
  797.         self::convert_map_attributes$atts );
  798.  
  799.         // Default query is for posts
  800.         $object_name isset$atts['object_name') ) $atts['object_name''post';
  801.  
  802.         // Find the ID and location of the container object if it exists
  803.         if 'post' == $object_name and $wp_query->in_the_loop {
  804.  
  805.             $context_object_id $wp_query->post->ID;
  806.  
  807.         else if 'comment' == $object_name and $in_comment_loop {
  808.             
  809.             $context_object_id get_comment_ID();
  810.  
  811.         else if 'user' == $object_name and $wp_query->post {
  812.  
  813.             $context_object_id $wp_query->post->post_author;
  814.  
  815.         }
  816.         if empty$atts['object_id'and empty$context_object_id ) ) {
  817.             
  818.             $atts['object_id'$context_object_id;
  819.             $context_location GeoMashupDB::get_object_location$object_name$context_object_id );
  820.  
  821.         }
  822.  
  823.         // Map content type isn't required, so resolve it
  824.         $map_content = isset$atts['map_content'$atts['map_content'null;
  825.  
  826.         if empty $map_content ) ) {
  827.  
  828.             if empty$context_object_id ) ) {
  829.                 $map_content 'contextual';
  830.             else if empty$context_location ) ) {
  831.                 // Not located, go global
  832.                 $map_content 'global';
  833.             else {
  834.                 // Located, go single
  835.                 $map_content 'single';
  836.             }
  837.  
  838.         }
  839.  
  840.         switch ($map_content{
  841.             case 'contextual':
  842.                 $atts['map_content''contextual';
  843.                 $atts += $geo_mashup_options->get'context_map'$click_to_load_options );
  844.                 $object_ids array();
  845.                 if 'comment' == $object_name {
  846.                     $context_objects $wp_query->comments;
  847.                 else {
  848.                     $context_objects $wp_query->posts;
  849.                 }
  850.                 if !is_array$context_objects ) ) {
  851.                     return '<!-- ' __'Geo Mashup found no objects to map in this context''GeoMashup' '-->';
  852.                 }
  853.                 foreach $context_objects as $context_object {
  854.                     if 'post' == $object_name {
  855.                         $object_ids[$context_object->ID;
  856.                     else if 'user' == $object_name {
  857.                         $object_ids[$context_object->post_author;
  858.                     else if 'comment' == $object_name {
  859.                         $object_ids[$context_object->comment_ID;
  860.                     }
  861.                 }
  862.                 $atts['object_ids'implode','$object_ids );
  863.                 break;
  864.  
  865.             case 'single':
  866.                 $atts['map_content''single';
  867.                 $atts += $geo_mashup_options->get'single_map'$click_to_load_options );
  868.                 if empty$atts['object_id') ) {
  869.                     return '<!-- ' __'Geo Mashup found no current object to map''GeoMashup' '-->';
  870.                 }
  871.                 $single_location GeoMashupDB::get_object_location$object_name$atts['object_id');
  872.                 if empty$single_location ) ) {
  873.                     return '<!-- ' __'Geo Mashup omitted a map for an object with no location''GeoMashup' '-->';
  874.                 }
  875.                 break;
  876.  
  877.             case 'global':
  878.                 if isset$_GET['template'and 'full-post' == $_GET['template'{
  879.                     // Global maps tags in response to a full-post query can infinitely nest, prevent this
  880.                     return '<!-- ' __'Geo Mashup map omitted to avoid nesting maps''GeoMashup' '-->';
  881.                 }
  882.                 $atts['map_content''global';
  883.                 if isset($_SERVER['QUERY_STRING']and == $map_number {
  884.                     // The first global map on a page will make use of query string arguments
  885.                     $atts wp_parse_args$_SERVER['QUERY_STRING']$atts );
  886.                 
  887.                 $atts += $geo_mashup_options->get'global_map'$click_to_load_options );
  888.                 // Don't query more than max_posts
  889.                 $max_posts $geo_mashup_options->get'global''max_posts' );
  890.                 if empty$atts['limit'and !empty$max_posts ) )
  891.                     $atts['limit'$max_posts;
  892.                 break;
  893.  
  894.             default:
  895.                 return '<div class="gm-map"><p>Unrecognized value for map_content: "'.$map_content.'".</p></div>';
  896.         }
  897.         
  898.         $click_to_load $atts['click_to_load'];
  899.         unset$atts['click_to_load');
  900.         $click_to_load_text $atts['click_to_load_text'];
  901.         unset$atts['click_to_load_text');
  902.         if !isset$atts['name') )
  903.             $atts['name''gm-map-' $map_number;
  904.  
  905.         $map_data self::build_map_data$atts );
  906.         if empty$map_data['object_data']['objects'and !isset$map_data['load_empty_map') )
  907.             return '<!-- ' __'Geo Mashup omitted a map with no located objects found.''GeoMashup' '-->';
  908.         unset$map_data['load_empty_map');
  909.  
  910.         $map_image '';
  911.         if $static {
  912.             // Static maps have a limit of 50 markers: http://code.google.com/apis/maps/documentation/staticmaps/#Markers
  913.             $atts['limit'empty$atts['limit'50 $atts['limit'];
  914.  
  915.             if !empty$map_data['object_data']['objects') ) {
  916.                 $image_width str_replace'%'''$map_data['width');
  917.                 $image_height str_replace'%'''$map_data['height');
  918.                 $map_image '<img src="http://maps.google.com/maps/api/staticmap?size='.$image_width.'x'.$image_height;
  919.                 if count$map_data['object_data']['objects'== 1{
  920.                     $map_image .= '&amp;center=' $map_data['object_data']['objects'][0]['lat'',' .
  921.                         $map_data['object_data']['objects'][0]['lng'];
  922.                 }
  923.                 $map_image .= '&amp;sensor=false&amp;zoom=' $map_data['zoom''&amp;markers=size:small|color:red';
  924.                 foreach$map_data['object_data']['objects'as $location {
  925.                     // TODO: Try to use the correct color for the category? Draw category lines?
  926.                     $map_image .= '|' $location['lat'',' $location['lng'];
  927.                 }
  928.                 $map_image .= '" alt="geo_mashup_map"';
  929.                 if ($click_to_load == 'true'{
  930.                     $map_image .= '" title="'.$click_to_load_text.'"';
  931.                 }
  932.                 $map_image .= ' />';
  933.             }
  934.         }
  935.  
  936.         $atts_md5 =  md5serialize$atts ) );
  937.         set_transient'gmm' $atts_md5$map_data20 );
  938.         set_transient'gmp' $atts_md5$atts60*60*24 );
  939.  
  940.         $iframe_src =  home_url'?geo_mashup_content=render-map&amp;map_data_key=' $atts_md5 );
  941.         if !empty$atts['lang') )
  942.             $iframe_src .= '&amp;lang=' $atts['lang'];
  943.             
  944.         $content "";
  945.  
  946.         if ($click_to_load == 'true'{
  947.             if is_feed() ) {
  948.                 $content .= "<a href=\"{$iframe_src}\">$click_to_load_text</a>";
  949.             else {
  950.                 self::$add_loader_script true;
  951.                 $style "height:{$map_data['height']}px;width:{$map_data['width']}px;background-color:#ddd;".
  952.                     "background-image:url(".GEO_MASHUP_URL_PATH."/images/wp-gm-pale.png);".
  953.                     "background-repeat:no-repeat;background-position:center;cursor:pointer;";
  954.                 $content "<div class=\"gm-map\" style=\"$style\" .
  955.                     "onclick=\"GeoMashupLoader.addMapFrame(this,'$iframe_src','{$map_data['height']}','{$map_data['width']}','{$map_data['name']}')\">";
  956.                 if $static {
  957.                     // TODO: test whether click to load really works with a static map
  958.                     $content .= $map_image '</div>';
  959.                 else {
  960.                     $content .= "<p style=\"text-align:center;\">$click_to_load_text</p></div>";
  961.                 }
  962.             }
  963.         else if $static {
  964.             $content "<div class=\"gm-map\">$map_image</div>";
  965.         else {
  966.             $content =  "<div class=\"gm-map\"><iframe name=\"{$map_data['name']}\" src=\"{$iframe_src}\" .
  967.                 "height=\"{$map_data['height']}\" width=\"{$map_data['width']}\" marginheight=\"0\" marginwidth=\"0\" ".
  968.                 "scrolling=\"no\" frameborder=\"0\"></iframe></div>";
  969.         }
  970.         return $content;
  971.     }
  972.  
  973.     /**
  974.      * Full post template tag.
  975.      *
  976.      * Returns a placeholder where a related map should display the full post content
  977.      * of the currently selected marker.
  978.      *
  979.      * @since 1.1
  980.      * @link http://code.google.com/p/wordpress-geo-mashup/wiki/TagReference#Full_Post
  981.      * 
  982.      * @param string|array$args Template tag arguments.
  983.      * @return string Placeholder HTML.
  984.      */
  985.     public static function full_post($args null{
  986.         $args wp_parse_args($args);
  987.         $for_map 'gm';
  988.         if !empty$args['for_map') ) {
  989.             $for_map $args['for_map'];
  990.         }
  991.         // It's nice if click-to-load works in the full post display
  992.         self::$add_loader_script true;
  993.  
  994.         return '<div id="' $for_map '-post"></div>';
  995.     }
  996.  
  997.     /**
  998.      * Category name template tag.
  999.      *
  1000.      * If there is a map_cat parameter, return the name of that category.
  1001.      *
  1002.      * @since 1.1
  1003.      * @link http://code.google.com/p/wordpress-geo-mashup/wiki/TagReference#Category_Name
  1004.      * 
  1005.      * @param string|array$option_args Template tag arguments.
  1006.      * @return string Category name.
  1007.      */
  1008.     public static function category_name($option_args null{
  1009.         $category_name '';
  1010.         if (is_string($option_args)) {
  1011.             $option_args wp_parse_args($option_args);
  1012.         }
  1013.         if (is_page(&& isset($_SERVER['QUERY_STRING'])) {
  1014.             $option_args $option_args self::explode_assoc('=','&amp;',$_SERVER['QUERY_STRING']);
  1015.         }
  1016.         if (isset($option_args['map_cat'])) {
  1017.             $category_name get_cat_name($option_args['map_cat']);
  1018.         }
  1019.         return $category_name;
  1020.     }
  1021.  
  1022.     /**
  1023.      * Category legend template tag.
  1024.      *
  1025.      * Returns a placeholder where a related map should display a legend for the
  1026.      * categories of the displayed content.
  1027.      *
  1028.      * @since 1.1
  1029.      * @link http://code.google.com/p/wordpress-geo-mashup/wiki/TagReference#Category_Legend
  1030.      * 
  1031.      * @param string|array$args Template tag arguments.
  1032.      * @return string Placeholder HTML.
  1033.      */
  1034.     public static function category_legend($args null{
  1035.         $args wp_parse_args($args);
  1036.         $for_map 'gm-map-1';
  1037.         if !empty$args['for_map') ) {
  1038.             $for_map $args['for_map'];
  1039.         }    
  1040.         return '<div id="' $for_map '-legend"></div>';
  1041.     }
  1042.  
  1043.     /**
  1044.      * If the option is set, add a map link to category lists.
  1045.      *
  1046.      * list_cats {@link http://codex.wordpress.org/Plugin_API/Filter_Reference#Category_Filters filter}
  1047.      * called by WordPress.
  1048.      *
  1049.      * @since 1.0
  1050.      */
  1051.     public static function list_cats($content$category null{
  1052.         global $geo_mashup_options;
  1053.  
  1054.         if $category and 'category' == $category->taxonomy {
  1055.             $count GeoMashupDB::category_located_post_count$category->cat_ID );
  1056.             // Add map link only if there are geo-located posts to see
  1057.             if ($count{
  1058.                 // This feature doesn't work unless there is a category description
  1059.                 if empty$category->description ) ) {
  1060.                     return $content $geo_mashup_options->get('overall''category_link_separator'
  1061.                         __'You must add a description to this category to use this Geo Mashup feature.''GeoMashup' );
  1062.                 }
  1063.                 $link '';
  1064.                 $url get_page_link($geo_mashup_options->get('overall''mashup_page'));
  1065.                 if (strstr($url,'?')) {
  1066.                     $url .= '&amp;';
  1067.                 else {
  1068.                     $url .= '?';
  1069.                 }
  1070.                 $link '<a href="'.$url.'map_cat='.$category->cat_ID.'&amp;zoom='.$geo_mashup_options->get('overall''category_zoom').
  1071.                     '" title="'.$geo_mashup_options->get('overall''category_link_text').'">';
  1072.                 return $content.'</a>'.$geo_mashup_options->get('overall''category_link_separator').$link.
  1073.                     $geo_mashup_options->get('overall''category_link_text');
  1074.             }
  1075.         }
  1076.         return $content;
  1077.     }
  1078.  
  1079.     /**
  1080.      * WordPress action to add the Geo Mashup Options settings admin page.
  1081.      *
  1082.      * admin_menu {@link http://codex.wordpress.org/Plugin_API/Action_Reference#Advanced_Actions action}
  1083.      * called by WordPress.
  1084.      *
  1085.      * @since 1.0
  1086.      */
  1087.     public static function admin_menu({
  1088.         if (function_exists('add_options_page')) {
  1089.             add_options_page(__('Geo Mashup Options','GeoMashup')__('Geo Mashup','GeoMashup')'manage_options'__FILE__array__CLASS__'options_page'));
  1090.         }
  1091.     }
  1092.  
  1093.     /**
  1094.      * WordPress action to display important messages in the admin.
  1095.      * 
  1096.      * admin_notices {@link http://codex.wordpress.org/Plugin_API/Action_Reference#Advanced_Actions action}
  1097.      * called by WordPress.
  1098.      *
  1099.      * @since 1.3
  1100.      */
  1101.     public static function admin_notices({
  1102.         global $geo_mashup_options;
  1103.  
  1104.         $message '';
  1105.         if self::is_options_page() ) {
  1106.             // We're not looking at the settings, but it may be important to do so
  1107.             $google_key $geo_mashup_options->get'overall''google_key' );
  1108.             if empty$google_key and 'google' == $geo_mashup_options->get'overall''map_api' and current_user_can'manage_options' ) ) {
  1109.                 $message __'Geo Mashup requires a Google API key in the <a href="%s">settings</a> before it will work.''GeoMashup' );
  1110.                 $message sprintf$messageadmin_url'options-general.php?page=' GEO_MASHUP_PLUGIN_NAME ) );
  1111.             }
  1112.             if GEO_MASHUP_DB_VERSION != GeoMashupDB::installed_version(and current_user_can'manage_options' ) ) {
  1113.                 $message __'Geo Mashup needs to upgrade its database, visit the <a href="%s">settings</a> to do it now.''GeoMashup' );
  1114.                 $message sprintf$messageadmin_url'options-general.php?page=' GEO_MASHUP_PLUGIN_NAME ) );
  1115.             }
  1116.         }
  1117.  
  1118.         if empty$message ) ) {
  1119.             echo '<div class="error fade"><p>' $message '</p></div>';
  1120.         }
  1121.     }
  1122.  
  1123.     /**
  1124.      * WordPress action to add custom action links to the plugin listing.
  1125.      * 
  1126.      * plugin_action_links {@link http://codex.wordpress.org/Plugin_API/Filter_Reference#Advanced_WordPress_Filters filter},
  1127.      * called by WordPress.
  1128.      *
  1129.      * @since 1.3
  1130.      */
  1131.     public static function plugin_action_links$links$file {
  1132.         if GEO_MASHUP_PLUGIN_NAME == $file {
  1133.             $settings_link '<a href="' admin_url'options-general.php?page=' GEO_MASHUP_PLUGIN_NAME .'">' .
  1134.                 __'Settings' '</a>';
  1135.             array_unshift$links$settings_link );
  1136.         }
  1137.         return $links;
  1138.     }
  1139.  
  1140.     /**
  1141.      * WordPress action to add custom meta links to the plugin listing.
  1142.      * 
  1143.      * plugin_row_meta {@link http://codex.wordpress.org/Plugin_API/Filter_Reference#Advanced_WordPress_Filters filter},
  1144.      * called by WordPress.
  1145.      *
  1146.      * @since 1.3
  1147.      */
  1148.     public static function plugin_row_meta$links$file {
  1149.         if GEO_MASHUP_PLUGIN_NAME == $file {
  1150.             $links['<a href="http://code.google.com/p/wordpress-geo-mashup/wiki/Documentation">' .
  1151.                 __'Documentation''GeoMashup' '</a>';
  1152.             $links['<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=11045324">' .
  1153.                 __'Donate''GeoMashup' '</a>';
  1154.         }
  1155.         return $links;
  1156.     }
  1157.  
  1158.     /**
  1159.      * WordPress action to produce the Geo Mashup Options admin page.
  1160.      *
  1161.      * Called by the WordPress admin.
  1162.      * 
  1163.      * @since 1.0
  1164.      */
  1165.     public static function options_page({
  1166.         include_oncepath_joinGEO_MASHUP_DIR_PATH'options.php' ) );
  1167.         geo_mashup_options_page();
  1168.     }
  1169.  
  1170.     /**
  1171.      * Get the location of the current loop object, if any.
  1172.      *
  1173.      * @since 1.3
  1174.      *
  1175.      * @param string $output ARRAY_A | ARRAY_N | OBJECT
  1176.      * @return object|boolLocation object or false if none.
  1177.      */
  1178.     public static function current_location$output OBJECT {
  1179.         global $in_comment_loop$in_user_loop$user;
  1180.  
  1181.  
  1182.         $location false;
  1183.  
  1184.         if $in_comment_loop {
  1185.             $object_name 'comment';
  1186.             $object_id get_comment_ID();
  1187.         else if $in_user_loop {
  1188.             $object_name 'user';
  1189.             $object_id $user->ID;
  1190.         else if in_the_loop() ) {
  1191.             $object_name 'post';
  1192.             $object_id get_the_ID();
  1193.         else {
  1194.             $object_name $object_id '';
  1195.         }
  1196.             
  1197.         if $object_name && $object_id {
  1198.             $location GeoMashupDB::get_object_location$object_name$object_id$output );
  1199.         }
  1200.         return $location;
  1201.     }
  1202.  
  1203.     /** 
  1204.      * A template tag to insert location information.
  1205.      *
  1206.      * @since 1.3
  1207.      *
  1208.      * @param string|array$args Template tag arguments.
  1209.      * @return string The information requested, empty string if none.
  1210.      */
  1211.     public static function location_info$args '' {
  1212.         $defaults array
  1213.             'fields' => 'address'
  1214.             'separator' => ','
  1215.             'format' => '',
  1216.             'object_name' => null
  1217.             'object_id' => null );
  1218.         $args wp_parse_args$args$defaults );
  1219.         extract$argsEXTR_SKIP );
  1220.         $info '';
  1221.  
  1222.         if $object_name && $object_id {
  1223.             $location GeoMashupDB::get_object_location$object_name$object_idARRAY_A );
  1224.         else {
  1225.             $location self::current_locationARRAY_A );
  1226.         }
  1227.  
  1228.         if !empty$location ) ) {
  1229.             $fields preg_split'/\s*,\s*/'$fields );
  1230.             $values array();
  1231.             foreach$fields as $field {
  1232.                 if isset$location[$field) ) {
  1233.                     array_push$values$location[$field);
  1234.                 else {
  1235.                     if 'country_name' == $field 
  1236.                         array_push$valuesGeoMashupDB::get_administrative_name$location['country_code') );
  1237.                     else if 'admin_name' == $field {
  1238.                         array_push$valuesGeoMashupDB::get_administrative_name$location['country_code']$location['admin_code') );
  1239.                     else {
  1240.                         array_push$values'' );
  1241.                     }
  1242.                 
  1243.             }
  1244.             if empty$format ) ) {
  1245.                 $info implode$separator$values );
  1246.             else {
  1247.                 $info vsprintf$format$values );
  1248.             }
  1249.         }
  1250.         return $info;
  1251.     }    
  1252.  
  1253.     /**
  1254.      * A template tag to insert a link to a post on the mashup.
  1255.      * 
  1256.      * @see show_on_map_link()
  1257.      */
  1258.     public static function post_link($option_args ''{
  1259.         return self::show_on_map_link($option_args);
  1260.     }
  1261.  
  1262.     /**
  1263.      * A template tag to return an URL for the current location on the
  1264.      * global map page.
  1265.      *
  1266.      * @since 1.3
  1267.      *
  1268.      * @return string The URL, empty if no current location is found.
  1269.      */
  1270.     public static function show_on_map_link_url$args null {
  1271.         global $geo_mashup_options;
  1272.  
  1273.         $defaults array'zoom' => '' );
  1274.         $args wp_parse_args$args$defaults );
  1275.  
  1276.         $url '';
  1277.         $location self::current_location();
  1278.         if $location {
  1279.             $url get_page_link($geo_mashup_options->get('overall''mashup_page'));
  1280.             if !$url {
  1281.                 return $url;
  1282.             }
  1283.             if strstr$url'?' ) ) {
  1284.                 $url .= '&amp;';
  1285.             else {
  1286.                 $url .= '?';
  1287.             }
  1288.             $open '';
  1289.             if $geo_mashup_options->get'global_map''auto_info_open' == 'true' {
  1290.                 $open '&open_object_id=' $location->object_id;
  1291.             }
  1292.             $zoom '';
  1293.             if !empty$args['zoom') ) {
  1294.                 $zoom '&zoom=' urlencode$args['zoom');
  1295.             }
  1296.             $url .= htmlentities("center_lat={$location->lat}&center_lng={$location->lng}$open$zoom");
  1297.         }
  1298.         return $url;
  1299.     }
  1300.  
  1301.     /**
  1302.      * A template tag to insert a link to the current location post on the
  1303.      * global map page.
  1304.      *
  1305.      * @since 1.3
  1306.      *
  1307.      * @return string The link HTML, empty if no current location is found.
  1308.      */
  1309.     public static function show_on_map_link$args null {
  1310.         $defaults array'text' => __'Show on map''GeoMashup' ),
  1311.              'display' => false,
  1312.              'zoom' => '',
  1313.              'show_icon' => true );
  1314.         $options wp_parse_args($args$defaults);
  1315.         $link '';
  1316.         $url self::show_on_map_link_url$args );
  1317.         if $url {
  1318.             $icon '';
  1319.             if ($options['show_icon'&& strcmp$options['show_icon']'false' != 0{
  1320.                 $icon '<img src="'.GEO_MASHUP_URL_PATH.
  1321.                     '/images/geotag_16.png" alt="'.__('Geotag Icon','GeoMashup').'"/>';
  1322.             }
  1323.             $link '<a class="gm-link" href="'.$url.'">'.
  1324.                 $icon.' '.$options['text'].'</a>';
  1325.             if ($options['display']{
  1326.                 echo $link;
  1327.             }
  1328.         }
  1329.         return $link;
  1330.     }
  1331.  
  1332.     /** 
  1333.      * Visible posts list template tag.
  1334.      *
  1335.      * Returns a placeholder where a related map should display a list
  1336.      * of the currently visible posts.
  1337.      *
  1338.      * @since 1.2
  1339.      * @link http://code.google.com/p/wordpress-geo-mashup/wiki/TagReference#Visible_Posts_List
  1340.      *
  1341.      * @param string|array$args Template tag arguments.
  1342.      * @return string Placeholder HTML.
  1343.      */
  1344.     public static function visible_posts_list($args null{
  1345.         $args wp_parse_args($args);
  1346.  
  1347.         $list_html '';
  1348.  
  1349.         $for_map 'gm-map-1';
  1350.         if !empty$args['for_map') ) {
  1351.             $for_map $args['for_map'];
  1352.         }    
  1353.         if !empty$args['heading_text') ) {
  1354.             $heading_div '<div id="' $for_map '-visible-list-header" style="display:none;">';
  1355.             $heading_tags '<h2>';
  1356.             if !empty$args['heading_tags') ) {
  1357.                 $heading_tags $args['heading_tags'];
  1358.             }
  1359.             $list_html .= balanceTags$heading_div $heading_tags $args['heading_text']true );
  1360.         }
  1361.         $list_html .= '<div id="' $for_map '-visible-list"></div>';
  1362.         return $list_html;
  1363.     }
  1364.  
  1365.     /**
  1366.      * List located posts template tag.
  1367.      *
  1368.      * Returns an HTML list of all located posts.
  1369.      *
  1370.      * @since 1.1
  1371.      * @link http://code.google.com/p/wordpress-geo-mashup/wiki/TagReference#List_Located_Posts
  1372.      *
  1373.      * @param string|array$args Template tag arguments.
  1374.      * @return string List HTML.
  1375.      */
  1376.     public static function list_located_posts$option_args null {
  1377.         $option_args wp_parse_args$option_args );
  1378.         $option_args['object_name''post';
  1379.         $list_html '<ul class="gm-index-posts">';
  1380.         $locs GeoMashupDB::get_object_locations$option_args );
  1381.         if ($locs{
  1382.             foreach ($locs as $loc{
  1383.                 $list_html .= '<li><a href="'.get_permalink($loc->object_id).'">'.
  1384.                     $loc->label."</a></li>\n";
  1385.             }
  1386.         }
  1387.         $list_html .= '</ul>';
  1388.         return $list_html;
  1389.     }
  1390.  
  1391.     /**
  1392.      * List located posts by area template tag.
  1393.      *
  1394.      * Returns an HTML list of all located posts by country and state. May try to look up
  1395.      * this information when absent.
  1396.      *
  1397.      * @since 1.2
  1398.      * @link http://code.google.com/p/wordpress-geo-mashup/wiki/TagReference#List_Located_Posts_By_Area
  1399.      *
  1400.      * @param string|array$args Template tag arguments.
  1401.      * @return string List HTML.
  1402.      */
  1403.     public static function list_located_posts_by_area$args {
  1404.         $args wp_parse_args$args );
  1405.         $list_html '<div class="gm-area-list">';
  1406.         $countries GeoMashupDB::get_distinct_located_values'country_code'array'object_name' => 'post' ) );
  1407.         $country_count count$countries );
  1408.         $country_heading '';
  1409.         foreach $countries as $country {
  1410.             if $country_count {
  1411.                 $country_name GeoMashupDB::get_administrative_name$country->country_code )
  1412.                 $country_name $country_name $country_name $country->country_code;
  1413.                 $country_heading '<h3>' $country_name '</h3>';
  1414.             }
  1415.             $states GeoMashupDB::get_distinct_located_values'admin_code'
  1416.                 array'country_code' => $country->country_code'object_name' => 'post' ) );
  1417.             if empty$states ) ) {
  1418.                 $states array(object) array'admin_code' => null ) );
  1419.             }
  1420.             foreach ($states as $state 
  1421.                 $location_query array
  1422.                     'object_name' => 'post',
  1423.                     'country_code' => $country->country_code,
  1424.                     'admin_code' => $state->admin_code,
  1425.                     'sort' => 'post_title'
  1426.                 );
  1427.                 $post_locations GeoMashupDB::get_object_locations$location_query );
  1428.                 if count$post_locations {
  1429.                     if empty$country_heading ) ) {
  1430.                         $list_html .= $country_heading;
  1431.                         $country_heading '';
  1432.                     }
  1433.                     if null != $states[0]->admin_code {
  1434.                         $state_name GeoMashupDB::get_administrative_name$country->country_code$state->admin_code );
  1435.                         $state_name $state_name $state_name $state->admin_code;
  1436.                         $list_html .= '<h4>' $state_name '</h4>';
  1437.                     }
  1438.                     $list_html .= '<ul class="gm-index-posts">';
  1439.                     foreach $post_locations as $post_location 
  1440.                         $list_html .= '<li><a href="' 
  1441.                             get_permalink$post_location->object_id .
  1442.                             '">' .
  1443.                             $post_location->label .
  1444.                             '</a>';
  1445.                         if isset$args['include_address'&& $args['include_address'== 'true' {
  1446.                             $list_html .= '<p>' $post_location->address '</p>';
  1447.                         }
  1448.                         $list_html .= '</li>';
  1449.                     }
  1450.                     $list_html .= '</ul>';
  1451.                 }
  1452.             }
  1453.         }
  1454.         $list_html .= '</div>';
  1455.         return $list_html;
  1456.     }
  1457.  
  1458.     /**
  1459.      * Post coordinates template tag.
  1460.      *
  1461.      * Get the coordinates of the current post.
  1462.      *
  1463.      * @since 1.0
  1464.      * @link http://code.google.com/p/wordpress-geo-mashup/wiki/TagReference#Post_Coordinates
  1465.      * @deprecated 1.3 Use GeoMashup::current_location()
  1466.      *
  1467.      * @param string|array$places Maximum number of decimal places to use.
  1468.      * @return array Array containing 'lat' and 'lng' keys.
  1469.      */
  1470.     public static function post_coordinates($places 10{
  1471.         global $post;
  1472.  
  1473.         $location GeoMashupDB::get_object_location'post'$post->ID );
  1474.         $coordinates array();
  1475.         if !empty$location ) ) {
  1476.             $lat $location->lat;
  1477.             $lng $location->lng;
  1478.             $lat_dec_pos strpos($lat,'.');
  1479.             if ($lat_dec_pos !== false{
  1480.                 $lat substr($lat0$lat_dec_pos+$places+1);
  1481.             }
  1482.             $lng_dec_pos strpos($lng,'.');
  1483.             if ($lng_dec_pos !== false{
  1484.                 $lng substr($lng0$lng_dec_pos+$places+1);
  1485.             }
  1486.             $coordinates['lat'$lat;
  1487.             $coordinates['lng'$lng;
  1488.         }
  1489.         return $coordinates;
  1490.     }
  1491.  
  1492.     /**
  1493.      * WordPress action to emit GeoRSS namespace.
  1494.      *
  1495.      * rss_ns {@link http://codex.wordpress.org/Plugin_API/Action_Reference#Feed_Actions action}
  1496.      * called by WordPress.
  1497.      *
  1498.      * @since 1.0
  1499.      */
  1500.     public static function rss_ns({
  1501.         echo 'xmlns:georss="http://www.georss.org/georss" ';
  1502.     }
  1503.  
  1504.     /**
  1505.      * WordPress action to emit GeoRSS tags.
  1506.      *
  1507.      * rss_item {@link http://codex.wordpress.org/Plugin_API/Action_Reference#Feed_Actions action}
  1508.      * called by WordPress.
  1509.      *
  1510.      * @since 1.0
  1511.      */
  1512.     public static function rss_item({
  1513.         global $wp_query;
  1514.  
  1515.         // Using Simple GeoRSS for now
  1516.         $location GeoMashupDB::get_object_location'post'$wp_query->post->ID );
  1517.         if !empty$location ) ) {
  1518.             echo '<georss:point>' esc_html$location->lat ' ' $location->lng '</georss:point>';
  1519.         }
  1520.     }
  1521.  
  1522.     /**
  1523.      * Tabbed category index template tag.
  1524.      *
  1525.      * Returns a placeholder where a related map should display a list
  1526.      * of map objects by category, organized into HTML suited for presentation
  1527.      * as tabs.
  1528.      *
  1529.      * @since 1.2
  1530.      * @link http://code.google.com/p/wordpress-geo-mashup/wiki/TagReference#Visible_Posts_List
  1531.      *
  1532.      * @param string|array$args Template tag arguments.
  1533.      * @return string Placeholder HTML.
  1534.      */
  1535.     public static function tabbed_category_index$args {
  1536.         $args wp_parse_args($args);
  1537.  
  1538.         $for_map 'gm-map-1';
  1539.         if !empty$args['for_map') ) {
  1540.             $for_map $args['for_map'];
  1541.         }    
  1542.         
  1543.         return '<div id="' $for_map '-tabbed-index"></div>';
  1544.     }
  1545. // class GeoMashup
  1546. // class exists
  1547.  
  1548. ?>

Documentation generated on Sat, 09 Jul 2011 21:54:53 -0700 by phpDocumentor 1.4.3