diff --git a/docs/upgrades/packages-7.7.6/root_import_survey_default-answer-edit.wgpkg b/docs/upgrades/packages-7.7.6/root_import_survey_default-answer-edit.wgpkg new file mode 100644 index 000000000..2201e358d Binary files /dev/null and b/docs/upgrades/packages-7.7.6/root_import_survey_default-answer-edit.wgpkg differ diff --git a/docs/upgrades/packages-7.7.6/root_import_survey_default-questions.wgpkg b/docs/upgrades/packages-7.7.6/root_import_survey_default-questions.wgpkg new file mode 100644 index 000000000..7b7edd2e2 Binary files /dev/null and b/docs/upgrades/packages-7.7.6/root_import_survey_default-questions.wgpkg differ diff --git a/lib/WebGUI/Asset/Wobject/Survey/ExpressionEngine.pm b/lib/WebGUI/Asset/Wobject/Survey/ExpressionEngine.pm index 30e358be6..4d3032411 100644 --- a/lib/WebGUI/Asset/Wobject/Survey/ExpressionEngine.pm +++ b/lib/WebGUI/Asset/Wobject/Survey/ExpressionEngine.pm @@ -171,50 +171,67 @@ sub answeredX { =head2 tag ($name, [$value]) -Mutator utility sub that gives expressions access to tag response values (and optionally set them). +Utility sub that allows expressions to tag data =head3 $name -Name of tag whose value is returned. +Name of tag to set =head3 $value (optional) -If provided, the tag is set to this value. +Value of tag to set. Defaults to 1 (boolean true flag). =cut sub tag { my ($name, $value) = @_; - if (defined $value) { - $session->log->debug("Setting tag [$name] to [$value]"); - $tags->{$name} = $value; - } else { - $value = $tags->{$name}; - $session->log->debug("tag($name) resolves to [$value]"); - } - return $value; + $value = 1 if !defined $value; + $session->log->debug("Setting tag [$name] to [$value]"); + $tags->{$name} = $value; } -=head2 tagX +=head2 tagged ($name) -Same as L, except that first argument is an asset spec (assetId or url), which must resolve -to a valid survey instance. The sub is applied to the most recent completed response for the user -on the survey instance given by asset_spec. +Utility sub that gives expressions access to tagged data -Note that it doesn't really make sense to try to set a tag on an external asset, so this sub -is only an accessor. +=head3 $name + +Name of tag whose value is returned. =cut -sub tagX { +sub tagged { + my ($name) = @_; + if (@_ == 2) { + my $args = join ',', @_; + $session->log->warn("Two arguments passed to tagged($args). Did you mean tag($args)?"); + } + my $value = $tags->{$name}; + $session->log->debug("tagged($name) resolves to [$value]"); + return $value; +} + +=head2 taggedX + +Same as L, except that first argument is an asset spec (assetId or url), which must resolve +to a valid survey instance. The sub is applied to the most recent completed response for the user +on the survey instance given by asset_spec. + +=cut + +sub taggedX { my ( $asset_spec, $name ) = @_; + if (@_ == 3) { + my $args = join ',', @_; + $session->log->warn("Three arguments passed to taggedX($args). Did you mean tag($args)?"); + } # See if $otherInstances already contains the external survey if (my $other_instance = $otherInstances->{$asset_spec}) { my $tags = $other_instance->{tags}; my $value = $tags->{$name}; - $session->log->debug("tagX($asset_spec, $name) returns [$value]"); + $session->log->debug("taggedX($asset_spec, $name) returns [$value]"); return $value; } else { # Throw an exception, triggering run() to resolve the external reference and re-run @@ -362,7 +379,8 @@ sub run { $compartment->share('&answered'); $compartment->share('&answeredX'); $compartment->share('&tag'); - $compartment->share('&tagX'); + $compartment->share('&tagged'); + $compartment->share('&taggedX'); $compartment->share('&jump'); $compartment->share('&avg'); diff --git a/lib/WebGUI/i18n/English/Asset_Survey.pm b/lib/WebGUI/i18n/English/Asset_Survey.pm index 73b945579..ff390c2e5 100644 --- a/lib/WebGUI/i18n/English/Asset_Survey.pm +++ b/lib/WebGUI/i18n/English/Asset_Survey.pm @@ -281,23 +281,23 @@ our $I18N = { lastUpdated => 1224686319 }, 'cols description' => { - message => q|The number of columns used for the comment TextArea input field.|, + message => q|The number of columns used for the input field (for TextArea question types).|, context => q|Description of the 'cols' field, used as hoverhelp in the edit question dialog.|, - lastUpdated => 0 + lastUpdated => 1241588599 }, 'comment rows' => { message => q|Comment Rows:|, lastUpdated => 1224686319 }, 'rows description' => { - message => q|The number of rows shown for the comment TextArea input field.|, + message => q|The number of rows used for the input field (for TextArea question types).|, context => q|Description of the 'rows' field, used as hoverhelp in the edit question dialog.|, - lastUpdated => 0 + lastUpdated => 1241588599 + }, + 'maximum number of answers' => { + message => q|Maximum number of answers:|, + lastUpdated => 1224686319 }, - 'maximum number of answers' => { - message => q|Maximum number of answers:|, - lastUpdated => 1224686319 - }, 'maximum number of answers description' => { message => q|Enter the maximum number of answers.|, context => q|Description of the 'maximum number of answers' field, used as hoverhelp in the edit question dialog.|, @@ -393,41 +393,41 @@ our $I18N = { lastUpdated => 1224686319 }, 'min label' => { - message => q|Slider Min|, - lastUpdated => 1224686319 + message => q|Min|, + lastUpdated => 1241588065 }, - 'min description' => { - message => q|The minimum value of this answer for slider type questions.|, - context => q|Description of the 'min' field, used as hoverhelp in the edit answer dialog.|, - lastUpdated => 0 - }, + 'min description' => { + message => q|The minimum numeric value allowed for this answer (for numeric question types such as Number and Slider). Keep this field empty if you do not want to enforce a minimum value. |, + context => q|Description of the 'min' field, used as hoverhelp in the edit answer dialog.|, + lastUpdated => 1241588065 + }, 'max label' => { - message => q|Slider Max|, - lastUpdated => 1224686319 + message => q|Max|, + lastUpdated => 1241588065 }, - 'max description' => { - message => q|The maximum value of this answer for slider type questions.|, - context => q|Description of the 'max' field, used as hoverhelp in the edit answer dialog.|, - lastUpdated => 0 - }, + 'max description' => { + message => q|The maximum numeric value allowed for this answer (for Number and Slider type questions). Keep this field empty if you do not want to enforce a maximum value. |, + context => q|Description of the 'max' field, used as hoverhelp in the edit answer dialog.|, + lastUpdated => 1241588065 + }, 'step label' => { - message => q|Slider Step|, - lastUpdated => 1224686319 + message => q|Step|, + lastUpdated => 1241588065 }, - 'step description' => { - message => q|The step value of this answer for slider type questions.|, - context => q|Description of the 'step' field, used as hoverhelp in the edit answer dialog.|, - lastUpdated => 0 - }, + 'step description' => { + message => q|The step value, that is, the numeric interval to allow between values (for Number and Slider type questions). Keep this field empty if you do not want to enforce a step value. |, + context => q|Description of the 'step' field, used as hoverhelp in the edit answer dialog.|, + lastUpdated => 0 + }, 'verbatim label' => { message => q|Verbatim|, lastUpdated => 1224686319 }, - 'verbatim description' => { - message => q|Set to yes to add an extra text input to the answer, where the user can enter a single line of text. Typically used to permit a free-text 'other' response.|, - context => q|Description of the 'verbatim' field, used as hoverhelp in the edit answer dialog.|, - lastUpdated => 0 - }, + 'verbatim description' => { + message => q|Set to yes to add an extra text input to the answer, where the user can enter a single line of text. Typically used to permit a free-text 'other' response.|, + context => q|Description of the 'verbatim' field, used as hoverhelp in the edit answer dialog.|, + lastUpdated => 0 + }, 'answer score' => { message => q|Answer score:|, lastUpdated => 1239251986 @@ -1358,13 +1358,23 @@ section/answer.|, 'textCols' => { message => q|The number of columns for TextArea questions.|, context => q|Description of a template variable for a template Help page.|, - lastUpdated => 0, + lastUpdated => 1241588599, + }, + + 'textCols label' => { + message => q|TextArea Columns|, + lastUpdated => 1241588599 }, 'textRows' => { message => q|The number of rows for TextArea questions.|, context => q|Description of a template variable for a template Help page.|, - lastUpdated => 0, + lastUpdated => 1241588599, + }, + + 'textRows label' => { + message => q|TextArea Rows|, + lastUpdated => 1241588599 }, 'answers' => { diff --git a/t/Asset/Wobject/Survey/ExpressionEngine.t b/t/Asset/Wobject/Survey/ExpressionEngine.t index d1f41ac1d..0c22c665e 100644 --- a/t/Asset/Wobject/Survey/ExpressionEngine.t +++ b/t/Asset/Wobject/Survey/ExpressionEngine.t @@ -22,7 +22,7 @@ my $session = WebGUI::Test->session; #---------------------------------------------------------------------------- # Tests -my $tests = 49; +my $tests = 50; plan tests => $tests + 1; #---------------------------------------------------------------------------- @@ -141,19 +141,24 @@ SKIP: { '..but can be changed' ); cmp_deeply( - $e->run( $session, q{ tag(b,1) }, { values => \%values, tags => { a => 1 } } ), + $e->run( $session, q{ tag(b) }, { values => \%values, tags => { a => 1 } } ), { jump => undef, tags => { a => 1, b => 1 } }, - '..and new values can be set' + '..and new values can be set (defaults to 1)' ); cmp_deeply( - $e->run( $session, q{ jump{ tag(a) == 'abc' } target }, { values => \%values, tags => { a => 'abc' } } ), + $e->run( $session, q{ jump{ tagged(a) } target }, { values => \%values, tags => { a => 1 } } ), + { jump => 'target', tags => { a => 1 } }, + '..flag can be checked with tagged()' + ); + cmp_deeply( + $e->run( $session, q{ jump{ tagged(a) eq 'abc' } target }, { values => \%values, tags => { a => 'abc' } } ), { jump => 'target', tags => { a => 'abc' } }, - '..tag value resolved by tag() with single arg' + '..and any sort of tagged data returned' ); cmp_deeply( - $e->run( $session, q{ tag(a,xyz); jump{ tag(a) == 'xyz' } target }, { values => {a => 'def'}, tags => { a => 'abc' } } ), + $e->run( $session, q{ tag(a,xyz); jump{ tagged(a) eq 'xyz' } target }, { values => {a => 'def'}, tags => { a => 'abc' } } ), { jump => 'target', tags => { a => 'xyz' } }, - '..overwritten tag value can be used too everything else' + '..overwritten tag data can be used too' ); # Create a test user @@ -207,7 +212,7 @@ SKIP: { { jump => 'target', tags => {} }, 'external score resolves ok too' ); cmp_deeply( $e->run( $session, qq{jump {scoreX('$url', ext_s0) == 200} target}, {userId => $user->userId} ), { jump => 'target', tags => {} }, 'external score section totals work too' ); - cmp_deeply( $e->run( $session, qq{jump {tagX('$url', ext_tag) == 199} target}, {userId => $user->userId} ), + cmp_deeply( $e->run( $session, qq{jump {taggedX('$url', ext_tag, 1) == 199} target}, {userId => $user->userId} ), { jump => 'target', tags => {} }, 'external tag lookups work too' ); } diff --git a/t/Asset/Wobject/Survey/ResponseJSON.t b/t/Asset/Wobject/Survey/ResponseJSON.t index f4020a932..5d3e5aef8 100644 --- a/t/Asset/Wobject/Survey/ResponseJSON.t +++ b/t/Asset/Wobject/Survey/ResponseJSON.t @@ -440,7 +440,7 @@ $rJSON->nextResponse(2); # pretend we just finished s0q2 cmp_deeply($rJSON->tags, {}, 'No tag data'); $rJSON->processExpression('tag(a,100)'); cmp_deeply($rJSON->tags, { a => 100 }, 'Tag data set'); -$rJSON->processExpression('tag(b,50); jump {tag(a) + tag(b) == 150} s1'); +$rJSON->processExpression('tag(b,50); jump {tagged(a) + tagged(b) == 150} s1'); cmp_deeply($rJSON->tags, { a => 100, b => 50 }, 'Tag data cumulative'); is($rJSON->nextResponse, 3, '..and is useful for jump expressions');