File Coverage

blib/lib/Mars/Class.pm
Criterion Covered Total %
statement 89 89 100.0
branch 18 18 100.0
condition 17 18 94.4
subroutine 34 34 100.0
pod 5 5 100.0
total 163 164 99.3


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