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
13 # Return a list of notes in a given area
15 # Figure out the bbox - we prefer a bbox argument but also
16 # support the old, deprecated, method with four arguments
18 bbox = BoundingBox.from_bbox_params(params)
20 raise OSM::APIBadUserInput.new("No l was given") unless params[:l]
21 raise OSM::APIBadUserInput.new("No r was given") unless params[:r]
22 raise OSM::APIBadUserInput.new("No b was given") unless params[:b]
23 raise OSM::APIBadUserInput.new("No t was given") unless params[:t]
25 bbox = BoundingBox.from_lrbt_params(params)
28 # Get the sanitised boundaries
29 @min_lon, @min_lat, @max_lon, @max_lat = sanitise_boundaries(bbox)
31 # Get any conditions that need to be applied
32 notes = closed_condition(Note.scoped)
34 # Check that the boundaries are valid
37 # Check the the bounding box is not too big
38 bbox.check_size(MAX_NOTE_REQUEST_AREA)
40 # Find the notes we want to return
41 @notes = notes.bbox(bbox).order("updated_at DESC").limit(result_limit).preload(:comments)
44 respond_to do |format|
55 # Check the arguments are sane
56 raise OSM::APIBadUserInput.new("No lat was given") unless params[:lat]
57 raise OSM::APIBadUserInput.new("No lon was given") unless params[:lon]
58 raise OSM::APIBadUserInput.new("No text was given") unless params[:text]
60 # Extract the arguments
61 lon = params[:lon].to_f
62 lat = params[:lat].to_f
63 comment = params[:text]
66 # Include in a transaction to ensure that there is always a note_comment for every note
69 @note = Note.create(:lat => lat, :lon => lon)
70 raise OSM::APIBadUserInput.new("The note is outside this world") unless @note.in_world?
72 #TODO: move this into a helper function
74 url = "http://nominatim.openstreetmap.org/reverse?lat=" + lat.to_s + "&lon=" + lon.to_s + "&zoom=16"
75 response = REXML::Document.new(Net::HTTP.get(URI.parse(url)))
77 if result = response.get_text("reversegeocode/result")
78 @note.nearby_place = result.to_s
80 @note.nearby_place = "unknown"
82 rescue Exception => err
83 @note.nearby_place = "unknown"
89 # Add a comment to the note
90 add_comment(@note, comment, name, "opened")
98 # Add a comment to an existing note
100 # Check the arguments are sane
101 raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
102 raise OSM::APIBadUserInput.new("No text was given") unless params[:text]
104 # Extract the arguments
105 id = params[:id].to_i
106 comment = params[:text]
107 name = params[:name] or "NoName"
109 # Find the note and check it is valid
111 raise OSM::APINotFoundError unless note
112 raise OSM::APIAlreadyDeletedError unless note.visible?
114 # Add a comment to the note
116 add_comment(note, comment, name, "commented")
119 # Send an OK response
126 # Check the arguments are sane
127 raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
129 # Extract the arguments
130 id = params[:id].to_i
133 # Find the note and check it is valid
134 note = Note.find_by_id(id)
135 raise OSM::APINotFoundError unless note
136 raise OSM::APIAlreadyDeletedError unless note.visible?
138 # Close the note and add a comment
142 add_comment(note, nil, name, "closed")
145 # Send an OK response
150 # Get a feed of recent notes and comments
152 # Get any conditions that need to be applied
153 notes = closed_condition(Note.scoped)
157 bbox = BoundingBox.from_bbox_params(params)
159 bbox.check_boundaries
160 bbox.check_size(MAX_NOTE_REQUEST_AREA)
162 notes = notes.bbox(bbox)
165 # Find the comments we want to return
166 @comments = NoteComment.where(:note => notes).order("created_at DESC").limit(result_limit).include(:note)
169 respond_to do |format|
177 # Check the arguments are sane
178 raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
180 # Find the note and check it is valid
181 @note = Note.find(params[:id])
182 raise OSM::APINotFoundError unless @note
183 raise OSM::APIAlreadyDeletedError unless @note.visible?
186 respond_to do |format|
195 # Delete (hide) a note
197 # Check the arguments are sane
198 raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
200 # Extract the arguments
201 id = params[:id].to_i
204 # Find the note and check it is valid
206 raise OSM::APINotFoundError unless note
207 raise OSM::APIAlreadyDeletedError unless note.visible?
209 # Mark the note as hidden
211 note.status = "hidden"
214 add_comment(note, nil, name, "hidden")
218 render :text => "ok\n", :content_type => "text/html"
222 # Return a list of notes matching a given string
224 # Check the arguments are sane
225 raise OSM::APIBadUserInput.new("No query string was given") unless params[:q]
227 # Get any conditions that need to be applied
228 conditions = closed_condition
229 conditions = cond_merge conditions, ['note_comments.body ~ ?', params[:q]]
231 # Find the notes we want to return
232 @notes = Note.find(:all,
233 :conditions => conditions,
234 :order => "updated_at DESC",
235 :limit => result_limit,
237 :include => :comments)
240 respond_to do |format|
241 format.html { render :action => :list, :format => :rjs, :content_type => "text/javascript"}
242 format.rss { render :action => :list }
244 format.xml { render :action => :list }
245 format.json { render :action => :list }
246 format.gpx { render :action => :list }
251 if params[:display_name]
252 @user2 = User.find_by_display_name(params[:display_name], :conditions => { :status => ["active", "confirmed"] })
255 if @user2.data_public? or @user2 == @user
256 conditions = ['note_comments.author_id = ?', @user2.id]
258 conditions = ['false']
260 else #if request.format == :html
261 @title = t 'user.no_such_user.title'
262 @not_found_user = params[:display_name]
263 render :template => 'user/no_such_user', :status => :not_found
269 user_link = render_to_string :partial => "user", :object => @user2
272 @title = t 'note.mine.title', :user => @user2.display_name
273 @heading = t 'note.mine.heading', :user => @user2.display_name
274 @description = t 'note.mine.description', :user => user_link
276 @page = (params[:page] || 1).to_i
279 @notes = Note.find(:all,
280 :include => [:comments, {:comments => :author}],
282 :order => "updated_at DESC",
283 :conditions => conditions,
284 :offset => (@page - 1) * @page_size,
285 :limit => @page_size).uniq
289 #------------------------------------------------------------
290 # utility functions below.
291 #------------------------------------------------------------
294 # Render an OK response
296 if params[:format] == "js"
297 render :text => "osbResponse();", :content_type => "text/javascript"
299 render :text => "ok " + @note.id.to_s + "\n", :content_type => "text/plain" if @note
300 render :text => "ok\n", :content_type => "text/plain" unless @note
305 # Get the maximum number of results to return
307 if params[:limit] and params[:limit].to_i > 0 and params[:limit].to_i < 10000
315 # Generate a condition to choose which bugs we want based
316 # on their status and the user's request parameters
317 def closed_condition(notes)
319 closed_since = params[:closed].to_i
325 notes = notes.where("status != 'hidden'")
326 elsif closed_since > 0
327 notes = notes.where("(status = 'open' OR (status = 'closed' AND closed_at > '#{Time.now - closed_since.days}'))")
329 notes = notes.where("status = 'open'")
336 # Add a comment to a note
337 def add_comment(note, text, name, event)
338 name = "NoName" if name.nil?
340 attributes = { :visible => true, :event => event, :body => text }
343 attributes[:author_id] = @user.id
344 attributes[:author_name] = @user.display_name
346 attributes[:author_ip] = request.remote_ip
347 attributes[:author_name] = name + " (a)"
350 note.comments.create(attributes)
352 note.comments.map { |c| c.author }.uniq.each do |user|
353 if user and user != @user
354 Notifier.deliver_note_comment_notification(comment, user)