Commit | Line | Data |
75d07914 |
1 | package # hide from PAUSE |
c0e7b4e5 |
2 | DBIx::Class::Componentised; |
227d4dee |
3 | |
bf5ecff9 |
4 | use strict; |
5 | use warnings; |
6 | |
147dd158 |
7 | use Class::C3; |
c037c03a |
8 | use Class::Inspector; |
4d87db01 |
9 | use Carp::Clan qw/DBIx::Class/; |
147dd158 |
10 | |
227d4dee |
11 | sub inject_base { |
12 | my ($class, $target, @to_inject) = @_; |
13 | { |
14 | no strict 'refs'; |
eb47985e |
15 | foreach my $to (reverse @to_inject) { |
df88a29c |
16 | my @comps = qw(DigestColumns ResultSetManager Ordered UTF8Columns); |
17 | # Add components here that need to be loaded before Core |
18 | foreach my $first_comp (@comps) { |
19 | if ($to eq 'DBIx::Class::Core' && |
20 | $target->isa("DBIx::Class::${first_comp}")) { |
21 | warn "Possible incorrect order of components in ". |
22 | "${target}::load_components($first_comp) call: Core loaded ". |
23 | "before $first_comp. See the documentation for ". |
24 | "DBIx::Class::$first_comp for more information"; |
25 | } |
26 | } |
27 | unshift( @{"${target}::ISA"}, $to ) |
28 | unless ($target eq $to || $target->isa($to)); |
eb47985e |
29 | } |
227d4dee |
30 | } |
20518cb4 |
31 | |
32 | # Yes, this is hack. But it *does* work. Please don't submit tickets about |
33 | # it on the basis of the comments in Class::C3, the author was on #dbix-class |
34 | # while I was implementing this. |
35 | |
9a15732e |
36 | my $table = { Class::C3::_dump_MRO_table }; |
75a23b3e |
37 | eval "package $target; import Class::C3;" unless exists $table->{$target}; |
227d4dee |
38 | } |
39 | |
40 | sub load_components { |
41 | my $class = shift; |
7411204b |
42 | my $base = $class->component_base_class; |
6db94aca |
43 | my @comp = map { /^\+(.*)$/ ? $1 : "${base}::$_" } grep { $_ !~ /^#/ } @_; |
227d4dee |
44 | $class->_load_components(@comp); |
971c0085 |
45 | Class::C3::reinitialize(); |
227d4dee |
46 | } |
47 | |
48 | sub load_own_components { |
49 | my $class = shift; |
50 | my @comp = map { "${class}::$_" } grep { $_ !~ /^#/ } @_; |
51 | $class->_load_components(@comp); |
52 | } |
53 | |
54 | sub _load_components { |
55 | my ($class, @comp) = @_; |
56 | foreach my $comp (@comp) { |
c037c03a |
57 | $class->ensure_class_loaded($comp); |
227d4dee |
58 | } |
59 | $class->inject_base($class => @comp); |
60 | } |
61 | |
efe6365b |
62 | # Given a class name, tests to see if it is already loaded or otherwise |
63 | # defined. If it is not yet loaded, the package is require'd, and an exception |
64 | # is thrown if the class is still not loaded. |
65 | # |
c037c03a |
66 | # TODO: handle ->has_many('rel', 'Class'...) instead of |
67 | # ->has_many('rel', 'Some::Schema::Class'...) |
9d3d92ab |
68 | # |
69 | # BUG: For some reason, packages with syntax errors are added to %INC on |
70 | # require |
c037c03a |
71 | sub ensure_class_loaded { |
72 | my ($class, $f_class) = @_; |
175e2616 |
73 | return if Class::Inspector->loaded($f_class); |
9d3d92ab |
74 | eval "require $f_class"; # require needs a bareword or filename |
4d87db01 |
75 | if ($@) { |
76 | if ($class->can('throw_exception')) { |
77 | $class->throw_exception($@); |
78 | } else { |
79 | croak $@; |
80 | } |
81 | } |
efe6365b |
82 | } |
83 | |
84 | # Returns true if the specified class is installed or already loaded, false |
85 | # otherwise |
86 | sub ensure_class_found { |
87 | my ($class, $f_class) = @_; |
88 | return Class::Inspector->loaded($f_class) || |
89 | Class::Inspector->installed($f_class); |
90 | } |
91 | |
92 | # Returns a true value if the specified class is installed and loaded |
93 | # successfully, throws an exception if the class is found but not loaded |
94 | # successfully, and false if the class is not installed |
95 | sub load_optional_class { |
96 | my ($class, $f_class) = @_; |
97 | if ($class->ensure_class_found($f_class)) { |
98 | $class->ensure_class_loaded($f_class); |
99 | return 1; |
100 | } else { |
101 | return 0; |
102 | } |
c037c03a |
103 | } |
104 | |
227d4dee |
105 | 1; |