File Coverage

lib/CallBackery/GuiPlugin/AbstractAction.pm
Criterion Covered Total %
statement 56 78 71.7
branch 10 18 55.5
condition 2 9 22.2
subroutine 10 13 76.9
pod 1 1 100.0
total 79 119 66.3


line stmt bran cond sub pod time code
1             package CallBackery::GuiPlugin::AbstractAction;
2 1     1   629 use Carp qw(carp croak);
  1         1  
  1         55  
3 1     1   4 use CallBackery::Translate qw(trm);
  1         1  
  1         33  
4 1     1   3 use CallBackery::Exception qw(mkerror);
  1         1  
  1         26  
5 1     1   63 use Mojo::Promise;
  1         4  
  1         8  
6 1     1   33 use Mojo::JSON qw(encode_json);
  1         1  
  1         36  
7 1     1   3 use Mojo::Util qw(dumper);
  1         1  
  1         48  
8              
9             =head1 NAME
10              
11             CallBackery::GuiPlugin::AbstractAction - action form base class
12              
13             =head1 SYNOPSIS
14              
15             use Mojo::Base 'CallBackery::GuiPlugin::AbstractAction';
16              
17             =head1 DESCRIPTION
18              
19             The base class for gui forms with actions.
20              
21             =cut
22              
23 1     1   4 use Mojo::Base 'CallBackery::GuiPlugin::Abstract', -signatures;
  1         2  
  1         5  
