Skip to content

Commit

Permalink
MDL-29794 Initial support for re-using a shared grading form
Browse files Browse the repository at this point in the history
The patch introduces a new script templates.php that allows to search
for a previously shared form (template) and re-use it.

The patch also modifies the preview rendering of grading forms. Now
plugins are responsible for rendering the form itselft, without any
headers, descriptions etc (we need to embed the form preview into
various places so the caller looks after the frame).
  • Loading branch information
mudrd8mz committed Nov 1, 2011
1 parent 18dd4a6 commit 20836db
Show file tree
Hide file tree
Showing 10 changed files with 405 additions and 22 deletions.
42 changes: 31 additions & 11 deletions grade/grading/form/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -382,22 +382,13 @@ public function create_instance($raterid, $itemid = null) {
/**
* Returns the HTML code displaying the preview of the grading form
*
* Plugins are supposed to override/extend this. Ideally they should delegate
* Plugins are forced to override this. Ideally they should delegate
* the task to their own renderer.
*
* @param moodle_page $page the target page
* @return string
*/
public function render_preview(moodle_page $page) {

if (!$this->is_form_defined()) {
throw new coding_exception('It is the caller\'s responsibility to make sure that the form is actually defined');
}

$output = $page->get_renderer('core_grading');

return $output->preview_definition_header($this);
}
abstract public function render_preview(moodle_page $page);

/**
* Deletes the form definition and all the associated data
Expand All @@ -423,6 +414,35 @@ public function delete_definition() {
$this->definition = false;
}

/**
* Prepare the part of the search query to append to the FROM statement
*
* @param string $gdid the alias of grading_definitions.id column used by the caller
* @return string
*/
public static function sql_search_from_tables($gdid) {
return '';
}

/**
* Prepare the parts of the SQL WHERE statement to search for the given token
*
* The returned array cosists of the list of SQL comparions and the list of
* respective parameters for the comparisons. The returned chunks will be joined
* with other conditions using the OR operator.
*
* @param string $token token to search for
* @return array
*/
public static function sql_search_where($token) {
global $DB;

$subsql = array();
$params = array();

return array($subsql, $params);
}

////////////////////////////////////////////////////////////////////////////

/**
Expand Down
48 changes: 44 additions & 4 deletions grade/grading/form/rubric/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -366,16 +366,16 @@ public function get_renderer(moodle_page $page) {
*/
public function render_preview(moodle_page $page) {

// use the parent's method to render the common information about the form
$header = parent::render_preview($page);
if (!$this->is_form_defined()) {
throw new coding_exception('It is the caller\'s responsibility to make sure that the form is actually defined');
}

// append the rubric itself, using own renderer
$output = $this->get_renderer($page);
$criteria = $this->definition->rubric_criteria;
$options = $this->get_options();
$rubric = $output->display_rubric($criteria, $options, self::DISPLAY_PREVIEW, 'rubric');

return $header . $rubric;
return $rubric;
}

/**
Expand Down Expand Up @@ -411,6 +411,46 @@ public function render_grade($page, $itemid, $grading_info, $defaultcontent) {
$instances = $this->get_current_instances($itemid);
return $this->get_renderer($page)->display_instances($this->get_current_instances($itemid), $defaultcontent);
}

//// full-text search support /////////////////////////////////////////////

/**
* Prepare the part of the search query to append to the FROM statement
*
* @param string $gdid the alias of grading_definitions.id column used by the caller
* @return string
*/
public static function sql_search_from_tables($gdid) {
return " LEFT JOIN {gradingform_rubric_criteria} rc ON (rc.formid = $gdid)
LEFT JOIN {gradingform_rubric_levels} rl ON (rl.criterionid = rc.id)";
}

/**
* Prepare the parts of the SQL WHERE statement to search for the given token
*
* The returned array cosists of the list of SQL comparions and the list of
* respective parameters for the comparisons. The returned chunks will be joined
* with other conditions using the OR operator.
*
* @param string $token token to search for
* @return array
*/
public static function sql_search_where($token) {
global $DB;

$subsql = array();
$params = array();

// search in rubric criteria description
$subsql[] = $DB->sql_like('rc.description', '?', false, false);
$params[] = '%'.$DB->sql_like_escape($token).'%';

// search in rubric levels definition
$subsql[] = $DB->sql_like('rl.definition', '?', false, false);
$params[] = '%'.$DB->sql_like_escape($token).'%';

return array($subsql, $params);
}
}

