5771eb77c2fbc4686b83782f3f6ab907f72df168
[scpubgit/DX.git] / lib / DX / Action / SetBoundValue.pm
1 package DX::Action::SetBoundValue;
2
3 use DX::Update::SetValue;
4 use DX::Class;
5
6 with 'DX::Role::Action';
7
8 has target_path => (is => 'ro', required => 1);
9
10 has rebind_path => (is => 'ro', required => 1);
11
12 has new_value => (is => 'ro', required => 1);
13
14 has inner_action => (is => 'ro', required => 1);
15
16 sub dry_run {
17   my ($self, $hyp) = @_;
18   my ($outer_hyp, @inner_events) = $self->inner_action->dry_run(
19     $hyp->but(
20       action_applications => [ @{$hyp->action_applications}, $self ],
21     ),
22   );
23   my ($scope, @events) = $outer_hyp->scope->apply_updates(
24                            DX::Update::SetValue->new(
25                              target_path => $self->target_path,
26                              new_value => $self->new_value,
27                            )
28                          );
29   my $new_bound = do {
30     my $targ = $scope;
31     $targ = $targ->get_member_at($_) for @{$self->rebind_path};
32     $targ;
33   };
34   my @actions = @{$outer_hyp->actions};
35   foreach my $idx (0.. $#actions) {
36     my $act = $actions[$idx];
37     if (
38       $act->isa('DX::Action::BindValue')
39         and join("\0", @{$act->target_path})
40               eq join("\0", @{$self->rebind_path})
41     ) {
42       my $bind = splice @actions, $idx, 1;
43       push @actions, $bind->but(new_value => $new_bound);
44       last;
45     }
46   }
47   return (
48     $outer_hyp->but(scope => $scope, actions => \@actions),
49     @inner_events, @events
50   );
51 }
52
53 sub run { die }
54
55 1;