1 class NoteController < ApplicationController
3 layout 'site', :only => [:mine]
5 before_filter :check_api_readable
6 before_filter :authorize_web, :only => [:create, :close, :update, :delete, :mine]
7 before_filter :check_api_writable, :only => [:create, :close, :update, :delete]
8 before_filter :set_locale, :only => [:mine]
9 after_filter :compress_output
10 around_filter :api_call_handle_error, :api_call_timeout
12 # Help methods for checking boundary sanity and area size
16 # Return a list of notes in a given area
18 # Figure out the bbox - we prefer a bbox argument but also
19 # support the old, deprecated, method with four arguments
21 bbox = BoundingBox.from_bbox_params(params)
23 raise OSM::APIBadUserInput.new("No l was given") unless params[:l]
24 raise OSM::APIBadUserInput.new("No r was given") unless params[:r]
25 raise OSM::APIBadUserInput.new("No b was given") unless params[:b]
26 raise OSM::APIBadUserInput.new("No t was given") unless params[:t]
28 bbox = BoundingBox.from_lrbt_params(params)
31 # Get the sanitised boundaries
32 @min_lon, @min_lat, @max_lon, @max_lat = sanitise_boundaries(bbox)
34 # Get any conditions that need to be applied
35 notes = closed_condition(Note.scoped)
37 # Check that the boundaries are valid
40 # Check the the bounding box is not too big
41 bbox.check_size(MAX_NOTE_REQUEST_AREA)
43 # Find the notes we want to return
44 @notes = notes.bbox(bbox).order("updated_at DESC").limit(result_limit).preload(:comments)
47 respond_to do |format|
58 # Check the arguments are sane
59 raise OSM::APIBadUserInput.new("No lat was given") unless params[:lat]
60 raise OSM::APIBadUserInput.new("No lon was given") unless params[:lon]
61 raise OSM::APIBadUserInput.new("No text was given") unless params[:text]
63 # Extract the arguments
64 lon = params[:lon].to_f
65 lat = params[:lat].to_f
66 comment = params[:text]
69 # Include in a transaction to ensure that there is always a note_comment for every note
72 @note = Note.create(:lat => lat, :lon => lon)
73 raise OSM::APIBadUserInput.new("The note is outside this world") unless @note.in_world?
75 #TODO: move this into a helper function
77 url = "http://nominatim.openstreetmap.org/reverse?lat=" + lat.to_s + "&lon=" + lon.to_s + "&zoom=16"
78 response = REXML::Document.new(Net::HTTP.get(URI.parse(url)))
80 if result = response.get_text("reversegeocode/result")
81 @note.nearby_place = result.to_s
83 @note.nearby_place = "unknown"
85 rescue Exception => err
86 @note.nearby_place = "unknown"
92 # Add a comment to the note
93 add_comment(@note, comment, name, "opened")
101 # Add a comment to an existing note
103 # Check the arguments are sane
104 raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
105 raise OSM::APIBadUserInput.new("No text was given") unless params[:text]
107 # Extract the arguments
108 id = params[:id].to_i
109 comment = params[:text]
110 name = params[:name] or "NoName"
112 # Find the note and check it is valid
114 raise OSM::APINotFoundError unless note
115 raise OSM::APIAlreadyDeletedError unless note.visible?
117 # Add a comment to the note
119 add_comment(note, comment, name, "commented")
122 # Send an OK response
129 # Check the arguments are sane
130 raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
132 # Extract the arguments
133 id = params[:id].to_i
136 # Find the note and check it is valid
137 note = Note.find_by_id(id)
138 raise OSM::APINotFoundError unless note
139 raise OSM::APIAlreadyDeletedError unless note.visible?
141 # Close the note and add a comment
145 add_comment(note, nil, name, "closed")
148 # Send an OK response
153 # Get a feed of recent notes and comments
155 # Get any conditions that need to be applied
156 notes = closed_condition(Note.scoped)
160 bbox = BoundingBox.from_bbox_params(params)
162 bbox.check_boundaries
163 bbox.check_size(MAX_NOTE_REQUEST_AREA)
165 notes = notes.bbox(bbox)
168 # Find the comments we want to return
169 @comments = NoteComment.where(:note => notes).order("created_at DESC").limit(result_limit).include(:note)
172 respond_to do |format|
180 # Check the arguments are sane
181 raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
183 # Find the note and check it is valid
184 @note = Note.find(params[:id])
185 raise OSM::APINotFoundError unless @note
186 raise OSM::APIAlreadyDeletedError unless @note.visible?
189 respond_to do |format|
198 # Delete (hide) a note
200 # Check the arguments are sane
201 raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
203 # Extract the arguments
204 id = params[:id].to_i
207 # Find the note and check it is valid
209 raise OSM::APINotFoundError unless note
210 raise OSM::APIAlreadyDeletedError unless note.visible?
212 # Mark the note as hidden
214 note.status = "hidden"
217 add_comment(note, nil, name, "hidden")
221 render :text => "ok\n", :content_type => "text/html"
225 # Return a list of notes matching a given string
227 # Check the arguments are sane
228 raise OSM::APIBadUserInput.new("No query string was given") unless params[:q]
230 # Get any conditions that need to be applied
231 conditions = closed_condition
232 conditions = cond_merge conditions, ['note_comments.body ~ ?', params[:q]]
234 # Find the notes we want to return
235 @notes = Note.find(:all,
236 :conditions => conditions,
237 :order => "updated_at DESC",
238 :limit => result_limit,
240 :include => :comments)
243 respond_to do |format|
244 format.html { render :action => :list, :format => :rjs, :content_type => "text/javascript"}
245 format.rss { render :action => :list }
247 format.xml { render :action => :list }
248 format.json { render :action => :list }
249 format.gpx { render :action => :list }
254 if params[:display_name]
255 @user2 = User.find_by_display_name(params[:display_name], :conditions => { :status => ["active", "confirmed"] })
258 if @user2.data_public? or @user2 == @user
259 conditions = ['note_comments.author_id = ?', @user2.id]
261 conditions = ['false']
263 else #if request.format == :html
264 @title = t 'user.no_such_user.title'
265 @not_found_user = params[:display_name]
266 render :template => 'user/no_such_user', :status => :not_found
272 user_link = render_to_string :partial => "user", :object => @user2
275 @title = t 'note.mine.title', :user => @user2.display_name
276 @heading = t 'note.mine.heading', :user => @user2.display_name
277 @description = t 'note.mine.description', :user => user_link
279 @page = (params[:page] || 1).to_i
282 @notes = Note.find(:all,
283 :include => [:comments, {:comments => :author}],
285 :order => "updated_at DESC",
286 :conditions => conditions,
287 :offset => (@page - 1) * @page_size,
288 :limit => @page_size).uniq
292 #------------------------------------------------------------
293 # utility functions below.
294 #------------------------------------------------------------
297 # Render an OK response
299 if params[:format] == "js"
300 render :text => "osbResponse();", :content_type => "text/javascript"
302 render :text => "ok " + @note.id.to_s + "\n", :content_type => "text/plain" if @note
303 render :text => "ok\n", :content_type => "text/plain" unless @note
308 # Get the maximum number of results to return
310 if params[:limit] and params[:limit].to_i > 0 and params[:limit].to_i < 10000
318 # Generate a condition to choose which bugs we want based
319 # on their status and the user's request parameters
320 def closed_condition(notes)
322 closed_since = params[:closed].to_i
328 notes = notes.where("status != 'hidden'")
329 elsif closed_since > 0
330 notes = notes.where("(status = 'open' OR (status = 'closed' AND closed_at > '#{Time.now - closed_since.days}'))")
332 notes = notes.where("status = 'open'")
339 # Add a comment to a note
340 def add_comment(note, text, name, event)
341 name = "NoName" if name.nil?
343 attributes = { :visible => true, :event => event, :body => text }
346 attributes[:author_id] = @user.id
347 attributes[:author_name] = @user.display_name
349 attributes[:author_ip] = request.remote_ip
350 attributes[:author_name] = name + " (a)"
353 note.comments.create(attributes)
355 note.comments.map { |c| c.author }.uniq.each do |user|
356 if user and user != @user
357 Notifier.deliver_note_comment_notification(comment, user)