diff options
Diffstat (limited to 'perllib/FixMyStreet/DB')
34 files changed, 777 insertions, 314 deletions
diff --git a/perllib/FixMyStreet/DB/Factories.pm b/perllib/FixMyStreet/DB/Factories.pm index 56cff280b..5af9ed38f 100644 --- a/perllib/FixMyStreet/DB/Factories.pm +++ b/perllib/FixMyStreet/DB/Factories.pm @@ -94,9 +94,25 @@ sub data { my $self = shift; my %titles = ( + 'Abandoned vehicles' => ['Car on pavement, has been there for months', 'Silver car outside house, never used'], + 'Bus stops' => ['Bus stop sign wonky', 'Information board broken'], + 'Dog fouling' => ['Bad dog fouling in alley way', 'Inconsiderate dog owner' ], + 'Flyposting' => ['Fence by road covered in posters', 'Under the bridge is a poster haven'], + 'Flytipping' => ['Flytipping on country lane', 'Ten bags of rubbish'], + 'Footpath/bridleway away from road' => ['Vehicle blocking footpath'], + 'Graffiti' => ['Graffiti', 'Graffiti', 'Offensive graffiti', 'Graffiti on the bridge', 'Remove graffiti'], + 'Parks/landscapes' => ['Full litter bins', 'Allotment gate needs repair'], + 'Pavements' => ['Hedge encroaching pavement', 'Many cracked slabs on street corner'], 'Potholes' => ['Deep pothole', 'Small pothole', 'Pothole in cycle lane', 'Pothole on busy pavement', 'Large pothole', 'Sinking manhole'], + 'Public toilets' => ['Door will not open'], + 'Roads/highways' => ['Restricted sight line by zig-zag lines', 'Missing lane markings'], + 'Road traffic signs' => ['Bent sign', 'Zebra crossing', 'Bollard missing'], + 'Rubbish (refuse and recycling)' => ['Missing bin', 'Bags left uncollected'], + 'Street cleaning' => ['Two abandoned trollies', 'Yet more litter'], 'Street lighting' => ['Faulty light', 'Street light not working', 'Lights out in tunnel', 'Light not coming on', 'Light not going off'], - 'Graffiti' => ['Graffiti', 'Graffiti', 'Offensive graffiti', 'Graffiti on the bridge', 'Remove graffiti'], + 'Street nameplates' => ['Broken nameplate', 'Missing nameplate'], + 'Traffic lights' => ['Out of sync lights', 'Always on green', 'Broken light'], + 'Trees' => ['Young tree damaged', 'Tree looks dangerous in wind'], 'Other' => ['Loose drain cover', 'Flytipping on country lane', 'Vehicle blocking footpath', 'Hedge encroaching pavement', 'Full litter bins'], ); my %photos = ( @@ -171,8 +187,8 @@ sub create_problem { $params->{latitude} += rand(2 * $inaccurate_km) - $inaccurate_km; $params->{longitude} += rand(3 * $inaccurate_km) - 1.5 * $inaccurate_km, - $params->{title} = $titles->[$rand]; - $params->{detail} = $descs->[$rand]; + $params->{title} ||= $titles->[$rand]; + $params->{detail} ||= $descs->[$rand] || 'Please deal with this issue, thank you.'; $params->{photo_id} = $photo; $params->{confirmed} = DateTime::Format::Pg->format_datetime($params->{confirmed}); return $self->create($params); @@ -183,7 +199,7 @@ sub create_problem { package FixMyStreet::DB::Factory::Body; use parent -norequire, "FixMyStreet::DB::Factory::Base"; -use mySociety::MaPit; +use FixMyStreet::MapIt; __PACKAGE__->resultset(FixMyStreet::DB->resultset("Body")); @@ -192,7 +208,7 @@ __PACKAGE__->exclude(['area_id', 'categories']); __PACKAGE__->fields({ name => __PACKAGE__->callback(sub { my $area_id = shift->get('area_id'); - my $area = mySociety::MaPit::call('area', $area_id); + my $area = FixMyStreet::MapIt::call('area', $area_id); $area->{name}; }), body_areas => __PACKAGE__->callback(sub { @@ -212,7 +228,7 @@ sub key_field { 'id' } package FixMyStreet::DB::Factory::Contact; -use parent "DBIx::Class::Factory"; +use parent -norequire, "FixMyStreet::DB::Factory::Base"; __PACKAGE__->resultset(FixMyStreet::DB->resultset("Contact")); @@ -224,8 +240,8 @@ __PACKAGE__->fields({ category => 'Other', email => __PACKAGE__->callback(sub { my $category = shift->get('category'); - (my $email = lc $_) =~ s/ /-/g; - lc $category . '@example.org'; + (my $email = lc $category) =~ s/ /-/g; + $email . '@example.org'; }), state => 'confirmed', editor => 'Factory', @@ -233,6 +249,8 @@ __PACKAGE__->fields({ note => 'Created by factory', }); +sub key_field { 'id' } + ####################### package FixMyStreet::DB::Factory::ResponseTemplate; diff --git a/perllib/FixMyStreet/DB/RABXColumn.pm b/perllib/FixMyStreet/DB/RABXColumn.pm index 5f1583018..d14b48dc8 100644 --- a/perllib/FixMyStreet/DB/RABXColumn.pm +++ b/perllib/FixMyStreet/DB/RABXColumn.pm @@ -59,7 +59,6 @@ sub rabx_column { my $self = shift; my $ser = shift; return undef unless defined $ser; - utf8::encode($ser) if utf8::is_utf8($ser); my $h = new IO::String($ser); return RABX::wire_rd($h); }, @@ -78,18 +77,23 @@ sub rabx_column { $RABX_COLUMNS{ _get_class_identifier($class) }{$col} = 1; } +# The underlying column should always be UTF-8 encoded bytes. +sub get_column { + my ($self, $col) = @_; + my $res = $self->next::method ($col); + utf8::encode($res) if $RABX_COLUMNS{_get_class_identifier($self)}{$col} && utf8::is_utf8($res); + return $res; +} sub set_filtered_column { my ($self, $col, $val) = @_; - my $class = ref $self; - # because filtered objects may be expensive to marshall for storage there # is a cache that attempts to detect if they have changed or not. For us # this cache breaks things and our marshalling is cheap, so clear it when # trying set a column. delete $self->{_filtered_column}{$col} - if $RABX_COLUMNS{ _get_class_identifier($class) }{$col}; + if $RABX_COLUMNS{ _get_class_identifier($self) }{$col}; return $self->next::method($col, $val); } diff --git a/perllib/FixMyStreet/DB/Result/Abuse.pm b/perllib/FixMyStreet/DB/Result/Abuse.pm index e8e554afa..7818eb743 100644 --- a/perllib/FixMyStreet/DB/Result/Abuse.pm +++ b/perllib/FixMyStreet/DB/Result/Abuse.pm @@ -8,14 +8,18 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("abuse"); __PACKAGE__->add_columns("email", { data_type => "text", is_nullable => 0 }); __PACKAGE__->set_primary_key("email"); -# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-08 17:19:55 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:PnQhGMx+ktK++3gWOMJBpQ +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:6XdWpymMMUEC4WT9Yh0RLw # You can replace this text with custom code or comments, and it will be preserved on regeneration 1; diff --git a/perllib/FixMyStreet/DB/Result/AdminLog.pm b/perllib/FixMyStreet/DB/Result/AdminLog.pm index 1c9bd3a63..221690405 100644 --- a/perllib/FixMyStreet/DB/Result/AdminLog.pm +++ b/perllib/FixMyStreet/DB/Result/AdminLog.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("admin_log"); __PACKAGE__->add_columns( "id", @@ -54,7 +58,7 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-07-20 14:38:36 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:y2xZ4BDv7H+f4vbIZyNflw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BLPP1KitphuY56ptaXhzgg 1; diff --git a/perllib/FixMyStreet/DB/Result/Alert.pm b/perllib/FixMyStreet/DB/Result/Alert.pm index 2a52a7bca..8979fa338 100644 --- a/perllib/FixMyStreet/DB/Result/Alert.pm +++ b/perllib/FixMyStreet/DB/Result/Alert.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("alert"); __PACKAGE__->add_columns( "id", @@ -65,8 +69,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2015-08-13 16:33:38 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:5RNyB430T8PqtFlmGV/MUg +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:pWmsXAFvvjr4x1Q3Zsu4Cg # You can replace this text with custom code or comments, and it will be preserved on regeneration @@ -75,17 +79,6 @@ use namespace::clean -except => [ 'meta' ]; with 'FixMyStreet::Roles::Abuser'; -my $stz = sub { - my ( $orig, $self ) = ( shift, shift ); - my $s = $self->$orig(@_); - return $s unless $s && UNIVERSAL::isa($s, "DateTime"); - FixMyStreet->set_time_zone($s); - return $s; -}; - -around whensubscribed => $stz; -around whendisabled => $stz; - =head2 confirm $alert->confirm(); diff --git a/perllib/FixMyStreet/DB/Result/AlertSent.pm b/perllib/FixMyStreet/DB/Result/AlertSent.pm index 83043a33b..d4e669f7f 100644 --- a/perllib/FixMyStreet/DB/Result/AlertSent.pm +++ b/perllib/FixMyStreet/DB/Result/AlertSent.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("alert_sent"); __PACKAGE__->add_columns( "alert_id", @@ -31,8 +35,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2015-08-13 16:33:38 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:/+Vodu8VJxJ0EY9P3Qjjjw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:xriosaSCkOo/REOG1OxdQA # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/Result/AlertType.pm b/perllib/FixMyStreet/DB/Result/AlertType.pm index 3aa9677e0..3d9603008 100644 --- a/perllib/FixMyStreet/DB/Result/AlertType.pm +++ b/perllib/FixMyStreet/DB/Result/AlertType.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("alert_type"); __PACKAGE__->add_columns( "ref", @@ -47,8 +51,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-08 17:19:55 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:KDBYzNEAM5lPvZjb9cv22g +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:7JyCGS/rEvL1++p520749w # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/Result/Body.pm b/perllib/FixMyStreet/DB/Result/Body.pm index 74a38f225..663181746 100644 --- a/perllib/FixMyStreet/DB/Result/Body.pm +++ b/perllib/FixMyStreet/DB/Result/Body.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("body"); __PACKAGE__->add_columns( "id", @@ -18,6 +22,12 @@ __PACKAGE__->add_columns( is_nullable => 0, sequence => "body_id_seq", }, + "name", + { data_type => "text", is_nullable => 0 }, + "external_url", + { data_type => "text", is_nullable => 1 }, + "parent", + { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, "endpoint", { data_type => "text", is_nullable => 1 }, "jurisdiction", @@ -36,20 +46,14 @@ __PACKAGE__->add_columns( { data_type => "boolean", default_value => \"false", is_nullable => 0 }, "send_extended_statuses", { data_type => "boolean", default_value => \"false", is_nullable => 0 }, - "name", - { data_type => "text", is_nullable => 0 }, - "parent", - { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, - "deleted", - { data_type => "boolean", default_value => \"false", is_nullable => 0 }, - "external_url", - { data_type => "text", is_nullable => 1 }, "fetch_problems", { data_type => "boolean", default_value => \"false", is_nullable => 0 }, "blank_updates_permitted", - { data_type => "boolean", default_value => \"false", is_nullable => 1 }, + { data_type => "boolean", default_value => \"false", is_nullable => 0 }, "convert_latlong", { data_type => "boolean", default_value => \"false", is_nullable => 0 }, + "deleted", + { data_type => "boolean", default_value => \"false", is_nullable => 0 }, "extra", { data_type => "text", is_nullable => 1 }, ); @@ -126,22 +130,30 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2018-04-05 14:29:33 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:HV8IM2C1ErrpvXoRTZ1B1Q +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:8CuxbffDaYS7TFlgff1nEg __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); __PACKAGE__->rabx_column('extra'); use Moo; use namespace::clean; +use FixMyStreet::MapIt; with 'FixMyStreet::Roles::Translatable', 'FixMyStreet::Roles::Extra'; +sub _url { + my ( $obj, $cobrand, $args ) = @_; + my $uri = URI->new('/reports/' . $cobrand->short_name($obj)); + $uri->query_form($args) if $args; + return $uri; +} + sub url { my ( $self, $c, $args ) = @_; - # XXX $areas_info was used here for Norway parent - needs body parents, I guess - return $c->uri_for( '/reports/' . $c->cobrand->short_name( $self ), $args || {} ); + my $cobrand = $self->result_source->schema->cobrand; + return _url($self, $cobrand, $args); } __PACKAGE__->might_have( @@ -174,7 +186,8 @@ sub first_area_children { return unless $body_area; my $cobrand = $self->result_source->schema->cobrand; - my $children = mySociety::MaPit::call('area/children', $body_area->area_id, + + my $children = FixMyStreet::MapIt::call('area/children', $body_area->area_id, type => $cobrand->area_types_children, ); @@ -197,7 +210,8 @@ sub get_cobrand_handler { } sub calculate_average { - my ($self) = @_; + my ($self, $threshold) = @_; + $threshold ||= 0; my $substmt = "select min(id) from comment where me.problem_id=comment.problem_id and (problem_state in ('fixed', 'fixed - council', 'fixed - user') or mark_fixed)"; my $subquery = FixMyStreet::DB->resultset('Comment')->to_body($self)->search({ @@ -207,6 +221,7 @@ sub calculate_average { ], 'me.id' => \"= ($substmt)", 'me.state' => 'confirmed', + 'problem.state' => [ FixMyStreet::DB::Result::Problem->visible_states() ], }, { select => [ { extract => "epoch from me.confirmed-problem.confirmed", -as => 'time' }, @@ -217,12 +232,15 @@ sub calculate_average { join => 'problem' })->as_subselect_rs; - my $avg = $subquery->search({ + my $result = $subquery->search({ }, { - select => [ { avg => "time" } ], - as => [ qw/avg/ ], - })->first->get_column('avg'); - return $avg; + select => [ { avg => "time" }, { count => "time" } ], + as => [ qw/avg count/ ], + })->first; + my $avg = $result->get_column('avg'); + my $count = $result->get_column('count'); + + return $count >= $threshold ? $avg : undef; } 1; diff --git a/perllib/FixMyStreet/DB/Result/BodyArea.pm b/perllib/FixMyStreet/DB/Result/BodyArea.pm index 4447777dc..7f0956c7d 100644 --- a/perllib/FixMyStreet/DB/Result/BodyArea.pm +++ b/perllib/FixMyStreet/DB/Result/BodyArea.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("body_areas"); __PACKAGE__->add_columns( "body_id", @@ -25,8 +29,8 @@ __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:+hzie6kHleUBoEt199c/nQ +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VPs3e9McGNO+Dd7C4pApxw __PACKAGE__->set_primary_key(__PACKAGE__->columns); diff --git a/perllib/FixMyStreet/DB/Result/Comment.pm b/perllib/FixMyStreet/DB/Result/Comment.pm index 8a4dbe475..5d0253ef4 100644 --- a/perllib/FixMyStreet/DB/Result/Comment.pm +++ b/perllib/FixMyStreet/DB/Result/Comment.pm @@ -6,10 +6,13 @@ package FixMyStreet::DB::Result::Comment; use strict; use warnings; -use FixMyStreet::Template; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("comment"); __PACKAGE__->add_columns( "id", @@ -70,8 +73,8 @@ __PACKAGE__->add_columns( { data_type => "timestamp", is_nullable => 1 }, ); __PACKAGE__->set_primary_key("id"); -__PACKAGE__->might_have( - "moderation_original_data", +__PACKAGE__->has_many( + "moderation_original_datas", "FixMyStreet::DB::Result::ModerationOriginalData", { "foreign.comment_id" => "self.id" }, { cascade_copy => 0, cascade_delete => 0 }, @@ -90,8 +93,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2015-08-13 16:33:38 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:ZR+YNA1Jej3s+8mr52iq6Q +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:CozqNY621I8G7kUPXi5RoQ # __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); @@ -99,21 +102,32 @@ __PACKAGE__->rabx_column('extra'); use Moo; use namespace::clean -except => [ 'meta' ]; +use FixMyStreet::Template; with 'FixMyStreet::Roles::Abuser', 'FixMyStreet::Roles::Extra', + 'FixMyStreet::Roles::Moderation', 'FixMyStreet::Roles::PhotoSet'; -my $stz = sub { - my ( $orig, $self ) = ( shift, shift ); - my $s = $self->$orig(@_); - return $s unless $s && UNIVERSAL::isa($s, "DateTime"); - FixMyStreet->set_time_zone($s); - return $s; -}; +=head2 get_cobrand_logged + +Get a cobrand object for the cobrand the update was made on. + +e.g. if an update was logged at www.fixmystreet.com, this will be a +FixMyStreet::Cobrand::FixMyStreet object. + +=cut + +has get_cobrand_logged => ( + is => 'ro', + lazy => 1, + default => sub { + my $self = shift; + my $cobrand_class = FixMyStreet::Cobrand->get_class_for_moniker( $self->cobrand ); + return $cobrand_class->new; + }, +); -around created => $stz; -around confirmed => $stz; # You can replace this text with custom code or comments, and it will be preserved on regeneration @@ -156,17 +170,6 @@ sub url { return "/report/" . $self->problem_id . '#update_' . $self->id; } -=head2 latest_moderation_log_entry - -Return most recent ModerationLog object - -=cut - -sub latest_moderation_log_entry { - my $self = shift; - return $self->admin_log_entries->search({ action => 'moderation' }, { order_by => { -desc => 'id' } })->first; -} - __PACKAGE__->has_many( "admin_log_entries", "FixMyStreet::DB::Result::AdminLog", @@ -177,24 +180,24 @@ __PACKAGE__->has_many( } ); -# we already had the `moderation_original_data` rel above, as inferred by -# Schema::Loader, but that doesn't know about the problem_id mapping, so we now -# (slightly hackishly) redefine here: -# -# we also add cascade_delete, though this seems to be insufficient. -# -# TODO: should add FK on moderation_original_data field for this, to get S::L to -# pick up without hacks. - +# This will return the oldest moderation_original_data, if any. +# The plural can be used to return all entries. __PACKAGE__->might_have( "moderation_original_data", "FixMyStreet::DB::Result::ModerationOriginalData", { "foreign.comment_id" => "self.id", "foreign.problem_id" => "self.problem_id", }, - { cascade_copy => 0, cascade_delete => 1 }, + { order_by => 'id', + rows => 1, + cascade_copy => 0, cascade_delete => 1 }, ); +sub moderation_filter { + my $self = shift; + { problem_id => $self->problem_id }; +} + =head2 meta_line Returns a string to be used on a report update, describing some of the metadata @@ -228,7 +231,9 @@ sub meta_line { $body = "$body <img src='/cobrands/greenwich/favicon.png' alt=''>"; } } - my $can_view_contribute = $c->user_exists && $c->user->has_permission_to('view_body_contribute_details', $self->problem->bodies_str_ids); + my $cobrand_always_view_body_user = $c->cobrand->call_hook("always_view_body_contribute_details"); + my $can_view_contribute = $cobrand_always_view_body_user || + ($c->user_exists && $c->user->has_permission_to('view_body_contribute_details', $self->problem->bodies_str_ids)); if ($self->text) { if ($can_view_contribute) { $meta = sprintf( _( 'Posted by <strong>%s</strong> (%s) at %s' ), $body, $user_name, Utils::prettify_dt( $self->confirmed ) ); @@ -253,24 +258,22 @@ sub meta_line { return $meta; }; +sub problem_state_processed { + my $self = shift; + return 'fixed - user' if $self->mark_fixed; + return 'confirmed' if $self->mark_open; + return $self->problem_state; +} + sub problem_state_display { my ( $self, $c ) = @_; - my $update_state = ''; - my $cobrand = $c->cobrand->moniker; - - if ($self->mark_fixed) { - return FixMyStreet::DB->resultset("State")->display('fixed', 1); - } elsif ($self->mark_open) { - return FixMyStreet::DB->resultset("State")->display('confirmed', 1); - } elsif ($self->problem_state) { - my $state = $self->problem_state; - my $cobrand_name = $cobrand; - $cobrand_name = 'bromley' if $self->problem->to_body_named('Bromley'); - $update_state = FixMyStreet::DB->resultset("State")->display($state, 1, $cobrand_name); - } + my $state = $self->problem_state_processed; + return '' unless $state; - return $update_state; + my $cobrand_name = $c->cobrand->moniker; + $cobrand_name = 'bromley' if $self->problem->to_body_named('Bromley'); + return FixMyStreet::DB->resultset("State")->display($state, 1, $cobrand_name); } sub is_latest { @@ -298,4 +301,27 @@ sub hide { return $ret; } +sub as_hashref { + my ($self, $c, $cols) = @_; + + my $out = { + id => $self->id, + problem_id => $self->problem_id, + text => $self->text, + state => $self->state, + created => $self->created, + }; + + $out->{problem_state} = $self->problem_state_processed; + + $out->{photos} = [ map { $_->{url} } @{$self->photos} ] if !$cols || $cols->{photos}; + + if ($self->confirmed) { + $out->{confirmed} = $self->confirmed if !$cols || $cols->{confirmed}; + $out->{confirmed_pp} = $c->cobrand->prettify_dt( $self->confirmed ) if !$cols || $cols->{confirmed_pp}; + } + + return $out; +} + 1; diff --git a/perllib/FixMyStreet/DB/Result/Contact.pm b/perllib/FixMyStreet/DB/Result/Contact.pm index c544f084a..17620f279 100644 --- a/perllib/FixMyStreet/DB/Result/Contact.pm +++ b/perllib/FixMyStreet/DB/Result/Contact.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("contacts"); __PACKAGE__->add_columns( "id", @@ -24,6 +28,8 @@ __PACKAGE__->add_columns( { data_type => "text", default_value => "Other", is_nullable => 0 }, "email", { data_type => "text", is_nullable => 0 }, + "state", + { data_type => "text", is_nullable => 0 }, "editor", { data_type => "text", is_nullable => 0 }, "whenedited", @@ -42,8 +48,6 @@ __PACKAGE__->add_columns( { data_type => "text", default_value => "", is_nullable => 1 }, "send_method", { data_type => "text", is_nullable => 1 }, - "state", - { data_type => "text", is_nullable => 0 }, ); __PACKAGE__->set_primary_key("id"); __PACKAGE__->add_unique_constraint("contacts_body_id_category_idx", ["body_id", "category"]); @@ -73,8 +77,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-07-08 20:45:04 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:t/VtPP11R8bbqPZdEVXffw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:f7XjQj4iABikbR4EZrjL3g __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); __PACKAGE__->rabx_column('extra'); @@ -94,14 +98,9 @@ sub category_display { $self->translate_column('category'); } -sub get_metadata_for_input { +sub get_metadata_for_editing { my $self = shift; - my $id_field = $self->id_field; my @metadata = @{$self->get_extra_fields}; - # First, ones we always want to ignore (hard-coded, old system) - @metadata = grep { $_->{code} !~ /^(easting|northing|closest_address|$id_field)$/ } @metadata; - # Also ignore any we have with a 'server_set' automated attribute - @metadata = grep { !$_->{automated} || $_->{automated} ne 'server_set' } @metadata; # Just in case the extra data is in an old parsed format foreach (@metadata) { @@ -112,6 +111,16 @@ sub get_metadata_for_input { return \@metadata; } +sub get_metadata_for_input { + my $self = shift; + my $metadata = $self->get_metadata_for_editing; + + # Also ignore any we have with a 'server_set' automated attribute + my @metadata = grep { !$_->{automated} || $_->{automated} ne 'server_set' } @$metadata; + + return \@metadata; +} + sub id_field { my $self = shift; return $self->get_extra_metadata('id_field') || 'fixmystreet_id'; diff --git a/perllib/FixMyStreet/DB/Result/ContactDefectType.pm b/perllib/FixMyStreet/DB/Result/ContactDefectType.pm index 2199f0b42..25d842e23 100644 --- a/perllib/FixMyStreet/DB/Result/ContactDefectType.pm +++ b/perllib/FixMyStreet/DB/Result/ContactDefectType.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("contact_defect_types"); __PACKAGE__->add_columns( "id", @@ -38,8 +42,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-02-13 15:11:11 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:VIczmM0OXXpWgQVpop3SMw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:yjQ/+17jn8fW8J70fFtvgg # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/Result/ContactResponsePriority.pm b/perllib/FixMyStreet/DB/Result/ContactResponsePriority.pm index d5afd75a7..8406e2762 100644 --- a/perllib/FixMyStreet/DB/Result/ContactResponsePriority.pm +++ b/perllib/FixMyStreet/DB/Result/ContactResponsePriority.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("contact_response_priorities"); __PACKAGE__->add_columns( "id", @@ -38,8 +42,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-09-06 15:33:04 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:kM/9jY1QSgakyPTvutS+hw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:NvXWYJu14GUXEHztl3Zp4w # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/Result/ContactResponseTemplate.pm b/perllib/FixMyStreet/DB/Result/ContactResponseTemplate.pm index 3c777533c..3139b2c84 100644 --- a/perllib/FixMyStreet/DB/Result/ContactResponseTemplate.pm +++ b/perllib/FixMyStreet/DB/Result/ContactResponseTemplate.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("contact_response_templates"); __PACKAGE__->add_columns( "id", @@ -38,8 +42,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-08-24 11:29:04 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:d6niNsxi2AsijhvJSuQeKw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:PE5+8AZp77pb+tDFEwiOqg # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/Result/ContactsHistory.pm b/perllib/FixMyStreet/DB/Result/ContactsHistory.pm index c90bb9d66..5a6039d6a 100644 --- a/perllib/FixMyStreet/DB/Result/ContactsHistory.pm +++ b/perllib/FixMyStreet/DB/Result/ContactsHistory.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("contacts_history"); __PACKAGE__->add_columns( "contacts_history_id", @@ -26,20 +30,20 @@ __PACKAGE__->add_columns( { data_type => "text", default_value => "Other", is_nullable => 0 }, "email", { data_type => "text", is_nullable => 0 }, + "state", + { data_type => "text", is_nullable => 0 }, "editor", { data_type => "text", is_nullable => 0 }, "whenedited", { data_type => "timestamp", is_nullable => 0 }, "note", { data_type => "text", is_nullable => 0 }, - "state", - { data_type => "text", is_nullable => 0 }, ); __PACKAGE__->set_primary_key("contacts_history_id"); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-07-08 20:45:04 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:HTt0g29yXTM/WyHKN179FA +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:es6F6L3MS8pEUDprFplnYg # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/Result/DefectType.pm b/perllib/FixMyStreet/DB/Result/DefectType.pm index a2969f59e..baee066af 100644 --- a/perllib/FixMyStreet/DB/Result/DefectType.pm +++ b/perllib/FixMyStreet/DB/Result/DefectType.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("defect_types"); __PACKAGE__->add_columns( "id", @@ -49,8 +53,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-02-13 15:11:11 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BBLjb/aAoTKJZerdYCeBMQ +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:d5Gkeysiz/1P/Ww4Xur0vA __PACKAGE__->many_to_many( contacts => 'contact_defect_types', 'contact' ); diff --git a/perllib/FixMyStreet/DB/Result/ModerationOriginalData.pm b/perllib/FixMyStreet/DB/Result/ModerationOriginalData.pm index d7240cd5d..18d2a7683 100644 --- a/perllib/FixMyStreet/DB/Result/ModerationOriginalData.pm +++ b/perllib/FixMyStreet/DB/Result/ModerationOriginalData.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("moderation_original_data"); __PACKAGE__->add_columns( "id", @@ -37,9 +41,16 @@ __PACKAGE__->add_columns( is_nullable => 0, original => { default_value => \"now()" }, }, + "extra", + { data_type => "text", is_nullable => 1 }, + "category", + { data_type => "text", is_nullable => 1 }, + "latitude", + { data_type => "double precision", is_nullable => 1 }, + "longitude", + { data_type => "double precision", is_nullable => 1 }, ); __PACKAGE__->set_primary_key("id"); -__PACKAGE__->add_unique_constraint("moderation_original_data_comment_id_key", ["comment_id"]); __PACKAGE__->belongs_to( "comment", "FixMyStreet::DB::Result::Comment", @@ -59,9 +70,149 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2015-08-13 16:33:38 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:DBtGjCJykDtLnGtkj638eA +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:FLKiZELcfBcc9VwHU2MZYQ + +use Moo; +use Text::Diff; +use Data::Dumper; + +with 'FixMyStreet::Roles::Extra'; + +__PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); +__PACKAGE__->rabx_column('extra'); + +sub admin_log { + my $self = shift; + my $rs = $self->result_source->schema->resultset("AdminLog"); + my $log = $rs->search({ + object_id => $self->id, + object_type => 'moderation', + })->first; + return $log; +} + +sub compare_with { + my ($self, $other) = @_; + if ($self->comment_id) { + my $new_detail = $other->can('text') ? $other->text : $other->detail; + return { + detail => string_diff($self->detail, $new_detail), + photo => $self->compare_photo($other), + anonymous => $self->compare_anonymous($other), + extra => $self->compare_extra($other), + }; + } + return { + title => string_diff($self->title, $other->title), + detail => string_diff($self->detail, $other->detail), + photo => $self->compare_photo($other), + anonymous => $self->compare_anonymous($other), + coords => $self->compare_coords($other), + category => string_diff($self->category, $other->category, single => 1), + extra => $self->compare_extra($other), + } +} + +sub compare_anonymous { + my ($self, $other) = @_; + string_diff( + $self->anonymous ? _('Yes') : _('No'), + $other->anonymous ? _('Yes') : _('No'), + ); +} + +sub compare_coords { + my ($self, $other) = @_; + return '' unless $self->latitude && $self->longitude; + my $old = join ',', $self->latitude, $self->longitude; + my $new = join ',', $other->latitude, $other->longitude; + string_diff($old, $new, single => 1); +} + +sub compare_photo { + my ($self, $other) = @_; + + my $old = $self->photo || ''; + my $new = $other->photo || ''; + return '' if $old eq $new; + + $old = [ split /,/, $old ]; + $new = [ split /,/, $new ]; + + my $diff = Algorithm::Diff->new( $old, $new ); + my (@added, @deleted); + while ( $diff->Next ) { + next if $diff->Same; + push @deleted, $diff->Items(1); + push @added, $diff->Items(2); + } + return (join ', ', map { + "<del style='background-color:#fcc'>$_</del>"; + } @deleted) . (join ', ', map { + "<ins style='background-color:#cfc'>$_</ins>"; + } @added); +} + +sub compare_extra { + my ($self, $other) = @_; + + my $old = $self->get_extra_metadata; + my $new = $other->get_extra_metadata; + + my $both = { %$old, %$new }; + my @all_keys = sort keys %$both; + my @s; + foreach (@all_keys) { + if ($old->{$_} && $new->{$_}) { + push @s, string_diff("$_ = $old->{$_}", "$_ = $new->{$_}"); + } elsif ($new->{$_}) { + push @s, string_diff("", "$_ = $new->{$_}"); + } else { + push @s, string_diff("$_ = $old->{$_}", ""); + } + } + return join ', ', grep { $_ } @s; +} + +sub extra_diff { + my ($self, $other, $key) = @_; + my $o = $self->get_extra_metadata($key); + my $n = $other->get_extra_metadata($key); + return string_diff($o, $n); +} + +sub string_diff { + my ($old, $new, %options) = @_; + + return '' if $old eq $new; + + $old = FixMyStreet::Template::html_filter($old); + $new = FixMyStreet::Template::html_filter($new); + if ($options{single}) { + return unless $old; + $old = [ $old ]; + $new = [ $new ]; + } + $old = [ split //, $old ] unless ref $old; + $new = [ split //, $new ] unless ref $new; + my $diff = Algorithm::Diff->new( $old, $new ); + my $string; + while ($diff->Next) { + my $d = $diff->Diff; + if ($d & 1) { + my $deleted = join '', $diff->Items(1); + $string .= "<del style='background-color:#fcc'>$deleted</del>"; + } + my $inserted = join '', $diff->Items(2); + if ($d & 2) { + $string .= "<ins style='background-color:#cfc'>$inserted</ins>"; + } else { + $string .= $inserted; + } + } + return $string; +} -# You can replace this text with custom code or comments, and it will be preserved on regeneration 1; diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm index f67e0b0f8..dc45091ee 100644 --- a/perllib/FixMyStreet/DB/Result/Problem.pm +++ b/perllib/FixMyStreet/DB/Result/Problem.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("problem"); __PACKAGE__->add_columns( "id", @@ -20,14 +24,38 @@ __PACKAGE__->add_columns( }, "postcode", { data_type => "text", is_nullable => 0 }, + "latitude", + { data_type => "double precision", is_nullable => 0 }, + "longitude", + { data_type => "double precision", is_nullable => 0 }, + "bodies_str", + { data_type => "text", is_nullable => 1 }, + "bodies_missing", + { data_type => "text", is_nullable => 1 }, + "areas", + { data_type => "text", is_nullable => 0 }, + "category", + { data_type => "text", default_value => "Other", is_nullable => 0 }, "title", { data_type => "text", is_nullable => 0 }, "detail", { data_type => "text", is_nullable => 0 }, "photo", { data_type => "bytea", is_nullable => 1 }, + "used_map", + { data_type => "boolean", is_nullable => 0 }, + "user_id", + { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, "name", { data_type => "text", is_nullable => 0 }, + "anonymous", + { data_type => "boolean", is_nullable => 0 }, + "external_id", + { data_type => "text", is_nullable => 1 }, + "external_body", + { data_type => "text", is_nullable => 1 }, + "external_team", + { data_type => "text", is_nullable => 1 }, "created", { data_type => "timestamp", @@ -35,57 +63,37 @@ __PACKAGE__->add_columns( is_nullable => 0, original => { default_value => \"now()" }, }, - "state", - { data_type => "text", is_nullable => 0 }, - "whensent", - { data_type => "timestamp", is_nullable => 1 }, - "used_map", - { data_type => "boolean", is_nullable => 0 }, - "bodies_str", - { data_type => "text", is_nullable => 1 }, - "anonymous", - { data_type => "boolean", is_nullable => 0 }, - "category", - { data_type => "text", default_value => "Other", is_nullable => 0 }, "confirmed", { data_type => "timestamp", is_nullable => 1 }, - "send_questionnaire", - { data_type => "boolean", default_value => \"true", is_nullable => 0 }, - "lastupdate", - { - data_type => "timestamp", - default_value => \"current_timestamp", - is_nullable => 0, - original => { default_value => \"now()" }, - }, - "areas", + "state", { data_type => "text", is_nullable => 0 }, - "service", - { data_type => "text", default_value => "", is_nullable => 0 }, "lang", { data_type => "text", default_value => "en-gb", is_nullable => 0 }, + "service", + { data_type => "text", default_value => "", is_nullable => 0 }, "cobrand", { data_type => "text", default_value => "", is_nullable => 0 }, "cobrand_data", { data_type => "text", default_value => "", is_nullable => 0 }, - "latitude", - { data_type => "double precision", is_nullable => 0 }, - "longitude", - { data_type => "double precision", is_nullable => 0 }, - "external_id", - { data_type => "text", is_nullable => 1 }, - "external_body", - { data_type => "text", is_nullable => 1 }, - "external_team", + "lastupdate", + { + data_type => "timestamp", + default_value => \"current_timestamp", + is_nullable => 0, + original => { default_value => \"now()" }, + }, + "whensent", + { data_type => "timestamp", is_nullable => 1 }, + "send_questionnaire", + { data_type => "boolean", default_value => \"true", is_nullable => 0 }, + "extra", { data_type => "text", is_nullable => 1 }, - "user_id", - { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, "flagged", { data_type => "boolean", default_value => \"false", is_nullable => 0 }, - "extra", - { data_type => "text", is_nullable => 1 }, "geocode", { data_type => "bytea", is_nullable => 1 }, + "response_priority_id", + { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, "send_fail_count", { data_type => "integer", default_value => 0, is_nullable => 0 }, "send_fail_reason", @@ -104,10 +112,6 @@ __PACKAGE__->add_columns( { data_type => "integer", default_value => 0, is_nullable => 1 }, "subcategory", { data_type => "text", is_nullable => 1 }, - "bodies_missing", - { data_type => "text", is_nullable => 1 }, - "response_priority_id", - { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, "defect_type_id", { data_type => "integer", is_foreign_key => 1, is_nullable => 1 }, ); @@ -166,8 +170,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-02-13 15:11:11 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:8zzWlJX7OQOdvrGxKuZUmg +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hUXle+TtlkDkxkBrVa/u+g # Add fake relationship to stored procedure table __PACKAGE__->has_one( @@ -177,11 +181,15 @@ __PACKAGE__->has_one( { cascade_copy => 0, cascade_delete => 0 }, ); +# This will return the oldest moderation_original_data, if any. +# The plural can be used to return all entries. __PACKAGE__->might_have( "moderation_original_data", "FixMyStreet::DB::Result::ModerationOriginalData", { "foreign.problem_id" => "self.id" }, { where => { 'comment_id' => undef }, + order_by => 'id', + rows => 1, cascade_copy => 0, cascade_delete => 1 }, ); @@ -206,6 +214,7 @@ my $IM = eval { with 'FixMyStreet::Roles::Abuser', 'FixMyStreet::Roles::Extra', + 'FixMyStreet::Roles::Moderation', 'FixMyStreet::Roles::Translatable', 'FixMyStreet::Roles::PhotoSet'; @@ -318,19 +327,6 @@ sub visible_states_remove { } } -my $stz = sub { - my ( $orig, $self ) = ( shift, shift ); - my $s = $self->$orig(@_); - return $s unless $s && UNIVERSAL::isa($s, "DateTime"); - FixMyStreet->set_time_zone($s); - return $s; -}; - -around created => $stz; -around confirmed => $stz; -around whensent => $stz; -around lastupdate => $stz; - around service => sub { my ( $orig, $self ) = ( shift, shift ); # service might be undef if e.g. unsaved code report @@ -663,7 +659,7 @@ sub body { my @body_names = sort map { my $name = $_->name; if ($c and FixMyStreet->config('AREA_LINKS_FROM_PROBLEMS')) { - '<a href="' . $_->url($c) . '">' . $name . '</a>'; + '<a href="' . $_->url . '">' . $name . '</a>'; } else { $name; } @@ -759,7 +755,7 @@ sub defect_types { # Note: this only makes sense when called on a problem that has been sent! sub can_display_external_id { my $self = shift; - if ($self->external_id && $self->send_method_used && $self->to_body_named('Oxfordshire|Angus')) { + if ($self->external_id && $self->send_method_used && $self->to_body_named('Oxfordshire|Lincolnshire')) { return 1; } return 0; @@ -780,7 +776,7 @@ sub duration_string { sub local_coords { my $self = shift; - my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($self->cobrand)->new; + my $cobrand = $self->get_cobrand_logged; if ($cobrand->moniker eq 'zurich') { my ($x, $y) = Geo::Coordinates::CH1903Plus::from_latlon($self->latitude, $self->longitude); return ( int($x+0.5), int($y+0.5) ); @@ -893,11 +889,12 @@ bodies by some mechanism. Right now that mechanism is Open311. sub updates_sent_to_body { my $self = shift; - return unless $self->send_method_used && $self->send_method_used eq 'Open311'; + return unless $self->send_method_used && $self->send_method_used =~ /Open311/; # Some bodies only send updates *to* FMS, they don't receive updates. - # NB See also the list in bin/send-comments - my $excluded = qr{Lewisham|Oxfordshire}; + my $cobrand = $self->get_cobrand_logged; + my $handler = $cobrand->call_hook(get_body_handler_for_problem => $self); + return 0 if $handler && $handler->call_hook('open311_post_update_skip'); my @bodies = values %{ $self->bodies }; my @updates_sent = grep { @@ -905,8 +902,7 @@ sub updates_sent_to_body { ( $_->send_method eq 'Open311' || $_->send_method eq 'Noop' # Sending might be temporarily disabled - ) && - !($_->name =~ /$excluded/) + ) } @bodies; return scalar @updates_sent; } @@ -922,6 +918,12 @@ sub add_send_method { } } +sub resend { + my $self = shift; + $self->whensent(undef); + $self->send_method_used(undef); +} + sub as_hashref { my ($self, $c, $cols) = @_; @@ -952,17 +954,6 @@ sub as_hashref { return $out; } -=head2 latest_moderation_log_entry - -Return most recent ModerationLog object - -=cut - -sub latest_moderation_log_entry { - my $self = shift; - return $self->admin_log_entries->search({ action => 'moderation' }, { order_by => { -desc => 'id' } })->first; -} - __PACKAGE__->has_many( "admin_log_entries", "FixMyStreet::DB::Result::AdminLog", @@ -973,6 +964,11 @@ __PACKAGE__->has_many( } ); +sub moderation_filter { + my $self = shift; + { comment_id => undef }; +} + sub get_time_spent { my $self = shift; my $admin_logs = $self->admin_log_entries->search({}, @@ -1017,6 +1013,7 @@ sub pin_data { id => $self->id, title => $title, problem => $self, + draggable => $opts{draggable}, type => $opts{type}, } }; diff --git a/perllib/FixMyStreet/DB/Result/Questionnaire.pm b/perllib/FixMyStreet/DB/Result/Questionnaire.pm index 30f2ab7ce..2d5445669 100644 --- a/perllib/FixMyStreet/DB/Result/Questionnaire.pm +++ b/perllib/FixMyStreet/DB/Result/Questionnaire.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("questionnaire"); __PACKAGE__->add_columns( "id", @@ -40,21 +44,17 @@ __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 +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:AWRb6itjsVkG5VUDRmBTIg use Moo; use namespace::clean -except => [ 'meta' ]; -my $stz = sub { - my ( $orig, $self ) = ( shift, shift ); - my $s = $self->$orig(@_); - return $s unless $s && UNIVERSAL::isa($s, "DateTime"); - FixMyStreet->set_time_zone($s); - return $s; -}; - -around whensent => $stz; -around whenanswered => $stz; +sub marks_fixed { + my $self = shift; + my $new_fixed = FixMyStreet::DB::Result::Problem->fixed_states()->{$self->new_state}; + my $old_fixed = FixMyStreet::DB::Result::Problem->fixed_states()->{$self->old_state}; + return $new_fixed && !$old_fixed; +} 1; diff --git a/perllib/FixMyStreet/DB/Result/ReportExtraFields.pm b/perllib/FixMyStreet/DB/Result/ReportExtraField.pm index 27a6bd2c6..f88169bba 100644 --- a/perllib/FixMyStreet/DB/Result/ReportExtraFields.pm +++ b/perllib/FixMyStreet/DB/Result/ReportExtraField.pm @@ -1,5 +1,5 @@ use utf8; -package FixMyStreet::DB::Result::ReportExtraFields; +package FixMyStreet::DB::Result::ReportExtraField; # Created by DBIx::Class::Schema::Loader # DO NOT MODIFY THE FIRST PART OF THIS FILE @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("report_extra_fields"); __PACKAGE__->add_columns( "id", @@ -30,8 +34,8 @@ __PACKAGE__->add_columns( __PACKAGE__->set_primary_key("id"); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-07-28 09:51:34 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:LkfbsUInnEyXowdcCEPjUQ +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 15:41:27 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:yRF676ybdkfalMwZ9V+yhw __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); __PACKAGE__->rabx_column('extra'); diff --git a/perllib/FixMyStreet/DB/Result/ResponsePriority.pm b/perllib/FixMyStreet/DB/Result/ResponsePriority.pm index df54cfa08..a478ac7b9 100644 --- a/perllib/FixMyStreet/DB/Result/ResponsePriority.pm +++ b/perllib/FixMyStreet/DB/Result/ResponsePriority.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("response_priorities"); __PACKAGE__->add_columns( "id", @@ -20,10 +24,10 @@ __PACKAGE__->add_columns( }, "body_id", { data_type => "integer", is_foreign_key => 1, is_nullable => 0 }, - "name", - { data_type => "text", is_nullable => 0 }, "deleted", { data_type => "boolean", default_value => \"false", is_nullable => 0 }, + "name", + { data_type => "text", is_nullable => 0 }, "description", { data_type => "text", is_nullable => 1 }, "external_id", @@ -53,8 +57,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-09-12 09:32:53 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:JBIHFnaLvXCAUjgwTSB3CQ +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:gIttzSJcQ8GxTowrQZ8oAw __PACKAGE__->many_to_many( contacts => 'contact_response_priorities', 'contact' ); diff --git a/perllib/FixMyStreet/DB/Result/ResponseTemplate.pm b/perllib/FixMyStreet/DB/Result/ResponseTemplate.pm index 73e0d898e..85bf80aef 100644 --- a/perllib/FixMyStreet/DB/Result/ResponseTemplate.pm +++ b/perllib/FixMyStreet/DB/Result/ResponseTemplate.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("response_templates"); __PACKAGE__->add_columns( "id", @@ -54,8 +58,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07048 @ 2018-03-22 11:18:36 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:p0+/jFma6H9eZ3MZAJQRaQ +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:MzTa7p2rryKkxbRi7zN+Uw __PACKAGE__->many_to_many( contacts => 'contact_response_templates', 'contact' ); diff --git a/perllib/FixMyStreet/DB/Result/Secret.pm b/perllib/FixMyStreet/DB/Result/Secret.pm index 449dfec0e..045375fef 100644 --- a/perllib/FixMyStreet/DB/Result/Secret.pm +++ b/perllib/FixMyStreet/DB/Result/Secret.pm @@ -8,13 +8,17 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("secret"); __PACKAGE__->add_columns("secret", { data_type => "text", is_nullable => 0 }); -# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-08 17:19:55 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:9XiWSKJ1PD3LSYjrSA3drw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mVU/XGxS3DVhEcHTA2srgA # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/Result/Session.pm b/perllib/FixMyStreet/DB/Result/Session.pm index a478c5444..94f7e823c 100644 --- a/perllib/FixMyStreet/DB/Result/Session.pm +++ b/perllib/FixMyStreet/DB/Result/Session.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("sessions"); __PACKAGE__->add_columns( "id", @@ -21,8 +25,8 @@ __PACKAGE__->add_columns( __PACKAGE__->set_primary_key("id"); -# Created by DBIx::Class::Schema::Loader v0.07017 @ 2012-03-08 17:19:55 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:MVmCn4gLQWXTDIIaDHiVmA +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:HoYrCwULpxJVJ1m9ASMk3A use Storable; use MIME::Base64; diff --git a/perllib/FixMyStreet/DB/Result/State.pm b/perllib/FixMyStreet/DB/Result/State.pm index b8a35d42b..66477111b 100644 --- a/perllib/FixMyStreet/DB/Result/State.pm +++ b/perllib/FixMyStreet/DB/Result/State.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("state"); __PACKAGE__->add_columns( "id", @@ -30,8 +34,8 @@ __PACKAGE__->add_unique_constraint("state_label_key", ["label"]); __PACKAGE__->add_unique_constraint("state_name_key", ["name"]); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-08-22 15:17:43 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:dvtAOpeYqEF9T3otHHgLqw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:f/QeR3FYL/4wIGRu3c/C/A use Moo; use namespace::clean; diff --git a/perllib/FixMyStreet/DB/Result/Token.pm b/perllib/FixMyStreet/DB/Result/Token.pm index a60e23839..444d5e5a8 100644 --- a/perllib/FixMyStreet/DB/Result/Token.pm +++ b/perllib/FixMyStreet/DB/Result/Token.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("token"); __PACKAGE__->add_columns( "scope", @@ -28,8 +32,8 @@ __PACKAGE__->add_columns( __PACKAGE__->set_primary_key("scope", "token"); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2015-08-13 16:33:38 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:HkvzOY5STjOdXN64hxg5NA +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:km/1K3PurX8bbgnYPWgLIA use mySociety::AuthToken; diff --git a/perllib/FixMyStreet/DB/Result/Translation.pm b/perllib/FixMyStreet/DB/Result/Translation.pm index fafc7ccf1..4d6373d40 100644 --- a/perllib/FixMyStreet/DB/Result/Translation.pm +++ b/perllib/FixMyStreet/DB/Result/Translation.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("translation"); __PACKAGE__->add_columns( "id", @@ -36,8 +40,8 @@ __PACKAGE__->add_unique_constraint( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2017-07-14 23:24:32 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:///VNqg4BOuO29xKhnY8vw +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:EsseG51ZpQa5QYHPCpkL8A # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm index 8b539f85d..d01ba92d0 100644 --- a/perllib/FixMyStreet/DB/Result/User.pm +++ b/perllib/FixMyStreet/DB/Result/User.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("users"); __PACKAGE__->add_columns( "id", @@ -36,16 +40,6 @@ __PACKAGE__->add_columns( { data_type => "boolean", default_value => \"false", is_nullable => 0 }, "is_superuser", { data_type => "boolean", default_value => \"false", is_nullable => 0 }, - "title", - { data_type => "text", is_nullable => 1 }, - "twitter_id", - { data_type => "bigint", is_nullable => 1 }, - "facebook_id", - { data_type => "bigint", is_nullable => 1 }, - "area_id", - { data_type => "integer", is_nullable => 1 }, - "extra", - { data_type => "text", is_nullable => 1 }, "created", { data_type => "timestamp", @@ -60,6 +54,16 @@ __PACKAGE__->add_columns( is_nullable => 0, original => { default_value => \"now()" }, }, + "title", + { data_type => "text", is_nullable => 1 }, + "twitter_id", + { data_type => "bigint", is_nullable => 1 }, + "facebook_id", + { data_type => "bigint", is_nullable => 1 }, + "extra", + { data_type => "text", is_nullable => 1 }, + "area_ids", + { data_type => "integer[]", is_nullable => 1 }, ); __PACKAGE__->set_primary_key("id"); __PACKAGE__->add_unique_constraint("users_facebook_id_key", ["facebook_id"]); @@ -119,8 +123,8 @@ __PACKAGE__->has_many( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2018-05-23 18:54:36 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:/V7+Ygv/t6VX8dDhNGN16w +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:BCCqv3JCec8psuRk/SdCJQ # These are not fully unique constraints (they only are when the *_verified # is true), but this is managed in ResultSet::User's find() wrapper. @@ -131,6 +135,7 @@ __PACKAGE__->load_components("+FixMyStreet::DB::RABXColumn"); __PACKAGE__->rabx_column('extra'); use Moo; +use Text::CSV; use FixMyStreet::SMS; use mySociety::EmailUtil; use namespace::clean -except => [ 'meta' ]; @@ -175,8 +180,8 @@ sub phone_display { sub latest_anonymity { my $self = shift; - my $p = $self->problems->search(undef, { order_by => { -desc => 'id' } } )->first; - my $c = $self->comments->search(undef, { order_by => { -desc => 'id' } } )->first; + my $p = $self->problems->search(undef, { rows => 1, order_by => { -desc => 'id' } } )->first; + my $c = $self->comments->search(undef, { rows => 1, order_by => { -desc => 'id' } } )->first; my $p_created = $p ? $p->created->epoch : 0; my $c_created = $c ? $c->created->epoch : 0; my $obj = $p_created >= $c_created ? $p : $c; @@ -291,6 +296,11 @@ sub body { return $self->from_body->name; } +sub moderating_user_name { + my $self = shift; + return $self->body || _('an administrator'); +} + =head2 belongs_to_body $belongs_to_body = $user->belongs_to_body( $bodies ); @@ -329,6 +339,37 @@ sub split_name { return { first => $first || '', last => $last || '' }; } +sub can_moderate { + my ($self, $object, $perms) = @_; + + my ($type, $ids); + if ($object->isa("FixMyStreet::DB::Result::Comment")) { + $type = 'update'; + $ids = $object->problem->bodies_str_ids; + } else { + $type = 'problem'; + $ids = $object->bodies_str_ids; + } + + my $staff_perm = exists($perms->{staff}) ? $perms->{staff} : $self->has_permission_to(moderate => $ids); + return 1 if $staff_perm; + + # See if the cobrand wants to allow it in some circumstance + my $cobrand = $self->result_source->schema->cobrand; + return $cobrand->call_hook('moderate_permission', $self, $type => $object); +} + +sub can_moderate_title { + my ($self, $problem, $perm) = @_; + + # Must have main permission, this is to potentially restrict only + return 0 unless $perm; + + # If hook returns anything use it, otherwise default to yes + my $cobrand = $self->result_source->schema->cobrand; + return $cobrand->call_hook('moderate_permission_title', $self, $problem) // 1; +} + has body_permissions => ( is => 'ro', lazy => 1, @@ -339,13 +380,16 @@ has body_permissions => ( ); sub permissions { - my ($self, $c, $body_id) = @_; + my ($self, $problem) = @_; + my $cobrand = $self->result_source->schema->cobrand; if ($self->is_superuser) { - my $perms = $c->cobrand->available_permissions; + my $perms = $cobrand->available_permissions; return { map { %$_ } values %$perms }; } + my $body_id = $problem->bodies_str; + return unless $self->belongs_to_body($body_id); my @permissions = grep { $_->body_id == $self->from_body->id } @{$self->body_permissions}; @@ -544,6 +588,17 @@ has categories => ( }, ); +has categories_string => ( + is => 'ro', + lazy => 1, + default => sub { + my $self = shift; + my $csv = Text::CSV->new; + $csv->combine(@{$self->categories}); + return $csv->string; + }, +); + sub set_last_active { my $self = shift; my $time = shift; @@ -551,4 +606,19 @@ sub set_last_active { $self->last_active($time or \'current_timestamp'); } +has areas_hash => ( + is => 'ro', + lazy => 1, + default => sub { + my $self = shift; + my %ids = map { $_ => 1 } @{$self->area_ids || []}; + return \%ids; + }, +); + +sub in_area { + my ($self, $area) = @_; + return $self->areas_hash->{$area}; +} + 1; diff --git a/perllib/FixMyStreet/DB/Result/UserBodyPermission.pm b/perllib/FixMyStreet/DB/Result/UserBodyPermission.pm index a118a1996..8fdabbdda 100644 --- a/perllib/FixMyStreet/DB/Result/UserBodyPermission.pm +++ b/perllib/FixMyStreet/DB/Result/UserBodyPermission.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("user_body_permissions"); __PACKAGE__->add_columns( "id", @@ -44,8 +48,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2014-06-05 15:46:02 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:IWy2rYBU7WP6MyIkLYsc9Q +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mcgnPaCmEuLWdzB3GuQiTg # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/Result/UserPlannedReport.pm b/perllib/FixMyStreet/DB/Result/UserPlannedReport.pm index 1e893c7a9..cd1716f02 100644 --- a/perllib/FixMyStreet/DB/Result/UserPlannedReport.pm +++ b/perllib/FixMyStreet/DB/Result/UserPlannedReport.pm @@ -8,7 +8,11 @@ use strict; use warnings; use base 'DBIx::Class::Core'; -__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime", "EncodedColumn"); +__PACKAGE__->load_components( + "FilterColumn", + "FixMyStreet::InflateColumn::DateTime", + "FixMyStreet::EncodedColumn", +); __PACKAGE__->table("user_planned_reports"); __PACKAGE__->add_columns( "id", @@ -47,8 +51,8 @@ __PACKAGE__->belongs_to( ); -# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-07-20 15:03:08 -# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:mv7koDhvZSBW/4aQivtpAQ +# Created by DBIx::Class::Schema::Loader v0.07035 @ 2019-04-25 12:06:39 +# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:A9ICDFNVzkmd/erdtYdeVA # You can replace this text with custom code or comments, and it will be preserved on regeneration diff --git a/perllib/FixMyStreet/DB/ResultSet/Body.pm b/perllib/FixMyStreet/DB/ResultSet/Body.pm index 0aa3e8240..4e9661d2e 100644 --- a/perllib/FixMyStreet/DB/ResultSet/Body.pm +++ b/perllib/FixMyStreet/DB/ResultSet/Body.pm @@ -41,7 +41,7 @@ This restricts the ResultSet to bodies that are not marked as deleted. sub active { my $rs = shift; - $rs->search({ deleted => 0 }); + $rs->search({ 'me.deleted' => 0 }); } =item translated @@ -61,6 +61,22 @@ sub translated { }); } +=item with_parent_name + +This adds the parent name associated with each body to the ResultSet, +in the parent_name column. + +=cut + +sub with_parent_name { + my $rs = shift; + $rs->search(undef, { + '+select' => [ 'parent.name' ], + '+as' => [ 'parent_name' ], + join => 'parent', + }); +} + =item with_area_count This adds the number of areas associated with each body to the ResultSet, @@ -78,10 +94,45 @@ sub with_area_count { }); } +=item with_defect_type_count + +This adds the number of defect types associated with each body to the +ResultSet, in the defect_type_count column. + +=cut + +sub with_defect_type_count { + my $rs = shift; + $rs->search(undef, { + '+select' => [ { count => 'defect_types.name' } ], + '+as' => [ 'defect_type_count' ], + join => 'defect_types', + distinct => 1, + }); +} + +=item with_children_count + +This adds the number of children associated with each body to the +ResultSet, in the children_count column. + +=cut + +sub with_children_count { + my $rs = shift; + $rs->search(undef, { + '+select' => [ { count => 'bodies.id' } ], + '+as' => [ 'children_count' ], + join => 'bodies', + distinct => 1, + }); +} + =item all_sorted -This returns all results, as C<all()>, but sorted by their name column -(which will be the translated names if present). +This returns all results, as C<all()>, but sorted by their name (including +the translated names, if present), and as simple hashrefs not objects, for +performance reasons. =back @@ -89,8 +140,34 @@ This returns all results, as C<all()>, but sorted by their name column sub all_sorted { my $rs = shift; - my @bodies = $rs->all; - @bodies = sort { strcoll($a->name, $b->name) } @bodies; + + # Use a HashRefInflator here to return simple hashrefs rather than full + # objects. This is quicker if you have a large number of bodies; note + # fetching only the columns you need provides even more of a speed up. + my @bodies = $rs->search(undef, { + result_class => 'DBIx::Class::ResultClass::HashRefInflator', + })->all; + @bodies = sort { strcoll($a->{msgstr} || $a->{name}, $b->{msgstr} || $b->{name}) } @bodies; + + my $cobrand = $rs->result_source->schema->cobrand; + + foreach my $body (@bodies) { + $body->{parent} = { id => $body->{parent}, name => $body->{parent_name} } if $body->{parent}; + + # DEPRECATED: url(c, query_params) -> url + $body->{url} = sub { + my ($c, $args) = @_; + return FixMyStreet::DB::Result::Body::_url($body, $cobrand, $args); + }; + + # DEPRECATED: get_column('area_count') -> area_count + next unless defined $body->{area_count}; + $body->{get_column} = sub { + my $key = shift; + return $body->{$key}; + }; + } + return @bodies; } diff --git a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm index b075e3664..2ebe309e3 100644 --- a/perllib/FixMyStreet/DB/ResultSet/Nearby.pm +++ b/perllib/FixMyStreet/DB/ResultSet/Nearby.pm @@ -10,31 +10,34 @@ sub to_body { } sub nearby { - my ( $rs, $c, $dist, $ids, $limit, $mid_lat, $mid_lon, $categories, $states, $extra_params ) = @_; + my ( $rs, $c, %args ) = @_; - unless ( $states ) { - $states = FixMyStreet::DB::Result::Problem->visible_states(); + unless ( $args{states} ) { + $args{states} = FixMyStreet::DB::Result::Problem->visible_states(); } my $params = { - state => [ keys %$states ], + state => [ keys %{$args{states}} ], }; - $params->{id} = { -not_in => $ids } - if $ids; - $params->{category} = $categories if $categories && @$categories; + $params->{id} = { -not_in => $args{ids} } + if $args{ids}; + $params->{category} = $args{categories} if $args{categories} && @{$args{categories}}; + + $params->{$c->stash->{report_age_field}} = { '>=', \"current_timestamp-'$args{report_age}'::interval" } + if $args{report_age}; FixMyStreet::DB::ResultSet::Problem->non_public_if_possible($params, $c); $rs = $c->cobrand->problems_restriction($rs); # Add in any optional extra query parameters - $params = { %$params, %$extra_params } if $extra_params; + $params = { %$params, %{$args{extra}} } if $args{extra}; my $attrs = { prefetch => 'problem', - bind => [ $mid_lat, $mid_lon, $dist ], + bind => [ $args{latitude}, $args{longitude}, $args{distance} ], order_by => [ 'distance', { -desc => 'created' } ], - rows => $limit, + rows => $args{limit}, }; my @problems = mySociety::Locale::in_gb_locale { $rs->search( $params, $attrs )->all }; diff --git a/perllib/FixMyStreet/DB/ResultSet/Problem.pm b/perllib/FixMyStreet/DB/ResultSet/Problem.pm index ef078ed08..37fc34057 100644 --- a/perllib/FixMyStreet/DB/ResultSet/Problem.pm +++ b/perllib/FixMyStreet/DB/ResultSet/Problem.pm @@ -28,13 +28,23 @@ sub body_query { sub non_public_if_possible { my ($rs, $params, $c) = @_; if ($c->user_exists) { + my $only_non_public = $c->stash->{only_non_public} ? 1 : 0; if ($c->user->is_superuser) { # See all reports, no restriction - } elsif ($c->user->has_body_permission_to('report_inspect')) { - $params->{'-or'} = [ - non_public => 0, - $rs->body_query($c->user->from_body->id), - ]; + $params->{non_public} = 1 if $only_non_public; + } elsif ($c->user->has_body_permission_to('report_inspect') || + $c->user->has_body_permission_to('report_mark_private')) { + if ($only_non_public) { + $params->{'-and'} = [ + non_public => 1, + $rs->body_query($c->user->from_body->id), + ]; + } else { + $params->{'-or'} = [ + non_public => 0, + $rs->body_query($c->user->from_body->id), + ]; + } } else { $params->{non_public} = 0; } @@ -57,6 +67,10 @@ sub to_body { # Front page statistics +sub _cache_timeout { + FixMyStreet->config('CACHE_TIMEOUT') // 3600; +} + sub recent_fixed { my $rs = shift; my $key = "recent_fixed:$site_key"; @@ -66,7 +80,7 @@ sub recent_fixed { state => [ FixMyStreet::DB::Result::Problem->fixed_states() ], lastupdate => { '>', \"current_timestamp-'1 month'::interval" }, } )->count; - Memcached::set($key, $result, 3600); + Memcached::set($key, $result, _cache_timeout()); } return $result; } @@ -80,7 +94,7 @@ sub number_comments { { 'comments.state' => 'confirmed' }, { join => 'comments' } )->count; - Memcached::set($key, $result, 3600); + Memcached::set($key, $result, _cache_timeout()); } return $result; } @@ -95,7 +109,7 @@ sub recent_new { state => [ FixMyStreet::DB::Result::Problem->visible_states() ], confirmed => { '>', \"current_timestamp-'$interval'::interval" }, } )->count; - Memcached::set($key, $result, 3600); + Memcached::set($key, $result, _cache_timeout()); } return $result; } @@ -144,10 +158,10 @@ sub _recent { # Need to reattach schema so that confirmed column gets reinflated. $probs->[0]->result_source->schema( $rs->result_source->schema ) if $probs->[0]; # Catch any cached ones since hidden - $probs = [ grep { ! $_->is_hidden } @$probs ]; + $probs = [ grep { $_->photo && ! $_->is_hidden } @$probs ]; } else { $probs = [ $rs->search( $query, $attrs )->all ]; - Memcached::set($key, $probs, 3600); + Memcached::set($key, $probs, _cache_timeout()); } } @@ -172,6 +186,9 @@ sub around_map { latitude => { '>=', $p{min_lat}, '<', $p{max_lat} }, longitude => { '>=', $p{min_lon}, '<', $p{max_lon} }, }; + + $q->{$c->stash->{report_age_field}} = { '>=', \"current_timestamp-'$p{report_age}'::interval" } if + $p{report_age}; $q->{category} = $p{categories} if $p{categories} && @{$p{categories}}; $rs->non_public_if_possible($q, $c); @@ -198,9 +215,9 @@ sub timeline { return $rs->search( { -or => { - created => { '>=', \"current_timestamp-'7 days'::interval" }, - confirmed => { '>=', \"current_timestamp-'7 days'::interval" }, - whensent => { '>=', \"current_timestamp-'7 days'::interval" }, + 'me.created' => { '>=', \"current_timestamp-'7 days'::interval" }, + 'me.confirmed' => { '>=', \"current_timestamp-'7 days'::interval" }, + 'me.whensent' => { '>=', \"current_timestamp-'7 days'::interval" }, } }, { diff --git a/perllib/FixMyStreet/DB/ResultSet/ReportExtraFields.pm b/perllib/FixMyStreet/DB/ResultSet/ReportExtraField.pm index 1348df3c2..9c47b1894 100644 --- a/perllib/FixMyStreet/DB/ResultSet/ReportExtraFields.pm +++ b/perllib/FixMyStreet/DB/ResultSet/ReportExtraField.pm @@ -1,4 +1,4 @@ -package FixMyStreet::DB::ResultSet::ReportExtraFields; +package FixMyStreet::DB::ResultSet::ReportExtraField; use base 'DBIx::Class::ResultSet'; use strict; |