initial checkin for UserStamp
[dbsrgits/DBIx-Class-UserStamp.git] / lib / DBIx / Class / UserStamp.pm
CommitLineData
7bde9079 1package DBIx::Class::UserStamp;
2
3use base qw(DBIx::Class);
4
5use warnings;
6use strict;
7
8our $VERSION = '0.10';
9
10__PACKAGE__->mk_classdata(
11 '__column_userstamp_triggers' => {
12 on_update => [], on_create => []
13 }
14);
15
16=head1 NAME
17
18DBIx::Class::UserStamp - Automatically set update and create user id fields
19
20=head1 DESCRIPTION
21
22Automatically set fields on 'update' and 'create' that hold user id
23values in a table. This can be used for any user id based
24field that needs trigger like functionality when a record is
25added or updated.
26
27=head1 SYNOPSIS
28
29 package MyApp::Schema;
30
31 __PACKAGE__->mk_group_accessors('simple' => qw/current_user_id/);
32
33
34 package MyApp::Model::MyAppDB;
35 use Moose;
36
37 around 'build_per_context_instance' => sub {
38 my ($meth, $self) = (shift, shift);
39 my ($c) = @_; # There are other params but we dont care about them
40 my $new = bless({ %$self }, ref($self));
41 my $user_info = $c->_user_in_session;
42 my $user = $new->schema->resultset('User')->new_result({ %$user_info });
43 $new->schema->current_user_id($user->id) if (defined $user_info);
44 return $new;
45 };
46
47
48 package MyApp::Schema::SomeTable;
49
50 __PACKAGE__->load_components(qw( UserStamp ... Core ));
51
52 __PACKAGE__->add_columns(
53 id => { data_type => 'integer' },
54 u_created => { data_type => 'int', store_user_on_create => 1 },
55 u_updated => { data_type => 'int',
56 store_user_on_create => 1, store_user_on_update => 1 },
57 );
58
59Now, any update or create actions will update the specified columns with the
60current user_id, using the current_user_id accessor.
61
62This is effectively trigger emulation to ease user id field insertion
63
64=cut
65
66sub add_columns {
67 my $self = shift;
68
69 # Add everything else, get everything setup, and then process
70 $self->next::method(@_);
71
72 my @update_columns = ();
73 my @create_columns = ();
74
75 foreach my $column ( $self->columns ) {
76 my $info = $self->column_info($column);
77 if ( $info->{store_user_on_update} ) {
78 push @update_columns, $column;
79 }
80 if ( $info->{store_user_on_create} ) {
81 push @create_columns, $column;
82 }
83 }
84 if ( @update_columns or @create_columns ) {
85 my $triggers = {
86 on_update => [ @update_columns ],
87 on_create => [ @create_columns ],
88 };
89 $self->__column_userstamp_triggers($triggers);
90 }
91}
92
93sub insert {
94 my $self = shift;
95 my $attrs = shift;
96
97 my $user_id = $self->get_current_user_id;
98
99 my @columns = @{ $self->__column_userstamp_triggers()->{on_create} };
100
101 foreach my $column ( @columns ) {
102 next if defined $self->get_column( $column );
103 my $accessor = $self->column_info($column)->{accessor} || $column;
104 $self->$accessor($user_id);
105 }
106
107 return $self->next::method(@_);
108}
109
110sub update {
111 my $self = shift;
112
113 my $user_id = $self->get_current_user_id;
114 my %dirty = $self->get_dirty_columns();
115 my @columns = @{ $self->__column_userstamp_triggers()->{on_update} };
116
117 foreach my $column ( @columns ) {
118 next if exists $dirty{ $column };
119 my $accessor = $self->column_info($column)->{accessor} || $column;
120 $self->$accessor($user_id);
121 }
122
123 return $self->next::method(@_);
124}
125
126=head1 METHODS
127
128=head2 get_current_user_id
129
130This method is meant to be overridden. The default is to return a
131schema accessor called current_user_id which should be populated as such.
132
133=cut
134sub get_current_user_id { shift->result_source->schema->current_user_id }
135
136=head1 AUTHOR
137
138 Matt S. Trout <mst@shadowcatsystems.co.uk>
139
140=head1 CONTRIBUTOR
141
142 John Goulah <jgoulah@cpan.org>
143
144=head1 COPYRIGHT
145
146This program is free software; you can redistribute
147it and/or modify it under the same terms as Perl itself.
148
149=cut
150
1511;