diff options
author | mkanat%bugzilla.org <> | 2006-09-08 08:41:32 +0200 |
---|---|---|
committer | mkanat%bugzilla.org <> | 2006-09-08 08:41:32 +0200 |
commit | 460eb160b7d524b38fe7ea340922521c333282d7 (patch) | |
tree | 47c5486a0876cdab4871b605c15787719153b3c6 | |
parent | 666dd28a656b6893c96e837517e5ee65e19e1447 (diff) | |
download | bugzilla-460eb160b7d524b38fe7ea340922521c333282d7.tar.gz bugzilla-460eb160b7d524b38fe7ea340922521c333282d7.tar.xz |
Bug 350217: Extensions need to be able to update Bugzilla's DB schema
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=ghendricks, a=myk
-rw-r--r-- | Bugzilla.pm | 11 | ||||
-rw-r--r-- | Bugzilla/DB/Schema.pm | 11 | ||||
-rw-r--r-- | Bugzilla/Hook.pm | 100 | ||||
-rw-r--r-- | Bugzilla/Install/DB.pm | 3 | ||||
-rwxr-xr-x | enter_bug.cgi | 2 |
5 files changed, 116 insertions, 11 deletions
diff --git a/Bugzilla.pm b/Bugzilla.pm index 0fb223e9e..24e93edc7 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -343,6 +343,12 @@ sub custom_field_names { @{Bugzilla::Field->match({ custom=>1, obsolete=>0 })}); } +sub hook_args { + my ($class, $args) = @_; + $class->request_cache->{hook_args} = $args if $args; + return $class->request_cache->{hook_args}; +} + sub request_cache { if ($ENV{MOD_PERL}) { require Apache2::RequestUtil; @@ -556,4 +562,9 @@ The current Parameters of Bugzilla, as a hashref. If C<data/params> does not exist, then we return an empty hashref. If C<data/params> is unreadable or is not valid perl, we C<die>. +=item C<hook_args> + +If you are running inside a code hook (see L<Bugzilla::Hook>) this +is how you get the arguments passed to the hook. + =back diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm index ea25a125a..4c270e68c 100644 --- a/Bugzilla/DB/Schema.pm +++ b/Bugzilla/DB/Schema.pm @@ -35,9 +35,11 @@ package Bugzilla::DB::Schema; use strict; use Bugzilla::Error; +use Bugzilla::Hook; use Bugzilla::Util; use Bugzilla::Constants; +use Hash::Util qw(lock_value unlock_hash lock_keys unlock_keys); use Safe; # Historical, needed for SCHEMA_VERSION = '1.00' use Storable qw(dclone freeze thaw); @@ -1168,6 +1170,15 @@ sub _initialize { $abstract_schema ||= ABSTRACT_SCHEMA; + # Let extensions add tables, but make sure they can't modify existing + # tables. If we don't lock/unlock keys, lock_value complains. + lock_keys(%$abstract_schema); + lock_value(%$abstract_schema, $_) foreach (keys %$abstract_schema); + unlock_keys(%$abstract_schema); + Bugzilla::Hook::process('db_schema-abstract_schema', + { schema => $abstract_schema }); + unlock_hash(%$abstract_schema); + $self->{schema} = dclone($abstract_schema); # While ABSTRACT_SCHEMA cannot be modified, # $self->{abstract_schema} can be. So, we dclone it to prevent diff --git a/Bugzilla/Hook.pm b/Bugzilla/Hook.pm index 8ce1482c1..be4a70077 100644 --- a/Bugzilla/Hook.pm +++ b/Bugzilla/Hook.pm @@ -29,8 +29,7 @@ use Bugzilla::Error; use strict; sub process { - my $name = shift; - trick_taint($name); + my ($name, $args) = @_; # get a list of all extensions my @extensions = glob(bz_locations()->{'extensionsdir'} . "/*"); @@ -43,6 +42,7 @@ sub process { # worry about, so we can safely detaint them: trick_taint($extension); if (-e $extension.'/code/'.$name.'.pl') { + Bugzilla->hook_args($args); do($extension.'/code/'.$name.'.pl'); ThrowCodeError('extension_invalid', { name => $name, extension => $extension }) if $@; @@ -61,26 +61,106 @@ Bugzilla::Hook - Extendible extension hooks for Bugzilla code =head1 SYNOPSIS - use Bugzilla::Hook; + use Bugzilla::Hook; - Bugzilla::Hook::process("hookname"); + Bugzilla::Hook::process("hookname", { arg => $value, arg2 => $value2 }); =head1 DESCRIPTION Bugzilla allows extension modules to drop in and add routines at arbitrary points in Bugzilla code. These points are refered to as hooks. When a piece of standard Bugzilla code wants to allow an extension -to perform additional functions, it uses Bugzilla::Hook's process() +to perform additional functions, it uses Bugzilla::Hook's L</process> subroutine to invoke any extension code if installed. -=over 4 +=head2 How Hooks Work + +When a hook named C<HOOK_NAME> is run, Bugzilla will attempt to invoke any +source files named F<extensions/*/code/HOOK_NAME.pl>. + +So, for example, if your extension is called "testopia", and you +want to have code run during the L</install-update_db> hook, you +would have a file called F<extensions/testopia/code/install-update_db.pl> +that contained perl code to run during that hook. + +=head2 Arguments Passed to Hooks + +Some L<hooks|/HOOKS> have params that are passed to them. + +These params are accessible through L<Bugzilla/hook_args>. +That returns a hashref. Very frequently, if you want your +hook to do anything, you have to modify these variables. + +=head1 SUBROUTINES + +=over =item C<process> -Invoke any code hooks with a matching name from any installed extensions. -When this subroutine is called with hook name foo, Bugzilla will attempt -to invoke any source files in C<bugzilla/extension/EXTENSION_NAME/code/foo.pl>. +=over + +=item B<Description> + +Invoke any code hooks with a matching name from any installed extensions. + See C<customization.xml> in the Bugzilla Guide for more information on -Bugzilla's extension mechanism. +Bugzilla's extension mechanism. + +=item B<Params> + +=over + +=item C<$name> - The name of the hook to invoke. + +=item C<$args> - A hashref. The named args to pass to the hook. +They will be accessible to the hook via L<Bugzilla/hook_args>. + +=back + +=item B<Returns> (nothing) + +=back + +=back + +=head1 HOOKS + +This describes what hooks exist in Bugzilla currently. + +=head2 enter_bug-entrydefaultvars + +This happens right before the template is loaded on enter_bug.cgi. + +Params: + +=over + +=item C<vars> - A hashref. The variables that will be passed into the template. + +=back + +=head2 install-update_db + +This happens at the very end of all the tables being updated +during an installation or upgrade. If you need to modify your custom +schema, do it here. No params are passed. + +=head2 db_schema-abstract_schema + +This allows you to add tables to Bugzilla. Note that we recommend that you +prefix the names of your tables with some word, so that they don't conflict +with any future Bugzilla tables. + +If you wish to add new I<columns> to existing Bugzilla tables, do that +in L</install-update_db>. + +Params: + +=over + +=item C<schema> - A hashref, in the format of +L<Bugzilla::DB::Schema/ABSTRACT_SCHEMA>. Add new hash keys to make new table +definitions. F<checksetup.pl> will automatically add these tables to the +database when run. =back diff --git a/Bugzilla/Install/DB.pm b/Bugzilla/Install/DB.pm index d7918f6ac..e4e4e97fe 100644 --- a/Bugzilla/Install/DB.pm +++ b/Bugzilla/Install/DB.pm @@ -23,6 +23,7 @@ use strict; use Bugzilla::Bug qw(is_open_state); use Bugzilla::Constants; +use Bugzilla::Hook; use Bugzilla::Util; use Bugzilla::Series; @@ -490,6 +491,8 @@ sub update_table_definitions { ################################################################ # New --TABLE-- changes should go *** A B O V E *** this point # ################################################################ + + Bugzilla::Hook::process('install-update_db'); } # Subroutines should be ordered in the order that they are called. diff --git a/enter_bug.cgi b/enter_bug.cgi index a138d5edf..62abdcd81 100755 --- a/enter_bug.cgi +++ b/enter_bug.cgi @@ -547,7 +547,7 @@ foreach my $row (@$grouplist) { $vars->{'group'} = \@groups; -Bugzilla::Hook::process("enter_bug-entrydefaultvars"); +Bugzilla::Hook::process("enter_bug-entrydefaultvars", { vars => $vars }); $vars->{'default'} = \%default; |