| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Mojolicious::Plugin::Tables::Model; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 3 |  |  | 3 |  | 20 | use strict; | 
|  | 3 |  |  |  |  | 7 |  | 
|  | 3 |  |  |  |  | 94 |  | 
| 4 | 3 |  |  | 3 |  | 15 | use warnings; | 
|  | 3 |  |  |  |  | 9 |  | 
|  | 3 |  |  |  |  | 85 |  | 
| 5 |  |  |  |  |  |  |  | 
| 6 | 3 |  |  | 3 |  | 17 | use base qw/DBIx::Class::Schema/; | 
|  | 3 |  |  |  |  | 8 |  | 
|  | 3 |  |  |  |  | 2059 |  | 
| 7 | 3 |  |  | 3 |  | 179608 | use DBIx::Class::Schema::Loader::Dynamic; | 
|  | 3 |  |  |  |  | 541443 |  | 
|  | 3 |  |  |  |  | 3994 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | __PACKAGE__->mk_group_accessors(inherited => qw/log connect_info model/); | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | sub setup { | 
| 12 | 3 |  |  | 3 | 0 | 10 | my ($class, $conf) = @_; | 
| 13 | 3 | 50 |  |  |  | 13 | if (my $connect_info = $conf->{connect_info}) { | 
| 14 | 3 |  |  |  |  | 65 | $class->connect_info($connect_info) | 
| 15 |  |  |  |  |  |  | } else { | 
| 16 | 0 | 0 |  |  |  | 0 | die "Provide connect_info either as a config value or an override" | 
| 17 |  |  |  |  |  |  | unless $class->connect_info | 
| 18 |  |  |  |  |  |  | } | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | # to return a schema object-ref here say 'connect' instead of 'connection'. | 
| 21 | 3 |  |  |  |  | 48 | my $schema = $class->connection(@{$class->connect_info}); | 
|  | 3 |  |  |  |  | 53 |  | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | DBIx::Class::Schema::Loader::Dynamic->new( | 
| 24 |  |  |  |  |  |  | left_base_classes   => $class->row_base, | 
| 25 |  |  |  |  |  |  | rel_name_map        => $class->rel_name_map, | 
| 26 | 27 |  |  | 27 |  | 779811 | custom_column_info  => sub { $class->custom_column_info(@_) }, | 
| 27 |  |  |  |  |  |  | naming              => 'v8', | 
| 28 |  |  |  |  |  |  | use_namespaces      => 0, | 
| 29 |  |  |  |  |  |  | schema              => $schema, | 
| 30 | 3 | 50 |  |  |  | 278113 | %{$conf->{loader_opts}||{}}, | 
|  | 3 |  |  |  |  | 41 |  | 
| 31 |  |  |  |  |  |  | )->load; | 
| 32 |  |  |  |  |  |  |  | 
| 33 | 3 |  |  |  |  | 123822 | $schema->model($schema->_model); | 
| 34 |  |  |  |  |  |  |  | 
| 35 | 3 |  |  |  |  | 102 | return $schema; | 
| 36 |  |  |  |  |  |  | } | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 3 |  |  | 3 | 0 | 32 | sub row_base { 'Mojolicious::Plugin::Tables::Model::Row' } | 
| 39 |  |  |  |  |  |  |  | 
| 40 | 48 |  |  | 48 | 1 | 200 | sub glossary { +{ id => 'Identifier' } } | 
| 41 |  |  |  |  |  |  |  | 
| 42 | 27 |  |  | 27 | 1 | 175 | sub input_attrs { +{ name => { size=>80 } } } | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | sub make_label { | 
| 45 | 48 |  |  | 48 | 0 | 94 | my $self = shift; | 
| 46 | 48 |  |  |  |  | 103 | my $name = shift; | 
| 47 | 48 |  |  |  |  | 162 | my @label = split '_', $name; | 
| 48 | 48 |  |  |  |  | 126 | for (@label) { | 
| 49 | 48 | 50 |  |  |  | 133 | $_ = $self->glossary->{$_}, next if $self->glossary->{$_}; | 
| 50 | 48 |  |  |  |  | 162 | $_ = ucfirst | 
| 51 |  |  |  |  |  |  | } | 
| 52 | 48 |  |  |  |  | 228 | join(' ', @label) | 
| 53 |  |  |  |  |  |  | } | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | sub custom_column_info { | 
| 56 | 27 |  |  | 27 | 0 | 74 | my ($class, $table, $column, $column_info) = @_; | 
| 57 | 27 |  |  |  |  | 74 | my $info = { label => $class->make_label($column) }; | 
| 58 | 27 |  |  |  |  | 56 | my $attrs1; | 
| 59 | 27 |  |  |  |  | 67 | for ($column_info->{data_type}) { | 
| 60 | 27 | 100 |  |  |  | 221 | $attrs1 = | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
| 61 |  |  |  |  |  |  | /numeric|integer/ ? {type=>'number'} : | 
| 62 |  |  |  |  |  |  | /timestamp/       ? {type=>'datetime-local'} : | 
| 63 |  |  |  |  |  |  | /date|time/       ? {type=>$_} : | 
| 64 |  |  |  |  |  |  | {}; | 
| 65 |  |  |  |  |  |  | } | 
| 66 | 27 |  | 100 |  |  | 80 | my $attrs2 = $class->input_attrs->{$column} || {}; | 
| 67 | 27 | 100 | 100 |  |  | 220 | $info->{input_attrs} = {%$attrs1, %$attrs2} if keys(%$attrs1) || keys(%$attrs2); | 
| 68 | 27 |  |  |  |  | 109 | $info | 
| 69 |  |  |  |  |  |  | }; | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 3 |  |  | 3 | 1 | 20 | sub rel_name_map { +{} } | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | sub _model { | 
| 74 | 3 |  |  | 3 |  | 539 | my $schema  = shift; | 
| 75 |  |  |  |  |  |  |  | 
| 76 | 3 |  |  |  |  | 12 | my @tablist = (); | 
| 77 | 3 |  |  |  |  | 12 | my %bytable = (); | 
| 78 |  |  |  |  |  |  | #my $log     = $schema->log; | 
| 79 |  |  |  |  |  |  | #$log->debug("$schema is building its model"); | 
| 80 | 3 |  |  |  |  | 27 | for my $source (sort $schema->sources) { | 
| 81 | 9 |  |  |  |  | 195 | my $s = $schema->source($source); | 
| 82 | 9 |  |  |  |  | 443 | my @has_a; | 
| 83 |  |  |  |  |  |  | my %has_many; | 
| 84 | 9 |  |  |  |  | 48 | for my $rel ($s->relationships) { | 
| 85 | 12 |  |  |  |  | 98 | my $info   = $s->relationship_info($rel); | 
| 86 | 12 |  |  |  |  | 182 | my $ftable = $info->{class}->table; | 
| 87 | 12 |  |  |  |  | 523 | my $attrs  = $info->{attrs}; | 
| 88 | 12 |  |  |  |  | 26 | my $card   = $attrs->{accessor}; | 
| 89 | 12 | 100 |  |  |  | 56 | if ($card eq 'single') { | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 90 | 6 |  |  |  |  | 16 | my $fks = $attrs->{fk_columns}; | 
| 91 | 6 |  |  |  |  | 24 | my @fks = keys %$fks; | 
| 92 | 6 | 50 |  |  |  | 37 | push @has_a, { fkey=>$fks[0], parent=>$rel, label=>$schema->make_label($rel), ptable=>$ftable } | 
| 93 |  |  |  |  |  |  | if @fks == 1 | 
| 94 |  |  |  |  |  |  | } elsif ($card eq 'filter') { | 
| 95 | 0 |  |  |  |  | 0 | my @ffkeys = keys %{$info->{cond}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 96 | 0 | 0 |  |  |  | 0 | if (@ffkeys == 1) { | 
| 97 | 0 |  |  |  |  | 0 | (my $cfkey = $ffkeys[0]) =~ s/^foreign\.//; | 
| 98 | 0 |  |  |  |  | 0 | push @has_a, { fkey=>$cfkey, parent=>$rel, label=>$schema->make_label($rel), ptable=>$ftable } | 
| 99 |  |  |  |  |  |  | } else { | 
| 100 | 0 |  |  |  |  | 0 | warn __PACKAGE__." model: $source: $rel: multi-barrelled M-1 keys not supported\n" | 
| 101 |  |  |  |  |  |  | } | 
| 102 |  |  |  |  |  |  | } elsif ($card eq 'multi') { | 
| 103 | 6 |  |  |  |  | 16 | my $fsource_name = $info->{source}; | 
| 104 | 6 |  |  |  |  | 22 | my $fsource      = $schema->source($fsource_name); | 
| 105 | 6 |  |  |  |  | 456 | my $fpkey        = join(',', $fsource->primary_columns); | 
| 106 | 6 |  |  |  |  | 51 | my @ffkeys       = keys %{$info->{cond}}; | 
|  | 6 |  |  |  |  | 26 |  | 
| 107 | 6 | 50 |  |  |  | 28 | if (@ffkeys == 1) { | 
| 108 | 6 |  |  |  |  | 30 | (my $cfkey = $ffkeys[0]) =~ s/^foreign\.//; | 
| 109 | 6 |  |  |  |  | 104 | $has_many{$rel} = {ctable=>$ftable, cpkey=>$fpkey, cfkey=>$cfkey, label=>$schema->make_label($rel)}; | 
| 110 |  |  |  |  |  |  | } else { | 
| 111 | 0 |  |  |  |  | 0 | warn __PACKAGE__." model: $source: $rel: multi-barrelled 1-M keys not supported\n" | 
| 112 |  |  |  |  |  |  | } | 
| 113 |  |  |  |  |  |  | } else { | 
| 114 | 0 |  |  |  |  | 0 | warn __PACKAGE__." model: $source: $rel: strange cardinality: $card\n"; | 
| 115 |  |  |  |  |  |  | } | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  | my %bycolumn = map { | 
| 118 | 9 |  |  |  |  | 58 | my %info = %{$s->column_info($_)}; | 
|  | 27 |  |  |  |  | 121 |  | 
|  | 27 |  |  |  |  | 73 |  | 
| 119 | 27 |  |  |  |  | 376 | delete $info{name}; | 
| 120 | 27 |  | 100 |  |  | 178 | /^_/ && delete $info{$_} for keys %info; | 
| 121 | 27 |  |  |  |  | 97 | ( $_ => \%info ) | 
| 122 |  |  |  |  |  |  | } $s->columns; | 
| 123 | 9 |  |  |  |  | 30 | for (@has_a) { | 
| 124 | 6 |  |  |  |  | 16 | my $fkey = $_->{fkey}; | 
| 125 | 6 |  |  |  |  | 15 | my $parent = delete $_->{parent}; | 
| 126 | 6 | 50 |  |  |  | 28 | $bycolumn{$fkey}->{parent} = $parent if $bycolumn{$fkey}; | 
| 127 | 6 |  |  |  |  | 17 | $bycolumn{$parent} = $_; # gets {fkey=>, label=>, ptable=>,} | 
| 128 |  |  |  |  |  |  | } | 
| 129 | 9 |  |  |  |  | 31 | my $pkeys   = [$s->primary_columns]; | 
| 130 | 9 |  |  |  |  | 89 | my $pknum   = 0; | 
| 131 | 9 |  |  |  |  | 24 | for (@$pkeys) { | 
| 132 | 9 |  |  |  |  | 27 | $bycolumn{$_}{is_primary_key} = ++$pknum | 
| 133 |  |  |  |  |  |  | } | 
| 134 | 9 | 100 |  |  |  | 30 | my @columns = map { $_, $bycolumn{$_}{parent}? ($bycolumn{$_}{parent}): () } | 
|  | 27 |  |  |  |  | 151 |  | 
| 135 |  |  |  |  |  |  | $s->columns; | 
| 136 | 9 |  |  |  |  | 38 | my $label   = $schema->make_label($s->name); | 
| 137 | 9 |  |  |  |  | 50 | my $tabinfo = { | 
| 138 |  |  |  |  |  |  | source   => $source, | 
| 139 |  |  |  |  |  |  | columns  => \@columns, | 
| 140 |  |  |  |  |  |  | bycolumn => \%bycolumn, | 
| 141 |  |  |  |  |  |  | has_many => \%has_many, | 
| 142 |  |  |  |  |  |  | label    => $label, | 
| 143 |  |  |  |  |  |  | pkeys    => $pkeys, | 
| 144 |  |  |  |  |  |  | }; | 
| 145 | 9 |  |  |  |  | 33 | push @tablist, $s->name; | 
| 146 | 9 |  |  |  |  | 44 | $bytable{$s->name} = $tabinfo; | 
| 147 |  |  |  |  |  |  | } | 
| 148 | 3 |  |  |  |  | 105 | return {schema=>$schema, tablist=>\@tablist, bytable=>\%bytable}; | 
| 149 |  |  |  |  |  |  | } | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | 1; | 
| 152 |  |  |  |  |  |  | __END__ |