diff options
Diffstat (limited to 'lib/Reaction/UI/Controller/Collection.pm')
-rw-r--r-- | lib/Reaction/UI/Controller/Collection.pm | 190 |
1 files changed, 58 insertions, 132 deletions
diff --git a/lib/Reaction/UI/Controller/Collection.pm b/lib/Reaction/UI/Controller/Collection.pm index 7597d0f..d37f958 100644 --- a/lib/Reaction/UI/Controller/Collection.pm +++ b/lib/Reaction/UI/Controller/Collection.pm @@ -1,18 +1,25 @@ package Reaction::UI::Controller::Collection; -use strict; -use warnings; use base 'Reaction::UI::Controller'; use Reaction::Class; use aliased 'Reaction::UI::ViewPort::Collection::Grid'; -use aliased 'Reaction::UI::ViewPort::Object'; -has model_name => (isa => 'Str', is => 'rw', required => 1); -has collection_name => (isa => 'Str', is => 'rw', required => 1); +__PACKAGE__->config( + action => { + list => { Chained => 'base', PathPart => '' }, + object => { Chained => 'base', PathPart => 'id', CaptureArgs => 1, }, + view => { Chained => 'object', }, + }, +); -has action_viewport_map => (isa => 'HashRef', is => 'rw', lazy_build => 1); -has action_viewport_args => (isa => 'HashRef', is => 'rw', lazy_build => 1); +with( + 'Reaction::UI::Controller::Role::GetCollection', + 'Reaction::UI::Controller::Role::Action::Simple', + 'Reaction::UI::Controller::Role::Action::Object', + 'Reaction::UI::Controller::Role::Action::View', + 'Reaction::UI::Controller::Role::Action::List' +); has default_member_actions => ( isa => 'ArrayRef', @@ -30,34 +37,34 @@ sub _build_default_member_actions { ['view'] } sub _build_default_collection_actions { [] } -sub _build_action_viewport_map { - my $self = shift; - my %map; - $map{list} = Grid; - $map{view} = Object; #if grep {$_ eq 'view'} @{$self->default_member_actions}; - return \%map; -} +around _build_action_viewport_map => sub { + my $orig = shift; + my $map = shift->$orig( @_ ); + $map->{list} = Grid; + return $map; +}; -sub _build_action_viewport_args { +around _build_action_viewport_args => sub { + my $orig = shift; my $self = shift; my $args = { list => { Member => {} } }; - my $m_protos = $args->{list}{Member}{action_prototypes} = {}; - for my $action_name( @{ $self->default_member_actions }){ - my $label = join(' ', map { ucfirst } split(/_/, $action_name)); - my $proto = $self->_build_member_action_prototype($label, $action_name); - $m_protos->{$action_name} = $proto; - } + my $m_protos = $args->{list}{Member}{action_prototypes} = {}; + for my $action_name( @{ $self->default_member_actions }){ + my $label = join(' ', map { ucfirst } split(/_/, $action_name)); + my $proto = $self->_build_member_action_prototype($label, $action_name); + $m_protos->{$action_name} = $proto; + } - my $c_protos = $args->{list}{action_prototypes} = {}; - for my $action_name( @{ $self->default_collection_actions }){ - my $label = join(' ', map { ucfirst } split(/_/, $action_name)); - my $proto = $self->_build_collection_action_prototype($label, $action_name); - $c_protos->{$action_name} = $proto; - } + my $c_protos = $args->{list}{action_prototypes} = {}; + for my $action_name( @{ $self->default_collection_actions }){ + my $label = join(' ', map { ucfirst } split(/_/, $action_name)); + my $proto = $self->_build_collection_action_prototype($label, $action_name); + $c_protos->{$action_name} = $proto; + } return $args; -} +}; sub _build_member_action_prototype { my ($self, $label, $action_name) = @_; @@ -81,56 +88,21 @@ sub _build_collection_action_prototype { }; } -#XXX candidate for futre optimization, should cache reader? -sub get_collection { - my ($self, $c) = @_; - my $model = $c->model( $self->model_name ); - confess "Failed to find Catalyst model named: " . $self->model_name - unless $model; - my $collection = $self->collection_name; - if( my $meth = $model->can( $collection ) ){ - return $model->$meth; - } elsif ( my $meta = $model->can('meta') ){ - if ( my $attr = $model->$meta->find_attribute_by_name($collection) ) { - my $reader = $attr->get_read_method; - return $model->$reader; - } - } - confess "Failed to find collection $collection"; -} -sub base :Action :CaptureArgs(0) { +sub base :CaptureArgs(0) { my ($self, $c) = @_; } -sub object :Chained('base') :PathPart('id') :CaptureArgs(1) { - my ($self, $c, $key) = @_; - my $object = $self->get_collection($c)->find($key); - $c->detach("/error_404") unless $object; - $c->stash(object => $object); -} - -sub list :Chained('base') :PathPart('') :Args(0) { - my ($self, $c) = @_; - my $collection = $c->stash->{collection} || $self->get_collection($c); - $self->basic_page($c, { collection => $collection }); -} - -sub view :Chained('object') :Args(0) { - my ($self, $c) = @_; - $self->basic_page($c, { model => $c->stash->{object} }); -} +##DEPRECATED ACTION sub basic_page { - my ($self, $c, $vp_args) = @_; - my $action_name = $c->stack->[-1]->name; - my $vp = $self->action_viewport_map->{$action_name}, - my $args = $self->merge_config_hashes - ( - $vp_args || {}, - $self->action_viewport_args->{$action_name} || {} , - ); - return $self->push_viewport($vp, %$args); + my( $self, $c, @args) = @_; + if( $c->debug ){ + my ($package,undef,$line,$sub_name,@rest) = caller(1); + my $message = "The method 'basic_page', called from sub '${sub_name}' in package ${package} at line ${line} is deprecated. Please use 'setup_viewport' instead."; + $c->log->debug( $message ); + } + $self->setup_viewport( $c, @args ); } 1; @@ -146,48 +118,25 @@ Reaction::UI::Controller Controller class used to make displaying collections easier. Inherits from L<Reaction::UI::Controller>. -=head1 ATTRIBUTES - -=head2 model_name +=head1 ROLES CONSUMED -The name of the model this controller will use as it's data source. Should be a -name that can be passed to C<$C-E<gt>model> +This role also consumes the following roles: -=head2 collection_name +=over4 -The name of the collection whithin the model that this Controller will be -utilizing. +=item L<Reaction::UI::Controller::Role::Action::GetCollection> -=head2 action_viewport_map +=item L<Reaction::UI::Controller::Role::Action::Simple> -=over 4 +=item L<Reaction::UI::Controller::Role::Action::Object> -=item B<_build_action_viewport_map> - Provided builder method, see METHODS +=item L<Reaction::UI::Controller::Role::Action::List> -=item B<has_action_viewport_map> - Auto generated predicate - -=item B<clear_action_viewport_map>- Auto generated clearer method +=item L<Reaction::UI::Controller::Role::Action::View> =back -Read-write lazy building hashref. The keys should match action names in the -Controller and the value should be the ViewPort class that this action should -use. See method C<basic_page> for more info. - -=head2 action_viewport_args - -Read-write lazy building hashref. Additional ViewPort arguments for the action -named as the key in the controller. See method C<basic_page> for more info. - -=over 4 - -=item B<_build_action_viewport_args> - Provided builder method, see METHODS - -=item B<has_action_viewport_args> - Auto generated predicate - -=item B<clear_action_viewport_args>- Auto generated clearer method - -=back +=head1 ATTRIBUTES =head2 default_member_actions @@ -225,16 +174,9 @@ is only empty. =head1 METHODS -=head2 get_collection $c - -Returns an instance of the collection this controller uses. - =head2 _build_action_viewport_map -Provided builder for C<action_viewport_map>. Returns a hash containing: - - list => 'Reaction::UI::ViewPort::Collection::Grid', - view => 'Reaction::UI::ViewPort::Object', +Set C<list> to L<Reaction::UI::ViewPort::Collection::Grid> =head2 _build_action_viewport_args @@ -269,11 +211,7 @@ based on the action, current captures. =head2 basic_page $c, \%vp_args -Accepts two arguments, context, and a hashref of viewport arguments. It will -automatically determine the action name using the catalyst stack and call -C<push_viewport> with the ViewPort class name contained in the -C<action_viewport_map> with a set of options determined by merging C<$vp_args> -and the arguments contained in C<action_viewport_args>, if any. +Deprecated alias to C<setup_viewport>. =head1 ACTIONS @@ -283,27 +221,15 @@ Chain link, no-op. =head2 list -Chain link, chained to C<base>. C<list> fetches the collection for the model -and calls C<basic_page> with a single argument, C<collection>. - -The default ViewPort for this action is C<Reaction::UI::ViewPort::ListView> and -can be changed by altering the C<action_viewport_map> attribute hash. +Chained to C<base>. See L<Reaction::UI::Controller::Role::Action::List> =head2 object -Chain link, chained to C<base>, captures one argument, 'id'. Attempts to find -a single object by searching for a member of the current collection which has a -Primary Key or Unique constraint matching that argument. If the object is found -it is stored in the stash under the C<object> key. +Chained to C<base>. See L<Reaction::UI::Controller::Role::Action::Object> =head2 view -Chain link, chained to C<object>. Calls C<basic page> with one argument, -C<model>, which contains an instance of the object fetched by the C<object> -action link. - -The default ViewPort for this action is C<Reaction::UI::ViewPort::Object> and -can be changed by altering the C<action_viewport_map> attribute hash. +Chained to C<object>. See L<Reaction::UI::Controller::Role::Action::View> =head1 SEE ALSO |