/**
Expand Down
45 changes: 45 additions & 0 deletions grade/grading/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,51 @@ public function create_shared_area($method) {
return $DB->insert_record('grading_areas', $area);
}

/**
* Helper method to tokenize the given string
*
* Splits the given string into smaller strings. This is a helper method for
* full text searching in grading forms. If the given string is surrounded with
* double quotes, the resulting array consists of a single item containing the
* quoted content.
*
* Otherwise, string like 'grammar, english language' would be tokenized into
* the three tokens 'grammar', 'english', 'language'.
*
* One-letter tokens like are dropped in non-phrase mode. Repeated tokens are
* returned just once.
*
* @param string $needle
* @return array
*/
public static function tokenize($needle) {

// check if we are searching for the exact phrase
if (preg_match('/^[\s]*"[\s]*(.*?)[\s]*"[\s]*$/', $needle, $matches)) {
$token = $matches[1];
if ($token === '') {
return array();
} else {
return array($token);
}
}

// split the needle into smaller parts separated by non-word characters
$tokens = preg_split("/\W/u", $needle);
// keep just non-empty parts
$tokens = array_filter($tokens);
// distinct
$tokens = array_unique($tokens);
// drop one-letter tokens
foreach ($tokens as $ix => $token) {
if (strlen($token) == 1) {
unset($tokens[$ix]);
}
}

return array_values($tokens);
}

////////////////////////////////////////////////////////////////////////////

/**
Expand Down
2 changes: 1 addition & 1 deletion grade/grading/manage.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
} else {
echo $output->management_action_icon($controller->get_editor_url($returnurl),
get_string('manageactionnew', 'core_grading'), 'b/document-new');
$pickurl = new moodle_url('/grade/grading/pick.php', array('targetid' => $controller->get_areaid()));
$pickurl = new moodle_url('/grade/grading/templates.php', array('targetid' => $controller->get_areaid()));
if (!is_null($returnurl)) {
$pickurl->param('returnurl', $returnurl->out(false));
}
Expand Down
15 changes: 9 additions & 6 deletions grade/grading/renderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,18 @@ public function management_message($message) {
}

/**
* Renders the common information about the form definition
* Renders the template action icon
*
* @param gradingform_controller $controller
* @param moodle_url $url action URL
* @param string $text action text
* @param string $icon the name of the icon to use
* @param string $class extra class of this action
* @return string
*/
public function preview_definition_header(gradingform_controller $controller) {
public function pick_action_icon(moodle_url $url, $text, $icon = '', $class = '') {

$definition = $controller->get_definition();
// todo make this nicer, append the information about the time created/modified etc
return $this->output->heading(format_text($definition->name));
$img = html_writer::empty_tag('img', array('src' => $this->output->pix_url($icon), 'class' => 'action-icon'));
$txt = html_writer::tag('div', $text, array('class' => 'action-text'));
return html_writer::link($url, $img . $txt, array('class' => 'action '.$class));
}
}
29 changes: 29 additions & 0 deletions grade/grading/simpletest/testlib.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,33 @@ public function test_set_and_get_grading_area() {
$this->expectException('moodle_exception');
$gradingman->set_active_method('no_one_should_ever_try_to_implement_a_method_with_this_silly_name');
}

public function test_tokenize() {

$needle = " šašek, \n\n \r a král; \t";
$tokens = testable_grading_manager::tokenize($needle);
$this->assertEqual(2, count($tokens));
$this->assertTrue(in_array('šašek', $tokens));
$this->assertTrue(in_array('král', $tokens));

$needle = ' " šašek a král " ';
$tokens = testable_grading_manager::tokenize($needle);
$this->assertEqual(1, count($tokens));
$this->assertTrue(in_array('šašek a král', $tokens));

$needle = '""';
$tokens = testable_grading_manager::tokenize($needle);
$this->assertTrue(empty($tokens));

$needle = '"0"';
$tokens = testable_grading_manager::tokenize($needle);
$this->assertEqual(1, count($tokens));
$this->assertTrue(in_array('0', $tokens));

$needle = '<span>Aha</span>, then who\'s a bad guy here he?';
$tokens = testable_grading_manager::tokenize($needle);
$this->assertTrue(in_array('span', $tokens));
$this->assertTrue(in_array('Aha', $tokens));
$this->assertTrue(in_array('who', $tokens));
}
}
Loading

0 comments on commit 20836db

Please sign in to comment.