diff options
Diffstat (limited to 'perllib/FixMyStreet/Roles')
-rw-r--r-- | perllib/FixMyStreet/Roles/ContactExtra.pm | 48 | ||||
-rw-r--r-- | perllib/FixMyStreet/Roles/Extra.pm | 16 | ||||
-rw-r--r-- | perllib/FixMyStreet/Roles/Translatable.pm | 116 |
3 files changed, 180 insertions, 0 deletions
diff --git a/perllib/FixMyStreet/Roles/ContactExtra.pm b/perllib/FixMyStreet/Roles/ContactExtra.pm new file mode 100644 index 000000000..55c055d99 --- /dev/null +++ b/perllib/FixMyStreet/Roles/ContactExtra.pm @@ -0,0 +1,48 @@ +package FixMyStreet::Roles::ContactExtra; + +use Moo::Role; +use JSON::MaybeXS; + +requires 'join_table', 'map_extras'; + +sub for_bodies { + my ($rs, $bodies, $category) = @_; + my $join_table = $rs->join_table(); + my $attrs = { + 'me.body_id' => $bodies, + }; + my $order = $rs->can('name_column') ? $rs->name_column() : 'name'; + my $filters = { + order_by => $order, + join => { $join_table => 'contact' }, + prefetch => $join_table, + distinct => 1, + }; + if ($category) { + $attrs->{'contact.category'} = [ $category, undef ]; + } + $rs->search($attrs, $filters); +} + +sub by_categories { + my ($rs, $area_id, @contacts) = @_; + my %body_ids = map { $_->body_id => 1 } FixMyStreet::DB->resultset('BodyArea')->search({ area_id => $area_id }); + my @body_ids = keys %body_ids; + my %extras = (); + my @results = $rs->for_bodies(\@body_ids, undef); + @contacts = grep { $body_ids{$_->body_id} } @contacts; + + foreach my $contact (@contacts) { + my $join_table = $rs->join_table(); + my @ts = grep { + $_->$join_table == 0 # There's no category at all on this defect type/template/priority + || (grep { $_->contact_id == $contact->get_column('id') } $_->$join_table) + } @results; + @ts = $rs->map_extras(@ts); + $extras{$contact->category} = encode_json(\@ts); + } + + return \%extras; +} + +1; diff --git a/perllib/FixMyStreet/Roles/Extra.pm b/perllib/FixMyStreet/Roles/Extra.pm index dc2e5c241..445f6d91c 100644 --- a/perllib/FixMyStreet/Roles/Extra.pm +++ b/perllib/FixMyStreet/Roles/Extra.pm @@ -175,4 +175,20 @@ sub get_extra { return $extra; } +=head2 get_extra_field_value + +Return the value of a field stored in `_fields` in extra, or undefined if +it's not present. + +=cut + +sub get_extra_field_value { + my ($self, $name) = @_; + + my @fields = @{ $self->get_extra_fields() }; + + my ($field) = grep { $_->{name} eq $name } @fields; + return $field->{value}; +} + 1; diff --git a/perllib/FixMyStreet/Roles/Translatable.pm b/perllib/FixMyStreet/Roles/Translatable.pm new file mode 100644 index 000000000..d39d97bf8 --- /dev/null +++ b/perllib/FixMyStreet/Roles/Translatable.pm @@ -0,0 +1,116 @@ +package FixMyStreet::Roles::Translatable; + +use Moo::Role; +use FixMyStreet; + +has _translated => (is => 'rw'); + +sub translated { + my $self = shift; + $self->_translated or $self->_translated({}); +} + +sub translate_around { + my ($orig, $self) = (shift, shift); + my $fallback = $self->$orig(@_); + (my $col = (caller(2))[3]) =~ s/.*:://; + $self->_translate($col, $fallback); +} + +sub translate_column { + my ($self, $col) = (shift, shift); + my $fallback = $self->$col(@_); + $self->_translate($col, $fallback); +} + +sub _translate { + my ($self, $col, $fallback) = @_; + + my $langs = FixMyStreet->config('LANGUAGES'); + return $fallback if !$langs || @$langs < 2; + + my %cols = $self->get_columns; + return $cols{msgstr} if $cols{msgstr}; + + my $schema = $self->result_source->schema; + my $table = lc $self->result_source->source_name; + my $id = $self->id; + my $lang = $schema->lang || ''; + + my $translated = $self->translated->{$col}{$lang}; + return $translated if $translated; + + # Deal with the fact problem table has denormalized copy of category string + if ($table eq 'problem' && $col eq 'category') { + my $body_id = $self->bodies_str_ids->[0]; + return $fallback unless $body_id && $body_id =~ /^[0-9]+$/; + my $contact = $schema->resultset("Contact")->find( { + body_id => $body_id, + category => $fallback, + } ); + return $fallback unless $contact; # Shouldn't happen, but some tests + $table = 'contact'; + $id = $contact->id; + } + + if (ref $schema) { + my $translation = $schema->resultset('Translation')->find({ + lang => $lang, + tbl => $table, + object_id => $id, + col => $col + }); + $fallback = $translation->msgstr if $translation; + } else { + warn "Can't use translation on this call to $table.$col"; + } + $self->translated->{$col}{$lang} = $fallback; + return $fallback; +}; + +# These next two functions (translation_for and and_translation_for) are +# convenience methods for use in the translation interface in the admin. +# They shouldn't be used else where as they don't take account of things +# like denormalised strings (e.g report category) +sub translation_for { + my ($self, $col, $lang) = @_; + + my $schema = $self->result_source->schema; + + my $props = { + tbl => lc $self->result_source->source_name, + object_id => $self->id, + col => $col + }; + + if ($lang) { + $props->{lang} = $lang; + } + + my $translations = $schema->resultset('Translation')->search($props); + + return $lang ? $translations->first : $translations; +} + +sub add_translation_for { + my ($self, $col, $lang, $msgstr) = @_; + + my $schema = $self->result_source->schema; + + my $props = { + tbl => lc $self->result_source->source_name, + object_id => $self->id, + col => $col, + lang => $lang, + msgstr => $msgstr, + }; + + my $translation = $schema->resultset('Translation')->update_or_create( + $props, + { key => 'translation_tbl_object_id_col_lang_key' } + ); + + return $translation; +} + +1; |