1package Gantry::Utils::ModelHelper;
2use strict; use warnings;
3
4sub import {
5    my $class   = shift;
6
7    my $callpkg = caller( 0 );
8
9    foreach my $method ( @_ ) {
10        if ( $method eq 'auth_db_Main' ) {
11            no strict;
12            *{ "$callpkg\::db_Main" } = \&{ "$class\::auth_db_Main" };
13        }
14        else {
15            no strict;
16            *{ "$callpkg\::$method" } = \&{ "$class\::$method" };
17        }
18    }
19} # END of import
20
21#----------------------------------------------------------------------
22# db_Main
23# compatible with Class::DBI and Gantry::Plugins::DBIxClassConn
24#----------------------------------------------------------------------
25sub db_Main {
26    my $invocant = shift;
27    my $class    = ( ref $invocant ) ? ref $invocant : $invocant;
28
29    my $dbh;
30
31    my $helper = Gantry::Utils::DBConnHelper->get_subclass();
32
33    $dbh       = $helper->get_dbh();
34
35    if ( not $dbh ) {
36        my $conn_info  = $helper->get_conn_info();
37
38        my $db_options = $class->get_db_options();
39
40        $db_options->{AutoCommit} = 0 unless defined $db_options->{AutoCommit};
41
42        $dbh = DBI->connect(
43                $conn_info->{ 'dbconn' },
44                $conn_info->{ 'dbuser' },
45                $conn_info->{ 'dbpass' },
46                $db_options
47        );
48        $helper->set_dbh( $dbh );
49    }
50
51    return $dbh;
52
53} # end db_Main
54
55#----------------------------------------------------------------------
56# auth_db_Main
57# compatible with Class::DBI and Gantry::Plugins::DBIxClassConn
58#----------------------------------------------------------------------
59sub auth_db_Main {
60    my $invocant = shift;
61    my $class    = ( ref $invocant ) ? ref $invocant : $invocant;
62
63    my $auth_dbh;
64
65    my $helper   = Gantry::Utils::DBConnHelper->get_subclass();
66
67    $auth_dbh    = $helper->get_auth_dbh();
68
69    if ( not $auth_dbh ) {
70        my $auth_conn_info  = $helper->get_auth_conn_info();
71
72        my $db_options = $class->get_db_options();
73
74        $db_options->{AutoCommit} = 0 unless defined $db_options->{AutoCommit};
75
76        $auth_dbh = DBI->connect(
77                $auth_conn_info->{ 'auth_dbconn' },
78                $auth_conn_info->{ 'auth_dbuser' },
79                $auth_conn_info->{ 'auth_dbpass' },
80                $db_options
81        );
82        $helper->set_auth_dbh( $auth_dbh );
83    }
84
85    return $auth_dbh;
86
87} # end auth_db_Main
88
89#-------------------------------------------------
90# $class->get_listing
91#-------------------------------------------------
92sub get_listing {
93    my ( $class, $params ) = @_;
94
95    my $f_display_fields = [];
96    eval {
97        $f_display_fields = $class->get_foreign_display_fields;
98    };
99
100    if ( $params->{order_by} ) {
101        return $class->retrieve_all( order_by => $params->{order_by} );
102    }
103    elsif ( $f_display_fields ) {
104        return $class->retrieve_all(
105            order_by => join( ', ', @{ $f_display_fields } )
106        );
107    }
108    else {
109        return $class->retrieve_all( );
110    }
111
112}
113
114#-------------------------------------------------
115# $class->retrieve_all_for_main_listing
116# DEPRECATED
117#-------------------------------------------------
118sub retrieve_all_for_main_listing {
119    my ( $class, $order_fields ) = ( shift, shift );
120
121    $order_fields ||= join ', ', @{ $class->get_foreign_display_fields };
122
123    return( $class->retrieve_all( order_by => $order_fields ) );
124
125} # retrieve_all_for_main_listing
126
127#-------------------------------------------------
128# $class->get_form_selctions
129#-------------------------------------------------
130sub get_form_selections {
131    my $class = shift;
132
133    my %retval;
134
135    # foreach foreign key get a selection list
136    FOREIGN_TABLE:
137    foreach my $foreign_table ( $class->get_foreign_tables() ) {
138
139        my $short_table_name = $foreign_table;
140        $short_table_name    =~ s/.*:://;
141
142        my $foreigners;
143
144        eval {
145            $foreigners = $foreign_table->get_foreign_display_fields();
146        };
147        if ( $@ ) {
148            warn $@;
149            next FOREIGN_TABLE;
150        }
151
152        my $order_by         = join ', ', @{ $foreigners };
153
154        # get all rows in foreign table ordered by foreign display
155        my @foreign_display_rows = $foreign_table->retrieve_all(
156                { order_by => $order_by }
157        );
158
159        # push into returnable hash
160        my @items;
161        push( @items, { value => '', label => '- Select -' } );
162
163        foreach my $item ( @foreign_display_rows ) {
164
165            my $label;
166
167            eval {
168                $label = $item->foreign_display();
169            };
170            warn "    ERROR for " . $item->id() . " $@" if $@;
171
172            push @items, {
173                value => $item->id(),
174                label => $label || '',
175            };
176        }
177
178        $retval{$short_table_name} = \@items;
179    }
180
181    return( \%retval );
182
183} # end get_form_selections
184
1851;
186
187=head1 NAME
188
189Gantry::Utils::ModelHelper - mixin for model base classes
190
191=head1 SYNOPSIS
192
193    use Gantry::Utils::ModelHelper qw(
194        db_Main
195        get_listing
196        get_form_selections
197    );
198
199    sub get_db_options {
200        return {};  # put your default options here
201        # consider calling __PACKAGE->_default_attributes
202    }
203
204=head1 DESCRIPTION
205
206This module provides mixin methods commonly needed by model base classes.
207Note that you must request the methods you want for the mixin scheme to
208work.  Also note that you can request either db_Main or auth_db_Main, but
209not both.  Whichever one you choose will be exported as db_Main in your
210package.
211
212=head1 METHODS
213
214=over 4
215
216=item db_Main
217
218This method returns a valid dbh using the scheme described in
219Gantry::Docs::DBConn.  It is compatible with Class::DBI and
220Gantry::Plugins::DBIxClassConn (the later is a mixin which allows
221easy access to a DBIx::Schema object for controllers).
222
223=item auth_db_Main
224
225This method is exported as db_Main and works with the scheme described
226in Gantry::Docs::DBConn.  It too is compatible with Class::DBI and
227Gantry::Plugins::DBIxClassConn.
228
229I will repeat, if you ask for this method in your use statement:
230
231    use lib/Gantry/Utils/ModelHelper qw( auth_db_Main ... );
232
233it will come into your namespace as db_Main.
234
235=item get_form_selections
236
237This method gives you a selection list for each foriegn key in your
238table.  The lists come to you as a single hash keyed by the table names
239of the foreign keys.  The values in the hash are ready for use
240by form.tt as options on the field (whose type should be select).
241Example:
242
243    {
244        status => [
245            { value => 2, label => 'Billed' },
246            { value => 1, label => 'In Progress' },
247            { value => 3, label => 'Paid' },
248        ],
249        other_table => [ ... ],
250    }
251
252To use this method, your models must implement these class methods:
253
254=over 4
255
256=item get_foreign_tables
257
258(Must be implemented by the model on which get_form_selections is called.)
259Returns a list of the fully qualified package names of the models
260of this table's foreign keys.  Example:
261
262    sub get_foreign_tables {
263        return qw(
264            Apps::AppName::Model::users
265            Apps::AppName::Model::other_table
266        );
267    }
268
269=item get_foreign_display_fields
270
271(Must be implemented by all the models of this table's foreign keys.)
272Returns an array reference whose elements are the names of the columns
273which will appear on the screen in the selection list.  Example:
274
275    sub get_foreign_display_fields {
276        return [ qw( last_name first_name ) ];
277    }
278
279=back
280
281=item get_listing
282
283Replacement for retrieve_all_for_main_listing.
284
285Returns a list of row objects (one for each row in the table).  The
286ORDER BY clause is either the same as the foreign_display columns
287or chosen by you.  If you want to supply the order do it like this:
288
289    my @rows = $MODEL->get_listing ( { order_by => 'last, first' } );
290
291Note that your order_by will be used AS IS, so it must be a valid SQL
292ORDER BY clause, but feel free to include DESC or anything else you and SQL
293like.
294
295=item retrieve_all_for_main_listing
296
297DEPRECATED use get_listing instead
298
299Returns a list of row objects (one for each row in the table) in order
300by their foreign_display columns.
301
302=back
303
304=head1 AUTHOR
305
306Phil Crow <philcrow2000@yahoo.com>
307
308=head1 COPYRIGHT and LICENSE
309
310Copyright (c) 2006, Phil Crow
311
312This library is free software; you can redistribute it and/or modify
313it under the same terms as Perl itself, either Perl version 5.8.6 or,
314at your option, any later version of Perl 5 you may have available.
315
316=cut
317