File Coverage

blib/lib/MasonX/Request/ExtendedCompRoot.pm
Criterion Covered Total %
statement 27 389 6.9
branch 0 200 0.0
condition 0 49 0.0
subroutine 9 32 28.1
pod 6 14 42.8
total 42 684 6.1


line stmt bran cond sub pod time code
1             # This software is copyright (c) 2004 Alex Robinson.
2             # It is free software and can be used under the same terms as perl,
3             # i.e. either the GNU Public Licence or the Artistic License.
4              
5             package MasonX::Request::ExtendedCompRoot;
6              
7 1     1   4184 use strict;
  1         1  
  1         34  
8              
9             our $VERSION = '0.04';
10              
11 1     1   4 use Carp;
  1         1  
  1         40  
12 1     1   480 use Data::Dumper;
  1         7952  
  1         66  
13              
14 1     1   6 use base qw(HTML::Mason::Request);
  1         2  
  1         671  
15              
16             # Need this because we've copied comp to _comp
17 1     1   45160 use constant STACK_BUFFER => 2;
  1         2  
  1         58  
18              
19             # fetch_comp needs this
20 1     1   4 use HTML::Mason::Tools qw(absolute_comp_path);
  1         1  
  1         46  
21 1     1   4 use HTML::Mason::Exceptions( abbr => [qw(param_error error)] );
  1         1  
  1         6  
22 1     1   45 use Params::Validate qw(:all);
  1         2  
  1         163  
23             Params::Validate::validation_options( on_fail => sub { param_error( join '', @_ ) } );
24 1     1   4 use File::Spec;# qw(canonpath file_name_is_absolute);
  1         6  
  1         2749  
