Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lang/en/qtype_stack.php
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,7 @@
$string['stackBlock_ascii_answer_format'] = 'The answer attribute of the ASCII block must be in the format \"[ans1,extractor,filter],[ans2,extractor,filter],...\".';
$string['stackBlock_ascii_unknown_param'] = 'Unknown parameter \'{$a}\' for the ASCII block.';
$string['stackBlock_ascii_param'] = 'Valid parameters are: {$a->param}.';
$string['stackBlock_ascii_incorrect_alignment'] = 'The output must be aligned left or right.';

$string['stackBlock_extractor_targetinput_required'] = 'You must define the targetinput for the extractor block to send the answer to.';
$string['stackBlock_extractor_type_required'] = 'You must define the type of extractor you want to use.';
Expand Down
18 changes: 16 additions & 2 deletions stack/cas/castext2/blocks/ascii.block.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ public function compile($format, $options): ?MP_Node {
$height = $existsuserheight ? $xpars['height'] : "400px";
$xpars['width'] = $width;
$xpars['height'] = $height;
$direction = stack_get_system_direction();
if (($xpars['align'] ?? null) === 'left') {
$direction = 'ltr';
} else if (($xpars['align'] ?? null) === 'right') {
$direction = 'rtl';
}
$xpars['stack-ascii-direction'] = $direction;

// Set a title.
$xpars['title'] = 'STACK ASCII ///ASCII_COUNT///';
Expand Down Expand Up @@ -287,22 +294,29 @@ public function validate(
$valid = false;
$err[] = stack_string('stackBlock_ascii_underdefined_dimension');
}
if (
array_key_exists('align', $this->params) && !in_array($this->params['align'], ['left', 'right'])
) {
$valid = false;
$err[] = stack_string('stackBlock_ascii_incorrect_alignment');
}

// Check that only valid parameters are passed to block header.
$valids = null;
foreach ($this->params as $key => $value) {
if (
$key !== 'width' &&
$key !== 'height' &&
$key !== 'aspect-ratio' &
$key !== 'aspect-ratio' &&
$key !== 'align' &&
$key !== 'input' &&
$key !== 'hidden'
) {
$err[] = stack_string('stackBlock_ascii_unknown_param', $key);
$valid = false;
if ($valids === null) {
$valids = [
'width', 'height', 'aspect-ratio', 'input', 'hidden',
'width', 'height', 'aspect-ratio', 'align', 'input', 'hidden',
];
$err[] = stack_string('stackBlock_ascii_param', [
'param' => implode(', ', $valids),
Expand Down
9 changes: 8 additions & 1 deletion stack/cas/castext2/blocks/iframe.block.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,15 @@ public function postprocess(
$code = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
$code .= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' .
' "http://www.w3.org/TR/xhtml1/DTD/strict.dtd">' . "\n";
$directionattribute = '';
if (isset($parameters['stack-ascii-direction'])) {
$direction = $parameters['stack-ascii-direction'];
if ($direction === 'ltr' || $direction === 'rtl') {
$directionattribute = ' dir="' . $direction . '"';
}
}
$code .= '<html xmlns="http://www.w3.org/TR/xhtml1/strict" lang="' .
stack_get_system_language() . '">';
stack_get_system_language() . '"' . $directionattribute . '>';
// Include a title to help JS debugging.
$code .= '<head><title>' . $title . '</title>';
$code .= $style;
Expand Down
1 change: 0 additions & 1 deletion styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -1247,7 +1247,6 @@ table.HELM_table th:last-child {
.que.stack .equivinput,
.que.stack .varmatrixinput,
.que.stack .matrixtable,
.que.stack .freetextinput,
/* Question authoring form */
#page-question-type-stack textarea#id_questionvariables,
#page-question-type-stack input#id_variantsselectionseed,
Expand Down
99 changes: 98 additions & 1 deletion tests/ascii_block_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

namespace qtype_stack;

use api\util\StackIframeHolder;
use castext2_evaluatable;
use qtype_stack_testcase;
use stack_cas_session2;
Expand Down Expand Up @@ -60,6 +61,30 @@ private function get_string_items(\MP_List $compiled): array {
return $strings;
}

/**
* Render an ASCII block and return the generated iframe document.
* @param string $raw
* @return string
*/
private function render_ascii_iframe_content(string $raw): string {
stack_cas_castext2_iframe::register_counter('///IFRAME_COUNT///');
StackIframeHolder::$islibrary = true;
StackIframeHolder::$iframes = [];

try {
$at1 = castext2_evaluatable::make_from_source($raw, 'test-case');
$session = new stack_cas_session2([$at1]);
$session->instantiate();
$at1->apply_placeholder_holder($at1->get_rendered());

$this->assertCount(1, StackIframeHolder::$iframes);
return StackIframeHolder::$iframes[0][1];
} finally {
StackIframeHolder::$islibrary = false;
StackIframeHolder::$iframes = [];
}
}

public function test_basic_ascii_block(): void {
stack_cas_castext2_iframe::register_counter('///IFRAME_COUNT///');

Expand All @@ -73,6 +98,32 @@ public function test_basic_ascii_block(): void {
$this->assertEquals($expected, $at1->apply_placeholder_holder($at1->get_rendered()));
}

public function test_ascii_iframe_document_uses_system_direction(): void {
$iframecontent = $this->render_ascii_iframe_content('[[ascii input="ans1"]][[/ascii]]');

$this->assertStringContainsString(
'<html xmlns="http://www.w3.org/TR/xhtml1/strict" lang="' . stack_get_system_language() .
'" dir="' . stack_get_system_direction() . '">',
$iframecontent
);
$this->assertStringContainsString('<div class="container row asciimath" id="asciiContainerRow"', $iframecontent);
$this->assertStringNotContainsString('id="asciiContainerRow" dir=', $iframecontent);
}

public function test_ascii_align_parameter_overrides_iframe_document_direction(): void {
$leftcontent = $this->render_ascii_iframe_content('[[ascii input="ans1" align="left"]][[/ascii]]');
$rightcontent = $this->render_ascii_iframe_content('[[ascii input="ans1" align="right"]][[/ascii]]');

$this->assertStringContainsString(
'<html xmlns="http://www.w3.org/TR/xhtml1/strict" lang="' . stack_get_system_language() . '" dir="ltr">',
$leftcontent
);
$this->assertStringContainsString(
'<html xmlns="http://www.w3.org/TR/xhtml1/strict" lang="' . stack_get_system_language() . '" dir="rtl">',
$rightcontent
);
}

public function test_ascii_block_with_filter_and_extractor_children(): void {
stack_cas_castext2_iframe::register_counter('///IFRAME_COUNT///');

Expand Down Expand Up @@ -102,6 +153,7 @@ public function test_ascii_compile_adds_default_filter_and_input_request(): void
$xpars = json_decode($compiled->items[1]->value, true);
$this->assertEquals('100%', $xpars['width']);
$this->assertEquals('400px', $xpars['height']);
$this->assertEquals(stack_get_system_direction(), $xpars['stack-ascii-direction']);
$this->assertStringContainsString('STACK ASCII', $xpars['title']);

$strings = $this->get_string_items($compiled);
Expand Down Expand Up @@ -131,6 +183,35 @@ public function test_ascii_compile_without_input_parameter_uses_empty_input_requ
$this->assertStringContainsString($expectedlinkcode, $joined);
}

public function test_ascii_align_parameter_sets_document_direction_only(): void {
$blockright = new \stack_cas_castext2_ascii(['align' => 'right'], []);
$compiledright = $blockright->compile(null, []);

$this->assertInstanceOf(\MP_List::class, $compiledright);

$xparsright = json_decode($compiledright->items[1]->value, true);
$this->assertEquals('rtl', $xparsright['stack-ascii-direction']);
$strings = $this->get_string_items($compiledright);
$joined = implode("\n", $strings);
$this->assertStringContainsString(
'<div class="container row asciimath" id="asciiContainerRow"',
$joined
);
$this->assertStringNotContainsString('algebraic-right', $joined);

$blockleft = new \stack_cas_castext2_ascii(['align' => 'left'], []);
$compiledleft = $blockleft->compile(null, []);
$this->assertInstanceOf(\MP_List::class, $compiledleft);
$xparsleft = json_decode($compiledleft->items[1]->value, true);
$this->assertEquals('ltr', $xparsleft['stack-ascii-direction']);
$joinedleft = implode("\n", $this->get_string_items($compiledleft));
$this->assertStringContainsString(
'<div class="container row asciimath" id="asciiContainerRow"',
$joinedleft
);
$this->assertStringNotContainsString('algebraic-right', $joinedleft);
}

public function test_ascii_compile_uses_child_filter_and_extractor_operations(): void {
$filter = new \stack_cas_castext2_filter([
'type' => 'markdown',
Expand Down Expand Up @@ -254,6 +335,22 @@ public function test_ascii_aspect_ratio_dimension_rules(): void {
$this->assertEquals(stack_string('stackBlock_ascii_underdefined_dimension'), $atunder->get_errors());
}

public function test_ascii_validate_alignment_parameter(): void {
$validleft = '[[ascii input="ans1" align="left"]][[/ascii]]';
$validright = '[[ascii input="ans1" align="right"]][[/ascii]]';
$invalid = '[[ascii input="ans1" align="center"]][[/ascii]]';

$atleft = castext2_evaluatable::make_from_source($validleft, 'test-case');
$this->assertTrue($atleft->get_valid());

$atright = castext2_evaluatable::make_from_source($validright, 'test-case');
$this->assertTrue($atright->get_valid());

$atinvalid = castext2_evaluatable::make_from_source($invalid, 'test-case');
$this->assertFalse($atinvalid->get_valid());
$this->assertEquals(stack_string('stackBlock_ascii_incorrect_alignment'), $atinvalid->get_errors());
}

public function test_ascii_unknown_param_rejected(): void {
$raw = '[[ascii input="ans1" bad_param="x"]][[/ascii]]';

Expand All @@ -262,7 +359,7 @@ public function test_ascii_unknown_param_rejected(): void {
$this->assertFalse($at1->get_valid());
$this->assertStringContainsString(stack_string('stackBlock_ascii_unknown_param', 'bad_param'), $at1->get_errors());
$this->assertStringContainsString(stack_string('stackBlock_ascii_param', [
'param' => 'width, height, aspect-ratio, input, hidden',
'param' => 'width, height, aspect-ratio, align, input, hidden',
]), $at1->get_errors());
}
}
7 changes: 7 additions & 0 deletions vle_specific.php
Original file line number Diff line number Diff line change
Expand Up @@ -370,3 +370,10 @@ function stack_fetch_included_content(string $url) {
function stack_get_system_language(): string {
return current_language();
}

/**
* Fetches the direction of the current VLE UI language.
*/
function stack_get_system_direction(): string {
return function_exists('right_to_left') && right_to_left() ? 'rtl' : 'ltr';
}
Loading