]> git.openstreetmap.org Git - rails.git/blob - app/controllers/diary_entries_controller.rb
Add a limit on the number of points in a GPS trace
[rails.git] / app / controllers / diary_entries_controller.rb
1 class DiaryEntriesController < ApplicationController
2   include UserMethods
3
4   layout "site", :except => :rss
5
6   before_action :authorize_web
7   before_action :set_locale
8   before_action :check_database_readable
9
10   authorize_resource
11
12   before_action :lookup_user, :only => [:show, :comments]
13   before_action :check_database_writable, :only => [:new, :create, :edit, :update, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
14   before_action :allow_thirdparty_images, :only => [:new, :create, :edit, :update, :index, :show, :comments]
15
16   def index
17     if params[:display_name]
18       @user = User.active.find_by(:display_name => params[:display_name])
19
20       if @user
21         @title = t ".user_title", :user => @user.display_name
22         entries = @user.diary_entries
23       else
24         render_unknown_user params[:display_name]
25         return
26       end
27     elsif params[:friends]
28       if current_user
29         @title = t ".title_friends"
30         entries = DiaryEntry.where(:user => current_user.friends)
31       else
32         require_user
33         return
34       end
35     elsif params[:nearby]
36       if current_user
37         @title = t ".title_nearby"
38         entries = DiaryEntry.where(:user => current_user.nearby)
39       else
40         require_user
41         return
42       end
43     else
44       entries = DiaryEntry.joins(:user).where(:users => { :status => %w[active confirmed] })
45
46       if params[:language]
47         @title = t ".in_language_title", :language => Language.find(params[:language]).english_name
48         entries = entries.where(:language_code => params[:language])
49       else
50         candidate_codes = preferred_languages.flat_map(&:candidates).uniq.map(&:to_s)
51         @languages = Language.where(:code => candidate_codes).in_order_of(:code, candidate_codes)
52         @title = t ".title"
53       end
54     end
55
56     entries = entries.visible unless can? :unhide, DiaryEntry
57
58     @params = params.permit(:display_name, :friends, :nearby, :language)
59
60     @entries, @newer_entries_id, @older_entries_id = get_page_items(entries, [:user, :language])
61   end
62
63   def show
64     entries = @user.diary_entries
65     entries = entries.visible unless can? :unhide, DiaryEntry
66     @entry = entries.find_by(:id => params[:id])
67     if @entry
68       @title = t ".title", :user => params[:display_name], :title => @entry.title
69       @comments = can?(:unhidecomment, DiaryEntry) ? @entry.comments : @entry.visible_comments
70     else
71       @title = t "diary_entries.no_such_entry.title", :id => params[:id]
72       render :action => "no_such_entry", :status => :not_found
73     end
74   end
75
76   def new
77     @title = t ".title"
78
79     default_lang = current_user.preferences.find_by(:k => "diary.default_language")
80     lang_code = default_lang ? default_lang.v : current_user.preferred_language
81     @diary_entry = DiaryEntry.new(entry_params.merge(:language_code => lang_code))
82     set_map_location
83     render :action => "new"
84   end
85
86   def edit
87     @title = t ".title"
88     @diary_entry = DiaryEntry.find(params[:id])
89
90     redirect_to diary_entry_path(@diary_entry.user, @diary_entry) if current_user != @diary_entry.user
91
92     set_map_location
93   rescue ActiveRecord::RecordNotFound
94     render :action => "no_such_entry", :status => :not_found
95   end
96
97   def create
98     @title = t "diary_entries.new.title"
99
100     @diary_entry = DiaryEntry.new(entry_params)
101     @diary_entry.user = current_user
102
103     if @diary_entry.save
104       default_lang = current_user.preferences.find_by(:k => "diary.default_language")
105       if default_lang
106         default_lang.v = @diary_entry.language_code
107         default_lang.save!
108       else
109         current_user.preferences.create(:k => "diary.default_language", :v => @diary_entry.language_code)
110       end
111
112       # Subscribe user to diary comments
113       @diary_entry.subscriptions.create(:user => current_user)
114
115       redirect_to :action => "index", :display_name => current_user.display_name
116     else
117       render :action => "new"
118     end
119   end
120
121   def update
122     @title = t "diary_entries.edit.title"
123     @diary_entry = DiaryEntry.find(params[:id])
124
125     if current_user != @diary_entry.user ||
126        (params[:diary_entry] && @diary_entry.update(entry_params))
127       redirect_to diary_entry_path(@diary_entry.user, @diary_entry)
128     else
129       set_map_location
130       render :action => "edit"
131     end
132   rescue ActiveRecord::RecordNotFound
133     render :action => "no_such_entry", :status => :not_found
134   end
135
136   def comment
137     @entry = DiaryEntry.find(params[:id])
138     @comments = @entry.visible_comments
139     @diary_comment = @entry.comments.build(comment_params)
140     @diary_comment.user = current_user
141     if @diary_comment.save
142
143       # Notify current subscribers of the new comment
144       @entry.subscribers.visible.each do |user|
145         UserMailer.diary_comment_notification(@diary_comment, user).deliver_later if current_user != user
146       end
147
148       # Add the commenter to the subscribers if necessary
149       @entry.subscriptions.create(:user => current_user) unless @entry.subscribers.exists?(current_user.id)
150
151       redirect_to diary_entry_path(@entry.user, @entry)
152     else
153       render :action => "show"
154     end
155   rescue ActiveRecord::RecordNotFound
156     render :action => "no_such_entry", :status => :not_found
157   end
158
159   def subscribe
160     @diary_entry = DiaryEntry.find(params[:id])
161
162     if request.post?
163       @diary_entry.subscriptions.create(:user => current_user) unless @diary_entry.subscribers.exists?(current_user.id)
164
165       redirect_to diary_entry_path(@diary_entry.user, @diary_entry)
166     end
167   rescue ActiveRecord::RecordNotFound
168     render :action => "no_such_entry", :status => :not_found
169   end
170
171   def unsubscribe
172     @diary_entry = DiaryEntry.find(params[:id])
173
174     if request.post?
175       @diary_entry.subscriptions.where(:user => current_user).delete_all if @diary_entry.subscribers.exists?(current_user.id)
176
177       redirect_to diary_entry_path(@diary_entry.user, @diary_entry)
178     end
179   rescue ActiveRecord::RecordNotFound
180     render :action => "no_such_entry", :status => :not_found
181   end
182
183   def rss
184     if params[:display_name]
185       user = User.active.find_by(:display_name => params[:display_name])
186
187       if user
188         @entries = user.diary_entries
189         @title = t("diary_entries.feed.user.title", :user => user.display_name)
190         @description = t("diary_entries.feed.user.description", :user => user.display_name)
191         @link = url_for :action => "index", :display_name => user.display_name, :host => Settings.server_url, :protocol => Settings.server_protocol
192       else
193         head :not_found
194         return
195       end
196     else
197       @entries = DiaryEntry.joins(:user).where(:users => { :status => %w[active confirmed] })
198
199       # Items can't be flagged as deleted in the RSS format.
200       # For the general feeds, allow a delay before publishing, to help spam fighting
201       @entries = @entries.where("created_at < :time", :time => Settings.diary_feed_delay.hours.ago)
202
203       if params[:language]
204         @entries = @entries.where(:language_code => params[:language])
205         @title = t("diary_entries.feed.language.title", :language_name => Language.find(params[:language]).english_name)
206         @description = t("diary_entries.feed.language.description", :language_name => Language.find(params[:language]).english_name)
207         @link = url_for :action => "index", :language => params[:language], :host => Settings.server_url, :protocol => Settings.server_protocol
208       else
209         @title = t("diary_entries.feed.all.title")
210         @description = t("diary_entries.feed.all.description")
211         @link = url_for :action => "index", :host => Settings.server_url, :protocol => Settings.server_protocol
212       end
213     end
214     @entries = @entries.visible.includes(:user).order("created_at DESC").limit(20)
215   end
216
217   def hide
218     entry = DiaryEntry.find(params[:id])
219     entry.update(:visible => false)
220     redirect_to :action => "index", :display_name => entry.user.display_name
221   end
222
223   def unhide
224     entry = DiaryEntry.find(params[:id])
225     entry.update(:visible => true)
226     redirect_to :action => "index", :display_name => entry.user.display_name
227   end
228
229   def hidecomment
230     comment = DiaryComment.find(params[:comment])
231     comment.update(:visible => false)
232     redirect_to diary_entry_path(comment.diary_entry.user, comment.diary_entry)
233   end
234
235   def unhidecomment
236     comment = DiaryComment.find(params[:comment])
237     comment.update(:visible => true)
238     redirect_to diary_entry_path(comment.diary_entry.user, comment.diary_entry)
239   end
240
241   def comments
242     @title = t ".title", :user => @user.display_name
243
244     comments = DiaryComment.where(:user => @user)
245     comments = comments.visible unless can? :unhidecomment, DiaryEntry
246
247     @params = params.permit(:display_name, :before, :after)
248
249     @comments, @newer_comments_id, @older_comments_id = get_page_items(comments, [:user])
250   end
251
252   private
253
254   ##
255   # return permitted diary entry parameters
256   def entry_params
257     params.require(:diary_entry).permit(:title, :body, :language_code, :latitude, :longitude)
258   rescue ActionController::ParameterMissing
259     ActionController::Parameters.new.permit(:title, :body, :language_code, :latitude, :longitude)
260   end
261
262   ##
263   # return permitted diary comment parameters
264   def comment_params
265     params.require(:diary_comment).permit(:body)
266   end
267
268   ##
269   # decide on a location for the diary entry map
270   def set_map_location
271     if @diary_entry.latitude && @diary_entry.longitude
272       @lon = @diary_entry.longitude
273       @lat = @diary_entry.latitude
274       @zoom = 12
275     elsif !current_user.home_location?
276       @lon = params[:lon] || -0.1
277       @lat = params[:lat] || 51.5
278       @zoom = params[:zoom] || 4
279     else
280       @lon = current_user.home_lon
281       @lat = current_user.home_lat
282       @zoom = 12
283     end
284   end
285
286   def get_page_items(items, includes)
287     id_column = "#{items.table_name}.id"
288     page_items = if params[:before]
289                    items.where("#{id_column} < ?", params[:before]).order(:id => :desc)
290                  elsif params[:after]
291                    items.where("#{id_column} > ?", params[:after]).order(:id => :asc)
292                  else
293                    items.order(:id => :desc)
294                  end
295
296     page_items = page_items.limit(20)
297     page_items = page_items.includes(includes)
298     page_items = page_items.sort.reverse
299
300     newer_items_id = page_items.first.id if page_items.count.positive? && items.exists?(["#{id_column} > ?", page_items.first.id])
301     older_items_id = page_items.last.id if page_items.count.positive? && items.exists?(["#{id_column} < ?", page_items.last.id])
302
303     [page_items, newer_items_id, older_items_id]
304   end
305 end