Skip to content

Commit ce50b5d

Browse files
committed
Define API endpoint for printing as a team
This endpoint can be used for `printfile` CLI submit tools, when printing via DOMjudge has been configured.
1 parent 8330284 commit ce50b5d

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace App\Controller\API;
4+
5+
use App\Service\DOMJudgeService;
6+
use Doctrine\ORM\EntityManagerInterface;
7+
use FOS\RestBundle\Controller\AbstractFOSRestController;
8+
use FOS\RestBundle\Controller\Annotations as Rest;
9+
use OpenApi\Attributes as OA;
10+
use Psr\Log\LoggerInterface;
11+
use Symfony\Component\HttpFoundation\JsonResponse;
12+
use Symfony\Component\HttpFoundation\Request;
13+
use Symfony\Component\HttpFoundation\Response;
14+
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
15+
use Symfony\Component\Routing\Attribute\Route;
16+
use Symfony\Component\Security\Http\Attribute\IsGranted;
17+
use App\Entity\Language;
18+
19+
#[Route(path: "/printing")]
20+
#[OA\Tag(name: "Printing")]
21+
#[OA\Response(ref: "#/components/responses/Unauthenticated", response: 401)]
22+
#[OA\Response(ref: "#/components/responses/Unauthorized", response: 403)]
23+
class PrintController extends AbstractFOSRestController
24+
{
25+
public function __construct(
26+
protected readonly EntityManagerInterface $em,
27+
protected readonly DOMJudgeService $dj,
28+
protected readonly LoggerInterface $logger
29+
) {
30+
}
31+
32+
/**
33+
* Send a file to the system printer as a team.
34+
* @return JsonResponse
35+
*/
36+
#[IsGranted("ROLE_TEAM")]
37+
#[Rest\Post("/team")]
38+
#[OA\Tag(name: "Printing")]
39+
#[OA\RequestBody(
40+
required: true,
41+
content: new OA\JsonContent(
42+
properties: [
43+
new OA\Property(
44+
property: "original_name",
45+
description: "The original name of the file",
46+
type: "string"
47+
),
48+
new OA\Property(
49+
property: "language",
50+
description: "The programming language of the file contents",
51+
type: "string"
52+
),
53+
new OA\Property(
54+
property: "file_contents",
55+
description: "The plaintext contents of the source file",
56+
type: "string"
57+
),
58+
],
59+
type: "object"
60+
)
61+
)]
62+
#[OA\Response(
63+
response: 200,
64+
description: "Returns the ID of the imported problem and any messages produced",
65+
content: new OA\JsonContent(
66+
properties: [
67+
new OA\Property(
68+
property: "success",
69+
description: "Whether printing was successful",
70+
type: "boolean"
71+
),
72+
new OA\Property(
73+
property: "output",
74+
description: "The print command output",
75+
type: "string"
76+
),
77+
],
78+
type: "object"
79+
)
80+
)]
81+
#[OA\Response(
82+
response: 422,
83+
description: "An error occurred while processing the print job",
84+
content: new OA\JsonContent(
85+
properties: [
86+
new OA\Property(property: "errors", type: "object"),
87+
]
88+
)
89+
)]
90+
public function printAsTeam(Request $request): JsonResponse
91+
{
92+
$origname = $request->request->get("original_name");
93+
$contents = $request->request->get("file_contents");
94+
/** @var array<string,string> error messages */
95+
$errors = [];
96+
97+
$language = $request->request->get("language");
98+
$langid = $this->em
99+
->createQueryBuilder()
100+
->from(Language::class, "l")
101+
->select("l.langid")
102+
->andWhere("l.allowSubmit = 1")
103+
->andWhere("l.name = :name")
104+
->setParameter("name", $language)
105+
->getQuery()
106+
->getScalarResult();
107+
if (empty($langid)) {
108+
$errors[] = "Programming language not found";
109+
}
110+
111+
if (!($tempFilename = tempnam($this->dj->getDomjudgeTmpDir(), "printfile-"))) {
112+
throw new ServiceUnavailableHttpException(null, "Could not create temporary file.");
113+
}
114+
115+
if (file_put_contents($tempFilename, $contents) === false) {
116+
throw new ServiceUnavailableHttpException(
117+
null,
118+
sprintf("Could not write printfile to temporary file '%s'.", $tempFilename)
119+
);
120+
}
121+
122+
// Handle validation errors
123+
if (!empty($errors)) {
124+
unlink($tempFilename);
125+
return new JsonResponse(
126+
["errors" => $errors],
127+
Response::HTTP_UNPROCESSABLE_ENTITY
128+
);
129+
}
130+
131+
$ret = $this->dj->printUserFile($tempFilename, $origname, "c", true);
132+
unlink($tempFilename);
133+
134+
$status = Response::HTTP_OK;
135+
if (!$ret[0]) {
136+
$status = Response::HTTP_SERVICE_UNAVAILABLE;
137+
}
138+
return new JsonResponse(
139+
["success" => $ret[0], "output" => $ret[1]],
140+
$status
141+
);
142+
}
143+
}

0 commit comments

Comments
 (0)