use warnings; use strict; package Jifty::Mason::Halo; use base qw/HTML::Mason::Plugin/; use Time::HiRes (); Jifty->handle->log_sql_statements(1); =head1 NAME Jifty::Mason::Halo - Class for drawing "halos" around page components =head1 DESCRIPTION =cut =head2 start_component_hook CONTEXT_OBJECT Whenever we start to render a component, check to see if we can draw a halo around the component. Either way, record halo metadata. =cut sub start_component_hook { my $self = shift; my $context = shift; return if ($context->comp->path && $context->comp->path eq "/__jifty/halo"); Jifty->handler->stash->{ '_halo_index_stack' } ||= []; my $DEPTH = Jifty->handler->stash->{'_halo_depth'} || 0; my $STACK = Jifty->handler->stash->{'_halo_stack'} ||= []; my $INDEX_STACK = Jifty->handler->stash->{'_halo_index_stack'}; my $halo_base = Jifty->web->serial; Jifty->handler->stash->{'_halo_depth'} = ++$DEPTH; if ($STACK->[-1]) { push @{$STACK->[-1]->{sql_statements}}, Jifty->handle->sql_statement_log; Jifty->handle->clear_sql_statement_log; } push @$STACK, { id => $halo_base, args => [map { eval { defined $_ and fileno( $_ ) } ? "*GLOB*" : $_} @{$context->args}], start_time => Time::HiRes::time(), path => $context->comp->path || '', subcomponent => ( $context->comp->is_subcomp() ? 1:0), name => $context->comp->name || '(Unamed component)', proscribed => ($self->_unrendered_component($context) ? 1 :0 ), depth => $DEPTH }; push @$INDEX_STACK, $#{$STACK}; return if $self->_unrendered_component($context); $context->request->out(qq{
}); } =head2 end_component_hook CONTEXT_OBJECT When we're done rendering a component, record how long it took and close off the halo C if we have one. =cut sub end_component_hook { my $self = shift; my $context = shift; return if ($context->comp->path && $context->comp->path =~ "^/__jifty/halo"); my $STACK = Jifty->handler->stash->{'_halo_stack'}; my $INDEX_STACK = Jifty->handler->stash->{'_halo_index_stack'}; my $DEPTH = Jifty->handler->stash->{'_halo_depth'}; my $FRAME_ID = pop @$INDEX_STACK; my $frame = $STACK->[$FRAME_ID]; $frame->{'render_time'} = int((Time::HiRes::time - $frame->{'start_time'}) * 1000)/1000; push @{$frame->{sql_statements}}, Jifty->handle->sql_statement_log; Jifty->handle->clear_sql_statement_log; Jifty->handler->stash->{'_halo_depth'} = $DEPTH-1 ; # If return if $self->_unrendered_component($context); # print out the div with our halo magic actions. # if we didn't render a beginning of the span, don't render an end unless ( $frame->{'proscribed'} ) { my $comp_name = $frame->{'path'}; $context->request->out('
'); $context->request->out( Jifty->web->link( label => _( 'Edit %1', $comp_name ), class => 'inline_edit', onclick => [ { element => "#halo-" . $frame->{id}, replace_with => '/__jifty/edit_inline/mason_component/'.$comp_name } ] ) ) if 0 and ( $frame->{'path'} and $frame->{'path'} !~ /^\/?__jifty/ ); } } =head2 _unrendered_component CONTEXT Returns true if we're not currently inside the "Body" section of the webpage OR the current component is a subcomponent. (Rendering halos for subcomponents being too "heavy") =cut sub _unrendered_component { my $self = shift; my $context = shift; if ( $context->comp->is_subcomp() or not Jifty->handler->stash->{'in_body'}) { return 1; } else { return undef; } } =head2 render_component_tree Once we're just about to finish rendering our HTML page (just before the C<> tag, we should call render_component_tree to output all the halo data and metadata. =cut sub render_component_tree { my $self = shift; my @stack = @{ Jifty->handler->stash->{'_halo_stack'} }; for (@stack) { $_->{'render_time'} = int((Time::HiRes::time - $_->{'start_time'}) * 1000)/1000 unless defined $_->{'render_time'}; } Jifty->web->mason->comp("/__jifty/halo", stack => \@stack ); } 1;