loading Config::Any in Reaction::UI::Skin
[catagits/Reaction.git] / lib / Reaction / UI / Controller.pm
CommitLineData
7adfd53f 1package Reaction::UI::Controller;
2
7f43bb45 3use base qw(Catalyst::Controller); # Reaction::Object);
1810d302 4
7adfd53f 5use Reaction::Class;
747a1feb 6use Scalar::Util 'weaken';
db80cb74 7use namespace::clean -except => [ qw(meta) ];
7adfd53f 8
d0736579 9has context => (is => 'ro', isa => 'Object', weak_ref => 1);
10with 'Catalyst::Component::InstancePerContext';
11
12sub build_per_context_instance {
13 my ($self, $c, @args) = @_;
14 my $newself = $self->new($self->_application, {%$self, context => $c, @args});
15 return $newself;
16}
17
7adfd53f 18sub push_viewport {
19 my $self = shift;
1810d302 20 my $c = $self->context;
21 my $focus_stack = $c->stash->{focus_stack};
7adfd53f 22 my ($class, @proto_args) = @_;
23 my %args;
7adfd53f 24 if (my $vp_attr = $c->stack->[-1]->attributes->{ViewPort}) {
25 if (ref($vp_attr) eq 'ARRAY') {
26 $vp_attr = $vp_attr->[0];
27 }
28 if (ref($vp_attr) eq 'HASH') {
29 if (my $conf_class = delete $vp_attr->{class}) {
30 $class = $conf_class;
31 }
504e2c44 32 %args = %{ $self->merge_config_hashes($vp_attr, {@proto_args}) };
7adfd53f 33 } else {
34 $class = $vp_attr;
35 %args = @proto_args;
36 }
37 } else {
38 %args = @proto_args;
39 }
40
41 $args{ctx} = $c;
42
43 if (exists $args{next_action} && !ref($args{next_action})) {
44 $args{next_action} = [ $self, 'redirect_to', $args{next_action} ];
45 }
46 $focus_stack->push_viewport($class, %args);
47}
48
49sub pop_viewport {
1810d302 50 return shift->context->stash->{focus_stack}->pop_viewport;
7adfd53f 51}
52
53sub pop_viewports_to {
54 my ($self, $vp) = @_;
1810d302 55 return $self->context->stash->{focus_stack}->pop_viewports_to($vp);
7adfd53f 56}
57
58sub redirect_to {
59 my ($self, $c, $to, $cap, $args, $attrs) = @_;
60
61 #the confess calls could be changed later to $c->log ?
62 my $action;
9cf5bc0b 63 my $reftype = ref($to);
64 if( $reftype eq '' ){
65 $action = $self->action_for($to);
66 confess("Failed to locate action ${to} in " . blessed($self)) unless $action;
67 } elsif($reftype eq 'ARRAY' && @$to == 2){ #is that overkill / too strict?
68 $action = $c->controller($to->[0])->action_for($to->[1]);
69 confess("Failed to locate action $to->[1] in $to->[0]" ) unless $action;
70 } elsif( blessed $to && $to->isa('Catalyst::Action') ){
71 $action = $to;
7adfd53f 72 } else{
9cf5bc0b 73 confess("Failed to locate action from ${to}");
7adfd53f 74 }
75
76 $cap ||= $c->req->captures;
77 $args ||= $c->req->args;
78 $attrs ||= {};
79 my $uri = $c->uri_for($action, $cap, @$args, $attrs);
80 $c->res->redirect($uri);
81}
82
747a1feb 83sub make_context_closure {
84 my($self, $closure) = @_;
85 my $ctx = $self->context;
db80cb74 86 weaken($ctx);
747a1feb 87 return sub { $closure->($ctx, @_) };
88}
89
7adfd53f 901;
f2756356 91
92__END__;
93
94=head1 NAME
95
63bb30b4 96Reaction::UI::Controller - Reaction Base Controller Class
97
98=head1 SYNOPSIS
99
100 package MyApp::Controller::Foo;
101 use strict;
102 use warnings;
103 use parent 'Reaction::UI::Controller';
104
105 use aliased 'Reaction::UI::ViewPort';
106
107 sub foo: Chained('/base') Args(0) {
108 my ($self, $ctx) = @_;
109
110 $ctx->push_viewport(ViewPort,
111 layout => 'foo',
112 );
113 }
114
115 1;
f2756356 116
117=head1 DESCRIPTION
118
119Base Reaction Controller class. Inherits from:
120
121=over 4
122
123=item L<Catalyst::Controller>
124=item L<Catalyst::Component::ACCEPT_CONTEXT>
125=item L<Reaction::Object>
126
127=back
128
129=head1 METHODS
130
131=head2 push_viewport $vp_class, %args
132
f1cd5548 133Creates a new instance of the L<Reaction::UI::ViewPort> class
134($vp_class) using the rest of the arguments given (%args). Defaults of
135the action can be overridden by using the C<ViewPort> key in the
136controller configuration. For example to override the default number
137of items in a CRUD list action:
138
139__PACKAGE__->config(
140 action => {
141 list => { ViewPort => { per_page => 50 } },
142 }
143 );
144
145The ViewPort is added to the L<Reaction::UI::Window>'s FocusStack in
146the stash, and also returned to the calling code.
147
148Related items:
149
150=over
151
152=item L<Reaction::UI::Controller::Root>
153=item L<Reaction::UI::Window>
154
155=back
f2756356 156
157TODO: explain how next_action as a scalar gets converted to the redirect arrayref thing
158
159=head2 pop_viewport
160
161=head2 pop_viewport_to $vp
162
f1cd5548 163Call L<Reaction::UI::FocusStack/pop_viewport> or
164L<Reaction::UI::FocusStack/pop_viewport_to> on
165the C<< $c->stash->{focus_stack} >>.
f2756356 166
167=head2 redirect_to $c, $to, $captures, $args, $attrs
168
f1cd5548 169Construct a URI and redirect to it.
170
171$to can be:
172
173=over
f2756356 174
f1cd5548 175=item The name of an action in the current controller.
f2756356 176
f1cd5548 177=item A L<Catalyst::Action> instance.
178
179=item An arrayref of controller name and the name of an action in that
180controller.
181
182=back
f2756356 183
f1cd5548 184$captures and $args default to the current requests $captures and
185$args if not supplied.
f2756356 186
187=head1 AUTHORS
188
189See L<Reaction::Class> for authors.
190
191=head1 LICENSE
192
193See L<Reaction::Class> for the license.
194
195=cut