]> git.openstreetmap.org Git - rails.git/blob - app/controllers/diary_entries_controller.rb
Merge remote-tracking branch 'upstream/pull/4517'
[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     diary_entry.subscriptions.create(:user => current_user) unless diary_entry.subscribers.exists?(current_user.id)
163
164     redirect_to diary_entry_path(diary_entry.user, diary_entry)
165   rescue ActiveRecord::RecordNotFound
166     render :action => "no_such_entry", :status => :not_found
167   end
168
169   def unsubscribe
170     diary_entry = DiaryEntry.find(params[:id])
171
172     diary_entry.subscriptions.where(:user => current_user).delete_all if diary_entry.subscribers.exists?(current_user.id)
173
174     redirect_to diary_entry_path(diary_entry.user, diary_entry)
175   rescue ActiveRecord::RecordNotFound
176     render :action => "no_such_entry", :status => :not_found
177   end
178
179   def rss
180     if params[:display_name]
181       user = User.active.find_by(:display_name => params[:display_name])
182
183       if user
184         @entries = user.diary_entries
185         @title = t("diary_entries.feed.user.title", :user => user.display_name)
186         @description = t("diary_entries.feed.user.description", :user => user.display_name)
187         @link = url_for :action => "index", :display_name => user.display_name, :host => Settings.server_url, :protocol => Settings.server_protocol
188       else
189         head :not_found
190         return
191       end
192     else
193       @entries = DiaryEntry.joins(:user).where(:users => { :status => %w[active confirmed] })
194
195       # Items can't be flagged as deleted in the RSS format.
196       # For the general feeds, allow a delay before publishing, to help spam fighting
197       @entries = @entries.where("created_at < :time", :time => Settings.diary_feed_delay.hours.ago)
198
199       if params[:language]
200         @entries = @entries.where(:language_code => params[:language])
201         @title = t("diary_entries.feed.language.title", :language_name => Language.find(params[:language]).english_name)
202         @description = t("diary_entries.feed.language.description", :language_name => Language.find(params[:language]).english_name)
203         @link = url_for :action => "index", :language => params[:language], :host => Settings.server_url, :protocol => Settings.server_protocol
204       else
205         @title = t("diary_entries.feed.all.title")
206         @description = t("diary_entries.feed.all.description")
207         @link = url_for :action => "index", :host => Settings.server_url, :protocol => Settings.server_protocol
208       end
209     end
210     @entries = @entries.visible.includes(:user).order("created_at DESC").limit(20)
211   end
212
213   def hide
214     entry = DiaryEntry.find(params[:id])
215     entry.update(:visible => false)
216     redirect_to :action => "index", :display_name => entry.user.display_name
217   end
218
219   def unhide
220     entry = DiaryEntry.find(params[:id])
221     entry.update(:visible => true)
222     redirect_to :action => "index", :display_name => entry.user.display_name
223   end
224
225   def hidecomment
226     comment = DiaryComment.find(params[:comment])
227     comment.update(:visible => false)
228     redirect_to diary_entry_path(comment.diary_entry.user, comment.diary_entry)
229   end
230
231   def unhidecomment
232     comment = DiaryComment.find(params[:comment])
233     comment.update(:visible => true)
234     redirect_to diary_entry_path(comment.diary_entry.user, comment.diary_entry)
235   end
236
237   def comments
238     @title = t ".title", :user => @user.display_name
239
240     comments = DiaryComment.where(:user => @user)
241     comments = comments.visible unless can? :unhidecomment, DiaryEntry
242
243     @params = params.permit(:display_name, :before, :after)
244
245     @comments, @newer_comments_id, @older_comments_id = get_page_items(comments, [:user])
246   end
247
248   private
249
250   ##
251   # return permitted diary entry parameters
252   def entry_params
253     params.require(:diary_entry).permit(:title, :body, :language_code, :latitude, :longitude)
254   rescue ActionController::ParameterMissing
255     ActionController::Parameters.new.permit(:title, :body, :language_code, :latitude, :longitude)
256   end
257
258   ##
259   # return permitted diary comment parameters
260   def comment_params
261     params.require(:diary_comment).permit(:body)
262   end
263
264   ##
265   # decide on a location for the diary entry map
266   def set_map_location
267     if @diary_entry.latitude && @diary_entry.longitude
268       @lon = @diary_entry.longitude
269       @lat = @diary_entry.latitude
270       @zoom = 12
271     elsif !current_user.home_location?
272       @lon = params[:lon] || -0.1
273       @lat = params[:lat] || 51.5
274       @zoom = params[:zoom] || 4
275     else
276       @lon = current_user.home_lon
277       @lat = current_user.home_lat
278       @zoom = 12
279     end
280   end
281
282   def get_page_items(items, includes)
283     id_column = "#{items.table_name}.id"
284     page_items = if params[:before]
285                    items.where("#{id_column} < ?", params[:before]).order(:id => :desc)
286                  elsif params[:after]
287                    items.where("#{id_column} > ?", params[:after]).order(:id => :asc)
288                  else
289                    items.order(:id => :desc)
290                  end
291
292     page_items = page_items.limit(20)
293     page_items = page_items.includes(includes)
294     page_items = page_items.sort.reverse
295
296     newer_items_id = page_items.first.id if page_items.count.positive? && items.exists?(["#{id_column} > ?", page_items.first.id])
297     older_items_id = page_items.last.id if page_items.count.positive? && items.exists?(["#{id_column} < ?", page_items.last.id])
298
299     [page_items, newer_items_id, older_items_id]
300   end
301 end