--- 4.6.0/location.module-4.6.0 2006-01-09 10:47:35.000000000 +0100 +++ location.module 2006-01-24 17:48:45.000000000 +0100 @@ -20,9 +20,18 @@ include_once LOCATION_PATH.'/location.in function location_menu($may_cache = FALSE) { $items = array(); if ($may_cache) { - $items[] = array('path' => 'search/location', 'title' => t('by location'), 'callback' => 'location_search_form_page', 'access' => user_access('search content'), 'type' => MENU_LOCAL_TASK, 'weight' => 9); - $items[] = array('path' => 'admin/settings/location/main', 'title' => t('main settings'), 'type' => MENU_DEFAULT_LOCAL_TASK); - $items[] = array('path' => 'admin/settings/location/maplinking', 'title' => t('map links'), 'callback' => 'location_map_link_options_page', 'access' => user_access('administer site configuration'), 'type' => MENU_LOCAL_TASK); + $items[] = array('path' => 'location', 'title' => t('content by location'), + 'callback' => 'location_content', + 'access' => user_access('view location'), + 'type' => MENU_SUGGESTED_ITEM, 'weight' => 9); + $items[] = array('path' => 'search/location', 'title' => t('by location'), + 'callback' => 'location_search_form_page', 'access' => user_access('search content'), + 'type' => MENU_LOCAL_TASK, 'weight' => 9); + $items[] = array('path' => 'admin/settings/location/main', 'title' => t('main settings'), + 'type' => MENU_DEFAULT_LOCAL_TASK); + $items[] = array('path' => 'admin/settings/location/maplinking', 'title' => t('map links'), + 'callback' => 'location_map_link_options_page', 'access' => user_access('administer site configuration'), + 'type' => MENU_LOCAL_TASK); } else { drupal_set_html_head(location_form_html_head()); @@ -31,7 +40,7 @@ function location_menu($may_cache = FALS } function location_perm() { - return array('submit latitude/longitude'); + return array('submit latitude/longitude', 'view location section'); } /** @@ -60,6 +69,394 @@ function location_help($section) { } } + +/** + * Menu callback; checks path (under /location/) and directs request to relevant functions. + */ +function location_content($a = NULL, $b = NULL, $c = NULL, $d = NULL, $e = NULL) { + + // set defaults // + $categories = array($a,$b,$c,$d,$e); + $location_arguments = array(); + $is_kml = 0; + $is_networklink = 0; + $is_rss = 0; + $is_iframe = 0; + $country = ''; + + // retrieve list of country codes from elsewhere in module // + $supported_countries = _location_supported_countries(); + + // work through levels in path, set flags where necessary and read in country code if present // + for ($cat_count = count($categories)-1; $cat_count >= 0; $cat_count--) { + if ($categories[$cat_count]) { + switch ($categories[$cat_count]) { + case 'networklink': + $is_networklink = 1; + break; + case 'kml': + $is_kml = 1; + break; + case 'feed': + $is_feed = 1; + break; + default: + // check to see if it is a valid country and lookup name // + if (array_key_exists($categories[$cat_count],$supported_countries)) { + $isocode = $categories[$cat_count]; + $countryname = $supported_countries[$isocode]; + } + } + } + } + + if ($isocode) { + $location_arguments[] = array('isocode' => $isocode); + $location_arguments[] = array('country' => $countryname); + } + + if (!$is_feed) { + // if not a feed, display page + location_content_page_last($location_arguments); + } + else { + if (!$is_kml) { + // if not KML, then generate RSS + location_content_feed_last($location_arguments); + } + else { + if (!$is_networklink) { + // if not network link, generate KML feed + location_content_kml_last($location_arguments); + } + else { + //generate KML network link + location_content_networklink($location_arguments); + } + } + } + +} + + +/** + * Displays a KML feed containing recent location-enabled nodes. + */ +function location_content_kml_last($location_arguments = array()) { + foreach ($location_arguments as $location_argument) { + foreach ($location_argument as $key => $value) { + switch ($key) { + case 'isocode': + $isocode = $value; + $country_restrict = "AND l.country = '$isocode'"; + case 'country': + $country = $value; + } + } + } + + $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM {node} n INNER JOIN {location} l ON n.nid = l.oid INNER JOIN {users} u ON n.uid = u.uid WHERE n.status = 1 AND l.source != 0 $country_restrict ORDER BY n.created DESC"), 0, 15); + + $site = variable_get('site_name', 'drupal'); + if (isset($isocode)) { + $title = t('%site content in %country', array('%site' => $site, '%country' => $country)); + } + else { + $title = t('%site content worldwide', array('%site' => $site)); + } + + $channel['title'] .= $title; + $channel['link'] = url('location', NULL, NULL, TRUE); + $channel['description'] = $term->description; + format_kml_feed($result, $channel); +} + + +/** + * A generic function for generating KML (Keyhole Markup Language for Google Earth) feeds from a set of nodes. + * + * @param $nodes + * An object as returned by db_query() which contains the nid field. + * @param $channel + * An associative array containing title, link, description and other keys. + * The link should be an absolute URL. + */ +function format_kml_feed($nodes = 0, $channel = array()) { + + $items = ''; + while ($node = db_fetch_object($nodes)) { + // Load the specified node: + $item = node_load(array('nid' => $node->nid)); + $link = url("node/$node->nid", NULL, NULL, 1); + + // Filter and prepare node teaser + if (node_hook($item, 'view')) { + node_invoke($item, 'view', TRUE, FALSE); + } + else { + $item = node_prepare($item, TRUE); + } + + // Allow modules to change $node->teaser before viewing. + node_invoke_nodeapi($item, 'view', true, false); + + // Allow modules to add additional item fields + $extra = node_invoke_nodeapi($item, 'kml item'); + $items .= format_kml_placemark($item->title, $link, $item->teaser, $item->location['latitude'], $item->location['longitude'], 0, $extra); + } + + $output = "\n"; + $output .= "\n"; + $output .= " \n"; + $output .= format_kml_folder($channel['title'], $channel['description'], $items, $extras); + $output .= " \n"; + $output .= "\n"; + + drupal_set_header('Content-Type: application/vnd.google-earth.kml+xml'); + print $output; +} + + +/** + * Formats a KML Folder (based on format_rss_channel()). + * + * Arbitrary elements may be added using the $args associative array. + */ +function format_kml_folder($title, $description, $items, $args = array()) { + // arbitrary elements may be added using the $args associative array + + $output = " \n"; + $output .= ' '. check_plain($title) ."\n"; + $output .= ' '. check_plain($description) ."\n"; + if ($args) { + foreach ($args as $key => $value) { + $output .= ' <'. $key .'>'. check_plain($value) ."\n"; + } + } + $output .= $items; + $output .= " \n"; + + return $output; +} + + +/** + * Format a single KML Placemark (based on format_rss_item()). + * + * Arbitrary elements may be added using the $args associative array. + */ +function format_kml_placemark($title, $link, $description, $lat = 0, $long = 0, $alt = 0, $args = array()) { + $output = " \n"; + $output .= ' '. check_plain($title) ."\n"; + $output .= ' '. check_plain($description .'
'. t('View page') .'') ."
\n"; + $output .= " \n"; + $coordinates = $long. ','. $lat. ','. $alt; + $output .= ' '. $coordinates ."\n"; + $output .= " \n"; + foreach ($args as $key => $value) { + if (is_array($value)) { + if ($value['key']) { + $output .= ' <'. $value['key']; + if (is_array($value['attributes'])) { + $output .= drupal_attributes($value['attributes']); + } + + if ($value['value']) { + $output .= '>'. $value['value'] .'\n"; + } + else { + $output .= " />\n"; + } + } + } + else { + $output .= ' <'. $key .'>'. check_plain($value) ."\n"; + } + } + $output .= "
\n"; + + return $output; +} + + +/** + * A function for creating a KML Network Link for a specific KML feed. + * + */ +function location_content_networklink($location_arguments = array()) { + foreach ($location_arguments as $location_argument) { + foreach ($location_argument as $key => $value) { + switch ($key) { + case 'isocode': + $isocode = $value; + case 'country': + $country = $value; + } + } + } + + $site = variable_get('site_name', 'drupal'); + if (isset($isocode)) { + $title = t('%site content in %country', array('%site' => $site, '%country' => $country)); + } + else { + $title = t('%site content worldwide', array('%site' => $site)); + } + + // set link to KML feed to send out through Network Link + $kml_feed = url(NULL, NULL, NULL, TRUE); + if (isset($isocode)) { + $kml_feed .= 'location/'.$isocode.'/feed/kml'; + } + else { + $kml_feed .= 'location/feed/kml'; + } + + $url['name'] = $title; + $url['href'] = $kml_feed; + $url['refreshMode'] = 'onInterval'; + $url['refreshInterval'] = 60; + $url['viewRefreshMode'] = 'onStop'; + $url['viewRefreshTime'] = 0; + + $output = format_kml_networklink($title,$kml_feed,$url); + + drupal_set_header('Content-Type: application/vnd.google-earth.kml+xml'); + print $output; +} + + +/** + * A generic function for generating a KML (Keyhole Markup Language for Google Earth) Network Link. + * + * Arbitrary elements may be added using the $args associative array. + */ +function format_kml_networklink($title, $kml_feed, $url_items = array(), $args = array()) { + $output = "\n"; + $output .= "\n"; + $output .= " \n"; + $output .= " \n"; + $output .= " \n"; + foreach ($url_items as $url_item => $value) { + $output .= ' <'. $url_item .'>'. check_plain($value) .'\n"; + } + $output .= " \n"; + $output .= " \n"; + $output .= " \n"; + $output .= "\n"; + + return $output; +} + + +/** + * Displays an RSS feed containing recent location-enabled nodes. + */ +function location_content_feed_last($location_arguments = array()) { + foreach ($location_arguments as $location_argument) { + foreach ($location_argument as $key => $value) { + switch ($key) { + case 'isocode': + $isocode = $value; + $country_restrict = "AND l.country = '$isocode'"; + case 'country': + $country = $value; + } + } + } + + $result = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM {node} n INNER JOIN {location} l ON n.nid = l.oid INNER JOIN {users} u ON n.uid = u.uid WHERE n.status = 1 AND l.source != 0 $country_restrict ORDER BY n.created DESC"), 0, 15); + + $site = variable_get('site_name', 'drupal'); + if (isset($isocode)) { + $title = t('%site content in %country', array('%site' => $site, '%country' => $country)); + } + else { + $title = t('%site content worldwide', array('%site' => $site)); + } + + $channel['title'] .= $title; + $channel['link'] = url('location', NULL, NULL, TRUE); + $channel['description'] = $term->description; + node_feed($result, $channel); +} + + +/** + * Displays a Drupal page containing recent location-enabled entries. + */ +function location_content_page_last($location_arguments = array()) { + $output = ''; + + foreach ($location_arguments as $location_argument) { + foreach ($location_argument as $key => $value) { + switch ($key) { + case 'isocode': + $isocode = $value; + $country_restrict = "AND l.country = '$isocode'"; + case 'country': + $country = $value; + } + } + } + + $result = pager_query(db_rewrite_sql("SELECT n.nid, n.title, n.teaser, n.created, u.name, u.uid FROM {node} n INNER JOIN {location} l ON n.nid = l.oid INNER JOIN {users} u ON n.uid = u.uid WHERE n.status = 1 AND l.source != 0 $country_restrict ORDER BY n.created DESC"), variable_get('default_nodes_main', 10)); + + // output items to page + while ($node = db_fetch_object($result)) { + $output .= node_view(node_load(array('nid' => $node->nid)), 1); + } + $output .= theme('pager', NULL, variable_get('default_nodes_main', 10)); + + // add list of links to country-specific listings (only countries with content) + $supported_countries = _location_supported_countries(); + $result = db_query("SELECT l.country FROM {location} l WHERE l.country != '' AND l.country != 'xx' GROUP BY l.country ORDER BY l.country ASC"); + $country_links[] = 'all'; + while ($country_link = db_fetch_object($result)) { + $country_links[] = ''. $supported_countries[$country_link->country] .''; + } + $output .= t('Countries with content:'); + $country_links_remaining = count($country_links); + foreach ($country_links as $country_link) { + $country_links_remaining--; + $output .= ' '. $country_link; + if ($country_links_remaining > 0) { + $output .= ','; + } + } + + // set appropriate location of rss and kml feeds and also page title + if (isset($isocode)) { + $xml_feed = 'location/'.$isocode.'/feed'; + $kml_feed = 'location/'.$isocode.'/feed/kml/networklink'; + $title = t('Content in %country', array('%country' => $country)); + } + else { + $xml_feed = 'location/feed'; + $kml_feed = 'location/feed/kml'; + $title = t('Content around the world'); + } + drupal_set_title($title); + + // add xml and kml icons to page, linking to relevant feeds + $output .= theme('xml_icon', url($xml_feed)); + $output .= ''.t('KML feed').''; + + // add rel tags to page to assist in automatic discovery of feeds + drupal_add_link(array('rel' => 'alternate', + 'type' => 'application/rss+xml', + 'title' => t('RSS - location enabled pages'), + 'href' => url($xml_feed))); + drupal_add_link(array('rel' => 'alternate', + 'type' => 'application/vnd.google-earth.kml+xml', + 'title' => t('KML - location enabled pages'), + 'href' => url($kml_feed))); + + print theme('page', $output); +} + + + /** * Serves a search-by-location page for nodes. * On $_POST, displays searh form + search results. @@ -533,7 +930,8 @@ function location_nodeapi(&$node, $op, $ case 'rss item': $items = array(); if (!is_null($node->location['lat']) && !is_null($node->location['lon'])) { - $items[] = array('key' => 'geo:Point', 'value' => "\n ". $node->location['lat'] ."\n ". $node->location['lon'] ."\n"); + $items[] = array('key' => 'geo:Point', 'value' => "". $node->location['lat'] ."". $node->location['lon'] .""); + $items[] = array('key' => 'icbm:latitude', 'value' => $node->location['lat']); $items[] = array('key' => 'icbm:longitude', 'value' => $node->location['lon']); $items[] = array('key' => 'geourl:latitude', 'value' => $node->location['lat']);