File Coverage

Poll.pm
Criterion Covered Total %
statement 30 163 18.4
branch 0 48 0.0
condition 0 24 0.0
subroutine 10 29 34.4
pod n/a
total 40 264 15.1


line stmt bran cond sub pod time code
1             package WWW::Poll;
2              
3 1     1   818 use strict;
  1         2  
  1         38  
4 1     1   6 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         2  
  1         77  
5 1     1   5 use Carp;
  1         5  
  1         188  
6              
7             require Exporter;
8             require AutoLoader;
9              
10             @ISA = qw(Exporter AutoLoader);
11             # Items to export into callers namespace by default. Note: do not export
12             # names by default without a very good reason. Use EXPORT_OK instead.
13             # Do not simply export all your public functions/methods/constants.
14             @EXPORT = qw(
15            
16             );
17             $VERSION = '0.01';
18              
19              
20             # Preloaded methods go here.
21              
22             my $deBug=1;
23              
24             # define constant variables
25 1     1   5 use constant QID => 'qid.dat';
  1         2  
  1         120  
26 1     1   6 use constant QUEST => 'questions.dat';
  1         2  
  1         43  
27 1     1   5 use constant ANS => '_ans.dat';
  1         2  
  1         48  
28 1     1   5 use constant VOTES => '_poll.dat';
  1         2  
  1         53  
29 1     1   5 use constant MAXWIDTH => '300';
  1         8  
  1         42  
30             # make a constant for fonts & the bar image location
31 1     1   5 use constant FONT => '';
  1         2  
  1         117  
32             my $imagepath = $ENV{SCRIPT_NAME}; # same as calling script
33             $imagepath =~ s|^(.*/).*?$|$1|;
34 1     1   5 use constant IMAGE => $imagepath.'bar.jpg';
  1         3  
  1         4437  
