shallow copying req->params
[catagits/Reaction.git] / lib / Reaction / UI / ViewPort / Action.pm
1 package Reaction::UI::ViewPort::Action;
2
3 use Reaction::Class;
4
5 use MooseX::Types::Moose qw/Int Str/;
6 use Reaction::Types::Core qw/NonEmptySimpleStr/;
7
8 use namespace::clean -except => [ qw(meta) ];
9
10 extends 'Reaction::UI::ViewPort::Object::Mutable';
11 with 'Reaction::UI::ViewPort::Action::Role::OK';
12
13 has message => (is => 'rw', isa => Str);
14 has '+model' => (handles => [qw/error_message has_error_message/]);
15
16 #this has to fucking go. it BLOWS.
17 has method => (
18   is => 'rw',
19   isa => NonEmptySimpleStr,
20   default => sub { 'post' }
21 );
22
23 has changed => (
24   is => 'rw',
25   isa => Int,
26   reader => 'is_changed',
27   default => sub{0}
28 );
29
30 sub can_apply {
31   my ($self) = @_;
32   foreach my $field ( @{ $self->fields } ) {
33     return 0 if $field->needs_sync;
34     # if e.g. a datetime field has an invalid value that can't be re-assembled
35     # into a datetime object, the action may be in a consistent state but
36     # not synchronized from the fields; in this case, we must not apply
37   }
38   return $self->model->can_apply;
39 }
40
41 sub do_apply {
42   shift->model->do_apply;
43 }
44
45 after apply_child_events => sub {
46   # interrupt here because fields will have been updated
47   my ($self) = @_;
48   $self->sync_action_from_fields;
49 };
50
51 sub sync_action_from_fields {
52   my ($self) = @_;
53   foreach my $field (@{$self->fields}) {
54     $field->sync_to_action; # get the field to populate the $action if possible
55   }
56   $self->model->sync_all;
57   foreach my $field (@{$self->fields}) {
58     $field->sync_from_action; # get errors from $action if applicable
59   }
60 }
61
62
63 __PACKAGE__->meta->make_immutable;
64
65 1;
66
67 __END__;
68
69 =head1 NAME
70
71 Reaction::UI::ViewPort::Action - Provide user with a form with OK, Apply and Close.
72
73 =head1 SYNOPSIS
74
75   $controller->push_viewport('Reaction::UI::ViewPort::Action',
76     model           => $interface_model_action,
77     field_order     => [qw( firstname lastname )],
78     excluded_fields => [qw( password )],
79   );
80
81 =head1 DESCRIPTION
82
83 This subclass of L<Reaction::UI::ViewPort::Object::Mutable> is used for 
84 rendering a complete form supporting Apply, Close and OK.
85
86 =head1 ATTRIBUTES
87
88 =head2 message
89
90 =head2 model
91
92 Inherited from L<Reaction::UI::ViewPort::Object::Mutable>. Must be a
93 L<Reaction::InterfaceModel::Action>.
94
95 Also handles C<error_message> and C<has_error_message> methods.
96
97 =head2 method
98
99 post / get
100
101 =head2 changed
102
103 Returns true if a field has been edited.
104
105 =head1 METHODS
106
107 =head2 can_apply
108
109 Returns true if no field C<needs_sync> and the L</model> C<can_apply>.
110
111 =head2 do_apply
112
113 Delegates to C<do_apply> on the L</model>, which is a 
114 L<Reaction::InterfaceModel::Action>.
115
116 =head2 sync_action_from_fields
117
118 Firstly calls C<sync_to_action> on every L<Reaction::UI::ViewPort::Field::Mutable>
119 in L<fields|Reaction::UI::ViewPort::Object/fields>. Then it calls C<sync_all> on
120 the L<Reaction::InterfaceModel::Action> in L</model>. Next it will call
121 C<sync_from_action> on every field to repopulate them from the L</model>.
122
123 =head1 SUBCLASSING
124
125   package MyApp::UI::ViewPort::Action;
126   use Reaction::Class;
127   use MooseX::Types::Moose qw( Int );
128
129   use namespace::clean -except => 'meta';
130
131   extends 'Reaction::UI::ViewPort::Action';
132
133   has render_timestamp => (
134     is       => 'ro',
135     isa      => Int,
136     default  => sub { time },
137     required => 1,
138   );
139
140   has '+field_order' => (default => sub {[qw( firstname lastname )]});
141
142   1;
143
144 =head1 SEE ALSO
145
146 L<Reaction::UI::ViewPort>
147
148 L<Reaction::UI::ViewPort::Object>
149
150 L<Reaction::UI::ViewPort::Object::Mutable>
151
152 L<Reaction::InterfaceModel::Action::Role::Apply>
153
154 L<Reaction::InterfaceModel::Action::Role::Close>
155
156 L<Reaction::InterfaceModel::Action::Role::OK>
157
158 =head1 AUTHORS
159
160 See L<Reaction::Class> for authors.
161
162 =head1 LICENSE
163
164 See L<Reaction::Class> for the license.
165
166 =cut
167