66052fe14a092516780a47d5fcb0ec02a0f9cbf5
[catagits/CatalystX-Declare.git] / lib / CatalystX / Declare / Controller / ActionPreparation.pm
1 use MooseX::Declare;
2
3 role CatalystX::Declare::Controller::ActionPreparation {
4
5     use aliased 'CatalystX::Declare::Action::CatchValidationError';
6     use aliased 'CatalystX::Declare::Dispatching::ChainTypeSensitivity';
7
8     method _find_method_type_constraint (Str $name) {
9
10         $self->meta->find_method_type_constraint($name)
11             || do {
12                 my $method = $self->meta->find_method_by_name($name);
13                     ( $_ = $method->can('type_constraint') )
14                     ? $method->$_
15                     : undef
16             };
17     }
18
19     method _find_method_named_params (Str $name) {
20
21         return $self->meta->find_method_named_params($name);
22     }
23
24     method _find_method_named_type_constraint (Str $method, Str $param) {
25
26         return $self->meta->find_method_named_type_constraint($method, $param);
27     }
28
29     method _ensure_applied_dispatchtype_roles {
30
31         my $type = $self->_app->dispatcher->dispatch_type('Chained');
32
33         return
34             if $type->DOES(ChainTypeSensitivity);
35
36         my $immutable = $type->meta->is_immutable;
37         my %immutable_options;
38         if ($immutable) {
39             %immutable_options = $type->meta->immutable_options;
40             $type->meta->make_mutable;
41         }
42
43         # FIXME we really shouldn't have to tweak the dispatch type
44         ChainTypeSensitivity->meta->apply($type->meta);
45
46         $type->meta->make_immutable(%immutable_options)
47             if $immutable;
48     }
49
50     after register_actions {
51
52         $self->_ensure_applied_dispatchtype_roles;
53     }
54
55     around gather_action_roles(%args) {
56         return (
57             $self->$orig(%args),
58             @{ delete($args{attributes}{CatalystX_Declarative_ActionRoles}) || [] },
59         );
60     }
61
62     around create_action (%args) {
63         my $action = $self->$orig(%args);
64
65         return $action
66             if $args{attributes}{Private};
67
68         return $action 
69             unless $action->DOES(CatchValidationError);
70
71         my $tc = $self->_find_method_type_constraint($action->name);
72         my $np = $self->_find_method_named_params($action->name);
73
74         return $action
75             unless $tc;
76
77         $action->controller_instance($self);
78         $action->method_type_constraint($tc);
79
80         if ($np) {
81
82             $action->method_named_params($np);
83             $action->method_named_type_constraint({
84                 map +($_, $self->_find_method_named_type_constraint($action->name, $_)),
85                     @$np,
86             });
87         }
88
89         return $action;
90     }
91 }