inline symbol table tweaking in ClassData
[catagits/Catalyst-Runtime.git] / lib / Catalyst / ClassData.pm
1 package Catalyst::ClassData;
2
3 use Moose::Role;
4 use Class::MOP;
5 use Scalar::Util 'blessed';
6
7 sub mk_classdata {
8   my ($class, $attribute) = @_;
9   confess("mk_classdata() is a class method, not an object method")
10     if blessed $class;
11
12   my $slot = '$'.$attribute;
13   my $accessor =  sub {
14     my $meta = $_[0]->meta;
15     my $pkg = ref $_[0] || $_[0];
16     if(@_ > 1){
17       $meta->namespace->{$attribute} = \$_[1];
18       return $_[1];
19     }
20
21     # tighter version of
22     # if ( $meta->has_package_symbol($slot) ) {
23     #   return ${ $meta->get_package_symbol($slot) };
24     # }
25     no strict 'refs';
26     my $v = *{"${pkg}::${attribute}"}{SCALAR};
27     if (defined ${$v}) {
28      return ${$v};
29     } else {
30       foreach my $super ( $meta->linearized_isa ) {
31         # tighter version of same after
32         # my $super_meta = Moose::Meta::Class->initialize($super);
33         my $v = *{"${super}::${attribute}"}{SCALAR};
34         if (defined ${$v}) {
35           return ${$v};
36         }
37       }
38     }
39     return;
40   };
41
42   confess("Failed to create accessor: $@ ")
43     unless ref $accessor eq 'CODE';
44
45   my $meta = $class->meta;
46   my $immutable_options;
47   if( $meta->is_immutable ){
48     $immutable_options = $meta->get_immutable_options;
49     $meta->make_mutable;
50   }
51   my $alias = "_${attribute}_accessor";
52   $meta->add_method($alias, $accessor);
53   $meta->add_method($attribute, $accessor);
54   if(defined $immutable_options){
55     $meta->make_immutable($immutable_options);
56   }
57   $class->$attribute($_[2]) if(@_ > 2);
58   return $accessor;
59 }
60
61 1;
62
63 __END__
64
65
66 =head1 NAME
67
68 Catalyst::ClassData - Class data acessors
69
70 =head1 METHODS
71
72 =head2 mk_classdata $name, $optional_value
73
74 A moose-safe clone of L<Class::Data::Inheritable> that borrows some ideas from
75 L<Class::Accessor::Grouped>;
76
77 =head1 AUTHOR
78
79 Guillermo Roditi
80
81 =head1 COPYRIGHT
82
83 This program is free software, you can redistribute it and/or modify it under
84 the same terms as Perl itself.
85
86 =cut