File Coverage

blib/lib/Mojolicious/Plugin/Surveil.pm
Criterion Covered Total %
statement 27 34 79.4
branch 4 6 66.6
condition 5 7 71.4
subroutine 7 8 87.5
pod 1 1 100.0
total 44 56 78.5


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::Surveil;
2              
3             =head1 NAME
4              
5             Mojolicious::Plugin::Surveil - Surveil user actions
6              
7             =head1 VERSION
8              
9             0.01
10              
11             =head1 DESCRIPTION
12              
13             L is a plugin which allow you to see every
14             event a user trigger on your web page. It is meant as a debug tool for
15             seeing events, even if the browser does not have a JavaScript console.
16              
17             Note: With great power, comes great responsibility.
18              
19             CAVEAT: The JavaScript that is injected require WebSocket in the browser to
20             run. The surveil events are attached to the "body" element, so any other event
21             that prevent events from bubbling will not emit this to the WebSocket
22             resource.
23              
24             =head1 SYNOPSIS
25              
26             Use default logging:
27              
28             use Mojolicious::Lite;
29             plugin "surveil";
30             app->start;
31              
32             Use custom route:
33              
34             use Mojolicious::Lite;
35             use Mojo::JSON "j";
36              
37             plugin surveil => { path => "/surveil" };
38              
39             websocket "/surveil" => sub {
40             my $c = shift;
41              
42             $c->on(message => sub {
43             my ($c, $action) = @_;
44             warn "User event: $action\n";
45             });
46             };
47              
48             app->start;
49              
50             =head1 CONFIG
51              
52             This plugin can take the following config params:
53              
54             =over 4
55              
56             =item * enable_param = "..."
57              
58             Used to specify a query parameter to be part of the URL to enable surveil.
59              
60             Default is not to require any query parameter.
61              
62             =item * events = [...]
63              
64             The events that should be reported back over the WebSocket.
65              
66             Defaults to click, touchstart, touchcancel and touchend.
67             (The default list is EXPERIMENTAL).
68              
69             =item * path = "...";
70              
71             The path to the WebSocket route.
72              
73             Defaults to C. Emitting the "path" parameter will
74             also add a default WebSocket route which simply log with "debug" the action
75             that was taken. (The format of the logging is EXPERIMENTAL)
76              
77             =back
78              
79             =cut
80              
81 2     2   1938 use Mojo::Base 'Mojolicious::Plugin';
  2         5  
  2         16  
82 2     2   427 use Mojo::JSON 'j';
  2         4  
  2         1706  
83              
84             our $VERSION = '0.01';
85              
86             =head1 METHODS
87              
88             =head2 register
89              
90             $self->register($app, $config);
91              
92             Used to add an "after_render" hook into the application which adds a
93             JavaScript to every HTML document.
94              
95             =cut
96              
97             sub register {
98 2     2 1 97 my ($self, $app, $config) = @_;
99              
100 2   50     22 $config->{events} ||= [qw( click touchstart touchcancel touchend )];
101              
102 2         3 push @{ $app->renderer->classes }, __PACKAGE__;
  2         71  
103 2         100 $self->_after_render_hook($app, $config);
104 2 50       104 $self->_default_route($app, $config) unless $config->{path};
105             }
106              
107             sub _after_render_hook {
108 2     2   5 my ($self, $app, $config) = @_;
109 2         6 my $enable_param = $config->{enable_param};
110              
111             $app->hook(after_render => sub {
112 3     3   136827 my ($c, $output, $format) = @_;
113 3 50       27 return if $format ne 'html';
114 3 100 100     29 return if $enable_param and !$c->param($enable_param);
115 2         678 my $js = $self->_javascript_code($c, $config);
116 2         18047 $$output =~ s!!$js!;
117 2         22 });
118             }
119              
120             sub _default_route {
121 2     2   6 my ($self, $app, $config) = @_;
122              
123 2         6 $config->{path} = '/mojolicious/plugin/surveil';
124              
125             $app->routes->websocket($config->{path})->to(cb => sub {
126 0     0   0 my $c = shift;
127 0         0 $c->inactivity_timeout(60);
128             $c->on(message => sub {
129 0         0 my $action = j $_[1];
130 0         0 my ($type, $target) = (delete $action->{type}, delete $action->{target});
131 0         0 $app->log->debug(qq(Event "$type" on "$target" @{[j $action]}));
  0         0  
132 0         0 });
133 2         58 });
134             }
135              
136             sub _javascript_code {
137 2     2   6 my ($self, $c, $config) = @_;
138 2   50     13 my $scheme = $c->req->url->to_abs->scheme || 'http';
139              
140 2         9781 $scheme =~ s!^http!ws!;
141              
142 2         19 $c->render_to_string(
143             template => 'mojolicious/plugin/surveil',
144             events => j($config->{events}),
145             surveil_url => $c->url_for($config->{path})->to_abs->scheme($scheme),
146             );
147             }
148              
149             =head1 COPYRIGHT AND LICENSE
150              
151             Copyright (C) 2014, Jan Henning Thorsen
152              
153             This program is free software, you can redistribute it and/or modify it under
154             the terms of the Artistic License version 2.0.
155              
156             =head1 AUTHOR
157              
158             Jan Henning Thorsen - C
159              
160             =cut
161              
162             1;
163             __DATA__