Skip to content

Instantly share code, notes, and snippets.

@jakecraige
Created October 17, 2013 22:11
Show Gist options
  • Select an option

  • Save jakecraige/7033176 to your computer and use it in GitHub Desktop.

Select an option

Save jakecraige/7033176 to your computer and use it in GitHub Desktop.
<?php
/**
* @file
* leaflet powered custom maps for townelake homes.
* by Jake Craige @ Poetic Systems
*/
/**
* How To Import Lots
* TL:DR Delete all current lots(feed/json), import feed lots, import json lots
* ==============================
* ***THIS MUST BE DONE IN ORDER***
* Go to /import and delete all current lots
* Go to /lot-search and delete all non-feed based lots
* Update JSON url in this file if necessary to current feed
* Go to /import and import all lots
* Go to /json and let that run
* You're done! It's that easy
* See me with any questions -Jake
*/
// Green
$home_style = array(
'weight' => 1,
'color' => '#008000'
);
// Blue
$lot_style = array(
'weight' => 1,
'color' => '#0878BA'
);
// Red
$not_available_style = array(
'weight' => 1,
'color' => '#ED2228'
);
// Gray
$other_builder_style = array(
'weight' => 1,
'color' => '#B1B1B1'
);
define('HOME_STYLE', serialize($home_style));
define('LOT_STYLE', serialize($lot_style));
define('NOT_AVAILABLE_STYLE', serialize($not_available_style));
define('OTHER_BUILDER_STYLE', serialize($other_builder_style));
//define('JSON_URL', 'http://jakecraige.com/geojson/townelake/townelake-part1.geojson');
define('JSON_URL', 'http://jakecraige.com/geojson/townelake/townelake-part2.geojson');
// This path pulls in the feed from the hard coded data source
function townelake_maps_menu() {
$items['json'] = array(
'title' => 'Parse GeoJson Feed',
'page callback' => 'townelake_maps_import_lots',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
$items['quick-home-search'] = array(
'title' => 'Drag the map around and zoom in to see specific lots',
'page callback' => 'townelake_maps_page',
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
);
//'page arguments' => array(1),
return $items;
}
function townelake_maps_page() {
$lot_nodes = townelake_maps_get_lot_nodes();
$points = townelake_maps_process_geofield_data($lot_nodes);
//dsm(count($points). 'points');
if (!empty($points)) {
$styles = module_invoke_all('leaflet_map_info');
$default_settings = $styles['OSM Mapnik']['settings'];
$attr_google = 'Map data &copy; <a href="http://googlemaps.com">Google</a>';
$prot = '//' ;
$map_info['google-high-res'] = array(
'label' => 'Google high-res road & terrain (zoom 0..18)',
'description' => t('Google road & terrain layers, with high-res (Retina) support'),
'settings' => array('layerControl' => TRUE) + $default_settings,
'layers' => array(
'terrain' => array(
'type' => 'google',
'urlTemplate' => $prot . 'mt{s}.googleapis.com/vt?lyrs=t,r&x={x}&y={y}&z={z}',
'options' => array(
'attribution' => $attr_google,
'detectRetina' => TRUE,
'subdomains' => array(0, 1, 2, 3)
)
),
'roadmap' => array(
'type' => 'google',
// For retina displays we append '&style=high_dpi&w=512',
// see leaflet_more_maps_preprocess_leaflet_map()
'urlTemplate' => $prot . 'mt{s}.googleapis.com/vt?lyrs=m@237049708&x={x}&y={y}&z={z}',
'options' => array(
'attribution' => $attr_google,
'detectRetina' => TRUE,
'subdomains' => array(0, 1, 2, 3)
)
)
)
);
return leaflet_render_map($map_info['google-high-res'], $points, '800px');
}
else {
return "No points found";
}
}
function townelake_maps_get_lot_nodes() {
$results = db_query("SELECT nid
FROM {node}
WHERE type='lot'
AND status='1'");
foreach ($results as $result) {
$home_ids[] = $result->nid;
}
$homes = node_load_multiple($home_ids); // Array of Home Nodes
return $homes;
}
// TODO: Look into using leaflet_process_geofield function in leaflet.formatters.inc
function townelake_maps_process_geofield_data($nodes) {
geophp_load();
$geodata = array();
foreach ($nodes as $node) {
$field_geometry = field_get_items('node', $node, 'field_geometry');
if($field_geometry) {
$field_geometry_wkt = $field_geometry[0]['wkt'];
$geometry = geoPHP::load($field_geometry_wkt, 'wkt');
$components = $geometry->getComponents();
$components = $components[0]->getComponents();
$data = array();
$data['type'] = 'polygon';
$data['leaflet_id'] = 'lot'.$node->nid;
$field_available = field_get_items('node', $node, 'field_available');
$field_home_reference = field_get_items('node', $node, 'field_home_reference');
$field_section_reference = field_get_items('node', $node, 'field_section_reference');
$field_builder_reference = field_get_items('node', $node, 'field_builder_reference');
//dsm($field_builder_reference);
$available = $field_available[0]['value'];
$section_reference = $field_section_reference[0]['target_id'];
$section = node_load($section_reference);
$section_name = $section->field_marketing_name['und'][0]['value'];
$section_sold_out = $section->field_sold_out['und'][0]['value'];
$section_info = '<h4>Nid: '.$node->nid.'</h4>';
$section_info .= '<h4>Title/ID: '.$node->title.'</h4>';
$section_info .= '<h3>Section: '.$node->field_section_id['und'][0]['value'].'</h3>';
$section_info .= '<h3>Block: '.$node->field_block_id['und'][0]['value'].'</h3>';
$section_info .= '<h3>Lot: '.$node->field_lot_id['und'][0]['value'].'</h3>';
//$section_info .= '<p class="section-info">'
//. townelake_maps_get_section_name($section_reference) . '</p>
//<input type="hidden" value="'.$node->nid.'"/>';
// Status References: Available is " Available, Completed, Start"
// if it red out or invalid builder?
// Make it RED
// if it gray out? -
// Make it GRAY
// else if it's not in sold out section
// if it's available
// if it has a home reference
// make it GREEN
// else no home reference
// make it BLUE
// else if has builder reference and not available
// make it RED
// else no builder reference and not available
// make it GRAY
// else in sold out section
// mark it RED
if(townelake_maps_get_red_out($node->nid) || townelake_maps_invalid_builder($node->nid)) {
$data['options'] = unserialize(NOT_AVAILABLE_STYLE);
$data['popup'] .= $section_info;
$data['popup'] .= 'This lot is <b>not available</b>.';
}
elseif(townelake_maps_get_gray_out($node->nid)) {
$data['options'] = unserialize(OTHER_BUILDER_STYLE);
$data['popup'] .= $section_info;
$data['popup'] .= 'This lot is <b>not available</b>.';
}
elseif(!townelake_maps_get_sold_out($section_reference)) {
if($available) {
if($field_home_reference) {
$home_node = node_load($field_home_reference[0]['target_id']);
$nid = $home_node->nid;
$street_address = $home_node->field_address['und'][0]['thoroughfare'];
$city_state = $home_node->field_address['und'][0]['locality']
. ', ' . $home_node->field_address['und'][0]['administrative_area']
. ' ' . $home_node->field_address['und'][0]['postal_code'];
$body = $home_node->field_description['und'][0]['value'];
$price = $home_node->field_price['und'][0]['value'];
$sqft = $home_node->field_square_feet['und'][0]['value'];
$beds = $home_node->field_bedrooms['und'][0]['value'];
$baths = $home_node->field_bathrooms['und'][0]['value'];
$image = $home_node->field_image['und'][0]['uri'];
$data['options'] = unserialize(HOME_STYLE);
$popup_html = '<h2><a href="/node/' . $nid . '">'
. $street_address . '<br>' . $city_state . '</a></h2>';
$popup_html .= $section_info;
$popup_html .= '<div class="left_fifty">';
$popup_html .= '<img width="100" height="80" src="' . drupal_realpath($image) . '">';
$popup_html .= '</div>';
$popup_html .= '<div class="right_fifty">';
$popup_html .= '<p>';
$popup_html .= '<span class="price">$' . number_format($price) . '</span><br>';
$popup_html .= '<span class="sqft">'
. number_format($sqft) . ' sqft</span><br>';
$popup_html .= "<span class=\"beds\">$beds beds</span><br>";
$popup_html .= '<span class="baths">'
. trim(trim($baths, 0), '.') . ' baths</span>';
$popup_html .= '</p>';
$popup_html .= '</div>';
$popup_html .= '<div class="body">';
if(strlen($body) > 160) {
$popup_html .= '<p>' . substr($body, 0 , 160) . '...</p>';
}
else {
$popup_html .= '<p>' . $body . '</p>';
}
$popup_html .= '</div>';
$data['popup'] .= $popup_html;
} else { // Available but not referenced to a home
$data['options'] = unserialize(LOT_STYLE);
$data['popup'] .= $section_info;
$builder_nid = $field_builder_reference[0]['target_id'];
if($builder_nid) {
$builder_link = drupal_get_path_alias('node/' .$builder_nid );
$builder_name = townelake_maps_get_builder_name($builder_nid);
$data['popup'] .= "This lot is <b>available</b>. <a href='$builder_link'>Contact $builder_name</a> to inquire about it.";
}
else {
$data['popup'] .= "This lot is <b>available</b>. <a href='/welcome'>Contact us</a> to inquire about it.";
}
}
} elseif($field_builder_reference[0]['target_id']) { // Not available, has builder
$data['options'] = unserialize(NOT_AVAILABLE_STYLE);
$data['popup'] .= $section_info;
$data['popup'] .= 'This lot is <b>not available</b>.';
} else { // Lot not Available, no builder and not available status
$data['options'] = unserialize(OTHER_BUILDER_STYLE);
$data['popup'] .= $section_info;
$data['popup'] .= 'This lot is <b>not available</b>.';
}
}
else { // In a sold out section
$data['options'] = unserialize(NOT_AVAILABLE_STYLE);
$data['popup'] .= $section_info;
$data['popup'] .= 'This lot is <b>not available</b>.';
}
foreach ($components as $component) {
$data['points'][] = array(
'lat' => $component->getY(),
'lon' => $component->getX(),
);
}
// If CS scoa , coming soon lot
$geodata[] = $data;
}
}
return $geodata;
}
function townelake_maps_parse_geojson_feed() {
$geophp = geophp_load();
if (!$geophp) return FALSE;
$json = file_get_contents(JSON_URL);
$feed = json_decode($json);
$results = array();
foreach($feed->features as $feature) {
$geometry = json_encode($feature->geometry);
$results[] = array(
'properties' => townelake_maps_process_job($feature->properties),
townelake_maps_process_geojson($geometry)
);
}
return $results;
}
// Converts the json to a wkt format
function townelake_maps_process_geojson($geojson) {
$geom = geoPHP::load($geojson, 'json'); // DINGDING. DATA IS AN ARRAY, not json
$result = array('wkt' => $geom->out('wkt'));
geofield_compute_values($result, 'wkt'); // Uses reference to set value
return $result;
}
// format for the json to have an id
function townelake_maps_process_job($properties) {
return $properties->Section . '-' . $properties->Block . '-' . $properties->Lot;
}
function townelake_maps_import_lots() {
$geojson = townelake_maps_parse_geojson_feed();
$feed_home_data = townelake_maps_generate_home_data();
foreach($feed_home_data as $home) {
foreach($geojson as $key => $geo) {
if($home['home_unique_id'] == $geo['properties']) {
$node = node_load($home['nid']);
townelake_maps_set_map_data($node, $geo);
node_save($node);
unset($geojson[$key]);
break;
}
}
}
// Loop through the data not matched with a current lot in the lot feed and
// add it as a new node
foreach($geojson as $geo) {
$node = new stdClass();
$node->type = 'lot';
node_object_prepare($node);
$node->title = 'NotBuilt-' . $geo['properties'];
$node->language = LANGUAGE_NONE;
$node->uid = 1;
// Default to not being available
$node->field_available['und'][0]['value'] = 0;
$section_reference = townelake_maps_get_section_reference($geo['properties']);
$node->field_section_reference['und'][0]['target_id'] = $section_reference;
preg_match('/(\w+)-(\w+)-(\w+)/', $geo['properties'], $matches);
$section = $matches[1];
$block = $matches[2];
$lot = $matches[3];
$node->field_section_id['und'][0]['value'] = $section;
$node->field_block_id['und'][0]['value'] = $block;
$node->field_lot_id['und'][0]['value'] = $lot;
townelake_maps_set_map_data($node, $geo);
node_submit($node);
node_save($node);
}
echo 'Lot Import Done.';
}
// Used to create identifier from section, block, and lot that is used
// to compare the home with the lot data
function townelake_maps_generate_home_data() {
// Normal Feed
$feeds = db_query("SELECT entity_id FROM {feeds_item} WHERE id='lot'");
$feeds_info = array();
foreach($feeds as $feed) {
$node = node_load($feed->entity_id);
$section = $node->field_section_id[$node->language][0]['value'];
$block = $node->field_block_id[$node->language][0]['value'];
$lot = $node->field_lot_id[$node->language][0]['value'];
$id = $section . '-' . $block . '-' . $lot;
$feeds_info[] = array('nid' => $feed->entity_id,
'home_unique_id' => $id);
}
// End Normal Feed
// Manual Import
//$feed_one = db_query("SELECT entity_id FROM {feeds_item} WHERE id='manual_lot_1'");
//$feed_two = db_query("SELECT entity_id FROM {feeds_item} WHERE id='manual_lot_2'");
//$feeds_info = array();
//foreach($feed_one as $feed) {
//$node = node_load($feed->entity_id);
//$section = $node->field_section_id[$node->language][0]['value'];
//$block = $node->field_block_id[$node->language][0]['value'];
//$lot = $node->field_lot_id[$node->language][0]['value'];
//$id = $section . '-' . $block . '-' . $lot;
//$feeds_info[] = array('nid' => $feed->entity_id,
//'home_unique_id' => $id);
//}
//foreach($feed_two as $feed) {
//$node = node_load($feed->entity_id);
//$section = $node->field_section_id[$node->language][0]['value'];
//$block = $node->field_block_id[$node->language][0]['value'];
//$lot = $node->field_lot_id[$node->language][0]['value'];
//$id = $section . '-' . $block . '-' . $lot;
//$feeds_info[] = array('nid' => $feed->entity_id,
//'home_unique_id' => $id);
//}
// End Manual Import
return $feeds_info;
}
// Returns Entity ID for Section Reference when given the properties of the
// geofield
function townelake_maps_get_section_reference($properties) {
// Pull section number out of calculated properties
preg_match('/(\w+)/', $properties, $matches);
$section_matches = db_query("SELECT entity_id
FROM {field_data_field_section_number}
WHERE field_section_number_value = :num
LIMIT 1",
array(':num' => $matches[0]));
foreach($section_matches as $match) {
return $match->entity_id;
}
return 0;
}
function townelake_maps_set_map_data(&$node, &$geo) {
$node->field_geometry['und'][0]['wkt'] = $geo[0]['wkt'];
$node->field_geometry['und'][0]['geo_type'] = $geo[0]['geo_type'];
$node->field_geometry['und'][0]['lat'] = $geo[0]['lat'];
$node->field_geometry['und'][0]['lon'] = $geo[0]['lon'];
$node->field_geometry['und'][0]['top'] = $geo[0]['top'];
$node->field_geometry['und'][0]['bottom'] = $geo[0]['bottom'];
$node->field_geometry['und'][0]['right'] = $geo[0]['left'];
$node->field_geometry['und'][0]['left'] = $geo[0]['right'];
}
function townelake_maps_get_section_name($section_id) {
$query = db_query("SELECT field_marketing_name_value
FROM {field_data_field_marketing_name}
WHERE entity_id=:nid
LIMIT 1",
array(':nid' => $section_id ));
foreach($query as $q) {
return $q->field_marketing_name_value;
}
}
function townelake_maps_get_sold_out($section_id) {
$query = db_query("SELECT field_sold_out_value
FROM {field_data_field_sold_out}
WHERE entity_id=:nid
LIMIT 1",
array(':nid' => $section_id ));
foreach($query as $q) {
return $q->field_sold_out_value;
}
}
function townelake_maps_get_gray_out($nid) {
$query = db_query("SELECT field_gray_out_value
FROM {field_data_field_gray_out}
WHERE entity_id=:nid
LIMIT 1",
array(':nid' => $nid ));
foreach($query as $q) {
return $q->field_gray_out_value;
}
}
function townelake_maps_get_red_out($nid) {
$query = db_query("SELECT field_red_out_value
FROM {field_data_field_red_out}
WHERE entity_id=:nid
LIMIT 1",
array(':nid' => $nid ));
foreach($query as $q) {
return $q->field_red_out_value;
}
}
function townelake_maps_get_builder_name($nid) {
$query = db_query("SELECT title
FROM {node}
WHERE nid=:nid
LIMIT 1",
array(':nid' => $nid ));
foreach($query as $q) {
return $q->title;
}
}
function townelake_maps_invalid_builder($nid) {
$query = db_query("SELECT field_builder_id_value
FROM {field_data_field_builder_id}
WHERE entity_id=:nid
LIMIT 1",
array(':nid' => $nid ));
$value = '';
foreach($query as $q) {
$value = $q->field_builder_id_value;
}
// Excludes certain builder id's that aren't allowed to be green
if($value == '8e8e97fa-5219-de11-967c-0015c5ec09eb' ||
$value == '8cd47444-9130-dc11-9bcf-0015c5ec09eb') {
return true;
}
else {
return false;
}
}
// Used for logging important info to console
function townelake_maps_log($message) {
echo '<script type="text/javascript">';
echo 'console.log("' . $message . '")';
echo '</script>';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment