line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Rose::Planter::Soil; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 NAME |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
Rose::Planter::Soil -- default base object class for classes created by Rose::Planter. |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 DESCRIPTION |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
This provides a few extra handy functions and |
10
|
|
|
|
|
|
|
defaults for manipulating Rose classes. |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
=head1 METHODS |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
=cut |
15
|
|
|
|
|
|
|
|
16
|
2
|
|
|
2
|
|
6529
|
use strict; |
|
2
|
|
|
|
|
5
|
|
|
2
|
|
|
|
|
51
|
|
17
|
2
|
|
|
2
|
|
11
|
use warnings; |
|
2
|
|
|
|
|
20
|
|
|
2
|
|
|
|
|
57
|
|
18
|
|
|
|
|
|
|
|
19
|
2
|
|
|
2
|
|
10
|
use Log::Log4perl qw/:easy/; |
|
2
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
14
|
|
20
|
2
|
|
|
2
|
|
1418
|
use base 'Rose::DB::Object'; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
168
|
|
21
|
2
|
|
|
2
|
|
11
|
use Rose::DB::Object::Helpers qw/:all/; |
|
2
|
|
|
|
|
3
|
|
|
2
|
|
|
|
|
37
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head2 as_hash |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
Like Rose::DB::Object::Helper::as_tree but with a few differences : |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
- parent keys in a child table are excluded. |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
- datetimes are returned in ISO 8601 format. |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
- the parameter skip_re can be given to skip columns matching a regex. |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
- only one-to-one and one-to-many relationships are traversed |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=cut |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub as_hash { |
38
|
3
|
|
|
3
|
1
|
17586
|
my $self = shift; |
39
|
3
|
|
|
|
|
53
|
my %args = @_; |
40
|
3
|
|
|
|
|
6
|
my $skip_re = $args{skip_re}; |
41
|
3
|
|
|
|
|
5
|
my $parent = $args{_parent}; |
42
|
3
|
|
|
|
|
5
|
my %parent_columns; |
43
|
|
|
|
|
|
|
|
44
|
3
|
100
|
|
|
|
12
|
if ($parent) { |
45
|
2
|
|
|
|
|
10
|
%parent_columns = reverse $parent->column_map; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
3
|
|
|
|
|
23
|
my %h; # to be returned. |
49
|
|
|
|
|
|
|
|
50
|
3
|
|
|
|
|
12
|
for my $col ( $self->meta->columns ) { |
51
|
8
|
100
|
|
|
|
100
|
next if $parent_columns{$col->name}; |
52
|
6
|
|
|
|
|
60
|
my $accessor = $col->accessor_method_name; |
53
|
6
|
|
|
|
|
193
|
my $value = scalar( $self->$accessor ); |
54
|
6
|
50
|
|
|
|
41
|
if (ref $value eq 'DateTime') { |
55
|
|
|
|
|
|
|
# timezone may be a DateTime::TimeZone::OffsetOnly |
56
|
|
|
|
|
|
|
# whose name is e.g. -0400. It needs to be -04:00 for iso 8601. |
57
|
0
|
|
|
|
|
0
|
my $offset = $value->time_zone->name; |
58
|
0
|
|
|
|
|
0
|
$value = $value->iso8601; |
59
|
0
|
0
|
|
|
|
0
|
if ($offset =~ /\d{4}/ ) { |
|
|
0
|
|
|
|
|
|
60
|
0
|
|
|
|
|
0
|
$offset=~ s/00$/:00/; |
61
|
0
|
|
|
|
|
0
|
$value .= $offset; |
62
|
|
|
|
|
|
|
} elsif ($offset =~ /^UTC|floating/) { |
63
|
|
|
|
|
|
|
# ok |
64
|
|
|
|
|
|
|
} else { |
65
|
|
|
|
|
|
|
# Could this happen with an explicitly set timezone? |
66
|
0
|
|
|
|
|
0
|
WARN "unrecognized timezone name : $offset"; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
} |
69
|
6
|
50
|
33
|
|
|
18
|
next if $skip_re && $accessor =~ /$skip_re/; |
70
|
6
|
|
|
|
|
17
|
$h{$accessor} = $value; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
3
|
|
|
|
|
12
|
for my $rel ($self->meta->relationships) { |
74
|
3
|
100
|
|
|
|
80
|
next unless $rel->object_has_related_objects($self); # undocumented API call |
75
|
1
|
|
|
|
|
51
|
my $name = $rel->name; |
76
|
1
|
50
|
|
|
|
9
|
die "cannot recurse" unless $self->can($name); |
77
|
1
|
50
|
|
|
|
6
|
if ($rel->type eq 'one to one') { |
|
|
50
|
|
|
|
|
|
78
|
0
|
|
|
|
|
0
|
$h{$name} = $self->$name->as_hash( _parent => $rel); |
79
|
|
|
|
|
|
|
} elsif ($rel->type eq 'one to many') { |
80
|
1
|
|
|
|
|
16
|
my @children = $self->$name; |
81
|
1
|
|
|
|
|
14
|
for my $child (@children) { |
82
|
2
|
50
|
|
|
|
15
|
die "cannot dump $name" unless $child->can('as_hash'); |
83
|
2
|
|
100
|
|
|
12
|
$h{$name} ||= []; |
84
|
2
|
|
|
|
|
2
|
push @{ $h{$name} }, $child->as_hash( _parent => $rel); |
|
2
|
|
|
|
|
13
|
|
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
} else { |
87
|
|
|
|
|
|
|
# warn "relationship type ".$rel->type." not implemented in as_hash"; |
88
|
|
|
|
|
|
|
# silently skip many-to-one relationships |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
3
|
|
|
|
|
59
|
return \%h; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=head2 nested_tables |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
Get or set a list of "nested table" associated with this |
98
|
|
|
|
|
|
|
class. These are tables which are always retrieved alongside |
99
|
|
|
|
|
|
|
this one. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=cut |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
our %NestedMap; |
104
|
|
|
|
|
|
|
sub nested_tables { |
105
|
|
|
|
|
|
|
# The Right way to do this is probably to provide our own base meta class, too. |
106
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
107
|
0
|
|
0
|
|
|
|
my $class = ref $self || $self; |
108
|
0
|
0
|
|
|
|
|
return $NestedMap{$class} unless @_ > 0; |
109
|
0
|
0
|
|
|
|
|
$NestedMap{$class} = ref($_[0]) ? shift : [ @_ ]; |
110
|
0
|
|
|
|
|
|
return $NestedMap{$class}; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
1; |
114
|
|
|
|
|
|
|
|