=head2 bug_columns
+B<DEPRECATED> Use L</object_columns> instead.
+
This allows you to add new fields that will show up in every L<Bugzilla::Bug>
object. Note that you will also need to use the L</bug_fields> hook in
conjunction with this hook to make this work.
=back
+=head2 object_columns
+
+This hook allows you to add new "fields" to existing Bugzilla objects,
+that correspond to columns in their tables.
+
+For example, if you added an C<example> column to the "bugs" table, you
+would have to also add an C<example> field to the C<Bugzilla::Bug> object
+in order to access that data via Bug objects.
+
+Don't do anything slow inside this hook--it's called several times on
+every page of Bugzilla.
+
+Params:
+
+=over
+
+=item C<class>
+
+The name of the class that this hook is being called on. You can check this
+like C<< if ($class->isa('Some::Class')) >> in your code, to add new
+fields only for certain classes.
+
+=item C<columns>
+
+An arrayref. Add the string names of columns to this array to add new
+values to objects.
+
+For example, if you add an C<example> column to a particular table
+(using L</install_update_db>), and then push the string C<example> into
+this array for the object that uses that table, then you can access the
+information in that column via C<< $object->{example} >> on all objects
+of that type.
+
+This arrayref does not contain the standard column names--you cannot modify
+or remove standard object columns using this hook.
+
+=back
+
=head2 object_end_of_create_validators
Called at the end of L<Bugzilla::Object/run_create_validators>. You can
The name of the class that C<VALIDATORS> was called on. You can check this
like C<< if ($class->isa('Some::Class')) >> in your code, to add
-validators only for certain classes
+validators only for certain classes.
=item C<validators>
my $class = shift;
my ($param) = @_;
my $dbh = Bugzilla->dbh;
- my $columns = join(',', $class->DB_COLUMNS);
+ my $columns = join(',', $class->_get_db_columns);
my $table = $class->DB_TABLE;
my $name_field = $class->NAME_FIELD;
my $id_field = $class->ID_FIELD;
sub _do_list_select {
my ($class, $where, $values, $postamble) = @_;
my $table = $class->DB_TABLE;
- my $cols = join(',', $class->DB_COLUMNS);
+ my $cols = join(',', $class->_get_db_columns);
my $order = $class->LIST_ORDER;
my $sql = "SELECT $cols FROM $table";
sub check_boolean { return $_[1] ? 1 : 0 }
-# For some classes, VALIDATORS takes time to generate, so we cache it. Also,
-# this allows the object_validators hook to only run once per request,
-# instead of every time we call set() on a class of objects.
-#
-# This method is intentionally private and should only be called by
-# Bugzilla::Object.
+####################
+# Constant Helpers #
+####################
+
+# For some classes, some constants take time to generate, so we cache them
+# and only access them through the below methods. This also allows certain
+# hooks to only run once per request instead of multiple times on each
+# page.
+
+sub _get_db_columns {
+ my $invocant = shift;
+ my $class = ref($invocant) || $invocant;
+ my $cache = Bugzilla->request_cache;
+ my $cache_key = "object_${class}_db_columns";
+ return @{ $cache->{$cache_key} } if $cache->{$cache_key};
+ # Currently you can only add new columns using object_columns, not
+ # remove or modify existing columns, because removing columns would
+ # almost certainly cause Bugzilla to function improperly.
+ my @add_columns;
+ Bugzilla::Hook::process('object_columns',
+ { class => $class, columns => \@add_columns });
+ my @columns = ($invocant->DB_COLUMNS, @add_columns);
+ $cache->{$cache_key} = \@columns;
+ return @{ $cache->{$cache_key} };
+}
+
+# This method is private and should only be called by Bugzilla::Object.
sub _get_validators {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
The names of the columns that you want to read out of the database
and into this object. This should be an array.
+I<Note>: Though normally you will never need to access this constant's data
+directly in your subclass, if you do, you should access it by calling the
+C<_get_db_columns> method instead of accessing the constant directly. (The
+only exception to this rule is calling C<SUPER::DB_COLUMNS> from within
+your own C<DB_COLUMNS> subroutine in a subclass.)
+
=item C<NAME_FIELD>
The name of the column that should be considered to be the unique