aboutsummaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/controllers/admin_request_controller.rb5
-rw-r--r--app/controllers/comment_controller.rb7
-rw-r--r--app/controllers/holiday_controller.rb4
-rw-r--r--app/models/application_mailer.rb123
-rw-r--r--app/models/censor_rule.rb4
-rw-r--r--app/models/holiday.rb56
-rw-r--r--app/models/info_request.rb10
-rw-r--r--app/models/public_body.rb41
-rw-r--r--app/models/request_classification.rb14
-rw-r--r--app/models/user.rb8
-rw-r--r--app/views/admin_request/edit.rhtml4
-rw-r--r--app/views/request/_after_actions.rhtml8
-rw-r--r--app/views/request/_sidebar.rhtml8
-rw-r--r--app/views/track/_tracking_links.rhtml10
14 files changed, 237 insertions, 65 deletions
diff --git a/app/controllers/admin_request_controller.rb b/app/controllers/admin_request_controller.rb
index 7cf23e61e..53ff2957b 100644
--- a/app/controllers/admin_request_controller.rb
+++ b/app/controllers/admin_request_controller.rb
@@ -71,6 +71,7 @@ class AdminRequestController < AdminController
old_allow_new_responses_from = @info_request.allow_new_responses_from
old_handle_rejected_responses = @info_request.handle_rejected_responses
old_tag_string = @info_request.tag_string
+ old_comments_allowed = @info_request.comments_allowed
@info_request.title = params[:info_request][:title]
@info_request.prominence = params[:info_request][:prominence]
@@ -81,6 +82,7 @@ class AdminRequestController < AdminController
@info_request.allow_new_responses_from = params[:info_request][:allow_new_responses_from]
@info_request.handle_rejected_responses = params[:info_request][:handle_rejected_responses]
@info_request.tag_string = params[:info_request][:tag_string]
+ @info_request.comments_allowed = params[:info_request][:comments_allowed] == "true" ? true : false
if @info_request.valid?
@info_request.save!
@@ -92,7 +94,8 @@ class AdminRequestController < AdminController
:old_awaiting_description => old_awaiting_description, :awaiting_description => @info_request.awaiting_description,
:old_allow_new_responses_from => old_allow_new_responses_from, :allow_new_responses_from => @info_request.allow_new_responses_from,
:old_handle_rejected_responses => old_handle_rejected_responses, :handle_rejected_responses => @info_request.handle_rejected_responses,
- :old_tag_string => old_tag_string, :tag_string => @info_request.tag_string
+ :old_tag_string => old_tag_string, :tag_string => @info_request.tag_string,
+ :old_comments_allowed => old_comments_allowed, :tag_string => @info_request.comments_allowed
})
# expire cached files
expire_for_request(@info_request)
diff --git a/app/controllers/comment_controller.rb b/app/controllers/comment_controller.rb
index 1552017c2..988a8a6f8 100644
--- a/app/controllers/comment_controller.rb
+++ b/app/controllers/comment_controller.rb
@@ -23,6 +23,13 @@ class CommentController < ApplicationController
else
raise "Unknown type " + params[:type]
end
+
+ # Are comments disabled on this request?
+ #
+ # There is no “add comment” link when comments are disabled, so users should
+ # not usually hit this unless they are explicitly attempting to avoid the comment
+ # block, so we just raise an exception.
+ raise "Comments are not allowed on this request" if !@info_request.comments_allowed?
# Banned from adding comments?
if !authenticated_user.nil? && !authenticated_user.can_make_comments?
diff --git a/app/controllers/holiday_controller.rb b/app/controllers/holiday_controller.rb
index 7f62aa26d..9430c0756 100644
--- a/app/controllers/holiday_controller.rb
+++ b/app/controllers/holiday_controller.rb
@@ -14,7 +14,9 @@ class HolidayController < ApplicationController
def due_date
if params[:holiday]
@request_date = Date.strptime(params[:holiday]) or raise "Invalid date"
- @due_date = Holiday.due_date_from(@request_date, 20)
+ days_later = MySociety::Config.get('REPLY_LATE_AFTER_DAYS', 20)
+ working_or_calendar_days = MySociety::Config.get('WORKING_OR_CALENDAR_DAYS', 'working')
+ @due_date = Holiday.due_date_from(@request_date, days_later, working_or_calendar_days)
@skipped = Holiday.all(
:conditions => [ 'day >= ? AND day <= ?',
@request_date.strftime("%F"), @due_date.strftime("%F")
diff --git a/app/models/application_mailer.rb b/app/models/application_mailer.rb
index 044006f7c..b6cd5a4bf 100644
--- a/app/models/application_mailer.rb
+++ b/app/models/application_mailer.rb
@@ -5,7 +5,7 @@
# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
#
# $Id: application_mailer.rb,v 1.8 2009-02-09 10:37:12 francis Exp $
-
+require 'action_mailer/version'
class ApplicationMailer < ActionMailer::Base
# Include all the functions views get, as emails call similar things.
helper :application
@@ -26,5 +26,126 @@ class ApplicationMailer < ActionMailer::Base
# Site-wide access to configuration settings
include ConfigHelper
+
+ # Instantiate a new mailer object. If +method_name+ is not +nil+, the mailer
+ # will be initialized according to the named method. If not, the mailer will
+ # remain uninitialized (useful when you only need to invoke the "receive"
+ # method, for instance).
+ def initialize(method_name=nil, *parameters) #:nodoc:
+ create!(method_name, *parameters) if method_name
+ end
+
+ # For each multipart template (e.g. "the_template_file.text.html.erb") available,
+ # add the one from the view path with the highest priority as a part to the mail
+ def render_multipart_templates
+ added_content_types = {}
+ self.view_paths.each do |view_path|
+ Dir.glob("#{view_path}/#{mailer_name}/#{@template}.*").each do |path|
+ template = view_path["#{mailer_name}/#{File.basename(path)}"]
+
+ # Skip unless template has a multipart format
+ next unless template && template.multipart?
+ next if added_content_types[template.content_type] == true
+ @parts << Part.new(
+ :content_type => template.content_type,
+ :disposition => "inline",
+ :charset => charset,
+ :body => render_message(template, @body)
+ )
+ added_content_types[template.content_type] = true
+ end
+ end
+ end
+
+ # Look for the current template in each element of view_paths in order,
+ # return the first
+ def find_template
+ self.view_paths.each do |view_path|
+ if template = view_path["#{mailer_name}/#{@template}"]
+ return template
+ end
+ end
+ return nil
+ end
+
+ if ActionMailer::VERSION::MAJOR == 2
+
+ # This method is a customised version of ActionMailer::Base.create!
+ # modified to allow templates to be selected correctly for multipart
+ # mails when themes have added to the view_paths. The problem from our
+ # point of view with ActionMailer::Base is that it sets template_root to
+ # the first element of the view_paths array and then uses only that (directly
+ # and via template_path, which is created from it) in the create! method when
+ # looking for templates. Our modified version looks for templates in the view_paths
+ # in order.
+ # Changed lines marked with ***
+
+ # Initialize the mailer via the given +method_name+. The body will be
+ # rendered and a new TMail::Mail object created.
+ def create!(method_name, *parameters) #:nodoc:
+ initialize_defaults(method_name)
+ __send__(method_name, *parameters)
+
+ # If an explicit, textual body has not been set, we check assumptions.
+ unless String === @body
+ # First, we look to see if there are any likely templates that match,
+ # which include the content-type in their file name (i.e.,
+ # "the_template_file.text.html.erb", etc.). Only do this if parts
+ # have not already been specified manually.
+ if @parts.empty?
+ # *** render_multipart_templates replaces the following code
+ # Dir.glob("#{template_path}/#{@template}.*").each do |path|
+ # template = template_root["#{mailer_name}/#{File.basename(path)}"]
+ #
+ # # Skip unless template has a multipart format
+ # next unless template && template.multipart?
+ #
+ # @parts << Part.new(
+ # :content_type => template.content_type,
+ # :disposition => "inline",
+ # :charset => charset,
+ # :body => render_message(template, @body)
+ # )
+ # end
+ render_multipart_templates
+
+ unless @parts.empty?
+ @content_type = "multipart/alternative" if @content_type !~ /^multipart/
+ @parts = sort_parts(@parts, @implicit_parts_order)
+ end
+ end
+
+ # Then, if there were such templates, we check to see if we ought to
+ # also render a "normal" template (without the content type). If a
+ # normal template exists (or if there were no implicit parts) we render
+ # it.
+ template_exists = @parts.empty?
+
+ # *** find_template replaces template_root call
+ # template_exists ||= template_root["#{mailer_name}/#{@template}"]
+ template_exists ||= find_template
+
+ @body = render_message(@template, @body) if template_exists
+
+ # Finally, if there are other message parts and a textual body exists,
+ # we shift it onto the front of the parts and set the body to nil (so
+ # that create_mail doesn't try to render it in addition to the parts).
+ if !@parts.empty? && String === @body
+ @parts.unshift ActionMailer::Part.new(:charset => charset, :body => @body)
+ @body = nil
+ end
+ end
+
+ # If this is a multipart e-mail add the mime_version if it is not
+ # already set.
+ @mime_version ||= "1.0" if !@parts.empty?
+
+ # build the mail object itself
+ @mail = create_mail
+ end
+ else
+ raise "ApplicationMailer.create! is obsolete - find another way to ensure that themes can override mail templates for multipart mails"
+ end
+
end
diff --git a/app/models/censor_rule.rb b/app/models/censor_rule.rb
index da3f49760..a74fdcb24 100644
--- a/app/models/censor_rule.rb
+++ b/app/models/censor_rule.rb
@@ -1,5 +1,5 @@
# == Schema Information
-# Schema version: 114
+# Schema version: 20120919140404
#
# Table name: censor_rules
#
@@ -9,11 +9,11 @@
# public_body_id :integer
# text :text not null
# replacement :text not null
-# regexp :boolean
# last_edit_editor :string(255) not null
# last_edit_comment :text not null
# created_at :datetime not null
# updated_at :datetime not null
+# regexp :boolean
#
# models/censor_rule.rb:
diff --git a/app/models/holiday.rb b/app/models/holiday.rb
index debd88dec..1072f6a70 100644
--- a/app/models/holiday.rb
+++ b/app/models/holiday.rb
@@ -25,18 +25,34 @@
class Holiday < ActiveRecord::Base
- # Calculate the date on which a request made on a given date falls due.
+ def Holiday.weekend_or_holiday?(date)
+ # TODO only fetch holidays after the start_date
+ holidays = self.all.collect { |h| h.day }.to_set
+
+ date.wday == 0 || date.wday == 6 || holidays.include?(date)
+ end
+
+ def Holiday.due_date_from(start_date, days, type_of_days)
+ case type_of_days
+ when "working"
+ Holiday.due_date_from_working_days(start_date, days)
+ when "calendar"
+ Holiday.due_date_from_calendar_days(start_date, days)
+ else
+ raise "Unexpected value for type_of_days: #{type_of_days}"
+ end
+ end
+
+ # Calculate the date on which a request made on a given date falls due when
+ # days are given in working days
# i.e. it is due by the end of that day.
- def Holiday.due_date_from(start_date, working_days)
+ def Holiday.due_date_from_working_days(start_date, working_days)
# convert date/times into dates
start_date = start_date.to_date
- # TODO only fetch holidays after the start_date
- holidays = self.all.collect { |h| h.day }.to_set
-
- # Count forward (20) working days. We start with today as "day zero". The
- # first of the twenty full working days is the next day. We return the
- # date of the last of the twenty.
+ # Count forward the number of working days. We start with today as "day zero". The
+ # first of the full working days is the next day. We return the
+ # date of the last of the number of working days.
# This response for example of a public authority complains that we had
# it wrong. We didn't (even thought I changed the code for a while,
@@ -46,15 +62,27 @@ class Holiday < ActiveRecord::Base
days_passed = 0
response_required_by = start_date
- # Now step forward into each of the 20 days.
+ # Now step forward into each of the working days.
while days_passed < working_days
- response_required_by += 1.day
- next if response_required_by.wday == 0 || response_required_by.wday == 6 # weekend
- next if holidays.include?(response_required_by)
- days_passed += 1
+ response_required_by += 1
+ days_passed += 1 unless weekend_or_holiday?(response_required_by)
end
- return response_required_by
+ response_required_by
end
+ # Calculate the date on which a request made on a given date falls due when
+ # the days are given in calendar days (rather than working days)
+ # If the due date falls on a weekend or a holiday then the due date is the next
+ # weekday that isn't a holiday.
+ def Holiday.due_date_from_calendar_days(start_date, days)
+ # convert date/times into dates
+ start_date = start_date.to_date
+
+ response_required_by = start_date + days
+ while weekend_or_holiday?(response_required_by)
+ response_required_by += 1
+ end
+ response_required_by
+ end
end
diff --git a/app/models/info_request.rb b/app/models/info_request.rb
index 2e16d0f58..141440c6d 100644
--- a/app/models/info_request.rb
+++ b/app/models/info_request.rb
@@ -1,4 +1,5 @@
# == Schema Information
+# Schema version: 20120919140404
#
# Table name: info_requests
#
@@ -19,6 +20,7 @@
# external_user_name :string(255)
# external_url :string(255)
# attention_requested :boolean default(FALSE)
+# comments_allowed :boolean default(TRUE), not null
#
require 'digest/sha1'
@@ -688,7 +690,8 @@ public
# things, e.g. fees, not properly covered.
def date_response_required_by
days_later = MySociety::Config.get('REPLY_LATE_AFTER_DAYS', 20)
- return Holiday.due_date_from(self.date_initial_request_last_sent_at, days_later)
+ working_or_calendar_days = MySociety::Config.get('WORKING_OR_CALENDAR_DAYS', 'working')
+ return Holiday.due_date_from(self.date_initial_request_last_sent_at, days_later, working_or_calendar_days)
end
# This is a long stop - even with UK public interest test extensions, 40
# days is a very long time.
@@ -696,12 +699,13 @@ public
last_sent = last_event_forming_initial_request
very_late_days_later = MySociety::Config.get('REPLY_VERY_LATE_AFTER_DAYS', 40)
school_very_late_days_later = MySociety::Config.get('SPECIAL_REPLY_VERY_LATE_AFTER_DAYS', 60)
+ working_or_calendar_days = MySociety::Config.get('WORKING_OR_CALENDAR_DAYS', 'working')
if self.public_body.is_school?
# schools have 60 working days maximum (even over a long holiday)
- return Holiday.due_date_from(self.date_initial_request_last_sent_at, 60)
+ return Holiday.due_date_from(self.date_initial_request_last_sent_at, school_very_late_days_later, working_or_calendar_days)
else
# public interest test ICO guidance gives 40 working maximum
- return Holiday.due_date_from(self.date_initial_request_last_sent_at, 40)
+ return Holiday.due_date_from(self.date_initial_request_last_sent_at, very_late_days_later, working_or_calendar_days)
end
end
diff --git a/app/models/public_body.rb b/app/models/public_body.rb
index 77da81d4c..2cf1ce8a2 100644
--- a/app/models/public_body.rb
+++ b/app/models/public_body.rb
@@ -1,32 +1,27 @@
-# -*- coding: utf-8 -*-
# == Schema Information
+# Schema version: 20120919140404
#
# Table name: public_bodies
#
-# id :integer not null, primary key
-# name :text not null
-# short_name :text not null
-# request_email :text not null
-# version :integer not null
-# last_edit_editor :string(255) not null
-# last_edit_comment :text not null
-# created_at :datetime not null
-# updated_at :datetime not null
-# url_name :text not null
-# home_page :text default(""), not null
-# notes :text default(""), not null
-# first_letter :string(255) not null
-# publication_scheme :text default(""), not null
-# api_key :string(255) not null
-#
-# models/public_body.rb:
-# A public body, from which information can be requested.
+# id :integer not null, primary key
+# name :text not null
+# short_name :text not null
+# request_email :text not null
+# version :integer not null
+# last_edit_editor :string(255) not null
+# last_edit_comment :text not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# url_name :text not null
+# home_page :text default(""), not null
+# notes :text default(""), not null
+# first_letter :string(255) not null
+# publication_scheme :text default(""), not null
+# api_key :string(255)
+# info_requests_count :integer default(0), not null
#
-# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved.
-# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
-#
-# $Id: public_body.rb,v 1.160 2009-10-02 22:56:35 francis Exp $
+# -*- coding: utf-8 -*-
require 'csv'
require 'securerandom'
require 'set'
diff --git a/app/models/request_classification.rb b/app/models/request_classification.rb
index 678b6cd16..f5a1b4bee 100644
--- a/app/models/request_classification.rb
+++ b/app/models/request_classification.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+# Schema version: 20120919140404
+#
+# Table name: request_classifications
+#
+# id :integer not null, primary key
+# user_id :integer
+# info_request_event_id :integer
+# created_at :datetime
+# updated_at :datetime
+#
+
class RequestClassification < ActiveRecord::Base
belongs_to :user
@@ -13,4 +25,4 @@ class RequestClassification < ActiveRecord::Base
:include => :user)
end
-end \ No newline at end of file
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 657ea2a4a..bb1b54d70 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,4 +1,5 @@
# == Schema Information
+# Schema version: 20120919140404
#
# Table name: users
#
@@ -21,13 +22,6 @@
# no_limit :boolean default(FALSE), not null
# receive_email_alerts :boolean default(TRUE), not null
#
-# models/user.rb:
-# Model of people who use the site to file requests, make comments etc.
-#
-# Copyright (c) 2007 UK Citizens Online Democracy. All rights reserved.
-# Email: francis@mysociety.org; WWW: http://www.mysociety.org/
-#
-# $Id: user.rb,v 1.106 2009-10-01 01:43:36 francis Exp $
require 'digest/sha1'
diff --git a/app/views/admin_request/edit.rhtml b/app/views/admin_request/edit.rhtml
index 808028b47..8fa2a1fe2 100644
--- a/app/views/admin_request/edit.rhtml
+++ b/app/views/admin_request/edit.rhtml
@@ -28,6 +28,10 @@
<br/>(don't forget to change 'awaiting description' when you set described state)<br/>
</p>
+ <p><label for="info_request_comments_allowed"><strong>Are comments allowed?</strong></label>
+ <%= select('info_request', "comments_allowed", [["Yes – comments allowed", true], ["No – comments disabled", false]]) %>
+ </p>
+
<p><label for="info_request_tag_string"><strong>Tags</strong> <small>(space separated, can use key:value)</small></label><br/>
<%= text_field 'info_request', 'tag_string', :size => 60 %></p>
diff --git a/app/views/request/_after_actions.rhtml b/app/views/request/_after_actions.rhtml
index 15ca6302e..580ff0e87 100644
--- a/app/views/request/_after_actions.rhtml
+++ b/app/views/request/_after_actions.rhtml
@@ -5,9 +5,11 @@
<div id="anyone_actions">
<strong><%= _('Anyone:') %></strong>
<ul>
- <li>
- <%= _('<a href="%s">Add an annotation</a> (to help the requester or others)') % [new_comment_url(:url_title => @info_request.url_title)] %>
- </li>
+ <% if @info_request.comments_allowed? %>
+ <li>
+ <%= _('<a href="%s">Add an annotation</a> (to help the requester or others)') % [new_comment_url(:url_title => @info_request.url_title)] %>
+ </li>
+ <% end %>
<% if @old_unclassified %>
<li>
<%= link_to _('Update the status of this request'), '#describe_state_form_1' %>
diff --git a/app/views/request/_sidebar.rhtml b/app/views/request/_sidebar.rhtml
index 731bfb34e..dc0d2eb31 100644
--- a/app/views/request/_sidebar.rhtml
+++ b/app/views/request/_sidebar.rhtml
@@ -24,7 +24,7 @@
<% end %>
<% else %>
<p><%= _('Requests for personal information and vexatious requests are not considered valid for FOI purposes (<a href="/help/about">read more</a>).') %></p>
- <p><%= ('If you believe this request is not suitable, you can report it for attention by the site administrators') %></p>
+ <p><%= _('If you believe this request is not suitable, you can report it for attention by the site administrators') %></p>
<%= link_to _("Report this request"), report_path, :class => "link_button_green", :method => "POST" %>
<% end %>
<% end %>
@@ -32,11 +32,11 @@
<div class="act_link">
<% tweet_link = "https://twitter.com/share?url=#{h(request.url)}&via=#{h(MySociety::Config.get('TWITTER_USERNAME', ''))}&text='#{h(@info_request.title)}'&related=#{_('alaveteli_foi:The software that runs {{site_name}}', :site_name => h(site_name))}" %>
- <%= link_to '<img src="/images/twitter-16.png" alt="twitter icon">', tweet_link %>
- <%= link_to _("Tweet this request"), tweet_link %>
+ <%= link_to '<img src="/images/twitter-16.png" alt="twitter icon">', tweet_link %>
+ <%= link_to _("Tweet this request"), tweet_link %>
</div>
<div class="act_link">
- <%= link_to '<img src="/images/wordpress.png" alt="" class="rss">', "http://wordpress.com/"%>
+ <%= link_to '<img src="/images/wordpress.png" alt="" class="rss">', "http://wordpress.com/"%>
<%= link_to _("Start your own blog"), "http://wordpress.com/"%>
</div>
diff --git a/app/views/track/_tracking_links.rhtml b/app/views/track/_tracking_links.rhtml
index 39f346eff..3ba9d15e2 100644
--- a/app/views/track/_tracking_links.rhtml
+++ b/app/views/track/_tracking_links.rhtml
@@ -4,12 +4,12 @@
end
%>
-<% if own_request %>
+<% if own_request %>
<p><%= _('This is your own request, so you will be automatically emailed when new responses arrive.')%></p>
-<% elsif existing_track %>
+<% elsif existing_track %>
<p><%= track_thing.params[:verb_on_page_already] %></p>
<div class="feed_link feed_link_<%=location%>">
- <%= link_to "Unsubscribe", {:controller => 'track', :action => 'update', :track_id => existing_track.id, :track_medium => "delete", :r => request.request_uri}, :class => "link_button_green" %>
+ <%= link_to _("Unsubscribe"), {:controller => 'track', :action => 'update', :track_id => existing_track.id, :track_medium => "delete", :r => request.request_uri}, :class => "link_button_green" %>
</div>
<% elsif track_thing %>
<div class="feed_link feed_link_<%=location%>">
@@ -19,9 +19,9 @@
<%= link_to _("Follow"), do_track_url(track_thing), :class => "link_button_green" %>
<% end %>
</div>
-
+
<div class="feed_link feed_link_<%=location%>">
- <%= link_to '<img src="/images/feed-16.png" alt="">', do_track_url(track_thing, 'feed') %>
+ <%= link_to '<img src="/images/feed-16.png" alt="">', do_track_url(track_thing, 'feed') %>
<%= link_to (location == 'sidebar' ? _('RSS feed of updates') : _('RSS feed')), do_track_url(track_thing, 'feed') %>
</div>
<% end %>