diff options
Diffstat (limited to 'perllib')
-rw-r--r-- | perllib/Open311/Endpoint.pm | 17 | ||||
-rw-r--r-- | perllib/Open311/Endpoint/Role/mySociety.pm | 152 | ||||
-rw-r--r-- | perllib/Open311/Endpoint/Schema.pm | 3 | ||||
-rw-r--r-- | perllib/Open311/Endpoint/Service/Request.pm | 3 | ||||
-rw-r--r-- | perllib/Open311/Endpoint/Service/Request/Update.pm | 57 | ||||
-rw-r--r-- | perllib/Open311/Endpoint/Service/Request/mySociety.pm | 52 | ||||
-rw-r--r-- | perllib/Open311/Endpoint/Spark.pm | 3 |
7 files changed, 284 insertions, 3 deletions
diff --git a/perllib/Open311/Endpoint.pm b/perllib/Open311/Endpoint.pm index 8a440e4ae..0abb52aab 100644 --- a/perllib/Open311/Endpoint.pm +++ b/perllib/Open311/Endpoint.pm @@ -38,7 +38,11 @@ and provide the necessary methods. =head1 SUBCLASSING -See also t/open311/endpoint/Endpoint1.pm as an example. + package My::Open311::Endpoint; + use Web::Simple; + extends 'Open311::Endpoint'; + +See also t/open311/endpoint/Endpoint1.pm and Endpoint2.pm as examples. =head2 methods to override @@ -202,6 +206,11 @@ has schema => ( }, ); +sub learn_additional_types { + # my ($self, $rx) = @_; + ## no-op, but override in ::Role or implementation! +} + has spark => ( is => 'lazy', default => sub { @@ -232,6 +241,12 @@ has w3_dt => ( default => sub { DateTime::Format::W3CDTF->new }, ); +sub maybe_inflate_datetime { + my ($self, $dt) = @_; + return unless $dt; + return $self->w3_dt->parse_datetime($dt); +} + =head2 Dispatching The method dispatch_request returns a list of all the dispatcher routines diff --git a/perllib/Open311/Endpoint/Role/mySociety.pm b/perllib/Open311/Endpoint/Role/mySociety.pm new file mode 100644 index 000000000..42afe73bb --- /dev/null +++ b/perllib/Open311/Endpoint/Role/mySociety.pm @@ -0,0 +1,152 @@ +package Open311::Endpoint::Role::mySociety; + +=head1 NAME + +Open311::Endpoint::Role::mySociety - mySociety's proposed Open311 extensions + +=head1 SYNOPSIS + +See mySociety's +L<blog post|https://www.mysociety.org/2013/02/20/open311-extended/> +and +L<proposal|https://github.com/mysociety/FixMyStreet/wiki/Open311-FMS---Proposed-differences-to-Open311> +for a full explanation of the spec extension. + +You can use the extensions as follows: + + package My::Open311::Endpoint; + use Web::Simple; + extends 'Open311::Endpoint'; + with 'Open311::Endpoint::Role::mySociety'; + +You will have to provide implementations of + + get_service_request_updates + post_service_request_update + +You will need to return L<Open311::Endpoint::Service::Request::Update> +objects. However, the root L<Open311::Endpoint::Service::Request> is not +aware of updates, so you may may find it easier to ensure that the ::Service +objects you create (with get_service_request etc.) return +L<Open311::Endpoint::Service::Request::mySociety> objects. + +=cut + +use Moo::Role; +no warnings 'illegalproto'; + +around dispatch_request => sub { + my ($orig, $self, @args) = @_; + my @dispatch = $self->$orig(@args); + return ( + @dispatch, + + sub (GET + /servicerequestupdates + ?*) { + my ($self, $args) = @_; + $self->call_api( GET_Service_Request_Updates => $args ); + }, + + sub (POST + /servicerequestupdates + ?*) { + my ($self, $args) = @_; + $self->call_api( POST_Service_Request_Update => $args ); + }, + + ); +}; + +sub GET_Service_Request_Updates_input_schema { + my $self = shift; + return { + type => '//rec', + required => { + $self->get_jurisdiction_id_required_clause, + }, + optional => { + $self->get_jurisdiction_id_optional_clause,, + start_date => '/open311/datetime', + end_date => '/open311/datetime', + } + }; +} + +sub GET_Service_Request_Updates_output_schema { + my $self = shift; + return { + type => '//rec', + required => { + service_request_updates => { + type => '//arr', + contents => '/open311/service_request_update', + }, + }, + }; +} + +sub GET_Service_Request_Updates { + my ($self, $args) = @_; + + my @updates = $self->get_service_request_updates({ + jurisdiction_id => $args->{jurisdiction_id}, + start_date => $args->{start_date}, + end_date => $args->{end_date}, + }); + + $self->format_updates(@updates); +} + +sub format_updates { + my ($self, @updates) = @_; + return { + service_request_updates => [ + map { + my $update = $_; + +{ + ( + map { + $_ => $update->$_, + } + qw/ + update_id + service_request_id + status + description + media_url + / + ), + ( + map { + $_ => $self->w3_dt->format_datetime( $update->$_ ), + } + qw/ + updated_datetime + / + ), + } + } @updates + ] + }; +} + +sub get_service_request_updates { + my ($self, $args) = @_; + die "abstract method get_service_request_updates not overridden"; +} + +sub learn_additional_types { + my ($self, $schema) = @_; + $schema->learn_type( 'tag:wiki.open311.org,GeoReport_v2:rx/service_request_update', + { + type => '//rec', + required => { + service_request_id => $self->get_identifier_type('service_request_id'), + update_id => $self->get_identifier_type('update_id'), + status => '/open311/status', + updated_datetime => '/open311/datetime', + description => '//str', + media_url => '//str', + }, + } + ); +} + +1; diff --git a/perllib/Open311/Endpoint/Schema.pm b/perllib/Open311/Endpoint/Schema.pm index e30f9ad90..9a2ad81e5 100644 --- a/perllib/Open311/Endpoint/Schema.pm +++ b/perllib/Open311/Endpoint/Schema.pm @@ -12,6 +12,7 @@ has endpoint => ( get_jurisdiction_id_required_clause get_jurisdiction_id_optional_clause get_identifier_type + learn_additional_types /], ); @@ -167,6 +168,8 @@ has schema => ( } ); + $self->learn_additional_types($schema); + return $schema; }, ); diff --git a/perllib/Open311/Endpoint/Service/Request.pm b/perllib/Open311/Endpoint/Service/Request.pm index b56cee393..1d835f2d5 100644 --- a/perllib/Open311/Endpoint/Service/Request.pm +++ b/perllib/Open311/Endpoint/Service/Request.pm @@ -1,5 +1,6 @@ package Open311::Endpoint::Service::Request; use Moo; +use MooX::HandlesVia; use Types::Standard ':all'; use namespace::clean; @@ -57,7 +58,7 @@ has requested_datetime => ( ); has updated_datetime => ( - is => 'ro', + is => 'rw', isa => Maybe[ InstanceOf['DateTime'] ], ); diff --git a/perllib/Open311/Endpoint/Service/Request/Update.pm b/perllib/Open311/Endpoint/Service/Request/Update.pm new file mode 100644 index 000000000..b881af9ce --- /dev/null +++ b/perllib/Open311/Endpoint/Service/Request/Update.pm @@ -0,0 +1,57 @@ +package Open311::Endpoint::Service::Request::Update; +use Moo; +use Types::Standard ':all'; +use namespace::clean; + +sub BUILDARGS { + my ($class, %args) = @_; + my $service_request = delete $args{service_request}; + + if (! $args{status}) { + $args{status} = $service_request->status; + } + + return \%args; +} + +has update_id => ( + is => 'ro', + isa => Maybe[Str], + predicate => 1, +); + +has service_request_id => ( + is => 'ro', + isa => Maybe[Str], + predicate => 1, +); + +has token => ( + is => 'ro', + isa => Maybe[Str], + predicate => 1, +); + +has status => ( + is => 'ro', + isa => Enum[qw/ open closed /], +); + +has description => ( + is => 'ro', + isa => Maybe[Str], +); + +has media_url => ( + is => 'ro', + isa => Str, + default => sub { '' }, +); + +has updated_datetime => ( + is => 'ro', + isa => InstanceOf['DateTime'], + default => sub { DateTime->now() }, +); + +1; diff --git a/perllib/Open311/Endpoint/Service/Request/mySociety.pm b/perllib/Open311/Endpoint/Service/Request/mySociety.pm new file mode 100644 index 000000000..748065ad8 --- /dev/null +++ b/perllib/Open311/Endpoint/Service/Request/mySociety.pm @@ -0,0 +1,52 @@ +package Open311::Endpoint::Service::Request::mySociety; +use Moo; +use MooX::HandlesVia; +extends 'Open311::Endpoint::Service::Request'; + +use DateTime; +use Open311::Endpoint::Service::Request::Update; +use Types::Standard ':all'; + +has updates => ( + is => 'rw', + isa => ArrayRef[InstanceOf['Open311::Endpoint::Service::Request::Update']], + default => sub { [] }, + handles_via => 'Array', + handles => { + _add_update => 'push', + get_updates => 'elements', + get_update => 'get', + has_updates => 'count', + filter_updates => 'grep', + } +); + +sub add_update { + my ($self, %args) = @_; + my $update = Open311::Endpoint::Service::Request::Update->new( + %args, + service_request => $self, + service_request_id => $self->service_request_id, + ); + $self->_add_update($update); +} + + +sub last_update { + my $self = shift; + return $self->has_updates ? $self->get_update(-1) : undef; +} + +around updated_datetime => sub { + my ($orig, $self) = @_; + my $last_update = $self->last_update or return; + return $last_update->updated_datetime; +}; + +around status => sub { + my ($orig, $self) = @_; + my $last_update = $self->last_update or return 'open'; + return $last_update->status; +}; + +1; diff --git a/perllib/Open311/Endpoint/Spark.pm b/perllib/Open311/Endpoint/Spark.pm index ae179cecc..292a66996 100644 --- a/perllib/Open311/Endpoint/Spark.pm +++ b/perllib/Open311/Endpoint/Spark.pm @@ -1,6 +1,5 @@ package Open311::Endpoint::Spark; use Moo; -use Data::Visitor::Callback; =head1 NAME @@ -102,7 +101,9 @@ sub _process_for_xml { my %singular_map = ( service_requests => 'request', + service_request_updates => 'request_update', ); + sub _singularize { my $name = shift; return $singular_map{ $name } |