File Coverage

blib/lib/Mojolicious/Plugin/DBViewer.pm
Criterion Covered Total %
statement 61 66 92.4
branch 13 16 81.2
condition 13 14 92.8
subroutine 9 9 100.0
pod 1 1 100.0
total 97 106 91.5


line stmt bran cond sub pod time code
1 3     3   353861 use 5.008001;
  3         9  
2             package Mojolicious::Plugin::DBViewer;
3 3     3   376 use Mojo::Base 'Mojolicious::Plugin';
  3         7179  
  3         18  
4              
5 3     3   969 use Cwd 'abs_path';
  3         6  
  3         137  
6 3     3   580 use DBIx::Custom;
  3         49990  
  3         37  
7 3     3   1613 use Validator::Custom;
  3         38583  
  3         19  
8 3     3   93 use Carp 'croak';
  3         5  
  3         2191  
9              
10             our $VERSION = '0.29';
11              
12             has 'command';
13             has 'prefix';
14             has 'validator';
15             has 'dbi';
16              
17 8     8   24 sub _driver { lc shift->dbi->dbh->{Driver}->{Name} }
18              
19             sub register {
20 8     8 1 92053 my ($self, $app, $conf) = @_;
21            
22             # Prefix
23 8         19 my $prefix = $conf->{prefix};
24 8 100       32 $prefix = 'dbviewer' unless defined $prefix;
25            
26             # Slash and prefix
27 8 100       32 my $sprefix = $prefix eq '' ? $prefix : "/$prefix";
28            
29             # Default charset
30 8   100     46 my $charset = $conf->{charset} || 'UTF-8';
31            
32             # DBI
33             my $dbi = DBIx::Custom->connect(
34             dsn => $conf->{dsn},
35             user => $conf->{user},
36             password => $conf->{password},
37             option => $conf->{option} || {},
38 8   50     102 connector => 1
39             );
40 8         22228 $self->dbi($dbi);
41 8 100       79 if (ref $conf->{connector_get} eq 'SCALAR') {
42 7         116 ${$conf->{connector_get}} = $dbi->connector;
  7         36  
43             }
44            
45             # Validator
46 8         69 my $validator = Validator::Custom->new;
47             $validator->register_constraint(
48             safety_name => sub {
49 313     313   122366 my $name = shift;
50 313 100 100     1954 return ($name || '') =~ /^[a-zA-Z0-9_\.]+$/ ? 1 : 0;
51             }
52 8         1167 );
53 8         313 $self->validator($validator);
54            
55             # Commaned and namespace
56 8         43 my $driver = $self->_driver;
57 8         868 my $command;
58             my $namespace;
59 8 50       34 if ($driver eq 'mysql') {
    50          
60 0         0 require Mojolicious::Plugin::DBViewer::MySQL::Command;
61 0         0 $command = Mojolicious::Plugin::DBViewer::MySQL::Command->new(dbi => $dbi);
62 0         0 $namespace = 'Mojolicious::Plugin::DBViewer::MySQL';
63             }
64             elsif ($driver eq 'sqlite') {
65 8         853 require Mojolicious::Plugin::DBViewer::SQLite::Command;
66 8         92 $command = Mojolicious::Plugin::DBViewer::SQLite::Command->new(dbi => $dbi);
67 8         55 $namespace = 'Mojolicious::Plugin::DBViewer::SQLite';
68             }
69 0         0 else { croak "Mojolicious::Plugin::DBViewer don't support $driver" }
70 8         33 $self->command($command);
71            
72             # Add public and template path
73 8         75 my $class = __PACKAGE__;
74 8         50 $class =~ s/::/\//g;
75 8         13 $class .= '.pm';
76 8         795 my $base_path = abs_path $INC{$class};
77 8         38 $base_path =~ s/\.pm$//;
78 8         15 push @{$app->static->paths}, "$base_path/public";
  8         39  
79 8         98 push @{$app->renderer->paths}, "$base_path/templates";
  8         32  
80            
81             # Routes
82 8         73 my $r = $conf->{route};
83 8 100       41 $r = $app->routes unless defined $r;
84 8         40 $self->prefix($prefix);
85             {
86             # Config
87 8   100     38 my $site_title = $conf->{site_title} || 'DBViewer';
  8         38  
88 8   100     27 my $footer_text = $conf->{footer_text} || 'Mojolicious::Plugin::DBViewer';
89             my $footer_link = $conf->{footer_link}
90 8   100     32 || 'http://search.cpan.org/dist/Mojolicious-Plugin-DBViewer'
91             . '/lib/Mojolicious/Plugin/DBViewer.pm';
92              
93             # Utilities
94 8         45 my $utilities = [
95             {path => 'create-tables', title => 'Create tables'},
96             {path => 'primary-keys', title => 'Primary keys'},
97             {path => 'null-allowed-columns', title => 'Null allowed columns'},
98             ];
99 8 50       26 if ($driver eq 'mysql') {
100 0         0 push @$utilities,
101             {path => 'database-engines', title => 'Database engines'},
102             {path => 'charsets', title => 'Charsets'}
103             }
104 8         22 push @$utilities,
105             {path => 'select-statements', title => 'Selects statements'};
106            
107             # Route Config
108             my $r = $r->route("/$prefix")->to(
109             'dbviewer#',
110             namespace => $namespace,
111             plugin => $self,
112             sprefix => $sprefix,
113             site_title => $site_title,
114             driver => $driver,
115             dbviewer => $self,
116             charset => $charset,
117             footer_text => $footer_text,
118             footer_link => $footer_link,
119             utilities => $utilities,
120             join => $conf->{join} || {}
121 8   100     67 );
122            
123             # Auto Route
124 8         1735 $app->plugin('AutoRoute', route => $r, top_dir => 'dbviewer/auto');
125             }
126             }
127              
128             1;
129              
130             =head1 NAME
131              
132             Mojolicious::Plugin::DBViewer - Mojolicious plugin to display database information on browser
133              
134             =head1 SYNOPSYS
135              
136             # Mojolicious::Lite
137             plugin(
138             'DBViewer',
139             dsn => "dbi:mysql:database=bookshop",
140             user => 'ken',
141             password => '!LFKD%$&'
142             );
143              
144             # Mojolicious
145             $app->plugin(
146             'DBViewer',
147             dsn => "dbi:mysql:database=bookshop",
148             user => 'ken',
149             password => '!LFKD%$&'
150             );
151            
152             # Access
153             http://localhost:3000/dbviewer
154            
155             # Prefix change (http://localhost:3000/dbviewer2)
156             plugin 'DBViewer', dsn => $dsn, prefix => 'dbviewer2';
157              
158             # Route
159             my $bridge = $app->route->under(sub {...});
160             plugin 'DBViewer', dsn => $dsn, route => $bridge;
161              
162             =head1 DESCRIPTION
163              
164             L is L plugin
165             to display Database information on your browser.
166              
167             L have the following features.
168              
169             =over 4
170              
171             =item *
172              
173             Support C and C
174              
175             =item *
176              
177             Display all table names
178              
179             =item *
180              
181             Display C
182              
183             =item *
184              
185             Execute simple select statement
186              
187             =item *
188              
189             Display C, C, C
190             and C in all tables.
191              
192             =back
193              
194             =head1 OPTIONS
195              
196             =head2 connector_get
197              
198             connector_get => \$connector
199              
200             Get L object internally used.
201            
202             # Get database handle
203             my $connector;
204             plugin('DBViewer', ..., connector_get => \$connector);
205             my $dbh = $connector->dbh;
206              
207             =head2 charset
208              
209             charset => 'euc-jp'
210              
211             Database charset, default is C.
212              
213             =head2 dsn
214              
215             dsn => "dbi:SQLite:dbname=proj"
216              
217             Datasource name.
218              
219              
220             =head2 password
221              
222             password => 'secret';
223              
224             Database password.
225              
226             =head2 prefix
227              
228             prefix => 'dbviewer2'
229              
230             Application base path, default to C.
231             You can access DB viewer by the following path.
232              
233             http://somehost.com/dbviewer2
234              
235             =head2 footer_text
236              
237             footer_text => 'Web DB Viewer'
238              
239             Footer text.
240              
241             =head2 footer_link
242              
243             footer_link => 'https://github.com/yuki-kimoto/webdbviewer'
244              
245             Footer link
246              
247             =head2 join
248              
249             join => {
250             book => [
251             'left join author on book.author_id = author.id',
252             'left join title on book.title_id = title.id'
253             ]
254             }
255              
256             Join clause. If you set join clause, you can use join mode in select page.
257              
258             =head2 option
259              
260             option => $option
261            
262             DBI option (L connect method's fourth argument).
263              
264             =head2 route
265              
266             route => $route
267              
268             Router for bridge, default to C<$app->routes>.
269              
270             my $bridge = $r->under(sub {...});
271             plugin 'DBViewer', dsn => $dsn, route => $bridge;
272              
273             =head2 user
274              
275             user => 'kimoto'
276              
277             =head2 site_title
278              
279             site_title => 'Your DB Viewer';
280              
281             Site title.
282              
283             Database user.
284              
285             =head1 BACKWARDS COMPATIBILITY POLICY
286              
287             If a feature is DEPRECATED, you can know it by DEPRECATED warnings.
288             DEPRECATED feature is removed after C,
289             but if at least one person use the feature and tell me that thing
290             I extend one year each time he tell me it.
291              
292             DEPRECATION warnings can be suppressed
293             by C
294             environment variable.
295              
296             EXPERIMENTAL features will be changed without warnings.
297              
298             =head1 COPYRIGHT & LICENSE
299              
300             Copyright 2013 Yuki Kimoto, all rights reserved.
301              
302             This program is free software; you can redistribute it and/or modify it
303             under the same terms as Perl itself.
304              
305             =cut