aboutsummaryrefslogtreecommitdiffstats
path: root/perllib
diff options
context:
space:
mode:
authorMatthew Somerville <matthew@mysociety.org>2015-12-02 17:45:03 +0000
committerMatthew Somerville <matthew@mysociety.org>2015-12-02 17:45:03 +0000
commitb6fcd966d204d35c149b2bff91513e732f3101c8 (patch)
tree75fb01b3910fc4093584bb3b9056e9ea6dbe0eba /perllib
parent8543192128ed15c9bc73e3686ab03324ee5e2b11 (diff)
parent7b20745945638cce030879eafc8cac8f8bd81c56 (diff)
Merge branch 'reduce-fixmystreet-app'
Diffstat (limited to 'perllib')
-rw-r--r--perllib/FixMyStreet.pm33
-rw-r--r--perllib/FixMyStreet/App.pm161
-rw-r--r--perllib/FixMyStreet/App/Controller/JSON.pm3
-rwxr-xr-xperllib/FixMyStreet/App/Controller/Rss.pm2
-rw-r--r--perllib/FixMyStreet/App/Model/DB.pm2
-rw-r--r--perllib/FixMyStreet/App/Model/EmailSend.pm55
-rw-r--r--perllib/FixMyStreet/App/Model/PhotoSet.pm2
-rw-r--r--perllib/FixMyStreet/Cobrand.pm13
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm2
-rw-r--r--perllib/FixMyStreet/Cobrand/UKCouncils.pm4
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm6
-rw-r--r--perllib/FixMyStreet/DB.pm5
-rw-r--r--perllib/FixMyStreet/DB/Result/Alert.pm5
-rw-r--r--perllib/FixMyStreet/DB/Result/Comment.pm9
-rw-r--r--perllib/FixMyStreet/DB/Result/Contact.pm5
-rw-r--r--perllib/FixMyStreet/DB/Result/Nearby.pm5
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm45
-rw-r--r--perllib/FixMyStreet/DB/Result/Questionnaire.pm2
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Alert.pm2
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/AlertType.pm266
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Comment.pm2
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Problem.pm309
-rw-r--r--perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm104
-rw-r--r--perllib/FixMyStreet/Email.pm124
-rw-r--r--perllib/FixMyStreet/EmailSend.pm70
-rw-r--r--perllib/FixMyStreet/Geocode/Bing.pm3
-rw-r--r--perllib/FixMyStreet/Roles/Abuser.pm2
-rw-r--r--perllib/FixMyStreet/Roles/Extra.pm7
-rw-r--r--perllib/FixMyStreet/Script/Alerts.pm293
-rw-r--r--perllib/FixMyStreet/Script/Questionnaires.pm117
-rw-r--r--perllib/FixMyStreet/Script/Reports.pm313
-rw-r--r--perllib/FixMyStreet/SendReport.pm19
-rw-r--r--perllib/FixMyStreet/SendReport/EastHants.pm4
-rw-r--r--perllib/FixMyStreet/SendReport/Email.pm17
-rw-r--r--perllib/FixMyStreet/SendReport/EmptyHomes.pm10
-rw-r--r--perllib/FixMyStreet/SendReport/Noop.pm2
-rw-r--r--perllib/FixMyStreet/SendReport/Open311.pm6
-rw-r--r--perllib/FixMyStreet/SendReport/Refused.pm2
-rw-r--r--perllib/FixMyStreet/SendReport/Zurich.pm8
-rw-r--r--perllib/FixMyStreet/TestMech.pm16
-rw-r--r--perllib/Open311.pm37
-rw-r--r--perllib/Open311/GetServiceRequestUpdates.pm19
-rw-r--r--perllib/Open311/GetUpdates.pm9
-rw-r--r--perllib/Open311/PopulateServiceList.pm16
-rw-r--r--perllib/Utils/Photo.pm41
45 files changed, 1122 insertions, 1055 deletions
diff --git a/perllib/FixMyStreet.pm b/perllib/FixMyStreet.pm
index 76befb96a..1a9c8ff60 100644
--- a/perllib/FixMyStreet.pm
+++ b/perllib/FixMyStreet.pm
@@ -95,15 +95,12 @@ sub override_config($&) {
mySociety::MaPit::configure($config->{MAPIT_URL}) if $config->{MAPIT_URL};
- # For historical reasons, we have two ways of asking for config variables.
- # Override them both, I'm sure we'll find time to get rid of one eventually.
- #
- # NB: though we have these two functions, templates tend to use [% c.config %]
+ # NB: though we have this, templates tend to use [% c.config %].
# This overriding happens after $c->config is set, so note that
# FixMyStreet::App->setup_request rewrites $c->config if we are in
# test_mode, so tests should Just Work there too.
- my $override_guard1 = Sub::Override->new(
+ my $override_guard = Sub::Override->new(
"FixMyStreet::config",
sub {
my ($class, $key) = @_;
@@ -113,30 +110,19 @@ sub override_config($&) {
return $orig_config->{$key} if exists $orig_config->{$key};
}
);
- my $override_guard2 = Sub::Override->new(
- "mySociety::Config::get",
- sub ($;$) {
- my ($key, $default) = @_;
- return $config->{$key} if exists $config->{$key};
- my $orig_config = mySociety::Config::load_default();
- return $orig_config->{$key} if exists $orig_config->{$key};
- return $default if @_ == 2;
- }
- );
FixMyStreet::Map::reload_allowed_maps() if $config->{MAP_TYPE};
$code->();
- $override_guard1->restore();
- $override_guard2->restore();
+ $override_guard->restore();
mySociety::MaPit::configure() if $config->{MAPIT_URL};
FixMyStreet::Map::reload_allowed_maps() if $config->{MAP_TYPE};
}
=head2 dbic_connect_info
- $connect_info = FixMyStreet->dbic_connect_info();
+ $connect_info = FixMyStreet->dbic_connect_info;
Returns the array that DBIx::Class::Schema needs to connect to the database.
Most of the values are read from the config file and others are hordcoded here.
@@ -172,7 +158,7 @@ sub dbic_connect_info {
};
my $dbic_args = {};
- return [ $dsn, $user, $password, $dbi_args, $dbic_args ];
+ return ( $dsn, $user, $password, $dbi_args, $dbic_args );
}
=head2 configure_mysociety_dbhandle
@@ -221,21 +207,24 @@ sub get_email_template {
return $template;
}
-my $tz = DateTime::TimeZone->new( name => "local" );
+my $tz;
my $tz_f;
-$tz_f = DateTime::TimeZone->new( name => FixMyStreet->config('TIME_ZONE') )
- if FixMyStreet->config('TIME_ZONE');
sub local_time_zone {
+ $tz //= DateTime::TimeZone->new( name => "local" );
return $tz;
}
sub time_zone {
+ $tz_f //= DateTime::TimeZone->new( name => FixMyStreet->config('TIME_ZONE') )
+ if FixMyStreet->config('TIME_ZONE');
return $tz_f;
}
sub set_time_zone {
my ($class, $dt) = @_;
+ my $tz = local_time_zone();
+ my $tz_f = time_zone();
$dt->set_time_zone($tz);
$dt->set_time_zone($tz_f) if $tz_f;
}
diff --git a/perllib/FixMyStreet/App.pm b/perllib/FixMyStreet/App.pm
index c9286b177..b8ce2e051 100644
--- a/perllib/FixMyStreet/App.pm
+++ b/perllib/FixMyStreet/App.pm
@@ -2,9 +2,6 @@ package FixMyStreet::App;
use Moose;
use namespace::autoclean;
-# Should move away from Email::Send, but until then:
-$Return::Value::NO_CLUCK = 1;
-
use Catalyst::Runtime 5.80;
use FixMyStreet;
use FixMyStreet::Cobrand;
@@ -12,6 +9,7 @@ use Memcached;
use mySociety::Email;
use mySociety::Random qw(random_bytes);
use FixMyStreet::Map;
+use FixMyStreet::Email;
use Utils;
use Path::Class;
@@ -319,7 +317,7 @@ sub send_email {
]
};
- return if $c->is_abuser($vars->{to});
+ return if FixMyStreet::Email::is_abuser($c->model('DB')->schema, $vars->{to});
# render the template
my $content = $c->view('Email')->render( $c, $template, $vars );
@@ -347,7 +345,7 @@ sub send_email {
) };
if (my $attachments = $extra_stash_values->{attachments}) {
- $email_text = munge_attachments($email_text, $attachments);
+ $email_text = FixMyStreet::Email::munge_attachments($email_text, $attachments);
}
# send the email
@@ -356,107 +354,6 @@ sub send_email {
return $email;
}
-sub send_email_cron {
- my ( $c, $params, $env_from, $nomail, $cobrand, $lang_code ) = @_;
-
- my $sender = $c->config->{DO_NOT_REPLY_EMAIL};
- $env_from ||= $sender;
- if (!$params->{From}) {
- my $sender_name = $cobrand->contact_name;
- $params->{From} = [ $sender, _($sender_name) ];
- }
-
- return 1 if $c->is_abuser($params->{To});
-
- $params->{'Message-ID'} = sprintf('<fms-cron-%s-%s@%s>', time(),
- unpack('h*', random_bytes(5, 1)), FixMyStreet->config('EMAIL_DOMAIN')
- );
-
- # This is all to set the path for the templates processor so we can override
- # signature and site names in emails using templates in the old style emails.
- # It's a bit involved as not everywhere we use it knows about the cobrand so
- # we can't assume there will be one.
- my $include_path = FixMyStreet->path_to( 'templates', 'email', 'default' )->stringify;
- if ( $cobrand ) {
- $include_path =
- FixMyStreet->path_to( 'templates', 'email', $cobrand->moniker )->stringify . ':'
- . $include_path;
- if ( $lang_code ) {
- $include_path =
- FixMyStreet->path_to( 'templates', 'email', $cobrand->moniker, $lang_code )->stringify . ':'
- . $include_path;
- }
- }
- my $tt = Template->new({
- INCLUDE_PATH => $include_path
- });
- my ($sig, $site_name);
- $tt->process( 'signature.txt', $params, \$sig );
- $sig = Encode::decode('utf8', $sig);
- $params->{_parameters_}->{signature} = $sig;
-
- $tt->process( 'site-name.txt', $params, \$site_name );
- $site_name = Utils::trim_text(Encode::decode('utf8', $site_name));
- $params->{_parameters_}->{site_name} = $site_name;
-
- $params->{_line_indent} = '';
- my $attachments = delete $params->{attachments};
-
- my $email = mySociety::Locale::in_gb_locale { mySociety::Email::construct_email($params) };
-
- $email = munge_attachments($email, $attachments) if $attachments;
-
- if ($nomail) {
- print $email;
- return 1; # Failure
- } else {
- my %model_args;
- if (!FixMyStreet->test_mode && $env_from eq FixMyStreet->config('CONTACT_EMAIL')) {
- $model_args{mailer} = 'FixMyStreet::EmailSend::ContactEmail';
- }
- my $result = $c->model('EmailSend', %model_args)->send($email);
- return $result ? 0 : 1;
- }
-}
-
-sub munge_attachments {
- my ($message, $attachments) = @_;
- # $attachments should be an array_ref of things that can be parsed to Email::MIME,
- # for example
- # [
- # body => $binary_data,
- # attributes => {
- # content_type => 'image/jpeg',
- # encoding => 'base64',
- # filename => '1234.1.jpeg',
- # name => '1234.1.jpeg',
- # },
- # ...
- # ]
- #
- # XXX: mySociety::Email::construct_email isn't using a MIME library and
- # requires more analysis to refactor, so for now, we'll simply parse the
- # generated MIME and add attachments.
- #
- # (Yes, this means that the email is constructed by Email::Simple, munged
- # manually by custom code, turned back into Email::Simple, and then munged
- # with Email::MIME. What's your point?)
-
- require Email::MIME;
- my $mime = Email::MIME->new($message);
- $mime->parts_add([ map { Email::MIME->create(%$_)} @$attachments ]);
- my $data = $mime->as_string;
-
- # unsure why Email::MIME adds \r\n. Possibly mail client should handle
- # gracefully, BUT perhaps as the segment constructed by
- # mySociety::Email::construct_email strips to \n, they seem not to.
- # So we re-run the same regexp here to the added part.
- $data =~ s/\r\n/\n/gs;
-
- return $data;
-}
-
-
=head2 uri_with
$uri = $c->uri_with( ... );
@@ -535,58 +432,6 @@ sub render_fragment {
$c->view('Web')->render($c, $template, $vars);
}
-=head2 get_photo_params
-
-Returns a hashref of details of any attached photo for use in templates.
-Hashref contains height, width and url keys.
-
-=cut
-
-sub get_photo_params {
- my ($self, $key) = @_;
-
- return {} unless $self->photo;
-
- $key = ($key eq 'id') ? '' : "/$key";
-
- my $pre = "/photo$key/" . $self->id;
- my $post = '.jpeg';
- my $photo = {};
-
- if (length($self->photo) == 40) {
- $post .= '?' . $self->photo;
- $photo->{url_full} = "$pre.full$post";
- # XXX Can't use size here because {url} (currently 250px height) may be
- # being used, but at this point it doesn't yet exist to find the width
- # $str = FixMyStreet->config('UPLOAD_DIR') . $self->photo . '.jpeg';
- } else {
- my $str = \$self->photo;
- ( $photo->{width}, $photo->{height} ) = Image::Size::imgsize( $str );
- }
-
- $photo->{url} = "$pre$post";
- $photo->{url_tn} = "$pre.tn$post";
- $photo->{url_fp} = "$pre.fp$post";
-
- return $photo;
-}
-
-sub is_abuser {
- my ($c, $to) = @_;
- my $email;
- if (ref($to) eq 'ARRAY') {
- if (ref($to->[0]) eq 'ARRAY') {
- $email = $to->[0][0];
- } else {
- $email = $to->[0];
- }
- } else {
- $email = $to;
- }
- my ($domain) = $email =~ m{ @ (.*) \z }x;
- return $c->model('DB::Abuse')->search( { email => [ $email, $domain ] } )->first;
-}
-
=head2 get_param
$param = $c->get_param('name');
diff --git a/perllib/FixMyStreet/App/Controller/JSON.pm b/perllib/FixMyStreet/App/Controller/JSON.pm
index 959ead245..be738bb8b 100644
--- a/perllib/FixMyStreet/App/Controller/JSON.pm
+++ b/perllib/FixMyStreet/App/Controller/JSON.pm
@@ -8,7 +8,6 @@ use JSON;
use DateTime;
use DateTime::Format::ISO8601;
use List::MoreUtils 'uniq';
-use FixMyStreet::App;
=head1 NAME
@@ -81,7 +80,7 @@ sub problems : Local {
$date_col = 'lastupdate';
}
- my $dt_parser = FixMyStreet::App->model('DB')->schema->storage->datetime_parser;
+ my $dt_parser = $c->model('DB')->schema->storage->datetime_parser;
my $one_day = DateTime::Duration->new( days => 1 );
my $query = {
diff --git a/perllib/FixMyStreet/App/Controller/Rss.pm b/perllib/FixMyStreet/App/Controller/Rss.pm
index b817fe326..586d5e7ae 100755
--- a/perllib/FixMyStreet/App/Controller/Rss.pm
+++ b/perllib/FixMyStreet/App/Controller/Rss.pm
@@ -218,7 +218,7 @@ sub query_main : Private {
. ($alert_type->head_table ? $alert_type->head_table . '_id=? and ' : '')
. $alert_type->item_where . ' order by '
. $alert_type->item_order;
- my $rss_limit = mySociety::Config::get('RSS_LIMIT');
+ my $rss_limit = FixMyStreet->config('RSS_LIMIT');
$query .= " limit $rss_limit" unless $c->stash->{type} =~ /^all/;
my $q = $c->model('DB::Alert')->result_source->storage->dbh->prepare($query);
diff --git a/perllib/FixMyStreet/App/Model/DB.pm b/perllib/FixMyStreet/App/Model/DB.pm
index f9e43172f..ac1f98dc9 100644
--- a/perllib/FixMyStreet/App/Model/DB.pm
+++ b/perllib/FixMyStreet/App/Model/DB.pm
@@ -8,7 +8,7 @@ use FixMyStreet;
__PACKAGE__->config(
schema_class => 'FixMyStreet::DB',
- connect_info => FixMyStreet->dbic_connect_info,
+ connect_info => sub { FixMyStreet::DB->storage->dbh },
);
=head1 NAME
diff --git a/perllib/FixMyStreet/App/Model/EmailSend.pm b/perllib/FixMyStreet/App/Model/EmailSend.pm
index 475026267..93751d4a6 100644
--- a/perllib/FixMyStreet/App/Model/EmailSend.pm
+++ b/perllib/FixMyStreet/App/Model/EmailSend.pm
@@ -4,67 +4,16 @@ use base 'Catalyst::Model::Factory';
use strict;
use warnings;
-use FixMyStreet;
-use Email::Send;
-
=head1 NAME
FixMyStreet::App::Model::EmailSend
=head1 DESCRIPTION
-Thin wrapper around Email::Send - configuring it correctly acording to our config.
-
-If the config value 'SMTP_SMARTHOST' is set then email is routed via SMTP to
-that. Otherwise it is sent using a 'sendmail' like binary on the local system.
-
-And finally if if FixMyStreet->test_mode returns true then emails are not sent
-at all but are stored in memory for the test suite to inspect (using
-Email::Send::Test).
+Catalyst Model wrapper around FixMyStreet::EmailSend
=cut
-my $args = undef;
-
-if ( FixMyStreet->test_mode ) {
-
- # Email::Send::Test
- $args = { mailer => 'Test', };
-}
-elsif ( my $smtp_host = FixMyStreet->config('SMTP_SMARTHOST') ) {
-
- # Email::Send::SMTP
- my $type = FixMyStreet->config('SMTP_TYPE') || '';
- my $port = FixMyStreet->config('SMTP_PORT') || '';
- my $username = FixMyStreet->config('SMTP_USERNAME') || '';
- my $password = FixMyStreet->config('SMTP_PASSWORD') || '';
-
- unless ($port) {
- $port = 25;
- $port = 465 if $type eq 'ssl';
- $port = 587 if $type eq 'tls';
- }
-
- my $mailer_args = [
- Host => $smtp_host,
- Port => $port,
- ];
- push @$mailer_args, ssl => 1 if $type eq 'ssl';
- push @$mailer_args, tls => 1 if $type eq 'tls';
- push @$mailer_args, username => $username, password => $password
- if $username && $password;
- $args = {
- mailer => 'FixMyStreet::EmailSend::DoNotReply',
- mailer_args => $mailer_args,
- };
-}
-else {
-
- # Email::Send::Sendmail
- $args = { mailer => 'Sendmail' };
-}
-
__PACKAGE__->config(
- class => 'Email::Send',
- args => $args,
+ class => 'FixMyStreet::EmailSend',
);
diff --git a/perllib/FixMyStreet/App/Model/PhotoSet.pm b/perllib/FixMyStreet/App/Model/PhotoSet.pm
index b18460821..f1334ff38 100644
--- a/perllib/FixMyStreet/App/Model/PhotoSet.pm
+++ b/perllib/FixMyStreet/App/Model/PhotoSet.pm
@@ -56,7 +56,7 @@ has upload_dir => (
lazy => 1,
default => sub {
my $self = shift;
- my $cache_dir = path( $self->c->config->{UPLOAD_DIR} );
+ my $cache_dir = path( FixMyStreet->config('UPLOAD_DIR') );
$cache_dir->mkpath;
unless ( -d $cache_dir && -w $cache_dir ) {
warn "Can't find/write to photo cache directory '$cache_dir'";
diff --git a/perllib/FixMyStreet/Cobrand.pm b/perllib/FixMyStreet/Cobrand.pm
index ff7d7f943..9f61635d8 100644
--- a/perllib/FixMyStreet/Cobrand.pm
+++ b/perllib/FixMyStreet/Cobrand.pm
@@ -8,7 +8,7 @@ use warnings;
use FixMyStreet;
use Carp;
-use Moose;
+use Package::Stash;
use Module::Pluggable
sub_name => '_cobrands',
@@ -77,11 +77,12 @@ sub available_cobrand_classes {
sub class {
my $avail = shift;
return $avail->{class} if $avail->{class};
- my $moniker = $avail->{moniker};
- Class::MOP::Class->create("FixMyStreet::Cobrand::$moniker" => (
- superclasses => [ 'FixMyStreet::Cobrand::Default' ],
- ));
- return "FixMyStreet::Cobrand::$moniker";
+ my $moniker = "FixMyStreet::Cobrand::$avail->{moniker}";
+ my $class = bless {}, $moniker;
+ my $stash = Package::Stash->new($moniker);
+ my $isa = $stash->get_or_add_symbol('@ISA');
+ @{$isa} = ('FixMyStreet::Cobrand::Default');
+ return $moniker;
}
=head2 get_class_for_host
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm
index 9541f2601..48c997047 100644
--- a/perllib/FixMyStreet/Cobrand/Default.pm
+++ b/perllib/FixMyStreet/Cobrand/Default.pm
@@ -682,7 +682,7 @@ sub get_body_sender {
if ( $body->can_be_devolved ) {
# look up via category
- my $config = FixMyStreet::App->model("DB::Contact")->search( { body_id => $body->id, category => $category } )->first;
+ my $config = $body->result_source->schema->resultset("Contact")->search( { body_id => $body->id, category => $category } )->first;
if ( $config->send_method ) {
return { method => $config->send_method, config => $config };
} else {
diff --git a/perllib/FixMyStreet/Cobrand/UKCouncils.pm b/perllib/FixMyStreet/Cobrand/UKCouncils.pm
index 074da0915..0fb8c23d0 100644
--- a/perllib/FixMyStreet/Cobrand/UKCouncils.pm
+++ b/perllib/FixMyStreet/Cobrand/UKCouncils.pm
@@ -43,7 +43,7 @@ sub problems {
sub base_url {
my $self = shift;
- my $base_url = mySociety::Config::get('BASE_URL');
+ my $base_url = FixMyStreet->config('BASE_URL');
my $u = $self->council_url;
if ( $base_url !~ /$u/ ) {
# council cobrands are not https so transform to http as well
@@ -113,7 +113,7 @@ sub owns_problem {
if (ref $report eq 'HASH') {
return unless $report->{bodies_str};
@bodies = split /,/, $report->{bodies_str};
- @bodies = FixMyStreet::App->model('DB::Body')->search({ id => \@bodies })->all;
+ @bodies = FixMyStreet::DB->resultset('Body')->search({ id => \@bodies })->all;
} else { # Object
@bodies = values %{$report->bodies};
}
diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index 1376f1e45..b7c9e9f45 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -850,7 +850,7 @@ sub admin_report_edit {
# Add new update from status_update
if (my $update = $c->get_param('status_update')) {
- FixMyStreet::App->model('DB::Comment')->create( {
+ $c->model('DB::Comment')->create( {
text => $update,
user => $c->user->obj,
state => 'unconfirmed',
@@ -1010,10 +1010,10 @@ sub _admin_send_email {
}
sub munge_sendreport_params {
- my ($self, $c, $row, $h, $params) = @_;
+ my ($self, $row, $h, $params) = @_;
if ($row->state =~ /^(closed|investigating)$/ && $row->get_extra_metadata('publish_photo')) {
# we attach images to reports sent to external bodies
- my $photoset = $row->get_photoset($c);
+ my $photoset = $row->get_photoset();
my @images = $photoset->all_images
or return;
my $index = 0;
diff --git a/perllib/FixMyStreet/DB.pm b/perllib/FixMyStreet/DB.pm
index a1767abe9..d920c809f 100644
--- a/perllib/FixMyStreet/DB.pm
+++ b/perllib/FixMyStreet/DB.pm
@@ -15,5 +15,8 @@ __PACKAGE__->load_namespaces;
# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-08 17:19:55
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CjFpUvon7KggFM7OF7VK/w
-# You can replace this text with custom code or comments, and it will be preserved on regeneration
+use FixMyStreet;
+
+__PACKAGE__->connection(FixMyStreet->dbic_connect_info);
+
1;
diff --git a/perllib/FixMyStreet/DB/Result/Alert.pm b/perllib/FixMyStreet/DB/Result/Alert.pm
index 35cce8368..2a52a7bca 100644
--- a/perllib/FixMyStreet/DB/Result/Alert.pm
+++ b/perllib/FixMyStreet/DB/Result/Alert.pm
@@ -70,7 +70,7 @@ __PACKAGE__->belongs_to(
# You can replace this text with custom code or comments, and it will be preserved on regeneration
-use Moose;
+use Moo;
use namespace::clean -except => [ 'meta' ];
with 'FixMyStreet::Roles::Abuser';
@@ -113,7 +113,4 @@ sub disable {
return 1;
}
-# need the inline_constuctor bit as we don't inherit from Moose
-__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
-
1;
diff --git a/perllib/FixMyStreet/DB/Result/Comment.pm b/perllib/FixMyStreet/DB/Result/Comment.pm
index 0caaa8968..41e8cf315 100644
--- a/perllib/FixMyStreet/DB/Result/Comment.pm
+++ b/perllib/FixMyStreet/DB/Result/Comment.pm
@@ -96,8 +96,8 @@ __PACKAGE__->belongs_to(
__PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn");
__PACKAGE__->rabx_column('extra');
-use Image::Size;
-use Moose;
+use Moo;
+use Utils::Photo;
use namespace::clean -except => [ 'meta' ];
with 'FixMyStreet::Roles::Abuser';
@@ -156,7 +156,7 @@ Returns a hashref of details of any attached photo for use in templates.
sub get_photo_params {
my $self = shift;
- return FixMyStreet::App::get_photo_params($self, 'c');
+ return Utils::Photo::get_photo_params($self, 'c');
}
=head2 meta_problem_state
@@ -214,7 +214,4 @@ __PACKAGE__->might_have(
{ cascade_copy => 0, cascade_delete => 1 },
);
-# we need the inline_constructor bit as we don't inherit from Moose
-__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
-
1;
diff --git a/perllib/FixMyStreet/DB/Result/Contact.pm b/perllib/FixMyStreet/DB/Result/Contact.pm
index 2fbb0716d..dab5432c6 100644
--- a/perllib/FixMyStreet/DB/Result/Contact.pm
+++ b/perllib/FixMyStreet/DB/Result/Contact.pm
@@ -63,12 +63,9 @@ __PACKAGE__->belongs_to(
__PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn");
__PACKAGE__->rabx_column('extra');
-use Moose;
+use Moo;
use namespace::clean -except => [ 'meta' ];
with 'FixMyStreet::Roles::Extra';
-# we need the inline_constructor bit as we don't inherit from Moose
-__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
-
1;
diff --git a/perllib/FixMyStreet/DB/Result/Nearby.pm b/perllib/FixMyStreet/DB/Result/Nearby.pm
index d3d228788..adeba703a 100644
--- a/perllib/FixMyStreet/DB/Result/Nearby.pm
+++ b/perllib/FixMyStreet/DB/Result/Nearby.pm
@@ -6,7 +6,7 @@ use strict;
use warnings;
use base 'DBIx::Class::Core';
-use Moose;
+use Moo;
use namespace::clean -except => [ 'meta' ];
__PACKAGE__->table( 'NONE' );
@@ -27,7 +27,4 @@ __PACKAGE__->belongs_to(
__PACKAGE__->result_source_instance
->name( \'problem_find_nearby(?,?,?)' );
-# we need the inline_constructor bit as we don't inherit from Moose
-__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
-
1;
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
index 3b7f8bcfd..f2df41f09 100644
--- a/perllib/FixMyStreet/DB/Result/Problem.pm
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -157,10 +157,10 @@ __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn");
__PACKAGE__->rabx_column('extra');
__PACKAGE__->rabx_column('geocode');
-use Image::Size;
-use Moose;
+use Moo;
use namespace::clean -except => [ 'meta' ];
use Utils;
+use Utils::Photo;
with 'FixMyStreet::Roles::Abuser',
'FixMyStreet::Roles::Extra';
@@ -462,7 +462,7 @@ sub bodies($) {
my $self = shift;
return {} unless $self->bodies_str;
my $bodies = $self->bodies_str_ids;
- my @bodies = FixMyStreet::App->model('DB::Body')->search({ id => $bodies })->all;
+ my @bodies = $self->result_source->schema->resultset('Body')->search({ id => $bodies })->all;
return { map { $_->id => $_ } @bodies };
}
@@ -477,6 +477,11 @@ sub url {
return "/report/" . $self->id;
}
+sub admin_url {
+ my ($self, $cobrand) = @_;
+ return $cobrand->admin_base_url . '/report_edit/' . $self->id;
+}
+
=head2 get_photo_params
Returns a hashref of details of the attached photo, if any, for use in templates.
@@ -491,7 +496,7 @@ sub get_photo_params {
# use Carp 'cluck';
# cluck "get_photo_params called"; # TEMPORARY die to make sure I've done right thing with Zurich templates
my $self = shift;
- return FixMyStreet::App::get_photo_params($self, 'id');
+ return Utils::Photo::get_photo_params($self, 'id');
}
=head2 is_open
@@ -628,7 +633,7 @@ sub body {
$body = join( _(' and '),
map {
my $name = $_->name;
- if ($c and mySociety::Config::get('AREA_LINKS_FROM_PROBLEMS')) {
+ if ($c and FixMyStreet->config('AREA_LINKS_FROM_PROBLEMS')) {
'<a href="' . $_->url($c) . '">' . $name . '</a>';
} else {
$name;
@@ -648,7 +653,7 @@ order of title.
sub response_templates {
my $problem = shift;
- return FixMyStreet::App->model('DB::ResponseTemplate')->search(
+ return $problem->result_source->schema->resultset('ResponseTemplate')->search(
{
body_id => $problem->bodies_str_ids
},
@@ -754,20 +759,17 @@ sub update_from_open311_service_request {
$status_notes = $request->{status_notes};
}
- my $update = FixMyStreet::App->model('DB::Comment')->new(
- {
- problem_id => $self->id,
- state => 'confirmed',
- created => $updated || \'current_timestamp',
- confirmed => \'current_timestamp',
- text => $status_notes,
- mark_open => 0,
- mark_fixed => 0,
- user => $system_user,
- anonymous => 0,
- name => $body->name,
- }
- );
+ my $update = $self->new_related(comments => {
+ state => 'confirmed',
+ created => $updated || \'current_timestamp',
+ confirmed => \'current_timestamp',
+ text => $status_notes,
+ mark_open => 0,
+ mark_fixed => 0,
+ user => $system_user,
+ anonymous => 0,
+ name => $body->name,
+ });
my $w3c = DateTime::Format::W3CDTF->new;
my $req_time = $w3c->parse_datetime( $request->{updated_datetime} );
@@ -894,7 +896,4 @@ sub get_time_spent {
return $admin_logs ? $admin_logs->get_column('sum_time_spent') : 0;
}
-# we need the inline_constructor bit as we don't inherit from Moose
-__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
-
1;
diff --git a/perllib/FixMyStreet/DB/Result/Questionnaire.pm b/perllib/FixMyStreet/DB/Result/Questionnaire.pm
index 6f2941546..30f2ab7ce 100644
--- a/perllib/FixMyStreet/DB/Result/Questionnaire.pm
+++ b/perllib/FixMyStreet/DB/Result/Questionnaire.pm
@@ -43,7 +43,7 @@ __PACKAGE__->belongs_to(
# Created by DBIx::Class::Schema::Loader v0.07035 @ 2013-09-10 17:11:54
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:oL1Hk4/bNG14CY74GA75SA
-use Moose;
+use Moo;
use namespace::clean -except => [ 'meta' ];
my $stz = sub {
diff --git a/perllib/FixMyStreet/DB/ResultSet/Alert.pm b/perllib/FixMyStreet/DB/ResultSet/Alert.pm
index bb1c61141..1866e9b06 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Alert.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Alert.pm
@@ -8,7 +8,7 @@ sub timeline_created {
my ( $rs, $restriction ) = @_;
my $prefetch =
- FixMyStreet::App->model('DB')->schema->storage->sql_maker->quote_char ?
+ $rs->result_source->storage->sql_maker->quote_char ?
[ qw/alert_type user/ ] :
[ qw/alert_type/ ];
diff --git a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
index 25c727e25..a801600ea 100644
--- a/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/AlertType.pm
@@ -4,272 +4,10 @@ use base 'DBIx::Class::ResultSet';
use strict;
use warnings;
-use mySociety::DBHandle qw(dbh);
-use mySociety::Gaze;
-use mySociety::Locale;
-use mySociety::MaPit;
-use IO::String;
-use RABX;
-
-# Child must have confirmed, id, email, state(!) columns
-# If parent/child, child table must also have name and text
-# and foreign key to parent must be PARENT_id
sub email_alerts ($) {
my ( $rs ) = @_;
-
- my $q = $rs->search( { ref => { -not_like => '%local_problems%' } } );
- while (my $alert_type = $q->next) {
- my $ref = $alert_type->ref;
- my $head_table = $alert_type->head_table;
- my $item_table = $alert_type->item_table;
- my $query = 'select alert.id as alert_id, alert.user_id as alert_user_id, alert.lang as alert_lang, alert.cobrand as alert_cobrand,
- alert.cobrand_data as alert_cobrand_data, alert.parameter as alert_parameter, alert.parameter2 as alert_parameter2, ';
- if ($head_table) {
- $query .= "
- $item_table.id as item_id, $item_table.text as item_text,
- $item_table.name as item_name, $item_table.anonymous as item_anonymous,
- $item_table.confirmed as item_confirmed,
- $head_table.*
- from alert, $item_table, $head_table
- where alert.parameter::integer = $head_table.id
- and $item_table.${head_table}_id = $head_table.id
- ";
- } else {
- $query .= " $item_table.*,
- $item_table.id as item_id
- from alert, $item_table
- where 1 = 1";
- }
- $query .= "
- and alert_type='$ref' and whendisabled is null and $item_table.confirmed >= whensubscribed
- and $item_table.confirmed >= current_timestamp - '7 days'::interval
- and (select whenqueued from alert_sent where alert_sent.alert_id = alert.id and alert_sent.parameter::integer = $item_table.id) is null
- and $item_table.user_id <> alert.user_id
- and " . $alert_type->item_where . "
- and alert.confirmed = 1
- order by alert.id, $item_table.confirmed";
- # XXX Ugh - needs work
- $query =~ s/\?/alert.parameter/ if ($query =~ /\?/);
- $query =~ s/\?/alert.parameter2/ if ($query =~ /\?/);
-
- $query = dbh()->prepare($query);
- $query->execute();
- my $last_alert_id;
- my %data = ( template => $alert_type->template, data => '' );
- while (my $row = $query->fetchrow_hashref) {
-
- my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->{alert_cobrand})->new();
- $cobrand->set_lang_and_domain( $row->{alert_lang}, 1, FixMyStreet->path_to('locale')->stringify );
-
- # Cobranded and non-cobranded messages can share a database. In this case, the conf file
- # should specify a vhost to send the reports for each cobrand, so that they don't get sent
- # more than once if there are multiple vhosts running off the same database. The email_host
- # call checks if this is the host that sends mail for this cobrand.
- next unless $cobrand->email_host;
-
- # this is for the new_updates alerts
- next if $row->{non_public} and $row->{user_id} != $row->{alert_user_id};
-
- FixMyStreet::App->model('DB::AlertSent')->create( {
- alert_id => $row->{alert_id},
- parameter => $row->{item_id},
- } );
- if ($last_alert_id && $last_alert_id != $row->{alert_id}) {
- _send_aggregated_alert_email(%data);
- %data = ( template => $alert_type->template, data => '' );
- }
-
- # create problem status message for the templates
- if ( FixMyStreet::DB::Result::Problem::fixed_states()->{$row->{state}} ) {
- $data{state_message} = _("This report is currently marked as fixed.");
- } elsif ( FixMyStreet::DB::Result::Problem::closed_states()->{$row->{state}} ) {
- $data{state_message} = _("This report is currently marked as closed.")
- } else {
- $data{state_message} = _("This report is currently marked as open.");
- }
-
- my $url = $cobrand->base_url_for_report($row);
- # this is currently only for new_updates
- if ($row->{item_text}) {
- if ( $cobrand->moniker ne 'zurich' && $row->{alert_user_id} == $row->{user_id} ) {
- # This is an alert to the same user who made the report - make this a login link
- # Don't bother with Zurich which has no accounts
- my $user = FixMyStreet::App->model('DB::User')->find( {
- id => $row->{alert_user_id}
- } );
- $data{alert_email} = $user->email;
- my $token_obj = FixMyStreet::App->model('DB::Token')->create( {
- scope => 'alert_to_reporter',
- data => {
- id => $row->{id},
- }
- } );
- $data{problem_url} = $url . "/R/" . $token_obj->token;
- } else {
- $data{problem_url} = $url . "/report/" . $row->{id};
- }
- $data{data} .= $row->{item_name} . ' : ' if $row->{item_name} && !$row->{item_anonymous};
- if ( $cobrand->include_time_in_update_alerts ) {
- my $parser = DateTime::Format::Pg->new();
- my $dt = $parser->parse_timestamp( $row->{item_confirmed} );
- # We need to always set this otherwise we end up with the DateTime
- # object being in the floating timezone in which case applying a
- # subsequent timezone set will have no effect.
- # this is basically recreating the code from the inflate wrapper
- # in the database model.
- FixMyStreet->set_time_zone($dt);
- $data{data} .= $cobrand->prettify_dt( $dt, 'alert' ) . "\n\n";
- }
- $data{data} .= $row->{item_text} . "\n\n------\n\n";
- # this is ward and council problems
- } else {
- $data{data} .= $url . "/report/" . $row->{id} . " - $row->{title}\n\n";
- if ( exists $row->{geocode} && $row->{geocode} && $ref =~ /ward|council/ ) {
- my $nearest_st = _get_address_from_gecode( $row->{geocode} );
- $data{data} .= $nearest_st if $nearest_st;
- }
- $data{data} .= "\n\n------\n\n";
- }
- if (!$data{alert_user_id}) {
- %data = (%data, %$row);
- if ($ref eq 'area_problems' || $ref eq 'council_problems' || $ref eq 'ward_problems') {
- my $va_info = mySociety::MaPit::call('area', $row->{alert_parameter});
- $data{area_name} = $va_info->{name};
- }
- if ($ref eq 'ward_problems') {
- my $va_info = mySociety::MaPit::call('area', $row->{alert_parameter2});
- $data{ward_name} = $va_info->{name};
- }
- }
- $data{cobrand} = $row->{alert_cobrand};
- $data{cobrand_data} = $row->{alert_cobrand_data};
- $data{lang} = $row->{alert_lang};
- $last_alert_id = $row->{alert_id};
- }
- if ($last_alert_id) {
- _send_aggregated_alert_email(%data);
- }
- }
-
- # Nearby done separately as the table contains the parameters
- my $template = $rs->find( { ref => 'local_problems' } )->template;
- my $query = FixMyStreet::App->model('DB::Alert')->search( {
- alert_type => 'local_problems',
- whendisabled => undef,
- confirmed => 1
- }, {
- order_by => 'id'
- } );
- while (my $alert = $query->next) {
- my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($alert->cobrand)->new();
- next unless $cobrand->email_host;
- next if $alert->is_from_abuser;
-
- my $longitude = $alert->parameter;
- my $latitude = $alert->parameter2;
- my $d = mySociety::Gaze::get_radius_containing_population($latitude, $longitude, 200000);
- # Convert integer to GB locale string (with a ".")
- $d = mySociety::Locale::in_gb_locale {
- sprintf("%f", int($d*10+0.5)/10);
- };
- my $states = "'" . join( "', '", FixMyStreet::DB::Result::Problem::visible_states() ) . "'";
- my %data = ( template => $template, data => '', alert_id => $alert->id, alert_email => $alert->user->email, lang => $alert->lang, cobrand => $alert->cobrand, cobrand_data => $alert->cobrand_data );
- my $q = "select problem.id, problem.bodies_str, problem.postcode, problem.geocode, problem.title from problem_find_nearby(?, ?, ?) as nearby, problem, users
- where nearby.problem_id = problem.id
- and problem.user_id = users.id
- and problem.state in ($states)
- and problem.non_public = 'f'
- and problem.confirmed >= ? and problem.confirmed >= current_timestamp - '7 days'::interval
- and (select whenqueued from alert_sent where alert_sent.alert_id = ? and alert_sent.parameter::integer = problem.id) is null
- and users.email <> ?
- order by confirmed desc";
- $q = dbh()->prepare($q);
- $q->execute($latitude, $longitude, $d, $alert->whensubscribed, $alert->id, $alert->user->email);
- while (my $row = $q->fetchrow_hashref) {
- FixMyStreet::App->model('DB::AlertSent')->create( {
- alert_id => $alert->id,
- parameter => $row->{id},
- } );
- my $url = $cobrand->base_url_for_report($row);
- $data{data} .= $url . "/report/" . $row->{id} . " - $row->{title}\n\n";
- if ( exists $row->{geocode} && $row->{geocode} ) {
- my $nearest_st = _get_address_from_gecode( $row->{geocode} );
- $data{data} .= $nearest_st if $nearest_st;
- }
- $data{data} .= "\n\n------\n\n";
- }
- _send_aggregated_alert_email(%data) if $data{data};
- }
-}
-
-sub _send_aggregated_alert_email(%) {
- my %data = @_;
-
- my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($data{cobrand})->new();
-
- $cobrand->set_lang_and_domain( $data{lang}, 1, FixMyStreet->path_to('locale')->stringify );
-
- if (!$data{alert_email}) {
- my $user = FixMyStreet::App->model('DB::User')->find( {
- id => $data{alert_user_id}
- } );
- $data{alert_email} = $user->email;
- }
-
- my ($domain) = $data{alert_email} =~ m{ @ (.*) \z }x;
- return if FixMyStreet::App->model('DB::Abuse')->search( {
- email => [ $data{alert_email}, $domain ]
- } )->first;
-
- my $token = FixMyStreet::App->model("DB::Token")->new_result( {
- scope => 'alert',
- data => {
- id => $data{alert_id},
- type => 'unsubscribe',
- email => $data{alert_email},
- }
- } );
- $data{unsubscribe_url} = $cobrand->base_url( $data{cobrand_data} ) . '/A/' . $token->token;
-
- my $template = FixMyStreet->get_email_template($cobrand->moniker, $data{lang}, "$data{template}.txt");
-
- my $result = FixMyStreet::App->send_email_cron(
- {
- _template_ => $template,
- _parameters_ => \%data,
- To => $data{alert_email},
- },
- undef,
- 0,
- $cobrand,
- $data{lang}
- );
-
- unless ($result) {
- $token->insert();
- } else {
- print "Failed to send alert $data{alert_id}!";
- }
-}
-
-sub _get_address_from_gecode {
- my $geocode = shift;
-
- return '' unless defined $geocode;
- utf8::encode($geocode) if utf8::is_utf8($geocode);
- my $h = new IO::String($geocode);
- my $data = RABX::wire_rd($h);
-
- my $str = '';
-
- my $address = $data->{resourceSets}[0]{resources}[0]{address};
- my @address;
- push @address, $address->{addressLine} if $address->{addressLine} && $address->{addressLine} ne 'Street';
- push @address, $address->{locality} if $address->{locality};
- $str .= sprintf(_("Nearest road to the pin placed on the map (automatically generated by Bing Maps): %s\n\n"),
- join( ', ', @address ) ) if @address;
-
- return $str;
+ require FixMyStreet::Script::Alerts;
+ FixMyStreet::Script::Alerts::send(@_);
}
1;
diff --git a/perllib/FixMyStreet/DB/ResultSet/Comment.pm b/perllib/FixMyStreet/DB/ResultSet/Comment.pm
index 1b6afb819..3059baab1 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Comment.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Comment.pm
@@ -14,7 +14,7 @@ sub timeline {
my ( $rs, $body_restriction ) = @_;
my $prefetch =
- FixMyStreet::App->model('DB')->schema->storage->sql_maker->quote_char ?
+ $rs->result_source->storage->sql_maker->quote_char ?
[ qw/user/ ] :
[];
diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
index e9f5d0f8e..f82f0135c 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm
@@ -4,14 +4,9 @@ use base 'DBIx::Class::ResultSet';
use strict;
use warnings;
-use CronFns;
-
-use Utils;
-use mySociety::Config;
-use mySociety::MaPit;
-
-use FixMyStreet::App;
-use FixMyStreet::SendReport;
+use Memcached;
+use mySociety::Locale;
+use FixMyStreet::DB;
my $site_key;
@@ -173,7 +168,7 @@ sub timeline {
my ( $rs ) = @_;
my $prefetch =
- FixMyStreet::App->model('DB')->schema->storage->sql_maker->quote_char ?
+ $rs->result_source->storage->sql_maker->quote_char ?
[ qw/user/ ] :
[];
@@ -235,302 +230,10 @@ sub categories_summary {
return \%categories;
}
-sub get_admin_url {
- my ($rs, $cobrand, $row) = @_;
- return $cobrand->admin_base_url . '/report_edit/' . $row->id;
-}
-
sub send_reports {
my ( $rs, $site_override ) = @_;
-
- # Set up site, language etc.
- my ($verbose, $nomail, $debug_mode) = CronFns::options();
-
- my $base_url = mySociety::Config::get('BASE_URL');
- my $site = $site_override || CronFns::site($base_url);
-
- my $states = [ 'confirmed', 'fixed' ];
- $states = [ 'unconfirmed', 'confirmed', 'in progress', 'planned', 'closed', 'investigating' ] if $site eq 'zurich';
- my $unsent = $rs->search( {
- state => $states,
- whensent => undef,
- bodies_str => { '!=', undef },
- } );
- my (%notgot, %note);
-
- my $send_report = FixMyStreet::SendReport->new();
- my $senders = $send_report->get_senders;
-
- my $debug_unsent_count = 0;
- debug_print("starting to loop through unsent problem reports...") if $debug_mode;
- while (my $row = $unsent->next) {
-
- my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->cobrand)->new();
-
- if ($debug_mode) {
- $debug_unsent_count++;
- print "\n";
- debug_print("state=" . $row->state . ", bodies_str=" . $row->bodies_str . ($row->cobrand? ", cobrand=" . $row->cobrand : ""), $row->id);
- }
-
- # Cobranded and non-cobranded messages can share a database. In this case, the conf file
- # should specify a vhost to send the reports for each cobrand, so that they don't get sent
- # more than once if there are multiple vhosts running off the same database. The email_host
- # call checks if this is the host that sends mail for this cobrand.
- if (! $cobrand->email_host()) {
- debug_print("skipping because this host does not send reports for cobrand " . $cobrand->moniker, $row->id) if $debug_mode;
- next;
- }
-
- $cobrand->set_lang_and_domain($row->lang, 1);
- if ( $row->is_from_abuser) {
- $row->update( { state => 'hidden' } );
- debug_print("hiding because its sender is flagged as an abuser", $row->id) if $debug_mode;
- next;
- } elsif ( $row->title =~ /app store test/i ) {
- $row->update( { state => 'hidden' } );
- debug_print("hiding because it is an app store test message", $row->id) if $debug_mode;
- next;
- }
-
- # Template variables for the email
- my $email_base_url = $cobrand->base_url_for_report($row);
- my %h = map { $_ => $row->$_ } qw/id title detail name category latitude longitude used_map/;
- map { $h{$_} = $row->user->$_ || '' } qw/email phone/;
- $h{confirmed} = DateTime::Format::Pg->format_datetime( $row->confirmed->truncate (to => 'second' ) )
- if $row->confirmed;
-
- $h{query} = $row->postcode;
- $h{url} = $email_base_url . $row->url;
- $h{admin_url} = $rs->get_admin_url($cobrand, $row);
- $h{phone_line} = $h{phone} ? _('Phone:') . " $h{phone}\n\n" : '';
- if ($row->photo) {
- $h{has_photo} = _("This web page also contains a photo of the problem, provided by the user.") . "\n\n";
- $h{image_url} = $email_base_url . '/photo/' . $row->id . '.full.jpeg';
- } else {
- $h{has_photo} = '';
- $h{image_url} = '';
- }
- $h{fuzzy} = $row->used_map ? _('To view a map of the precise location of this issue')
- : _('The user could not locate the problem on a map, but to see the area around the location they entered');
- $h{closest_address} = '';
-
- if ( $row->used_map ) {
- $h{closest_address} = $cobrand->find_closest( $h{latitude}, $h{longitude}, $row );
- }
-
- if ( $cobrand->allow_anonymous_reports &&
- $row->user->email eq $cobrand->anonymous_account->{'email'}
- ) {
- $h{anonymous_report} = 1;
- $h{user_details} = _('This report was submitted anonymously');
- } else {
- $h{user_details} = sprintf(_('Name: %s'), $row->name) . "\n\n";
- $h{user_details} .= sprintf(_('Email: %s'), $row->user->email) . "\n\n";
- }
-
- $h{easting_northing} = '';
-
- if ($cobrand->can('process_additional_metadata_for_email')) {
- $cobrand->process_additional_metadata_for_email($row, \%h);
- }
-
- my $bodies = FixMyStreet::App->model("DB::Body")->search(
- { id => $row->bodies_str_ids },
- { order_by => 'name' },
- );
-
- my $missing;
- if ($row->bodies_missing) {
- my @missing = FixMyStreet::App->model("DB::Body")->search(
- { id => [ split /,/, $row->bodies_missing ] },
- { order_by => 'name' }
- )->get_column('name')->all;
- $missing = join(' / ', @missing) if @missing;
- }
-
- my @dear;
- my %reporters = ();
- while (my $body = $bodies->next) {
- my $sender_info = $cobrand->get_body_sender( $body, $row->category );
- my $sender = "FixMyStreet::SendReport::" . $sender_info->{method};
-
- if ( ! exists $senders->{ $sender } ) {
- warn sprintf "No such sender [ $sender ] for body %s ( %d )", $body->name, $body->id;
- next;
- }
- $reporters{ $sender } ||= $sender->new();
-
- if ( $reporters{ $sender }->should_skip( $row ) ) {
- debug_print("skipped by sender " . $sender_info->{method} . " (might be due to previous failed attempts?)", $row->id) if $debug_mode;
- } else {
- debug_print("OK, adding recipient body " . $body->id . ":" . $body->name . ", " . $body->send_method, $row->id) if $debug_mode;
- push @dear, $body->name;
- $reporters{ $sender }->add_body( $body, $sender_info->{config} );
- }
-
- # If we are in the UK include eastings and northings, and nearest stuff
- if ( $cobrand->country eq 'GB' && !$h{easting} ) {
- my $coordsyst = 'G';
- my $first_area = $body->body_areas->first->area_id;
- my $area_info = mySociety::MaPit::call('area', $first_area);
- $coordsyst = 'I' if $area_info->{type} eq 'LGD';
-
- ( $h{easting}, $h{northing} ) = Utils::convert_latlon_to_en( $h{latitude}, $h{longitude}, $coordsyst );
-
- # email templates don't have conditionals so we need to format this here
- $h{easting_northing} = "Easting/Northing";
- $h{easting_northing} .= " (IE)" if $coordsyst eq 'I';
- $h{easting_northing} .= ": $h{easting}/$h{northing}\n\n";
- }
- }
-
- unless ( keys %reporters ) {
- die 'Report not going anywhere for ID ' . $row->id . '!';
- }
-
- unless (@dear) {
- debug_print("can't send because sender count is zero", $row->id) if $debug_mode;
- next;
- }
-
- if ($h{category} eq _('Other')) {
- $h{category_footer} = _('this type of local problem');
- $h{category_line} = '';
- } else {
- $h{category_footer} = "'" . $h{category} . "'";
- $h{category_line} = sprintf(_("Category: %s"), $h{category}) . "\n\n";
- }
-
- if ( $row->subcategory ) {
- $h{subcategory_line} = sprintf(_("Subcategory: %s"), $row->subcategory) . "\n\n";
- } else {
- $h{subcategory_line} = "\n\n";
- }
-
- $h{bodies_name} = join(_(' and '), @dear);
- if ($h{category} eq _('Other')) {
- $h{multiple} = @dear>1 ? "[ " . _("This email has been sent to both councils covering the location of the problem, as the user did not categorise it; please ignore it if you're not the correct council to deal with the issue, or let us know what category of problem this is so we can add it to our system.") . " ]\n\n"
- : '';
- } else {
- $h{multiple} = @dear>1 ? "[ " . _("This email has been sent to several councils covering the location of the problem, as the category selected is provided for all of them; please ignore it if you're not the correct council to deal with the issue.") . " ]\n\n"
- : '';
- }
- $h{missing} = '';
- if ($missing) {
- $h{missing} = '[ '
- . sprintf(_('We realise this problem might be the responsibility of %s; however, we don\'t currently have any contact details for them. If you know of an appropriate contact address, please do get in touch.'), $missing)
- . " ]\n\n";
- }
-
- if (mySociety::Config::get('STAGING_SITE') && !mySociety::Config::get('SEND_REPORTS_ON_STAGING')) {
- # on a staging server send emails to ourselves rather than the bodies
- %reporters = map { $_ => $reporters{$_} } grep { /FixMyStreet::SendReport::(Email|EmptyHomes)/ } keys %reporters;
- unless (%reporters) {
- %reporters = ( 'FixMyStreet::SendReport::Email' => FixMyStreet::SendReport::Email->new() );
- }
- }
-
- # Multiply results together, so one success counts as a success.
- my $result = -1;
-
- for my $sender ( keys %reporters ) {
- debug_print("sending using " . $sender, $row->id) if $debug_mode;
- $result *= $reporters{ $sender }->send( $row, \%h );
- if ( $reporters{ $sender }->unconfirmed_counts) {
- foreach my $e (keys %{ $reporters{ $sender }->unconfirmed_counts } ) {
- foreach my $c (keys %{ $reporters{ $sender }->unconfirmed_counts->{$e} }) {
- $notgot{$e}{$c} += $reporters{ $sender }->unconfirmed_counts->{$e}{$c};
- }
- }
- %note = (
- %note,
- %{ $reporters{ $sender }->unconfirmed_notes }
- );
- }
- }
-
- unless ($result) {
- $row->update( {
- whensent => \'current_timestamp',
- lastupdate => \'current_timestamp',
- } );
- if ( $cobrand->report_sent_confirmation_email && !$h{anonymous_report}) {
- _send_report_sent_email( $row, \%h, $nomail, $cobrand );
- }
- debug_print("send successful: OK", $row->id) if $debug_mode;
- } else {
- my @errors;
- for my $sender ( keys %reporters ) {
- unless ( $reporters{ $sender }->success ) {
- push @errors, $reporters{ $sender }->error;
- }
- }
- $row->update_send_failed( join( '|', @errors ) );
- debug_print("send FAILED: " . join( '|', @errors ), $row->id) if $debug_mode;
- }
- }
- if ($debug_mode) {
- print "\n";
- if ($debug_unsent_count) {
- debug_print("processed all unsent reports (total: $debug_unsent_count)");
- } else {
- debug_print("no unsent reports were found (must have whensent=null and suitable bodies_str & state) -- nothing to send");
- }
- }
-
- if ($verbose || $debug_mode) {
- print "Council email addresses that need checking:\n" if keys %notgot;
- foreach my $e (keys %notgot) {
- foreach my $c (keys %{$notgot{$e}}) {
- print " " . $notgot{$e}{$c} . " problem, to $e category $c (" . $note{$e}{$c}. ")\n";
- }
- }
- my $sending_errors = '';
- my $unsent = $rs->search( {
- state => [ 'confirmed', 'fixed' ],
- whensent => undef,
- bodies_str => { '!=', undef },
- send_fail_count => { '>', 0 }
- } );
- while (my $row = $unsent->next) {
- my $base_url = mySociety::Config::get('BASE_URL');
- $sending_errors .= "* " . $base_url . "/report/" . $row->id . ", failed "
- . $row->send_fail_count . " times, last at " . $row->send_fail_timestamp
- . ", reason " . $row->send_fail_reason . "\n";
- }
- if ($sending_errors) {
- print "The following reports had problems sending:\n$sending_errors";
- }
- }
-}
-
-sub _send_report_sent_email {
- my $row = shift;
- my $h = shift;
- my $nomail = shift;
- my $cobrand = shift;
-
- my $template = FixMyStreet->get_email_template($row->cobrand, $row->lang, 'confirm_report_sent.txt');
-
- FixMyStreet::App->send_email_cron(
- {
- _template_ => $template,
- _parameters_ => $h,
- To => $row->user->email,
- From => [ mySociety::Config::get('CONTACT_EMAIL'), $cobrand->contact_name ],
- },
- mySociety::Config::get('CONTACT_EMAIL'),
- $nomail,
- $cobrand
- );
-}
-
-sub debug_print {
- my $msg = shift;
- my $id = shift || '';
- $id = "report $id: " if $id;
- print "[] $id$msg\n";
+ require FixMyStreet::Script::Reports;
+ FixMyStreet::Script::Reports::send($site_override);
}
1;
diff --git a/perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm b/perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm
index bf1c68c49..6a1ce0d78 100644
--- a/perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm
+++ b/perllib/FixMyStreet/DB/ResultSet/Questionnaire.pm
@@ -3,111 +3,11 @@ use base 'DBIx::Class::ResultSet';
use strict;
use warnings;
-use Encode;
-use Utils;
sub send_questionnaires {
my ( $rs, $params ) = @_;
- $rs->send_questionnaires_period( '4 weeks', $params );
- $rs->send_questionnaires_period( '26 weeks', $params )
- if $params->{site} eq 'emptyhomes';
-}
-
-sub send_questionnaires_period {
- my ( $rs, $period, $params ) = @_;
-
- # Select all problems that need a questionnaire email sending
- my $q_params = {
- state => [ FixMyStreet::DB::Result::Problem::visible_states() ],
- whensent => [
- '-and',
- { '!=', undef },
- { '<', \"current_timestamp - '$period'::interval" },
- ],
- send_questionnaire => 1,
- };
- # FIXME Do these a bit better...
- if ($params->{site} eq 'emptyhomes' && $period eq '4 weeks') {
- $q_params->{'(select max(whensent) from questionnaire where me.id=problem_id)'} = undef;
- } elsif ($params->{site} eq 'emptyhomes' && $period eq '26 weeks') {
- $q_params->{'(select max(whensent) from questionnaire where me.id=problem_id)'} = { '!=', undef };
- } else {
- $q_params->{'-or'} = [
- '(select max(whensent) from questionnaire where me.id=problem_id)' => undef,
- '(select max(whenanswered) from questionnaire where me.id=problem_id)' => { '<', \"current_timestamp - '$period'::interval" }
- ];
- }
-
- my $unsent = FixMyStreet::App->model('DB::Problem')->search( $q_params, {
- order_by => { -desc => 'confirmed' }
- } );
-
- while (my $row = $unsent->next) {
-
- my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->cobrand)->new();
- $cobrand->set_lang_and_domain($row->lang, 1);
-
- # Not all cobrands send questionnaires
- next unless $cobrand->send_questionnaires;
- next if $row->is_from_abuser;
-
- # Cobranded and non-cobranded messages can share a database. In this case, the conf file
- # should specify a vhost to send the reports for each cobrand, so that they don't get sent
- # more than once if there are multiple vhosts running off the same database. The email_host
- # call checks if this is the host that sends mail for this cobrand.
- next unless $cobrand->email_host;
-
- my $template;
- if ($params->{site} eq 'emptyhomes') {
- ($template = $period) =~ s/ //;
- $template = Utils::read_file( FixMyStreet->path_to( "templates/email/emptyhomes/" . $row->lang . "/questionnaire-$template.txt" )->stringify );
- } else {
- $template = FixMyStreet->get_email_template($cobrand->moniker, $row->lang, 'questionnaire.txt');
- }
-
- my %h = map { $_ => $row->$_ } qw/name title detail category/;
- $h{created} = Utils::prettify_duration( time() - $row->confirmed->epoch, 'week' );
-
- my $questionnaire = FixMyStreet::App->model('DB::Questionnaire')->create( {
- problem_id => $row->id,
- whensent => \'current_timestamp',
- } );
-
- # We won't send another questionnaire unless they ask for it (or it was
- # the first EHA questionnaire.
- $row->send_questionnaire( 0 )
- if $params->{site} ne 'emptyhomes' || $period eq '26 weeks';
-
- my $token = FixMyStreet::App->model("DB::Token")->new_result( {
- scope => 'questionnaire',
- data => $questionnaire->id,
- } );
- $h{url} = $cobrand->base_url($row->cobrand_data) . '/Q/' . $token->token;
-
- print "Sending questionnaire " . $questionnaire->id . ", problem "
- . $row->id . ", token " . $token->token . " to "
- . $row->user->email . "\n"
- if $params->{verbose};
-
- my $result = FixMyStreet::App->send_email_cron(
- {
- _template_ => $template,
- _parameters_ => \%h,
- To => [ [ $row->user->email, $row->name ] ],
- },
- undef,
- $params->{nomail},
- $cobrand
- );
- unless ($result) {
- print " ...success\n" if $params->{verbose};
- $row->update();
- $token->insert();
- } else {
- print " ...failed\n" if $params->{verbose};
- $questionnaire->delete;
- }
- }
+ require FixMyStreet::Script::Questionnaires;
+ FixMyStreet::Script::Questionnaires::send($params);
}
sub timeline {
diff --git a/perllib/FixMyStreet/Email.pm b/perllib/FixMyStreet/Email.pm
index 4a2784787..a65a5e340 100644
--- a/perllib/FixMyStreet/Email.pm
+++ b/perllib/FixMyStreet/Email.pm
@@ -1,7 +1,13 @@
package FixMyStreet::Email;
+use Encode;
+use Template;
+use mySociety::Email;
+use mySociety::Locale;
+use mySociety::Random qw(random_bytes);
use Utils::Email;
use FixMyStreet;
+use FixMyStreet::EmailSend;
sub test_dmarc {
my $email = shift;
@@ -9,4 +15,122 @@ sub test_dmarc {
return Utils::Email::test_dmarc($email);
}
+sub is_abuser {
+ my ($schema, $to) = @_;
+
+ my $email;
+ if (ref($to) eq 'ARRAY') {
+ if (ref($to->[0]) eq 'ARRAY') {
+ $email = $to->[0][0];
+ } else {
+ $email = $to->[0];
+ }
+ } else {
+ $email = $to;
+ }
+
+ my ($domain) = $email =~ m{ @ (.*) \z }x;
+ return $schema->resultset('Abuse')->search( { email => [ $email, $domain ] } )->first;
+}
+
+sub send_cron {
+ my ( $schema, $params, $env_from, $nomail, $cobrand, $lang_code ) = @_;
+
+ my $sender = FixMyStreet->config('DO_NOT_REPLY_EMAIL');
+ $env_from ||= $sender;
+ if (!$params->{From}) {
+ my $sender_name = $cobrand->contact_name;
+ $params->{From} = [ $sender, _($sender_name) ];
+ }
+
+ return 1 if is_abuser($schema, $params->{To});
+
+ $params->{'Message-ID'} = sprintf('<fms-cron-%s-%s@%s>', time(),
+ unpack('h*', random_bytes(5, 1)), FixMyStreet->config('EMAIL_DOMAIN')
+ );
+
+ # This is all to set the path for the templates processor so we can override
+ # signature and site names in emails using templates in the old style emails.
+ # It's a bit involved as not everywhere we use it knows about the cobrand so
+ # we can't assume there will be one.
+ my $include_path = FixMyStreet->path_to( 'templates', 'email', 'default' )->stringify;
+ if ( $cobrand ) {
+ $include_path =
+ FixMyStreet->path_to( 'templates', 'email', $cobrand->moniker )->stringify . ':'
+ . $include_path;
+ if ( $lang_code ) {
+ $include_path =
+ FixMyStreet->path_to( 'templates', 'email', $cobrand->moniker, $lang_code )->stringify . ':'
+ . $include_path;
+ }
+ }
+ my $tt = Template->new({
+ INCLUDE_PATH => $include_path
+ });
+ my ($sig, $site_name);
+ $tt->process( 'signature.txt', $params, \$sig );
+ $sig = Encode::decode('utf8', $sig);
+ $params->{_parameters_}->{signature} = $sig;
+
+ $tt->process( 'site-name.txt', $params, \$site_name );
+ $site_name = Utils::trim_text(Encode::decode('utf8', $site_name));
+ $params->{_parameters_}->{site_name} = $site_name;
+
+ $params->{_line_indent} = '';
+ my $attachments = delete $params->{attachments};
+
+ my $email = mySociety::Locale::in_gb_locale { mySociety::Email::construct_email($params) };
+
+ $email = munge_attachments($email, $attachments) if $attachments;
+
+ if ($nomail) {
+ print $email;
+ return 1; # Failure
+ } else {
+ my %model_args;
+ if (!FixMyStreet->test_mode && $env_from eq FixMyStreet->config('CONTACT_EMAIL')) {
+ $model_args{mailer} = 'FixMyStreet::EmailSend::ContactEmail';
+ }
+ my $result = FixMyStreet::EmailSend->new(%model_args)->send($email);
+ return $result ? 0 : 1;
+ }
+}
+
+sub munge_attachments {
+ my ($message, $attachments) = @_;
+ # $attachments should be an array_ref of things that can be parsed to Email::MIME,
+ # for example
+ # [
+ # body => $binary_data,
+ # attributes => {
+ # content_type => 'image/jpeg',
+ # encoding => 'base64',
+ # filename => '1234.1.jpeg',
+ # name => '1234.1.jpeg',
+ # },
+ # ...
+ # ]
+ #
+ # XXX: mySociety::Email::construct_email isn't using a MIME library and
+ # requires more analysis to refactor, so for now, we'll simply parse the
+ # generated MIME and add attachments.
+ #
+ # (Yes, this means that the email is constructed by Email::Simple, munged
+ # manually by custom code, turned back into Email::Simple, and then munged
+ # with Email::MIME. What's your point?)
+
+ require Email::MIME;
+ my $mime = Email::MIME->new($message);
+ $mime->parts_add([ map { Email::MIME->create(%$_)} @$attachments ]);
+ my $data = $mime->as_string;
+
+ # unsure why Email::MIME adds \r\n. Possibly mail client should handle
+ # gracefully, BUT perhaps as the segment constructed by
+ # mySociety::Email::construct_email strips to \n, they seem not to.
+ # So we re-run the same regexp here to the added part.
+ $data =~ s/\r\n/\n/gs;
+
+ return $data;
+}
+
1;
diff --git a/perllib/FixMyStreet/EmailSend.pm b/perllib/FixMyStreet/EmailSend.pm
new file mode 100644
index 000000000..29c93b2d6
--- /dev/null
+++ b/perllib/FixMyStreet/EmailSend.pm
@@ -0,0 +1,70 @@
+package FixMyStreet::EmailSend;
+
+use strict;
+use warnings;
+
+BEGIN {
+ # Should move away from Email::Send, but until then:
+ $Return::Value::NO_CLUCK = 1;
+}
+
+use FixMyStreet;
+use Email::Send;
+
+=head1 NAME
+
+FixMyStreet::EmailSend
+
+=head1 DESCRIPTION
+
+Thin wrapper around Email::Send - configuring it correctly according to our config.
+
+If the config value 'SMTP_SMARTHOST' is set then email is routed via SMTP to
+that. Otherwise it is sent using a 'sendmail' like binary on the local system.
+
+And finally if if FixMyStreet->test_mode returns true then emails are not sent
+at all but are stored in memory for the test suite to inspect (using
+Email::Send::Test).
+
+=cut
+
+my $args = undef;
+
+if ( FixMyStreet->test_mode ) {
+ # Email::Send::Test
+ $args = { mailer => 'Test', };
+} elsif ( my $smtp_host = FixMyStreet->config('SMTP_SMARTHOST') ) {
+ # Email::Send::SMTP
+ my $type = FixMyStreet->config('SMTP_TYPE') || '';
+ my $port = FixMyStreet->config('SMTP_PORT') || '';
+ my $username = FixMyStreet->config('SMTP_USERNAME') || '';
+ my $password = FixMyStreet->config('SMTP_PASSWORD') || '';
+
+ unless ($port) {
+ $port = 25;
+ $port = 465 if $type eq 'ssl';
+ $port = 587 if $type eq 'tls';
+ }
+
+ my $mailer_args = [
+ Host => $smtp_host,
+ Port => $port,
+ ];
+ push @$mailer_args, ssl => 1 if $type eq 'ssl';
+ push @$mailer_args, tls => 1 if $type eq 'tls';
+ push @$mailer_args, username => $username, password => $password
+ if $username && $password;
+ $args = {
+ mailer => 'FixMyStreet::EmailSend::DoNotReply',
+ mailer_args => $mailer_args,
+ };
+} else {
+ # Email::Send::Sendmail
+ $args = { mailer => 'Sendmail' };
+}
+
+sub new {
+ my ($cls, %hash) = @_;
+ my %args = ( %$args, %hash );
+ return Email::Send->new(\%args);
+}
diff --git a/perllib/FixMyStreet/Geocode/Bing.pm b/perllib/FixMyStreet/Geocode/Bing.pm
index d7db10ae6..a846f3348 100644
--- a/perllib/FixMyStreet/Geocode/Bing.pm
+++ b/perllib/FixMyStreet/Geocode/Bing.pm
@@ -8,6 +8,7 @@ package FixMyStreet::Geocode::Bing;
use strict;
+use FixMyStreet::Geocode;
use Utils;
# string STRING CONTEXT
@@ -71,7 +72,7 @@ sub reverse {
my ( $latitude, $longitude, $bing_culture ) = @_;
# Get nearest road-type thing from Bing
- my $key = mySociety::Config::get('BING_MAPS_API_KEY', '');
+ my $key = FixMyStreet->config('BING_MAPS_API_KEY', '');
if ($key) {
my $url = "http://dev.virtualearth.net/REST/v1/Locations/$latitude,$longitude?key=$key";
$url .= '&c=' . $bing_culture if $bing_culture;
diff --git a/perllib/FixMyStreet/Roles/Abuser.pm b/perllib/FixMyStreet/Roles/Abuser.pm
index b9e951305..fc76565ca 100644
--- a/perllib/FixMyStreet/Roles/Abuser.pm
+++ b/perllib/FixMyStreet/Roles/Abuser.pm
@@ -1,6 +1,6 @@
package FixMyStreet::Roles::Abuser;
-use Moose::Role;
+use Moo::Role;
=head2 is_from_abuser
diff --git a/perllib/FixMyStreet/Roles/Extra.pm b/perllib/FixMyStreet/Roles/Extra.pm
index f815a3e9a..19fc91873 100644
--- a/perllib/FixMyStreet/Roles/Extra.pm
+++ b/perllib/FixMyStreet/Roles/Extra.pm
@@ -1,5 +1,5 @@
package FixMyStreet::Roles::Extra;
-use Moose::Role;
+use Moo::Role;
=head1 NAME
@@ -9,12 +9,9 @@ FixMyStreet::Roles::Extra - role for accessing {extra} field
This is to applied to a DB class like Problem or Contacts that has a rich {extra} field:
- use Moose;
+ use Moo;
with 'FixMyStreet::Roles::Extra';
-(NB: there is actually a little more boilerplate, because DBIC doesn't actually
-inherit from Moose, see ::Problem for an example.)
-
Then:
$contact->set_extra_fields(
diff --git a/perllib/FixMyStreet/Script/Alerts.pm b/perllib/FixMyStreet/Script/Alerts.pm
new file mode 100644
index 000000000..fea897a24
--- /dev/null
+++ b/perllib/FixMyStreet/Script/Alerts.pm
@@ -0,0 +1,293 @@
+package FixMyStreet::Script::Alerts;
+
+use strict;
+use warnings;
+
+use DateTime::Format::Pg;
+use IO::String;
+
+use mySociety::DBHandle qw(dbh);
+use mySociety::Gaze;
+use mySociety::Locale;
+use mySociety::MaPit;
+use RABX;
+
+use FixMyStreet::Cobrand;
+use FixMyStreet::DB;
+use FixMyStreet::Email;
+
+FixMyStreet->configure_mysociety_dbhandle;
+
+# Child must have confirmed, id, email, state(!) columns
+# If parent/child, child table must also have name and text
+# and foreign key to parent must be PARENT_id
+sub send() {
+ my $rs = FixMyStreet::DB->resultset('AlertType');
+ my $schema = $rs->result_source->schema;
+
+ my $q = $rs->search( { ref => { -not_like => '%local_problems%' } } );
+ while (my $alert_type = $q->next) {
+ my $ref = $alert_type->ref;
+ my $head_table = $alert_type->head_table;
+ my $item_table = $alert_type->item_table;
+ my $query = 'select alert.id as alert_id, alert.user_id as alert_user_id, alert.lang as alert_lang, alert.cobrand as alert_cobrand,
+ alert.cobrand_data as alert_cobrand_data, alert.parameter as alert_parameter, alert.parameter2 as alert_parameter2, ';
+ if ($head_table) {
+ $query .= "
+ $item_table.id as item_id, $item_table.text as item_text,
+ $item_table.name as item_name, $item_table.anonymous as item_anonymous,
+ $item_table.confirmed as item_confirmed,
+ $head_table.*
+ from alert, $item_table, $head_table
+ where alert.parameter::integer = $head_table.id
+ and $item_table.${head_table}_id = $head_table.id
+ ";
+ } else {
+ $query .= " $item_table.*,
+ $item_table.id as item_id
+ from alert, $item_table
+ where 1 = 1";
+ }
+ $query .= "
+ and alert_type='$ref' and whendisabled is null and $item_table.confirmed >= whensubscribed
+ and $item_table.confirmed >= current_timestamp - '7 days'::interval
+ and (select whenqueued from alert_sent where alert_sent.alert_id = alert.id and alert_sent.parameter::integer = $item_table.id) is null
+ and $item_table.user_id <> alert.user_id
+ and " . $alert_type->item_where . "
+ and alert.confirmed = 1
+ order by alert.id, $item_table.confirmed";
+ # XXX Ugh - needs work
+ $query =~ s/\?/alert.parameter/ if ($query =~ /\?/);
+ $query =~ s/\?/alert.parameter2/ if ($query =~ /\?/);
+
+ $query = dbh()->prepare($query);
+ $query->execute();
+ my $last_alert_id;
+ my %data = ( template => $alert_type->template, data => '', schema => $schema );
+ while (my $row = $query->fetchrow_hashref) {
+
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->{alert_cobrand})->new();
+ $cobrand->set_lang_and_domain( $row->{alert_lang}, 1, FixMyStreet->path_to('locale')->stringify );
+
+ # Cobranded and non-cobranded messages can share a database. In this case, the conf file
+ # should specify a vhost to send the reports for each cobrand, so that they don't get sent
+ # more than once if there are multiple vhosts running off the same database. The email_host
+ # call checks if this is the host that sends mail for this cobrand.
+ next unless $cobrand->email_host;
+
+ # this is for the new_updates alerts
+ next if $row->{non_public} and $row->{user_id} != $row->{alert_user_id};
+
+ $schema->resultset('AlertSent')->create( {
+ alert_id => $row->{alert_id},
+ parameter => $row->{item_id},
+ } );
+ if ($last_alert_id && $last_alert_id != $row->{alert_id}) {
+ _send_aggregated_alert_email(%data);
+ %data = ( template => $alert_type->template, data => '', schema => $schema );
+ }
+
+ # create problem status message for the templates
+ if ( FixMyStreet::DB::Result::Problem::fixed_states()->{$row->{state}} ) {
+ $data{state_message} = _("This report is currently marked as fixed.");
+ } elsif ( FixMyStreet::DB::Result::Problem::closed_states()->{$row->{state}} ) {
+ $data{state_message} = _("This report is currently marked as closed.")
+ } else {
+ $data{state_message} = _("This report is currently marked as open.");
+ }
+
+ my $url = $cobrand->base_url_for_report($row);
+ # this is currently only for new_updates
+ if ($row->{item_text}) {
+ if ( $cobrand->moniker ne 'zurich' && $row->{alert_user_id} == $row->{user_id} ) {
+ # This is an alert to the same user who made the report - make this a login link
+ # Don't bother with Zurich which has no accounts
+ my $user = $schema->resultset('User')->find( {
+ id => $row->{alert_user_id}
+ } );
+ $data{alert_email} = $user->email;
+ my $token_obj = $schema->resultset('Token')->create( {
+ scope => 'alert_to_reporter',
+ data => {
+ id => $row->{id},
+ }
+ } );
+ $data{problem_url} = $url . "/R/" . $token_obj->token;
+ } else {
+ $data{problem_url} = $url . "/report/" . $row->{id};
+ }
+ $data{data} .= $row->{item_name} . ' : ' if $row->{item_name} && !$row->{item_anonymous};
+ if ( $cobrand->include_time_in_update_alerts ) {
+ my $parser = DateTime::Format::Pg->new();
+ my $dt = $parser->parse_timestamp( $row->{item_confirmed} );
+ # We need to always set this otherwise we end up with the DateTime
+ # object being in the floating timezone in which case applying a
+ # subsequent timezone set will have no effect.
+ # this is basically recreating the code from the inflate wrapper
+ # in the database model.
+ FixMyStreet->set_time_zone($dt);
+ $data{data} .= $cobrand->prettify_dt( $dt, 'alert' ) . "\n\n";
+ }
+ $data{data} .= $row->{item_text} . "\n\n------\n\n";
+ # this is ward and council problems
+ } else {
+ $data{data} .= $url . "/report/" . $row->{id} . " - $row->{title}\n\n";
+ if ( exists $row->{geocode} && $row->{geocode} && $ref =~ /ward|council/ ) {
+ my $nearest_st = _get_address_from_gecode( $row->{geocode} );
+ $data{data} .= $nearest_st if $nearest_st;
+ }
+ $data{data} .= "\n\n------\n\n";
+ }
+ if (!$data{alert_user_id}) {
+ %data = (%data, %$row);
+ if ($ref eq 'area_problems' || $ref eq 'council_problems' || $ref eq 'ward_problems') {
+ my $va_info = mySociety::MaPit::call('area', $row->{alert_parameter});
+ $data{area_name} = $va_info->{name};
+ }
+ if ($ref eq 'ward_problems') {
+ my $va_info = mySociety::MaPit::call('area', $row->{alert_parameter2});
+ $data{ward_name} = $va_info->{name};
+ }
+ }
+ $data{cobrand} = $row->{alert_cobrand};
+ $data{cobrand_data} = $row->{alert_cobrand_data};
+ $data{lang} = $row->{alert_lang};
+ $last_alert_id = $row->{alert_id};
+ }
+ if ($last_alert_id) {
+ _send_aggregated_alert_email(%data);
+ }
+ }
+
+ # Nearby done separately as the table contains the parameters
+ my $template = $rs->find( { ref => 'local_problems' } )->template;
+ my $query = $schema->resultset('Alert')->search( {
+ alert_type => 'local_problems',
+ whendisabled => undef,
+ confirmed => 1
+ }, {
+ order_by => 'id'
+ } );
+ while (my $alert = $query->next) {
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($alert->cobrand)->new();
+ next unless $cobrand->email_host;
+ next if $alert->is_from_abuser;
+
+ my $longitude = $alert->parameter;
+ my $latitude = $alert->parameter2;
+ my $d = mySociety::Gaze::get_radius_containing_population($latitude, $longitude, 200000);
+ # Convert integer to GB locale string (with a ".")
+ $d = mySociety::Locale::in_gb_locale {
+ sprintf("%f", int($d*10+0.5)/10);
+ };
+ my $states = "'" . join( "', '", FixMyStreet::DB::Result::Problem::visible_states() ) . "'";
+ my %data = (
+ template => $template,
+ data => '',
+ alert_id => $alert->id,
+ alert_email => $alert->user->email,
+ lang => $alert->lang,
+ cobrand => $alert->cobrand,
+ cobrand_data => $alert->cobrand_data,
+ schema => $schema,
+ );
+ my $q = "select problem.id, problem.bodies_str, problem.postcode, problem.geocode, problem.title from problem_find_nearby(?, ?, ?) as nearby, problem, users
+ where nearby.problem_id = problem.id
+ and problem.user_id = users.id
+ and problem.state in ($states)
+ and problem.non_public = 'f'
+ and problem.confirmed >= ? and problem.confirmed >= current_timestamp - '7 days'::interval
+ and (select whenqueued from alert_sent where alert_sent.alert_id = ? and alert_sent.parameter::integer = problem.id) is null
+ and users.email <> ?
+ order by confirmed desc";
+ $q = dbh()->prepare($q);
+ $q->execute($latitude, $longitude, $d, $alert->whensubscribed, $alert->id, $alert->user->email);
+ while (my $row = $q->fetchrow_hashref) {
+ $schema->resultset('AlertSent')->create( {
+ alert_id => $alert->id,
+ parameter => $row->{id},
+ } );
+ my $url = $cobrand->base_url_for_report($row);
+ $data{data} .= $url . "/report/" . $row->{id} . " - $row->{title}\n\n";
+ if ( exists $row->{geocode} && $row->{geocode} ) {
+ my $nearest_st = _get_address_from_gecode( $row->{geocode} );
+ $data{data} .= $nearest_st if $nearest_st;
+ }
+ $data{data} .= "\n\n------\n\n";
+ }
+ _send_aggregated_alert_email(%data) if $data{data};
+ }
+}
+
+sub _send_aggregated_alert_email(%) {
+ my %data = @_;
+
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($data{cobrand})->new();
+
+ $cobrand->set_lang_and_domain( $data{lang}, 1, FixMyStreet->path_to('locale')->stringify );
+
+ if (!$data{alert_email}) {
+ my $user = $data{schema}->resultset('User')->find( {
+ id => $data{alert_user_id}
+ } );
+ $data{alert_email} = $user->email;
+ }
+
+ my ($domain) = $data{alert_email} =~ m{ @ (.*) \z }x;
+ return if $data{schema}->resultset('Abuse')->search( {
+ email => [ $data{alert_email}, $domain ]
+ } )->first;
+
+ my $token = $data{schema}->resultset("Token")->new_result( {
+ scope => 'alert',
+ data => {
+ id => $data{alert_id},
+ type => 'unsubscribe',
+ email => $data{alert_email},
+ }
+ } );
+ $data{unsubscribe_url} = $cobrand->base_url( $data{cobrand_data} ) . '/A/' . $token->token;
+
+ my $template = FixMyStreet->get_email_template($cobrand->moniker, $data{lang}, "$data{template}.txt");
+
+ my $result = FixMyStreet::Email::send_cron(
+ $data{schema},
+ {
+ _template_ => $template,
+ _parameters_ => \%data,
+ To => $data{alert_email},
+ },
+ undef,
+ 0,
+ $cobrand,
+ $data{lang}
+ );
+
+ unless ($result) {
+ $token->insert();
+ } else {
+ print "Failed to send alert $data{alert_id}!";
+ }
+}
+
+sub _get_address_from_gecode {
+ my $geocode = shift;
+
+ return '' unless defined $geocode;
+ utf8::encode($geocode) if utf8::is_utf8($geocode);
+ my $h = new IO::String($geocode);
+ my $data = RABX::wire_rd($h);
+
+ my $str = '';
+
+ my $address = $data->{resourceSets}[0]{resources}[0]{address};
+ my @address;
+ push @address, $address->{addressLine} if $address->{addressLine} && $address->{addressLine} ne 'Street';
+ push @address, $address->{locality} if $address->{locality};
+ $str .= sprintf(_("Nearest road to the pin placed on the map (automatically generated by Bing Maps): %s\n\n"),
+ join( ', ', @address ) ) if @address;
+
+ return $str;
+}
+
+1;
diff --git a/perllib/FixMyStreet/Script/Questionnaires.pm b/perllib/FixMyStreet/Script/Questionnaires.pm
new file mode 100644
index 000000000..2d676f15d
--- /dev/null
+++ b/perllib/FixMyStreet/Script/Questionnaires.pm
@@ -0,0 +1,117 @@
+package FixMyStreet::Script::Questionnaires;
+
+use strict;
+use warnings;
+use Utils;
+use FixMyStreet::DB;
+use FixMyStreet::Email;
+use FixMyStreet::Cobrand;
+
+sub send {
+ my ( $params ) = @_;
+ send_questionnaires_period( '4 weeks', $params );
+ send_questionnaires_period( '26 weeks', $params )
+ if $params->{site} eq 'emptyhomes';
+}
+
+sub send_questionnaires_period {
+ my ( $period, $params ) = @_;
+
+ my $rs = FixMyStreet::DB->resultset('Questionnaire');
+
+ # Select all problems that need a questionnaire email sending
+ my $q_params = {
+ state => [ FixMyStreet::DB::Result::Problem::visible_states() ],
+ whensent => [
+ '-and',
+ { '!=', undef },
+ { '<', \"current_timestamp - '$period'::interval" },
+ ],
+ send_questionnaire => 1,
+ };
+ # FIXME Do these a bit better...
+ if ($params->{site} eq 'emptyhomes' && $period eq '4 weeks') {
+ $q_params->{'(select max(whensent) from questionnaire where me.id=problem_id)'} = undef;
+ } elsif ($params->{site} eq 'emptyhomes' && $period eq '26 weeks') {
+ $q_params->{'(select max(whensent) from questionnaire where me.id=problem_id)'} = { '!=', undef };
+ } else {
+ $q_params->{'-or'} = [
+ '(select max(whensent) from questionnaire where me.id=problem_id)' => undef,
+ '(select max(whenanswered) from questionnaire where me.id=problem_id)' => { '<', \"current_timestamp - '$period'::interval" }
+ ];
+ }
+
+ my $unsent = FixMyStreet::DB->resultset('Problem')->search( $q_params, {
+ order_by => { -desc => 'confirmed' }
+ } );
+
+ while (my $row = $unsent->next) {
+
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->cobrand)->new();
+ $cobrand->set_lang_and_domain($row->lang, 1);
+
+ # Not all cobrands send questionnaires
+ next unless $cobrand->send_questionnaires;
+ next if $row->is_from_abuser;
+
+ # Cobranded and non-cobranded messages can share a database. In this case, the conf file
+ # should specify a vhost to send the reports for each cobrand, so that they don't get sent
+ # more than once if there are multiple vhosts running off the same database. The email_host
+ # call checks if this is the host that sends mail for this cobrand.
+ next unless $cobrand->email_host;
+
+ my $template;
+ if ($params->{site} eq 'emptyhomes') {
+ ($template = $period) =~ s/ //;
+ $template = Utils::read_file( FixMyStreet->path_to( "templates/email/emptyhomes/" . $row->lang . "/questionnaire-$template.txt" )->stringify );
+ } else {
+ $template = FixMyStreet->get_email_template($cobrand->moniker, $row->lang, 'questionnaire.txt');
+ }
+
+ my %h = map { $_ => $row->$_ } qw/name title detail category/;
+ $h{created} = Utils::prettify_duration( time() - $row->confirmed->epoch, 'week' );
+
+ my $questionnaire = $rs->create( {
+ problem_id => $row->id,
+ whensent => \'current_timestamp',
+ } );
+
+ # We won't send another questionnaire unless they ask for it (or it was
+ # the first EHA questionnaire.
+ $row->send_questionnaire( 0 )
+ if $params->{site} ne 'emptyhomes' || $period eq '26 weeks';
+
+ my $token = FixMyStreet::DB->resultset("Token")->new_result( {
+ scope => 'questionnaire',
+ data => $questionnaire->id,
+ } );
+ $h{url} = $cobrand->base_url($row->cobrand_data) . '/Q/' . $token->token;
+
+ print "Sending questionnaire " . $questionnaire->id . ", problem "
+ . $row->id . ", token " . $token->token . " to "
+ . $row->user->email . "\n"
+ if $params->{verbose};
+
+ my $result = FixMyStreet::Email::send_cron(
+ $rs->result_source->schema,
+ {
+ _template_ => $template,
+ _parameters_ => \%h,
+ To => [ [ $row->user->email, $row->name ] ],
+ },
+ undef,
+ $params->{nomail},
+ $cobrand
+ );
+ unless ($result) {
+ print " ...success\n" if $params->{verbose};
+ $row->update();
+ $token->insert();
+ } else {
+ print " ...failed\n" if $params->{verbose};
+ $questionnaire->delete;
+ }
+ }
+}
+
+1;
diff --git a/perllib/FixMyStreet/Script/Reports.pm b/perllib/FixMyStreet/Script/Reports.pm
new file mode 100644
index 000000000..55b1bb21c
--- /dev/null
+++ b/perllib/FixMyStreet/Script/Reports.pm
@@ -0,0 +1,313 @@
+package FixMyStreet::Script::Reports;
+
+use strict;
+use warnings;
+
+use CronFns;
+use DateTime::Format::Pg;
+
+use Utils;
+use mySociety::MaPit;
+
+use FixMyStreet;
+use FixMyStreet::Cobrand;
+use FixMyStreet::DB;
+use FixMyStreet::Email;
+use FixMyStreet::SendReport;
+
+sub send(;$) {
+ my ($site_override) = @_;
+ my $rs = FixMyStreet::DB->resultset('Problem');
+
+ # Set up site, language etc.
+ my ($verbose, $nomail, $debug_mode) = CronFns::options();
+
+ my $base_url = FixMyStreet->config('BASE_URL');
+ my $site = $site_override || CronFns::site($base_url);
+
+ my $states = [ 'confirmed', 'fixed' ];
+ $states = [ 'unconfirmed', 'confirmed', 'in progress', 'planned', 'closed', 'investigating' ] if $site eq 'zurich';
+ my $unsent = $rs->search( {
+ state => $states,
+ whensent => undef,
+ bodies_str => { '!=', undef },
+ } );
+ my (%notgot, %note);
+
+ my $send_report = FixMyStreet::SendReport->new();
+ my $senders = $send_report->get_senders;
+
+ my $debug_unsent_count = 0;
+ debug_print("starting to loop through unsent problem reports...") if $debug_mode;
+ while (my $row = $unsent->next) {
+
+ my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($row->cobrand)->new();
+
+ if ($debug_mode) {
+ $debug_unsent_count++;
+ print "\n";
+ debug_print("state=" . $row->state . ", bodies_str=" . $row->bodies_str . ($row->cobrand? ", cobrand=" . $row->cobrand : ""), $row->id);
+ }
+
+ # Cobranded and non-cobranded messages can share a database. In this case, the conf file
+ # should specify a vhost to send the reports for each cobrand, so that they don't get sent
+ # more than once if there are multiple vhosts running off the same database. The email_host
+ # call checks if this is the host that sends mail for this cobrand.
+ if (! $cobrand->email_host()) {
+ debug_print("skipping because this host does not send reports for cobrand " . $cobrand->moniker, $row->id) if $debug_mode;
+ next;
+ }
+
+ $cobrand->set_lang_and_domain($row->lang, 1);
+ if ( $row->is_from_abuser) {
+ $row->update( { state => 'hidden' } );
+ debug_print("hiding because its sender is flagged as an abuser", $row->id) if $debug_mode;
+ next;
+ } elsif ( $row->title =~ /app store test/i ) {
+ $row->update( { state => 'hidden' } );
+ debug_print("hiding because it is an app store test message", $row->id) if $debug_mode;
+ next;
+ }
+
+ # Template variables for the email
+ my $email_base_url = $cobrand->base_url_for_report($row);
+ my %h = map { $_ => $row->$_ } qw/id title detail name category latitude longitude used_map/;
+ map { $h{$_} = $row->user->$_ || '' } qw/email phone/;
+ $h{confirmed} = DateTime::Format::Pg->format_datetime( $row->confirmed->truncate (to => 'second' ) )
+ if $row->confirmed;
+
+ $h{query} = $row->postcode;
+ $h{url} = $email_base_url . $row->url;
+ $h{admin_url} = $row->admin_url($cobrand);
+ $h{phone_line} = $h{phone} ? _('Phone:') . " $h{phone}\n\n" : '';
+ if ($row->photo) {
+ $h{has_photo} = _("This web page also contains a photo of the problem, provided by the user.") . "\n\n";
+ $h{image_url} = $email_base_url . '/photo/' . $row->id . '.full.jpeg';
+ } else {
+ $h{has_photo} = '';
+ $h{image_url} = '';
+ }
+ $h{fuzzy} = $row->used_map ? _('To view a map of the precise location of this issue')
+ : _('The user could not locate the problem on a map, but to see the area around the location they entered');
+ $h{closest_address} = '';
+
+ if ( $row->used_map ) {
+ $h{closest_address} = $cobrand->find_closest( $h{latitude}, $h{longitude}, $row );
+ }
+
+ if ( $cobrand->allow_anonymous_reports &&
+ $row->user->email eq $cobrand->anonymous_account->{'email'}
+ ) {
+ $h{anonymous_report} = 1;
+ $h{user_details} = _('This report was submitted anonymously');
+ } else {
+ $h{user_details} = sprintf(_('Name: %s'), $row->name) . "\n\n";
+ $h{user_details} .= sprintf(_('Email: %s'), $row->user->email) . "\n\n";
+ }
+
+ $h{easting_northing} = '';
+
+ if ($cobrand->can('process_additional_metadata_for_email')) {
+ $cobrand->process_additional_metadata_for_email($row, \%h);
+ }
+
+ my $bodies = FixMyStreet::DB->resultset('Body')->search(
+ { id => $row->bodies_str_ids },
+ { order_by => 'name' },
+ );
+
+ my $missing;
+ if ($row->bodies_missing) {
+ my @missing = FixMyStreet::DB->resultset("Body")->search(
+ { id => [ split /,/, $row->bodies_missing ] },
+ { order_by => 'name' }
+ )->get_column('name')->all;
+ $missing = join(' / ', @missing) if @missing;
+ }
+
+ my @dear;
+ my %reporters = ();
+ while (my $body = $bodies->next) {
+ my $sender_info = $cobrand->get_body_sender( $body, $row->category );
+ my $sender = "FixMyStreet::SendReport::" . $sender_info->{method};
+
+ if ( ! exists $senders->{ $sender } ) {
+ warn sprintf "No such sender [ $sender ] for body %s ( %d )", $body->name, $body->id;
+ next;
+ }
+ $reporters{ $sender } ||= $sender->new();
+
+ if ( $reporters{ $sender }->should_skip( $row ) ) {
+ debug_print("skipped by sender " . $sender_info->{method} . " (might be due to previous failed attempts?)", $row->id) if $debug_mode;
+ } else {
+ debug_print("OK, adding recipient body " . $body->id . ":" . $body->name . ", " . $body->send_method, $row->id) if $debug_mode;
+ push @dear, $body->name;
+ $reporters{ $sender }->add_body( $body, $sender_info->{config} );
+ }
+
+ # If we are in the UK include eastings and northings, and nearest stuff
+ if ( $cobrand->country eq 'GB' && !$h{easting} ) {
+ my $coordsyst = 'G';
+ my $first_area = $body->body_areas->first->area_id;
+ my $area_info = mySociety::MaPit::call('area', $first_area);
+ $coordsyst = 'I' if $area_info->{type} eq 'LGD';
+
+ ( $h{easting}, $h{northing} ) = Utils::convert_latlon_to_en( $h{latitude}, $h{longitude}, $coordsyst );
+
+ # email templates don't have conditionals so we need to format this here
+ $h{easting_northing} = "Easting/Northing";
+ $h{easting_northing} .= " (IE)" if $coordsyst eq 'I';
+ $h{easting_northing} .= ": $h{easting}/$h{northing}\n\n";
+ }
+ }
+
+ unless ( keys %reporters ) {
+ die 'Report not going anywhere for ID ' . $row->id . '!';
+ }
+
+ unless (@dear) {
+ debug_print("can't send because sender count is zero", $row->id) if $debug_mode;
+ next;
+ }
+
+ if ($h{category} eq _('Other')) {
+ $h{category_footer} = _('this type of local problem');
+ $h{category_line} = '';
+ } else {
+ $h{category_footer} = "'" . $h{category} . "'";
+ $h{category_line} = sprintf(_("Category: %s"), $h{category}) . "\n\n";
+ }
+
+ if ( $row->subcategory ) {
+ $h{subcategory_line} = sprintf(_("Subcategory: %s"), $row->subcategory) . "\n\n";
+ } else {
+ $h{subcategory_line} = "\n\n";
+ }
+
+ $h{bodies_name} = join(_(' and '), @dear);
+ if ($h{category} eq _('Other')) {
+ $h{multiple} = @dear>1 ? "[ " . _("This email has been sent to both councils covering the location of the problem, as the user did not categorise it; please ignore it if you're not the correct council to deal with the issue, or let us know what category of problem this is so we can add it to our system.") . " ]\n\n"
+ : '';
+ } else {
+ $h{multiple} = @dear>1 ? "[ " . _("This email has been sent to several councils covering the location of the problem, as the category selected is provided for all of them; please ignore it if you're not the correct council to deal with the issue.") . " ]\n\n"
+ : '';
+ }
+ $h{missing} = '';
+ if ($missing) {
+ $h{missing} = '[ '
+ . sprintf(_('We realise this problem might be the responsibility of %s; however, we don\'t currently have any contact details for them. If you know of an appropriate contact address, please do get in touch.'), $missing)
+ . " ]\n\n";
+ }
+
+ if (FixMyStreet->config('STAGING_SITE') && !FixMyStreet->config('SEND_REPORTS_ON_STAGING')) {
+ # on a staging server send emails to ourselves rather than the bodies
+ %reporters = map { $_ => $reporters{$_} } grep { /FixMyStreet::SendReport::(Email|EmptyHomes)/ } keys %reporters;
+ unless (%reporters) {
+ %reporters = ( 'FixMyStreet::SendReport::Email' => FixMyStreet::SendReport::Email->new() );
+ }
+ }
+
+ # Multiply results together, so one success counts as a success.
+ my $result = -1;
+
+ for my $sender ( keys %reporters ) {
+ debug_print("sending using " . $sender, $row->id) if $debug_mode;
+ $result *= $reporters{ $sender }->send( $row, \%h );
+ if ( $reporters{ $sender }->unconfirmed_counts) {
+ foreach my $e (keys %{ $reporters{ $sender }->unconfirmed_counts } ) {
+ foreach my $c (keys %{ $reporters{ $sender }->unconfirmed_counts->{$e} }) {
+ $notgot{$e}{$c} += $reporters{ $sender }->unconfirmed_counts->{$e}{$c};
+ }
+ }
+ %note = (
+ %note,
+ %{ $reporters{ $sender }->unconfirmed_notes }
+ );
+ }
+ }
+
+ unless ($result) {
+ $row->update( {
+ whensent => \'current_timestamp',
+ lastupdate => \'current_timestamp',
+ } );
+ if ( $cobrand->report_sent_confirmation_email && !$h{anonymous_report}) {
+ _send_report_sent_email( $row, \%h, $nomail, $cobrand );
+ }
+ debug_print("send successful: OK", $row->id) if $debug_mode;
+ } else {
+ my @errors;
+ for my $sender ( keys %reporters ) {
+ unless ( $reporters{ $sender }->success ) {
+ push @errors, $reporters{ $sender }->error;
+ }
+ }
+ $row->update_send_failed( join( '|', @errors ) );
+ debug_print("send FAILED: " . join( '|', @errors ), $row->id) if $debug_mode;
+ }
+ }
+ if ($debug_mode) {
+ print "\n";
+ if ($debug_unsent_count) {
+ debug_print("processed all unsent reports (total: $debug_unsent_count)");
+ } else {
+ debug_print("no unsent reports were found (must have whensent=null and suitable bodies_str & state) -- nothing to send");
+ }
+ }
+
+ if ($verbose || $debug_mode) {
+ print "Council email addresses that need checking:\n" if keys %notgot;
+ foreach my $e (keys %notgot) {
+ foreach my $c (keys %{$notgot{$e}}) {
+ print " " . $notgot{$e}{$c} . " problem, to $e category $c (" . $note{$e}{$c}. ")\n";
+ }
+ }
+ my $sending_errors = '';
+ my $unsent = $rs->search( {
+ state => [ 'confirmed', 'fixed' ],
+ whensent => undef,
+ bodies_str => { '!=', undef },
+ send_fail_count => { '>', 0 }
+ } );
+ while (my $row = $unsent->next) {
+ my $base_url = FixMyStreet->config('BASE_URL');
+ $sending_errors .= "* " . $base_url . "/report/" . $row->id . ", failed "
+ . $row->send_fail_count . " times, last at " . $row->send_fail_timestamp
+ . ", reason " . $row->send_fail_reason . "\n";
+ }
+ if ($sending_errors) {
+ print "The following reports had problems sending:\n$sending_errors";
+ }
+ }
+}
+
+sub _send_report_sent_email {
+ my $row = shift;
+ my $h = shift;
+ my $nomail = shift;
+ my $cobrand = shift;
+
+ my $template = FixMyStreet->get_email_template($row->cobrand, $row->lang, 'confirm_report_sent.txt');
+
+ FixMyStreet::Email::send_cron(
+ $row->result_source->schema,
+ {
+ _template_ => $template,
+ _parameters_ => $h,
+ To => $row->user->email,
+ From => [ FixMyStreet->config('CONTACT_EMAIL'), $cobrand->contact_name ],
+ },
+ FixMyStreet->config('CONTACT_EMAIL'),
+ $nomail,
+ $cobrand
+ );
+}
+
+sub debug_print {
+ my $msg = shift;
+ my $id = shift || '';
+ $id = "report $id: " if $id;
+ print "[] $id$msg\n";
+}
+
+1;
diff --git a/perllib/FixMyStreet/SendReport.pm b/perllib/FixMyStreet/SendReport.pm
index 9967b0663..40ec4caf2 100644
--- a/perllib/FixMyStreet/SendReport.pm
+++ b/perllib/FixMyStreet/SendReport.pm
@@ -1,20 +1,21 @@
package FixMyStreet::SendReport;
-use Moose;
+use Moo;
+use MooX::Types::MooseLike::Base qw(:all);
use Module::Pluggable
sub_name => 'senders',
search_path => __PACKAGE__,
require => 1;
-has 'body_config' => ( is => 'rw', isa => 'HashRef', default => sub { {} } );
-has 'bodies' => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
-has 'to' => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
-has 'bcc' => ( is => 'rw', isa => 'ArrayRef', default => sub { [] } );
-has 'success' => ( is => 'rw', isa => 'Bool', default => 0 );
-has 'error' => ( is => 'rw', isa => 'Str', default => '' );
-has 'unconfirmed_counts' => ( 'is' => 'rw', isa => 'HashRef', default => sub { {} } );
-has 'unconfirmed_notes' => ( 'is' => 'rw', isa => 'HashRef', default => sub { {} } );
+has 'body_config' => ( is => 'rw', isa => HashRef, default => sub { {} } );
+has 'bodies' => ( is => 'rw', isa => ArrayRef, default => sub { [] } );
+has 'to' => ( is => 'rw', isa => ArrayRef, default => sub { [] } );
+has 'bcc' => ( is => 'rw', isa => ArrayRef, default => sub { [] } );
+has 'success' => ( is => 'rw', isa => Bool, default => 0 );
+has 'error' => ( is => 'rw', isa => Str, default => '' );
+has 'unconfirmed_counts' => ( 'is' => 'rw', isa => HashRef, default => sub { {} } );
+has 'unconfirmed_notes' => ( 'is' => 'rw', isa => HashRef, default => sub { {} } );
sub should_skip {
diff --git a/perllib/FixMyStreet/SendReport/EastHants.pm b/perllib/FixMyStreet/SendReport/EastHants.pm
index 44bc084b1..3eb8ffcfa 100644
--- a/perllib/FixMyStreet/SendReport/EastHants.pm
+++ b/perllib/FixMyStreet/SendReport/EastHants.pm
@@ -1,6 +1,6 @@
package FixMyStreet::SendReport::EastHants;
-use Moose;
+use Moo;
BEGIN { extends 'FixMyStreet::SendReport'; }
@@ -28,7 +28,7 @@ EOF
}
sub send {
- return if mySociety::Config::get('STAGING_SITE');
+ return if FixMyStreet->config('STAGING_SITE');
my ( $self, $row, $h ) = @_;
diff --git a/perllib/FixMyStreet/SendReport/Email.pm b/perllib/FixMyStreet/SendReport/Email.pm
index bac408510..4d2c8bb17 100644
--- a/perllib/FixMyStreet/SendReport/Email.pm
+++ b/perllib/FixMyStreet/SendReport/Email.pm
@@ -1,6 +1,6 @@
package FixMyStreet::SendReport::Email;
-use Moose;
+use Moo;
use FixMyStreet::Email;
BEGIN { extends 'FixMyStreet::SendReport'; }
@@ -11,7 +11,7 @@ sub build_recipient_list {
my $all_confirmed = 1;
foreach my $body ( @{ $self->bodies } ) {
- my $contact = FixMyStreet::App->model("DB::Contact")->find( {
+ my $contact = $row->result_source->schema->resultset("Contact")->find( {
deleted => 0,
body_id => $body->id,
category => $row->category
@@ -75,7 +75,7 @@ sub send {
my $recips = $self->build_recipient_list( $row, $h );
# on a staging server send emails to ourselves rather than the bodies
- if (mySociety::Config::get('STAGING_SITE') && !mySociety::Config::get('SEND_REPORTS_ON_STAGING') && !FixMyStreet->test_mode) {
+ if (FixMyStreet->config('STAGING_SITE') && !FixMyStreet->config('SEND_REPORTS_ON_STAGING') && !FixMyStreet->test_mode) {
$recips = 1;
@{$self->to} = [ $row->user->email, $self->to->[0][1] || $row->name ];
}
@@ -94,20 +94,19 @@ sub send {
From => $self->send_from( $row ),
};
- my $app = FixMyStreet::App->new( cobrand => $cobrand );
-
- $cobrand->munge_sendreport_params($app, $row, $h, $params) if $cobrand->can('munge_sendreport_params');
+ $cobrand->munge_sendreport_params($row, $h, $params) if $cobrand->can('munge_sendreport_params');
$params->{Bcc} = $self->bcc if @{$self->bcc};
if (FixMyStreet::Email::test_dmarc($params->{From}[0])) {
$params->{'Reply-To'} = [ $params->{From} ];
- $params->{From} = [ mySociety::Config::get('CONTACT_EMAIL'), $params->{From}[1] ];
+ $params->{From} = [ FixMyStreet->config('CONTACT_EMAIL'), $params->{From}[1] ];
}
- my $result = $app->send_email_cron(
+ my $result = FixMyStreet::Email::send_cron(
+ $row->result_source->schema,
$params,
- mySociety::Config::get('CONTACT_EMAIL'),
+ FixMyStreet->config('CONTACT_EMAIL'),
$nomail,
$cobrand
);
diff --git a/perllib/FixMyStreet/SendReport/EmptyHomes.pm b/perllib/FixMyStreet/SendReport/EmptyHomes.pm
index ce69aaac3..b5faf8ddc 100644
--- a/perllib/FixMyStreet/SendReport/EmptyHomes.pm
+++ b/perllib/FixMyStreet/SendReport/EmptyHomes.pm
@@ -1,6 +1,6 @@
package FixMyStreet::SendReport::EmptyHomes;
-use Moose;
+use Moo;
use namespace::autoclean;
use mySociety::MaPit;
@@ -12,7 +12,7 @@ sub build_recipient_list {
my $all_confirmed = 1;
foreach my $body ( @{ $self->bodies } ) {
- my $contact = FixMyStreet::App->model("DB::Contact")->find( {
+ my $contact = $row->result_source->schema->resultset("Contact")->find( {
deleted => 0,
body_id => $body->id,
category => 'Empty property',
@@ -34,11 +34,11 @@ sub build_recipient_list {
my $area_info = mySociety::MaPit::call('area', $body->body_areas->first->area_id);
my $country = $area_info->{country};
if ($country eq 'W') {
- push @{$self->bcc}, 'wales@' . mySociety::Config::get('EMAIL_DOMAIN');
+ push @{$self->bcc}, 'wales@' . FixMyStreet->config('EMAIL_DOMAIN');
} elsif ($country eq 'S') {
- push @{$self->bcc}, 'scotland@' . mySociety::Config::get('EMAIL_DOMAIN');
+ push @{$self->bcc}, 'scotland@' . FixMyStreet->config('EMAIL_DOMAIN');
} else {
- push @{$self->bcc}, 'eha@' . mySociety::Config::get('EMAIL_DOMAIN');
+ push @{$self->bcc}, 'eha@' . FixMyStreet->config('EMAIL_DOMAIN');
}
}
diff --git a/perllib/FixMyStreet/SendReport/Noop.pm b/perllib/FixMyStreet/SendReport/Noop.pm
index f2e0a3bdb..60edda373 100644
--- a/perllib/FixMyStreet/SendReport/Noop.pm
+++ b/perllib/FixMyStreet/SendReport/Noop.pm
@@ -1,6 +1,6 @@
package FixMyStreet::SendReport::Noop;
-use Moose;
+use Moo;
BEGIN { extends 'FixMyStreet::SendReport'; }
diff --git a/perllib/FixMyStreet/SendReport/Open311.pm b/perllib/FixMyStreet/SendReport/Open311.pm
index fa216466e..4844aa2e9 100644
--- a/perllib/FixMyStreet/SendReport/Open311.pm
+++ b/perllib/FixMyStreet/SendReport/Open311.pm
@@ -1,12 +1,10 @@
package FixMyStreet::SendReport::Open311;
-use Moose;
+use Moo;
use namespace::autoclean;
BEGIN { extends 'FixMyStreet::SendReport'; }
-use FixMyStreet::App;
-use mySociety::Config;
use DateTime::Format::W3CDTF;
use Open311;
use Readonly;
@@ -85,7 +83,7 @@ sub send {
}
# FIXME: we've already looked this up before
- my $contact = FixMyStreet::App->model("DB::Contact")->find( {
+ my $contact = $row->result_source->schema->resultset("Contact")->find( {
deleted => 0,
body_id => $body->id,
category => $row->category
diff --git a/perllib/FixMyStreet/SendReport/Refused.pm b/perllib/FixMyStreet/SendReport/Refused.pm
index d71fc5c2c..c6c1a660d 100644
--- a/perllib/FixMyStreet/SendReport/Refused.pm
+++ b/perllib/FixMyStreet/SendReport/Refused.pm
@@ -1,6 +1,6 @@
package FixMyStreet::SendReport::Refused;
-use Moose;
+use Moo;
BEGIN { extends 'FixMyStreet::SendReport::Noop'; }
diff --git a/perllib/FixMyStreet/SendReport/Zurich.pm b/perllib/FixMyStreet/SendReport/Zurich.pm
index 2838440cb..a8730bbe4 100644
--- a/perllib/FixMyStreet/SendReport/Zurich.pm
+++ b/perllib/FixMyStreet/SendReport/Zurich.pm
@@ -1,6 +1,6 @@
package FixMyStreet::SendReport::Zurich;
-use Moose;
+use Moo;
BEGIN { extends 'FixMyStreet::SendReport::Email'; }
@@ -14,7 +14,7 @@ sub build_recipient_list {
# Wunsch set, but external_message hasn't yet been filled in. TODO should
# we instead be holding off sending?)
if ( $row->external_body ) {
- $body = FixMyStreet::App->model("DB::Body")->find( { id => $row->external_body } );
+ $body = $row->result_source->schema->resultset("Body")->find( { id => $row->external_body } );
$h->{bodies_name} = $body->name;
$h->{external_message} = $row->get_extra_metadata('external_message') || '';
}
@@ -29,7 +29,7 @@ sub build_recipient_list {
my $parent = $body->parent;
if ($parent && !$parent->parent) {
# Division, might have an individual contact email address
- my $contact = FixMyStreet::App->model("DB::Contact")->find( {
+ my $contact = $row->result_source->schema->resultset("Contact")->find( {
body_id => $body->id,
category => $row->category
} );
@@ -72,7 +72,7 @@ sub send_from {
if ( $row->external_body ) {
my $body = @{ $self->bodies }[0];
my $body_email = $body->endpoint;
- my $contact = FixMyStreet::App->model("DB::Contact")->find( {
+ my $contact = $body->result_source->schema->resultset("Contact")->find( {
body_id => $body->id,
category => $row->category
} );
diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm
index cc5f9dd71..d3adce08b 100644
--- a/perllib/FixMyStreet/TestMech.pm
+++ b/perllib/FixMyStreet/TestMech.pm
@@ -66,7 +66,7 @@ sub create_user_ok {
my ($email) = @_;
my $user =
- FixMyStreet::App->model('DB::User')
+ FixMyStreet::DB->resultset('User')
->find_or_create( { email => $email } );
ok $user, "found/created user for $email";
@@ -147,7 +147,7 @@ sub delete_user {
my $user =
ref $email_or_user
? $email_or_user
- : FixMyStreet::App->model('DB::User')
+ : FixMyStreet::DB->resultset('User')
->find( { email => $email_or_user } );
# If no user found we can't delete them
@@ -567,7 +567,7 @@ sub delete_problems_for_body {
my $mech = shift;
my $body = shift;
- my $reports = FixMyStreet::App->model('DB::Problem')->search( { bodies_str => $body } );
+ my $reports = FixMyStreet::DB->resultset('Problem')->search( { bodies_str => $body } );
if ( $reports ) {
for my $r ( $reports->all ) {
$r->comments->delete;
@@ -587,7 +587,7 @@ sub create_contact_ok {
note => 'Created for test',
@_
);
- my $contact = FixMyStreet::App->model('DB::Contact')->find_or_create( \%contact_params );
+ my $contact = FixMyStreet::DB->resultset('Contact')->find_or_create( \%contact_params );
ok $contact, 'found/created contact ' . $contact->category;;
return $contact;
}
@@ -596,7 +596,7 @@ sub create_body_ok {
my $self = shift;
my ( $area_id, $name, %extra ) = @_;
- my $body = FixMyStreet::App->model('DB::Body');
+ my $body = FixMyStreet::DB->resultset('Body');
my $params = { name => $name };
if ($extra{id}) {
$body = $body->update_or_create({ %$params, id => $extra{id} }, { key => 'primary' });
@@ -606,7 +606,7 @@ sub create_body_ok {
ok $body, "found/created body $name";
$body->body_areas->delete;
- FixMyStreet::App->model('DB::BodyArea')->find_or_create({
+ FixMyStreet::DB->resultset('BodyArea')->find_or_create({
area_id => $area_id,
body_id => $body->id,
});
@@ -621,7 +621,7 @@ sub create_problems_for_body {
my $dt = $params->{dt} || DateTime->now();
my $user = $params->{user} ||
- FixMyStreet::App->model('DB::User')
+ FixMyStreet::DB->resultset('User')
->find_or_create( { email => 'test@example.com', name => 'Test User' } );
delete $params->{user};
@@ -656,7 +656,7 @@ sub create_problems_for_body {
my %report_params = ( %$default_params, %$params );
my $problem =
- FixMyStreet::App->model('DB::Problem')->create( \%report_params );
+ FixMyStreet::DB->resultset('Problem')->create( \%report_params );
push @problems, $problem;
$count--;
diff --git a/perllib/Open311.pm b/perllib/Open311.pm
index 58ae96bc2..e500219bc 100644
--- a/perllib/Open311.pm
+++ b/perllib/Open311.pm
@@ -2,31 +2,34 @@ package Open311;
use utf8;
use URI;
-use Moose;
+use Moo;
+use MooX::Types::MooseLike::Base qw(:all);
use XML::Simple;
use LWP::Simple;
use LWP::UserAgent;
use DateTime::Format::W3CDTF;
use HTTP::Request::Common qw(POST);
-
-has jurisdiction => ( is => 'ro', isa => 'Str' );;
-has api_key => ( is => 'ro', isa => 'Str' );
-has endpoint => ( is => 'ro', isa => 'Str' );
-has test_mode => ( is => 'ro', isa => 'Bool' );
-has test_uri_used => ( is => 'rw', 'isa' => 'Str' );
+use FixMyStreet::Cobrand;
+use FixMyStreet::DB;
+
+has jurisdiction => ( is => 'ro', isa => Str );;
+has api_key => ( is => 'ro', isa => Str );
+has endpoint => ( is => 'ro', isa => Str );
+has test_mode => ( is => 'ro', isa => Bool );
+has test_uri_used => ( is => 'rw', 'isa' => Str );
has test_req_used => ( is => 'rw' );
has test_get_returns => ( is => 'rw' );
has endpoints => ( is => 'rw', default => sub { { services => 'services.xml', requests => 'requests.xml', service_request_updates => 'servicerequestupdates.xml', update => 'servicerequestupdates.xml' } } );
-has debug => ( is => 'ro', isa => 'Bool', default => 0 );
-has debug_details => ( is => 'rw', 'isa' => 'Str', default => '' );
-has success => ( is => 'rw', 'isa' => 'Bool', default => 0 );
-has error => ( is => 'rw', 'isa' => 'Str', default => '' );
-has always_send_latlong => ( is => 'ro', isa => 'Bool', default => 1 );
-has send_notpinpointed => ( is => 'ro', isa => 'Bool', default => 0 );
-has extended_description => ( is => 'ro', isa => 'Str', default => 1 );
-has use_service_as_deviceid => ( is => 'ro', isa => 'Bool', default => 0 );
-has use_extended_updates => ( is => 'ro', isa => 'Bool', default => 0 );
-has extended_statuses => ( is => 'ro', isa => 'Bool', default => 0 );
+has debug => ( is => 'ro', isa => Bool, default => 0 );
+has debug_details => ( is => 'rw', 'isa' => Str, default => '' );
+has success => ( is => 'rw', 'isa' => Bool, default => 0 );
+has error => ( is => 'rw', 'isa' => Str, default => '' );
+has always_send_latlong => ( is => 'ro', isa => Bool, default => 1 );
+has send_notpinpointed => ( is => 'ro', isa => Bool, default => 0 );
+has extended_description => ( is => 'ro', isa => Str, default => 1 );
+has use_service_as_deviceid => ( is => 'ro', isa => Bool, default => 0 );
+has use_extended_updates => ( is => 'ro', isa => Bool, default => 0 );
+has extended_statuses => ( is => 'ro', isa => Bool, default => 0 );
before [
qw/get_service_list get_service_meta_info get_service_requests get_service_request_updates
diff --git a/perllib/Open311/GetServiceRequestUpdates.pm b/perllib/Open311/GetServiceRequestUpdates.pm
index 1e5f4dc6b..6d846de42 100644
--- a/perllib/Open311/GetServiceRequestUpdates.pm
+++ b/perllib/Open311/GetServiceRequestUpdates.pm
@@ -1,15 +1,16 @@
package Open311::GetServiceRequestUpdates;
-use Moose;
+use Moo;
use Open311;
-use FixMyStreet::App;
+use FixMyStreet::DB;
use DateTime::Format::W3CDTF;
has system_user => ( is => 'rw' );
-has start_date => ( is => 'ro', default => undef );
-has end_date => ( is => 'ro', default => undef );
+has start_date => ( is => 'ro', default => sub { undef } );
+has end_date => ( is => 'ro', default => sub { undef } );
has suppress_alerts => ( is => 'rw', default => 0 );
has verbose => ( is => 'ro', default => 0 );
+has schema => ( is =>'ro', lazy => 1, default => sub { FixMyStreet::DB->connect } );
Readonly::Scalar my $AREA_ID_BROMLEY => 2482;
Readonly::Scalar my $AREA_ID_OXFORDSHIRE => 2237;
@@ -17,7 +18,7 @@ Readonly::Scalar my $AREA_ID_OXFORDSHIRE => 2237;
sub fetch {
my $self = shift;
- my $bodies = FixMyStreet::App->model('DB::Body')->search(
+ my $bodies = $self->schema->resultset('Body')->search(
{
send_method => 'Open311',
send_comments => 1,
@@ -91,7 +92,7 @@ sub update_comments {
my $criteria = {
external_id => $request_id,
};
- $problem = FixMyStreet::App->model('DB::Problem')->to_body($body)->search( $criteria );
+ $problem = $self->schema->resultset('Problem')->to_body($body)->search( $criteria );
if (my $p = $problem->first) {
my $c = $p->comments->search( { external_id => $request->{update_id} } );
@@ -99,7 +100,7 @@ sub update_comments {
if ( !$c->first ) {
my $comment_time = DateTime::Format::W3CDTF->parse_datetime( $request->{updated_datetime} );
- my $comment = FixMyStreet::App->model('DB::Comment')->new(
+ my $comment = $self->schema->resultset('Comment')->new(
{
problem => $p,
user => $self->system_user,
@@ -137,7 +138,7 @@ sub update_comments {
$comment->insert();
if ( $self->suppress_alerts ) {
- my @alerts = FixMyStreet::App->model('DB::Alert')->search( {
+ my @alerts = $self->schema->resultset('Alert')->search( {
alert_type => 'new_updates',
parameter => $p->id,
confirmed => 1,
@@ -145,7 +146,7 @@ sub update_comments {
} );
for my $alert (@alerts) {
- my $alerts_sent = FixMyStreet::App->model('DB::AlertSent')->find_or_create( {
+ my $alerts_sent = $self->schema->resultset('AlertSent')->find_or_create( {
alert_id => $alert->id,
parameter => $comment->id,
} );
diff --git a/perllib/Open311/GetUpdates.pm b/perllib/Open311/GetUpdates.pm
index bc55086f0..901e78809 100644
--- a/perllib/Open311/GetUpdates.pm
+++ b/perllib/Open311/GetUpdates.pm
@@ -1,8 +1,8 @@
package Open311::GetUpdates;
-use Moose;
+use Moo;
use Open311;
-use FixMyStreet::App;
+use FixMyStreet::Cobrand;
has body_list => ( is => 'ro' );
has system_user => ( is => 'ro' );
@@ -17,7 +17,7 @@ sub get_updates {
api_key => $body->api_key
);
- my $reports = FixMyStreet::App->model('DB::Problem')->to_body($body)->search(
+ my $reports = $body->result_source->schema->resultset('Problem')->to_body($body)->search(
{
state => { 'IN', [qw/confirmed fixed/] },
-and => [
@@ -62,8 +62,7 @@ sub update_reports {
my $request_id = $request->{service_request_id};
- my $problem =
- FixMyStreet::App->model('DB::Problem')
+ my $problem = $body->result_source->schema->resultset('Problem')
->search( { external_id => $request_id, } );
if (my $p = $problem->first) {
diff --git a/perllib/Open311/PopulateServiceList.pm b/perllib/Open311/PopulateServiceList.pm
index 5f45382e2..15a827217 100644
--- a/perllib/Open311/PopulateServiceList.pm
+++ b/perllib/Open311/PopulateServiceList.pm
@@ -1,21 +1,17 @@
package Open311::PopulateServiceList;
-use Moose;
-use LWP::Simple;
-use XML::Simple;
-use FixMyStreet::App;
+use Moo;
use Open311;
has bodies => ( is => 'ro' );
has found_contacts => ( is => 'rw', default => sub { [] } );
has verbose => ( is => 'ro', default => 0 );
+has schema => ( is => 'ro', lazy => 1, default => sub { FixMyStreet::DB->connect } );
has _current_body => ( is => 'rw' );
has _current_open311 => ( is => 'rw' );
has _current_service => ( is => 'rw' );
-my $bodies = FixMyStreet::App->model('DB::Body');
-
sub process_bodies {
my $self = shift;
@@ -43,7 +39,7 @@ sub process_body {
unless ( $list && $list->{service} ) {
if ($self->verbose >= 1) {
my $id = $self->_current_body->id;
- my $mapit_url = mySociety::Config::get('MAPIT_URL');
+ my $mapit_url = FixMyStreet->config('MAPIT_URL');
my $areas = join( ",", keys %{$self->_current_body->areas} );
warn "Body $id for areas $areas - $mapit_url/areas/$areas.html - did not return a service list\n";
warn $open311->error;
@@ -93,7 +89,7 @@ sub process_service {
$self->_current_service->{service_name};
print $self->_current_service->{service_code} . ': ' . $category . "\n" if $self->verbose >= 2;
- my $contacts = FixMyStreet::App->model( 'DB::Contact')->search(
+ my $contacts = $self->schema->resultset('Contact')->search(
{
body_id => $self->_current_body->id,
-OR => [
@@ -173,7 +169,7 @@ sub _create_contact {
my $contact;
eval {
- $contact = FixMyStreet::App->model( 'DB::Contact')->create(
+ $contact = $self->schema->resultset('Contact')->create(
{
email => $self->_current_service->{service_code},
body_id => $self->_current_body->id,
@@ -287,7 +283,7 @@ sub _normalize_service_name {
sub _delete_contacts_not_in_service_list {
my $self = shift;
- my $found_contacts = FixMyStreet::App->model( 'DB::Contact')->search(
+ my $found_contacts = $self->schema->resultset('Contact')->search(
{
email => { -not_in => $self->found_contacts },
body_id => $self->_current_body->id,
diff --git a/perllib/Utils/Photo.pm b/perllib/Utils/Photo.pm
new file mode 100644
index 000000000..a1af90fe1
--- /dev/null
+++ b/perllib/Utils/Photo.pm
@@ -0,0 +1,41 @@
+package Utils::Photo;
+
+use Image::Size;
+
+=head2 get_photo_params
+
+Returns a hashref of details of any attached photo for use in templates.
+Hashref contains height, width and url keys.
+
+=cut
+
+sub get_photo_params {
+ my ($self, $key) = @_;
+
+ return {} unless $self->photo;
+
+ $key = ($key eq 'id') ? '' : "/$key";
+
+ my $pre = "/photo$key/" . $self->id;
+ my $post = '.jpeg';
+ my $photo = {};
+
+ if (length($self->photo) == 40) {
+ $post .= '?' . $self->photo;
+ $photo->{url_full} = "$pre.full$post";
+ # XXX Can't use size here because {url} (currently 250px height) may be
+ # being used, but at this point it doesn't yet exist to find the width
+ # $str = FixMyStreet->config('UPLOAD_DIR') . $self->photo . '.jpeg';
+ } else {
+ my $str = \$self->photo;
+ ( $photo->{width}, $photo->{height} ) = Image::Size::imgsize( $str );
+ }
+
+ $photo->{url} = "$pre$post";
+ $photo->{url_tn} = "$pre.tn$post";
+ $photo->{url_fp} = "$pre.fp$post";
+
+ return $photo;
+}
+
+1;