Advertisement
Guest User

fix

a guest
Jun 28th, 2011
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 18.28 KB | None | 0 0
  1. <?php
  2.  
  3. if( basename( $_SERVER['SCRIPT_FILENAME'] ) == basename(__FILE__) )
  4.     die( 'Access denied.' );
  5.  
  6. if( !class_exists('BasicGoogleMapsPlacemarks') )
  7. {
  8.     /**
  9.      * A Wordpress plugin that adds a custom post type for placemarks and builds a Google Map with them
  10.      * Requires PHP5+ because of various OOP features, json_encode(), pass by reference, etc
  11.      * Requires Wordpress 3.0 because of custom post type support
  12.      *
  13.      * @package BasicGoogleMapsPlacemarks
  14.      * @author Ian Dunn <ian@iandunn.name>
  15.      * @link http://wordpress.org/extend/plugins/basic-google-maps-placemarks/
  16.      */
  17.     class BasicGoogleMapsPlacemarks
  18.     {
  19.         // Declare variables and constants
  20.         protected $settings, $options, $updatedOptions, $userMessageCount, $environmentOK, $mapShortcodeCalled;
  21.         const BGMP_VERSION          = '1.1.3';
  22.         const PREFIX                = 'bgmp_';
  23.         const POST_TYPE             = 'bgmp';
  24.         const DEBUG_MODE            = false;
  25.        
  26.         /**
  27.          * Constructor
  28.          * @author Ian Dunn <ian@iandunn.name>
  29.          */
  30.         public function __construct()
  31.         {
  32.             require_once('settings.php');
  33.            
  34.             // Initialize variables
  35.             $defaultOptions             = array( 'updates' => array(), 'errors' => array() );
  36.             $this->options              = array_merge( $defaultOptions, get_option( self::PREFIX . 'options', array() ) );  //mod
  37.             $this->updatedOptions       = false;
  38.            
  39.             $this->userMessageCount = array(); //mod
  40.             foreach ( $this->options as $msg_type => $msgs ) {
  41.                 $this->userMessageCount[$msg_type] = count( $msgs );
  42.             }
  43.            
  44.             $this->mapShortcodeCalled   = false;
  45.             $this->settings             = new BGMPSettings( $this );
  46.            
  47.             // Register actions, filters and shortcodes
  48.             add_action( 'admin_notices',                        array($this, 'printMessages') );
  49.             add_action( 'init',                                 array($this, 'createPostType') );
  50.             add_action( 'admin_init',                           array($this, 'registerCustomFields') );
  51.             add_action( 'save_post',                            array($this, 'saveCustomFields') );
  52.             add_action( 'wp_head',                              array($this, 'outputHead' ) );
  53.             add_action( 'wp_footer',                            array($this, 'outputFooter' ) );
  54.             add_action( 'wp_ajax_bgmp_get_map_options',         array($this, 'getMapOptions' ) );
  55.             add_action( 'wp_ajax_nopriv_bgmp_get_map_options',  array($this, 'getMapOptions' ) );
  56.             add_action( 'wp_ajax_bgmp_get_placemarks',          array($this, 'getPlacemarks' ) );
  57.             add_action( 'wp_ajax_nopriv_bgmp_get_placemarks',   array($this, 'getPlacemarks' ) );
  58.             add_filter( 'the_posts',                            array($this, 'loadResources'), 11 );
  59.             add_shortcode( 'bgmp-map',                          array($this, 'mapShortcode') );
  60.             add_shortcode( 'bgmp-list',                         array($this, 'listShortcode') );
  61.             register_activation_hook( __FILE__,                 array($this, 'activate') );
  62.            
  63.             if( is_admin() )
  64.                 add_theme_support( 'post-thumbnails' );
  65.                
  66.             $this->enqueueMessage('test during construct');
  67.         }
  68.        
  69.         /**
  70.          * Runs on plugin activation to prepare system for plugin usage
  71.          * @author Ian Dunn <ian@iandunn.name>
  72.          */
  73.         public function activate()
  74.         {
  75.             // Save default settings
  76.             if( !get_option( self::PREFIX . 'map-width' ) )
  77.                 add_option( self::PREFIX . 'map-width', 600 );
  78.             if( !get_option( self::PREFIX . 'map-height' ) )
  79.                 add_option( self::PREFIX . 'map-height', 400 );
  80.             if( !get_option( self::PREFIX . 'map-address' ) )
  81.                 add_option( self::PREFIX . 'map-address', 'Seattle' );
  82.             if( !get_option( self::PREFIX . 'map-latitude' ) )
  83.                 add_option( self::PREFIX . 'map-latitude', 47.6062095 );
  84.             if( !get_option( self::PREFIX . 'map-longitude' ) )
  85.                 add_option( self::PREFIX . 'map-longitude', -122.3320708 );
  86.             if( !get_option( self::PREFIX . 'map-zoom' ) )
  87.                 add_option( self::PREFIX . 'map-zoom', 7 );
  88.             if( !get_option( self::PREFIX . 'map-info-window-width' ) )
  89.                 add_option( self::PREFIX . 'map-info-window-width', 300 );
  90.             if( !get_option( self::PREFIX . 'map-info-window-height' ) )
  91.                 add_option( self::PREFIX . 'map-info-window-height', 250 );
  92.                
  93.             // Upgrade 1.0 placemark data
  94.             $posts = get_posts( array( 'numberposts' => -1, 'post_type' => self::POST_TYPE, 'post_status' => 'publish' ) );
  95.             if( $posts )
  96.             {
  97.                 foreach($posts as $p)
  98.                 {
  99.                     $address    = get_post_meta( $p->ID, self::PREFIX . 'address', true );
  100.                     $latitude   = get_post_meta( $p->ID, self::PREFIX . 'latitude', true );
  101.                     $longitude  = get_post_meta( $p->ID, self::PREFIX . 'longitude', true );
  102.                    
  103.                     if( empty($address) && !empty($latitude) && !empty($longitude) )
  104.                     {
  105.                         $address = $this->reverseGeocode($latitude, $longitude);
  106.                         if( $address )
  107.                             update_post_meta( $p->ID, self::PREFIX . 'address', $address );
  108.                     }
  109.                 }
  110.             }
  111.         }
  112.        
  113.         /**
  114.          * Checks the current post(s) to see if they contain the map shortcode
  115.          * @author Ian Dunn <ian@iandunn.name>
  116.          * @param array $posts
  117.          * @return bool
  118.          */
  119.         function mapShortcodeCalled($posts)
  120.         {
  121.             $this->mapShortcodeCalled = apply_filters( self::PREFIX .'mapShortcodeCalled', $this->mapShortcodeCalled );
  122.             if( $this->mapShortcodeCalled )
  123.                 return true;
  124.                
  125.             foreach( $posts as $p )
  126.             {
  127.                 preg_match( '/'. get_shortcode_regex() .'/s', $p->post_content, $matches );
  128.                 if( is_array($matches) && array_key_exists(2, $matches) && $matches[2] == 'bgmp-map' )
  129.                     return true;
  130.             }
  131.            
  132.             return false;
  133.         }
  134.        
  135.         /**
  136.          * Load CSS and JavaScript files
  137.          * @author Ian Dunn <ian@iandunn.name>
  138.          */
  139.         public function loadResources($posts)
  140.         {
  141.             // @todo - maybe find an action that gets run at the same time. would be better to hook there than to a filter. update faq for do_shortcode if do
  142.            
  143.             //wp_die(' plugin' );
  144.            
  145.             wp_register_script(
  146.                 'googleMapsAPI',
  147.                 'http'. ( is_ssl() ? 's' : '' ) .'://maps.google.com/maps/api/js?sensor=false',
  148.                 false,
  149.                 false,
  150.                 true
  151.             );
  152.            
  153.             wp_register_script(
  154.                 'bgmp',
  155.                 plugins_url( 'functions.js', __FILE__ ),
  156.                 array( 'googleMapsAPI', 'jquery' ),
  157.                 self::BGMP_VERSION,
  158.                 true
  159.             );
  160.            
  161.             wp_register_style(
  162.                 self::PREFIX .'style',
  163.                 plugins_url( 'style.css', __FILE__ ),
  164.                 false,
  165.                 self::BGMP_VERSION,
  166.                 false
  167.             );
  168.            
  169.             if( $posts )
  170.             {
  171.                 $this->mapShortcodeCalled = $this->mapShortcodeCalled( $posts );
  172.                
  173.                 if( !is_admin() && $this->mapShortcodeCalled )
  174.                 {
  175.                     wp_enqueue_script('googleMapsAPI');
  176.                     wp_enqueue_script('bgmp');
  177.                 }
  178.                
  179.                 if( is_admin() || $this->mapShortcodeCalled )
  180.                     wp_enqueue_style( self::PREFIX . 'style' );
  181.             }
  182.            
  183.             return $posts;
  184.         }
  185.        
  186.         /**
  187.          * Outputs elements in the <head> section of the front-end
  188.          * @author Ian Dunn <ian@iandunn.name>
  189.          */
  190.         public function outputHead()
  191.         {
  192.             if( $this->mapShortcodeCalled )
  193.                 require_once( dirname(__FILE__) . '/views/front-end-head.php' );
  194.         }
  195.        
  196.         /**
  197.          * Outputs some initial values for the JavaScript file to use
  198.          * @author Ian Dunn <ian@iandunn.name>
  199.          */
  200.         public function outputFooter()
  201.         {
  202.             if( $this->mapShortcodeCalled )
  203.                 require_once( dirname(__FILE__) . '/views/front-end-footer.php' );
  204.         }
  205.        
  206.         /**
  207.          * Registers the custom post type
  208.          * @author Ian Dunn <ian@iandunn.name>
  209.          */
  210.         public function createPostType()
  211.         {
  212.             if( !post_type_exists( self::POST_TYPE ) )
  213.             {
  214.                 $labels = array
  215.                 (
  216.                     'name' => __( 'Placemarks' ),
  217.                     'singular_name' => __( 'Placemark' ),
  218.                     'add_new' => __( 'Add New' ),
  219.                     'add_new_item' => __( 'Add New Placemark' ),
  220.                     'edit' => __( 'Edit' ),
  221.                     'edit_item' => __( 'Edit Placemark' ),
  222.                     'new_item' => __( 'New Placemark' ),
  223.                     'view' => __( 'View Placemark' ),
  224.                     'view_item' => __( 'View Placemark' ),
  225.                     'search_items' => __( 'Search Placemarks' ),
  226.                     'not_found' => __( 'No Placemarks found' ),
  227.                     'not_found_in_trash' => __( 'No Placemarks found in Trash' ),
  228.                     'parent' => __( 'Parent Placemark' ),
  229.                 );
  230.                
  231.                 register_post_type(
  232.                     self::POST_TYPE,
  233.                     array
  234.                     (
  235.                         'labels' => $labels,
  236.                         'singular_label' => __('Placemarks'),
  237.                         'public' => true,
  238.                         'menu_position' => 20,
  239.                         'hierarchical' => false,
  240.                         'capability_type' => 'post',
  241.                         'rewrite' => array( 'slug' => 'placemarks', 'with_front' => false ),
  242.                         'query_var' => true,
  243.                         'supports' => array('title', 'editor', 'author', 'thumbnail')
  244.                     )
  245.                 );
  246.             }
  247.         }
  248.        
  249.         /**
  250.          * Registers extra fields for the custom post type
  251.          * @author Ian Dunn <ian@iandunn.name>
  252.          */
  253.         public function registerCustomFields()
  254.         {
  255.             add_meta_box( self::PREFIX . 'placemark-address', 'Placemark Address', array($this, 'markupCustomFields'), self::POST_TYPE, 'normal', 'high' );
  256.         }
  257.        
  258.         /**
  259.          * Outputs the markup for the custom fields
  260.          * @author Ian Dunn <ian@iandunn.name>
  261.          */
  262.         public function markupCustomFields()
  263.         {
  264.             global $post;
  265.        
  266.             $address    = get_post_meta($post->ID, self::PREFIX . 'address', true);
  267.             $latitude   = get_post_meta($post->ID, self::PREFIX . 'latitude', true);
  268.             $longitude  = get_post_meta($post->ID, self::PREFIX . 'longitude', true);
  269.            
  270.             require_once( dirname(__FILE__) . '/views/add-edit.php' );
  271.         }
  272.        
  273.         /**
  274.          * Saves values of the the custom post type's extra fields
  275.          * @param
  276.          * @author Ian Dunn <ian@iandunn.name>
  277.          */
  278.         public function saveCustomFields($postID)
  279.         {
  280.             global $post;
  281.            
  282.             $this->enqueueMessage('test durring savecustofields');
  283.            
  284.             if( $post && $post->post_type == self::POST_TYPE && current_user_can( 'edit_posts' ) )
  285.             {
  286.                 if( ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE ) || $post->post_status == 'auto-draft' )
  287.                     return;
  288.                
  289.                 update_post_meta( $post->ID, self::PREFIX . 'address', $_POST[ self::PREFIX . 'address'] );
  290.                 $coordinates = $this->geocode( $_POST[ self::PREFIX . 'address'] );
  291.                
  292.                 if( $coordinates )
  293.                 {
  294.                     update_post_meta( $post->ID, self::PREFIX . 'latitude', $coordinates['latitude'] );
  295.                     update_post_meta( $post->ID, self::PREFIX . 'longitude', $coordinates['longitude'] );
  296.                 }
  297.                 else
  298.                 {
  299.                     // add error message for user
  300.                    
  301.                     update_post_meta( $post->ID, self::PREFIX . 'latitude', '' );
  302.                     update_post_meta( $post->ID, self::PREFIX . 'longitude', '' );
  303.                 }
  304.             }
  305.         }
  306.        
  307.         /**
  308.          * Geocodes an address
  309.          * Google's API has a daily request limit, but this is only called when a post is published, so shouldn't ever be a problem.
  310.          * @param
  311.          * @author Ian Dunn <ian@iandunn.name>
  312.          */
  313.         public function geocode($address)
  314.         {
  315.             $geocodeResponse = wp_remote_get( 'http://maps.googleapis.com/maps/api/geocode/json?address='. str_replace( ' ', '+', $address ) .'&sensor=false' );
  316.             $coordinates = json_decode( $geocodeResponse['body'] );
  317.                
  318.             if( is_wp_error($geocodeResponse) || empty($coordinates->results) )
  319.                 return false;
  320.             else
  321.                 return array( 'latitude' => $coordinates->results[0]->geometry->location->lat, 'longitude' => $coordinates->results[0]->geometry->location->lng );
  322.         }
  323.        
  324.         /**
  325.          * Reverse-geocodes a set of coordinates
  326.          * Google's API has a daily request limit, but this is only called when a post is published, so shouldn't ever be a problem.
  327.          * @param string $latitude
  328.          * @param string $longitude
  329.          * @author Ian Dunn <ian@iandunn.name>
  330.          */
  331.         protected function reverseGeocode($latitude, $longitude)
  332.         {
  333.             $geocodeResponse = wp_remote_get( 'http://maps.googleapis.com/maps/api/geocode/json?latlng='. $latitude .','. $longitude .'&sensor=false' );
  334.             $address = json_decode( $geocodeResponse['body'] );
  335.            
  336.             if( is_wp_error($geocodeResponse) || empty($address->results) )
  337.                 return false;
  338.             else
  339.                 return $address->results[0]->formatted_address;
  340.         }
  341.            
  342.         /**
  343.          * Defines the [bgmp-map] shortcode
  344.          * @author Ian Dunn <ian@iandunn.name>
  345.          * @param array $attributes Array of parameters automatically passed in by Wordpress
  346.          * return string The output of the shortcode
  347.          */
  348.         public function mapShortcode($attributes)
  349.         {
  350.             if( !wp_script_is( 'googleMapsAPI', 'queue' ) || !wp_script_is( 'bgmp', 'queue' ) || !wp_style_is( self::PREFIX .'style', 'queue' ) )
  351.                 return '<p class="error">'. BGMP_NAME .' error: JavaScript and/or CSS files aren\'t loaded. If you\'re using do_shortcode() you need to add a filter to your theme first. See <a href="http://wordpress.org/extend/plugins/basic-google-maps-placemarks/faq/">the FAQ</a> for details.</p>';
  352.            
  353.             $output = sprintf('
  354.                 <div id="%smap-canvas">
  355.                     <p>Loading map...</p>
  356.                     <p><img src="%s" alt="Loading" /></p>
  357.                 </div>',
  358.                 self::PREFIX,
  359.                 plugins_url( 'images/loading.gif', __FILE__ )
  360.             );
  361.            
  362.             return $output;
  363.         }      
  364.        
  365.         /**
  366.          * Defines the [bgmp-list] shortcode
  367.          * @author Ian Dunn <ian@iandunn.name>
  368.          * @param array $attributes Array of parameters automatically passed in by Wordpress
  369.          * return string The output of the shortcode
  370.          */
  371.         public function listShortcode($attributes)
  372.         {
  373.             $posts = get_posts( array( 'numberposts' => -1, 'post_type' => self::POST_TYPE, 'post_status' => 'publish' ) );
  374.            
  375.             if( $posts )
  376.             {
  377.                 $output = '<ul id="'. self::PREFIX .'list">';
  378.                
  379.                 foreach( $posts as $p )
  380.                 {
  381.                     $address = get_post_meta($p->ID, self::PREFIX . 'address', true);
  382.                        
  383.                     $output .= sprintf('
  384.                         <li>
  385.                             <h3>%s</h3>
  386.                             <div>%s</div>
  387.                             <p><a href="%s">%s</a></p>
  388.                         </li>',
  389.                         $p->post_title,
  390.                         nl2br($p->post_content),
  391.                         'http://google.com/maps?q='. $address,
  392.                         $address
  393.                     );
  394.                 }
  395.                
  396.                 $output .= '</ul>';
  397.                
  398.                 return $output;
  399.             }
  400.             else
  401.                 return "There aren't currently any placemarks in the system";
  402.         }
  403.        
  404.         /**
  405.          *
  406.          * @author Ian Dunn <ian@iandunn.name>
  407.          */
  408.         public function getMapOptions()
  409.         {
  410.             check_ajax_referer( self::PREFIX . 'nonce', 'nonce' );
  411.    
  412.             $options = array(
  413.                 'width'             => $this->settings->mapWidth,
  414.                 'height'            => $this->settings->mapHeight,
  415.                 'latitude'          => $this->settings->mapLatitude,
  416.                 'longitude'         => $this->settings->mapLongitude,
  417.                 'zoom'              => $this->settings->mapZoom,
  418.                 'infoWindowWidth'   => $this->settings->mapInfoWindowWidth,
  419.                 'infoWindowHeight'  => $this->settings->mapInfoWindowHeight
  420.             );
  421.        
  422.             $this->getHeaders();
  423.             die( json_encode($options) );
  424.         }
  425.        
  426.         /**
  427.          * Gets the published placemarks from the database, formats and outputs them.
  428.          * Called via AJAX. json_encode() requires PHP 5.
  429.          * @author Ian Dunn <ian@iandunn.name>
  430.          * @return string JSON formatted string of the placemarks
  431.          */
  432.         public function getPlacemarks()
  433.         {
  434.             check_ajax_referer( self::PREFIX . 'nonce', 'nonce' );
  435.            
  436.             $placemarks = array();
  437.             $posts = get_posts( array( 'numberposts' => -1, 'post_type' => self::POST_TYPE, 'post_status' => 'publish' ) );
  438.            
  439.             if( $posts )
  440.             {
  441.                 foreach($posts as $p)
  442.                 {
  443.                     $icon = wp_get_attachment_image_src( get_post_thumbnail_id($p->ID) );
  444.  
  445.                     $placemarks[] = array(
  446.                         'title'     => $p->post_title,
  447.                         'latitude'  => get_post_meta( $p->ID, self::PREFIX . 'latitude', true ),
  448.                         'longitude' => get_post_meta( $p->ID, self::PREFIX . 'longitude', true ),
  449.                         'details'   => nl2br($p->post_content),
  450.                         'icon'      => is_array($icon) ? $icon[0] : plugins_url( 'images/default-marker.png', __FILE__ )
  451.                     );
  452.                 }
  453.             }
  454.            
  455.             $this->getHeaders();
  456.             die( json_encode($placemarks) );
  457.         }
  458.        
  459.         /**
  460.          * Outputs GET headers for JSON requests
  461.          * @author Ian Dunn <ian@iandunn.name>
  462.          */
  463.         protected function getHeaders()
  464.         {
  465.             header('Cache-Control: no-cache, must-revalidate');
  466.             header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
  467.             header('Content-Type: application/json; charset=utf8');
  468.             header('Content-Type: application/json');
  469.             header($_SERVER["SERVER_PROTOCOL"]." 200 OK");
  470.         }
  471.        
  472.         /**
  473.          * Displays updates and errors
  474.          * @author Ian Dunn <ian@iandunn.name>
  475.          */
  476.         public function printMessages()
  477.         {
  478.             foreach( array('updates', 'errors') as $type )
  479.             {
  480.                 if( $this->options[$type] && ( self::DEBUG_MODE || $this->userMessageCount[$type] ) )
  481.                 {
  482.                     echo '<div id="message" class="'. ( $type == 'updates' ? 'updated' : 'error' ) .'">';
  483.                     foreach($this->options[$type] as $message)
  484.                         if( $message['mode'] == 'user' || self::DEBUG_MODE )
  485.                             echo '<p>'. $message['message'] .'</p>';
  486.                     echo '</div>';
  487.                    
  488.                     $this->options[$type] = array();
  489.                     $this->updatedOptions = true;
  490.                     $this->userMessageCount[$type] = 0;
  491.                 }
  492.             }
  493.            
  494.             if($this->updatedOptions)   // mod
  495.                 update_option(self::PREFIX . 'options', $this->options);
  496.         }
  497.        
  498.         /**
  499.          * Queues up a message to be displayed to the user
  500.          * @author Ian Dunn <ian@iandunn.name>
  501.          * @param string $message The text to show the user
  502.          * @param string $type 'update' for a success or notification message, or 'error' for an error message
  503.          * @param string $mode 'user' if it's intended for the user, or 'debug' if it's intended for the developer
  504.          */
  505.         protected function enqueueMessage($message, $type = 'update', $mode = 'user')
  506.         {
  507.             array_push($this->options[$type .'s'], array(
  508.                 'message' => $message,
  509.                 'type' => $type,
  510.                 'mode' => $mode
  511.             ) );
  512.            
  513.             if($mode == 'user')
  514.                 $this->userMessageCount[$type . 's']++;
  515.             update_option(self::PREFIX . 'options', $this->options);
  516.  
  517.             $this->updatedOptions = true;
  518.         }
  519.        
  520.         /**
  521.          * Stops execution and prints the input. Used for debugging.
  522.          * @author Ian Dunn <ian@iandunn.name>
  523.          * @param mixed $data
  524.          * @param string $message Optionally message to output before description
  525.          */
  526.         protected function describe( $data, $message = '' )
  527.         {
  528.             $type = gettype($data);
  529.  
  530.             switch( $type)
  531.             {
  532.                 case 'array':
  533.                 case 'object':
  534.                     $length = count( $data );
  535.                     $data = print_r( $data, true );
  536.                     break;
  537.                
  538.                 case 'string';
  539.                     $length = strlen( $data );
  540.                     break;
  541.                
  542.                 default:
  543.                     $length = count( $data );
  544.                    
  545.                     ob_start();
  546.                     var_dump( $data );
  547.                     $data = ob_get_contents();
  548.                     ob_end_clean();
  549.                    
  550.                     $data = print_r($data, true);
  551.                    
  552.                     break;
  553.             }
  554.            
  555.             wp_die( sprintf('
  556.                 <p>
  557.                     %s
  558.                     Type: %s<br />
  559.                     Length: %s<br />
  560.                     Content: <br /><blockquote><pre>%s</pre></blockquote>
  561.                 </p>',
  562.                 ( $message ? 'Message: '. $message .'<br />' : '' ),
  563.                 $type,
  564.                 $length,
  565.                 $data
  566.             ) );
  567.         }
  568.        
  569.         /**
  570.          * Destructor
  571.          * Writes options to the database
  572.          * @author Ian Dunn <ian@iandunn.name>
  573.          */
  574.         public function __destruct()
  575.         {
  576. //          if($this->updatedOptions)
  577.     //mod           update_option(self::PREFIX . 'options', $this->options);
  578.         }
  579.     } // end BasicGoogleMapsPlacemarks
  580. }
  581.  
  582. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement