File Coverage

blib/lib/Synth/Config.pm
Criterion Covered Total %
statement 86 93 92.4
branch 14 26 53.8
condition n/a
subroutine 16 17 94.1
pod 9 10 90.0
total 125 146 85.6


line stmt bran cond sub pod time code
1             package Synth::Config;
2             our $AUTHORITY = 'cpan:GENE';
3              
4             # ABSTRACT: Synthesizer settings librarian
5              
6             our $VERSION = '0.0040';
7              
8 1     1   1251 use Moo;
  1         11701  
  1         5  
9 1     1   2029 use strictures 2;
  1         1663  
  1         41  
10 1     1   199 use Carp qw(croak);
  1         3  
  1         43  
11 1     1   500 use Mojo::JSON qw(from_json to_json);
  1         214158  
  1         71  
12 1     1   509 use Mojo::SQLite ();
  1         231583  
  1         49  
13 1     1   477 use namespace::clean;
  1         11976  
  1         6  
14              
15              
16             has model => (
17             is => 'rw',
18             );
19              
20              
21             has dbname => (
22             is => 'ro',
23             required => 1,
24             default => sub { 'synth-config.db' },
25             );
26              
27             has _sqlite => (is => 'lazy');
28              
29             sub _build__sqlite {
30 1     1   11 my ($self) = @_;
31 1         16 my $sqlite = Mojo::SQLite->new('sqlite:' . $self->dbname);
32 1         3147 return $sqlite->db;
33             }
34              
35              
36             has verbose => (
37             is => 'ro',
38             isa => sub { croak "$_[0] is not a boolean" unless $_[0] =~ /^[01]$/ },
39             default => sub { 0 },
40             );
41              
42              
43             sub BUILD {
44 1     1 0 13 my ($self, $args) = @_;
45 1 50       8 return unless $args->{model};
46             # sanitize the model name
47 1         5 (my $model = $args->{model}) =~ s/\W/_/g;
48 1         11 $self->model(lc $model);
49             # create the model table unless it's already there
50 1         19 $self->_sqlite->query(
51             'create table if not exists '
52             . $self->model
53             . ' (
54             id integer primary key autoincrement,
55             settings json not null,
56             name text not null
57             )'
58             );
59             }
60              
61              
62             sub make_setting {
63 3     3 1 28033 my ($self, %args) = @_;
64 3         10 my $id = delete $args{id};
65 3         10 my $name = delete $args{name};
66 3 50       32 croak 'No columns given' unless keys %args;
67 3 100       12 if ($id) {
    50          
68             my $result = $self->_sqlite->select(
69             $self->model,
70             ['settings'],
71             { id => $id },
72 1         26 )->expand(json => 'settings')->hash->{settings};
73 1         1886 for my $arg (keys %args) {
74 1 50       29 $args{$arg} = '' unless defined $args{$arg};
75             }
76 1         11 my $params = { %$result, %args };
77 1         49 $self->_sqlite->update(
78             $self->model,
79             { settings => to_json($params) },
80             { id => $id },
81             );
82             }
83             elsif ($name) {
84 2         53 $id = $self->_sqlite->insert(
85             $self->model,
86             {
87             name => $name,
88             settings => to_json(\%args),
89             },
90             )->last_insert_id;
91             }
92 3         7334 return $id;
93             }
94              
95              
96             sub recall_setting {
97 3     3 1 1802 my ($self, %args) = @_;
98 3         10 my $id = delete $args{id};
99 3 50       9 croak 'No id given' unless $id;
100 3         76 my $result = $self->_sqlite->select(
101             $self->model,
102             ['name', 'settings'],
103             { id => $id },
104             )->expand(json => 'settings')->hash;
105 3         6133 my $setting = $result->{settings};
106 3         83 $setting->{name} = $result->{name};
107 3         13 return $setting;
108             }
109              
110              
111             sub search_settings {
112 5     5 1 5811 my ($self, %args) = @_;
113 5         13 my $name = delete $args{name};
114 5         15 my @where;
115 5 100       34 push @where, "name = '$name'" if $name;
116 5         16 for my $arg (keys %args) {
117 2 50       7 next unless $args{$arg};
118 2         6 $args{$arg} =~ s/'/''/g; # escape the single-quote
119 2         8 push @where, q/json_extract(settings, '$./ . $arg . q/') = / . "'$args{$arg}'";
120             }
121 5 50       14 return [] unless @where;
122 5         29 my $sql = q/select id,name,settings,json_extract(settings, '$.group') as mygroup, json_extract(settings, '$.parameter') as parameter from /
123             . $self->model
124             . ' where ' . join(' and ', @where)
125             . ' order by name,mygroup,parameter';
126 5 50       144 print "Search SQL: $sql\n" if $self->verbose;
127 5         150 my $results = $self->_sqlite->query($sql);
128 5         1244 my @settings;
129 5         20 while (my $next = $results->hash) {
130 5         259 push @settings, { $next->{id} => from_json($next->{settings}) };
131             # add the setting name to the settings data so we can use it in the templates
132 5         1383 $settings[-1]->{ $next->{id} }{name} = $next->{name};
133             }
134 5         145 return \@settings;
135             }
136              
137              
138             sub recall_all {
139 2     2 1 1091 my ($self) = @_;
140 2         10 my $sql = q/select id,name,settings,json_extract(settings, '$.group') as mygroup from /
141             . $self->model
142             . ' order by name,mygroup';
143 2         54 my $results = $self->_sqlite->query($sql);
144 1         248 my @settings;
145 1         6 while (my $next = $results->hash) {
146 2         83 push @settings, { $next->{id} => from_json($next->{settings}) };
147             # add the setting name to the settings data
148 2         546 $settings[-1]->{ $next->{id} }{name} = $next->{name};
149             }
150 1         29 return \@settings;
151             }
152              
153              
154             sub recall_models {
155 0     0 1 0 my ($self) = @_;
156 0         0 my @models;
157 0         0 my $results = $self->_sqlite->query(
158             "select name from sqlite_schema where type='table' order by name"
159             );
160 0         0 while (my $next = $results->array) {
161 0 0       0 next if $next->[0] =~ /^sqlite/;
162 0         0 push @models, $next->[0];
163             }
164 0         0 return \@models;
165             }
166              
167              
168             sub recall_names {
169 1     1 1 970 my ($self) = @_;
170 1         3 my @names;
171 1         26 my $results = $self->_sqlite->query(
172             'select distinct name from ' . $self->model
173             );
174 1         349 while (my $next = $results->array) {
175 1         52 push @names, $next->[0];
176             }
177 1         17 return \@names;
178             }
179              
180              
181             sub remove_setting {
182 1     1 1 1399 my ($self, %args) = @_;
183 1         3 my $id = delete $args{id};
184 1 50       5 croak 'No id given' unless $id;
185 1         27 $self->_sqlite->delete(
186             $self->model,
187             { id => $id }
188             );
189             }
190              
191              
192             sub remove_settings {
193 1     1 1 966 my ($self, %args) = @_;
194 1         3 my $name = delete $args{name};
195 1 50       6 croak 'No name given' unless $name;
196 1         27 $self->_sqlite->delete(
197             $self->model,
198             { name => $name }
199             );
200             }
201              
202              
203             sub remove_model {
204 1     1 1 2622 my ($self) = @_;
205 1         27 $self->_sqlite->query(
206             'drop table ' . $self->model
207             );
208             }
209              
210             1;
211              
212             __END__