File Coverage

blib/lib/Mixin/ExtraFields/Driver.pm
Criterion Covered Total %
statement 34 34 100.0
branch 4 4 100.0
condition n/a
subroutine 12 12 100.0
pod 6 6 100.0
total 56 56 100.0


line stmt bran cond sub pod time code
1              
2 4     4   80532 use strict;
  4         20  
  4         118  
3 4     4   20 use warnings;
  4         8  
  4         157  
4              
5             package Mixin::ExtraFields::Driver 0.140003;
6             # ABSTRACT: a backend for extra field storage
7              
8 4     4   22 use Carp ();
  4         8  
  4         65  
9 4     4   546 use Sub::Install ();
  4         1933  
  4         384  
10              
11             #pod =head1 SYNOPSIS
12             #pod
13             #pod This is really not something you'd use on your own, it's just used by
14             #pod Mixin::ExtraFields, but if you insist...
15             #pod
16             #pod my $driver = Mixin::ExtraFields::Driver::Phlogiston->from_args(\%arg);
17             #pod
18             #pod $driver->set($obj, $obj_id, flammable => "very!");
19             #pod
20             #pod =head1 DESCRIPTION
21             #pod
22             #pod Mixin::ExtraFields::Driver is a base class for drivers used by
23             #pod Mixin::ExtraFields -- hence the name. A driver is expected to store and
24             #pod retrieve data keyed to an object and a name or key. It can store this in any
25             #pod way it likes, and does not need to guarantee persistence across processes.
26             #pod
27             #pod =head1 SUBCLASSING
28             #pod
29             #pod All drivers must implement the four methods listed below. The base class has
30             #pod implementations of these methods which will die noisily (C-ing) when
31             #pod called.
32             #pod
33             #pod Almost all methods are passed the same data as their first two arguments:
34             #pod C<$object>, the object for which the driver is to find or alter data, and
35             #pod C<$id>, that object's unique id. While this may be slighly redundant, it keeps
36             #pod the id-finding call in one place.
37             #pod
38             #pod =head2 from_args
39             #pod
40             #pod my $driver = Mixin::ExtraFields::Driver::Subclass->from_args(\%arg);
41             #pod
42             #pod This method must return a driver object appropriate to the given args. It is
43             #pod not called C because it need not return a new object for each call to it.
44             #pod Returning identical objects for identical configurations may be safe for some
45             #pod driver implementations, and it is expressly allowed.
46             #pod
47             #pod The arguments passed to this method are those given as the C option to
48             #pod the C import group in Mixin::ExtraFields, less the C option.
49             #pod
50             #pod =head2 get_all_detailed_extra
51             #pod
52             #pod my %extra = $driver->get_all_detailed_extra($object, $id);
53             #pod
54             #pod This method must return all available information about all existing extra
55             #pod fields for the given object. It must be returned as a list of name/value
56             #pod pairs. The values must be references to hashes. Each hash must have an entry
57             #pod for the key C giving the value for that name.
58             #pod
59             #pod =head2 set_extra
60             #pod
61             #pod $driver->set_extra($object, $id, $name, $value);
62             #pod
63             #pod This method must set the named extra to the given value.
64             #pod
65             #pod =head2 delete_extra
66             #pod
67             #pod $driver->delete_extra($object, $id, $name);
68             #pod
69             #pod This method must delete the named extra, causing it to cease to exist.
70             #pod
71             #pod =cut
72              
73             BEGIN {
74 4     4   16 for my $name (qw(from_args get_all_detailed_extra set_extra delete_extra)) {
75             Sub::Install::install_sub({
76             as => $name,
77 4     4   3269 code => sub { Carp::confess "method $name called but not implemented!" },
78 16         755 });
79             }
80             }
81              
82             #pod =head1 OPTIMIZING
83             #pod
84             #pod The methods below can all be implemented in terms of those above. If they are
85             #pod not provided by the subclass, basic implementations exist. These
86             #pod implementations may be less efficient than implementations crafted for the
87             #pod specifics of the storage engine behind the driver, so authors of driver
88             #pod subclasses should consider implementing these methods.
89             #pod
90             #pod =head2 get_all_extra
91             #pod
92             #pod my %extra = $driver->get_all_extra($object, $id);
93             #pod
94             #pod This method behaves like C, above, but provides the
95             #pod entry's value, not a detailed hashref, as the value for each entry.
96             #pod
97             #pod =cut
98              
99             sub get_all_extra {
100 2     2 1 7 my ($self, $object, $id) = @_;
101            
102 2         6 my %extra = $self->get_all_detailed_extra($object, $id);
103 2         22 my @simple = map { $_ => $extra{$_}{value} } keys %extra;
  1         9  
104             }
105              
106             #pod =head2 get_extra
107             #pod
108             #pod =head2 get_detailed_extra
109             #pod
110             #pod my $value = $driver->get_extra($object, $id, $name);
111             #pod
112             #pod my $hash = $driver->get_detailed_extra($object, $id, $name);
113             #pod
114             #pod These methods return a single value requested by name, either as the value
115             #pod itself or a detailed hashref describing it.
116             #pod
117             #pod =cut
118              
119             sub get_extra {
120 3     3 1 10 my ($self, $object, $id, $name) = @_;
121            
122 3         9 my $extra = $self->get_detailed_extra($object, $id, $name);
123 3 100       17 return $extra ? $extra->{value} : ();
124             }
125              
126             sub get_detailed_extra {
127 4     4 1 10 my ($self, $object, $id, $name) = @_;
128              
129 4         14 my %extra = $self->get_all_detailed_extra($object, $id);
130 4 100       77 return exists $extra{$name} ? $extra{$name} : ();
131             }
132              
133             #pod =head2 get_all_extra_names
134             #pod
135             #pod my @names = $driver->get_all_extra_names($object, $id);
136             #pod
137             #pod This method returns the names of all existing extras for the given object.
138             #pod
139             #pod =cut
140              
141             sub get_all_extra_names {
142 3     3 1 10 my ($self, $object, $id) = @_;
143 3         13 my %extra = $self->get_all_detailed_extra($object, $id);
144 3         42 return keys %extra;
145             }
146              
147             #pod =head2 exists_extra
148             #pod
149             #pod if ($driver->exists_extra($object, $id, $name)) { ... }
150             #pod
151             #pod This method returns true if an entry exists for the given name and false
152             #pod otherwise.
153             #pod
154             #pod =cut
155              
156             sub exists_extra {
157 4     4 1 10 my ($self, $object, $id, $name) = @_;
158 4         14 my %extra = $self->get_all_detailed_extra($object, $id);
159              
160 4         59 return exists $extra{ $name };
161             }
162              
163             #pod =head2 delete_all_extra
164             #pod
165             #pod $driver->delete_all_extra($object, $id);
166             #pod
167             #pod This method deletes all extras for the object, as per the C
168             #pod method.
169             #pod
170             #pod =cut
171              
172             sub delete_all_extra {
173 1     1 1 3 my ($self, $object, $id) = @_;
174              
175 1         4 for my $name ($self->get_all_extra_names($object, $id)) {
176 1         5 $self->delete_extra($object, $id, $name);
177             }
178             }
179              
180             1;
181              
182             __END__