#### Accessors ######
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
=pod
=head2 Instance Properties
use constant DB_TABLE => 'bugs';
use constant ID_FIELD => 'bug_id';
+
use constant NAME_FIELD => 'alias';
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
use constant LIST_ORDER => ID_FIELD;
# Bugs have their own auditing table, bugs_activity.
use constant AUDIT_CREATES => 0;
#### Accessors ######
###############################
+use Class::XSAccessor {
+ accessors => {
+ name => __PACKAGE__->NAME_FIELD,
+ id => __PACKAGE__->ID_FIELD,
+ },
+};
+
sub class { return $_[0]->{class} }
sub bug_id { return $_[0]->{bug_id} }
AUDIT_REMOVES => 0,
USE_MEMCACHED => 0 };
+use Class::XSAccessor {
+ accessors => {
+ name => __PACKAGE__->NAME_FIELD,
+ id => __PACKAGE__->ID_FIELD,
+ },
+};
+
#####################################################################
# Provide accessors for our columns
#####################################################################
-sub id { return $_[0]->{id} }
sub bug_id { return $_[0]->{bug_id} }
sub user_id { return $_[0]->{user_id} }
sub last_visit_ts { return $_[0]->{last_visit_ts} }
sortkey => \&_check_sortkey,
};
+###############################
+#### Accessors ######
+###############################
+
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
###############################
#### Constructors #####
###############################
#### Accessors ######
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub already_wrapped { return $_[0]->{'already_wrapped'}; }
sub body { return $_[0]->{'thetext'}; }
sub bug_id { return $_[0]->{'bug_id'}; }
# There's no gain to caching these objects
use constant USE_MEMCACHED => 0;
-sub tag { return $_[0]->{'tag'} }
+###############################
+#### Accessors ######
+###############################
+
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ tag => __PACKAGE__->NAME_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub weight { return $_[0]->{'weight'} }
sub set_weight { $_[0]->set('weight', $_[1]); }
sub triage_owner_id { return $_[0]->{'triage_owner_id'} }
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
##############################################
# Implement Bugzilla::Field::ChoiceInterface #
##############################################
sub _check_is_mandatory { return $_[1] ? 1 : 0; }
+###############################
+#### Accessors ######
+###############################
+
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
=pod
=head2 Instance Properties
$class->SUPER::new(@_);
}
+###############################
+#### Accessors ######
+###############################
+
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
#########################
# Database Manipulation #
#########################
#### Accessors ######
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ },
+};
+
=head2 METHODS
=over
=cut
-sub id { return $_[0]->{'id'}; }
sub name { return $_[0]->type->name; }
sub type_id { return $_[0]->{'type_id'}; }
sub bug_id { return $_[0]->{'bug_id'}; }
#### Accessors ######
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
=head2 METHODS
=over
=cut
-sub id { return $_[0]->{'id'}; }
-sub name { return $_[0]->{'name'}; }
sub description { return $_[0]->{'description'}; }
sub cc_list { return $_[0]->{'cc_list'}; }
sub target_type { return $_[0]->{'target_type'} eq 'b' ? 'bug' : 'attachment'; }
#### Accessors ######
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub description { return $_[0]->{'description'}; }
sub is_bug_group { return $_[0]->{'isbuggroup'}; }
sub user_regexp { return $_[0]->{'userregexp'}; }
#### Accessors ######
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub description { return $_[0]->{'description'}; }
sub bug_count {
##### Accessors ######
################################
-sub name { return $_[0]->{'value'}; }
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub product_id { return $_[0]->{'product_id'}; }
sub sortkey { return $_[0]->{'sortkey'}; }
sub is_active { return $_[0]->{'isactive'}; }
#### Accessors ######
###############################
-sub id { return $_[0]->{$_[0]->ID_FIELD}; }
-sub name { return $_[0]->{$_[0]->NAME_FIELD}; }
-
###############################
#### Methods ####
###############################
#### Accessors ######
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub allows_unconfirmed { return $_[0]->{'allows_unconfirmed'}; }
sub description { return $_[0]->{'description'}; }
sub is_active { return $_[0]->{'isactive'}; }
use constant AUDIT_CREATES => 0;
use constant AUDIT_UPDATES => 0;
use constant AUDIT_REMOVES => 0;
+use constant USER_ID_FIELD => 'user_id';
+use constant ID_FIELD => 'id';
use constant DB_COLUMNS => qw(
id
# Simple Accessors #
####################
+use Class::XSAccessor {
+ accessors => {
+ user_id => __PACKAGE__->USER_ID_FIELD,
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub bug_list { return [split(',', $_[0]->{'bug_list'})]; }
sub list_order { return $_[0]->{'list_order'}; }
-sub user_id { return $_[0]->{'user_id'}; }
############
# Mutators #
# Simple Accessors #
####################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub url { return $_[0]->{'query'}; }
sub user {
use constant NAME_FIELD => 'login_name';
use constant ID_FIELD => 'userid';
+use constant REAL_NAME_FIELD => 'realname';
use constant LIST_ORDER => NAME_FIELD;
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->REAL_NAME_FIELD,
+ },
+};
+
use constant VALIDATORS => {
cryptpassword => \&_check_password,
disable_mail => \&_check_disable_mail,
################################################################################
# Accessors for user attributes
-sub name { $_[0]->{realname}; }
sub login { $_[0]->{login_name}; }
sub extern_id { $_[0]->{extern_id}; }
sub email { $_[0]->login . Bugzilla->params->{'emailsuffix'}; }
USE_MEMCACHED => 0 };
# Accessors
-sub id { return $_[0]->{id} }
+###############################
+#### Accessors ######
+###############################
+
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub user_id { return $_[0]->{user_id} }
sub api_key { return $_[0]->{api_key} }
sub app_id { return $_[0]->{app_id} }
USE_MEMCACHED => 0 };
# Accessors
-sub id { return $_[0]->{id} }
+
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub userid { return $_[0]->{userid} }
sub cookie { return $_[0]->{cookie} }
sub lastused { return $_[0]->{lastused} }
use constant DB_TABLE => 'versions';
use constant NAME_FIELD => 'value';
+
# This is "id" because it has to be filled in and id is probably the fastest.
# We do a custom sort in new_from_list below.
use constant LIST_ORDER => 'id';
##### Accessors ####
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub product_id { return $_[0]->{'product_id'}; }
sub is_active { return $_[0]->{'isactive'}; }
####################
# Simple Accessors #
####################
+
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub subject { return $_[0]->{'subject'}; }
sub body { return $_[0]->{'body'}; }
sub mail_if_no_bugs { return $_[0]->{'mailifnobugs'}; }
use constant NAME_FIELD => 'id';
use constant LIST_ORDER => 'sortkey';
+use constant QUERY_NAME_FIELD => 'query_name';
####################
# Simple Accessors #
####################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->QUERY_NAME_FIELD,
+ },
+};
+
sub eventid { return $_[0]->{'eventid'}; }
sub sortkey { return $_[0]->{'sortkey'}; }
sub one_email_per_bug { return $_[0]->{'onemailperbug'}; }
sub title { return $_[0]->{'title'}; }
-sub name { return $_[0]->{'query_name'}; }
1;
####################
# Simple Accessors #
####################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub eventid { return $_[0]->{'eventid'}; }
sub run_day { return $_[0]->{'run_day'}; }
sub run_time { return $_[0]->{'run_time'}; }
use constant USE_MEMCACHED => 0;
# getters
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
sub user {
my ($self) = @_;
# Provide accessors for our columns
#####################################################################
-sub id { return $_[0]->{id} }
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub bug_id { return $_[0]->{bug_id} }
sub user_id { return $_[0]->{user_id} }
sub modification_time { return $_[0]->{modification_time} }
# accessors
#
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub message_id { return $_[0]->{'message_id'} }
sub push_ts { return $_[0]->{'push_ts'}; }
sub payload { return $_[0]->{'payload'}; }
# accessors
#
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub connector { return $_[0]->{'connector'}; }
sub next_attempt_ts { return $_[0]->{'next_attempt_ts'}; }
sub attempts { return $_[0]->{'attempts'}; }
# accessors
#
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub message_id { return $_[0]->{'message_id'}; }
sub change_set { return $_[0]->{'change_set'}; }
sub routing_key { return $_[0]->{'routing_key'}; }
#
# accessors
#
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
sub push_ts { return $_[0]->{'push_ts'}; }
sub payload { return $_[0]->{'payload'}; }
connector => \&_check_connector,
};
use constant LIST_ORDER => 'connector';
-
+use constant NAME_FIELD => 'option_name';
#
# accessors
#
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
sub connector { return $_[0]->{'connector'}; }
-sub name { return $_[0]->{'option_name'}; }
sub value { return $_[0]->{'option_value'}; }
#
status
);
+###############################
+#### Accessors ######
+###############################
+
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
sub _check_param_required {
my ($param) = @_;
#### Accessors ####
###############################
+use constant ID_FIELD => 'field_id';
+
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub flag_id { return $_[0]->{'id'}; }
-sub name { return $_[0]->{'name'}; }
sub description { return $_[0]->{'description'}; }
sub flag_type { return $_[0]->{'type'}; }
sub sortkey { return $_[0]->{'sortkey'}; }
# Here we return 'field_id' instead of the real
# id as we want other Bugzilla code to treat this
# as a Bugzilla::Field object in certain places.
-sub id { return $_[0]->{'field_id'}; }
sub type { return FIELD_TYPE_EXTENSION; }
sub legal_values { return $_[0]->values; }
sub custom { return 1; }
#### Accessors ####
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub tracking_flag_id { return $_[0]->{'tracking_flag_id'}; }
sub bug_id { return $_[0]->{'bug_id'}; }
sub value { return $_[0]->{'value'}; }
);
use constant LIST_ORDER => 'sortkey';
+use constant NAME_FIELD => 'value';
use constant UPDATE_COLUMNS => qw(
setter_group_id
#### Accessors ####
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub tracking_flag_id { return $_[0]->{'tracking_flag_id'}; }
sub setter_group_id { return $_[0]->{'setter_group_id'}; }
sub value { return $_[0]->{'value'}; }
## Compatibility with Bugzilla::Field ##
########################################
-sub name { return $_[0]->{'value'}; }
sub is_visible_on_bug { return 1; }
1;
#### Accessors ####
###############################
+use Class::XSAccessor {
+ accessors => {
+ id => __PACKAGE__->ID_FIELD,
+ name => __PACKAGE__->NAME_FIELD,
+ },
+};
+
sub tracking_flag_id { return $_[0]->{'tracking_flag_id'}; }
sub product_id { return $_[0]->{'product_id'}; }
sub component_id { return $_[0]->{'component_id'}; }
--- /dev/null
+#!/usr/bin/perl
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# This Source Code Form is "Incompatible With Secondary Licenses", as
+# defined by the Mozilla Public License, v. 2.0.
+use 5.10.1;
+use strict;
+use warnings;
+use autodie;
+use lib qw(. lib local/lib/perl5);
+use constant HAVE_DATABASE => 0;
+
+use if HAVE_DATABASE, 'Bugzilla';
+BEGIN {
+ if (HAVE_DATABASE) {
+ Bugzilla->extensions
+ }
+}
+use Bugzilla::DB::Schema;
+use Module::Runtime qw(require_module);
+use Test::More;
+
+# These are all subclasses of Bugzilla::Object
+my @packages = qw(
+ Bugzilla::Attachment
+ Bugzilla::Bug
+ Bugzilla::BugUrl
+ Bugzilla::BugUserLastVisit
+ Bugzilla::Classification
+ Bugzilla::Comment
+ Bugzilla::Comment::TagWeights
+ Bugzilla::Component
+ Bugzilla::Extension::BugmailFilter::Filter
+ Bugzilla::Extension::MyDashboard::BugInterest
+ Bugzilla::Extension::Push::BacklogMessage
+ Bugzilla::Extension::Push::Backoff
+ Bugzilla::Extension::Push::LogEntry
+ Bugzilla::Extension::Push::Message
+ Bugzilla::Extension::Push::Option
+ Bugzilla::Extension::Review::FlagStateActivity
+ Bugzilla::Extension::TrackingFlags::Flag
+ Bugzilla::Extension::TrackingFlags::Flag::Bug
+ Bugzilla::Extension::TrackingFlags::Flag::Value
+ Bugzilla::Extension::TrackingFlags::Flag::Visibility
+ Bugzilla::Field
+ Bugzilla::Field::Choice
+ Bugzilla::Flag
+ Bugzilla::FlagType
+ Bugzilla::Group
+ Bugzilla::Keyword
+ Bugzilla::Milestone
+ Bugzilla::Product
+ Bugzilla::Search::Recent
+ Bugzilla::Search::Saved
+ Bugzilla::User
+ Bugzilla::User::APIKey
+ Bugzilla::User::Session
+ Bugzilla::Version
+ Bugzilla::Whine
+ Bugzilla::Whine::Query
+ Bugzilla::Whine::Schedule
+);
+
+# some of the subclasses have things to skip.
+# 'name' means skip checking the name() method
+# 'id' means skip checking the id() method
+# 'db_name' means NAME_FIELD isn't a database field.
+my %skip = (
+ 'Bugzilla::Attachment' => { db_name => 1 },
+ 'Bugzilla::Comment' => { db_name => 1 },
+ 'Bugzilla::Extension::BugmailFilter::Filter' => { db_name => 1 },
+ 'Bugzilla::Extension::Push::BacklogMessage' => { db_name => 1 },
+ 'Bugzilla::Extension::Push::Backoff' => { db_name => 1 },
+ 'Bugzilla::Extension::Push::Message' => { db_name => 1 },
+ 'Bugzilla::Extension::Push::Option' => { name => 1 },
+ 'Bugzilla::Extension::Review::FlagStateActivity' => { db_name => 1 },
+ 'Bugzilla::Extension::TrackingFlags::Flag' => { id => 1 },
+ 'Bugzilla::Extension::TrackingFlags::Flag::Bug' => { db_name => 1 },
+ 'Bugzilla::Extension::TrackingFlags::Flag::Value' => { name => 1 },
+ 'Bugzilla::Extension::TrackingFlags::Flag::Visibility' => { db_name => 1 },
+ 'Bugzilla::Flag' => { name => 1, id => 1 },
+ 'Bugzilla::Search::Recent' => { db_name => 1 },
+ 'Bugzilla::User' => { name => 1 },
+ 'Bugzilla::Whine' => { db_name => 1 },
+ 'Bugzilla::Whine::Query' => { name => 1 },
+);
+
+# this is kind of evil, but I want a copy
+# of the schema without accessing a real DB.
+my $schema = Bugzilla::DB::Schema::ABSTRACT_SCHEMA;
+if (HAVE_DATABASE) {
+ Bugzilla::Hook::process( 'db_schema_abstract_schema', { schema => $schema } );
+}
+
+foreach my $package (@packages) {
+ next if $package =~ /^Bugzilla::Extension::/ && !HAVE_DATABASE;
+ require_module($package);
+ isa_ok($package, 'Bugzilla::Object');
+ can_ok($package, qw( id name ID_FIELD NAME_FIELD));
+ my $fake = bless {}, $package;
+ my ($NAME_FIELD, $ID_FIELD);
+ unless ($skip{$package}{id}) {
+ $ID_FIELD = $package->ID_FIELD;
+ $fake->{ $package->ID_FIELD } = 42;
+ my $ok = eval {
+ is($fake->id, 42, "$package->id is ID_FIELD");
+ 1;
+ };
+ ok($ok, "$package->id is not a fatal error");
+ }
+ unless ($skip{$package}{name}) {
+ $NAME_FIELD = $package->NAME_FIELD;
+ $fake->{ $package->NAME_FIELD } = 'camel';
+ my $ok = eval {
+ is($fake->name, 'camel', "$package->name is NAME_FIELD");
+ 1;
+ };
+ ok($ok, "$package->name is not a fatal error");
+ }
+ if ($package->can('DB_TABLE')) {
+ my $table = $package->DB_TABLE;
+ my $table_def = $schema->{$table};
+ my %fields = @{ $table_def->{FIELDS} };
+ ok($table_def, "$package has a table definition");
+ if ($ID_FIELD and not $skip{$package}{db_id}) {
+ ok($fields{ $ID_FIELD }, "$package table $table has column named by $ID_FIELD");
+ }
+ if ($NAME_FIELD and not $skip{$package}{db_name}) {
+ ok($fields{ $NAME_FIELD }, "$package table $table has column named $NAME_FIELD");
+ }
+ }
+}
+
+done_testing;