map_layers 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.autotest ADDED
@@ -0,0 +1,7 @@
1
+ Autotest.add_hook :initialize do |autotest|
2
+ %w{coverage log script tasks \.git db}.each do |directory|
3
+ autotest.add_exception(%r{^\./#{directory}})
4
+ end
5
+ end
6
+
7
+
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ log/*
2
+ *~
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,104 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ map_layers (0.0.3)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ ZenTest (4.6.0)
10
+ abstract (1.0.0)
11
+ actionmailer (3.0.9)
12
+ actionpack (= 3.0.9)
13
+ mail (~> 2.2.19)
14
+ actionpack (3.0.9)
15
+ activemodel (= 3.0.9)
16
+ activesupport (= 3.0.9)
17
+ builder (~> 2.1.2)
18
+ erubis (~> 2.6.6)
19
+ i18n (~> 0.5.0)
20
+ rack (~> 1.2.1)
21
+ rack-mount (~> 0.6.14)
22
+ rack-test (~> 0.5.7)
23
+ tzinfo (~> 0.3.23)
24
+ activemodel (3.0.9)
25
+ activesupport (= 3.0.9)
26
+ builder (~> 2.1.2)
27
+ i18n (~> 0.5.0)
28
+ activerecord (3.0.9)
29
+ activemodel (= 3.0.9)
30
+ activesupport (= 3.0.9)
31
+ arel (~> 2.0.10)
32
+ tzinfo (~> 0.3.23)
33
+ activeresource (3.0.9)
34
+ activemodel (= 3.0.9)
35
+ activesupport (= 3.0.9)
36
+ activesupport (3.0.9)
37
+ arel (2.0.10)
38
+ autotest-notification (2.3.3)
39
+ autotest-standalone (~> 4.5)
40
+ autotest-rails (4.1.0)
41
+ ZenTest
42
+ autotest-standalone (4.5.5)
43
+ builder (2.1.2)
44
+ diff-lcs (1.1.2)
45
+ erubis (2.6.6)
46
+ abstract (>= 1.0.0)
47
+ i18n (0.5.0)
48
+ mail (2.2.19)
49
+ activesupport (>= 2.3.6)
50
+ i18n (>= 0.4.0)
51
+ mime-types (~> 1.16)
52
+ treetop (~> 1.4.8)
53
+ mime-types (1.16)
54
+ polyglot (0.3.2)
55
+ rack (1.2.3)
56
+ rack-mount (0.6.14)
57
+ rack (>= 1.0.0)
58
+ rack-test (0.5.7)
59
+ rack (>= 1.0)
60
+ rails (3.0.9)
61
+ actionmailer (= 3.0.9)
62
+ actionpack (= 3.0.9)
63
+ activerecord (= 3.0.9)
64
+ activeresource (= 3.0.9)
65
+ activesupport (= 3.0.9)
66
+ bundler (~> 1.0)
67
+ railties (= 3.0.9)
68
+ railties (3.0.9)
69
+ actionpack (= 3.0.9)
70
+ activesupport (= 3.0.9)
71
+ rake (>= 0.8.7)
72
+ rdoc (~> 3.4)
73
+ thor (~> 0.14.4)
74
+ rake (0.9.2)
75
+ rdoc (3.9.2)
76
+ rspec (2.0.1)
77
+ rspec-core (~> 2.0.1)
78
+ rspec-expectations (~> 2.0.1)
79
+ rspec-mocks (~> 2.0.1)
80
+ rspec-core (2.0.1)
81
+ rspec-expectations (2.0.1)
82
+ diff-lcs (>= 1.1.2)
83
+ rspec-mocks (2.0.1)
84
+ rspec-core (~> 2.0.1)
85
+ rspec-expectations (~> 2.0.1)
86
+ rspec-rails (2.0.1)
87
+ rspec (~> 2.0.0)
88
+ thor (0.14.6)
89
+ treetop (1.4.10)
90
+ polyglot
91
+ polyglot (>= 0.3.1)
92
+ tzinfo (0.3.29)
93
+
94
+ PLATFORMS
95
+ ruby
96
+
97
+ DEPENDENCIES
98
+ autotest-notification
99
+ autotest-rails
100
+ map_layers!
101
+ rails (>= 3.0.0)
102
+ rake
103
+ rspec (~> 2.0.0)
104
+ rspec-rails (~> 2.0.0)
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,160 @@
1
+ =MapLayers plugin for Rails
2
+
3
+ MapLayers makes it easy to integrate a dynamic map in a Rails application. It can display map tiles and markers loaded from many different data sources.
4
+ The included map viewer is OpenLayers[http://www.openlayers.org/].
5
+ With MapLayers you can display and publish ActiveRecord models with geographic data.
6
+
7
+
8
+ ==Getting Started
9
+
10
+ Install the latest version of the plugin:
11
+ ./script/plugin install git://github.com/pka/map_layers.git
12
+
13
+ Create a controller and a view
14
+ ./script/generate controller Map index
15
+
16
+ ===Initialization of the map
17
+ Add the map viewer initialization to the index action in the controller:
18
+ @map = MapLayers::Map.new("map") do |map, page|
19
+ page << map.add_layer(MapLayers::GOOGLE)
20
+ page << map.zoom_to_max_extent()
21
+ end
22
+
23
+ Add this to the head of your view:
24
+ <%= map_layers_includes :google => "ABQIAAAA3HdfrnxFAPWyY-aiJUxmqRTJQa0g3IQ9GZqIMmInSLzwtGDKaBQ0KYLwBEKSM7F9gCevcsIf6WPuIQ" %>
25
+
26
+ Put a map in the body your view:
27
+ <div id="map" style="width: 512px; height: 256px;"></div>
28
+
29
+ <%= @map.to_html %>
30
+
31
+ Test your basic map with <tt>http://localhost:3000/map</tt>
32
+
33
+ ===Multiple layers
34
+ Add a second layer and some more controls in the controller action:
35
+ @map = MapLayers::Map.new("map") do |map, page|
36
+ page << map.add_layer(MapLayers::GOOGLE)
37
+ page << map.add_layer(MapLayers::YAHOO_HYBRID)
38
+
39
+ page << map.add_control(Control::LayerSwitcher.new)
40
+ page << map.add_control(Control::Permalink.new('permalink'))
41
+ page << map.add_control(Control::MousePosition.new)
42
+
43
+ page << map.zoom_to_max_extent()
44
+ end
45
+
46
+ Add the Yahoo Javascript library to the includes:
47
+ <%= map_layers_includes :google => "ABQIAAAA3HdfrnxFAPWyY-aiJUxmqRTJQa0g3IQ9GZqIMmInSLzwtGDKaBQ0KYLwBEKSM7F9gCevcsIf6WPuIQ", :yahoo => "euzuro-openlayers" %>
48
+
49
+ There are many more predefined layer types available:
50
+ GOOGLE_SATELLITE, GOOGLE_HYBRID, GOOGLE_PHYSICAL, VE_ROAD, VE_AERIAL, VE_HYBRID, YAHOO, YAHOO_SATELLITE, YAHOO_HYBRID, MULTIMAP, OSM_MAPNIK, OSM_TELASCIENCE, GEOPOLE_OSM, NASA_GLOBAL_MOSAIC, BLUE_MARBLE_NG, WORLDWIND, WORLDWIND_URBAN, WORLDWIND_BATHY
51
+
52
+ To include all Javascript APIs, insert your API keys in the following statement:
53
+ <%= map_layers_includes :google => "ABQIAAAA3HdfrnxFAPWyY-aiJUxmqRTJQa0g3IQ9GZqIMmInSLzwtGDKaBQ0KYLwBEKSM7F9gCevcsIf6WPuIQ", :multimap => "metacarta_04", :virtualearth => true, :yahoo => "euzuro-openlayers" %>
54
+
55
+
56
+ ===Updating the map
57
+ Now we want to add some simple markers in an Ajax action.
58
+ First we add a link in the view:
59
+
60
+ <%= link_to_remote "Add marker", :url => { :action => "add_marker" } %>
61
+
62
+ This requires including the prototype library:
63
+
64
+ <%= javascript_include_tag 'prototype' %>
65
+
66
+ Then we include a marker layer in the map. Put this after the add_layer statements in the controller:
67
+
68
+ page.assign("markers", Layer::Markers.new('Markers'))
69
+ page << map.addLayer(:markers)
70
+
71
+ and then we implement the Ajax action:
72
+
73
+ def add_marker
74
+ render :update do |page|
75
+ @markers = JsVar.new('markers')
76
+ page << @markers.add_marker(OpenLayers::Marker.new(OpenLayers::LonLat.new(rand*50,rand*50)))
77
+ end
78
+ end
79
+
80
+ For accessing the marker layer in the Ajax action, we declare a Javascript variable with <tt>page.assign</tt> and access the variable later with the +JsVar+ wrapper.
81
+
82
+
83
+ ===OpenStreetMap in WGS84
84
+
85
+ To overlay data in WGS84 projection you can use a customized Open Street Map:
86
+
87
+ @map = MapLayers::Map.new("map") do |map, page|
88
+ page << map.add_layer(MapLayers::GEOPOLE_OSM)
89
+ page << map.zoom_to_max_extent()
90
+ end
91
+
92
+
93
+ =Publish your own data
94
+
95
+ Create a model:
96
+ ./script/generate model --skip-timestamps --skip-fixture Place placeName:string countryCode:string postalCode:string lat:float lng:float
97
+ rake db:migrate
98
+
99
+ Import some places:
100
+ ./script/runner "Geonames::Postalcode.search('Sidney').each { |pc| Place.create(pc.attributes.slice('placeName', 'postalCode', 'countryCode', 'lat', 'lng')) }"
101
+
102
+ Add a new controller with a map_layer:
103
+
104
+ class PlacesController < ApplicationController
105
+
106
+ map_layer :place, :text => :placeName
107
+
108
+ end
109
+
110
+ And add a layer to the map:
111
+
112
+ page << map.addLayer(Layer::GeoRSS.new("GeoRSS", "/places/georss"))
113
+
114
+
115
+ Other types of served layers:
116
+
117
+ page << map.add_layer(Layer::GML.new("Places KML", "/places/kml", {:format=> JsExpr.new("OpenLayers.Format.KML")}))
118
+
119
+ page << map.add_layer(Layer::WFS.new("Places WFS", "/places/wfs", {:typename => "places"}, {:featureClass => JsExpr.new("OpenLayers.Feature.WFS")}))
120
+
121
+
122
+ ==Spatial database support
123
+
124
+ Using a spatial database requires GeoRuby[http://georuby.rubyforge.org/] and the Spatial Adapter for Rails:
125
+
126
+ sudo gem install georuby
127
+ ruby script/plugin install svn://rubyforge.org/var/svn/georuby/SpatialAdapter/trunk/spatial_adapter
128
+
129
+ Install spatial functions in your DB (e.g. Postgis 8.1):
130
+ DB=map_layers_dev
131
+ createlang plpgsql $DB
132
+ psql -d $DB -q -f /usr/share/postgresql-8.1-postgis/lwpostgis.sql
133
+
134
+ Create a model:
135
+ ./script/generate model --skip-timestamps --skip-fixture WeatherStation name:string geom:point
136
+ rake db:migrate
137
+
138
+ Import some weather stations:
139
+ ./script/runner "Geonames::Weather.weather(:north => 44.1, :south => -9.9, :east => -22.4, :west => 55.2).each { |st| WeatherStation.create(:name => st.stationName, :geom => Point.from_x_y(st.lng, st.lat)) }"
140
+
141
+ Add a new controller with a map_layer:
142
+
143
+ class WeatherStationsController < ApplicationController
144
+
145
+ map_layer :weather_stations, :geometry => :geom
146
+
147
+ end
148
+
149
+ And add a WFS layer to the map:
150
+
151
+ page << map.add_layer(Layer::WFS.new("Weather Stations", "/weather_stations/wfs", {:typename => "weather_stations"}, {:featureClass => JsExpr.new("OpenLayers.Feature.WFS")}))
152
+
153
+ ==License
154
+ The MapLayers plugin for Rails is released under the MIT license.
155
+
156
+ ==Support
157
+ For any questions, enhancement proposals, bug notifications or corrections visit http://rubyforge.org/projects/map-layers/ or send a mail to pka[at]sourcepole[dot]ch.
158
+
159
+
160
+ <em>Copyright (c) 2008 Pirmin Kalberer, Sourcepole AG</em>
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { "rspec2" }
data/init.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'map_layers'
2
+ require 'map_layers/view_helpers'
3
+
4
+ ActionController::Base.send(:include, MapLayers)
5
+ ActionView::Base.send(:include, MapLayers)
6
+ ActionView::Base.send(:include, MapLayers::ViewHelpers)
7
+
8
+ Mime::Type.register "application/vnd.google-earth.kml+xml", :kml
data/install.rb ADDED
@@ -0,0 +1,13 @@
1
+ # Workaround a problem with script/plugin and http-based repos.
2
+ # See http://dev.rubyonrails.org/ticket/8189
3
+ Dir.chdir(Dir.getwd.sub(/vendor.*/, '')) do
4
+
5
+ def copy_files(source_path, destination_path, plugin_root)
6
+ source, destination = File.join(File.expand_path(plugin_root), source_path), File.join(RAILS_ROOT, destination_path)
7
+ FileUtils.mkdir(destination) unless File.exist?(destination)
8
+ FileUtils.cp_r(source, destination)
9
+ end
10
+
11
+ #copy_files("/public/.", "/public", File.dirname(__FILE__))
12
+
13
+ end
data/lib/map_layers.rb ADDED
@@ -0,0 +1,358 @@
1
+ require 'active_support/core_ext'
2
+
3
+ module MapLayers # :nodoc:
4
+
5
+ #Include helpers in the given scope to AC and AV.
6
+ # def self.include_helpers(scope)
7
+ # ActiveSupport.on_load(:action_controller) do
8
+ # include scope::MapLayers
9
+ # end
10
+
11
+ # ActiveSupport.on_load(:action_view) do
12
+ # include scope::MapLayers
13
+ # include scope::MapLayers::ViewHelpers
14
+ # end
15
+ # end
16
+
17
+ # extend the class that include this with the methods in ClassMethods
18
+ def self.included(base)
19
+ base.extend(ClassMethods)
20
+ end
21
+
22
+ def map_layers_config
23
+ self.class.map_layers_config
24
+ end
25
+
26
+ module ClassMethods
27
+
28
+ def map_layer(model_id = nil, options = {})
29
+ options.assert_valid_keys(:id, :lat, :lon, :geometry, :text)
30
+
31
+ # converts Foo::BarController to 'bar' and FooBarsController to 'foo_bar' and AddressController to 'address'
32
+ model_id = self.to_s.split('::').last.sub(/Controller$/, '').pluralize.singularize.underscore unless model_id
33
+
34
+ # create the configuration
35
+ @map_layers_config = MapLayers::Config::new(model_id, options)
36
+
37
+ module_eval do
38
+ include MapLayers::KML
39
+ include MapLayers::WFS
40
+ include MapLayers::GeoRSS
41
+ include MapLayers::Proxy
42
+ include MapLayers::Rest
43
+ end
44
+
45
+ #session :off, :only => [:kml, :wfs, :georss]
46
+
47
+ end
48
+
49
+ def map_layers_config
50
+ @map_layers_config || self.superclass.instance_variable_get('@map_layers_config')
51
+ end
52
+
53
+ end
54
+
55
+
56
+ class Config
57
+ attr_reader :model_id, :id, :lat, :lon, :geometry, :text
58
+
59
+ def initialize(model_id, options)
60
+ @model_id = model_id.to_s.pluralize.singularize
61
+ @id = options[:id] || :id
62
+ @lat = options[:lat] || :lat
63
+ @lon = options[:lon] || :lng
64
+ @geometry = options[:geometry]
65
+ @text = options[:text] || :name
66
+ end
67
+
68
+ def model
69
+ @model ||= @model_id.to_s.camelize.constantize
70
+ end
71
+ end
72
+
73
+
74
+ class Feature < Struct.new(:text, :x, :y, :id)
75
+ attr_accessor :geometry
76
+ def self.from_geom(text, geom, id = nil)
77
+ f = new(text, geom.x, geom.y, id)
78
+ f.geometry = geom
79
+ f
80
+ end
81
+ end
82
+
83
+ # KML Server methods
84
+ module KML
85
+
86
+ # Publish layer in KML format
87
+ def kml
88
+ rows = map_layers_config.model.find(:all, :limit => KML_FEATURE_LIMIT)
89
+ @features = rows.collect do |row|
90
+ if map_layers_config.geometry
91
+ Feature.from_geom(row.send(map_layers_config.text), row.send(map_layers_config.geometry))
92
+ else
93
+ Feature.new(row.send(map_layers_config.text), row.send(map_layers_config.lon), row.send(map_layers_config.lat))
94
+ end
95
+ end
96
+ @folder_name = map_layers_config.model_id.to_s.pluralize.humanize
97
+ logger.info "MapLayers::KML: returning #{@features.size} features"
98
+ render :inline => KML_XML_ERB, :content_type => "text/xml"
99
+ rescue Exception => e
100
+ logger.error "MapLayers::KML: returning no features - Caught exception '#{e}'"
101
+ render :text => KML_EMPTY_RESPONSE, :content_type => "text/xml"
102
+ end
103
+
104
+ protected
105
+
106
+ KML_FEATURE_LIMIT = 1000
107
+
108
+ KML_XML_ERB = <<EOS # :nodoc:
109
+ <?xml version="1.0" encoding="UTF-8" ?>
110
+ <kml xmlns="http://earth.google.com/kml/2.0">
111
+ <Document>
112
+ <Folder><name><%= @folder_name %></name>
113
+ <% for feature in @features -%>
114
+ <Placemark>
115
+ <description><%= feature.text %></description>
116
+ <Point><coordinates><%= feature.x %>,<%= feature.y %></coordinates></Point>
117
+ </Placemark>
118
+ <% end -%>
119
+ </Folder>
120
+ </Document>
121
+ </kml>
122
+ EOS
123
+
124
+ KML_EMPTY_RESPONSE = <<EOS # :nodoc:
125
+ <?xml version="1.0" encoding="UTF-8" ?>
126
+ <kml xmlns="http://earth.google.com/kml/2.0">
127
+ <Document>
128
+ </Document>
129
+ </kml>
130
+ EOS
131
+
132
+ end
133
+
134
+ # WFS Server methods
135
+ module WFS
136
+
137
+ WGS84 = 4326
138
+
139
+ # Publish layer in WFS format
140
+ def wfs
141
+ minx, miny, maxx, maxy = extract_params
142
+ model = map_layers_config.model
143
+ if map_layers_config.geometry
144
+ db_srid = model.columns_hash[map_layers_config.geometry.to_s].srid
145
+ if db_srid != @srid && !db_srid.nil? && db_srid != -1
146
+ #Transform geometry from db_srid to requested srid (not possible for undefined db_srid)
147
+ geom = "Transform(#{geom},#{@srid}) AS #{geom}"
148
+ end
149
+
150
+ spatial_cond = if model.respond_to?(:sanitize_sql_hash_for_conditions)
151
+ model.sanitize_sql_hash_for_conditions(map_layers_config.geometry => [[minx, miny],[maxx, maxy], db_srid])
152
+ else # Rails < 2
153
+ model.sanitize_sql_hash(map_layers_config.geometry => [[minx, miny],[maxx, maxy], db_srid])
154
+ end
155
+ #spatial_cond = "Transform(#{spatial_cond}, #{db_srid}) )" Not necessary: bbox is always WGS84 !?
156
+
157
+ rows = model.find(:all, :conditions => spatial_cond, :limit => @maxfeatures)
158
+ @features = rows.collect do |row|
159
+ Feature.from_geom(row.send(map_layers_config.text), row.send(map_layers_config.geometry.to_s))
160
+ end
161
+ else
162
+ rows = model.find(:all, :limit => @maxfeatures)
163
+ @features = rows.collect do |row|
164
+ Feature.new(row.send(map_layers_config.text), row.send(map_layers_config.lon), row.send(map_layers_config.lat))
165
+ end
166
+ end
167
+ logger.info "MapLayers::WFS: returning #{@features.size} features"
168
+ render :inline => WFS_XML_ERB, :content_type => "text/xml"
169
+ rescue Exception => e
170
+ logger.error "MapLayers::WFS: returning no features - Caught exception '#{e}'"
171
+ render :text => WFS_EMPTY_RESPONSE, :content_type => "text/xml"
172
+ end
173
+
174
+ protected
175
+
176
+ WFS_FEATURE_LIMIT = 1000
177
+
178
+ def extract_params # :nodoc:
179
+ @maxfeatures = (params[:maxfeatures] || WFS_FEATURE_LIMIT).to_i
180
+ @srid = params['SRS'].split(/:/)[1].to_i rescue WGS84
181
+ req_bbox = params['BBOX'].split(/,/).collect {|n| n.to_f } rescue nil
182
+ @bbox = req_bbox || [-180.0, -90.0, 180.0, 90.0]
183
+ end
184
+
185
+ WFS_XML_ERB = <<EOS # :nodoc:
186
+ <?xml version='1.0' encoding="UTF-8" ?>
187
+ <wfs:FeatureCollection
188
+ xmlns:ms="http://mapserver.gis.umn.edu/mapserver"
189
+ xmlns:wfs="http://www.opengis.net/wfs"
190
+ xmlns:gml="http://www.opengis.net/gml"
191
+ xmlns:ogc="http://www.opengis.net/ogc"
192
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
193
+ xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengeospatial.net/wfs/1.0.0/WFS-basic.xsd
194
+ http://mapserver.gis.umn.edu/mapserver http://www.geopole.org/map/wfs?SERVICE=WFS&amp;VERSION=1.0.0&amp;REQUEST=DescribeFeatureType&amp;TYPENAME=geopole&amp;OUTPUTFORMAT=XMLSCHEMA">
195
+ <gml:boundedBy>
196
+ <gml:Box srsName="EPSG:<%= @srid %>">
197
+ <gml:coordinates><%= @bbox[0] %>,<%= @bbox[1] %> <%= @bbox[2] %>,<%= @bbox[3] %></gml:coordinates>
198
+ </gml:Box>
199
+ </gml:boundedBy>
200
+ <% for feature in @features -%>
201
+ <gml:featureMember>
202
+ <ms:geopole>
203
+ <gml:boundedBy>
204
+ <gml:Box srsName="EPSG:<%= @srid %>">
205
+ <gml:coordinates><%= feature.x %>,<%= feature.y %> <%= feature.x %>,<%= feature.y %></gml:coordinates>
206
+ </gml:Box>
207
+ </gml:boundedBy>
208
+ <ms:msGeometry>
209
+ <gml:Point srsName="EPSG:<%= @srid %>">
210
+ <gml:coordinates><%= feature.x %>,<%= feature.y %></gml:coordinates>
211
+ </gml:Point>
212
+ </ms:msGeometry>
213
+ <ms:text><%= feature.text %></ms:text>
214
+ </ms:geopole>
215
+ </gml:featureMember>
216
+ <% end -%>
217
+ </wfs:FeatureCollection>
218
+ EOS
219
+
220
+ WFS_EMPTY_RESPONSE = <<EOS # :nodoc:
221
+ <?xml version='1.0' encoding="UTF-8" ?>
222
+ <wfs:FeatureCollection
223
+ xmlns:wfs="http://www.opengis.net/wfs"
224
+ xmlns:gml="http://www.opengis.net/gml"
225
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
226
+ xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengeospatial.net/wfs/1.0.0/WFS-basic.xsd">
227
+ <gml:boundedBy>
228
+ <gml:null>missing</gml:null>
229
+ </gml:boundedBy>
230
+ </wfs:FeatureCollection>
231
+ EOS
232
+
233
+ end
234
+
235
+ # GeoRSS Server methods
236
+ # http://www.georss.org/1
237
+
238
+ module GeoRSS
239
+
240
+ # Publish layer in GeoRSS format
241
+ def georss
242
+ rows = map_layers_config.model.find(:all, :limit => GEORSS_FEATURE_LIMIT)
243
+ @features = rows.collect do |row|
244
+ if map_layers_config.geometry
245
+ Feature.from_geom(row.send(map_layers_config.text), row.send(map_layers_config.geometry), row.send(map_layers_config.id))
246
+ else
247
+ Feature.new(row.send(map_layers_config.text), row.send(map_layers_config.lon), row.send(map_layers_config.lat))
248
+ end
249
+ end
250
+ @base_url = "http://#{request.env["HTTP_HOST"]}/"
251
+ @item_url = "#{@base_url}#{map_layers_config.model_id.to_s.pluralize}"
252
+ @title = map_layers_config.model_id.to_s.pluralize.humanize
253
+ logger.info "MapLayers::GEORSS: returning #{@features.size} features"
254
+ render :inline => GEORSS_XML_ERB, :content_type => "text/xml"
255
+ rescue Exception => e
256
+ logger.error "MapLayers::GEORSS: returning no features - Caught exception '#{e}'"
257
+ render :text => GEORSS_EMPTY_RESPONSE, :content_type => "text/xml"
258
+ end
259
+
260
+ protected
261
+
262
+ GEORSS_FEATURE_LIMIT = 1000
263
+
264
+ GEORSS_XML_ERB = <<EOS # :nodoc:
265
+ <?xml version="1.0" encoding="UTF-8"?>
266
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
267
+ xmlns="http://purl.org/rss/1.0/"
268
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
269
+ xmlns:georss="http://www.georss.org/georss">
270
+ <docs>This is an RSS file. Copy the URL into your aggregator of choice. If you don't know what this means and want to learn more, please see: <span>http://platial.typepad.com/news/2006/04/really_simple_t.html</span> for more info.</docs>
271
+ <channel rdf:about="<%= @base_url %>">
272
+ <link><%= @base_url %></link>
273
+ <title><%= @title %></title>
274
+ <description></description>
275
+ <items>
276
+ <rdf:Seq>
277
+ <% for feature in @features -%>
278
+ <rdf:li resource="<%= @item_url %>/<%= feature.id %>"/>
279
+ <% end -%>
280
+ </rdf:Seq>
281
+ </items>
282
+ </channel>
283
+ <% ts=Time.now.rfc2822 -%>
284
+ <% for feature in @features -%>
285
+ <item rdf:about="<%= @item_url %>/<%= feature.id %>">
286
+ <!--<link><%= @item_url %>/<%= feature.id %></link>-->
287
+ <title><%= @title %></title>
288
+ <description><![CDATA[<%= feature.text %>]]></description>
289
+ <georss:point><%= feature.y %> <%= feature.x %></georss:point>
290
+ <dc:creator>map-layers</dc:creator>
291
+ <dc:date><%= ts %></dc:date>
292
+ </item>
293
+ <% end -%>
294
+ </rdf:RDF>
295
+ EOS
296
+
297
+ GEORSS_EMPTY_RESPONSE = <<EOS # :nodoc:
298
+ <?xml version="1.0" encoding="UTF-8"?>
299
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
300
+ xmlns="http://purl.org/rss/1.0/">
301
+ <docs></docs>
302
+ <channel rdf:about="http://purl.org/rss/1.0/">
303
+ <link>http://purl.org/rss/1.0/</link>
304
+ <title>Empty GeoRSS</title>
305
+ <description></description>
306
+ <items>
307
+ <rdf:Seq>
308
+ </rdf:Seq>
309
+ </items>
310
+ </channel>
311
+ </rdf:RDF>
312
+ EOS
313
+
314
+ end
315
+
316
+ # Remote http Proxy
317
+ module Proxy
318
+
319
+ # Register an url, before the proxy is called
320
+ def register_remote_url(url)
321
+ session[:proxy_url] ||= []
322
+ session[:proxy_url] << url
323
+ end
324
+
325
+ # Proxy for accessing remote files like GeoRSS, which is not allowed directly from the browser
326
+ def proxy
327
+ if session[:proxy_url].nil? || !session[:proxy_url].include?(params["url"])
328
+ logger.warn "Proxy request not in session: #{params["url"]}"
329
+ render :nothing => true
330
+ return
331
+ end
332
+
333
+ url = URI.parse(URI.encode(params[:url]))
334
+ logger.debug "Proxy request for #{url.scheme}://#{url.host}#{url.path}"
335
+
336
+ result = Net::HTTP.get_response(url)
337
+ render :text => result.body, :status => result.code, :content_type => "text/xml"
338
+ end
339
+ end
340
+
341
+ # Restful feture Server methods (http://featureserver.org/)
342
+ module Rest
343
+
344
+ def index
345
+ respond_to do |format|
346
+ format.xml { wfs }
347
+ format.kml { kml }
348
+ end
349
+ end
350
+
351
+ end
352
+
353
+ end
354
+
355
+ require 'map_layers/version'
356
+ require 'map_layers/js_wrapper'
357
+ require 'map_layers/open_layers'
358
+ require 'map_layers/map'