File Coverage

blib/lib/Net/ICal/Property.pm
Criterion Covered Total %
statement 17 82 20.7
branch 1 28 3.5
condition n/a
subroutine 4 9 44.4
pod 3 3 100.0
total 25 122 20.4


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             # -*- Mode: perl -*-
3             #======================================================================
4             #
5             # This package is free software and is provided "as is" without
6             # express or implied warranty. It may be used, redistributed and/or
7             # modified under the same terms as perl itself. ( Either the Artistic
8             # License or the GPL. )
9             #
10             # $Id: Property.pm,v 1.16 2001/08/04 04:59:36 srl Exp $
11             #
12             # (C) COPYRIGHT 2000-2001, Reefknot developers.
13             #
14             # See the AUTHORS file included in the distribution for a full list.
15             #======================================================================
16              
17             # eek. 44 subclasses
18              
19             =head1 NAME
20              
21             Net::ICal::Property -- base class for ICalender properties
22              
23             =cut
24              
25             package Net::ICal::Property;
26 3     3   18 use strict;
  3         9  
  3         89  
27              
28 3     3   2430 use UNIVERSAL;
  3         25  
  3         15  
29 3     3   81 use base qw(Class::MethodMapper);
  3         3  
  3         3578  
30              
31             =head1 SYNOPSIS
32              
33             Creating a property from a ical string:
34             $p = Net::ICal::Property->new_from_ical ($str);
35              
36             print out an ical string
37             print $p->as_ical;
38              
39             =head1 DESCRIPTION
40              
41             This is the base class from which you derive specific ICal properties.
42              
43             =head1 CONSTRUCTORS
44              
45             =head2 new ($name, $map, %args)
46              
47             You never call this directly. Instead you call the new constructor for
48             a specific property type, which in turn calls this:
49              
50             $p = Net::ICal::Trigger (300);
51              
52             =begin testing
53              
54             TODO: {
55             local $TODO = "We need to write tests here";
56              
57             ok(0, 'write tests for new()');
58              
59             }
60             =end testing
61              
62             =cut
63              
64             sub new {
65 13     13 1 33 my ($classname, $name, $map, %args) = @_;
66              
67 13 50       39 if (not defined $map->{content}) {
68 0         0 warn "not a proper property\n";
69 0         0 return undef;
70             }
71              
72 13         70 $map->{name} = {
73             type => 'volatile',
74             doc => 'the ICalendar name of the property',
75             value => $name,
76             };
77              
78 13         51 my $self = new Class::MethodMapper;
79 13         116 bless $self, $classname;
80 13         80 $self->set_map (%$map);
81 13         332 $self->set (%args);
82              
83 13         70 return $self;
84             }
85              
86             =begin testing
87              
88             # TODO: write tests
89             TODO: {
90             local $TODO = "write tests here, please; patches welcome";
91             ok(0, 'write tests for _reclass_set()');
92             }
93             =end testing
94              
95             =cut
96             sub _reclass_set {
97 0     0     my ($self, $key, $val) = @_;
98              
99 0           my ($class) = $self =~ /^(.*?)=/g;
100              
101 0           foreach my $pclass (values %{$self->get_meta ('options', $key)}) {
  0            
102 0 0         if (UNIVERSAL::isa ($val, $pclass)) {
103 0           $self->{$key}->{value} = $val;
104 0           return;
105             }
106             }
107 0           warn "${class}->$key: '$val' is not a type of class. "
108             . "using 'undef' instead.\n";
109 0           $self->{$key}->{value} = undef;
110             }
111              
112             =head2 new_from_ical ($ical)
113              
114             Creates a new Net::ICal property from a string in ICal format
115              
116             =begin testing
117              
118             # TODO: write tests
119             TODO: {
120             local $TODO = 'write tests here please';
121             ok(0, 'write tests for new_from_ical()');
122             }
123             =end testing
124              
125             =cut
126              
127             sub new_from_ical {
128 0     0 1   my ($class, $ical) = @_;
129              
130 0           my ($prop) = $ical =~ /^(\w+)[;:]/g;
131 0 0         unless ($prop) {
132 0           warn "Not a valid ical stream\n";
133 0           return undef;
134             }
135 0           my $self = $class->_create;
136              
137             my $cb = sub {
138 0 0   0     return undef if $ical eq "";
139 0 0         if ($ical =~ /^;/) {
140             #FIXME: make this more robust (; in "" inside a field is possible
141             #BUG: 133739
142 0           $ical =~ s/;(.*?)\=(.*?)(;|$)/$3/;
143             #FIXME: make sure we definitely don't need anything but plain
144             # key/value
145 0           my ($name, $value) = ($1, $2);
146 0           $name =~ s/\W/_/g;
147 0           return (lc($name), $value);
148             } else {
149 0           $ical =~ s/^.*?([;:])/$1/;
150             # this too
151 0           $ical =~ s/:(.*?)$//;
152 0           my $value = $1;
153              
154             # Check if this is a property that can be one of several
155             # classes. determine what class with regexps
156 0 0         if ($self->get_meta ('domain', 'content')) {
157 0 0         if ($self->get_meta ('domain', 'content') eq 'reclass') {
158 0           my %rehash = %{$self->get_meta ('options', 'content')};
  0            
159 0           my $default = delete $rehash{'default'};
160 0           foreach my $re (keys %rehash) {
161 0 0         if ($value =~ /$re/) {
162 0           my $class = $rehash{$re};
163 0           eval "require $class";
164 0           my $param = $class->new ($value);
165 0           return ('content', $param);
166             }
167             }
168 0           eval "require $default";
169 0           my $param = $default->new ("$value");
170 0           return ('content', $param);
171             }
172             #FIXME: we may need to handle 'ref' and 'enum' domains too
173             } else {
174 0           return ('content', $value);
175             }
176             }
177 0           };
178 0           $self->restore ($cb);
179 0           return $self;
180             }
181              
182             =head1 METHODS
183              
184             =head2 name([$name])
185              
186             Get or set the name of the property. You're not supposed to actually
187             ever set this manually. It will be set by the new method of the
188             property type you are creating.
189              
190             =head2 as_ical
191              
192             returns an ICal string describing the property
193              
194             =begin testing
195              
196             # TODO: write tests
197             TODO: {
198             local $TODO = "write these tests";
199             ok(0, 'write tests for as_ical()');
200             }
201             =end testing
202              
203             =cut
204              
205             sub as_ical {
206 0     0 1   my ($self) = @_;
207 0           my $ical;
208              
209             my $cb = sub {
210 0     0     my ($self, $key, $value) = @_;
211 0           $key =~ s/_/-/g;
212 0           $key = uc ($key);
213              
214 0 0         return unless defined $value->{value};
215 0 0         if ($value->{domain} eq 'ref') {
216 0 0         if ($value->{options} eq 'ARRAY') {
    0          
217 0           foreach my $val (@{$value->{value}}) {
  0            
218 0 0         if (ref ($val)) {
219 0           $ical .= ";" . $key . "=" . $val->as_ical_value();
220             } else {
221 0           $ical .= ";" . $key . "=$val";
222             }
223             }
224             } elsif ($value->{options} eq 'HASH') {
225             # hash param (FIXME: will this ever be used?)
226             } else {
227             # assume it's a class
228 0           $ical .= ";" . $key . "=" . $value->{value}->as_ical_value;
229             }
230             } else {
231 0           $ical .= ";" . $key . "=" . $value->{value};
232             }
233 0           };
234              
235 0           $self->save ('parameter', $cb);
236              
237 0 0         if (ref ($self->content)) {
238 0           $ical .= ":" . $self->content->as_ical_value;
239             } else {
240 0           $ical .= ":" . $self->content;
241             }
242 0           return $ical;
243             }
244              
245             1;
246              
247             =head1 SEE ALSO
248              
249             L, L
250              
251             =cut