35             undef $imagepath;
36              
37             # new initializes with latest poll
38             sub new {
39 0     0     my $proto = shift;
40 0   0       my $class = ref($proto) || $proto;
41 0           my $self = {};
42 0           $self->{POLL_ID} = undef;
43 0           $self->{POLL_PATH} = undef;
44 0           $self->{POLL_QUESTION} = undef;
45 0           $self->{POLL_ANSWERS} = ();
46 0           $self->{POLL_VOTES} = ();
47 0           $self->{POLL_LIST} = ();
48 0           $self->{DATE} = ();
49 0           bless ($self, $class);
50 0           return $self;
51             }
52              
53             #------ BEGIN poll object methods ------#
54              
55             sub id {
56 0     0     my $self = shift;
57 0 0         if (@_) { $self->{POLL_ID} = shift; }
  0            
58 0 0         if ( !$self->{POLL_ID} ) { $self->_get_qid; }
  0            
59 0           return $self->{POLL_ID};
60             }
61              
62             sub question {
63 0     0     my $self = shift;
64 0 0         if (@_) { $self->{POLL_QUESTION} = shift; }
  0            
65 0 0         if ( !$self->{POLL_QUESTION} ) { $self->_get_question; }
  0            
66 0           return $self->{POLL_QUESTION};
67             }
68              
69             sub answers {
70 0     0     my $self = shift;
71 0 0         if (@_) { %{ $self->{POLL_ANSWERS} } = @_; }
  0            
  0            
72 0 0         if ( !$self->{POLL_ANSWERS} ) { $self->_get_answers; }
  0            
73 0           return $self->{POLL_ANSWERS};
74             #return %{ $self->{POLL_ANSWERS} };
75             }
76              
77             sub votes {
78 0     0     my $self = shift;
79 0 0         if (@_) { %{ $self->{POLL_VOTES} } = @_; }
  0            
  0            
80 0 0         if ( !$self->{POLL_VOTES} ) { $self->_get_votes; }
  0            
81 0           return $self->{POLL_VOTES};
82             #return %{ $self->{POLL_VOTES} };
83             }
84              
85             sub path {
86 0     0     my $self = shift;
87 0 0         if (@_) { $self->{POLL_PATH} = shift; }
  0            
88 0           return $self->{POLL_PATH};
89             }
90              
91             sub list {
92 0     0     my $self = shift;
93 0 0         if (!$self->{POLL_LIST}) { $self->_get_question("all"); }
  0            
94 0           return %{ $self->{POLL_LIST} };
  0            
95             }
96              
97             sub date {
98 0     0     my $self = shift;
99 0 0         if (@_) { $self->{POLL_DATE} = shift; }
  0            
100 0 0         if (!$self->{POLL_DATE}) { $self->{POLL_DATE} = &_create_date; }
  0            
101 0           return $self->{POLL_DATE};
102             }
103              
104             #------ END poll object methods ------#
105              
106             #-------------------------------------------#
107              
108             #------ BEGIN public methods ------#
109              
110             # read poll returning poll id
111             sub get {
112 0     0     my $self = shift;
113             # $self->get($n) will return a specified poll
114             # or the latest poll if no params or valid files
115 0 0 0       if (@_ && ($_[0] =~ /\d/)) { $self->{POLL_ID} = shift; } else { $self->id; }
  0            
  0            
116             # retrieve poll question
117 0           $self->_get_question;
118             # retrieve poll answers file
119 0           $self->_get_answers;
120             # retrieve poll results file
121 0           $self->_get_votes;
122             # send them html
123             #return $self->_create_poll_html;
124 0           return $self->id;
125             }
126              
127             # read poll returning html
128             sub get_html {
129 0     0     my $self = shift;
130             # $self->get($n) will return a specified poll
131             # or the latest poll if no params or valid files
132 0 0 0       if (@_ && ($_[0] =~ /\d/)) { $self->{POLL_ID} = shift; } else { $self->id; }
  0            
  0            
133             # retrieve poll question
134 0           $self->_get_question;
135             # retrieve poll answers file
136 0           $self->_get_answers;
137             # retrieve poll results file
138 0           $self->_get_votes;
139             # send them html
140 0           return $self->_create_poll_html;
141             }
142              
143             # vote on a poll
144             sub vote {
145 0     0     my $self = shift;
146 0           my $vote = shift;
147            
148             # get poll content
149 0           $self->_get_votes;
150             # increment proper poll result
151 0           foreach ($self->rkeys) {
152 0 0         ( $_ == $vote ) ? ++$self->votes->{$_} : next ;
153             }
154             # write new poll back to file
155 0           $self->_write_votes;
156 0           undef $vote; # cleanliness is next to godliness
157 0           return 1;
158             }
159              
160             # seed answers for poll creation
161             sub add_answers {
162 0     0     my $self = shift;
163 0           my $i=1;
164 0           foreach (@_) {
165 0 0         next unless (/\w/);
166 0           $self->{POLL_ANSWERS}->{$i} = $_;
167 0           $i++;
168             }
169             }
170              
171             # create a new poll
172             sub create {
173 0     0     my $self = shift;
174             # check to be sure all params have been set
175 0           $self->_check_params;
176             # clean out tabs & newlines from data
177 0           $self->_clean_input;
178             # get last qid number
179 0           $self->_get_qid;
180             # increment poll id
181 0           $self->id($self->id+1);
182             # append the question to the question file
183 0           $self->_insert_question;
184             # create answers file for new poll
185 0           $self->_write_answers;
186             # seed the votes object
187 0           foreach ($self->akeys) { $self->{POLL_VOTES}->{$_} = '1'; }
  0            
188             # create votes file for new poll
189 0           $self->_write_votes;
190             # update the qid file
191 0           $self->_set_qid;
192             # return some output html
193 0           return $self->_create_admin_html;
194             }
195              
196             # return keys for votes
197             sub rkeys {
198 0     0     my $self = shift;
199 0 0         if ( !$self->{POLL_VOTES} ) { $self->_get_votes; }
  0            
200 0           return (keys %{ $self->votes });
  0            
201             }
202              
203             # return keys for answers
204             sub akeys {
205 0     0     my $self = shift;
206 0 0         if ( !$self->{POLL_ANSWERS} ) { $self->_get_answers; }
  0            
207 0           return (keys %{ $self->answers });
  0            
208             }
209              
210             #------ END public methods ------#
211              
212             #-------------------------------------------#
213              
214             #------ BEGIN private methods ------#
215             # All private methods are accessing the hashes (except $self->id) directly
216             # rather than the proper object methods (just for the hell of it)
217              
218             #- BEGIN reading from files METHODS
219             sub _get_qid {
220 0     0     my $self = shift;
221             # get qid of latest poll
222 0 0 0       open(QFILE,$self->{POLL_PATH}."/".QID) || croak "$!, Perhaps \$poll->path() wasn't set?\n".$self->{POLL_PATH}."/".QID if $deBug;
223 0           my @qid = ;
224 0           close(QFILE);
225 0           $self->{POLL_ID} = $qid[0];
226             }
227              
228             sub _get_question {
229 0     0     my $self = shift;
230             # open & retrieve question
231 0 0 0       open(QFILE,$self->{POLL_PATH}."/".QUEST) || croak "$!, Perhaps \$poll->path() wasn't set?\n".$self->{POLL_PATH}."/".QUEST if $deBug;
232 0 0 0       if ( @_ && $_[0] eq 'all') {
233 0           while() {
234 0           /^(\d+)\t.*?\t(.*?)$/o;
235 0           $self->{POLL_LIST}->{$1}=$2;
236             }
237             } else {
238 0           while() {
239 0 0         if (/^$self->{POLL_ID}\t(.*?)\t(.*?)$/o) {
240 0           $self->{POLL_QUESTION}=($2);
241 0           $self->date($1);
242             }
243             }
244             }
245 0           close(QFILE);
246             }
247              
248             sub _get_answers {
249 0     0     my $self = shift;
250 0 0 0       open(AFILE,$self->{POLL_PATH}."/".$self->id.ANS) || croak "$!, Perhaps \$poll->path() wasn't set?\n".$self->{POLL_PATH}."/".$self->id.ANS if $deBug;
251 0           while () {
252 0           /^(\d+)\t(.*?)$/o;
253 0           $self->{POLL_ANSWERS}->{$1}=$2
254             }
255 0           close(AFILE);
256             }
257              
258             sub _get_votes {
259 0     0     my $self = shift;
260             # open & retrieve poll results file
261 0 0 0       open(PFILE,$self->{POLL_PATH}."/".$self->id.VOTES) || croak "$!, Perhaps \$poll->path() wasn't set?\n".$self->{POLL_PATH}."/".$self->id.VOTES if $deBug;
262 0           while () {
263 0           /^(\d+)\t(\d+)$/o;
264 0           $self->{POLL_VOTES}->{$1}=$2;
265             }
266 0           close(PFILE);
267             }
268              
269             sub _create_poll_html {
270             my $self = shift;
271             my ($sum,@votes);
272            
273             foreach (keys %{$self->{POLL_VOTES}}) {
274             push @votes, $self->{POLL_VOTES}->{$_};
275             $sum += $self->{POLL_VOTES}->{$_};
276             }
277            
278             # get highest vote
279             my @maxvotes = sort { $b<=>$a } @votes;
280             my $maxvote = $maxvotes[0];
281             undef (@maxvotes,@votes);
282            
283             if ( $maxvote<1 ) { $maxvote=1; }
284             #my $factor = MAXWIDTH/(MAXWIDTH-$maxvote);
285             #croak $factor;
286            
287             my $format_date = $self->{POLL_DATE};
288             $format_date =~ s|(\d{4})(\d{2})(\d{2})|$2/$3/$1|;
289             my $html = "
290             "; ";
291             $html .= "
292            
293             ".FONT."".$self->{POLL_QUESTION}." 
294             ( question posted ".$format_date." - ".$sum." votes total )
295             foreach ( sort keys %{$self->{POLL_VOTES}} ) {
296             my $vote = ( $self->{POLL_VOTES}->{$_}<1 ) ? 1 : $self->{POLL_VOTES}->{$_} ;
297             if ($sum<1 ) { $sum=1; }
298             $html .= "
299            

300            
301             ".FONT.$self->{POLL_ANSWERS}->{$_}."
302            
303            
304              ".int(($vote/$sum)*100)."%  - ".$vote." votes
305             ";
306             }
307             $html .= "
308            
";
309             return $html;
310             }
311              
312             sub _create_admin_html {
313             # format some html to display to admin
314             my $self = shift;
315             my $html = "
316             "; ";
317            
".FONT."".$self->{POLL_QUESTION}."
318             foreach ( keys %{$self->{POLL_ANSWERS}} ) {
319             $html .= "
320            
".FONT."Answer ".$_.":".FONT.$self->{POLL_ANSWERS}->{$_}."
321             }
322             $html .= qq|\n
\n|;
323             return $html;
324             }
325             #- END reading from files METHODS
326              
327             #- BEGIN writing to files METHODS
328             sub _set_qid {
329             my $self = shift;
330             # get qid of latest poll
331             open(QFILE,">".$self->{POLL_PATH}."/".QID) || croak "$!, Perhaps \$poll->path() wasn't set?\n".$self->{POLL_PATH}.QID if $deBug;
332             print QFILE $self->id;
333             close(QFILE);
334             }
335              
336             sub _insert_question {
337             my $self = shift;
338             # insert question & date(YYYYMMDD) into file
339             open(QFILE,">>".$self->{POLL_PATH}."/".QUEST) || croak "$!" if $deBug;
340             print QFILE $self->id."\t".$self->date."\t".$self->{POLL_QUESTION}."\n";
341             close(QFILE);
342             }
343              
344             sub _write_answers {
345             my $self = shift;
346             open(AFILE,">".$self->{POLL_PATH}."/".$self->id.ANS) || croak "$!" if $deBug;
347             foreach ( keys %{$self->{POLL_ANSWERS}} ) {
348             print AFILE $_ ."\t".$self->{POLL_ANSWERS}->{$_}."\n";
349             }
350             close(AFILE);
351             return 1;
352             }
353              
354             sub _write_votes {
355             my $self = shift;
356             open(PFILE,">".$self->{POLL_PATH}."/".$self->id.VOTES) || croak "$!" if $deBug;
357             foreach ( keys %{$self->{POLL_VOTES}} ) {
358             print PFILE $_ ."\t".$self->{POLL_VOTES}->{$_}."\n";
359             }
360             close(PFILE);
361             return 1;
362             }
363             #- END writing to files METHODS
364              
365             #- BEGIN miscellany METHODS
366             sub _chmod_files {
367             my $self = shift;
368             chmod 0666, $self->{POLL_PATH}."/".$self->id.VOTES,$self->{POLL_PATH}."/".$self->id.ANS;
369             return 1;
370             }
371              
372             sub _check_params {
373             my $self = shift;
374             if ( scalar((keys %{$self->{POLL_ANSWERS}}))<1 ) { die "$! Answers weren't set"; }
375             if ( $self->{POLL_QUESTION} !~ /\w/ ) { die "$! Question wasn't set"; }
376             }
377              
378             sub _clean_input {
379             my $self = shift;
380             $self->{POLL_QUESTION} =~ s/[\t\r\n]/ /g;
381             foreach ( keys %{ $self->{POLL_ANSWERS} } ) {
382             $self->{POLL_ANSWERS}->{$_} =~ s/[\t\r\n]/ /g;
383             }
384             }
385              
386             sub _create_date {
387             my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
388             $mon = '0'.($mon+1) if ($mon<10);
389             $mday = '0'.$mday if ($mday<10);
390             return (($year+1900).$mon.$mday);
391             }
392             #- END miscellany METHODS
393              
394             # uncomment this if mod_perl complains in the error log
395             #sub DESTROY { }
396              
397             #------ END private methods ------#
398              
399             #-------------------------------------------#
400              
401              
402             # Autoload methods go after =cut, and are processed by the autosplit program.
403              
404             1;
405             __END__