map_layers 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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'