File Coverage

blib/lib/WWW/Session.pm
Criterion Covered Total %
statement 174 197 88.3
branch 50 72 69.4
condition 22 32 68.7
subroutine 30 35 85.7
pod 17 17 100.0
total 293 353 83.0


line stmt bran cond sub pod time code
1             package WWW::Session;
2              
3 4     4   34719 use 5.006;
  4         12  
  4         139  
4 4     4   15 use strict;
  4         7  
  4         122  
5 4     4   18 use warnings;
  4         9  
  4         8543  
6              
7             =head1 NAME
8              
9             WWW::Session - Generic session management engine for web applications
10              
11             =head1 DESCRIPTION
12              
13             Generic session management engine for web applications with multiple backends,
14             object serialization and data validation
15              
16             =head1 VERSION
17              
18             Version 0.12
19              
20             =cut
21              
22             our $VERSION = '0.12';
23              
24             =head1 SYNOPSIS
25              
26             This module allows you to easily create sessions , store data in them and later
27             retrieve that information, using multiple storage backends
28              
29             Example:
30              
31             use WWW::Session;
32            
33             #set up the storage backends
34             WWW::Session->add_storage( 'File', {path => '/tmp/sessions'} );
35             WWW::Session->add_storage( 'Memcached', {servers => ['127.0.0.1:11211']} );
36            
37             #Set up the serialization engine (defaults to JSON)
38             WWW::Session->serialization_engine('JSON');
39            
40             #Set up the default expiration time (in seconds or -1 for never)
41             WWW::Session->default_expiration_time(3600);
42              
43             #Turn on autosave
44             WWW::Session->autosave(1);
45            
46             #and than ...
47            
48             #Create a new session
49             my $session = WWW::Session->new($sid,$hash_ref);
50             ...
51             $session->sid(); #returns $sid
52             $session->data(); #returns $hash_ref
53              
54             #set the user
55             $session->user($user);
56             #retrieve the user
57             my $user = $session->user();
58              
59             #returns undef if it doesn't exist or it's expired
60             my $session = WWW::Session->find($sid);
61            
62             #returns the existing session if it exists, creates a new session if it doesn't
63             my $session = WWW::Session->find_or_create($sid);
64              
65             Using the session :
66              
67             =over 4
68              
69             =item * Settings values
70              
71             There are two ways you can save a value on the session :
72              
73             $session->set('user',$user);
74            
75             or
76            
77             $session->user($user);
78            
79             If the requested field ("user" in the example above) already exists it will be
80             assigned the new value, if it doesn't it will be added.
81              
82             When you set a value for a field it will be validated first (see setup_field() ).
83             If the value doesn't pass validation the field will keep it's old value and the
84             set method will return 0. If everything goes well the set method will return 1.
85            
86             =item * Retrieving values
87              
88             my $user = $session->get('user');
89            
90             or
91            
92             my $user = $session->user();
93            
94             If the requested field ("user" in the example above) already exists it will return
95             it's value, otherwise will return C
96              
97             =back
98              
99             We can automaticaly deflate/inflate certain informations when we store / retrieve
100             from storage the session data (see setup_field() for more details):
101              
102             WWW::Session->setup_field( 'user',
103             inflate => sub { return Some::Package->new( $_[0] ) },
104             deflate => sub { $_[0]->id() }
105             );
106              
107             We can automaticaly validate certain informations when we store / retrieve
108             from storage the session data (see setup_field() for more details):
109              
110             WWW::Session->setup_field( 'age',
111             filter => sub { $_[0] >= 18 }
112             );
113              
114              
115             Another way to initialize the module :
116              
117             use WWW::Session storage => [ 'File' => { path => '/tmp/sessions'},
118             'Memcached' => { servers => ['127.0.0.1'] }
119             ],
120             serialization => 'JSON',
121             expires => 3600,
122             fields => {
123             user => {
124             inflate => sub { return Some::Package->new( $_[0] ) },
125             deflate => sub { $_[0]->id() },
126             }
127             };
128            
129             =cut
130              
131             #Internal variables
132             my @storage_engines = ();
133             my $serializer = undef;
134             my $default_expiration = -1;
135             my $fields_modifiers = {};
136             my $autosave = 1;
137              
138             #Set up the default serializer
139             __PACKAGE__->serialization_engine('JSON');
140              
141             =head1 SESSION & OBJECTS
142              
143             The default serialization engine is JSON, but JSON can't serialize objects by default,
144             you will have to write more code to accomplish that. If your session data data contains
145             objects you can take one of the following approaches :
146              
147             =over 4
148              
149             =item * Use inflate/deflate (recommended)
150              
151             # if we have a user object (eg MyApp::User) we can deflate it like this
152            
153             WWW::Session->setup_field('user', deflate => sub { return $_[0]->id() } );
154            
155             #and inflate it back like this
156            
157             WWW::Session->setup_field('user',inflate => sub { return Some::Package->new( $_[0] ) } );
158            
159             This method even thow it's slower, it reduces the size of the session object when stored, and
160             it ensures that if the object data changed since we saved it, this changes will be reflected in the
161             object when we retrieve restore it (usefull for database result objects)
162              
163             =item * Change the serialization module to 'Storable'
164              
165             The 'Storable' serialization engine can handle object without any additional changes
166              
167             WWW::Session->serialization_engine('Storable');
168              
169             Note : The perl Storable module is not very compatible between different version, so sharing data
170             between multiple machines could cause problems. We recommad using the 'JSON' engine with
171             inflate/defate (described above);
172              
173             =back
174              
175             =head1 STORAGE BACKENDS
176              
177             You can use one or more of the fallowing backends (the list might not be complete, more backends might be available on CPAN):
178              
179             =head2 File storage
180              
181             Here is how you can set up the File storage backend :
182              
183             use WWW::Session;
184              
185             WWW::Session->add_storage('File', {path => '.'} );
186              
187             See WWW::Session::Storage::File for more details
188              
189             =head2 Database storage
190              
191             If you want to store your session is MySQL do this :
192              
193             use WWW::Session;
194              
195             WWW::Session->add_storage( 'MySQL', {
196             dbh => $dbh,
197             table => 'sessions',
198             fields => {
199             sid => 'session_id',
200             expires => 'expires',
201             data => 'data'
202             },
203             }
204             );
205              
206             The "fields" hasref contains the mapping of session internal data to the column names from MySQL.
207             The keys are the session fields ("sid","expires" and "data") and must all be present.
208              
209             The MySQL types of the columns should be :
210              
211             =over 4
212              
213             =item * sid => varchar(32)
214              
215             =item * expires => DATETIME or TIMESTAMP
216              
217             =item * data => text
218              
219             =back
220              
221             See WWW::Session::Storage::MySQL for more details
222              
223             =head2 Memcached storage
224              
225             To use memcached as a storage backend do this :
226              
227             use WWW::Session;
228              
229             WWW::Session->add_storage('Memcached', {servers => ['127.0.0.1:11211']} );
230              
231              
232             See WWW::Session::Storage::Memcached for more details
233              
234              
235             =head1 SUBROUTINES/METHODS
236              
237             =head2 new
238              
239             Creates a new session object with the unique identifier and the given data.
240             If a session with the same identifier previously existed it will be overwritten
241              
242             Parameters
243              
244             =over 4
245              
246             =item * sid = unique id for this session
247              
248             =item * data = hash reference containing the data that we want to store in the session object
249              
250             =item * exipres = for how many secconds is this session valid (defaults to the default expiration time)
251              
252             =back
253              
254             Retuns a WWW::Session object
255              
256             Usage :
257              
258             my $session = WWW::Session->new('session_id',{ a=> 1, b=> 2});
259              
260             =cut
261              
262             sub new {
263 15     15 1 1705 my ($class,$sid,$data,$expires) = @_;
264            
265 15   50     75 $expires ||= -1;
266 15   50     43 $data ||= {};
267            
268 15 50       38 die "You cannot use a undefined string as a session id!" unless $sid;
269            
270 15         68 my $self = {
271             data => {},
272             expires => $expires,
273             sid => $sid,
274             changed => {},
275             };
276            
277 15         37 bless $self, $class;
278            
279 15         62 $self->set($_,$data->{$_}) foreach keys %{$data};
  15         85  
280            
281 15         44 return $self;
282             }
283              
284             =head2 find
285              
286             Retieves the session object for the given session id
287              
288             Usage :
289              
290             my $session = WWW::Session->find('session_id');
291              
292             =cut
293             sub find {
294 8     8 1 402 my ($class,$sid) = @_;
295            
296 8 50       23 die "You cannot use a undefined string as a session id!" unless $sid;
297            
298 8         10 my $info;
299            
300 8         18 foreach my $storage (@storage_engines) {
301 8         34 $info = $storage->retrieve($sid);
302 8 100       29 last if defined $info;
303             }
304            
305 8 100       19 if ($info) {
306 5         24 my $session = $class->load($info);
307 5         12 $session->{changed} = {};
308 5         14 return $session;
309             }
310            
311 3         8 return undef;
312             }
313              
314             =head2 find_or_create
315              
316             Retieves the session object for the given session id if it exists, if not it
317             creates a new object with the given session id
318              
319             =over 4
320              
321             =item * sid = unique id for this session
322              
323             =item * data = hash reference containing the data that we want to store in the session object
324              
325             =item * exipres = for how many secconds is this session valid (defaults to the default expiration time),
326              
327             =back
328              
329             Usage:
330              
331             my $session = WWW::Session->find_or_create('session_id',{ c=>2 })
332              
333             =cut
334             sub find_or_create {
335 2     2 1 5 my ($class,$sid,$data,$expires) = @_;
336            
337 2         8 my $self = $class->find($sid);
338            
339 2 100       8 if ($self) {
340 1 50       3 $self->expires($expires) if defined ($expires);
341 1         26 $self->set($_,$data->{$_}) foreach keys %{$data};
  1         6  
342             }
343             else {
344 1         4 $self = $class->new($sid,$data,$expires);
345             }
346            
347 2         8 return $self;
348             }
349              
350              
351             =head2 set
352              
353             Adds/sets a new value for the given field
354              
355             Usage :
356              
357             $session->set('user',$user);
358            
359             The values can also be set by calling the name of the field you want to set
360             as a method :
361              
362             $session->user($user);
363              
364             =cut
365              
366             sub set {
367 35     35 1 2451 my ($self,$field,$value) = @_;
368            
369 35 0 33     97 if (! defined $value && exists $fields_modifiers->{$field} && defined $fields_modifiers->{$field}->{default}) {
      33        
370 0         0 $value = $fields_modifiers->{$field}->{default};
371             }
372            
373 35         75 $self->run_trigger('before_set_value',$field,$value,$self->get($field));
374            
375 35         45 my $validated = 1;
376            
377 35 100 100     111 if ( exists $fields_modifiers->{$field} && defined $fields_modifiers->{$field}->{filter} ) {
378            
379 6         8 $validated = 0; #we have a filter, check the value against the filter first
380            
381 6         12 my $filter = $fields_modifiers->{$field}->{filter};
382            
383 6 50       16 die "Filter must be a hash ref or array ref or code ref" unless ref($filter);
384            
385 6 100       35 if (ref($filter) eq "ARRAY") {
    100          
    50          
386 2 100       2 if (grep { $value eq $_ } @{$filter}) {
  6         18  
  2         5  
387 1         3 $validated = 1;
388             }
389             }
390             elsif (ref($filter) eq "CODE") {
391 2         7 $validated = $filter->($value);
392             }
393             elsif (ref($filter) eq "HASH") {
394 2         3 my $h_valid = 1;
395            
396 2 50       10 if ( defined $filter->{isa} ) {
397 2 100       8 $h_valid = 0 unless ref($value) eq $filter->{isa};
398             }
399            
400 2         5 $validated = $h_valid;
401             }
402             }
403            
404 35 100       69 if ($validated) {
405 32         57 $self->{data}->{$field} = $value;
406 32         51 $self->{changed}->{$field} = 1;
407            
408 32         50 $self->run_trigger('after_set_value',$field,$value);
409             }
410             else {
411 3         309 warn "Value $value failed validation for key $field";
412             }
413            
414 35         118 return $validated;
415             }
416              
417              
418             =head2 get
419              
420             Retrieves the value of the given key from the session object
421              
422             Usage :
423              
424             my $user = $session->get('user');
425            
426             You can also use the name of the field you want to retrieve as a method.
427             The above call does the same as :
428              
429             my $user = $session->user();
430            
431             =cut
432              
433             sub get {
434 70     70 1 189 my ($self,$field) = @_;
435            
436 70         277 return $self->{data}->{$field};
437             }
438              
439             =head2 delete
440              
441             Removes the given key from the session data
442              
443             Usage :
444              
445             $session->delete('user');
446              
447             =cut
448             sub delete {
449 3     3 1 9 my ($self,$field) = @_;
450            
451 3         11 $self->run_trigger('before_delete',$field,$self->get($field));
452            
453 3         7 $self->{changed}->{$field} = 1;
454 3         9 my $rv = delete $self->{data}->{$field};
455            
456 3         8 $self->run_trigger('after_delete',$field,$self->get($field));
457            
458 3         17 return $rv;
459             }
460              
461             =head2 sid
462              
463             Returns the session id associated with this session
464            
465             =cut
466              
467             sub sid {
468 23     23 1 2477 my ($self) = @_;
469            
470 23         75 return $self->{sid};
471             }
472              
473             =head2 expires
474              
475             Getter/Setter for the expiration time of this session
476            
477             =cut
478              
479             sub expires {
480 0     0 1 0 my ($self,$value) = @_;
481              
482 0 0       0 if (defined $value) {
483 0         0 $self->{expires} = $value;
484             }
485              
486 0         0 return $self->{expires};
487             }
488              
489             =head2 add_storage
490              
491             Adds a new storge engine to the list of Storage engines that will be used to
492             store the session info
493              
494             Usage :
495              
496             WWW::Session->add_storage($storage_engine_name,$storage_engine_options);
497            
498             Parameters :
499              
500             =over 4
501              
502             =item * $storage_engine_name = Name of the class that defines a valid storage engine
503              
504             For WWW::Session::Storage::* modules you can use only the name of the storage,
505             you don't need the full name. eg Memcached and WWW::Session::Storage::Memcached
506             are synonyms
507              
508             =item * $storage_engine_options = hash ref containing the options that will be
509             passed on to the storage engine module when new() is called
510              
511             =back
512              
513             Example :
514              
515             WWW::Session->add_storage( 'File', {path => '/tmp/sessions'} );
516            
517             WWW::Session->add_storage( 'Memcached', {servers => ['127.0.0.1:11211']} );
518              
519             See each storage module for aditional details
520              
521             =cut
522              
523             sub add_storage {
524 3     3 1 1898 my ($class,$name,$options) = @_;
525            
526 3   50     11 $options ||= {};
527            
528 3 50       17 if ($name !~ /::/) {
529 3         10 $name = "WWW::Session::Storage::$name";
530             }
531            
532 3     3   198 eval "use $name";
  3         1610  
  3         7  
  3         52  
533            
534 3 50       11 die "WWW::Session cannot load '$name' storage engine! Error : $@" if ($@);
535            
536 3         11 my $storage = $name->new($options);
537            
538 3 50       20 if ($storage) {
539 3         18 push @storage_engines, $storage;
540             }
541             else {
542 0         0 die "WWW::Session storage engine '$name' failed to initialize with the given arguments!";
543             }
544             }
545              
546             =head2 serialization_engine
547              
548             Configures the serialization engine to be used for serialising sessions.
549              
550             The default serialization engine is JSON
551              
552             Usage :
553              
554             WWW::Session->serialization_engine('JSON');
555            
556             Parameters :
557              
558             =over 4
559              
560             =item * $serialization_engine_name = Name of the class that defines a valid serialization engine
561              
562             For WWW::Session::Serialization::* modules you can use only the short name of the module,
563             you don't need the full name. eg JSON and WWW::Session::Serialization::JSON
564             are synonyms
565              
566             =back
567              
568             =cut
569              
570             sub serialization_engine {
571 7     7 1 1126 my ($class,$name) = @_;
572            
573 7 50       37 if ($name !~ /::/) {
574 7         17 $name = "WWW::Session::Serialization::$name";
575             }
576            
577 4     4   2386 eval "use $name";
  4     3   9  
  4         80  
  7         503  
  3         50  
  3         5  
  3         56  
578            
579 7 50       26 die "WWW::Session cannot load '$name' serialization engine! Error : $@" if ($@);
580            
581 7         27 my $serializer_object = $name->new($fields_modifiers);
582            
583 7 50       33 if ($serializer_object) {
584 7         19 $serializer = $serializer_object;
585             }
586             else {
587 0         0 die "WWW::Session serialization engine '$name' failed to initialize!";
588             }
589             }
590              
591             =head2 autosave
592              
593             Turn on/off the autosave feature (on by default)
594              
595             If this feature is on the object will always be saved before beying destroyed
596              
597             Usage :
598              
599             WWW::Session->autosave(1);
600              
601             =cut
602              
603             sub autosave {
604 3     3 1 480 my ($class,$value) = @_;
605            
606 3 50       9 $autosave = $value if defined $value;
607            
608 3         4 return $autosave;
609             }
610              
611             =head2 default_expiration_time
612              
613             Setter/Getter for the default expiration time
614              
615             Usage :
616              
617             WWW::Session->default_expiration_time(1800);
618            
619             =cut
620              
621             sub default_expiration_time {
622 0     0 1 0 my ($class,$value) = @_;
623            
624 0 0       0 if (defined $value) {
625 0         0 $default_expiration = $value;
626             }
627            
628 0         0 return $default_expiration;
629             }
630              
631             =head2 destroy
632              
633             Completely removes all the data related to the current session
634              
635             NOTE: After calling destroy the session object will no longer be usable
636              
637             Usage :
638              
639             $session->destroy();
640            
641             =cut
642              
643             sub destroy {
644            
645             #save the session id fiers and undef the object before we delete it from
646             #storage to avoid autosave kikking in after we remove it from storage
647            
648 17     17 1 520 my $sid = $_[0]->sid();
649            
650 17         27 $_[0] = undef;
651            
652 17         53 foreach my $storage (@storage_engines) {
653 17         69 $storage->delete($sid);
654             }
655             }
656              
657              
658             =head2 setup_field
659              
660             Sets up the filters, inflators and deflators for the given field
661              
662             =head3 deflators
663              
664             Deflators are passed as code refs. The only argument the deflator
665             method receives is the value of the filed that it must be deflated and
666             it must return a single value (scalar, object or reference) that will be
667             asigned to the key.
668              
669             Example :
670              
671             # if we have a user object (eg MyApp::User) we can deflate it like this
672            
673             WWW::Session->setup_field('user', deflate => sub { return $_[0]->id() } );
674              
675             =head3 inflators
676              
677             Inflators are passed as code refs. The only argument the inflator
678             method receives is the value of the filed that it must inflate and
679             it must return a single value (scalar, object or reference) that will be
680             asigned to the key.
681              
682             Example :
683              
684             # if we have a user object (eg MyApp::User) we can inflate it like this
685              
686             WWW::Session->setup_field('user',inflate => sub { return Some::Package->new( $_[0] ) } );
687              
688             =head3 filters
689              
690             Filters can be used to ensure that the values from the session have the required values
691              
692             Filters can be :
693              
694             =over 4
695              
696             =item * array ref
697              
698             In this case when we call $session->set($field,$value) the values will have to be one of the
699             values from the array ref , or the operation will fail
700              
701             Example :
702              
703             #Check that the age is between 18 and 99
704             WWW::Session->setup_field('age',filter => [18..99] );
705              
706             =item * code ref
707              
708             In this case the field value will be passed to the code ref as the only parameter. The code ref
709             must return a true or false value. If it returns a false value the set() operation will fail
710              
711             Example :
712              
713             #Check that the age is > 18
714             WWW::Session->setup_field('age',filter => sub { $_[0] > 18 } );
715              
716             =item * hash ref
717              
718             In this case the only key from the hash that is recognised is "isa" will will chek that the
719             given value has the types specified as the value for "isa"
720              
721             Example :
722              
723             #Check that the 'rights' field is an array
724             WWW::Session->setup_field('age',filter => { isa => "ARRAY" } );
725            
726             #Check that the 'user' field is an MyApp::User object
727             WWW::Session->setup_field('user',filter => { isa => "MyApp::User" } );
728              
729             =back
730              
731             =head3 triggers
732              
733             Triggers allow you to execute a code ref when certain events happen on the key.
734              
735             The return values from the triggers are completely ignored.
736              
737             Available triggers are:
738              
739             =over 4
740              
741             =item * before_set_value
742              
743             Executed before the value is actually storred on the code. Arguments sent to the code ref
744             are : session object , new value, old value - in this order
745              
746             =item * after_set_value
747              
748             Executed after the new value is set on the session object. Arguments sent to the code ref
749             are : session object, new value
750              
751             =item * before_delete
752              
753             Executed before the key is removed from the session object. Arguments sent to the code ref
754             are : session object, current_value
755              
756             =item * after_delete
757              
758             Executed after the key is removed from the session object. Arguments sent to the code ref
759             are : session object, previous_value
760              
761             =back
762              
763             Example :
764              
765             WWW::Session->setup_field(
766             'user',
767             filter => { isa => "MyApp::User" },
768             deflate => sub { $_[0]->id() },
769             inflate => sub { return MyApp::User->find($_[0]) }
770             trigger => { before_set_value => sub { warn "About to set the user },
771             after_delete => sub { ... },
772             }
773             );
774              
775             =cut
776              
777             sub setup_field {
778 7     7 1 2711 my ($self,$field,%settings) = @_;
779            
780 7         36 while (my ($key,$val) = each %settings) {
781 9         107 $fields_modifiers->{$field}{$key} = $val;
782             }
783             }
784              
785             =head2 save
786              
787             Serializes a WWW::Session object sends it to all storage engines for saving
788              
789             =cut
790              
791             sub save {
792 19     19 1 382 my ($self) = @_;
793            
794 19         79 my $data = {
795             sid => $self->{sid},
796             expires => $self->{expires},
797             };
798            
799 19         29 foreach my $field ( keys %{$self->{data}} ) {
  19         71  
800 33 100 100     111 if (defined $fields_modifiers->{$field} && defined $fields_modifiers->{$field}->{deflate}) {
801 2         12 $data->{data}->{$field} = $fields_modifiers->{$field}->{deflate}->($self->{data}->{$field});
802             }
803             else {
804 31         91 $data->{data}->{$field} = $self->{data}->{$field}
805             }
806             }
807            
808 19         155 my $string = $serializer->serialize($data);
809            
810 19         607 foreach my $storage (@storage_engines) {
811 19         85 $storage->save($self->{sid},$self->{expires},$string);
812             }
813             }
814              
815             =head1 ACCESSING SESSION DATA
816              
817             Allows us to get/set session data directly by calling the field name as a method
818              
819             Example:
820              
821             my $user = $session->user(); #same as $user = $session->get('user');
822            
823             #or
824            
825             $session->age(21); #same as $session->set('age',21);
826              
827             =cut
828              
829             our $AUTOLOAD;
830             sub AUTOLOAD {
831 4     4   18 my $self = shift;
832 4         5 my $value = shift;
833              
834 4         4 my $field = $AUTOLOAD;
835              
836 4         23 $field =~ s/.*:://;
837              
838 4 100       13 if (defined $value) {
839 2         5 $self->set($field,$value);
840             }
841            
842 4         10 return $self->get($field);
843             }
844              
845              
846             =head1 AUTOSAVE FEATURE
847              
848             If you set autosave to 1 the session will be saved before the object is
849             destroyed if any data has changed
850              
851             BE CAREFULL : If you store complex structures only the changes made to direct
852             session keys will be detected.
853              
854             Example :
855              
856             #this change will be detected because it affects a direct session attribute
857             $session->age(21);
858              
859             #this changes won't be detected :
860             my $user = $session->user();
861             $user->{age} = 21;
862            
863             You have two choices :
864              
865             =over 4
866              
867             =item 1 Make a change that can be detected
868              
869             $session->some_random_field( time() );
870            
871             =item 2 Save the session manually
872              
873             $session->save();
874            
875             =back
876            
877             =cut
878              
879             sub DESTROY {
880 20     20   1611 my $self = shift;
881            
882 20 100 100     116 if ($autosave && scalar(keys %{$self->{changed}})) {
  18         86  
883 14         35 $self->save();
884             }
885             }
886              
887              
888             =head1 PRIVATE METHODS
889              
890             =head2 load
891              
892             Deserializes a WWW::Session object from the given string and deflates all the fields that
893             were inflated when the session was serialized
894              
895             =cut
896              
897             sub load {
898 5     5 1 9 my ($class,$string) = @_;
899            
900 5         16 my $self = $serializer->expand($string);
901            
902 5         123 foreach my $field ( keys %{$self->{data}} ) {
  5         20  
903 9 100 66     35 if (defined $fields_modifiers->{$field} && defined $fields_modifiers->{$field}->{inflate}) {
904 1         7 $self->{data}->{$field} = $fields_modifiers->{$field}->{inflate}->($self->{data}->{$field});
905             }
906             }
907            
908 5         38 bless $self,$class;
909            
910 5         9 return $self;
911             }
912              
913             =head2 import
914              
915             Allows us to configure all the module options in one line
916              
917             Example :
918              
919             use WWW::Session storage => [
920             'File' => { path => '/tmp/sessions'},
921             'Memcached' => { servers => ['127.0.0.1'] }
922             ],
923             serialization => 'Storable',
924             expires => 3600,
925             fields => {
926             user => {
927             inflate => sub { return Some::Package->new( $_[0]->id() ) },
928             deflate => sub { $_[0]->id() },
929             },
930             age => {
931             filter => [21..99],
932             }
933             },
934             autosave => 1;
935              
936             =cut
937              
938             sub import {
939 4     4   88 my ($class, %params) = @_;
940            
941 4 100       22 if (defined $params{storage}) {
942 1         2 while ( scalar(@{$params{storage}}) ) {
  2         6  
943 1         1 my $engine = shift @{$params{storage}};
  1         2  
944 1         2 my $options = shift @{$params{storage}};
  1         2  
945 1         5 $class->add_storage($engine,$options);
946             }
947             }
948 4 100       13 if (defined $params{serialization}) {
949 1         4 $class->serialization_engine($params{serialization});
950             }
951 4 50       20 if (defined $params{expires}) {
952 0         0 $class->default_expiration_time($params{expires});
953             }
954 4 100       22 if (defined $params{autosave}) {
955 1         3 $class->autosave($params{autosave});
956             }
957 4 50       1336 if (defined $params{fields}) {
958 0         0 foreach my $field (keys %{$params{fields}}) {
  0         0  
959 0         0 $class->setup_field($field,%{ $params{fields}->{$field} });
  0         0  
960             }
961             }
962             }
963              
964             =head2 run_trigger
965              
966             Runs a trigger for the given field
967              
968             =cut
969             sub run_trigger {
970 73     73 1 109 my $self = shift;
971 73         76 my $trigger = shift;
972 73         58 my $field = shift;
973            
974 73 100 100     341 if ( exists $fields_modifiers->{$field}
      100        
975             && defined $fields_modifiers->{$field}{trigger}
976             && defined $fields_modifiers->{$field}{trigger}{$trigger} )
977             {
978 4         9 my $trigger = $fields_modifiers->{$field}{trigger}{$trigger};
979 4 50 33     21 die "WWW::Session triggers must be code refs!" unless ref( $trigger ) && ref( $trigger ) eq "CODE";
980 4         14 $trigger->( $self, @_ );
981             }
982             }
983              
984              
985             =head1 TIE INTERFACE
986              
987             The WWW::Session objects can be tied to hashes to make them easier to use
988              
989             Example :
990              
991             my %session;
992            
993             tie %session, WWW::Session, 'session_id', {user => $user, authenticated => 1};
994            
995             ...
996             my $user = $session{user};
997              
998             ...
999             $session{authenticated} = 0;
1000             delete $session{user};
1001              
1002             =cut
1003              
1004             sub TIEHASH {
1005 1     1   15 my ($class,@params) = @_;
1006            
1007 1         6 return $class->find_or_create(@params);
1008             }
1009              
1010             sub STORE {
1011 1     1   4 my ($self,$key,$value) = @_;
1012            
1013 1         4 $self->set($key,$value);
1014             }
1015              
1016             sub FETCH {
1017 3     3   975 my ($self,$key) = @_;
1018            
1019 3         7 return $self->get($key);
1020             }
1021              
1022             sub DELETE {
1023 1     1   3 my ($self,$key) = @_;
1024            
1025 1         21 $self->delete($key);
1026             }
1027              
1028             sub CLEAR {
1029 0     0   0 my ($self) = @_;
1030            
1031 0         0 $self->{data} = {};
1032             }
1033              
1034             sub EXISTS {
1035 0     0   0 my ($self,$key) = @_;
1036            
1037 0         0 return exists $self->{data}->{$key};
1038             }
1039              
1040             sub FIRSTKEY {
1041 3     3   1037 my ($self) = @_;
1042            
1043 3         5 my $a = keys %{ $self->{data} };
  3         11  
1044            
1045 3         3 each %{ $self->{data} };
  3         16  
1046             }
1047              
1048             sub NEXTKEY {
1049 5     5   6 my ($self) = @_;
1050            
1051 5         7 return each %{ $self->{data} };
  5         27  
1052             }
1053              
1054             sub SCALAR {
1055 0     0   0 my ($self) = @_;
1056            
1057 0         0 return scalar %{ $self->{data} };
  0         0  
1058             }
1059              
1060             =head1 AUTHOR
1061              
1062             Gligan Calin Horea, C<< >>
1063              
1064             =head1 BUGS
1065              
1066             Please report any bugs or feature requests to C, or through
1067             the web interface at L. I will be notified, and then you'll
1068             automatically be notified of progress on your bug as I make changes.
1069              
1070              
1071             =head1 SUPPORT
1072              
1073             You can find documentation for this module with the perldoc command.
1074              
1075             perldoc WWW::Session
1076              
1077              
1078             You can also look for information at:
1079              
1080             =over 4
1081              
1082             =item * RT: CPAN's request tracker (report bugs here)
1083              
1084             L
1085              
1086             =item * AnnoCPAN: Annotated CPAN documentation
1087              
1088             L
1089              
1090             =item * CPAN Ratings
1091              
1092             L
1093              
1094             =item * Search CPAN
1095              
1096             L
1097              
1098             =back
1099              
1100              
1101             =head1 ACKNOWLEDGEMENTS
1102              
1103              
1104             =head1 LICENSE AND COPYRIGHT
1105              
1106             Copyright 2012 Gligan Calin Horea.
1107              
1108             This program is free software; you can redistribute it and/or modify it
1109             under the terms of either: the GNU General Public License as published
1110             by the Free Software Foundation; or the Artistic License.
1111              
1112             See http://dev.perl.org/licenses/ for more information.
1113              
1114              
1115             =cut
1116              
1117             1; # End of WWW::Session