more metadata generalization and modification
[bse.git] / site / cgi-bin / modules / BSE / MetaOwnerBase.pm
1 package BSE::MetaOwnerBase;
2 use strict;
3 use Carp 'confess';
4
5 our $VERSION = "1.001";
6
7 =head1 NAME
8
9 BSE::MetaOwnerBase - mix-in for objects that have metadata.
10
11 =head1 SYNOPSIS
12
13   my $file = ...
14   my @meta = $file->metadata;
15   my @text = $file->text_metadata;
16   my $meta = $file->meta_by_name($name);
17   my @names = $file->metanames;
18   my @info = $file->metainfo;
19   my @config = $file->meta_config;
20
21 =head1 DESCRIPTION
22
23 Provides generic metadata support methods.  These can be called on any
24 L<BSE::TB::ArticleFile> object, and possibly other objects in the
25 future.
26
27 =head1 PUBLIC METHODS
28
29 These can be called from anywhere, including templates:
30
31 =over
32
33 =item metadata
34
35 Return all metadata for the object (as metadata objects).
36
37 =cut
38
39 sub metadata {
40   my ($self) = @_;
41
42   require BSE::TB::Metadata;
43   return  BSE::TB::Metadata->getBy
44     (
45      file_id => $self->id,
46      owner_type => $self->meta_owner_type,
47     );
48 }
49
50 =item metadata
51
52 Return all metadata for the object with a content type of
53 C<text/plain>.
54
55 =cut
56
57 sub text_metadata {
58   my ($self) = @_;
59
60   require BSE::TB::Metadata;
61   return  BSE::TB::Metadata->getBy
62     (
63      file_id => $self->id,
64      owner_type => $self->meta_owner_type,
65      content_type => "text/plain",
66     );
67 }
68
69 =item meta_by_name
70
71 Retrieve metadata with a specific name.
72
73 Returns nothing if there is no metadata of that name.
74
75 =cut
76
77 sub meta_by_name {
78   my ($self, $name) = @_;
79
80   require BSE::TB::Metadata;
81   my ($result) = BSE::TB::Metadata->getBy
82     (
83      file_id => $self->id,
84      owner_type => $self->meta_owner_type,
85      name => $name
86     )
87       or return;
88
89   return $result;
90 }
91
92 =item metanames
93
94 Returns the names of each metadatum defined for the file.
95
96 =cut
97
98 sub metanames {
99   my ($self) = @_;
100
101   require BSE::TB::Metadata;
102   return BSE::TB::Metadata->getColumnBy
103     (
104      "name",
105      [
106       [ file_id => $self->id ],
107       [ owner_type => $self->meta_owner_type ],
108      ],
109     );
110
111 }
112
113 =item metainfo
114
115 Returns all but the value for metadata defined for the file.
116
117 This is useful to avoid loading large objects if the metadata happens
118 to be file content.
119
120 =cut
121
122 sub metainfo {
123   my ($self) = @_;
124
125   require BSE::TB::Metadata;
126   my @cols = grep $_ ne "value", BSE::TB::MetaEntry->columns;
127   return BSE::TB::Metadata->getColumnsBy
128     (
129      \@cols,
130      [
131       [ file_id => $self->id ],
132       [ owner_type => $self->meta_owner_type ],
133      ],
134     );
135 }
136
137 =item meta_config
138
139 Returns configured metadata fields for this object.
140
141 =cut
142
143 sub meta_config {
144   my ($self, $cfg) = @_;
145
146   $cfg || BSE::Cfg->single;
147
148   require BSE::MetaMeta;
149   my @metafields;
150   my $prefix = $self->meta_meta_cfg_prefix;
151   my @keys = $cfg->orderCS($self->meta_meta_cfg_section);
152   for my $name (@keys) {
153     my %opts = ( name => $name );
154     my $section = "$prefix $name";
155     for my $key (BSE::MetaMeta->keys) {
156       my $value = $cfg->entry($section, $key);
157       if (defined $value) {
158         $opts{$key} = $value;
159       }
160     }
161     push @metafields, BSE::MetaMeta->new(%opts, cfg => $cfg);
162   }
163
164   return @metafields;
165
166 }
167
168 =back
169
170 =head1 RESTRICTED METHODS
171
172 These are not accessible from templates.
173
174 =item clear_metadata
175
176 Remove all metadata for this object.  Should be called when the object
177 is removed.
178
179 Restricted.
180
181 =cut
182
183 sub clear_metadata {
184   my ($self) = @_;
185
186   BSE::DB->run(bseClearArticleFileMetadata => $self->id, $self->meta_owner_type);
187 }
188
189 =item clear_app_metadata
190
191 Remove all application metadata for this object.
192
193 Restricted.
194
195 =cut
196
197 sub clear_app_metadata {
198   my ($self) = @_;
199
200   BSE::DB->run(bseClearArticleFileAppMetadata => $self->id, $self->meta_owner_type);
201 }
202
203 =item clear_sys_metadata
204
205 Remove all system metadata for this object.
206
207 Restricted.
208
209 =cut
210
211 sub clear_sys_metadata {
212   my ($self) = @_;
213
214   BSE::DB->run(bseClearArticleFileSysMetadata => $self->id, $self->meta_owner_type);
215 }
216
217 =item delete_meta_by_name
218
219 Remove a single piece of metadata from the object.
220
221 Restricted.
222
223 =cut
224
225 sub delete_meta_by_name {
226   my ($self, $name) = @_;
227
228 print STDERR "Delete ", $self->id, ",", $name, ",", $self->meta_owner_type, ")\n";
229   BSE::DB->run(bseDeleteArticleFileMetaByName => $self->id, $name, $self->meta_owner_type);
230 }
231
232 =item add_meta
233
234 Add metadata to the object.
235
236 Restricted.
237
238 =cut
239
240 sub add_meta {
241   my ($self, %opts) = @_;
242
243   require BSE::TB::Metadata;
244   return BSE::TB::Metadata->make
245       (
246        file_id => $self->id,
247        owner_type => $self->meta_owner_type,
248        %opts,
249       );
250 }
251
252 sub restricted_method {
253   my ($self, $name) = @_;
254
255   return $name =~ /^(?:clear_|delete_|add_)/;
256 }
257
258 1;
259
260 =back
261
262 =cut