25              
26             my %params =
27             (
28             pseudodhandler_exclude_paths =>
29             {
30             type => ARRAYREF,
31             optional => 1,
32             default => [],
33             descr => 'list of regular expressions to match paths for pseudo-dhandlering to ignore'
34             },
35             pseudodhandler_exclude_comp_roots =>
36             {
37             type => ARRAYREF,
38             optional => 1,
39             default => [],
40             descr => 'list of regular expressions to match comp roots for pseudo-dhandlering to ignore'
41             },
42             pseudodhandler_name =>
43             {
44             type => SCALAR,
45             optional => 1,
46             default => 'pseudodhandler',
47             descr => "The filename to use for ExtendedCompRoot's 'pseudodhandler' capability - an empty string suppresses its use"
48             }
49             );
50              
51             __PACKAGE__->valid_params(%params);
52              
53             #
54             # Standard request subclass alter_superclass dance
55             #
56             sub new
57             {
58 0     0 1   my $class = shift;
59 0 0         $class->alter_superclass(
    0          
60             $HTML::Mason::ApacheHandler::VERSION ?
61             'HTML::Mason::Request::ApacheHandler' :
62             $HTML::Mason::CGIHandler::VERSION ?
63             'HTML::Mason::Request::CGI' :
64             'HTML::Mason::Request' );
65 0           my $self = $class->SUPER::new(@_);
66              
67 0           return $self->_init_extended(@_);
68             }
69              
70             sub _init_extended
71             {
72 0     0     my $self = shift;
73 0           my %params = @_;
74            
75 0           my $store_root = $self->comp_root;
76 0           $self->_base_comp_root($store_root);
77 0           $self->_pseudodhandler_exclude_paths($params{pseudodhandler_exclude_paths});
78 0           $self->_pseudodhandler_exclude_comp_roots($params{pseudodhandler_exclude_comp_roots});
79 0           $self->pseudodhandler_name($params{pseudodhandler_name});
80              
81 0           return $self;
82              
83             }
84              
85             sub _base_comp_root
86             {
87 0     0     my $self = shift;
88 0           my $value = shift;
89 0 0         $self->{base_comp_root} = $value if (defined($value));
90 0           return $self->{base_comp_root};
91             }
92             sub pseudodhandler_name
93             {
94 0     0 0   my $self = shift;
95 0           my $value = shift;
96 0 0         $self->{pseudodhandler_name} = $value if (defined($value));
97 0           return $self->{pseudodhandler_name};
98             }
99              
100             sub pseudodhandler_arg
101             {
102 0     0 0   my $self = shift;
103 0           my $value = shift;
104 0 0         $self->{pseudodhandler_arg} = $value if (defined($value));
105 0           return $self->{pseudodhandler_arg};
106             }
107              
108             sub adjusted_args
109             {
110 0     0 0   my $self = shift;
111 0           my $key = shift;
112 0           my $value = shift;
113 0 0         unless ($self->{adjusted_args_initialised})
114             {
115 0           $self->{adjusted_args} = $self->{request_args};
116 0           $self->{adjusted_args_initialised} = 1;
117             }
118            
119 0 0         unless ($key)
120             {
121 0 0         if (wantarray)
122             {
123 0           return @{$self->{adjusted_args}};
  0            
124             }
125             else
126             {
127 0           return { @{$self->{adjusted_args}} };
  0            
128             }
129             }
130             # surely I can do better than this?
131 0           my %adjusted_args = @{$self->{adjusted_args}};
  0            
132            
133 0 0         return $adjusted_args{$key} unless (defined($value));
134            
135 0           $adjusted_args{$key} = $value;
136 0           my @store_adjusted = %adjusted_args;
137 0           $self->{adjusted_args} = \@store_adjusted;
138 0           return $self->adjusted_args($key);
139             }
140              
141             sub _pseudodhandler_exclude_paths
142             {
143 0     0     my ($self, $exclude_paths) = @_;
144 0 0         if (defined($exclude_paths))
145             {
146 0           $self->{pseudodhandler_exclude_paths} = $exclude_paths;
147             }
148 0           $exclude_paths = $self->{pseudodhandler_exclude_paths};
149 0 0         return $exclude_paths ? @{$exclude_paths} : ();
  0            
150             }
151             sub _pseudodhandler_exclude_comp_roots
152             {
153 0     0     my ($self, $exclude_roots) = @_;
154 0 0         if (defined($exclude_roots))
155             {
156 0           $self->{pseudodhandler_exclude_comp_roots} = $exclude_roots;
157             }
158 0           $exclude_roots = $self->{pseudodhandler_exclude_comp_roots};
159 0 0         return $exclude_roots ? @{$exclude_roots} : ();
  0            
160             }
161              
162              
163             # to enable the passing of INHERIT and SUPER and also allow pseudo-dhandlering
164             # copied and pasted from HTML::Mason::Request 1.30 - checked against 1.37
165             sub _fetch_comp
166             {
167 0     0     my ($self, $path, $current_comp, $error) = @_;
168              
169             #
170             # Handle paths SELF, PARENT, and REQUEST
171             #
172 0 0         if ($path eq 'SELF') {
173 0           return $self->base_comp;
174             }
175 0 0         if ($path eq 'PARENT') {
176 0           my $c = $current_comp->parent;
177 0 0 0       $$error = "PARENT designator used from component with no parent" if !$c && defined($error);
178 0           return $c;
179             }
180 0 0         if ($path eq 'REQUEST') {
181 0           return $self->request_comp;
182             }
183              
184             #
185             # Handle paths of the form comp_path:method_name
186             #
187 0 0         if (index($path,':') != -1) {
188 0           my $method_comp;
189 0           my ($owner_path,$method_name) = split(':',$path,2);
190 0 0         if (my $owner_comp = $self->fetch_comp($owner_path, $current_comp, $error)) {
191 0 0         if ($owner_comp->_locate_inherited('methods',$method_name,\$method_comp)) {
192 0           return $method_comp;
193             } else {
194 0 0         if ($owner_path =~ m/^(INHERIT|SUPER)/) #ECR
195             { #ECR
196 0           $owner_path = $current_comp->path; #ECR
197 0           my @comp_root = $self->comp_root; #ECR
198 0 0         @comp_root = reverse(@comp_root) if ($owner_path eq 'SUPER'); #ECR
199 0           foreach my $root (@comp_root) #ECR
200             { #ECR
201 0 0         if (my $owner_comp = $self->fetch_comp($root->[0].'=>'.$owner_path, $current_comp, $error)) #ECR
202             { #ECR
203 0 0         if ($owner_comp->_locate_inherited('methods',$method_name,\$method_comp)) #ECR
204             { #ECR
205 0           return $method_comp; #ECR
206             } #ECR
207             } #ECR
208             } #ECR
209 0 0         $$error = "no such method '$method_name' exists in any comp root for component " . $owner_comp->title . " <- topmost root" if defined($error); #ECR
210 0           return; #ECR
211             } #ECR
212 0 0         $$error = "no such method '$method_name' for component " . $owner_comp->title if defined($error);
213             }
214             } else {
215 0 0 0       $$error ||= "could not find component for path '$owner_path'\n" if defined($error);
216             }
217              
218 0           return $method_comp;
219             }
220              
221 0           my $super; #ECR
222 0 0         if ($path =~ m/(SUPER|INHERIT)$/) #ECR
223             {
224 0 0         $super = 1 if ($path =~ m/SUPER$/); #ECR
225 0           $path = $current_comp->path; #ECR
226             #die "YADDER SUPER - ". $path; #ECR
227             } #ECR
228 0 0         if ($path =~ m/^_/) #ECR
229             { #ECR
230 0           $path =~ s/^_//; #ECR
231             # unfortunately, Mason::Request has a local select #ECR
232 0 0         if ($path =~ m/::SELECTED/) #ECR
233             { #ECR
234 0           $path = 'select'; #ECR
235             } #ECR
236 0   0       my $tags_path = $self->notes->{_OUTPUT}->{tag_type} || 'xhtml1-strict'; #ECR
237 0           $path = "/tags/$tags_path/$path"; #ECR
238             } #ECR
239              
240             #
241             # If path does not contain a slash, check for a subcomponent in the
242             # current component first.
243             #
244 0 0         if ($path !~ /\//) {
245             # Check my subcomponents.
246 0 0         if (my $subcomp = $current_comp->subcomps($path)) {
247 0           return $subcomp;
248             }
249             # If I am a subcomponent, also check my owner's subcomponents.
250             # This won't work when we go to multiply embedded subcomponents...
251 0 0 0       if ($current_comp->is_subcomp and my $subcomp = $current_comp->owner->subcomps($path)) {
252 0           return $subcomp;
253             }
254             }
255              
256             #
257             # Otherwise pass the canonicalized absolute path to interp->load.
258             #
259 0           $path = absolute_comp_path($path, $current_comp->dir_path);
260             #my $comp = $self->interp->load($path);
261 0           my $comp = $self->interp->load($path, $super); #ECR
262              
263             # ECR addition
264             # If no comp exists and pseudodhandlering is on
265             #
266 0 0 0       if (!$comp and $self->pseudodhandler_name)
267             {
268 0           my $pseudodhandler_arg;
269             # make any necessary adjustments to the comp_root
270             # grab the comp root and stash it
271 0           my @comp_root = $self->comp_root;
272 0           my @store_comp_root = @comp_root;
273             # check the list of excluded comp_roots
274 0           my @exclude_roots = $self->_pseudodhandler_exclude_comp_roots;
275 0           foreach my $exclude (@exclude_roots)
276             {
277 0           @comp_root = grep { $_->[0] !~ m/$exclude/ } @comp_root;
  0            
278             }
279             # check the list of excluded comp root paths
280 0           my @exclude_paths = $self->_pseudodhandler_exclude_paths;
281 0           foreach my $exclude (@exclude_paths)
282             {
283 0           @comp_root = grep { $_->[1] !~ m/$exclude/ } @comp_root;
  0            
284             }
285             # set the adjusted comp_root
286 0           $self->comp_root(\@comp_root);
287 0   0       while (($path) and (!$comp))
288             {
289 0           my $pseudoprefix = $path;
290 0           my $pseudodelimit = '-';
291 0           $pseudoprefix =~ s|/|$pseudodelimit|g;
292 0           $pseudoprefix =~ s|^$pseudodelimit(.*)|$1$pseudodelimit|;
293 0           my $check_path = $path.'/'.$pseudoprefix.$self->pseudodhandler_name;
294 0           $comp = $self->interp->load($check_path, $super);
295 0 0         unless ($comp)
296             {
297 0           $check_path = $path.'/'.$self->pseudodhandler_name;
298 0           $comp = $self->interp->load($check_path, $super);
299             }
300 0 0         if ($comp)
301             {
302 0           $pseudodhandler_arg =~ s|^/||;
303 0           $self->pseudodhandler_arg($pseudodhandler_arg);
304 0           last;
305             }
306 0           $path =~ s|(/[^/]+$)||;
307 0           $pseudodhandler_arg = $1.$pseudodhandler_arg;
308 0 0         last if ($path =~ m|=>$|);
309             }
310             # reset the adjusted comp_root
311 0           $self->comp_root(\@store_comp_root);
312             }
313             ## ECR addition ends
314              
315 0           return $comp;
316             }
317              
318             sub comp
319             {
320 0     0 1   my $self = shift;
321 0           my $original_pseudodhandler_arg = $self->pseudodhandler_arg;
322 0           $self->pseudodhandler_arg('');
323 0           my ($result, @results);
324 0 0         if (wantarray)
325             {
326 0           @results = $self->_comp(@_);
327             }
328             else
329             {
330 0           $result = $self->_comp(@_);
331             }
332 0           $self->pseudodhandler_arg($original_pseudodhandler_arg);
333 0 0         return wantarray ? @results : $result;
334             }
335              
336             #
337             # _comp copied from 1.37 for adjustment
338             #
339             sub _comp {
340 0     0     my $self = shift;
341              
342             # Get modifiers: optional hash reference passed in as first argument.
343             # Merge multiple hash references to simplify user and internal usage.
344             #
345 0           my %mods;
346 0           %mods = (%{shift()}, %mods) while ref($_[0]) eq 'HASH';
  0            
347              
348             # Get component path or object. If a path, load into object.
349             #
350 0           my $path;
351 0           my $comp = shift;
352 0 0         if (!ref($comp)) {
353 0 0         die "comp called without component - must pass a path or component object"
354             unless defined($comp);
355 0           $path = $comp;
356 0           my $error;
357 0 0 0       $comp = $self->fetch_comp($path, undef, \$error)
358             or error($error || "could not find component for path '$path'\n");
359             }
360              
361             # Increment depth and check for maximum recursion. Depth starts at 1.
362             #
363 0           my $depth = $self->depth;
364             error "$depth levels deep in component stack (infinite recursive call?)\n"
365 0 0         if $depth >= $self->{max_recurse};
366              
367             # Keep the same output buffer unless store modifier was passed. If we have
368             # a filter, put the filter buffer on the stack instead of the regular buffer.
369             #
370 0           my $filter_buffer = '';
371 0 0         my $top_buffer = defined($mods{store}) ? $mods{store} : $self->{top_stack}->[STACK_BUFFER];
372 0 0         my $stack_buffer = $comp->{has_filter} ? \$filter_buffer : $top_buffer;
373 0           $stack_buffer = \$filter_buffer; #ECR
374 0 0         my $flushable = exists $mods{flushable} ? $mods{flushable} : 1;
375              
376             # Add new stack frame and point dynamically scoped $self->{top_stack} at it.
377 0           push @{ $self->{stack} },
  0            
378             [ $comp, # STACK_COMP
379             \@_, # STACK_ARGS
380             $stack_buffer, # STACK_BUFFER
381             \%mods, # STACK_MODS
382             $path, # STACK_PATH
383             undef, # STACK_BASE_COMP
384             undef, # STACK_IN_CALL_SELF
385             $flushable, # STACK_BUFFER_IS_FLUSHABLE
386             ];
387 0           local $self->{top_stack} = $self->{stack}->[-1];
388              
389             # Run start_component hooks for each plugin.
390             #
391 0 0         if ($self->{has_plugins}) {
392 0           my $context = bless
393             [$self, $comp, \@_],
394             'HTML::Mason::Plugin::Context::StartComponent';
395              
396 0           foreach my $plugin_instance (@{$self->{plugin_instances}}) {
  0            
397 0           $plugin_instance->start_component_hook( $context );
398             }
399             }
400              
401             # Finally, call the component.
402             #
403 0           my $wantarray = wantarray;
404 0           my @result;
405            
406 0           eval {
407             # By putting an empty block here, we protect against stack
408             # corruption when a component calls next or last outside of a
409             # loop. See 05-request.t #28 for a test.
410             {
411 0 0         if ($wantarray) {
  0 0          
412 0           @result = $comp->run(@_);
413             } elsif (defined $wantarray) {
414 0           $result[0] = $comp->run(@_);
415             } else {
416 0           $comp->run(@_);
417             }
418             }
419             };
420 0           my $error = $@;
421              
422             # Run component's filter if there is one, and restore true top buffer
423             # (e.g. in case a plugin prints something).
424             #
425 0 0         if ($comp->{has_filter}) {
426             # We have to check $comp->filter because abort or error may
427             # occur before filter gets defined in component. In such cases
428             # there should be no output, but should look into this more.
429             #
430 0 0         if (defined($comp->filter)) {
431 0           $$top_buffer .= $comp->filter->($filter_buffer);
432             }
433             #$self->{top_stack}->[STACK_BUFFER] = $top_buffer; # -ECR
434             } else { #ECR
435             my $filter_newlines = $comp->{flags}->{filter_newlines} ||
436 0   0       $self->{interp}->{filter_newlines} || 'all'; #ECR
437 0 0 0       if ($filter_newlines and $filter_newlines ne 'none') { #ECR
438 0 0         my $lines_to_filter = $filter_newlines eq 'all' ? '' : '1'; #ECR
439 0           $filter_buffer =~ s/^\n{1,$lines_to_filter}//; #ECR
440 0           $filter_buffer =~ s/\n{1,$lines_to_filter}$//; #ECR
441             } #ECR
442 0           $$top_buffer .= $filter_buffer; #ECR
443             }
444 0           $self->{top_stack}->[STACK_BUFFER] = $top_buffer; #ECR
445              
446             # Run end_component hooks for each plugin, in reverse order.
447             #
448 0 0         if ($self->{has_plugins}) {
449 0           my $context = bless
450             [$self, $comp, \@_, $wantarray, \@result, \$error],
451             'HTML::Mason::Plugin::Context::EndComponent';
452            
453 0           foreach my $plugin_instance (@{$self->{plugin_instances_reverse}}) {
  0            
454 0           $plugin_instance->end_component_hook( $context );
455             }
456             }
457              
458             # This is very important in order to avoid memory leaks, since we
459             # stick the arguments on the stack. If we don't pop the stack,
460             # they don't get cleaned up until the component exits.
461 0           pop @{ $self->{stack} };
  0            
462              
463             # Repropagate error if one occurred, otherwise return result.
464 0 0         rethrow_exception $error if $error;
465 0 0         return $wantarray ? @result : $result[0];
466             }
467              
468             sub content
469             {
470 0     0 1   my $self = shift;
471 0           my $buffer = $self->SUPER::content;
472 0           $buffer =~ s/^\n+/\n/;
473 0           $buffer =~ s/\n+$/\n/;
474 0           return $buffer;
475             }
476              
477             #
478             # Call Request.pm's exec, then put comp_root back
479             # to what it was when the current request or subrequest was made
480             #
481             sub exec
482             {
483 0     0 1   my $self = shift;
484 0           $self->comp_root(@{$self->_base_comp_root});
  0            
485             #$self->_store_comp_root;
486 0           my $return_exec = $self->SUPER::exec(@_);
487 0           $self->comp_root(@{$self->_base_comp_root});
  0            
488 0           return $return_exec;
489             }
490              
491             #
492             # make alias to $interp->comp_root
493             #
494             sub comp_root
495             {
496 0     0 1   my $self = shift;
497              
498 0 0         unless (@_)
499             {
500 0           my $return_root = $self->interp->comp_root;
501 0 0         return (wantarray) ? @{$return_root} : $return_root;
  0            
502             }
503              
504 0           my @root = $self->_munge_root(@_);
505 0           my $return_root = $self->interp->comp_root(\@root);
506 0 0         return (wantarray) ? @{$return_root} : $return_root;
  0            
507             }
508              
509             sub _munge_root
510             {
511 0     0     my $self = shift;
512            
513 0           my @roots = @_;
514              
515 0           foreach my $root (@roots)
516             {
517 0 0         if (ref($root) eq 'ARRAY')
    0          
518             {
519 0           my @inner_root = @{$root};
  0            
520 0 0         if (scalar(@inner_root) == 2)
521             {
522 0 0         unless (ref($inner_root[0]) eq 'ARRAY')
523             {
524 0 0         next if (index($inner_root[0], '=>') == -1);
525             }
526             }
527 0           @roots = $self->_munge_root(@inner_root);
528             }
529             elsif (ref($root) eq 'HASH')
530             {
531 0           my @hasharray = map { $_, $root->{$_} } keys %{$root};
  0            
  0            
532 0           $root = \@hasharray;
533             }
534             else
535             {
536 0           my @strings = split('=>', $root);
537 0 0         $root = \@strings if (@strings);
538             }
539             }
540 0           return @roots;
541             }
542              
543             #
544             # add further comp_roots to the beginning of the comp_root array
545             #
546             sub prefix_comp_root
547             {
548 0     0 1   my $self = shift;
549 0           my @prefix = $self->_munge_root(@_);
550 0           my $foo = $self->comp_root;
551 0 0         if (ref($foo) ne 'ARRAY')
552             {
553 0           $foo = [['MAIN', $foo]];
554             }
555 0           unshift(@{$foo}, @prefix);
  0            
556 0           $self->comp_root($foo);
557 0           return;
558             }
559              
560              
561             #
562             # reverse the comp root - what it says on the can
563             #
564             sub _reverse_comp_root
565             {
566 0     0     my $self = shift;
567 0           my @comp_root_array = $self->comp_root();
568 0           @comp_root_array = reverse @comp_root_array;
569 0           $self->comp_root(\@comp_root_array);
570 0           return;
571             }
572              
573              
574             #
575             # Register - for when notes is not sufficent
576             #
577             sub register
578             {
579 0     0 0   my $self = shift;
580 0           my %params = @_;
581 0 0 0       return unless ($params{namespace} or $params{name});
582 0   0       my $namespace = $params{namespace} || 'default';
583 0   0       my $name = $params{name} || 'default';
584 0           my $content = $params{content};
585 0           my $contents = $params{contents};
586 0           my $marker = $params{marker};
587 0           my $marker_key = $params{marker_key};
588 0           my $priority = $params{priority};
589 0           my $remove = $params{remove};
590 0           my $clear = $params{clear};
591 0           my $clear_priority = $params{clear_priority};
592 0           my $unlock = $params{unlock};
593 0           my $lock = $params{lock};
594 0           my $allow_duplicates = $params{allow_duplicates};
595 0           my $overwrite = $params{overwrite};
596              
597             # unlock if required, spanner out if locked, lock if required
598             # NB. you can unlock, set the register and lock all in one
599 0 0         if ($unlock)
600             {
601 0           delete $self->{_REGISTER}{$namespace}{$name}{locked};
602             }
603 0 0         return if ($self->{_REGISTER}{$namespace}{$name}{locked});
604 0 0         if ($lock)
605             {
606 0           $self->{_REGISTER}{$namespace}{$name}{locked} = 1;
607             }
608              
609 0 0         if ($remove)
610             {
611 0 0         if ($self->{_REGISTER}{$namespace}{$name}{priority})
612             {
613 0           foreach my $key (sort keys %{$self->{_REGISTER}{$namespace}{$name}{priority}})
  0            
614             {
615 0 0 0       next if (defined($priority) and $priority != $key);
616 0           my @temp;
617 0           foreach my $bundle (@{$self->{_REGISTER}{$namespace}{$name}{priority}{$key}})
  0            
618             {
619 0 0         if ($bundle->{marker} =~ m|^$remove$|)
620             {
621 0           delete $self->{_REGISTER}{$namespace}{$name}{scoreboard}{$key}{$bundle->{marker}};
622             }
623             else
624             {
625 0           push(@temp, $bundle);
626             }
627             }
628 0           $self->{_REGISTER}{$namespace}{$name}{priority}{$key} = \@temp;
629             }
630             }
631             }
632              
633             # Here comes the get
634 0 0 0       unless (defined $content or $contents)
635             {
636 0           my @registered;
637 0 0         if ($self->{_REGISTER}{$namespace}{$name}{priority})
638             {
639 0           foreach my $key (sort keys %{$self->{_REGISTER}{$namespace}{$name}{priority}})
  0            
640             {
641 0 0 0       next if (defined($priority) and $priority != $key);
642 0           foreach my $bundle (@{$self->{_REGISTER}{$namespace}{$name}{priority}{$key}})
  0            
643             {
644 0           push(@registered, $bundle->{content});
645             }
646             }
647             }
648 0 0         if ($clear)
649             {
650 0           $self->{_REGISTER}{$namespace}{$name} = undef;
651             }
652 0 0         if (!wantarray) { return pop(@registered); }
  0            
653 0           return @registered;
654             }
655              
656 0 0         if ($clear)
657             {
658 0           $self->{_REGISTER}{$namespace}{$name} = undef;
659             }
660              
661              
662             # sanity check the priority level
663 0 0         $priority = 0.5 unless defined $priority;
664 0           $priority += 0;
665             # maybe this is unfairly restrictive, but it's good to have boundaries
666 0 0         $priority = 0 if ($priority < 0);
667 0 0         $priority = 1 if ($priority > 1);
668             # $marker prevents duplicate entries per priority level
669             # NB. if you want to add the same entry to different priorities, that's your bag
670 0 0         unless ($marker)
671             {
672 0 0         if ($marker_key)
673             {
674 0           $marker = $content->{$marker_key};
675             }
676             else
677             {
678 0 0 0       $marker = ref $content ? ($content->{marker} || $content->{content}) : $content;
679             }
680             }
681            
682 0 0         if ($clear_priority)
683             {
684 0           $self->{_REGISTER}{$namespace}{$name}{priority}{$priority} = [];
685 0           delete $self->{_REGISTER}{$namespace}{$name}{scoreboard}{$priority}{$marker};
686             }
687            
688 0 0         if ($contents)
689             {
690 0           my %new_params = %params;
691 0           delete $new_params{content};
692 0           delete $new_params{contents};
693 0           delete $new_params{clear};
694 0           delete $new_params{clear_priority};
695 0           foreach my $new_content (@{$contents})
  0            
696             {
697 0           $new_params{content} = $new_content;
698 0           ®ister(%new_params);
699             }
700 0           return;
701             }
702              
703 0 0 0       unless ($allow_duplicates and not $overwrite)
704             {
705 0 0         if ($self->{_REGISTER}{$namespace}{$name}{scoreboard}{$priority}{$marker})
706             {
707 0 0         return 'already registered' unless ($overwrite);
708 0           my @temp = grep { $_->{marker} ne $marker } @{$self->{_REGISTER}{$namespace}{$name}{priority}{$priority}};
  0            
  0            
709 0           $self->{_REGISTER}{$namespace}{$name}{priority}{$priority} = \@temp;
710             }
711             }
712            
713             # ensure a priority slot exists
714 0   0       $self->{_REGISTER}{$namespace}{$name}{priority}{$priority} ||= [];
715             # and make a note that this has been done
716 0           $self->{_REGISTER}{$namespace}{$name}{scoreboard}{$priority}{$marker} = 1;
717             # pump the parameters into the slot
718 0           push (@{$self->{_REGISTER}{$namespace}{$name}{priority}{$priority}}, {content=>$content, marker=>$marker});
  0            
719 0           return;
720             };
721              
722             #
723             # Register errors
724             #
725             sub register_error
726             {
727 0     0 0   my $self = shift;
728 0           return $self->_register_namespace('error', @_);
729             }
730             #
731             # Register warnings
732             #
733             sub register_warning
734             {
735 0     0 0   my $self = shift;
736 0           return $self->_register_namespace('warning', @_);
737             }
738             #
739             # Register info
740             #
741             sub register_info
742             {
743 0     0 0   my $self = shift;
744 0           return $self->_register_namespace('info', @_);
745             }
746             sub _register_namespace
747             {
748 0     0     my $self = shift;
749 0           my $namespace = shift;
750 0           my %params;
751             my $name;
752 0           my $content;
753              
754 0 0         if (scalar(@_)%2)
755             {
756 0           $name = shift;
757             }
758 0           %params = @_;
759 0 0         $params{name} = $name if defined($name);
760            
761 0 0         unless ($params{name})
762             {
763 0           $name = shift;
764 0 0         return unless ($name);
765 0 0         if (scalar(@_)%2)
766             {
767 0           $content = shift;
768             }
769 0           %params = @_;
770 0 0         $params{content} = $content if defined($content);
771 0 0         $params{name} = $name if defined($name);
772             }
773              
774 0           $params{namespace} = $namespace;
775 0           return $self->register(%params);
776             }
777              
778              
779             sub share_var
780             {
781 0     0 0   my $self = shift;
782 0           my $var_name = shift;
783 0           my $var_value = shift;
784 0           my $comp_path = $self->current_comp->path;
785 0           $comp_path =~ s/:.*//;
786 0 0         $self->notes->{_SHARED}->{$comp_path}->{$var_name} = $var_value if (defined($var_value));
787 0           return $self->notes->{_SHARED}->{$comp_path}->{$var_name};
788             }
789              
790             1;
791              
792              
793             __END__