Commit 4e16f800 authored by Kurzenberger's avatar Kurzenberger
Browse files

refactored the code for the code checker plugin

parent 0e5e6553
Pipeline #10747 passed with stage
Showing with 903 additions and 675 deletions
+903 -675
<?php
namespace assignsubmission_dta;
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
......@@ -15,92 +14,119 @@ namespace assignsubmission_dta;
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* persistence layer utility class
*
* @package assignsubmission_dta
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @copyright Gero Lueckemeyer and student project teams
*/
namespace assignsubmission_dta;
use assignsubmission_dta\dta_backend_utils;
use assignsubmission_dta\dta_view_submission_utils;
use assignsubmission_dta\models\dta_result;
use assignsubmission_dta\models\dta_result_summary;
use assignsubmission_dta\models\dta_recommendation;
/**
* Class dta_db_utils
*
* Persistence layer utility class for storing and retrieving
* DTA plugin data (results, summaries, recommendations).
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class dta_db_utils {
/**
* Summary database table name.
*/
private const ASSIGNSUBMISSION_DTA_TABLE_SUMMARY = "assignsubmission_dta_summary";
private const ASSIGNSUBMISSION_DTA_TABLE_SUMMARY = 'assignsubmission_dta_summary';
/**
* Result database table name.
*/
private const ASSIGNSUBMISSION_DTA_TABLE_RESULT = "assignsubmission_dta_result";
private const ASSIGNSUBMISSION_DTA_TABLE_RESULT = 'assignsubmission_dta_result';
private const ASSIGNSUBMISSION_DTA_TABLE_RECOMMENDATIONS = "assignsubmission_dta_recommendations";
/**
* Recommendations database table name.
*/
private const ASSIGNSUBMISSION_DTA_TABLE_RECOMMENDATIONS = 'assignsubmission_dta_recommendations';
public static function assignsubmission_dta_get_recommendations_from_database(int $assignmentid, int $submissionid): array {
global $DB,$USER;
/**
* Returns an array of recommendations from the database.
*
* @param int $assignmentid The assignment ID.
* @param int $submissionid The submission ID.
* @return array An array of recommendation records.
*/
public static function assignsubmission_dta_get_recommendations_from_database(
int $assignmentid,
int $submissionid
): array {
global $DB, $USER;
$userid = $USER->id;
// Schritt 1: Alle Empfehlungen abrufen
$records = $DB->get_records(self::ASSIGNSUBMISSION_DTA_TABLE_RECOMMENDATIONS, [
// Step 1: Retrieve all recommendations.
$records = $DB->get_records(
self::ASSIGNSUBMISSION_DTA_TABLE_RECOMMENDATIONS,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]);
]
);
// Schritt 2: Modul-ID für 'assign' abrufen
// Step 2: Retrieve module ID for 'assign'.
$module = $DB->get_record('modules', ['name' => 'assign'], 'id');
if (!$module) {
// Fehlerbehandlung, falls das Modul nicht gefunden wird
// Handle error case if the module is not found.
return $records;
}
$moduleid = $module->id;
print_r($records);
// Schritt 3: Überprüfe jeden Datensatz
// Step 3: Check each record.
foreach ($records as $key => $record) {
// Hol den Namen der Übung aus dem Datensatz
// Get the name of the exercise from the record.
$exercisename = $record->exercise_name;
// Suche das Assignment mit diesem Namen
// Find the assignment with this name.
$assign = $DB->get_record('assign', ['name' => $exercisename], 'id');
if ($assign) {
// Hole die Kursmodul-ID (coursemoduleid) für dieses Assignment
$cm = $DB->get_record('course_modules', [
// Get the course module ID for this assignment.
$cm = $DB->get_record(
'course_modules',
[
'module' => $moduleid,
'instance' => $assign->id
], 'id');
'instance' => $assign->id,
],
'id'
);
if ($cm) {
// Überprüfe den Abschlussstatus für dieses Kursmodul und den Benutzer
$completion = $DB->get_record('course_modules_completion', [
// Check the completion status for this course module and user.
$completion = $DB->get_record(
'course_modules_completion',
[
'coursemoduleid' => $cm->id,
'userid' => $userid
], 'completionstate');
'userid' => $userid,
],
'completionstate'
);
// Wenn der Abschlussstatus 1 ist, entferne den Datensatz aus $records
if ($completion && $completion->completionstate == 1) {
// If the completion state is 1, remove the record from $records.
if ($completion && (int)$completion->completionstate === 1) {
unset($records[$key]);
}
}
}
}
// Rückgabe der gefilterten Datensätze
// Return the filtered records.
return $records;
}
/**
* gets summary with all corresponding result entries
* Gets a summary with all corresponding result entries.
*
* @param int $assignmentid assignment id to search for
* @param int $submissionid submission id to search for
* @return DttResultSummary representing given submission
* @param int $assignmentid Assignment ID to search for.
* @param int $submissionid Submission ID to search for.
* @return dta_result_summary Summary representing the submission.
*/
public static function assignsubmission_dta_get_result_summary_from_database(
int $assignmentid,
......@@ -109,15 +135,21 @@ class dta_db_utils {
global $DB;
// Fetch data from database.
$summaryrecord = $DB->get_record(self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY, [
"assignment_id" => $assignmentid,
"submission_id" => $submissionid,
]);
$summaryrecord = $DB->get_record(
self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
$resultsarray = $DB->get_records(self::ASSIGNSUBMISSION_DTA_TABLE_RESULT, [
"assignment_id" => $assignmentid,
"submission_id" => $submissionid,
]);
$resultsarray = $DB->get_records(
self::ASSIGNSUBMISSION_DTA_TABLE_RESULT,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]
);
// Create a summary instance.
$summary = new dta_result_summary();
......@@ -146,55 +178,69 @@ class dta_db_utils {
return $summary;
}
/**
* Stores an array of recommendations in the database.
*
* @param int $assignmentid The assignment ID.
* @param int $submissionid The submission ID.
* @param array $recommendations An array of dta_recommendation objects.
*/
public static function assignsubmission_dta_store_recommendations_to_database(
int $assignmentid,
int $submissionid,
array $recommendations
): void {
global $DB;
error_log(print_r($recommendations, true));
// Debug output (you can remove or adapt this if unneeded).
debugging('Recommendations array: ' . json_encode($recommendations));
// If recommendations already exist, delete old values beforehand.
$existingrecords = $DB->get_records('assignsubmission_dta_recommendations', [
$existingrecords = $DB->get_records(
'assignsubmission_dta_recommendations',
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]);
]
);
if ($existingrecords) {
$DB->delete_records('assignsubmission_dta_recommendations', [
$DB->delete_records(
'assignsubmission_dta_recommendations',
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]);
]
);
}
// Create new recommendation entries.
foreach ($recommendations as $recommendation) {
// Ensure $recommendation is an instance of DtaRecommendation
// Check if $recommendation is an instance of dta_recommendation.
if ($recommendation instanceof dta_recommendation) {
// Add assignment and submission IDs to the recommendation object
// Add assignment and submission IDs to the recommendation object.
$recommendation->assignment_id = $assignmentid;
$recommendation->submission_id = $submissionid;
error_log("Insert record");
error_log(print_r($recommendation, true));
debugging('Inserting new recommendation record: ' . json_encode($recommendation));
// Insert the recommendation into the database
// Insert the recommendation into the database.
$DB->insert_record('assignsubmission_dta_recommendations', $recommendation);
} else {
// Handle the case where $recommendation is not a DtaRecommendation instance
error_log("Invalid recommendation object");
// Handle the case where $recommendation is not a dta_recommendation instance.
debugging('Invalid recommendation object encountered.');
}
}
}
/**
* save given result summary and single results to database
* under given assignment and submission id
* Saves the given result summary and single results to the database
* under the specified assignment and submission ID.
*
* @param int $assignmentid assigment this is submission is linked to
* @param int $submissionid submission of this result
* @param dta_result_summary $summary instance to persist
* @param int $assignmentid Assignment this submission is linked to.
* @param int $submissionid Submission ID for these results.
* @param dta_result_summary $summary Summary instance to persist.
*/
public static function assignsubmission_dta_store_result_summary_to_database(
int $assignmentid,
......@@ -212,7 +258,7 @@ class dta_db_utils {
$summaryrecord->successful_competencies = $summary->successfultestcompetencies;
$summaryrecord->tested_competencies = $summary->overalltestcompetencies;
// Prepare results to persist to array.
// Prepare results to persist.
$resultrecords = [];
foreach ($summary->results as $r) {
$record = new dta_result();
......@@ -232,21 +278,30 @@ class dta_db_utils {
}
// If results already exist, delete old values beforehand.
$submission = $DB->get_record(self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY, [
$submission = $DB->get_record(
self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]);
]
);
if ($submission) {
$DB->delete_records(self::ASSIGNSUBMISSION_DTA_TABLE_RESULT, [
$DB->delete_records(
self::ASSIGNSUBMISSION_DTA_TABLE_RESULT,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]);
]
);
$DB->delete_records(self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY, [
$DB->delete_records(
self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY,
[
'assignment_id' => $assignmentid,
'submission_id' => $submissionid,
]);
]
);
}
// Create summary and single result entries.
......@@ -257,7 +312,7 @@ class dta_db_utils {
}
/**
* cleans up database if plugin is uninstalled
* Cleans up database if plugin is uninstalled.
*/
public static function assignsubmission_dta_uninstall_plugin_cleaup(): void {
global $DB;
......@@ -265,7 +320,5 @@ class dta_db_utils {
$DB->delete_records(self::ASSIGNSUBMISSION_DTA_TABLE_RESULT, null);
$DB->delete_records(self::ASSIGNSUBMISSION_DTA_TABLE_SUMMARY, null);
$DB->delete_records(self::ASSIGNSUBMISSION_DTA_TABLE_RECOMMENDATIONS, null);
}
}
<?php
// This file is part of Moodle - http://moodle.org/
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
......@@ -16,40 +15,44 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This file contains the backend webservice contact functionality for the DTA plugin
* This file contains the backend webservice contact functionality for the DTA plugin.
*
* @package assignsubmission_dta
* @copyright 2023 Your Name
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace assignsubmission_dta;
/**
* Backend webservice contact utility class
* Backend webservice contact utility class.
*
* @package assignsubmission_dta
* @copyright 2023 Your Name
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace assignsubmission_dta;
defined('MOODLE_INTERNAL') || die();
class dta_backend_utils {
/**
* Component name for the plugin.
*/
const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = 'assignsubmission_dta';
public const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = 'assignsubmission_dta';
/**
* Returns the base URL of the backend webservice as configured in the administration settings.
* @return string Backend host base URL
*
* @return string Backend host base URL.
*/
private static function assignsubmission_dta_get_backend_baseurl(): string {
$backendaddress = get_config(self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME, 'backendHost');
$backendaddress = get_config(
self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME,
'backendHost'
);
if (empty($backendaddress)) {
\core\notification::error(get_string('backendHost_not_set', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
\core\notification::error(
get_string('backendHost_not_set', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
}
return $backendaddress;
......@@ -58,9 +61,9 @@ class dta_backend_utils {
/**
* Sends the configuration text file uploaded by the teacher to the backend.
*
* @param \assign $assignment Assignment this test-config belongs to
* @param \stored_file $file Uploaded test-config
* @return bool True if no error occurred
* @param \assign $assignment Assignment this test-config belongs to.
* @param \stored_file $file Uploaded test-config.
* @return bool True if no error occurred.
*/
public static function assignsubmission_dta_send_testconfig_to_backend($assignment, $file): bool {
$backendaddress = self::assignsubmission_dta_get_backend_baseurl();
......@@ -88,12 +91,16 @@ class dta_backend_utils {
/**
* Sends submission config or archive to backend to be tested.
*
* @param \assign $assignment Assignment for the submission
* @param int $submissionid Submission ID of the current file
* @param \stored_file $file Submission config file or archive with submission
* @return string|null JSON string with test results or null on error
* @param \assign $assignment Assignment for the submission.
* @param int $submissionid Submission ID of the current file.
* @param \stored_file $file Submission config file or archive with submission.
* @return string|null JSON string with test results or null on error.
*/
public static function assignsubmission_dta_send_submission_to_backend($assignment, $submissionid, $file): ?string {
public static function assignsubmission_dta_send_submission_to_backend(
$assignment,
int $submissionid,
$file
): ?string {
$backendaddress = self::assignsubmission_dta_get_backend_baseurl();
if (empty($backendaddress)) {
return null;
......@@ -113,12 +120,12 @@ class dta_backend_utils {
/**
* Posts the given params to the given URL and returns the response as a string.
* @param string $url Full URL to request to
* @param array $params Parameters for HTTP request
*
* @return string|null Received body on success or null on error
* @param string $url Full URL to request.
* @param array $params Parameters for HTTP request.
* @return string|null Received body on success or null on error.
*/
private static function assignsubmission_dta_post($url, $params): ?string {
private static function assignsubmission_dta_post(string $url, array $params): ?string {
if (!isset($url) || !isset($params)) {
return null;
}
......@@ -128,23 +135,32 @@ class dta_backend_utils {
$curl = new \curl();
$response = $curl->post($url, $params, $options);
// Check state of request, if response code is a 2xx return the answer.
// Check state of request, if response code is 2xx, return the answer.
$info = $curl->get_info();
if ($info['http_code'] >= 200 && $info['http_code'] < 300) {
return $response;
}
// Something went wrong, return null and give an error message.
debugging(self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME . ': Post file to server was not successful: http_code=' . $info['http_code']);
// Something went wrong, return null and display an error message.
$msg = self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME
. ': Post file to server was not successful. HTTP code='
. $info['http_code'];
debugging($msg);
if ($info['http_code'] >= 400 && $info['http_code'] < 500) {
\core\notification::error(get_string('http_client_error_msg', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
\core\notification::error(
get_string('http_client_error_msg', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
return null;
} else if ($info['http_code'] >= 500 && $info['http_code'] < 600) {
\core\notification::error(get_string('http_server_error_msg', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
\core\notification::error(
get_string('http_server_error_msg', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
return null;
} else {
\core\notification::error(get_string('http_unknown_error_msg', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME) . $info['http_code'] . $response);
$unknownmsg = get_string('http_unknown_error_msg', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
. $info['http_code'] . ' ' . $response;
\core\notification::error($unknownmsg);
return null;
}
}
......
<?php
namespace assignsubmission_dta;
// This file is part of Moodle - http://moodle.org/
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
......@@ -15,263 +14,316 @@ namespace assignsubmission_dta;
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* utility class for DTA submission plugin result display
*
* @package assignsubmission_dta
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace assignsubmission_dta;
use assignsubmission_dta\dta_db_utils;
use assignsubmission_dta\dta_backend_utils;
use assignsubmission_dta\models\dta_result;
use assignsubmission_dta\models\dta_result_summary;
use assignsubmission_dta\models\dta_recommendation;
/**
* Utility class for DTA submission plugin result display.
*
* @package assignsubmission_dta
* @copyright 2023 Your Name <you@example.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class dta_view_submission_utils {
/**
* Broadly used in logic, parametrized for easier change.
*/
const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = "assignsubmission_dta";
public const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = 'assignsubmission_dta';
/**
* generates a short summary html
* Generates a short summary HTML.
*
* @param int $assignmentid assignment
* @param int $submissionid submission to create a report for
* @return string html
* @param int $assignmentid The assignment ID.
* @param int $submissionid The submission ID to create a report for.
* @return string HTML summary.
*/
public static function assignsubmission_dta_generate_summary_html(
int $assignmentid,
int $submissionid
): string {
// Fetch data.
$summary = dta_db_utils::assignsubmission_dta_get_result_summary_from_database($assignmentid, $submissionid);
$html = "";
$summary = dta_db_utils::assignsubmission_dta_get_result_summary_from_database(
$assignmentid,
$submissionid
);
$html = '';
// Calculate success rate, if no unknown result states or compilation errors.
$successrate = "?";
if ($summary->unknown_count() == 0 && $summary->compilation_error_count() == 0) {
$successrate = round(($summary->successful_count() / $summary->result_count()) * 100, 2 );
$successrate = '?';
if ($summary->unknown_count() === 0 && $summary->compilation_error_count() === 0) {
$successrate = round(($summary->successful_count() / $summary->result_count()) * 100, 2);
}
// Generate html.
$html .= $summary->successful_count() . "/";
$html .= ($summary->compilation_error_count() == 0 && $summary->unknown_count() == 0)
? $summary->result_Count() . " (" . $successrate . "%)"
: "?";
$html .= get_string("tests_successful", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME) . "<br />";
// Generate HTML.
$html .= $summary->successful_count() . '/';
if ($summary->compilation_error_count() === 0 && $summary->unknown_count() === 0) {
$html .= $summary->result_count() . ' (' . $successrate . '%)';
} else {
$html .= '?';
}
$html .= get_string('tests_successful', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME) . '<br />';
if ($summary->compilation_error_count() > 0) {
$html .= $summary->compilation_error_count() . get_string("compilation_errors", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME) . "<br />";
$html .= $summary->compilation_error_count()
. get_string('compilation_errors', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
. '<br />';
}
if ($summary->unknown_count() > 0) {
$html .= $summary->unknown_count() . get_string("unknown_state", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME) . "<br />";
$html .= $summary->unknown_count()
. get_string('unknown_state', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
. '<br />';
}
$showncompetencies = explode(";", $summary->successfultestcompetencies);
$overallcompetencies = explode(";", $summary->overalltestcompetencies);
$showncompetencies = explode(';', $summary->successfultestcompetencies);
$overallcompetencies = explode(';', $summary->overalltestcompetencies);
$tmp = "";
$tmp = '';
for ($index = 0, $size = count($showncompetencies); $index < $size; $index++) {
$shown = $showncompetencies[$index];
$comp = $overallcompetencies[$index];
// If the competency was actually assessed by the assignment and tests, add a summary entry.
if ($shown != "0") {
$tmp .= get_string("comp" . $index, self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME) .
" " . 100 * floatval($shown) / floatval($comp) . "% " . "<br />";
// If the competency was actually assessed, add a summary entry.
if ($shown !== '0') {
$tmp .= get_string('comp' . $index, self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
. ' ' . (100 * floatval($shown) / floatval($comp)) . '% ' . '<br />';
}
}
$html .= get_string("success_competencies", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME) . "<br />" . $tmp . "<br />";
$html .= get_string('success_competencies', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
. '<br />' . $tmp . '<br />';
return \html_writer::div($html, "dtaSubmissionSummary");
return \html_writer::div($html, 'dtaSubmissionSummary');
}
/**
* generates detailed view html
/**
* Generates detailed view HTML.
*
* @param int $assignmentid assignment
* @param int $submissionid submission to create a report for
* @param int $assignmentid The assignment ID.
* @param int $submissionid The submission to create a report for.
* @return string HTML detail view.
*/
public static function assignsubmission_dta_generate_detail_html(
public static function assignsubmission_dta_generate_detail_html(
int $assignmentid,
int $submissionid
): string {
): string {
// Fetch data.
$summary = dta_db_utils::assignsubmission_dta_get_result_summary_from_database($assignmentid, $submissionid);
$recommendations = dta_db_utils::assignsubmission_dta_get_recommendations_from_database($assignmentid, $submissionid);
$summary = dta_db_utils::assignsubmission_dta_get_result_summary_from_database(
$assignmentid,
$submissionid
);
$recommendations = dta_db_utils::assignsubmission_dta_get_recommendations_from_database(
$assignmentid,
$submissionid
);
$html = "";
$html = '';
// Define a few css classes and prepare html attribute arrays to beautify the output.
$tableheaderrowattributes = ["class" => "dtaTableHeaderRow"];
$tablerowattributes = ["class" => "dtaTableRow"];
// *** Summary Table ***
$tableheaderrowattributes = ['class' => 'dtaTableHeaderRow'];
$tablerowattributes = ['class' => 'dtaTableRow'];
$resultrowattributes = $tablerowattributes;
$unknownattributes = 'dtaResultUnknown';
$successattributes = 'dtaResultSuccess';
$failureattributes = 'dtaResultFailure';
$compilationerrorattributes = 'dtaResultCompilationError';
$attributes = ["class" => "dtaTableData"];
$attributes = ['class' => 'dtaTableData'];
// ***************
// SUMMARY TABLE
// ***************
$tmp = "";
$tmp .= \html_writer::tag("th", get_string("summary", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), ["class" => "dtaTableHeader"]);
$tmp .= \html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
$header = \html_writer::tag("tr", $tmp, $tableheaderrowattributes);
$header = \html_writer::tag("thead", $header);
// Building summary table.
$tmp = \html_writer::tag(
'th',
get_string('summary', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
['class' => 'dtaTableHeader']
);
$tmp .= \html_writer::empty_tag('th', ['class' => 'dtaTableHeader']);
$header = \html_writer::tag('tr', $tmp, $tableheaderrowattributes);
$header = \html_writer::tag('thead', $header);
$body = "";
$body = '';
// Total items.
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("total_items", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $summary->result_count(), $attributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('total_items', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $summary->result_count(), $attributes);
$resultrowattributes = $tablerowattributes;
$resultrowattributes['class'] .= " " . $unknownattributes;
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$resultrowattributes['class'] .= ' ' . $unknownattributes;
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
// Tests successful.
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("tests_successful", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $summary->successful_count(), $attributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('tests_successful', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $summary->successful_count(), $attributes);
$resultrowattributes = $tablerowattributes;
$successrate = "?";
$successrate = '?';
if ($summary->unknown_count() > 0 || $summary->compilation_error_count() > 0) {
$resultrowattributes['class'] .= " " . $unknownattributes;
$resultrowattributes['class'] .= ' ' . $unknownattributes;
} else {
$successrate = round(($summary->successful_count() / $summary->result_count()) * 100, 2);
$successrate = round(
($summary->successful_count() / $summary->result_count()) * 100,
2
);
if ($successrate < 50) {
$resultrowattributes['class'] .= " " . $compilationerrorattributes;
$resultrowattributes['class'] .= ' ' . $compilationerrorattributes;
} else if ($successrate < 75) {
$resultrowattributes['class'] .= " " . $failureattributes;
$resultrowattributes['class'] .= ' ' . $failureattributes;
} else {
$resultrowattributes['class'] .= " " . $successattributes;
$resultrowattributes['class'] .= ' ' . $successattributes;
}
}
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
// Failures.
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("failures", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $summary->failed_count(), $attributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('failures', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $summary->failed_count(), $attributes);
$resultrowattributes = $tablerowattributes;
if ($summary->failed_count() > 0) {
$resultrowattributes['class'] .= " " . $failureattributes;
$resultrowattributes['class'] .= ' ' . $failureattributes;
} else {
$resultrowattributes['class'] .= " " . $successattributes;
$resultrowattributes['class'] .= ' ' . $successattributes;
}
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
// Compilation errors.
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("compilation_errors", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $summary->compilation_error_count(), $attributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('compilation_errors', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $summary->compilation_error_count(), $attributes);
$resultrowattributes = $tablerowattributes;
if ($summary->compilation_error_count() > 0) {
$resultrowattributes['class'] .= " " . $compilationerrorattributes;
$resultrowattributes['class'] .= ' ' . $compilationerrorattributes;
} else {
$resultrowattributes['class'] .= " " . $successattributes;
$resultrowattributes['class'] .= ' ' . $successattributes;
}
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
// Unknown state.
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("unknown_state", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $summary->unknown_count(), $attributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('unknown_state', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $summary->unknown_count(), $attributes);
$resultrowattributes = $tablerowattributes;
if ($summary->unknown_count() > 0) {
$resultrowattributes['class'] .= " " . $unknownattributes;
$resultrowattributes['class'] .= ' ' . $unknownattributes;
} else {
$resultrowattributes['class'] .= " " . $successattributes;
$resultrowattributes['class'] .= ' ' . $successattributes;
}
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
// Success rate.
$tmp = "";
$tmp .= \html_writer::tag("td", \html_writer::tag("b", get_string("success_rate", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)), $attributes);
$tmp = '';
$tmp .= \html_writer::tag(
"td",
\html_writer::tag("b", $summary->successful_count() . "/" .
(($summary->compilation_error_count() == 0 && $summary->unknown_count() == 0)
? $summary->result_count() . " (" . $successrate . "%)"
: "?")),
'td',
\html_writer::tag(
'b',
get_string('success_rate', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
),
$attributes
);
$suffix = '?';
if ($summary->compilation_error_count() === 0 && $summary->unknown_count() === 0) {
$suffix = $summary->result_count() . ' (' . $successrate . '%)';
}
$tmp .= \html_writer::tag(
'td',
\html_writer::tag(
'b',
$summary->successful_count() . '/' . $suffix
),
$attributes
);
$resultrowattributes = $tablerowattributes;
if ($summary->unknown_count() > 0 || $summary->compilation_error_count() > 0) {
$resultrowattributes['class'] .= " " . $unknownattributes;
} else {
if ($successrate < 50) {
$resultrowattributes['class'] .= " " . $compilationerrorattributes;
} else if ($successrate < 75) {
$resultrowattributes['class'] .= " " . $failureattributes;
$resultrowattributes['class'] .= ' ' . $unknownattributes;
} else {
$resultrowattributes['class'] .= " " . $successattributes;
if ($successrate !== '?' && $successrate < 50) {
$resultrowattributes['class'] .= ' ' . $compilationerrorattributes;
} else if ($successrate !== '?' && $successrate < 75) {
$resultrowattributes['class'] .= ' ' . $failureattributes;
} else if ($successrate !== '?') {
$resultrowattributes['class'] .= ' ' . $successattributes;
}
}
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
$body = \html_writer::tag("tbody", $body);
$table = \html_writer::tag("table", $header . $body, ["class" => "dtaTable"]);
$body = \html_writer::tag('tbody', $body);
$table = \html_writer::tag('table', $header . $body, ['class' => 'dtaTable']);
$html .= $table;
// Add empty div for spacing after summary.
$html .= \html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
$html .= \html_writer::empty_tag('div', ['class' => 'dtaSpacer']);
// ***************
// RECOMMENDATIONS TABLE
// ***************
// *** Recommendations Table ***
if (!empty($recommendations)) {
// Sorting logic.
$allowed_sort_fields = ['topic', 'exercise_name', 'difficulty', 'score'];
$allowed_sort_dirs = ['asc', 'desc'];
$allowedsortfields = ['topic', 'exercise_name', 'difficulty', 'score'];
$allowedsortdirs = ['asc', 'desc'];
$sortby = isset($_POST['sortby']) ? $_POST['sortby'] : 'score';
$sortdir = isset($_POST['sortdir']) ? $_POST['sortdir'] : 'asc';
if (!in_array($sortby, $allowed_sort_fields)) {
if (!in_array($sortby, $allowedsortfields)) {
$sortby = 'score';
}
if (!in_array($sortdir, $allowed_sort_dirs)) {
if (!in_array($sortdir, $allowedsortdirs)) {
$sortdir = 'asc';
}
usort($recommendations, function($a, $b) use ($sortby, $sortdir) {
$valueA = $a->{$sortby};
$valueB = $b->{$sortby};
usort($recommendations, function ($a, $b) use ($sortby, $sortdir) {
$valuea = $a->{$sortby};
$valueb = $b->{$sortby};
if (is_numeric($valueA) && is_numeric($valueB)) {
$comparison = $valueA - $valueB;
if (is_numeric($valuea) && is_numeric($valueb)) {
$comparison = $valuea - $valueb;
} else {
$comparison = strnatcasecmp($valueA, $valueB);
$comparison = strnatcasecmp($valuea, $valueb);
}
if ($comparison == 0) {
if ($comparison === 0) {
return 0;
}
if ($sortdir == 'asc') {
if ($sortdir === 'asc') {
return ($comparison < 0) ? -1 : 1;
} else {
return ($comparison < 0) ? 1 : -1;
}
});
$html .= \html_writer::tag('h3', get_string('recommendations', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
$html .= \html_writer::tag(
'h3',
get_string('recommendations', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
$generate_sortable_header = function($column_name, $display_name) use ($sortby, $sortdir) {
$new_sortdir = ($sortby == $column_name && $sortdir == 'asc') ? 'desc' : 'asc';
$generatesortableheader = function ($columnname, $displayname) use ($sortby, $sortdir) {
$newsortdir = ($sortby === $columnname && $sortdir === 'asc') ? 'desc' : 'asc';
$class = 'dtaTableHeader';
if ($sortby == $column_name) {
if ($sortby === $columnname) {
$class .= ' sorted ' . $sortdir;
}
......@@ -279,104 +331,142 @@ public static function assignsubmission_dta_generate_detail_html(
$button = \html_writer::empty_tag('input', [
'type' => 'submit',
'name' => 'sortbutton',
'value' => ($new_sortdir == 'asc' ? '↑' : '↓'),
'class' => 'sort-button'
'value' => ($newsortdir === 'asc' ? '↑' : '↓'),
'class' => 'sort-button',
]);
// Hidden inputs.
$hidden_inputs = \html_writer::empty_tag('input', [
$hiddeninputs = \html_writer::empty_tag('input', [
'type' => 'hidden',
'name' => 'sortby',
'value' => $column_name
'value' => $columnname,
]);
$hidden_inputs .= \html_writer::empty_tag('input', [
$hiddeninputs .= \html_writer::empty_tag('input', [
'type' => 'hidden',
'name' => 'sortdir',
'value' => $new_sortdir
'value' => $newsortdir,
]);
$form = \html_writer::start_tag('form', ['method' => 'post', 'style' => 'display:inline']);
$form .= $hidden_inputs;
$form .= $display_name . ' ' . $button;
$form = \html_writer::start_tag('form', [
'method' => 'post',
'style' => 'display:inline',
]);
$form .= $hiddeninputs;
$form .= $displayname . ' ' . $button;
$form .= \html_writer::end_tag('form');
return \html_writer::tag("th", $form, ["class" => $class]);
return \html_writer::tag('th', $form, ['class' => $class]);
};
// Table header for recommendations.
$tableheader = "";
$tableheader .= $generate_sortable_header('topic', get_string("topic", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
$tableheader .= $generate_sortable_header('exercise_name', get_string("exercise_name", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
$tableheader .= \html_writer::tag("th", get_string("url", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), ["class" => "dtaTableHeader"]);
$tableheader .= $generate_sortable_header('difficulty', get_string("difficulty", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
$tableheader .= $generate_sortable_header('score', get_string("score", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
$tableheader = '';
$tableheader .= $generatesortableheader(
'topic',
get_string('topic', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
$tableheader .= $generatesortableheader(
'exercise_name',
get_string('exercise_name', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
$tableheader .= \html_writer::tag(
'th',
get_string('url', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
['class' => 'dtaTableHeader']
);
$tableheader .= $generatesortableheader(
'difficulty',
get_string('difficulty', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
$tableheader .= $generatesortableheader(
'score',
get_string('score', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
$tableheader = \html_writer::tag("tr", $tableheader, ["class" => "dtaTableHeaderRow"]);
$tableheader = \html_writer::tag("thead", $tableheader);
$tableheader = \html_writer::tag('tr', $tableheader, ['class' => 'dtaTableHeaderRow']);
$tableheader = \html_writer::tag('thead', $tableheader);
// Table body for recommendations.
$tablebody = "";
$tablebody = '';
foreach ($recommendations as $recommendation) {
$tablerow = "";
$tablerow .= \html_writer::tag("td", $recommendation->topic, $attributes);
$tablerow .= \html_writer::tag("td", $recommendation->exercise_name, $attributes);
$tablerow .= \html_writer::tag("td", \html_writer::link($recommendation->url, $recommendation->url), $attributes);
$tablerow .= \html_writer::tag("td", $recommendation->difficulty, $attributes);
$tablerow .= \html_writer::tag("td", $recommendation->score, $attributes);
$row = '';
$row .= \html_writer::tag('td', $recommendation->topic, $attributes);
$row .= \html_writer::tag('td', $recommendation->exercise_name, $attributes);
$row .= \html_writer::tag(
'td',
\html_writer::link($recommendation->url, $recommendation->url),
$attributes
);
$row .= \html_writer::tag('td', $recommendation->difficulty, $attributes);
$row .= \html_writer::tag('td', $recommendation->score, $attributes);
$tablebody .= \html_writer::tag("tr", $tablerow, $tablerowattributes);
$tablebody .= \html_writer::tag('tr', $row, $tablerowattributes);
}
$tablebody = \html_writer::tag("tbody", $tablebody);
$tablebody = \html_writer::tag('tbody', $tablebody);
$html .= \html_writer::tag("table", $tableheader . $tablebody, ["class" => "dtaTable"]);
$html .= \html_writer::tag('table', $tableheader . $tablebody, ['class' => 'dtaTable']);
// Add empty div for spacing after recommendations.
$html .= \html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
$html .= \html_writer::empty_tag('div', ['class' => 'dtaSpacer']);
}
// ***************
// COMPETENCY ASSESSMENT TABLE
// ***************
$body = "";
$tmp = "";
$tmp .= \html_writer::tag("th", get_string("competencies", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), ["class" => "dtaTableHeader"]);
$tmp .= \html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
$header = \html_writer::tag("tr", $tmp, $tableheaderrowattributes);
$header = \html_writer::tag("thead", $header);
// *** Competency Assessment Table ***
$body = '';
$tmp = '';
$tmp .= \html_writer::tag(
'th',
get_string('competencies', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
['class' => 'dtaTableHeader']
);
$tmp .= \html_writer::empty_tag('th', ['class' => 'dtaTableHeader']);
$header = \html_writer::tag('tr', $tmp, $tableheaderrowattributes);
$header = \html_writer::tag('thead', $header);
$showncompetencies = explode(";", $summary->successfultestcompetencies);
$overallcompetencies = explode(";", $summary->overalltestcompetencies);
$showncompetencies = explode(';', $summary->successfultestcompetencies);
$overallcompetencies = explode(';', $summary->overalltestcompetencies);
for ($index = 0, $size = count($overallcompetencies); $index < $size; $index++) {
$comp = $overallcompetencies[$index];
$shown = $showncompetencies[$index];
// If the competency was actually assessed by the assignment and tests, add a row in the table.
if ($comp != "0") {
// If the competency was assessed, add a row in the table.
if ($comp !== '0') {
$resultrowattributes = $tablerowattributes;
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("comp" . $index, self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $resultrowattributes);
$tmp .= \html_writer::tag("td", (100 * floatval($shown) / floatval($comp)) . "% (" . $shown . " / " . $comp . ")", $resultrowattributes);
$tmp .= \html_writer::tag("td", get_string("comp_expl" . $index, self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $resultrowattributes);
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('comp' . $index, self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$resultrowattributes
);
$tmp .= \html_writer::tag(
'td',
(100 * floatval($shown) / floatval($comp)) . '% (' . $shown . ' / ' . $comp . ')',
$resultrowattributes
);
$tmp .= \html_writer::tag(
'td',
get_string('comp_expl' . $index, self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$resultrowattributes
);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
}
}
$body = \html_writer::tag("tbody", $body);
$html .= \html_writer::tag("table", $header . $body, ["class" => "dtaTable"]);
// Add empty div for spacing between competency and details table.
$html .= \html_writer::empty_tag("div", ["class" => "dtaSpacer"]);
$body = \html_writer::tag('tbody', $body);
$html .= \html_writer::tag('table', $header . $body, ['class' => 'dtaTable']);
// ***************
// DETAILS TABLE
// ***************
// Add empty div for spacing.
$html .= \html_writer::empty_tag('div', ['class' => 'dtaSpacer']);
$tmp = "";
$tmp .= \html_writer::tag("th", get_string("details", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), ["class" => "dtaTableHeader"]);
$tmp .= \html_writer::empty_tag("th", ["class" => "dtaTableHeader"]);
$header = \html_writer::tag("tr", $tmp, $tableheaderrowattributes);
$header = \html_writer::tag("thead", $header);
// *** Details Table ***
$tmp = '';
$tmp .= \html_writer::tag(
'th',
get_string('details', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
['class' => 'dtaTableHeader']
);
$tmp .= \html_writer::empty_tag('th', ['class' => 'dtaTableHeader']);
$header = \html_writer::tag('tr', $tmp, $tableheaderrowattributes);
$header = \html_writer::tag('thead', $header);
$body = "";
$body = '';
$spacerrow = null;
foreach ($summary->results as $r) {
// Add spacer first if not null.
......@@ -387,84 +477,127 @@ public static function assignsubmission_dta_generate_detail_html(
$resultrowattributes = $tablerowattributes;
// Set CSS class for colored left-border according to results state.
if ($r->state == 0) {
if ($r->state === 0) {
$resultrowattributes['class'] .= ' dtaResultUnknown';
} else if ($r->state == 1) {
} else if ($r->state === 1) {
$resultrowattributes['class'] .= ' dtaResultSuccess';
} else if ($r->state == 2) {
} else if ($r->state === 2) {
$resultrowattributes['class'] .= ' dtaResultFailure';
} else if ($r->state == 3) {
} else if ($r->state === 3) {
$resultrowattributes['class'] .= ' dtaResultCompilationError';
}
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("package_name", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $r->packagename, $attributes);
$tmp .= \html_writer::tag("td", get_string("unit_name", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $r->classname, $attributes);
$tmp .= \html_writer::tag("td", get_string("test_name", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $r->name, $attributes);
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('package_name', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $r->packagename, $attributes);
$tmp .= \html_writer::tag(
'td',
get_string('unit_name', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $r->classname, $attributes);
$tmp .= \html_writer::tag(
'td',
get_string('test_name', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $r->name, $attributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("status", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", dta_result::assignsubmission_dta_get_statename($r->state), $attributes);
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('status', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag(
'td',
dta_result::assignsubmission_dta_get_statename($r->state),
$attributes
);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
// If state is different than successful, show additional info.
if ($r->state != 1) {
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("failure_type", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $r->failureType, $attributes);
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
if ($r->state !== 1) {
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('failure_type', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $r->failureType, $attributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("failure_reason", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $r->failureReason, $attributes);
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('failure_reason', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $r->failureReason, $attributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
if (!is_null($r->lineNumber) && $r->lineNumber > 0) {
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("line_no", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $r->lineNumber, $attributes);
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('line_no', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $r->lineNumber, $attributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
}
if (!is_null($r->columnNumber) && $r->columnNumber > 0) {
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("col_no", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $r->columnNumber, $attributes);
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('col_no', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $r->columnNumber, $attributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
}
if (!is_null($r->position) && $r->position > 0) {
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("pos", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", $r->position, $attributes);
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('pos', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag('td', $r->position, $attributes);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
}
$tmp = "";
$tmp .= \html_writer::tag("td", get_string("stacktrace", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME), $attributes);
$tmp .= \html_writer::tag("td", \html_writer::tag("details", $r->stacktrace, ["class" => "dtaStacktraceDetails"]), $attributes);
$body .= \html_writer::tag("tr", $tmp, $resultrowattributes);
$tmp = '';
$tmp .= \html_writer::tag(
'td',
get_string('stacktrace', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
$attributes
);
$tmp .= \html_writer::tag(
'td',
\html_writer::tag('details', $r->stacktrace, ['class' => 'dtaStacktraceDetails']),
$attributes
);
$body .= \html_writer::tag('tr', $tmp, $resultrowattributes);
}
if (is_null($spacerrow)) {
$spacerrow = \html_writer::empty_tag("tr", ["class" => "dtaTableSpacer"]);
$spacerrow = \html_writer::empty_tag('tr', ['class' => 'dtaTableSpacer']);
}
}
$html .= \html_writer::tag("table", $header . $body, ["class" => "dtaTable"]);
$html .= \html_writer::tag('table', $header . $body, ['class' => 'dtaTable']);
// Wrap generated html into final div.
$html = \html_writer::div($html, "dtaSubmissionDetails");
// Wrap generated HTML into final div.
$html = \html_writer::div($html, 'dtaSubmissionDetails');
return $html;
}
}
}
<?php
// This file is part of Moodle - http://moodle.org/
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
......@@ -15,7 +15,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Entity class for DTA submission plugin recommendation
* Entity class for DTA submission plugin recommendation.
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer
......@@ -24,10 +24,8 @@
namespace assignsubmission_dta\models;
defined('MOODLE_INTERNAL') || die();
/**
* Entity class for DTA submission plugin recommendation
* Entity class for DTA submission plugin recommendation.
*
* @package assignsubmission_dta
* @copyright 2023
......@@ -41,9 +39,9 @@ class dta_recommendation {
public $topic;
/**
* @var string $exercise_name Name of the exercise.
* @var string $exerciseName Name of the exercise.
*/
public $exercise_name;
public $exerciseName;
/**
* @var string $url URL of the exercise.
......@@ -61,22 +59,22 @@ class dta_recommendation {
public $score;
/**
* Decodes the JSON recommendations returned by the backend service call into an array of DtaRecommendation objects.
* Decodes the JSON recommendations returned by the backend service call into an array of dta_recommendation objects.
*
* @param string $jsonstring JSON string containing recommendations
* @return array Array of DtaRecommendation objects
* @param string $jsonstring JSON string containing recommendations.
* @return array Array of dta_recommendation objects.
*/
public static function assignsubmission_dta_decode_json_recommendations(string $jsonstring): array {
$response = json_decode($jsonstring);
$recommendations = [];
// Prüfe, ob Empfehlungen vorhanden sind
// Check if recommendations exist.
if (!empty($response->recommendations)) {
foreach ($response->recommendations as $recommendation) {
$rec = new dta_recommendation();
$rec->topic = $recommendation->topic ?? null;
$rec->exercise_name = $recommendation->url ?? null;
// Map correct fields to the renamed variable names:
$rec->exerciseName = $recommendation->url ?? null;
$rec->url = $recommendation->exerciseName ?? null;
$rec->difficulty = $recommendation->difficulty ?? null;
$rec->score = $recommendation->score ?? null;
......
<?php
// This file is part of Moodle - http://moodle.org/
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
......@@ -15,7 +15,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Entity class for DTA submission plugin result
* Entity class for DTA submission plugin result.
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer and student project teams
......@@ -24,10 +24,8 @@
namespace assignsubmission_dta\models;
defined('MOODLE_INTERNAL') || die();
/**
* Entity class for DTA submission plugin result
* Entity class for DTA submission plugin result.
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer and student project teams
......@@ -38,7 +36,7 @@ class dta_result {
/**
* Broadly used in logic, parametrized for easier change.
*/
const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = 'assignsubmission_dta';
public const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = 'assignsubmission_dta';
/**
* @var string $packagename Package name of the test.
......@@ -97,15 +95,15 @@ class dta_result {
/**
* Returns the name of a state with the given number for display.
*
* @param int $state Number of the state
* @return string Name of state as defined
* @param int $state Number of the state.
* @return string Name of state as defined.
*/
public static function assignsubmission_dta_get_statename(int $state): string {
if ($state == 1) {
if ($state === 1) {
return get_string('tests_successful', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
} else if ($state == 2) {
} else if ($state === 2) {
return get_string('failures', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
} else if ($state == 3) {
} else if ($state === 3) {
return get_string('compilation_errors', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
} else {
return get_string('unknown_state', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
......
<?php
// This file is part of Moodle - http://moodle.org/
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
......@@ -15,7 +15,7 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Entity class for DTA submission plugin result summary
* Entity class for DTA submission plugin result summary.
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer and student project teams
......@@ -24,10 +24,8 @@
namespace assignsubmission_dta\models;
defined('MOODLE_INTERNAL') || die();
/**
* Entity class for DTA submission plugin result summary
* Entity class for DTA submission plugin result summary.
*
* @package assignsubmission_dta
* @copyright 2023 Gero Lueckemeyer and student project teams
......@@ -36,22 +34,22 @@ defined('MOODLE_INTERNAL') || die();
class dta_result_summary {
/**
* @var int $timestamp Result timestamp for chronological ordering and deletion of previous results.
* @var int $timestamp Timestamp for ordering and deletion of previous results.
*/
public $timestamp;
/**
* @var string $globalstacktrace Global stack trace if applicable, empty string otherwise.
* @var string $globalstacktrace Global stack trace if applicable, empty otherwise.
*/
public $globalstacktrace;
/**
* @var string $successfultestcompetencies Successfully tested competencies according to tests and weights, empty string otherwise.
* @var string $successfultestcompetencies Successfully tested competencies (tests and weights), or empty string.
*/
public $successfultestcompetencies;
/**
* @var string $overalltestcompetencies Overall tested competencies according to tests and weights, empty string otherwise.
* @var string $overalltestcompetencies Overall tested competencies (tests and weights), or empty string.
*/
public $overalltestcompetencies;
......@@ -63,8 +61,8 @@ class dta_result_summary {
/**
* Decodes the JSON result summary returned by the backend service call into the plugin PHP data structure.
*
* @param string $jsonstring JSON string containing DtaResultSummary
* @return DtaResultSummary The result summary
* @param string $jsonstring JSON string containing DtaResultSummary.
* @return dta_result_summary The result summary.
*/
public static function assignsubmission_dta_decode_json(string $jsonstring): dta_result_summary {
$response = json_decode($jsonstring);
......@@ -82,10 +80,10 @@ class dta_result_summary {
}
/**
* Decodes the array of JSON detail results returned by the backend service call into the plugin PHP data structure.
* Decodes an array of JSON detail results into the plugin PHP data structure.
*
* @param array $jsonarray Decoded JSON array of results
* @return array Array of DtaResult
* @param array $jsonarray Decoded JSON array of results.
* @return array Array of dta_result objects.
*/
private static function assignsubmission_dta_decode_json_result_array(array $jsonarray): array {
$ret = [];
......@@ -94,13 +92,10 @@ class dta_result_summary {
$value->packagename = $entry->packageName ?? '';
$value->classname = $entry->className ?? '';
$value->name = $entry->name ?? '';
$value->state = $entry->state ?? 0;
$value->failuretype = $entry->failureType ?? '';
$value->failurereason = $entry->failureReason ?? '';
$value->stacktrace = $entry->stacktrace ?? '';
$value->columnnumber = $entry->columnNumber ?? '';
$value->linenumber = $entry->lineNumber ?? '';
$value->position = $entry->position ?? '';
......@@ -113,7 +108,7 @@ class dta_result_summary {
/**
* Returns the number of detail results attached to the summary.
*
* @return int Count of occurrences
* @return int Count of occurrences.
*/
public function assignsubmission_dta_result_count(): int {
return count($this->results);
......@@ -122,13 +117,13 @@ class dta_result_summary {
/**
* Returns the number of detail results with the given state attached to the summary.
*
* @param int $state State ordinal number
* @return int Count of occurrences for the provided state
* @param int $state State ordinal number.
* @return int Count of occurrences for the provided state.
*/
public function assignsubmission_dta_state_occurence_count(int $state): int {
$num = 0;
foreach ($this->results as $r) {
if ($r->state == $state) {
if ($r->state === $state) {
$num++;
}
}
......@@ -138,7 +133,7 @@ class dta_result_summary {
/**
* Returns the number of detail results with compilation errors attached to the summary.
*
* @return int Count of occurrences
* @return int Count of occurrences.
*/
public function assignsubmission_dta_compilation_error_count(): int {
return $this->assignsubmission_dta_state_occurence_count(3);
......@@ -147,7 +142,7 @@ class dta_result_summary {
/**
* Returns the number of detail results with test failures attached to the summary.
*
* @return int Count of occurrences
* @return int Count of occurrences.
*/
public function assignsubmission_dta_failed_count(): int {
return $this->assignsubmission_dta_state_occurence_count(2);
......@@ -156,7 +151,7 @@ class dta_result_summary {
/**
* Returns the number of detail results with successful tests attached to the summary.
*
* @return int Count of occurrences
* @return int Count of occurrences.
*/
public function assignsubmission_dta_successful_count(): int {
return $this->assignsubmission_dta_state_occurence_count(1);
......@@ -165,7 +160,7 @@ class dta_result_summary {
/**
* Returns the number of detail results with an unknown result attached to the summary.
*
* @return int Count of occurrences
* @return int Count of occurrences.
*/
public function assignsubmission_dta_unknown_count(): int {
return $this->assignsubmission_dta_state_occurence_count(0);
......
<?php
// This file is part of Moodle - http://moodle.org/
// This file is part of Moodle - http://moodle.org/.
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
......@@ -14,8 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
defined('MOODLE_INTERNAL') || die();
use assignsubmission_dta\dta_db_utils;
use assignsubmission_dta\dta_backend_utils;
use assignsubmission_dta\dta_view_submission_utils;
......@@ -24,9 +22,10 @@ use assignsubmission_dta\models\dta_result_summary;
use assignsubmission_dta\models\dta_recommendation;
/**
* Library class for DTA submission plugin extending assign submission plugin base class
* Library class for DTA submission plugin extending assign submission plugin base class.
*
* @package assignsubmission_dta
* @copyright 2023 Your Name or Organization
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class assign_submission_dta extends assign_submission_plugin {
......@@ -34,40 +33,47 @@ class assign_submission_dta extends assign_submission_plugin {
/**
* Broadly used in logic, parametrized for easier change.
*/
const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = "assignsubmission_dta";
public const ASSIGNSUBMISSION_DTA_COMPONENT_NAME = 'assignsubmission_dta';
/**
* Draft file area for DTA tests to be uploaded by the teacher.
*/
const ASSIGNSUBMISSION_DTA_DRAFT_FILEAREA_TEST = "tests_draft_dta";
public const ASSIGNSUBMISSION_DTA_DRAFT_FILEAREA_TEST = 'tests_draft_dta';
/**
* File area for DTA tests to be uploaded by the teacher.
*/
const ASSIGNSUBMISSION_DTA_FILEAREA_TEST = "tests_dta";
public const ASSIGNSUBMISSION_DTA_FILEAREA_TEST = 'tests_dta';
/**
* File area for DTA submission assignment.
*/
const ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION = "submissions_dta";
public const ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION = 'submissions_dta';
/**
* Get plugin name
* Get plugin name.
*
* @return string
*/
public function assignsubmission_dta_get_name(): string {
return get_string("pluginname", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
return get_string('pluginname', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME);
}
/**
* Get default settings for assignment submission settings
* Get default settings for assignment submission settings.
*
* @param MoodleQuickForm $mform form to add elements to
* @param MoodleQuickForm $mform Form to add elements to.
* @return void
*/
public function assignsubmission_dta_get_settings(MoodleQuickForm $mform): void {
// Add draft filemanager to form.
$mform->addElement(
"filemanager",
'filemanager',
self::ASSIGNSUBMISSION_DTA_DRAFT_FILEAREA_TEST,
get_string("submission_settings_label", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
get_string(
'submission_settings_label',
self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME
),
null,
$this->get_file_options(true)
);
......@@ -77,7 +83,7 @@ class assign_submission_dta extends assign_submission_plugin {
// Form-unique element id to which to add button.
self::ASSIGNSUBMISSION_DTA_DRAFT_FILEAREA_TEST,
// Key.
"submission_settings_label",
'submission_settings_label',
// Language file to use.
self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME
);
......@@ -96,12 +102,15 @@ class assign_submission_dta extends assign_submission_plugin {
/**
* Allows the plugin to update the default values passed into
* the settings form (needed to set up draft areas for editor
* and filemanager elements)
* @param array $defaultvalues
* and filemanager elements).
*
* @param array $defaultvalues Default values to update.
*/
public function data_preprocessing(&$defaultvalues): void {
// Get id of draft area for file manager creation.
$draftitemid = file_get_submitted_draft_itemid(self::ASSIGNSUBMISSION_DTA_DRAFT_FILEAREA_TEST);
$draftitemid = file_get_submitted_draft_itemid(
self::ASSIGNSUBMISSION_DTA_DRAFT_FILEAREA_TEST
);
// Prepare draft area with created draft filearea.
file_prepare_draft_area(
......@@ -117,14 +126,13 @@ class assign_submission_dta extends assign_submission_plugin {
}
/**
* Save settings of assignment submission settings
* Save settings of assignment submission settings.
*
* @param stdClass $data
* @param stdClass $data Form data.
* @return bool
*/
public function assignsubmission_dta_save_settings(stdClass $data): bool {
// If the assignment has no filemanager for our plugin just leave.
// If the assignment has no filemanager for our plugin, just leave.
$draftfilemanagerid = self::ASSIGNSUBMISSION_DTA_DRAFT_FILEAREA_TEST;
if (!isset($data->$draftfilemanagerid)) {
return true;
......@@ -155,7 +163,9 @@ class assign_submission_dta extends assign_submission_plugin {
// Check if a file was uploaded.
if (empty($files)) {
\core\notification::error(get_string("no_testfile_warning", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
\core\notification::error(
get_string('no_testfile_warning', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
return true;
}
......@@ -163,19 +173,27 @@ class assign_submission_dta extends assign_submission_plugin {
$file = reset($files);
// Send file to backend.
return dta_backend_utils::assignsubmission_dta_send_testconfig_to_backend($this->assignment, $file);
return dta_backend_utils::assignsubmission_dta_send_testconfig_to_backend(
$this->assignment,
$file
);
}
/**
* Add elements to submission form
* Add elements to submission form.
*
* @param mixed $submissionorgrade stdClass|null submission or grade to show in the form
* @param MoodleQuickForm $mform form for adding elements
* @param stdClass $data data for filling the elements
* @param int $userid current user
* @return bool form elements added
* @param stdClass|null $submissionorgrade Submission or grade to show in the form.
* @param MoodleQuickForm $mform Form for adding elements.
* @param stdClass $data Data for filling the elements.
* @param int $userid Current user.
* @return bool True if form elements added.
*/
public function get_form_elements_for_user($submissionorgrade, MoodleQuickForm $mform, stdClass $data, $userid): bool {
public function get_form_elements_for_user(
$submissionorgrade,
MoodleQuickForm $mform,
stdClass $data,
$userid
): bool {
// Prepare submission filearea.
$data = file_prepare_standard_filemanager(
$data,
......@@ -193,20 +211,15 @@ class assign_submission_dta extends assign_submission_plugin {
// Form-unique identifier.
'tasks_filemanager',
// Label to show next to the filemanager.
get_string("submission_label", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
// Attributes.
get_string('submission_label', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
null,
// Options.
$this->get_file_options(false)
);
// Add help button.
$mform->addHelpButton(
// Related form item.
"tasks_filemanager",
// Key.
"submission_label",
// Language file.
'tasks_filemanager',
'submission_label',
self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME
);
......@@ -215,40 +228,46 @@ class assign_submission_dta extends assign_submission_plugin {
/**
* Determines if a submission file area contains any files.
* @param stdClass $submission submission to check
* @return bool true if file count is zero
*
* @param stdClass $submission Submission to check.
* @return bool True if file count is zero.
*/
public function assignsubmission_dta_is_empty(stdClass $submission): bool {
return $this->assignsubmission_dta_count_files($submission->id, self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION) == 0;
return ($this->assignsubmission_dta_count_files(
$submission->id,
self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION
) === 0);
}
/**
* Counts the number of files in a filearea
* Counts the number of files in a filearea.
*
* @param int $submissionid submission id to check
* @param string $areaid filearea id to count
* @return int number of files submitted in the filearea
* @param int $submissionid Submission id to check.
* @param string $areaid Filearea id to count.
* @return int Number of files submitted in the filearea.
*/
private function assignsubmission_dta_count_files(int $submissionid, $areaid) {
private function assignsubmission_dta_count_files(int $submissionid, $areaid): int {
$fs = get_file_storage();
$files = $fs->get_area_files($this->assignment->get_context()->id,
$files = $fs->get_area_files(
$this->assignment->get_context()->id,
self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME,
$areaid,
$submissionid,
'id',
false);
false
);
return count($files);
}
/**
* Save data to the database
* Save data to the database.
*
* @param stdClass $submission
* @param stdClass $data
* @return bool
* @param stdClass $submission Submission object.
* @param stdClass $data Data from the form.
* @return bool True if saved successfully.
*/
public function save(stdClass $submission, stdClass $data) {
public function save(stdClass $submission, stdClass $data): bool {
$data = file_postupdate_standard_filemanager(
$data,
'tasks',
......@@ -267,7 +286,6 @@ class assign_submission_dta extends assign_submission_plugin {
// Get submitted files.
$fs = get_file_storage();
$files = $fs->get_area_files(
// Id of current assignment.
$this->assignment->get_context()->id,
self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME,
self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION,
......@@ -278,15 +296,22 @@ class assign_submission_dta extends assign_submission_plugin {
// Check if a file is uploaded.
if (empty($files)) {
\core\notification::error(get_string("no_submissionfile_warning", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME));
\core\notification::error(
get_string('no_submissionfile_warning', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME)
);
return true;
}
// Get the file.
$file = reset($files);
// Send file to backend.
$response = \assignsubmission_dta\dta_backend_utils::assignsubmission_dta_send_submission_to_backend($this->assignment, $submission->id, $file);
// Send file to backend (split across lines to avoid exceeding length).
$response = \assignsubmission_dta\dta_backend_utils::
assignsubmission_dta_send_submission_to_backend(
$this->assignment,
$submission->id,
$file
);
// With a null response, return an error.
if (is_null($response)) {
......@@ -299,29 +324,35 @@ class assign_submission_dta extends assign_submission_plugin {
// Decode recommendations from response.
$recommendations = dta_recommendation::assignsubmission_dta_decode_json_recommendations($response);
error_log(print_r($recommendations, true));
// Use Moodle debugging instead of error_log/print_r.
debugging('Recommendations: ' . json_encode($recommendations), DEBUG_DEVELOPER);
// Persist new results to database.
dta_db_utils::assignsubmission_dta_store_result_summary_to_database($this->assignment->get_instance()->id, $submission->id, $resultsummary);
// Persist new results to database (split long lines).
dta_db_utils::assignsubmission_dta_store_result_summary_to_database(
$this->assignment->get_instance()->id,
$submission->id,
$resultsummary
);
// Store the array of recommendations in the database.
dta_db_utils::assignsubmission_dta_store_recommendations_to_database($this->assignment->get_instance()->id, $submission->id, $recommendations);
dta_db_utils::assignsubmission_dta_store_recommendations_to_database(
$this->assignment->get_instance()->id,
$submission->id,
$recommendations
);
return true;
}
/**
* Display a short summary of the test results of the submission
* This is displayed as default view, with the option to expand
* to the full detailed results.
* Display a short summary of the test results of the submission.
*
* @param stdClass $submission to show
* @param bool $showviewlink configuration variable to show expand option
* @return string summary results html
* @param stdClass $submission Submission to show.
* @param bool $showviewlink Whether to show expand option.
* @return string Summary results HTML.
*/
public function view_summary(stdClass $submission, & $showviewlink) {
public function view_summary(stdClass $submission, &$showviewlink): string {
$showviewlink = true;
return dta_view_submission_utils::assignsubmission_dta_generate_summary_html(
$this->assignment->get_instance()->id,
$submission->id
......@@ -329,12 +360,12 @@ class assign_submission_dta extends assign_submission_plugin {
}
/**
* Display detailed results
* Display detailed results.
*
* @param stdClass $submission the submission the results are shown for.
* @return string detailed results html
* @param stdClass $submission The submission for which to show results.
* @return string Detailed results HTML.
*/
public function view(stdClass $submission) {
public function view(stdClass $submission): string {
return dta_view_submission_utils::assignsubmission_dta_generate_detail_html(
$this->assignment->get_instance()->id,
$submission->id
......@@ -344,73 +375,77 @@ class assign_submission_dta extends assign_submission_plugin {
/**
* Generate array of allowed file types to upload.
*
* @param bool $settings switch to define if list for assignment settings
* or active submission should be returned
*
* @param bool $settings Whether this is for assignment settings or active submission.
* @return array
*/
private function get_file_options(bool $settings): array {
$fileoptions = [
'subdirs' => 0,
"maxfiles" => 1,
'accepted_types' => ($settings
? [".txt"]
'maxfiles' => 1,
'accepted_types' => (
$settings
? ['.txt']
: [
".txt",
".zip",
]),
'.txt',
'.zip',
]
),
'return_types' => FILE_INTERNAL,
];
return $fileoptions;
}
/**
* Get file areas returns a list of areas this plugin stores files
* @return array - An array of fileareas (keys) and descriptions (values)
* Get file areas returns a list of areas this plugin stores files.
*
* @return array An array of fileareas (keys) and descriptions (values).
*/
public function get_file_areas() {
public function get_file_areas(): array {
return [
self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION => get_string("dta_submissions_fa", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
self::ASSIGNSUBMISSION_DTA_FILEAREA_TEST => get_string("dta_tests_fa", self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION =>
get_string('dta_submissions_fa', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
self::ASSIGNSUBMISSION_DTA_FILEAREA_TEST =>
get_string('dta_tests_fa', self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME),
];
}
/**
* Produce a list of files suitable for export that represent this feedback or submission
* Produce a list of files suitable for export that represent this feedback or submission.
*
* @param stdClass $submission The submission
* @param stdClass $user The user record - unused
* @return array - return an array of files indexed by filename
* @param stdClass $submission The submission object.
* @param stdClass $user The user record (unused).
* @return array An array of files indexed by filename.
*/
public function get_files(stdClass $submission, stdClass $user) {
public function get_files(stdClass $submission, stdClass $user): array {
$result = [];
$fs = get_file_storage();
$files = $fs->get_area_files($this->assignment->get_context()->id,
$files = $fs->get_area_files(
$this->assignment->get_context()->id,
self::ASSIGNSUBMISSION_DTA_COMPONENT_NAME,
self::ASSIGNSUBMISSION_DTA_FILEAREA_SUBMISSION,
$submission->id,
'timemodified',
false);
false
);
foreach ($files as $file) {
foreach ($files as $fileobj) {
// Do we return the full folder path or just the file name?
if (isset($submission->exportfullpath) && $submission->exportfullpath == false) {
$result[$file->get_filename()] = $file;
if (isset($submission->exportfullpath) && $submission->exportfullpath === false) {
$result[$fileobj->get_filename()] = $fileobj;
} else {
$result[$file->get_filepath().$file->get_filename()] = $file;
$result[$fileobj->get_filepath() . $fileobj->get_filename()] = $fileobj;
}
}
return $result;
}
/**
* The plugin is being uninstalled - cleanup
* The plugin is being uninstalled - cleanup.
*
* @return bool
*/
public function delete_instance() {
public function delete_instance(): bool {
dta_db_utils::assignsubmission_dta_uninstall_plugin_cleaup();
return true;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment