/** * Encode places array in geojson compliant format * (refer to http://leafletjs.com/examples/geojson.html) * Define geomap boundaries according to $places * Default boundaries are defined using PHP_INT_MAX value * * @param array $places An array of place posts. * * @return array An array of markers and boundaries for Leaflet. */ function wl_shortcode_geomap_prepare_map($places) { // Prepare for min/max lat/long in case we need to define a view boundary for the client JavaScript. $min_latitude = PHP_INT_MAX; $min_longitude = PHP_INT_MAX; $max_latitude = ~PHP_INT_MAX; $max_longitude = ~PHP_INT_MAX; // Prepare an empty array of POIs in geoJSON format. $pois = array(); // And store list of points to allow Leaflet compute the optimal bounding box. // The main reason for this is that geoJSON has swapped coordinates (lon. lat) $boundaries = array(); // Add a POI for each entity that has coordinates. foreach ($places as $entity) { // Get the coordinates. $coordinates = wl_get_coordinates($entity->ID); // Don't show the widget if the coordinates aren't set. if ($coordinates['latitude'] == 0 || $coordinates['longitude'] == 0) { continue; } // TODO Map html rendering should be delegated to the wordlift js ui layer // This function should be focused on returning pure data instead // Get the title, URL and thumb of the entity. $title = esc_attr($entity->post_title); $link = esc_attr(get_permalink($entity->ID)); if ('' !== ($thumbnail_id = get_post_thumbnail_id($entity->ID)) && false !== ($attachment = wp_get_attachment_image_src($thumbnail_id))) { $img_src = esc_attr($attachment[0]); } // Build HTML popup. TODO: move thumb width in css $content = "<a href={$link}><h6>{$title}</h6>"; if (isset($img_src)) { $content = $content . "<img src={$img_src} style='width:100%'/>"; } $content = $content . "</a><ul>"; // Get the related posts (published) and print them in the popup. $related_posts = wl_core_get_related_post_ids($entity->ID, array('status' => 'publish')); foreach ($related_posts as $rp_id) { $rp = get_post($rp_id); $title = esc_attr($rp->post_title); $link = esc_attr(get_permalink($rp->ID)); $content = $content . "<li><a href={$link}>{$title}</a></li>"; } $content = $content . "</ul>"; // Formatting POI in geoJSON. // http://leafletjs.com/examples/geojson.html $poi = array('type' => 'Feature', 'properties' => array('popupContent' => $content), 'geometry' => array('type' => 'Point', 'coordinates' => array($coordinates['longitude'], $coordinates['latitude']))); $pois[] = $poi; // Formatting boundaries in a Leaflet-like format (see LatLngBounds). // http://leafletjs.com/reference.html#latlngbounds $boundaries[] = array($coordinates['latitude'], $coordinates['longitude']); } $map_data = array(); $map_data['features'] = $pois; $map_data['boundaries'] = $boundaries; return $map_data; }
/** * Create: * * 1 Post * * 3 Place entities referenced by the Post * * 1 Person entity reference by the Post * * Check that only the first 2 entities are returned when calling *wl_core_get_related_entity_ids*. */ function testGetPlaces() { $post_id = wl_create_post('', 'post-1', 'Post 1', 'publish', 'post'); $entity_1_id = wl_create_post("Entity 1 Text", 'entity-1', "Entity 1 Title", 'publish', 'entity'); wl_set_entity_main_type($entity_1_id, 'http://schema.org/Place'); add_post_meta($entity_1_id, WL_CUSTOM_FIELD_GEO_LATITUDE, 40.12, true); add_post_meta($entity_1_id, WL_CUSTOM_FIELD_GEO_LONGITUDE, 72.3, true); $entity_2_id = wl_create_post("Entity 2 Text", 'entity-2', "Entity 2 Title", 'publish', 'entity'); wl_set_entity_main_type($entity_2_id, 'http://schema.org/Place'); add_post_meta($entity_2_id, WL_CUSTOM_FIELD_GEO_LATITUDE, 41.2, true); add_post_meta($entity_2_id, WL_CUSTOM_FIELD_GEO_LONGITUDE, 78.2, true); $entity_3_id = wl_create_post('Entity 3 Text', 'entity-3', 'Entity 3 Title', 'publish', 'entity'); wl_set_entity_main_type($entity_2_id, 'http://schema.org/Place'); add_post_meta($entity_3_id, WL_CUSTOM_FIELD_GEO_LATITUDE, 45.12, true); add_post_meta($entity_3_id, WL_CUSTOM_FIELD_GEO_LONGITUDE, 90.3, true); $entity_4_id = wl_create_post('', 'entity-4', 'Entity 4', 'publish', 'entity'); wl_set_entity_main_type($entity_4_id, 'http://schema.org/Person'); wl_core_add_relation_instance($post_id, WL_WHERE_RELATION, $entity_1_id); wl_core_add_relation_instance($post_id, WL_WHERE_RELATION, $entity_2_id); wl_core_add_relation_instance($post_id, WL_WHO_RELATION, $entity_4_id); $places = wl_shortcode_geomap_get_places($post_id); $this->assertCount(2, $places); $places_ids = array_map(function ($item) { return $item->ID; }, $places); $this->assertContains($entity_1_id, $places_ids); $this->assertContains($entity_2_id, $places_ids); // From here onwards we check that the JSON response matches the places data. $response = wl_shortcode_geomap_prepare_map($places); // Check retrieved boundaries $this->assertTrue(isset($response['boundaries'])); $this->assertCount(2, $response['boundaries']); // Should contain two set of coordinates. $this->assertCount(2, $response['boundaries'][0]); // [minLat, minLon] $this->assertCount(2, $response['boundaries'][1]); // [maxLat, maxLon] // Check if coordinates are actually numbers $this->assertTrue(is_numeric($response['boundaries'][0][0])); $this->assertTrue(is_numeric($response['boundaries'][0][1])); $this->assertTrue(is_numeric($response['boundaries'][1][0])); $this->assertTrue(is_numeric($response['boundaries'][1][1])); // Check retrieved places $this->assertTrue(isset($response['features'])); $i = 0; foreach ($places as $place) { // Check object attributes $poi = $response['features'][$i]; $this->assertTrue(isset($poi)); $this->assertTrue(isset($poi['type'])); $this->assertTrue(isset($poi['properties'])); $this->assertNotEmpty(isset($poi['properties']['popupContent'])); $this->assertTrue(isset($poi['geometry'])); $this->assertTrue(isset($poi['geometry']['coordinates'])); $this->assertCount(2, $poi['geometry']['coordinates']); $this->assertTrue(is_numeric($poi['geometry']['coordinates'][0])); $this->assertTrue(is_numeric($poi['geometry']['coordinates'][1])); // Check consistency with declared places $coords = wl_get_coordinates($place->ID); $coords = array($coords['longitude'], $coords['latitude']); // Leaflet geoJSON wants them swapped $this->assertEquals($coords, $poi['geometry']['coordinates']); $i++; } }
/** * Displays the coordinates meta box contents (called by *add_meta_box* callback). * * @param WP_Post $post The current post. */ function wl_entities_coordinates_box_content($post) { // Add leaflet css and library. wp_enqueue_style('leaflet_css', plugins_url('bower_components/leaflet/dist/leaflet.css', __FILE__)); wp_enqueue_script('leaflet_js', plugins_url('bower_components/leaflet/dist/leaflet.js', __FILE__)); // Set nonce for both meta (latitude and longitude) wl_echo_nonce(WL_CUSTOM_FIELD_GEO_LATITUDE); wl_echo_nonce(WL_CUSTOM_FIELD_GEO_LONGITUDE); // Get coordinates $coords = wl_get_coordinates($post->ID); // Print input fields echo '<label for="wl_place_lat">' . __('Latitude', 'wordlift') . '</label>'; echo '<input type="text" id="wl_place_lat" name="wl_metaboxes[' . WL_CUSTOM_FIELD_GEO_LATITUDE . ']" value="' . $coords['latitude'] . '" style="width:100%" />'; echo '<label for="wl_place_lon">' . __('Longitude', 'wordlift') . '</label>'; echo '<input type="text" id="wl_place_lon" name="wl_metaboxes[' . WL_CUSTOM_FIELD_GEO_LONGITUDE . ']" value="' . $coords['longitude'] . '" style="width:100%" />'; // Show Leaflet map to pick coordinates echo "<div id='wl_place_coords_map'></div>"; echo "<script type='text/javascript'>\n \$ = jQuery;\n \$(document).ready(function(){\n \$('#wl_place_coords_map').width('100%').height('200px');\n var wlMap = L.map('wl_place_coords_map').setView([" . $coords['latitude'] . "," . $coords['longitude'] . "], 9);\n \n L.tileLayer( 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',\n { attribution: '© <a href=http://osm.org/copyright>OpenStreetMap</a> contributors'}\n ).addTo( wlMap );\n \n var marker = L.marker([" . $coords['latitude'] . "," . $coords['longitude'] . "]).addTo( wlMap );\n \n function refreshCoords(e) {\n \$('#wl_place_lat').val( e.latlng.lat );\n \$('#wl_place_lon').val( e.latlng.lng );\n marker.setLatLng( e.latlng )\n }\n\n wlMap.on('click', refreshCoords);\n });\n </script>"; }
public function get_data() { $entity_id = get_the_ID(); $this->data = wl_get_coordinates($entity_id); }