File Coverage

blib/lib/Mars/Class.pm
Criterion Covered Total %
statement 98 98 100.0
branch 20 20 100.0
condition 20 21 95.2
subroutine 43 43 100.0
pod 6 6 100.0
total 187 188 99.4


line stmt bran cond sub pod time code
1             package Mars::Class;
2              
3 4     8   5898 use 5.018;
  4         12  
4              
5 4     4   17 use strict;
  4         9  
  4         88  
6 4     4   17 use warnings;
  4         6  
  4         288  
7              
8             # IMPORT
9              
10             sub import {
11 53     53   39035 my ($self, @args) = @_;
12              
13 53         107 my $from = caller;
14              
15 53         1676 require Mars::Kind::Class;
16              
17 4     4   21 no strict 'refs';
  4         7  
  4         142  
18 4     4   19 no warnings 'redefine';
  4         7  
  4         158  
19 4     4   20 no warnings 'once';
  4         7  
  4         3228  
20              
21 53 100       479 my %exports = map +($_,$_), @args ? @args : qw(
22             attr
23             base
24             false
25             from
26             mixin
27             role
28             test
29             true
30             with
31             );
32              
33 53         113 @{"${from}::ISA"} = 'Mars::Kind::Class';
  53         918  
34              
35 53 100 66     276 if ($exports{"attr"} && !*{"${from}::attr"}{"CODE"}) {
  53         294  
36 17     21   68 *{"${from}::attr"} = sub {@_ = ($from, @_); goto \&attr};
  17     21   50  
  21     21   112  
  21     18   70  
37             }
38 53 100 100     153 if ($exports{"base"} && !*{"${from}::base"}{"CODE"}) {
  50         188  
39 14     7   50 *{"${from}::base"} = sub {@_ = ($from, @_); goto \&base};
  14     7   35  
  7     7   35  
  7     2   22  
40             }
41 53 100       70 if (!*{"${from}::false"}{"CODE"}) {
  53         174  
42 17     8   64 *{"${from}::false"} = sub {require Mars; Mars::false()};
  17     8   42  
  8     8   1383  
  8     8   27  
        5      
43             }
44 53 100 100     118 if ($exports{"from"} && !*{"${from}::from"}{"CODE"}) {
  50         174  
45 14     3   55 *{"${from}::from"} = sub {@_ = ($from, @_); goto \&from};
  14     3   28  
  3     3   16  
  3     3   9  
46             }
47 53 100 100     133 if ($exports{"mixin"} && !*{"${from}::mixin"}{"CODE"}) {
  50         165  
48 14     3   48 *{"${from}::mixin"} = sub {@_ = ($from, @_); goto \&mixin};
  14     3   31  
  3     2   15  
  3         11  
49             }
50 53 100 100     136 if ($exports{"role"} && !*{"${from}::role"}{"CODE"}) {
  50         198  
51 14     7   49 *{"${from}::role"} = sub {@_ = ($from, @_); goto \&role};
  14     6   29  
  6         35  
  6         24  
52             }
53 53 100 100     122 if ($exports{"test"} && !*{"${from}::test"}{"CODE"}) {
  50         170  
54 14     14   41 *{"${from}::test"} = sub {@_ = ($from, @_); goto \&test};
  14     10   43  
  10         51  
  10         32  
55             }
56 53 100       66 if (!*{"${from}::true"}{"CODE"}) {
  53         136  
57 17     6   44 *{"${from}::true"} = sub {require Mars; Mars::true()};
  17     6   34  
  6     6   43  
  6         19  
58             }
59 53 100 100     123 if ($exports{"with"} && !*{"${from}::with"}{"CODE"}) {
  50         171  
60 14     15   57 *{"${from}::with"} = sub {@_ = ($from, @_); goto \&test};
  14     11   32  
  11     10   54  
  11         50  
61             }
62              
63 53         79 ${"${from}::META"} = {};
  53         169  
64              
65 53         2725 return $self;
66             }
67              
68             sub attr {
69 21     25 1 41 my ($from, @args) = @_;
70              
71 21         106 $from->ATTR(@args);
72              
73 21         225 return $from;
74             }
75              
76             sub base {
77 7     11 1 15 my ($from, @args) = @_;
78              
79 7         40 $from->BASE(@args);
80              
81 7         76 return $from;
82             }
83              
84             sub from {
85 3     3 1 8 my ($from, @args) = @_;
86              
87 3         17 $from->FROM(@args);
88              
89 3         23 return $from;
90             }
91              
92             sub mixin {
93 3     3 1 8 my ($from, @args) = @_;
94              
95 3         25 $from->MIXIN(@args);
96              
97 3         37 return $from;
98             }
99              
100             sub role {
101 6     6 1 15 my ($from, @args) = @_;
102              
103 6         39 $from->ROLE(@args);
104              
105 6         56 return $from;
106             }
107              
108             sub test {
109 21     21 1 46 my ($from, @args) = @_;
110              
111 21         113 $from->TEST(@args);
112              
113 18         162 return $from;
114             }
115              
116             1;
117              
118              
119              
120             =head1 NAME
121              
122             Mars::Class - Class Declaration
123              
124             =cut
125              
126             =head1 ABSTRACT
127              
128             Class Declaration for Perl 5
129              
130             =cut
131              
132             =head1 SYNOPSIS
133              
134             package Person;
135              
136             use Mars::Class 'attr';
137              
138             attr 'fname';
139             attr 'lname';
140              
141             package Identity;
142              
143             use Mars::Role 'attr';
144              
145             attr 'id';
146             attr 'login';
147             attr 'password';
148              
149             sub EXPORT {
150             # explicitly declare routines to be consumed
151             ['id', 'login', 'password']
152             }
153              
154             package Authenticable;
155              
156             use Mars::Role;
157              
158             sub authenticate {
159             return true;
160             }
161              
162             sub AUDIT {
163             my ($self, $from) = @_;
164             # ensure the caller has a login and password when consumed
165             die "${from} missing the login attribute" if !$from->can('login');
166             die "${from} missing the password attribute" if !$from->can('password');
167             }
168              
169             sub BUILD {
170             my ($self, $data) = @_;
171             $self->{auth} = undef;
172             return $self;
173             }
174              
175             sub EXPORT {
176             # explicitly declare routines to be consumed
177             ['authenticate']
178             }
179              
180             package User;
181              
182             use Mars::Class;
183              
184             base 'Person';
185              
186             with 'Identity';
187              
188             attr 'email';
189              
190             test 'Authenticable';
191              
192             sub valid {
193             my ($self) = @_;
194             return $self->login && $self->password ? true : false;
195             }
196              
197             package main;
198              
199             my $user = User->new(
200             fname => 'Elliot',
201             lname => 'Alderson',
202             );
203              
204             # bless({fname => 'Elliot', lname => 'Alderson'}, 'User')
205              
206             =cut
207              
208             =head1 DESCRIPTION
209              
210             This package provides a class builder which when used causes the consumer to
211             inherit from L which provides object construction and
212             lifecycle L.
213              
214             =cut
215              
216             =head1 FUNCTIONS
217              
218             This package provides the following functions:
219              
220             =cut
221              
222             =head2 attr
223              
224             attr(Str $name) (Str)
225              
226             The attr function creates attribute accessors for the calling package. This
227             function is always exported unless a routine of the same name already exists.
228              
229             I>
230              
231             =over 4
232              
233             =item attr example 1
234              
235             package Example;
236              
237             use Mars::Class;
238              
239             attr 'name';
240              
241             # "Example"
242              
243             =back
244              
245             =cut
246              
247             =head2 base
248              
249             base(Str $name) (Str)
250              
251             The base function registers one or more base classes for the calling package.
252             This function is always exported unless a routine of the same name already
253             exists.
254              
255             I>
256              
257             =over 4
258              
259             =item base example 1
260              
261             package Entity;
262              
263             use Mars::Class;
264              
265             sub output {
266             return;
267             }
268              
269             package Example;
270              
271             use Mars::Class;
272              
273             base 'Entity';
274              
275             # "Example"
276              
277             =back
278              
279             =cut
280              
281             =head2 false
282              
283             false() (Bool)
284              
285             The false function returns a falsy boolean value which is designed to be
286             practically indistinguishable from the conventional numerical C<0> value. This
287             function is always exported unless a routine of the same name already exists.
288              
289             I>
290              
291             =over 4
292              
293             =item false example 1
294              
295             package Example;
296              
297             use Mars::Class;
298              
299             my $false = false;
300              
301             # 0
302              
303             =back
304              
305             =over 4
306              
307             =item false example 2
308              
309             package Example;
310              
311             use Mars::Class;
312              
313             my $true = !false;
314              
315             # 1
316              
317             =back
318              
319             =cut
320              
321             =head2 from
322              
323             from(Str $name) (Str)
324              
325             The from function registers one or more base classes for the calling package
326             and performs an L<"audit"|Mars::Kind/AUDIT>. This function is always exported
327             unless a routine of the same name already exists.
328              
329             I>
330              
331             =over 4
332              
333             =item from example 1
334              
335             package Entity;
336              
337             use Mars::Class;
338              
339             sub AUDIT {
340             my ($self, $from) = @_;
341             die "Missing startup" if !$from->can('startup');
342             die "Missing shutdown" if !$from->can('shutdown');
343             }
344              
345             package Example;
346              
347             use Mars::Class;
348              
349             attr 'startup';
350             attr 'shutdown';
351              
352             from 'Entity';
353              
354             # "Example"
355              
356             =back
357              
358             =cut
359              
360             =head2 mixin
361              
362             mixin(Str $name) (Str)
363              
364             The mixin function registers and consumes mixins for the calling package. This
365             function is always exported unless a routine of the same name already exists.
366              
367             I>
368              
369             =over 4
370              
371             =item mixin example 1
372              
373             package YesNo;
374              
375             use Mars::Mixin;
376              
377             sub no {
378             return 0;
379             }
380              
381             sub yes {
382             return 1;
383             }
384              
385             sub EXPORT {
386             ['no', 'yes']
387             }
388              
389             package Example;
390              
391             use Mars::Class;
392              
393             mixin 'YesNo';
394              
395             # "Example"
396              
397             =back
398              
399             =cut
400              
401             =head2 role
402              
403             role(Str $name) (Str)
404              
405             The role function registers and consumes roles for the calling package. This
406             function is always exported unless a routine of the same name already exists.
407              
408             I>
409              
410             =over 4
411              
412             =item role example 1
413              
414             package Ability;
415              
416             use Mars::Role;
417              
418             sub action {
419             return;
420             }
421              
422             package Example;
423              
424             use Mars::Class;
425              
426             role 'Ability';
427              
428             # "Example"
429              
430             =back
431              
432             =over 4
433              
434             =item role example 2
435              
436             package Ability;
437              
438             use Mars::Role;
439              
440             sub action {
441             return;
442             }
443              
444             sub EXPORT {
445             return ['action'];
446             }
447              
448             package Example;
449              
450             use Mars::Class;
451              
452             role 'Ability';
453              
454             # "Example"
455              
456             =back
457              
458             =cut
459              
460             =head2 test
461              
462             test(Str $name) (Str)
463              
464             The test function registers and consumes roles for the calling package and
465             performs an L<"audit"|Mars::Kind/AUDIT>, effectively allowing a role to act as
466             an interface. This function is always exported unless a routine of the same
467             name already exists.
468              
469             I>
470              
471             =over 4
472              
473             =item test example 1
474              
475             package Actual;
476              
477             use Mars::Role;
478              
479             package Example;
480              
481             use Mars::Class;
482              
483             test 'Actual';
484              
485             # "Example"
486              
487             =back
488              
489             =over 4
490              
491             =item test example 2
492              
493             package Actual;
494              
495             use Mars::Role;
496              
497             sub AUDIT {
498             die "Example is not an 'actual' thing" if $_[1]->isa('Example');
499             }
500              
501             package Example;
502              
503             use Mars::Class;
504              
505             test 'Actual';
506              
507             # "Example"
508              
509             =back
510              
511             =cut
512              
513             =head2 true
514              
515             true() (Bool)
516              
517             The true function returns a truthy boolean value which is designed to be
518             practically indistinguishable from the conventional numerical C<1> value. This
519             function is always exported unless a routine of the same name already exists.
520              
521             I>
522              
523             =over 4
524              
525             =item true example 1
526              
527             package Example;
528              
529             use Mars::Class;
530              
531             my $true = true;
532              
533             # 1
534              
535             =back
536              
537             =over 4
538              
539             =item true example 2
540              
541             package Example;
542              
543             use Mars::Class;
544              
545             my $false = !true;
546              
547             # 0
548              
549             =back
550              
551             =cut
552              
553             =head2 with
554              
555             with(Str $name) (Str)
556              
557             The with function registers and consumes roles for the calling package. This
558             function is an alias of the L function and will perform an
559             L<"audit"|Mars::Kind/AUDIT> if present. This function is always exported unless
560             a routine of the same name already exists.
561              
562             I>
563              
564             =over 4
565              
566             =item with example 1
567              
568             package Understanding;
569              
570             use Mars::Role;
571              
572             sub knowledge {
573             return;
574             }
575              
576             package Example;
577              
578             use Mars::Class;
579              
580             with 'Understanding';
581              
582             # "Example"
583              
584             =back
585              
586             =over 4
587              
588             =item with example 2
589              
590             package Understanding;
591              
592             use Mars::Role;
593              
594             sub knowledge {
595             return;
596             }
597              
598             sub EXPORT {
599             return ['knowledge'];
600             }
601              
602             package Example;
603              
604             use Mars::Class;
605              
606             with 'Understanding';
607              
608             # "Example"
609              
610             =back
611              
612             =cut
613              
614             =head1 AUTHORS
615              
616             Awncorp, C
617              
618             =cut