diff options
Diffstat (limited to 'extensions/UserProfile/Extension.pm')
-rw-r--r-- | extensions/UserProfile/Extension.pm | 796 |
1 files changed, 367 insertions, 429 deletions
diff --git a/extensions/UserProfile/Extension.pm b/extensions/UserProfile/Extension.pm index 9171b942d..cc8be3f1f 100644 --- a/extensions/UserProfile/Extension.pm +++ b/extensions/UserProfile/Extension.pm @@ -29,44 +29,43 @@ our $VERSION = '1'; # BEGIN { - *Bugzilla::User::last_activity_ts = \&_user_last_activity_ts; - *Bugzilla::User::set_last_activity_ts = \&_user_set_last_activity_ts; - *Bugzilla::User::last_statistics_ts = \&_user_last_statistics_ts; - *Bugzilla::User::clear_last_statistics_ts = \&_user_clear_last_statistics_ts; - *Bugzilla::User::address = \&_user_address; + *Bugzilla::User::last_activity_ts = \&_user_last_activity_ts; + *Bugzilla::User::set_last_activity_ts = \&_user_set_last_activity_ts; + *Bugzilla::User::last_statistics_ts = \&_user_last_statistics_ts; + *Bugzilla::User::clear_last_statistics_ts = \&_user_clear_last_statistics_ts; + *Bugzilla::User::address = \&_user_address; } -sub _user_last_activity_ts { $_[0]->{last_activity_ts} } -sub _user_last_statistics_ts { $_[0]->{last_statistics_ts} } +sub _user_last_activity_ts { $_[0]->{last_activity_ts} } +sub _user_last_statistics_ts { $_[0]->{last_statistics_ts} } + sub _user_address { - my $mode = Bugzilla->usage_mode; + my $mode = Bugzilla->usage_mode; - Email::Address->disable_cache if any { $mode == $_ } USAGE_MODE_CMDLINE, USAGE_MODE_TEST, USAGE_MODE_EMAIL; - return Email::Address->new(undef, $_[0]->email); + Email::Address->disable_cache + if any { $mode == $_ } USAGE_MODE_CMDLINE, USAGE_MODE_TEST, USAGE_MODE_EMAIL; + return Email::Address->new(undef, $_[0]->email); } -sub _user_set_last_activity_ts { - my ($self, $value) = @_; - $self->set('last_activity_ts', $_[1]); +sub _user_set_last_activity_ts { + my ($self, $value) = @_; + $self->set('last_activity_ts', $_[1]); - # we update the database directly to avoid audit_log entries - Bugzilla->dbh->do( - "UPDATE profiles SET last_activity_ts = ? WHERE userid = ?", - undef, - $value, $self->id); - Bugzilla->memcached->clear({ table => 'profiles', id => $self->id }); + # we update the database directly to avoid audit_log entries + Bugzilla->dbh->do("UPDATE profiles SET last_activity_ts = ? WHERE userid = ?", + undef, $value, $self->id); + Bugzilla->memcached->clear({table => 'profiles', id => $self->id}); } sub _user_clear_last_statistics_ts { - my ($self) = @_; - $self->set('last_statistics_ts', undef); - - # we update the database directly to avoid audit_log entries - Bugzilla->dbh->do( - "UPDATE profiles SET last_statistics_ts = NULL WHERE userid = ?", - undef, - $self->id); - Bugzilla->memcached->clear({ table => 'profiles', id => $self->id }); + my ($self) = @_; + $self->set('last_statistics_ts', undef); + + # we update the database directly to avoid audit_log entries + Bugzilla->dbh->do( + "UPDATE profiles SET last_statistics_ts = NULL WHERE userid = ?", + undef, $self->id); + Bugzilla->memcached->clear({table => 'profiles', id => $self->id}); } # @@ -76,327 +75,331 @@ sub _user_clear_last_statistics_ts { sub request_cleanup { Email::Address->purge_cache } sub bug_after_create { - my ($self, $args) = @_; - $self->_bug_touched($args); + my ($self, $args) = @_; + $self->_bug_touched($args); } sub bug_after_update { - my ($self, $args) = @_; - $self->_bug_touched($args); + my ($self, $args) = @_; + $self->_bug_touched($args); } sub _bug_touched { - my ($self, $args) = @_; - my $bug = $args->{bug}; - - my $user = Bugzilla->user; - my ($assigned_to, $qa_contact); - - # bug update - if (exists $args->{changes}) { - return unless - scalar(keys %{ $args->{changes} }) - || exists $args->{bug}->{added_comments}; - - # if the assignee or qa-contact is changed to someone other than the - # current user, update them - if (exists $args->{changes}->{assigned_to} - && $args->{changes}->{assigned_to}->[1] ne $user->login) - { - $assigned_to = $bug->assigned_to; - } - if (exists $args->{changes}->{qa_contact} - && ($args->{changes}->{qa_contact}->[1] || '') ne $user->login) - { - $qa_contact = $bug->qa_contact; - } - - # if the product is changed, we need to recount everyone involved with - # this bug - if (exists $args->{changes}->{product}) { - tag_for_recount_from_bug($bug->id); - } - + my ($self, $args) = @_; + my $bug = $args->{bug}; + + my $user = Bugzilla->user; + my ($assigned_to, $qa_contact); + + # bug update + if (exists $args->{changes}) { + return + unless scalar(keys %{$args->{changes}}) + || exists $args->{bug}->{added_comments}; + + # if the assignee or qa-contact is changed to someone other than the + # current user, update them + if (exists $args->{changes}->{assigned_to} + && $args->{changes}->{assigned_to}->[1] ne $user->login) + { + $assigned_to = $bug->assigned_to; } - # new bug - else { - # if the assignee or qa-contact is created set to someone other than - # the current user, update them - if ($bug->assigned_to->id != $user->id) { - $assigned_to = $bug->assigned_to; - } - if ($bug->qa_contact && $bug->qa_contact->id != $user->id) { - $qa_contact = $bug->qa_contact; - } + if (exists $args->{changes}->{qa_contact} + && ($args->{changes}->{qa_contact}->[1] || '') ne $user->login) + { + $qa_contact = $bug->qa_contact; } - my $dbh = Bugzilla->dbh; - $dbh->bz_start_transaction(); + # if the product is changed, we need to recount everyone involved with + # this bug + if (exists $args->{changes}->{product}) { + tag_for_recount_from_bug($bug->id); + } - # update user's last_activity_ts + } + + # new bug + else { + # if the assignee or qa-contact is created set to someone other than + # the current user, update them + if ($bug->assigned_to->id != $user->id) { + $assigned_to = $bug->assigned_to; + } + if ($bug->qa_contact && $bug->qa_contact->id != $user->id) { + $qa_contact = $bug->qa_contact; + } + } + + my $dbh = Bugzilla->dbh; + $dbh->bz_start_transaction(); + + # update user's last_activity_ts + eval { + $user->set_last_activity_ts($args->{timestamp}); + $self->_recalc_remove($user); + }; + if ($@) { + warn $@; + $self->_recalc_insert($user); + } + + # clear the last_statistics_ts for assignee/qa-contact to force a recount + # at the next poll + if ($assigned_to) { eval { - $user->set_last_activity_ts($args->{timestamp}); - $self->_recalc_remove($user); + $assigned_to->clear_last_statistics_ts(); + $self->_recalc_remove($assigned_to); }; if ($@) { - warn $@; - $self->_recalc_insert($user); + warn $@; + $self->_recalc_insert($assigned_to); } - - # clear the last_statistics_ts for assignee/qa-contact to force a recount - # at the next poll - if ($assigned_to) { - eval { - $assigned_to->clear_last_statistics_ts(); - $self->_recalc_remove($assigned_to); - }; - if ($@) { - warn $@; - $self->_recalc_insert($assigned_to); - } - } - if ($qa_contact) { - eval { - $qa_contact->clear_last_statistics_ts(); - $self->_recalc_remove($qa_contact); - }; - if ($@) { - warn $@; - $self->_recalc_insert($qa_contact); - } + } + if ($qa_contact) { + eval { + $qa_contact->clear_last_statistics_ts(); + $self->_recalc_remove($qa_contact); + }; + if ($@) { + warn $@; + $self->_recalc_insert($qa_contact); } + } - $dbh->bz_commit_transaction(); + $dbh->bz_commit_transaction(); } sub _recalc_insert { - my ($self, $user) = @_; - Bugzilla->dbh->do( - "INSERT IGNORE INTO profiles_statistics_recalc SET user_id=?", - undef, $user->id - ); + my ($self, $user) = @_; + Bugzilla->dbh->do("INSERT IGNORE INTO profiles_statistics_recalc SET user_id=?", + undef, $user->id); } sub _recalc_remove { - my ($self, $user) = @_; - Bugzilla->dbh->do( - "DELETE FROM profiles_statistics_recalc WHERE user_id=?", - undef, $user->id - ); + my ($self, $user) = @_; + Bugzilla->dbh->do("DELETE FROM profiles_statistics_recalc WHERE user_id=?", + undef, $user->id); } sub object_end_of_create { - my ($self, $args) = @_; - $self->_object_touched($args); + my ($self, $args) = @_; + $self->_object_touched($args); } sub object_end_of_update { - my ($self, $args) = @_; - $self->_object_touched($args); + my ($self, $args) = @_; + $self->_object_touched($args); } sub _object_touched { - my ($self, $args) = @_; - my $object = $args->{object} - or return; - return if exists $args->{changes} && !scalar(keys %{ $args->{changes} }); - - if ($object->isa('Bugzilla::Attachment')) { - # if an attachment is created or updated, that counts as user activity - my $user = Bugzilla->user; - my $timestamp = Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)'); - eval { - $user->set_last_activity_ts($timestamp); - $self->_recalc_remove($user); - }; - if ($@) { - warn $@; - $self->_recalc_insert($user); - } - } - elsif ($object->isa('Bugzilla::Product') && exists $args->{changes}->{name}) { - # if a product is renamed by an admin, rename in the - # profiles_statistics_products table - Bugzilla->dbh->do( - "UPDATE profiles_statistics_products SET product=? where product=?", - undef, - $args->{changes}->{name}->[1], $args->{changes}->{name}->[0], - ); + my ($self, $args) = @_; + my $object = $args->{object} or return; + return if exists $args->{changes} && !scalar(keys %{$args->{changes}}); + + if ($object->isa('Bugzilla::Attachment')) { + + # if an attachment is created or updated, that counts as user activity + my $user = Bugzilla->user; + my $timestamp = Bugzilla->dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)'); + eval { + $user->set_last_activity_ts($timestamp); + $self->_recalc_remove($user); + }; + if ($@) { + warn $@; + $self->_recalc_insert($user); } + } + elsif ($object->isa('Bugzilla::Product') && exists $args->{changes}->{name}) { + + # if a product is renamed by an admin, rename in the + # profiles_statistics_products table + Bugzilla->dbh->do( + "UPDATE profiles_statistics_products SET product=? where product=?", + undef, + $args->{changes}->{name}->[1], + $args->{changes}->{name}->[0], + ); + } } sub reorg_move_bugs { - my ($self, $args) = @_; - my $bug_ids = $args->{bug_ids}; - printf "Touching user profile data for %s bugs.\n", scalar(@$bug_ids); - my $count = 0; - foreach my $bug_id (@$bug_ids) { - $count += tag_for_recount_from_bug($bug_id); - } - print "Updated $count users.\n"; + my ($self, $args) = @_; + my $bug_ids = $args->{bug_ids}; + printf "Touching user profile data for %s bugs.\n", scalar(@$bug_ids); + my $count = 0; + foreach my $bug_id (@$bug_ids) { + $count += tag_for_recount_from_bug($bug_id); + } + print "Updated $count users.\n"; } sub merge_users_before { - my ($self, $args) = @_; - my ($old_id, $new_id) = @$args{qw(old_id new_id)}; - # when users are merged, we have to delete all the statistics for both users - # we'll recalcuate the stats after the merge - print "deleting user profile statistics for $old_id and $new_id\n"; - my $dbh = Bugzilla->dbh; - foreach my $table (qw( profiles_statistics profiles_statistics_status profiles_statistics_products )) { - $dbh->do("DELETE FROM $table WHERE " . $dbh->sql_in('user_id', [ $old_id, $new_id ])); - } + my ($self, $args) = @_; + my ($old_id, $new_id) = @$args{qw(old_id new_id)}; + + # when users are merged, we have to delete all the statistics for both users + # we'll recalcuate the stats after the merge + print "deleting user profile statistics for $old_id and $new_id\n"; + my $dbh = Bugzilla->dbh; + foreach my $table ( + qw( profiles_statistics profiles_statistics_status profiles_statistics_products ) + ) + { + $dbh->do( + "DELETE FROM $table WHERE " . $dbh->sql_in('user_id', [$old_id, $new_id])); + } } sub merge_users_after { - my ($self, $args) = @_; - my $new_id = $args->{new_id}; - print "generating user profile statistics $new_id\n"; - update_statistics_by_user($new_id); + my ($self, $args) = @_; + my $new_id = $args->{new_id}; + print "generating user profile statistics $new_id\n"; + update_statistics_by_user($new_id); } sub webservice_user_get { - my ($self, $args) = @_; - my ($service, $users) = @$args{qw(webservice users)}; - - my $dbh = Bugzilla->dbh; - my $ids = [ - map { blessed($_->{id}) ? $_->{id}->value : $_->{id} } - grep { exists $_->{id} } - @$users - ]; - return unless @$ids; - my $timestamps = $dbh->selectall_hashref( - "SELECT userid,last_activity_ts FROM profiles WHERE " . $dbh->sql_in('userid', $ids), - 'userid', - ); - foreach my $user (@$users) { - my $id = blessed($user->{id}) ? $user->{id}->value : $user->{id}; - $user->{last_activity} = $service->type('dateTime', $timestamps->{$id}->{last_activity_ts}); - } + my ($self, $args) = @_; + my ($service, $users) = @$args{qw(webservice users)}; + + my $dbh = Bugzilla->dbh; + my $ids = [map { blessed($_->{id}) ? $_->{id}->value : $_->{id} } + grep { exists $_->{id} } @$users]; + return unless @$ids; + my $timestamps = $dbh->selectall_hashref( + "SELECT userid,last_activity_ts FROM profiles WHERE " + . $dbh->sql_in('userid', $ids), + 'userid', + ); + foreach my $user (@$users) { + my $id = blessed($user->{id}) ? $user->{id}->value : $user->{id}; + $user->{last_activity} + = $service->type('dateTime', $timestamps->{$id}->{last_activity_ts}); + } } sub template_before_create { - my ($self, $args) = @_; - $args->{config}->{FILTERS}->{timeago} = sub { - my ($time_str) = @_; - return time_ago(datetime_from($time_str, 'UTC')); - }; + my ($self, $args) = @_; + $args->{config}->{FILTERS}->{timeago} = sub { + my ($time_str) = @_; + return time_ago(datetime_from($time_str, 'UTC')); + }; } sub page_before_template { - my ($self, $args) = @_; - my ($vars, $page) = @$args{qw(vars page_id)}; - return unless $page eq 'user_profile.html'; - my $user = Bugzilla->user; - - # determine user to display - my ($target, $login); - my $input = Bugzilla->input_params; - if (my $user_id = $input->{user_id}) { - # load from user_id - $user_id = 0 if $user_id =~ /\D/; - $target = Bugzilla::User->check({ id => $user_id }); - } else { - # loading from login name requires authentication - Bugzilla->login(LOGIN_REQUIRED); - $login = $input->{login}; - if (!$login) { - # show current user's profile by default - $target = $user; - } else { - my $limit = Bugzilla->params->{'maxusermatches'} + 1; - my $users = Bugzilla::User::match($login, $limit, 1); - if (scalar(@$users) == 1) { - # always allow singular matches without confirmation - $target = $users->[0]; - } else { - Bugzilla::User::match_field({ 'login' => {'type' => 'single'} }); - $target = Bugzilla::User->check($login); - } - } + my ($self, $args) = @_; + my ($vars, $page) = @$args{qw(vars page_id)}; + return unless $page eq 'user_profile.html'; + my $user = Bugzilla->user; + + # determine user to display + my ($target, $login); + my $input = Bugzilla->input_params; + if (my $user_id = $input->{user_id}) { + + # load from user_id + $user_id = 0 if $user_id =~ /\D/; + $target = Bugzilla::User->check({id => $user_id}); + } + else { + # loading from login name requires authentication + Bugzilla->login(LOGIN_REQUIRED); + $login = $input->{login}; + if (!$login) { + + # show current user's profile by default + $target = $user; + } + else { + my $limit = Bugzilla->params->{'maxusermatches'} + 1; + my $users = Bugzilla::User::match($login, $limit, 1); + if (scalar(@$users) == 1) { + + # always allow singular matches without confirmation + $target = $users->[0]; + } + else { + Bugzilla::User::match_field({'login' => {'type' => 'single'}}); + $target = Bugzilla::User->check($login); + } } - $login ||= $target->login; + } + $login ||= $target->login; - # load statistics into $vars - my $dbh = Bugzilla->switch_to_shadow_db; + # load statistics into $vars + my $dbh = Bugzilla->switch_to_shadow_db; - my $stats = $dbh->selectall_hashref( - "SELECT name, count + my $stats = $dbh->selectall_hashref( + "SELECT name, count FROM profiles_statistics - WHERE user_id = ?", - "name", - undef, - $target->id, - ); - map { $stats->{$_} = $stats->{$_}->{count} } keys %$stats; + WHERE user_id = ?", "name", undef, $target->id, + ); + map { $stats->{$_} = $stats->{$_}->{count} } keys %$stats; - my $statuses = $dbh->selectall_hashref( - "SELECT status, count + my $statuses = $dbh->selectall_hashref( + "SELECT status, count FROM profiles_statistics_status - WHERE user_id = ?", - "status", - undef, - $target->id, - ); - map { $statuses->{$_} = $statuses->{$_}->{count} } keys %$statuses; + WHERE user_id = ?", "status", undef, $target->id, + ); + map { $statuses->{$_} = $statuses->{$_}->{count} } keys %$statuses; - my $products = $dbh->selectall_arrayref( - "SELECT product, count + my $products = $dbh->selectall_arrayref( + "SELECT product, count FROM profiles_statistics_products WHERE user_id = ? - ORDER BY product = '', count DESC", - { Slice => {} }, - $target->id, - ); - - # ensure there's always an "other" product entry - my ($other_product) = grep { $_->{product} eq '' } @$products; - if (!$other_product) { - $other_product = { product => '', count => 0 }; - push @$products, $other_product; + ORDER BY product = '', count DESC", {Slice => {}}, $target->id, + ); + + # ensure there's always an "other" product entry + my ($other_product) = grep { $_->{product} eq '' } @$products; + if (!$other_product) { + $other_product = {product => '', count => 0}; + push @$products, $other_product; + } + + # load product objects and validate product visibility + foreach my $product (@$products) { + next if $product->{product} eq ''; + my $product_obj = Bugzilla::Product->new({name => $product->{product}}); + if (!$product_obj || !$user->can_see_product($product_obj->name)) { + + # products not accessible to current user are moved into "other" + $other_product->{count} += $product->{count}; + $product->{count} = 0; } - - # load product objects and validate product visibility - foreach my $product (@$products) { - next if $product->{product} eq ''; - my $product_obj = Bugzilla::Product->new({ name => $product->{product} }); - if (!$product_obj || !$user->can_see_product($product_obj->name)) { - # products not accessible to current user are moved into "other" - $other_product->{count} += $product->{count}; - $product->{count} = 0; - } else { - $product->{product} = $product_obj; - } + else { + $product->{product} = $product_obj; } + } - # set other's name, and remove empty products - $other_product->{product} = { name => 'Other' }; - $products = [ grep { $_->{count} } @$products ]; + # set other's name, and remove empty products + $other_product->{product} = {name => 'Other'}; + $products = [grep { $_->{count} } @$products]; - $vars->{stats} = $stats; - $vars->{statuses} = $statuses; - $vars->{products} = $products; - $vars->{login} = $login; - $vars->{target} = $target; + $vars->{stats} = $stats; + $vars->{statuses} = $statuses; + $vars->{products} = $products; + $vars->{login} = $login; + $vars->{target} = $target; } sub object_columns { - my ($self, $args) = @_; - my ($class, $columns) = @$args{qw(class columns)}; - if ($class->isa('Bugzilla::User')) { - my $dbh = Bugzilla->dbh; - my @new_columns = qw(last_activity_ts last_statistics_ts); - push @$columns, grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns; - } + my ($self, $args) = @_; + my ($class, $columns) = @$args{qw(class columns)}; + if ($class->isa('Bugzilla::User')) { + my $dbh = Bugzilla->dbh; + my @new_columns = qw(last_activity_ts last_statistics_ts); + push @$columns, + grep { $dbh->bz_column_info($class->DB_TABLE, $_) } @new_columns; + } } sub object_update_columns { - my ($self, $args) = @_; - my ($object, $columns) = @$args{qw(object columns)}; - if ($object->isa('Bugzilla::User')) { - push(@$columns, qw(last_activity_ts last_statistics_ts)); - } + my ($self, $args) = @_; + my ($object, $columns) = @$args{qw(object columns)}; + if ($object->isa('Bugzilla::User')) { + push(@$columns, qw(last_activity_ts last_statistics_ts)); + } } # @@ -404,161 +407,96 @@ sub object_update_columns { # sub db_schema_abstract_schema { - my ($self, $args) = @_; - $args->{'schema'}->{'profiles_statistics'} = { - FIELDS => [ - id => { - TYPE => 'MEDIUMSERIAL', - NOTNULL => 1, - PRIMARYKEY => 1, - }, - user_id => { - TYPE => 'INT3', - NOTNULL => 1, - REFERENCES => { - TABLE => 'profiles', - COLUMN => 'userid', - DELETE => 'CASCADE', - } - }, - name => { - TYPE => 'VARCHAR(30)', - NOTNULL => 1, - }, - count => { - TYPE => 'INT', - NOTNULL => 1, - }, - ], - INDEXES => [ - profiles_statistics_name_idx => { - FIELDS => [ 'user_id', 'name' ], - TYPE => 'UNIQUE', - }, - ], - }; - $args->{'schema'}->{'profiles_statistics_status'} = { - FIELDS => [ - id => { - TYPE => 'MEDIUMSERIAL', - NOTNULL => 1, - PRIMARYKEY => 1, - }, - user_id => { - TYPE => 'INT3', - NOTNULL => 1, - REFERENCES => { - TABLE => 'profiles', - COLUMN => 'userid', - DELETE => 'CASCADE', - } - }, - status => { - TYPE => 'VARCHAR(64)', - NOTNULL => 1, - }, - count => { - TYPE => 'INT', - NOTNULL => 1, - }, - ], - INDEXES => [ - profiles_statistics_status_idx => { - FIELDS => [ 'user_id', 'status' ], - TYPE => 'UNIQUE', - }, - ], - }; - $args->{'schema'}->{'profiles_statistics_products'} = { - FIELDS => [ - id => { - TYPE => 'MEDIUMSERIAL', - NOTNULL => 1, - PRIMARYKEY => 1, - }, - user_id => { - TYPE => 'INT3', - NOTNULL => 1, - REFERENCES => { - TABLE => 'profiles', - COLUMN => 'userid', - DELETE => 'CASCADE', - } - }, - product => { - TYPE => 'VARCHAR(64)', - NOTNULL => 1, - }, - count => { - TYPE => 'INT', - NOTNULL => 1, - }, - ], - INDEXES => [ - profiles_statistics_products_idx => { - FIELDS => [ 'user_id', 'product' ], - TYPE => 'UNIQUE', - }, - ], - }; - $args->{'schema'}->{'profiles_statistics_recalc'} = { - FIELDS => [ - user_id => { - TYPE => 'INT3', - NOTNULL => 1, - REFERENCES => { - TABLE => 'profiles', - COLUMN => 'userid', - DELETE => 'CASCADE', - } - }, - ], - INDEXES => [ - profiles_statistics_recalc_idx => { - FIELDS => [ 'user_id' ], - TYPE => 'UNIQUE', - }, - ], - }; - $args->{'schema'}->{'profiles_statistics_recalc'} = { - FIELDS => [ - user_id => { - TYPE => 'INT3', - NOTNULL => 1, - REFERENCES => { - TABLE => 'profiles', - COLUMN => 'userid', - DELETE => 'CASCADE', - } - }, - ], - INDEXES => [ - profiles_statistics_recalc_idx => { - FIELDS => [ 'user_id' ], - TYPE => 'UNIQUE', - }, - ], - }; + my ($self, $args) = @_; + $args->{'schema'}->{'profiles_statistics'} = { + FIELDS => [ + id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,}, + user_id => { + TYPE => 'INT3', + NOTNULL => 1, + REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE',} + }, + name => {TYPE => 'VARCHAR(30)', NOTNULL => 1,}, + count => {TYPE => 'INT', NOTNULL => 1,}, + ], + INDEXES => [ + profiles_statistics_name_idx => + {FIELDS => ['user_id', 'name'], TYPE => 'UNIQUE',}, + ], + }; + $args->{'schema'}->{'profiles_statistics_status'} = { + FIELDS => [ + id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,}, + user_id => { + TYPE => 'INT3', + NOTNULL => 1, + REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE',} + }, + status => {TYPE => 'VARCHAR(64)', NOTNULL => 1,}, + count => {TYPE => 'INT', NOTNULL => 1,}, + ], + INDEXES => [ + profiles_statistics_status_idx => + {FIELDS => ['user_id', 'status'], TYPE => 'UNIQUE',}, + ], + }; + $args->{'schema'}->{'profiles_statistics_products'} = { + FIELDS => [ + id => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1,}, + user_id => { + TYPE => 'INT3', + NOTNULL => 1, + REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE',} + }, + product => {TYPE => 'VARCHAR(64)', NOTNULL => 1,}, + count => {TYPE => 'INT', NOTNULL => 1,}, + ], + INDEXES => [ + profiles_statistics_products_idx => + {FIELDS => ['user_id', 'product'], TYPE => 'UNIQUE',}, + ], + }; + $args->{'schema'}->{'profiles_statistics_recalc'} = { + FIELDS => [ + user_id => { + TYPE => 'INT3', + NOTNULL => 1, + REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE',} + }, + ], + INDEXES => [ + profiles_statistics_recalc_idx => {FIELDS => ['user_id'], TYPE => 'UNIQUE',}, + ], + }; + $args->{'schema'}->{'profiles_statistics_recalc'} = { + FIELDS => [ + user_id => { + TYPE => 'INT3', + NOTNULL => 1, + REFERENCES => {TABLE => 'profiles', COLUMN => 'userid', DELETE => 'CASCADE',} + }, + ], + INDEXES => [ + profiles_statistics_recalc_idx => {FIELDS => ['user_id'], TYPE => 'UNIQUE',}, + ], + }; } sub install_update_db { - my $dbh = Bugzilla->dbh; - $dbh->bz_add_column('profiles', 'last_activity_ts', { TYPE => 'DATETIME' }); - $dbh->bz_add_column('profiles', 'last_statistics_ts', { TYPE => 'DATETIME' }); + my $dbh = Bugzilla->dbh; + $dbh->bz_add_column('profiles', 'last_activity_ts', {TYPE => 'DATETIME'}); + $dbh->bz_add_column('profiles', 'last_statistics_ts', {TYPE => 'DATETIME'}); } sub install_filesystem { - my ($self, $args) = @_; - my $files = $args->{'files'}; - my $extensions_dir = bz_locations()->{'extensionsdir'}; - my $script_name = $extensions_dir . "/" . __PACKAGE__->NAME . "/bin/update.pl"; - $files->{$script_name} = { - perms => Bugzilla::Install::Filesystem::WS_EXECUTE - }; - $script_name = $extensions_dir . "/" . __PACKAGE__->NAME . "/bin/migrate.pl"; - $files->{$script_name} = { - perms => Bugzilla::Install::Filesystem::OWNER_EXECUTE - }; + my ($self, $args) = @_; + my $files = $args->{'files'}; + my $extensions_dir = bz_locations()->{'extensionsdir'}; + my $script_name = $extensions_dir . "/" . __PACKAGE__->NAME . "/bin/update.pl"; + $files->{$script_name} = {perms => Bugzilla::Install::Filesystem::WS_EXECUTE}; + $script_name = $extensions_dir . "/" . __PACKAGE__->NAME . "/bin/migrate.pl"; + $files->{$script_name} + = {perms => Bugzilla::Install::Filesystem::OWNER_EXECUTE}; } __PACKAGE__->NAME; |