File Coverage

blib/lib/WebDAO/Engine.pm
Criterion Covered Total %
statement 58 185 31.3
branch 6 86 6.9
condition 2 16 12.5
subroutine 14 26 53.8
pod 2 5 40.0
total 82 318 25.7


line stmt bran cond sub pod time code
1             package WebDAO::Engine;
2              
3             #$Id$
4              
5             =head1 NAME
6              
7             =head1 DESCRIPTION
8              
9             WebDAO::Engine - Class for root object of application model
10              
11             =cut
12              
13             our $VERSION = '0.01';
14              
15 5     5   25 use Data::Dumper;
  5         9  
  5         247  
16 5     5   568 use WebDAO::Container;
  5         9  
  5         174  
17 5     5   2885 use WebDAO::Lib::MethodByPath;
  5         13  
  5         165  
18 5     5   3164 use WebDAO::Lib::RawHTML;
  5         14  
  5         180  
19 5     5   32 use base qw(WebDAO::Container);
  5         10  
  5         405  
20 5     5   33 use Carp;
  5         8  
  5         351  
21 5     5   31 use strict;
  5         10  
  5         134  
22 5     5   28 use warnings;
  5         11  
  5         12958  
23             __PACKAGE__->mk_attr( _session=>undef, __obj=>undef, __events=>undef);
24              
25             sub new {
26 1     1 1 4 my $class = shift;
27 1         2 my $self = {};
28 1         3 my $stat;
29 1         2 bless( $self, $class );
30 1 50       13 return ( $stat = $self->_init(@_) ) ? $self : $stat;
31             }
32              
33             sub _sysinit {
34 1     1   2 my ( $self, $ref ) = @_;
35 1         4 my %hash = @$ref;
36              
37             # Setup $init_hash;
38 1   50     8 my $my_name = $hash{id} || '';
39             unshift(
40 1         2 @{$ref},
  1         5  
41             {
42             ref_engine => $self, #! Setup _engine refernce for childs!
43             name_obj => "$my_name"
44             }
45             ); #! Setup _my_name
46             #Save session
47 1         32 _session $self $hash{session};
48              
49             # name_obj=>"applic"}); #! Setup _my_name
50 1         7 $self->SUPER::_sysinit($ref);
51              
52             #!init _runtime variables;
53 1         7 $self->_set_parent($self);
54              
55             #hash "function" -"package"
56 1         25 $self->__obj( {} );
57              
58             #init hash of evens names -> @Array of pointers of sub in objects
59 1         24 $self->__events( {} );
60              
61             }
62              
63             sub init {
64 1     1 0 4 my ( $self, %opt ) = @_;
65              
66             #register default clasess
67 1         5 $self->register_class(
68             'WebDAO::Lib::RawHTML' => '_rawhtml_element',
69             'WebDAO::Lib::MethodByPath' => '_method_call'
70             );
71              
72             #Register by init classes
73 1 50       4 if ( ref( my $classes = $opt{register} ) ) {
74 0         0 $self->register_class(%$classes);
75             }
76 1 50       7 if ( my $lexer = $opt{lexer} ) {
    50          
77 0         0 map { $_->value($self) } @{ $lexer->auto };
  0         0  
  0         0  
78 0         0 my @objs = map { $_->value($self) } @{ $lexer->tree };
  0         0  
  0         0  
79 0         0 $self->_add_childs_(@objs);
80             }
81             elsif ( my $lex = $opt{lex} ) {
82 0 0       0 my ( $pre, $fetch, $post ) = @{ $lex->value($self) || [] };
  0         0  
83 0         0 $self->__add_childs__( 0, @$pre );
84 0         0 $self->_add_childs_( @$fetch );
85 0         0 $self->__add_childs__( 2, @$post );
86             }
87              
88             }
89              
90             sub response {
91 0     0 1 0 my $self = shift;
92 0         0 return $self->_session->response_obj;
93             }
94              
95              
96             =head2 __handle_out__ ($sess, @output)
97              
98             Process output by fetch methods
99              
100             =cut
101              
102             sub __handle_out__ {
103 0     0   0 my $self = shift;
104 0         0 my $sess = shift;
105 0         0 for (@_) {
106 0 0       0 if ( UNIVERSAL::isa( $_, 'WebDAO::Element' ) ) {
    0          
    0          
107 0 0       0 $self->__handle_out__( $sess, $_->pre_fetch($sess) )
108             if UNIVERSAL::can( $_, 'pre_fetch' );
109              
110 0         0 $self->__handle_out__( $sess, $_->fetch($sess) );
111 0 0       0 $self->__handle_out__( $sess, $_->post_fetch($sess) )
112             if UNIVERSAL::can( $_, 'post_fetch' );
113              
114             }
115             elsif ( ref($_) eq 'CODE' ) {
116 0         0 return $self->__handle_out__( $sess, $_->($sess) );
117             }
118             elsif ( UNIVERSAL::isa( $_, 'WebDAO::Response' ) ) {
119 0         0 $_->_is_headers_printed(1);
120 0 0       0 $_->_print_dep_on_context($sess) unless $_->_is_file_send;
121 0         0 $_->flush;
122 0         0 $_->_destroy;
123              
124             }
125             else {
126 0         0 $sess->print($_);
127             }
128             }
129             }
130              
131             sub __events__ {
132 0     0   0 my $self = shift;
133 0         0 my $root = shift;
134 0         0 my $inject_fetch = shift;
135 0         0 my $path = $root->__path2me;
136 0         0 my @childs = ();
137              
138             #make inject event for objects
139 0 0       0 if ( my $res = $inject_fetch->{$path} ) {
140 0         0 @childs = (
141             {
142             fetch => $root->__path2me,
143             pme => $path,
144             ,
145             event => 'inject',
146             obj => $root,
147             res => $res
148             }
149             );
150              
151             }
152             else {
153              
154 0 0       0 if ( UNIVERSAL::isa( $root, 'WebDAO::Container' ) ) {
155              
156             #skip modal
157 0         0 for ( @{ $root->__childs() } ) {
  0         0  
158 0 0       0 push @childs, $self->__events__( $_, $inject_fetch )
159             unless UNIVERSAL::isa( $_, 'WebDAO::Modal' );
160             }
161             }
162             else {
163 0         0 @childs = (
164             {
165             fetch => $root->__path2me,
166             pme => $path,
167             ,
168             event => 'fetch',
169             obj => $root
170             }
171             );
172             }
173             }
174 0         0 my @res = (
175             {
176             st_ev => $root->__path2me,
177             pme => $path,
178             event => 'start',
179             obj => $root
180             },
181             @childs,
182             {
183             end_ev => $root->__path2me,
184             pme => $path,
185             event => 'end',
186             obj => $root
187             }
188             );
189             }
190              
191             sub _execute {
192 0     0   0 my $self =shift;
193 0         0 return $self->execute2(@_)
194             }
195              
196             sub execute2 {
197 0     0 0 0 my $self = shift;
198 0         0 my $sess = shift;
199 0         0 my $url = shift;
200 0         0 my @path = @{ $sess->call_path($url) };
  0         0  
201 0         0 my ( $src, $res ) = $self->_traverse_( $sess, @path );
202 0         0 my $response = $self->response;
203             #now analyze answers
204             # undef -> not Found
205 0 0       0 unless ( defined($res) ) {
206 0         0 $response->error404( "Url not found:" . join "/", @path );
207 0         0 $response->flush;
208 0         0 $response->_destroy;
209 0         0 return; #end
210             }
211              
212             #convert string and ref(scalar) to resonse with html
213             #special handle strings
214 0 0 0     0 if ( !ref($res) or ( ref($res) eq 'SCALAR' ) ) {
215 0 0       0 $res = $response->set_html( ref($res) ? $$res : $res );
216             }
217             #special handle HASH refs ( interpret as json)
218 0 0 0     0 if ( ( ref($res) eq 'HASH' ) and $response->wantformat('json') ) {
219 0         0 $res = $response->set_json( $res );
220             }
221             #check if response modal
222 0 0       0 if ( UNIVERSAL::isa( $res, 'WebDAO::Response' ) ) {
223             #check empty response( $r->set_empty)
224 0 0       0 return if $res->is_empty;
225 0 0       0 if ( $res->_is_modal() ) {
226              
227             #handle response
228 0 0       0 $res->_print_dep_on_context($sess, $res) unless $res->_is_file_send;
229 0         0 $res->flush;
230 0         0 $res->_destroy;
231 0         0 return;
232             }
233             }
234              
235             #extract all objects to evenets
236 0         0 my $root = $self;
237              
238             #if object modal ?
239 0 0       0 if ( UNIVERSAL::isa( $src, 'WebDAO::Modal' ) ) {
240              
241             #set him as root of putput
242 0         0 $root = $src;
243             }
244 0         0 my $need_inject_result = 1;
245              
246             #special handle strings
247 0 0 0     0 if ( !ref($res) or ( ref($res) eq 'SCALAR' ) ) {
    0          
248              
249             #now walk
250             }
251             elsif
252              
253             #if result ref to object and it eq $src run flow
254             ( $res == $src ) {
255 0         0 $need_inject_result = 0;
256             }
257 0 0       0 if ( UNIVERSAL::isa( $res, 'WebDAO::Element' ) ) {
258              
259             #nothing to do
260             }
261 0         0 my %injects = ();
262              
263             #if need inject check flow by path
264 0 0       0 if ($need_inject_result) {
265 0         0 $injects{ $src->__path2me } = $res;
266             }
267             #start out
268 0         0 $response->print_header;
269              
270 0         0 my @ev_flow = $self->__events__( $root, \%injects );
271 0         0 foreach my $ev (@ev_flow) {
272 0         0 my $obj = $ev->{obj};
273              
274             #_log1 $self "DO " . $ev->{event}. " for $obj";
275 0 0       0 if ( $ev->{event} eq 'start' ) {
    0          
    0          
    0          
276 0 0       0 $self->__handle_out__( $sess, $obj->pre_fetch($sess) )
277             if UNIVERSAL::can( $obj, 'pre_fetch' );
278             }
279             elsif ( $ev->{event} eq 'inject' ) {
280             $self->__handle_out__( $sess, $ev->{res} )
281              
282 0         0 }
283             elsif ( $ev->{event} eq 'fetch' ) {
284              
285             #skip fetch method for container
286              
287 0 0       0 $self->__handle_out__( $sess, $obj->fetch($sess) )
288             if UNIVERSAL::can( $obj, 'fetch' );
289              
290             }
291             elsif ( $ev->{event} eq 'end' ) {
292              
293 0 0       0 $self->__handle_out__( $sess, $obj->post_fetch($sess) )
294             if UNIVERSAL::can( $obj, 'post_fetch' );
295             }
296              
297             }
298 0         0 $response->flush;
299 0         0 $response->_destroy;
300             }
301              
302              
303             #fill $self->__events hash event - method
304             sub __register_event__ {
305 0     0   0 my ( $self, $ref_obj, $event_name, $ref_sub ) = @_;
306 0         0 my $ev_hash = $self->__events;
307 0 0       0 $ev_hash->{$event_name}->{ scalar($ref_obj) } = {
308             ref_obj => $ref_obj,
309             ref_sub => $ref_sub
310             }
311             if ( ref($ref_sub) );
312 0         0 return 1;
313             }
314              
315             sub __send_event__ {
316 0     0   0 my ( $self, $event_name, @Par ) = @_;
317 0         0 my $ev_hash = $self->__events;
318 0 0       0 unless ( exists( $ev_hash->{$event_name} ) ) {
319 0         0 _log2 $self "WARN: Event $event_name not exists.";
320 0         0 return 0;
321             }
322 0         0 foreach my $ref_rec ( keys %{ $ev_hash->{$event_name} } ) {
  0         0  
323 0         0 my $ref_sub = $ev_hash->{$event_name}->{$ref_rec}->{ref_sub};
324 0         0 my $ref_obj = $ev_hash->{$event_name}->{$ref_rec}->{ref_obj};
325 0         0 $ref_obj->$ref_sub( $event_name, @Par );
326             }
327             }
328              
329             =head3 _create_(,,@parameters)
330              
331             create object by .
332              
333             =cut
334              
335             sub _create_ {
336 0     0   0 my ( $self, $name_obj, $name_func, @par ) = @_;
337 0   0     0 my $pack = $self->_pack4name($name_func) || $name_func;
338 0         0 my $ref_init_hash = {
339             ref_engine => $self->_root_, #! Setup _engine refernce for childs!
340             name_obj => $name_obj
341             }; #! Setup _my_name
342 0 0       0 my $obj_ref =
343             $pack->isa('WebDAO::Element')
344             ? eval "'$pack'\-\>new(\@par)"
345             : eval "'$pack'\-\>new(\@par)";
346             # ? eval "'$pack'\-\>new(\$ref_init_hash,\@par)"
347             # : eval "'$pack'\-\>new(\@par)";
348 0 0       0 if ($pack->isa('WebDAO::Element') ) {
349 0         0 $obj_ref->{_engine} = $self->_root_ ;
350 0         0 $obj_ref->{__my_name} = $name_obj ;
351 0         0 $obj_ref->_init($ref_init_hash,@par)
352             }
353 0 0       0 $self->_log1("Error in eval: _create_ $@") if $@;
354 0         0 return $obj_ref;
355             }
356              
357             sub _createObj {
358 0     0   0 my $self = shift;
359              
360             # _deprecated $self "_create_";
361 0         0 return $self->_create_(@_);
362             }
363              
364             #Get package for functions name
365             sub _pack4name {
366 0     0   0 my ( $self, $name ) = @_;
367 0         0 my $ref = $self->__obj;
368 0 0       0 return $$ref{$name} if ( exists $$ref{$name} );
369             }
370              
371             sub register_class {
372 1     1 0 4 my ( $self, %register ) = @_;
373 1         22 my $_obj = $self->__obj;
374 1         6 while ( my ( $class, $alias ) = each %register ) {
375              
376             #check non loaded mods
377 2         11 my ( $main, $module ) = $class =~ m/(.*\:\:)?(\S+)$/;
378 2   50     6 $main ||= 'main::';
379 2         9 $module .= '::';
380 5     5   38 no strict 'refs';
  5         9  
  5         733  
381 2 50       9 unless ( exists $$main{$module} ) {
382 0         0 _log1 $self "Try use $class";
383 0         0 eval "use $class";
384 0 0       0 if ($@) {
385 0         0 _log1 $self "Error register class :$class with $@ ";
386 0         0 return "Error register class :$class with $@ ";
387 0         0 next;
388             }
389             }
390 5     5   25 use strict 'refs';
  5         9  
  5         639  
391              
392             #check if register_class used for eval ( see Lobject )
393 2 50       18 $$_obj{$alias} = $class if defined $alias;
394             }
395 1         3 return;
396             }
397              
398             =head3 _commit
399              
400             Method witch called after HTTP request
401              
402             =cut
403              
404       0     sub _commit {
405             #nothing by default
406             }
407              
408             sub _destroy {
409 0     0     my $self = shift;
410 0           $self->SUPER::_destroy;
411 0           $self->_session(undef);
412 0           $self->__obj(undef);
413 0           $self->__events(undef);
414             }
415             1;
416             __DATA__