Skip to content

Commit 4f5aef9

Browse files
committed
Adding batch ID to the assignment entity, so we can mark them as checked by plagiarism-detection tools.
1 parent e5b7f84 commit 4f5aef9

5 files changed

Lines changed: 143 additions & 14 deletions

File tree

app/V1Module/presenters/PlagiarismPresenter.php

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use App\Model\Entity\PlagiarismDetectedSimilarity;
1919
use App\Model\Entity\PlagiarismDetectedSimilarFile;
2020
use App\Model\Entity\SolutionFile;
21+
use App\Model\Repository\Assignments;
2122
use App\Model\Repository\AssignmentSolutions;
2223
use App\Model\Repository\PlagiarismDetectionBatches;
2324
use App\Model\Repository\PlagiarismDetectedSimilarities;
@@ -32,6 +33,12 @@
3233
*/
3334
class PlagiarismPresenter extends BasePresenter
3435
{
36+
/**
37+
* @var Assignments
38+
* @inject
39+
*/
40+
public $assignments;
41+
3542
/**
3643
* @var AssignmentSolutions
3744
* @inject
@@ -168,15 +175,38 @@ public function checkUpdateBatch(string $id): void
168175
* Update detection bath record. At the moment, only the uploadCompletedAt can be changed.
169176
* @POST
170177
*/
171-
#[Post("uploadCompleted", new VBool(), "Whether the upload of the batch data is completed or not.")]
178+
#[Post(
179+
"uploadCompleted",
180+
new VBool(),
181+
"Whether the upload of the batch data is completed or not.",
182+
required: false
183+
)]
184+
#[Post(
185+
"assignments",
186+
new VArray(new VUuid()),
187+
"List of assignment IDs to be marked as 'checked' by this batch.",
188+
required: false
189+
)]
172190
#[Path("id", new VUuid(), "Identification of the detection batch", required: true)]
173191
public function actionUpdateBatch(string $id): void
174192
{
175-
$req = $this->getRequest();
176-
$uploadCompleted = filter_var($req->getPost("uploadCompleted"), FILTER_VALIDATE_BOOLEAN);
177193
$batch = $this->detectionBatches->findOrThrow($id);
178-
$batch->setUploadCompleted($uploadCompleted);
179-
$this->detectionBatches->persist($batch);
194+
$req = $this->getRequest();
195+
196+
$uploadCompleted = $req->getPost("uploadCompleted");
197+
if ($uploadCompleted !== null) {
198+
$uploadCompleted = filter_var($uploadCompleted, FILTER_VALIDATE_BOOLEAN);
199+
$batch->setUploadCompleted($uploadCompleted);
200+
}
201+
202+
$assignments = $req->getPost("assignments") ?? [];
203+
foreach ($assignments as $assignmentId) {
204+
$assignment = $this->assignments->findOrThrow($assignmentId);
205+
$assignment->setPlagiarismBatch($batch);
206+
$this->assignments->persist($assignment, false); // no flush
207+
}
208+
209+
$this->detectionBatches->persist($batch); // and flush
180210
$this->sendSuccessResponse($batch);
181211
}
182212

@@ -281,7 +311,7 @@ public function actionAddSimilarities(string $id, string $solutionId): void
281311
}
282312

283313
try {
284-
$detectedFile = new PlagiarismDetectedSimilarFile(
314+
new PlagiarismDetectedSimilarFile(
285315
$detectedSimilarity,
286316
$similarSolution,
287317
$similarFile,

app/model/entity/Assignment.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,13 @@ public function syncWithExercise()
544544
$this->syncedAt = new DateTime();
545545
}
546546

547+
/**
548+
* @var PlagiarismDetectionBatch|null
549+
* @ORM\ManyToOne(targetEntity="PlagiarismDetectionBatch")
550+
* Refers to last plagiarism detection batch which checked solutions of this assignment.
551+
*/
552+
protected $plagiarismBatch = null;
553+
547554
/*
548555
* Accessors
549556
*/
@@ -702,4 +709,14 @@ public function setMaxPointsDeadlineInterpolation(bool $interpolation = true): v
702709
{
703710
$this->maxPointsDeadlineInterpolation = $interpolation;
704711
}
712+
713+
public function getPlagiarismBatch(): ?PlagiarismDetectionBatch
714+
{
715+
return $this->plagiarismBatch;
716+
}
717+
718+
public function setPlagiarismBatch(?PlagiarismDetectionBatch $batch = null)
719+
{
720+
$this->plagiarismBatch = $batch;
721+
}
705722
}

app/model/view/AssignmentViewFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ function (LocalizedExercise $text) use ($assignment) {
116116
],
117117
"solutionFilesLimit" => $assignment->getSolutionFilesLimit(),
118118
"solutionSizeLimit" => $assignment->getSolutionSizeLimit(),
119+
"plagiarismBatchId" => $assignment->getPlagiarismBatch()?->getId(),
119120
"permissionHints" => PermissionHints::get($this->assignmentAcl, $assignment)
120121
];
121122
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Migrations;
6+
7+
use Doctrine\DBAL\Schema\Schema;
8+
use Doctrine\Migrations\AbstractMigration;
9+
10+
/**
11+
* Auto-generated Migration: Please modify to your needs!
12+
*/
13+
final class Version20250411155056 extends AbstractMigration
14+
{
15+
public function getDescription(): string
16+
{
17+
return '';
18+
}
19+
20+
public function up(Schema $schema): void
21+
{
22+
// this up() migration is auto-generated, please modify it to your needs
23+
$this->addSql('ALTER TABLE assignment ADD plagiarism_batch_id CHAR(36) DEFAULT NULL COMMENT \'(DC2Type:uuid)\'');
24+
$this->addSql('ALTER TABLE assignment ADD CONSTRAINT FK_30C544BA5B4CC7BF FOREIGN KEY (plagiarism_batch_id) REFERENCES plagiarism_detection_batch (id)');
25+
$this->addSql('CREATE INDEX IDX_30C544BA5B4CC7BF ON assignment (plagiarism_batch_id)');
26+
}
27+
28+
public function down(Schema $schema): void
29+
{
30+
// this down() migration is auto-generated, please modify it to your needs
31+
$this->addSql('ALTER TABLE assignment DROP FOREIGN KEY FK_30C544BA5B4CC7BF');
32+
$this->addSql('DROP INDEX IDX_30C544BA5B4CC7BF ON assignment');
33+
$this->addSql('ALTER TABLE assignment DROP plagiarism_batch_id');
34+
}
35+
}

