<?php
namespace App\Controller;
use App\Entity\Admin;
use App\Entity\Headquarter;
use App\Entity\UserNotification;
use App\Entity\Role;
use App\Entity\Survey;
use App\Entity\User;
use App\Entity\UserDevice;
use App\Entity\UserTimesheet;
use App\Serializer\API\UserTimesheetSerializer;
use Doctrine\ORM\EntityManagerInterface;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\HeaderBag;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Uid\Uuid;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Validation;
use Symfony\Contracts\Translation\TranslatorInterface;
class RestController
{
/** @var ContainerInterface */
protected $container;
protected EntityManagerInterface $em;
/** @var Request */
protected $request;
protected TranslatorInterface $translator;
protected string $default_locale;
protected ?array $decode_token;
public function __construct(
EntityManagerInterface $em,
RequestStack $requestStack,
TranslatorInterface $translator,
string $default_locale = 'es'
) {
$this->em = $em;
$this->request = $requestStack->getCurrentRequest();
$this->translator = $translator;
$this->default_locale = $default_locale;
}
/**
* @internal
* @required
*/
public function setContainer(ContainerInterface $container): ?ContainerInterface
{
$previous = $this->container;
$this->container = $container;
return $previous;
}
protected function getRequestHeaders(): HeaderBag
{
return $this->request->headers;
}
protected function getRequestBody(): array
{
$json = (string)$this->request->getContent();
if ($json) {
return json_decode($json, true, 512, JSON_THROW_ON_ERROR);
}
return [];
}
protected function getDefaultLocale(): string
{
/** @phpstan-ignore-next-line */
return $this->request?->getDefaultLocale();
}
protected function getLocale(): string
{
/** @phpstan-ignore-next-line */
return $this->request?->getLocale();
}
public function getAdmin(): ?Admin
{
/** @phpstan-ignore-next-line */
return $this->request?->attributes?->get('admin');
}
public function getHeadquarter(): ?Headquarter
{
/** @phpstan-ignore-next-line */
return $this->request?->attributes?->get('headquarter');
}
public function getUser(): ?User
{
/** @phpstan-ignore-next-line */
return $this->request?->attributes?->get('user');
}
public function getDevice(): ?UserDevice
{
/** @phpstan-ignore-next-line */
return $this->request?->attributes?->get('device');
}
public function getAudiencesOrUsers(): ?array
{
/** @phpstan-ignore-next-line */
return $this->request?->attributes?->get('audiences_or_users');
}
public function getPermissionsToArray(): array
{
if ($admin = $this->getAdmin()) {
if ($admin->getIsSuper()) {
return $admin->getHeadquarter()->getPermissionsToArray();
}
return $admin->getPermissionsToArray();
}
if ($user = $this->getUser()) {
return $user->getRole()->getPermissionsToArray();
}
return [];
}
protected function validate(array $data, Collection $constraint): array
{
$validator = Validation::createValidator();
$errors = $validator->validate($data, $constraint);
$messages = [];
if (count($errors) > 0) {
foreach ($errors as $violation) {
$key = str_replace(array('[', ']'), '', $violation->getPropertyPath());
$messages[$key][] = $this->translator->trans(
$violation->getMessageTemplate(),
$violation->getParameters(),
'validators'
);
}
}
return $messages;
}
protected function json(
array|bool|null $data,
int $status = Response::HTTP_OK,
array $headers = [],
array $context = []
): JsonResponse {
$commons = null;
$user = $this->getUser();
if ($user instanceof User) {
$unread = $this->em->getRepository(UserNotification::class)->findBy([
'user' => $user,
'status' => UserNotification::STATUS_UNREAD
]);
/** @phpstan-ignore-next-line */
$surveys = $this->em->getRepository(Survey::class)->findPaginateBy(
[
'status' => Survey::STATUS_PUBLISHED,
'headquarter' => $this->getHeadquarter(),
],
[
'audiences_or_users' => $this->getAudiencesOrUsers(),
'between_start-expiration' => true
],
[
//
],
1,
0
);
$timesheet = $this->em->getRepository(UserTimesheet::class)->findOneBy([
'user' => $user,
'is_started' => true
]);
if ($timesheet instanceof UserTimesheet) {
$timesheet = UserTimesheetSerializer::item($timesheet);
}
$commons = [
'notifications_unread' => count($unread),
'surveys_pending' => count($surveys),
'timesheets_active' => $timesheet
];
}
$response = [
'data' => $data,
'commons' => $commons,
'requestId' => Uuid::v4()
];
/** @phpstan-ignore-next-line */
$json = $this->container->get('serializer')->serialize($response, 'json', array_merge([
'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS,
], $context));
return new JsonResponse($json, $status, $headers, true);
}
protected function render(
string $view,
array $parameters = [],
Response $response = null
): Response {
/** @phpstan-ignore-next-line */
$content = $this->container->get('twig')->render($view, $parameters);
if (null === $response) {
$response = new Response();
}
$response->setContent($content);
return $response;
}
protected function export(
?array $data,
): Response {
$spreadsheet = new Spreadsheet();
$spreadsheet
->getActiveSheet()
->fromArray($data, null, 'A1');
$content = IOFactory::createWriter($spreadsheet, 'Xlsx');
return new StreamedResponse(function () use ($content) {
$content->save('php://output');
});
}
}