<?php
namespace App\Controller\Api;
use App\Controller\BaseController;
use App\Entity\Project;
use App\Entity\Translation;
use App\Response\ResponseService;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* @package App\Controller
* @Route("/api/translations")
*/
class TranslationsController extends BaseController
{
private $locales;
public function __construct(string $locales)
{
$this->locales = explode('|', $locales);
}
/**
* @Route("/locales", name="api.translations.locales", methods={"GET"})
* @param Request $request
* @param LoggerInterface $logger
* @param ResponseService $responseService
* @return JsonResponse
*/
public function locales(Request $request, LoggerInterface $logger, ResponseService $responseService): JsonResponse
{
if (false === $request->headers->has('X-Auth-Token')) {
$logger->alert(sprintf(
'Translations for project: received a request with missing X-Auth-Token from IP: %s.',
$request->getClientIp()
));
return $this->json(null, 403);
}
$authToken = $request->headers->get('X-Auth-Token');
$project = $this->manager()
->getRepository(Project::class)
->findOneBy(['authToken' => $authToken]);
if (!$project) {
$logger->alert(sprintf(
'Translations for project: received a request with invalid X-Auth-Token: %s, from IP: %s.',
$authToken,
$request->getClientIp()
));
return $this->json(null, 404);
}
$locales = $this->manager()->getRepository(Translation::class)->locales($project);
return $responseService->successResponse([
'locales' => $locales,
]);
}
/**
* @Route("/domains", name="api.translations.domains", methods={"GET"})
* @param Request $request
* @param LoggerInterface $logger
* @param ResponseService $responseService
* @return JsonResponse
*/
public function domains(Request $request, LoggerInterface $logger, ResponseService $responseService): JsonResponse
{
if (false === $request->headers->has('X-Auth-Token')) {
$logger->alert(sprintf(
'Translations for project: received a request with missing X-Auth-Token from IP: %s.',
$request->getClientIp()
));
return $this->json(null, 403);
}
$authToken = $request->headers->get('X-Auth-Token');
$project = $this->manager()
->getRepository(Project::class)
->findOneBy(['authToken' => $authToken]);
if (!$project) {
$logger->alert(sprintf(
'Translations for project: received a request with invalid X-Auth-Token: %s, from IP: %s.',
$authToken,
$request->getClientIp()
));
return $this->json(null, 404);
}
$domains = $this->manager()->getRepository(Translation::class)->domains($project);
return $responseService->successResponse([
'domains' => $domains,
]);
}
/**
* @Route("/list", name="api.translations.list", methods={"GET"})
* @param Request $request
* @param LoggerInterface $logger
* @param ResponseService $responseService
* @return JsonResponse
*/
public function list(Request $request, LoggerInterface $logger, ResponseService $responseService): JsonResponse
{
if (false === $request->headers->has('X-Auth-Token')) {
$logger->alert(sprintf(
'Translations for project: received a request with missing X-Auth-Token from IP: %s.',
$request->getClientIp()
));
return $this->json(null, 403);
}
$authToken = $request->headers->get('X-Auth-Token');
$project = $this->manager()
->getRepository(Project::class)
->findOneBy(['authToken' => $authToken]);
if (!$project) {
$logger->alert(sprintf(
'Translations for project: received a request with invalid X-Auth-Token: %s, from IP: %s.',
$authToken,
$request->getClientIp()
));
return $this->json(null, 404);
}
$locale = $request->query->get('locale', $project->getDefaultLocale());
$locales = $this->manager()->getRepository(Translation::class)->locales($project);
if ($locale === $project->getDefaultLocale()) {
$nonDefaultLocales = array_values(array_diff($locales, [$project->getDefaultLocale()]));
$currentDefaultLocale = $nonDefaultLocales[0];
} else {
$currentDefaultLocale = $project->getDefaultLocale();
}
$translations = $this->manager()
->getRepository(Translation::class)
->forProjectRaw($project, $locale, $currentDefaultLocale, $request->query->all());
return $responseService->successResponse([
'translations' => $translations,
'defaultLocale' => $currentDefaultLocale,
]);
}
/**
* @Route("/{id}/update", name="api.translations.update", methods={"POST"})
* @param Request $request
* @param Translation $translation
* @param LoggerInterface $logger
* @return JsonResponse
*/
public function update(Request $request, Translation $translation, LoggerInterface $logger): JsonResponse
{
if (false === $request->headers->has('X-Auth-Token')) {
$logger->alert(sprintf(
'Translations for project: received a request with missing X-Auth-Token from IP: %s.',
$request->getClientIp()
));
return $this->json(null, 403);
}
$authToken = $request->headers->get('X-Auth-Token');
$project = $this->manager()
->getRepository(Project::class)
->findOneBy(['authToken' => $authToken]);
if (!$project) {
$logger->alert(sprintf(
'Translations for project: received a request with invalid X-Auth-Token: %s, from IP: %s.',
$authToken,
$request->getClientIp()
));
return $this->json(null, 404);
}
if ($translation->getProject() !== $project) {
return $this->json(null, 403);
}
$value = $request->request->get('value');
$translation->setTranslationValue($value);
$this->manager()->flush();
return $this->json(null);
}
/**
* @Route("", name="api.translations.send", methods={"GET"})
* @param Request $request
* @param ResponseService $responseService
* @param LoggerInterface $logger
* @return JsonResponse
*/
public function send(Request $request, ResponseService $responseService, LoggerInterface $logger): JsonResponse
{
if (false === $request->headers->has('X-Auth-Token')) {
$logger->alert(sprintf(
'Translations for project: received a request with missing X-Auth-Token from IP: %s.',
$request->getClientIp()
));
return $this->json(null, 403);
}
$authToken = $request->headers->get('X-Auth-Token');
$project = $this->manager()
->getRepository(Project::class)
->findOneBy(['authToken' => $authToken]);
if (!$project) {
$logger->alert(sprintf(
'Translations for project: received a request with invalid X-Auth-Token: %s, from IP: %s.',
$authToken,
$request->getClientIp()
));
return $this->json(null, 404);
}
$translations = $this->manager()
->getRepository(Translation::class)
->forProject($project);
$translations = $this->groupByLocaleAndDomain($translations);
return $responseService->successResponse($translations);
}
/**
* @Route("", name="api.translations.receive", methods={"POST"})
* @param Request $request
* @param LoggerInterface $logger
* @return JsonResponse
*/
public function receive(Request $request, LoggerInterface $logger): JsonResponse
{
if (false === $request->headers->has('X-Auth-Token')) {
$logger->alert(sprintf(
'Translations for project: received a request with missing X-Auth-Token from IP: %s.',
$request->getClientIp()
));
return $this->json(null, 403);
}
$authToken = $request->headers->get('X-Auth-Token');
$project = $this->manager()
->getRepository(Project::class)
->findOneBy(['authToken' => $authToken]);
if (!$project) {
$logger->alert(sprintf(
'Translations for project: received a request with invalid X-Auth-Token: %s, from IP: %s.',
$authToken,
$request->getClientIp()
));
return $this->json(null, 404);
}
$data = json_decode($request->getContent(), true);
if (empty($data)) {
return $this->json(null, 400);
}
// Iterate translation messages
$index = 1;
foreach ($data as $translationItem) {
$newTranslation = (new Translation)
->setProject($project)
->setLocale($translationItem['locale'])
->setDomain($translationItem['domain'])
->setTranslationKey($translationItem['translationKey'])
->setTranslationValue($translationItem['translationValue'])
;
$this->manager()->persist($newTranslation);
if ($index % 100 === 0) {
$this->manager()->flush();
}
$index++;
}
$this->manager()->flush();
// Return success response
return new JsonResponse();
}
/**
* @Route("/existing-translations", name="api.translations.existing_translations_for_project", methods={"GET"})
* @param Request $request
* @param LoggerInterface $logger
* @param ResponseService $responseService
* @return JsonResponse
*/
public function existingTranslationsForProject(Request $request, LoggerInterface $logger, ResponseService $responseService): JsonResponse
{
if (false === $request->headers->has('X-Auth-Token')) {
$logger->alert(sprintf(
'Existing translations for project: received a request with missing X-Auth-Token from IP: %s.',
$request->getClientIp()
));
return $this->json(null, 403);
}
$authToken = $request->headers->get('X-Auth-Token');
$project = $this->manager()
->getRepository(Project::class)
->findOneBy(['authToken' => $authToken]);
if (!$project) {
$logger->alert(sprintf(
'Existing translations for project: received a request with invalid X-Auth-Token: %s, from IP: %s.',
$authToken,
$request->getClientIp()
));
return $this->json(null, 404);
}
$translations = $this->manager()
->getRepository(Translation::class)
->existingTranslationsForProject($project);
return $responseService->successResponse($translations);
}
/**
* @param array $translations
* @return Translation[]
*/
private function groupByLocaleAndDomain(array $translations): array
{
$result = [];
foreach ($translations as $translation) {
/**
* @var $translation Translation
*/
$result[$translation->getLocale()][$translation->getDomain()][] = $translation;
}
return $result;
}
}