-
Notifications
You must be signed in to change notification settings - Fork 8
/
ApiController.php
151 lines (135 loc) · 5.08 KB
/
ApiController.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
<?php
declare(strict_types = 1);
namespace App\Controller;
use App\Model\Svg\SvgFile;
use App\Model\Title;
use App\Service\FileCache;
use App\Service\Renderer;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
/**
* API endpoint
*/
class ApiController extends AbstractController
{
/** @var FileCache */
private $cache;
/** @var Renderer */
protected $svgRenderer;
public function __construct(FileCache $cache, Renderer $svgRenderer)
{
$this->cache = $cache;
$this->svgRenderer = $svgRenderer;
}
/**
* Serve a PNG rendering of the given SVG in the given language (without any user-provided
* translation strings).
*
* @Route("/api/file/{filename}/{lang}.png", name="api_file", methods="GET")
*
* @param string $filename
* @param string $lang
* @return Response
*/
public function getFile(string $filename, string $lang): Response
{
$filename = Title::normalize($filename);
$content = $this->svgRenderer->render($this->cache->getPath($filename), $lang);
return new Response($content, 200, [
'Content-Type' => 'image/png',
'X-File-Hash' => sha1($content),
]);
}
/**
* Get a full filesystem path to a temporary PNG file.
* @param string $filename The base SVG filename.
* @param string $key They unique key to append to the filename.
* @return string
*/
protected function getTempPngFilename(string $filename, string $key): string
{
return $this->cache->fullPath($filename.'_'.$key.'.png');
}
/**
* Take POST data, write new translations into the SVG file, render a resultant PNG out to the
* filesystem, and return an identifier for that PNG file.
*
* @Route("/api/translate/{filename}/{lang}", name="api_file_request", methods="POST")
*/
public function requestFileWithTranslations(string $filename, string $lang, Request $request): Response
{
// Get the SVG file, and add in the new translations.
$filename = Title::normalize($filename);
$path = $this->cache->getPath($filename);
$file = new SvgFile($path);
$translations = $request->request->all();
$file->setTranslations($lang, $translations);
// Write the modified SVG out to the filesystem, named with a unique key. This is necessary
// both because multiple people could be translating the same file at the same time, and
// also means we can use the same key for the rendered PNG file. The key is generated from
// the translation set so that the
$fileKey = md5(serialize($translations));
$tempPngFilename = $this->getTempPngFilename($filename, $fileKey);
$file->saveToPath($tempPngFilename);
// Render the modified SVG to PNG, and return it's URL.
$renderedPngContents = $this->svgRenderer->render($tempPngFilename, $lang);
file_put_contents($tempPngFilename, $renderedPngContents);
$relativeUrl = $this->generateUrl('api_file_translated', [
'filename' => $filename,
'key' => $fileKey,
'lang' => $lang,
]);
return new JsonResponse(['imageSrc' => $relativeUrl]);
}
/**
* Get a request for a already-rendered, custom-translated PNG (identified by a key), and
* return that file.
*
* @Route("/api/file/{filename}/{lang}/{key}.png", name="api_file_translated", methods="GET")
*
* @param string $filename
* @param Request $request
* @return Response
*/
public function getFileWithTranslations(string $filename, string $lang, string $key, Request $request): Response
{
$tempPngFilename = $this->getTempPngFilename($filename, $key);
if (file_exists($tempPngFilename)) {
return new BinaryFileResponse($tempPngFilename);
}
throw new NotFoundHttpException();
}
/**
* @Route("/api/translations/{fileName}", name="api_translations", methods="GET")
*
* @param string $fileName
* @return Response
*/
public function getTranslations(string $fileName): Response
{
$fileName = Title::normalize($fileName);
$path = $this->cache->getPath($fileName);
$file = new SvgFile($path);
return $this->json($file->getInFileTranslations());
}
/**
* @Route("/api/languages/{fileName}", name="api_languages", methods="GET")
*
* @param string $fileName
* @return Response
*/
public function getLanguages(string $fileName): Response
{
$fileName = Title::normalize($fileName);
$path = $this->cache->getPath($fileName);
$file = new SvgFile($path);
$langs = $file->getSavedLanguages();
sort($langs);
return $this->json($langs);
}
}