From b5186bfbab50aaa6d24f53bf1ce17f696f4c4cf1 Mon Sep 17 00:00:00 2001 From: Patrick Donelan Date: Mon, 22 Jun 2009 07:08:08 +0000 Subject: [PATCH] fixed #10565: Survey: add question doing double-create --- docs/changelog/7.x.x.txt | 1 + docs/upgrades/upgrade_7.7.11-7.7.12.pl | 35 ++++++++++- lib/WebGUI/Asset/Wobject/Survey.pm | 14 +++-- lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm | 58 +++++++++++-------- t/Asset/Wobject/Survey/SurveyJSON.t | 2 +- 5 files changed, 79 insertions(+), 31 deletions(-) diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 85d1eb8b9..10b9cc584 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -1,6 +1,7 @@ 7.7.12 - Updated auth to allow sending back of non-text/html mime types. - fixed #10564: edit branch progress bar goes kablooey + - fixed #10565: Survey: add question doing double-create 7.7.11 - Fixed a bug where empty version tags were not deleted. (Martin Kamerbeek / Oqapi) diff --git a/docs/upgrades/upgrade_7.7.11-7.7.12.pl b/docs/upgrades/upgrade_7.7.11-7.7.12.pl index 99cf7f45f..ee2869141 100644 --- a/docs/upgrades/upgrade_7.7.11-7.7.12.pl +++ b/docs/upgrades/upgrade_7.7.11-7.7.12.pl @@ -22,7 +22,7 @@ use Getopt::Long; use WebGUI::Session; use WebGUI::Storage; use WebGUI::Asset; - +use WebGUI::Asset::Wobject::Survey; my $toVersion = '7.7.12'; my $quiet; # this line required @@ -31,6 +31,7 @@ my $quiet; # this line required my $session = start(); # this line required # upgrade functions go here +surveyCleanUp($session); finish($session); # this line required @@ -44,6 +45,38 @@ finish($session); # this line required # print "DONE!\n" unless $quiet; #} +#---------------------------------------------------------------------------- +sub surveyCleanUp { + my $session = shift; + print "\tRemoving extra properties that may have crept into surveyJSON... " unless $quiet; + + my $sth = $session->db->read('select assetId, revisionDate from Survey'); + + while (my ($assetId, $revision) = $sth->array) { + my $survey = WebGUI::Asset->new($session, $assetId, 'WebGUI::Asset::Wobject::Survey', $revision); + + # Remove recursive properties that snuck into the mold + if (my $mold = $survey->surveyJSON->mold) { + $mold->{question}{answers} = []; + $mold->{section}{questions} = []; + } + + # Remove keys that should never have been added to sections/questions/answers + for my $s (@{$survey->surveyJSON->sections}) { + for my $q (@{$s->{questions} || []}) { + for my $a (@{$q->{answers} || []}) { + delete $a->{$_} for qw(delete copy removetype addtype func); + } + delete $q->{$_} for qw(delete copy removetype addtype func); + } + delete $s->{$_} for qw(delete copy removetype addtype func); + } + $survey->persistSurveyJSON; + } + + print "DONE!\n" unless $quiet; +} + # -------------- DO NOT EDIT BELOW THIS LINE -------------------------------- diff --git a/lib/WebGUI/Asset/Wobject/Survey.pm b/lib/WebGUI/Asset/Wobject/Survey.pm index 3b241de57..80a28428b 100644 --- a/lib/WebGUI/Asset/Wobject/Survey.pm +++ b/lib/WebGUI/Asset/Wobject/Survey.pm @@ -828,9 +828,7 @@ sub www_submitObjectEdit { return $self->session->privilege->insufficient() unless $self->session->user->isInGroup( $self->get('groupToEditSurvey') ); - my $params = $self->session->form->paramsHashRef(); - - return $self->submitObjectEdit($params); + return $self->submitObjectEdit( $self->session->form->paramsHashRef ); } #------------------------------------------------------------------- @@ -989,10 +987,13 @@ See L sub deleteObject { my ( $self, $address ) = @_; + + $self->session->log->debug("Deleting object: " . join '-', @$address); # Each object checks the ref and then either updates or passes it to the correct child. # New objects will have an index of -1. my $message = $self->surveyJSON_remove($address); + $self->session->log->debug(Dumper($self->surveyJSON->{_sections})); # The parent address of the deleted object is returned. if ( @{$address} == 1 ) { @@ -1054,13 +1055,15 @@ sub www_dragDrop { my @bid = split /-/, $p->{before}->{id}; my $target = $self->surveyJSON->getObject( \@tid ); - $self->surveyJSON_remove( \@tid, 1 ); + $self->surveyJSON->remove( \@tid, 1 ); my $address = [0]; if ( @tid == 1 ) { - + #sections can only be inserted after another section so chop off the question and answer portion of $#bid = 0; $bid[0] = -1 if ( !defined $bid[0] ); + + $self->session->log->debug("Moving section $bid[0] to $tid[0]"); #If target is being moved down, then before has just moved up do to the target being deleted $bid[0]-- if($tid[0] < $bid[0]); @@ -1924,7 +1927,6 @@ sub persistSurveyJSON { my $data = $self->surveyJSON->freeze(); $self->update({surveyJSON=>$data}); -# $self->session->db->write( 'update Survey set surveyJSON = ? where assetId = ?', [ $data, $self->getId ] ); return; } diff --git a/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm b/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm index 10ad7ec9b..b588cc428 100644 --- a/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm +++ b/lib/WebGUI/Asset/Wobject/Survey/SurveyJSON.pm @@ -244,21 +244,21 @@ sub newObject { if ( $count == 0 ) { # Add a new section to the end of the list of sections.. - push @{ $self->sections }, $self->newSection(); + push @{ $self->{_sections} }, $self->newSection(); # Update $address with the index of the newly created section $address->[0] = $self->lastSectionIndex; } elsif ( $count == 1 ) { # Add a new question to the end of the list of questions in section located at $address - push @{ $self->questions($address) }, $self->newQuestion($address); + push @{ $self->section($address)->{questions} }, $self->newQuestion($address); # Update $address with the index of the newly created question $address->[1] = $self->lastQuestionIndex($address); } elsif ( $count == 2 ) { # Add a new answer to the end of the list of answers in section/question located at $address - push @{ $self->answers($address) }, $self->newAnswer($address); + push @{ $self->question($address)->{answers} }, $self->newAnswer($address); # Update $address with the index of the newly created answer $address->[2] = $self->lastAnswerIndex($address); @@ -674,18 +674,21 @@ sub uncompress { my ($smold, $qmold, $amold) = @{$self->mold}{'section', 'question', 'answer'}; # Iterate over all objects, adding back in the missing properties - for my $s (@{$sections || []}) { + for my $s (@$sections) { for my $q (@{$s->{questions} || []}) { for my $a (@{$q->{answers} || []}) { while (my($key, $value) = each %$amold) { + next if ref $value; $a->{$key} = $value unless exists $a->{$key}; } } while (my($key, $value) = each %$qmold) { + next if ref $value; $q->{$key} = $value unless exists $q->{$key}; } } while (my($key, $value) = each %$smold) { + next if ref $value; $s->{$key} = $value unless exists $s->{$key}; } } @@ -751,7 +754,7 @@ sub update { $object = $self->section($address); if ( !defined $object ) { $object = $self->newSection(); - push @{ $self->sections }, $object; + push @{ $self->{_sections} }, $object; } } elsif ( $count == 2 ) { @@ -759,7 +762,7 @@ sub update { if ( !defined $object ) { $object = $self->newQuestion(); $newQuestion = 1; # make note that a new question was created - push @{ $self->questions($address) }, $object; + push @{ $self->section($address)->{questions} }, $object; } # If questionType supplied, see if we need to update all of the answers to reflect the new questionType if ( $properties->{questionType} && $properties->{questionType} ne $object->{questionType} ) { @@ -770,17 +773,26 @@ sub update { $object = $self->answer($address); if ( !defined $object ) { $object = $self->newAnswer(); - push @{ $self->answers($address) }, $object; + push @{ $self->question($address)->{answers} }, $object; } } $self->_handleSpecialAnswerUpdates($address,$properties); + my $validSectionProps = $self->newSection; + my $validQuestionProps = $self->newQuestion; + my $validAnswerProps = $self->newAnswer; + # Update $object with all of the data in $properties while (my ($key, $value) = each %{$properties}) { if (defined $value) { $object->{$key} = $value; } + + # Only allow properties that we know about + delete $object->{$key} if $count == 1 and !exists $validSectionProps->{$key}; + delete $object->{$key} if $count == 2 and !exists $validQuestionProps->{$key}; + delete $object->{$key} if $count == 3 and !exists $validAnswerProps->{$key}; } return; @@ -849,15 +861,15 @@ sub insertObject { # Use splice to rearrange the relevant array of objects.. if ( $count == 1 ) { - splice @{ $self->sections($address) }, sIndex($address) +1, 0, $object; + splice @{ $self->{_sections} }, sIndex($address) +1, 0, $object; $address->[0]++; } elsif ( $count == 2 ) { - splice @{ $self->questions($address) }, qIndex($address) + 1, 0, $object; + splice @{ $self->section($address)->{questions} }, qIndex($address) + 1, 0, $object; $address->[1]++; } elsif ( $count == 3 ) { - splice @{ $self->answers($address) }, aIndex($address) + 1, 0, $object; + splice @{ $self->question($address)->{answers} }, aIndex($address) + 1, 0, $object; $address->[2]++; } @@ -903,21 +915,21 @@ sub copy { if ( $count == 1 ) { # Clone the indexed section onto the end of the list of sections.. - push @{ $self->sections }, clone $self->section($address); + push @{ $self->{_sections} }, clone $self->section($address); # Update $address with the index of the newly created section $address->[0] = $self->lastSectionIndex; } elsif ( $count == 2 ) { # Clone the indexed question onto the end of the list of questions.. - push @{ $self->questions($address) }, clone $self->question($address); + push @{ $self->section($address)->{questions} }, clone $self->question($address); # Update $address with the index of the newly created question $address->[1] = $self->lastQuestionIndex($address); } elsif ( $count == 3 ) { # Clone the indexed answer onto the end of the list of answers.. - push @{ $self->answers($address) }, clone $self->answer($address); + push @{ $self->question($address)->{answers} }, clone $self->answer($address); # Update $address with the index of the newly created answer $address->[2]++; @@ -969,14 +981,14 @@ sub remove { if ( $count == 1 ) { # Make sure the first section isn't removed unless we REALLY want to if ( sIndex($address) != 0 || defined $movingOverride ) { - splice @{ $self->sections }, sIndex($address), 1; + splice @{ $self->{_sections} }, sIndex($address), 1; } } elsif ( $count == 2 ) { - splice @{ $self->questions($address) }, qIndex($address), 1; + splice @{ $self->section($address)->{questions} }, qIndex($address), 1; } elsif ( $count == 3 ) { - splice @{ $self->answers($address) }, aIndex($address), 1; + splice @{ $self->question($address)->{answers} }, aIndex($address), 1; } return; @@ -1190,7 +1202,7 @@ Returns a reference to all the sections in this object. sub sections { my $self = shift; - return $self->{_sections}; + return $self->{_sections} || []; } =head2 mold @@ -1259,7 +1271,7 @@ Returns the total number of Sections sub totalSections { my $self = shift; - return scalar @{ $self->sections || [] }; + return scalar @{ $self->sections }; } =head2 totalQuestions ($address) @@ -1277,7 +1289,7 @@ sub totalQuestions { my ($address) = validate_pos(@_, { type => ARRAYREF, optional => 1 }); if ($address) { - return scalar @{ $self->questions($address) || [] }; + return scalar @{ $self->questions($address) }; } else { my $count = 0; for my $sIndex (0 .. $self->lastSectionIndex) { @@ -1302,7 +1314,7 @@ sub totalAnswers { my ($address) = validate_pos(@_, { type => ARRAYREF, optional => 1 }); if ($address) { - return scalar @{ $self->answers($address) || [] }; + return scalar @{ $self->answers($address) }; } else { my $count = 0; for my $sIndex (0 .. $self->lastSectionIndex) { @@ -1521,11 +1533,11 @@ sub questions { my ($address) = validate_pos(@_, { type => ARRAYREF, optional => 1}); if ($address) { - return $self->sections->[ $address->[0] ]->{questions}; + return $self->sections->[ $address->[0] ]->{questions} || []; } else { my $questions; push @$questions, @{$_->{questions} || []} for @{$self->sections}; - return $questions; + return $questions || []; } } @@ -1579,7 +1591,7 @@ sub answers { my $self = shift; my ($address) = validate_pos(@_, { type => ARRAYREF}); - return $self->sections->[ $address->[0] ]->{questions}->[ $address->[1] ]->{answers}; + return $self->sections->[ $address->[0] ]->{questions}->[ $address->[1] ]->{answers} || []; } =head2 answer ($address) diff --git a/t/Asset/Wobject/Survey/SurveyJSON.t b/t/Asset/Wobject/Survey/SurveyJSON.t index e3a4d87bc..dd381bd55 100644 --- a/t/Asset/Wobject/Survey/SurveyJSON.t +++ b/t/Asset/Wobject/Survey/SurveyJSON.t @@ -1980,7 +1980,7 @@ cmp_deeply( $address = $s->newObject([0]); is(scalar @{$s->questions}, 1, '..now 1 question'); is(scalar @{$s->questions([0])}, 1, '..in the first section'); - is($s->questions([2]), undef, '..and none in the second section (which doesnt even exist)'); + cmp_deeply($s->questions([2]), [], '..and none in the second section (which doesnt even exist)'); # Add a question to second section $address = $s->newObject([1]);