]> git.ipfire.org Git - thirdparty/bugzilla.git/commitdiff
Bug 347061: Create Bugzilla::Object->create and make Bugzilla::Keyword use it
authormkanat%bugzilla.org <>
Fri, 11 Aug 2006 00:53:07 +0000 (00:53 +0000)
committermkanat%bugzilla.org <>
Fri, 11 Aug 2006 00:53:07 +0000 (00:53 +0000)
Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=bkor, a=myk

Bugzilla/DB/Schema.pm
Bugzilla/Install/DB.pm
Bugzilla/Keyword.pm
Bugzilla/Object.pm
editkeywords.cgi
template/en/default/global/code-error.html.tmpl

index e997e41873dbe7f6fafd84ba7f2591799890838b..50785c5b7ebc97a77346200a24a54b96e55b8aac 100644 (file)
@@ -346,7 +346,7 @@ use constant ABSTRACT_SCHEMA => {
 
     keyworddefs => {
         FIELDS => [
-            id          => {TYPE => 'INT2', NOTNULL => 1,
+            id          => {TYPE => 'SMALLSERIAL', NOTNULL => 1,
                             PRIMARYKEY => 1},
             name        => {TYPE => 'varchar(64)', NOTNULL => 1},
             description => {TYPE => 'MEDIUMTEXT'},
index dfe7f957a7ff62a8fb59a4d25cca5511653f647f..a4ab54260ef55c0d7410795038c09afe2bc417ef 100644 (file)
@@ -468,6 +468,9 @@ sub update_table_definitions {
     $dbh->bz_alter_column('flagtypes', 'id',
           {TYPE => 'SMALLSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
 
+    $dbh->bz_alter_column('keyworddefs', 'id',
+        {TYPE => 'SMALLSERIAL', NOTNULL => 1, PRIMARYKEY => 1});
+
     ################################################################
     # New --TABLE-- changes should go *** A B O V E *** this point #
     ################################################################
index 2e0f19f4c6da17e1c681584b20f4fa9f06145b29..fead77821a8d5cf9614128df640f4ca820552685 100644 (file)
@@ -20,6 +20,9 @@ package Bugzilla::Keyword;
 
 use base qw(Bugzilla::Object);
 
+use Bugzilla::Error;
+use Bugzilla::Util;
+
 ###############################
 ####    Initialization     ####
 ###############################
@@ -32,6 +35,13 @@ use constant DB_COLUMNS => qw(
 
 use constant DB_TABLE => 'keyworddefs';
 
+use constant REQUIRED_CREATE_FIELDS => qw(name description);
+
+use constant VALIDATORS => {
+    name        => \&_check_name,
+    description => \&_check_description,
+};
+
 ###############################
 ####      Accessors      ######
 ###############################
@@ -81,6 +91,30 @@ sub get_all_with_bug_count {
     return $keywords;
 }
 
+###############################
+###       Validators        ###
+###############################
+
+sub _check_name {
+    my ($name) = @_;
+    $name = trim($name);
+    $name eq "" && ThrowUserError("keyword_blank_name");
+    if ($name =~ /[\s,]/) {
+        ThrowUserError("keyword_invalid_name");
+    }
+    my $keyword = new Bugzilla::Keyword({ name => $name });
+    ThrowUserError("keyword_already_exists", { name => $name }) if $keyword;
+
+    return $name;
+}
+
+sub _check_description {
+    my ($desc) = @_;
+    $desc = trim($desc);
+    $desc eq '' && ThrowUserError("keyword_blank_description");
+    return $desc;
+}
+
 1;
 
 __END__
index 56789f5847d3dea464af2ddfff930fbf67e2fafe..c250f80fda0e60474c3495ba3e4d37c374475a99 100644 (file)
@@ -108,6 +108,45 @@ sub name              { return $_[0]->{'name'};        }
 ####      Subroutines    ######
 ###############################
 
+sub create {
+    my ($class, $params) = @_;
+    my $dbh = Bugzilla->dbh;
+
+    my $required   = $class->REQUIRED_CREATE_FIELDS;
+    my $validators = $class->VALIDATORS;
+    my $table      = $class->DB_TABLE;
+
+    foreach my $field ($class->REQUIRED_CREATE_FIELDS) {
+        ThrowCodeError('param_required', 
+            { function => "${class}->create", param => $field })
+            if !exists $params->{$field};
+    }
+
+    my (@field_names, @values);
+    # We do the sort just to make sure that validation always
+    # happens in a consistent order.
+    foreach my $field (sort keys %$params) {
+        my $value;
+        if (exists $validators->{$field}) {
+            $value = &{$validators->{$field}}($params->{$field});
+        }
+        else {
+            $value = $params->{$field};
+        }
+        trick_taint($value);
+        push(@field_names, $field);
+        push(@values, $value);
+    }
+
+    my $qmarks = '?,' x @values;
+    chop($qmarks);
+    $dbh->do("INSERT INTO $table (" . join(', ', @field_names) 
+             . ") VALUES ($qmarks)", undef, @values);
+    my $id = $dbh->bz_last_key($table, 'id');
+
+    return $class->new($id);
+}
+
 sub get_all {
     my $class = shift;
     my $dbh = Bugzilla->dbh;
@@ -173,6 +212,19 @@ The order that C<new_from_list> and C<get_all> should return objects
 in. This should be the name of a database column. Defaults to
 C<name>.
 
+=item C<REQUIRED_CREATE_FIELDS>
+
+The list of fields that B<must> be specified when the user calls
+C<create()>. This should be an array.
+
+=item C<VALIDATORS>
+
+A hashref that points to a function that will validate each param to
+C<create()>. Each function in this hashref will be passed a single
+argument, the value passed to C<create()> for that field. These
+functions should call L<Bugzilla::Error/ThrowUserError> if they fail.
+They must return the validated value.
+
 =back
 
 =head1 METHODS
@@ -210,6 +262,25 @@ C<name>.
 
 =over
 
+=item C<create($params)>
+
+Description: Creates a new item in the database.
+             Throws a User Error if any of the passed-in params
+             are invalid.
+
+Params:      C<$params> - hashref - A value to put in each database
+               field for this object. Certain values must be set (the 
+               ones specified in L</REQUIRED_CREATE_FIELDS>), and
+               the function will throw a Code Error if you don't set
+               them.
+
+Returns:     The Object just created in the database.
+
+Notes:       In order for this function to work in your subclass,
+             your subclass's C<id> field must be of C<SERIAL>
+             type in the database. Your subclass also must
+             define L</REQUIRED_CREATE_FIELDS> and L</VALIDATORS>.
+
 =item C<get_all>
 
  Description: Returns all objects in this table from the database.
index 7b906c30b6f05669ad1514f563d8a20deda91779..7b94dbbe399ea4771a65d23eb5130b8d1f3a503d 100755 (executable)
@@ -34,25 +34,6 @@ my $dbh = Bugzilla->dbh;
 my $template = Bugzilla->template;
 my $vars = {};
 
-sub Validate {
-    my ($name, $description) = @_;
-    if ($name eq "") {
-        ThrowUserError("keyword_blank_name");
-    }
-    if ($name =~ /[\s,]/) {
-        ThrowUserError("keyword_invalid_name");
-    }    
-    if ($description eq "") {
-        ThrowUserError("keyword_blank_description");
-    }
-    # It is safe to detaint these values as they are only
-    # used in placeholders.
-    trick_taint($name);
-    $_[0] = $name;
-    trick_taint($description);
-    $_[1] = $description;
-}
-
 sub ValidateKeyID {
     my $id = shift;
 
@@ -102,49 +83,16 @@ if ($action eq 'add') {
 #
 # action='new' -> add keyword entered in the 'action=add' screen
 #
-
 if ($action eq 'new') {
-    # Cleanups and validity checks
-
-    my $name = trim($cgi->param('name') || '');
-    my $description  = trim($cgi->param('description')  || '');
-
-    Validate($name, $description);
-
-    my $id = $dbh->selectrow_array('SELECT id FROM keyworddefs
-                                    WHERE name = ?', undef, $name);
-
-    if ($id) {
-        $vars->{'name'} = $name;
-        ThrowUserError("keyword_already_exists", $vars);
-    }
-
-
-    # Pick an unused number.  Be sure to recycle numbers that may have been
-    # deleted in the past.  This code is potentially slow, but it happens
-    # rarely enough, and there really aren't ever going to be that many
-    # keywords anyway.
-
-    my $existing_ids =
-        $dbh->selectcol_arrayref('SELECT id FROM keyworddefs ORDER BY id');
+    my $name = $cgi->param('name') || '';
+    my $desc = $cgi->param('description')  || '';
 
-    my $newid = 1;
-
-    foreach my $oldid (@$existing_ids) {
-        if ($oldid > $newid) {
-            last;
-        }
-        $newid = $oldid + 1;
-    }
-
-    # Add the new keyword.
-    $dbh->do('INSERT INTO keyworddefs
-              (id, name, description) VALUES (?, ?, ?)',
-              undef, ($newid, $name, $description));
+    my $keyword = Bugzilla::Keyword->create(
+        { name => $name, description => $desc });
 
     print $cgi->header();
 
-    $vars->{'name'} = $name;
+    $vars->{'name'} = $keyword->name;
     $template->process("admin/keywords/created.html.tmpl", $vars)
       || ThrowTemplateError($template->error());
 
index f64cf6411083d92cd44d46706e663f4975094e46..9d039a07ce60c6778f1389e83360692508d3a091 100644 (file)
     Invalid parameter passed to [% function FILTER html %].
     It must be numeric.
 
+  [% ELSIF error == "param_required" %]
+    [% title = "Missing Parameter" %]
+    The function <code>[% function FILTER html %]</code> requires
+    a <code>[% param FILTER html %]</code> argument, and that
+    argument was not set.
+
   [% ELSIF error == "unknown_comparison_type" %]
     Specified comparison type is not supported.