tests/Presenters/PlagiarismPresenter.phpt

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,52 @@ class TestPlagiarismPresenter extends Tester\TestCase
158158
Assert::true($batch->getUploadCompletedAt() === null);
159159
}
160160

161+
public function testBatchSetCompletedAndMarkAssignments()
162+
{
163+
PresenterTestHelper::loginDefaultAdmin($this->container);
164+
165+
$batch = current(array_filter($this->presenter->detectionBatches->findAll(), function ($b) {
166+
return $b->getUploadCompletedAt() === null;
167+
}));
168+
Assert::notNull($batch);
169+
170+
$assignments = [];
171+
$otherAssignments = [];
172+
foreach ($this->presenter->assignments->findAll() as $assignment) {
173+
if ($assignment->isExam()) {
174+
$otherAssignments[] = $assignment;
175+
} else {
176+
$assignments[] = $assignment;
177+
}
178+
}
179+
Assert::count(2, $assignments);
180+
Assert::count(1, $otherAssignments);
181+
182+
$payload = PresenterTestHelper::performPresenterRequest(
183+
$this->presenter,
184+
'V1:PlagiarismPresenter',
185+
'POST',
186+
['action' => 'updateBatch', 'id' => $batch->getId()],
187+
[
188+
'assignments' => array_map(function ($a) {
189+
return $a->getId();
190+
}, $assignments)
191+
]
192+
);
193+
Assert::equal($batch->getId(), $payload->getId());
194+
Assert::true($payload->getUploadCompletedAt() === null);
195+
196+
foreach ($assignments as $assignment) {
197+
$this->presenter->assignments->refresh($assignment);
198+
Assert::equal($batch->getId(), $assignment->getPlagiarismBatch()?->getId());
199+
}
200+
201+
foreach ($otherAssignments as $assignment) {
202+
$this->presenter->assignments->refresh($assignment);
203+
Assert::null($assignment->getPlagiarismBatch());
204+
}
205+
}
206+
161207
public function testGetSimilarities()
162208
{
163209
PresenterTestHelper::loginDefaultAdmin($this->container);
@@ -237,16 +283,16 @@ class TestPlagiarismPresenter extends Tester\TestCase
237283
'fileEntry' => $similarity->getFileEntry(),
238284
'fragments' => [
239285
[
240-
[ 'offset' => 42, 'length' => 54 ],
241-
[ 'offset' => 42, 'length' => 54 ],
286+
['offset' => 42, 'length' => 54],
287+
['offset' => 42, 'length' => 54],
242288
],
243289
[
244-
[ 'offset' => 420, 'length' => 540 ],
245-
[ 'offset' => 420, 'length' => 540 ],
290+
['offset' => 420, 'length' => 540],
291+
['offset' => 420, 'length' => 540],
246292
],
247293
[
248-
[ 'offset' => 4200, 'length' => 1024 ],
249-
[ 'offset' => 4200, 'length' => 1024 ],
294+
['offset' => 4200, 'length' => 1024],
295+
['offset' => 4200, 'length' => 1024],
250296
],
251297
]
252298
]],
@@ -476,8 +522,8 @@ class TestPlagiarismPresenter extends Tester\TestCase
476522
'fileEntry' => $similarity->getFileEntry(),
477523
'fragments' => [
478524
[
479-
[ 'off' => 42, 'length' => 54 ],
480-
[ 'offset' => 42, 'len' => 54 ],
525+
['off' => 42, 'length' => 54],
526+
['offset' => 42, 'len' => 54],
481527
],
482528
]
483529
]],

0 commit comments

Comments
 (0)