24              
25             =head1 ATTRIBUTES
26              
27             The attributes of the L class plus:
28              
29             =head2 screenCfg
30              
31             Returns a configuration structure for the form. The output from this
32             method is fed to the callbackery.ui.form.Auto object to build the
33             Qooxdoo form.
34              
35             =cut
36              
37             has screenCfg => sub {
38             my $self = shift;
39             $self->__fixActionCfg;
40             return {
41             type => 'action',
42             options => $self->screenOpts,
43             action => $self->actionCfg,
44             }
45             };
46              
47             # if no user is assigned, all access checks are positive, this allows to explore the
48             # modules full capabilities during startup
49             has 'user'=> sub ($self) {
50             my $mockUser = bless {}, 'MockUser';
51             unless (defined &MockUser::may) {
52 1     1   7 *MockUser::may = sub ($mockSelf, $right) {
  1         3  
  1         3  
  1         2  
53             # $self->log->debug("MockUser::may($right) -> true");
54 1         5 return 1;
55             };
56             }
57             unless (defined &MockUser::mayAny) {
58 0     0   0 *MockUser::mayAny = sub ($mockSelf, $right) {
  0         0  
  0         0  
  0         0  
59             # $self->log->debug("MockUser::may($right) -> true");
60 0         0 return 1;
61             };
62             }
63             unless (defined &MockUser::userId) {
64 0     0   0 *MockUser::userId = sub ($mockSelf) {
  0         0  
  0         0  
65 0         0 return '__MockUser__';
66             };
67             }
68             unless (defined &MockUser::userInfo) {
69 0     0   0 *MockUser::userInfo = sub ($mockSelf) {
  0         0  
  0         0  
70 0         0 return {};
71             };
72             }
73             return $mockUser;
74             };
75              
76             =head2 screenOpts
77              
78             Returns a hash of options for the screen Options
79              
80             =cut
81              
82             has screenOpts => sub {
83             {
84             }
85             };
86              
87             =head2 actionCfg
88              
89             Returns a list of action buttons to place at the top of the form.
90              
91             =cut
92              
93             has actionCfg => sub {
94             [];
95             };
96              
97             =head2 actionCfgMap
98              
99             Lookup table for action plugins.
100              
101             NOTE: Unique keys are not checked for popup plugins as they don't have
102             action handlers.
103             This allows multiple popup actions using the same plugin instance.
104             In this case an additional cfg parameter C must be
105             used to make the QoxdooObjectIds unique used from frontend testing.
106              
107             =cut
108              
109             has actionCfgMap => sub {
110             my $self = shift;
111             my %map;
112             for my $row (@{$self->actionCfg}){
113             next unless $row->{action} =~ /^(submit|upload|download|display|autoSubmit|save)/;
114             next unless $row->{key};
115             my $key = $row->{key};
116             die mkerror(4646, "Duplicate action key $key") if exists $map{$key};
117             $map{$key} = $row;
118             }
119             return \%map;
120             };
121              
122              
123             =head1 METHODS
124              
125             All the methods of L plus:
126              
127             =cut
128              
129             =head2 massageConfig
130              
131             Function to integrate the plugin configuration recursively into the main config
132             hash.
133              
134             =cut
135              
136             sub massageConfig {
137 4     4 1 10 my $self = shift;
138 4         7 my $cfg = shift;
139 4         23 $self->__fixActionCfg;
140 4         16 my $actionCfg = $self->actionCfg;
141 4         27 for my $button (@$actionCfg){
142 6 100       35 if ($button->{action} =~ /popup|wizzard/) {
143 2         6 my $name = $button->{name};
144             # allow same plugin multiple times
145 2         6 $button->{name} = $name;
146 2 50       10 if ($cfg->{PLUGIN}{prototype}{$name}) {
147 0         0 my $newCfg = encode_json($button->{backend});
148 0         0 my $oldCfg = encode_json($cfg->{PLUGIN}{prototype}{$name}{backend});
149 0 0 0     0 if ($oldCfg ne 'null' and $newCfg ne $oldCfg) {
150 0         0 $self->log->warn("oldCfg=" . dumper $oldCfg);
151 0         0 $self->log->warn("newCfg=", dumper $newCfg);
152 0         0 die "Not unique plugin instance name $name not allowed as backend config is different\n";
153             }
154             }
155             my $popup = $cfg->{PLUGIN}{prototype}{$name}
156 2         9 = $self->app->config->loadAndNewPlugin($button->{backend}{plugin});
157 2         14 $popup->config($button->{backend}{config});
158 2         19 $popup->name($name);
159 2         19 $popup->app($self->app);
160 2         36 $popup->massageConfig($cfg);
161             }
162             }
163 4 50       19 if (ref $self->user eq 'MockUser') {
164             # $self->log->debug("massageConfig is done. undefining user");
165 4         19 $self->user(undef);
166             }
167 4         63 return;
168             }
169              
170             =head2 __fixActionCfg
171              
172             make sure actionCfg buttons only have keys and no names
173             add properly constructed name properties
174              
175             =cut
176              
177             sub __fixActionCfg {
178 4     4   10 my $self = shift;
179 4 50       15 return $self if $self->{__action_cfg_fixed};
180 4         14 my $name = $self->name;
181 4         26 my $pkg = ref $self;
182 4         7 for my $action (@{$self->actionCfg}) {
  4         15  
183             next if $action->{action} eq 'separator'
184             or $action->{action} eq 'refresh'
185 6 50 33     51 or $action->{action} eq 'logout';
      33        
186 6 50       15 if ($action->{name}) {
187 0         0 $self->log->warn(
188             $pkg . " action should not have a name attribute:"
189             . " name=$action->{name}"
190             );
191             }
192 6 50       20 if (not $action->{key}) {
193 0         0 $self->log->warn(
194             $pkg . " action should have a key attribute,"
195             . " created a key from name=$action->{name} instead"
196             );
197 0         0 $action->{key} = $action->{name};
198             }
199             # popups and wizzards do need a name internally
200 6 100       40 if ($action->{action} =~ /popup|wizzard/) {
201 2         10 $action->{name} = "${name}_$action->{key}";
202             }
203             }
204 4         11 $self->{__action_cfg_fixed} = 1;
205 4         9 return $self;
206             }
207              
208              
209             1;
210             __END__