<?php
namespace App\Controller;
use App\Entity\Badge;
use App\Entity\CustomInput;
use App\Entity\Setting;
use App\Form\RegistrationType;
use App\Form\SettingBadgeType;
use Doctrine\ORM\EntityManagerInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\Asset\Packages;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Mime\MimeTypes;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* @IsGranted("ROLE_ADMIN")
* @Route("/settings")
*/
class SettingController extends BaseController
{
/**
* @Route("/", name="app_setting_list")
*/
public function index(
Request $request,
EntityManagerInterface $entityManager,
RouterInterface $router,
TranslatorInterface $translator,
Packages $assetPackage
): Response
{
$settings = $entityManager->getRepository(Setting::class)->findAll();
foreach ($settings as $setting) {
if ($setting->getName() === 'badge_type') {
$badge = $entityManager->getRepository(Badge::class)
->findOneBy(['id' => $setting->getValue()]);
try {
$setting->setValue($badge->getName());
} catch (\Throwable $exception) {
$setting->setValue('Default');
}
}
if ($setting->getInputType()->getFqcn() === FileType::class) {
if (empty($setting->getValue())) {
$setting->setValue($translator->trans('general.noFileAdded'));
continue;
}
$mimeTypes = new MimeTypes();
$mimeType = $mimeTypes->guessMimeType($setting->getValue());
$url = $assetPackage->getUrl($setting->getValue());
switch (explode('/', $mimeType)[0]) {
case 'image':
$setting->setValue(
"<img alt='favicon' class='img-fluid img-thumbnail' " .
"src='$url' style='max-width: 150px; " .
"max-height: 150px;' />");
break;
case 'application':
$urlForDownload = $router->generate('app_exposedcheckin_downloadFile', ['settingName' => $setting->getName()]);
$downloadText = $translator->trans('general.download');
$viewText = $translator->trans('general.view');
$setting->setValue(
"<a class='btn btn-success btn-sm' href='$urlForDownload'>"
. "<i class='fa fa-download'></i> $downloadText</a>"
. "<a class='ml-2 btn btn-primary btn-sm' href='$url' target='_blank'>"
. "<i class='fa fa-eye'></i> $viewText"
);
break;
}
}
}
return $this->render('setting/index.html.twig', [
'settings' => $settings,
]);
}
/**
* @Route("/booleanModify/{value}/{type}", name="booleanModify")
*/
public function booleanModify(
EntityManagerInterface $em,
string $value,
string $type
): RedirectResponse {
$printingSetting = $em->getRepository(Setting::class)->findOneBy(
['name' => $type]
);
$printingSetting->setValue($value);
$em->flush();
return $this->redirectToRoute("app_setting_list");
}
/**
* @deprecated
* @Route("/app_logo", name="appLogoModify")
*/
public function appLogoModify(Request $request, KernelInterface $kernel)
{
if ($request->isMethod('POST')) {
/**
* @var $file UploadedFile
*/
$file = $request->files->get('upload_logo_file');
$logo = $this->em->getRepository(Setting::class)->findOneBy(['name'=>'logo']);
if (file_exists($kernel->getProjectDir() . '/public/'.$logo->getValue())) {
if ($logo->getValue() !== "/default_logo.png") {
unlink($kernel->getProjectDir() . '/public/' . $logo->getValue());
}
}
if (!file_exists($kernel->getProjectDir() . '/public/logos')) {
exec('mkdir -p ' . $kernel->getProjectDir() . '/public/logos');
exec('chmod -R 0777 ' . $kernel->getProjectDir() . '/public/logos');
}
$file->move($kernel->getProjectDir() . '/public/logos/',$file->getClientOriginalName());
$logo->setValue('logos/'.$file->getClientOriginalName());
$this->em->flush();
}
return $this->redirectToRoute("app_setting_list");
}
/**
* @deprecated
* @Route("/app_favicon", name="appFaviconModify")
*/
public function appFaviconModify(Request $request, KernelInterface $kernel)
{
if ($request->isMethod('POST')) {
/**
* @var $file UploadedFile
*/
$file = $request->files->get('upload_favicon_file');
$favicon = $this->em->getRepository(Setting::class)->findOneBy(['name'=>'favicon']);
if (file_exists($kernel->getProjectDir() . '/public/'.$favicon->getValue())) {
if ($favicon->getValue() !== "/favicon.ico") {
unlink($kernel->getProjectDir() . '/public/' . $favicon->getValue());
}
}
if (!file_exists($kernel->getProjectDir() . '/public/favicon')) {
exec('mkdir -p ' . $kernel->getProjectDir() . '/public/favicon');
exec('chmod -R 0777 ' . $kernel->getProjectDir() . '/public/favicon');
}
$file->move($kernel->getProjectDir() . '/public/favicon/',$file->getClientOriginalName());
$favicon->setValue('favicon/'.$file->getClientOriginalName());
$this->em->flush();
}
return $this->redirectToRoute("app_setting_list");
}
/**
* @Route("/appName", name="appNameModify")
*/
public function appName(EntityManagerInterface $em,Request $request): Response
{
$appNameSetting = $em->getRepository(Setting::class)->findOneBy(
['name' => 'app_name']
);
if ($request->isMethod('POST')) {
$appNameSetting->setValue($request->request->get('app_name'));
$this->em->flush();
return $this->redirectToRoute("app_setting_list");
}
return $this->render('setting/appname.html.twig', [
'setting' => $appNameSetting,
]);
}
/**
* @Route("/badge_type", name="app_setting_badge_type")
* @noinspection NullPointerExceptionInspection
*/
public function badgeType(EntityManagerInterface $em,Request $request): Response
{
//todo: Future Improvement -- Convert to generic ChoiceType
$badgeTypeSetting = $em->getRepository(Setting::class)->findOneBy(
['name' => 'badge_type']
);
$badge = $this->em->getRepository(Badge::class)->findOneBy(['id' => $badgeTypeSetting->getValue()]);
$form = $this->createForm(SettingBadgeType::class, ['default' => $badge ? 1 : 0, 'setting' => $badge]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ($form->get('default')->getData()) {
/** @var Badge $badge */
$badge = $form->get('setting')->getData();
$badgeTypeSetting->setValue($badge->getId());
} else {
$badgeTypeSetting->setValue('0');
}
$this->em->flush();
return $this->redirectToRoute("app_setting_list");
}
return $this->renderForm('setting/settingBadgeType_form.html.twig',
[
'form' => $form
]
);
}
/**
* @Route("/appSettings", name="appSettings")
*/
public function getAppSettings(): JsonResponse
{
$settings['badgeId'] = $this->em->getRepository(Setting::class)->findOneBy(['name' => 'badge_type'])->getValue();
$settings['showPackages'] = $this->em->getRepository(Setting::class)->findOneBy(['name' => Setting::PACKAGE_KEY])->getValue();
$settings['showQuestionnaire'] = $this->em->getRepository(Setting::class)->findOneBy(['name' => Setting::QUESTIONS_KEY])->getValue();
$settings['showFormPDFs'] = $this->em->getRepository(Setting::class)->findOneBy(['name' => Setting::FORM_PDF_KEY])->getValue();
$settings['showPrintBadge'] = $this->em->getRepository(Setting::class)->findOneBy(['name' => Setting::PRINTING_KEY])->getValue();
$settings['showCustomField'] = $this->em->getRepository(Setting::class)->findOneBy(['name' => Setting::CUSTOM_FIELDS_KEY])->getValue();
return new JsonResponse($settings);
}
/**
* @param Setting $setting
* @param UploadedFile $file
* @return JsonResponse
*/
public function uploadFileForSetting(Setting $setting, UploadedFile $file): JsonResponse
{
$downloadsDir = $this->getParameter('app.downloadPath').'/';
$folderName = $setting->getName().'/';
$fileName = $file->getClientOriginalName();
$filePath = $downloadsDir.$folderName.$fileName;
if (!is_dir(dirname($filePath)) && !mkdir($concurrentDirectory = dirname($filePath)) && !is_dir($concurrentDirectory)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $concurrentDirectory));
}
file_put_contents(
$filePath,
file_get_contents($file->getPathName())
);
$setting->setValue($filePath);
$this->em->persist($setting);
$this->em->flush();
return new JsonResponse(['is_error' => false ]);
}
/**
* @Route("/dynamic/{settingName}", name="app_setting_slug")
* @ParamConverter("setting", options={"mapping": {"settingName" : "name"}})
*
* @param Setting $setting
* @param Request $request
* @return Response
* @throws ExceptionInterface
*/
public function modifySettingByName(Setting $setting, Request $request): Response
{
$normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
$serializer = new Serializer([new DateTimeNormalizer(), $normalizer]);
$name = $setting->getName();
$customInput = new CustomInput();
$fieldName = str_replace(str_split(' .'), '_', strtolower($setting->getName()));
$uploadOnly = $setting->getInputType()->getFqcn() === FileType::class;
$customInput
->setFieldName($fieldName)
->setActive(true)
->setRequired(true)
->setName($name)
->setLabel($setting->getTranslationKey())
->setSortOrder(1)
->setShownByDefault(true)
->setUploadOnly($uploadOnly)
->setType($setting->getInputType());
$options['customInputs'][] = $customInput;
$options['isSettings'] = true;
$settingValue = $setting->getValue();
if ($setting->getInputType()->getFqcn() === DateTimeType::class) {
$settingValue = $serializer->denormalize($settingValue, \DateTime::class);
}
$form = $this->createForm(RegistrationType::class, [$fieldName => $settingValue], $options);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
if (!empty($data[$fieldName]) && is_object($data[$fieldName])) {
switch (get_class($data[$fieldName])) {
case \DateTime::class:
$data[$fieldName] = $serializer->normalize($data[$fieldName], 'json');
break;
case UploadedFile::class:
$response = $this->uploadFileForSetting($setting, $data[$fieldName]);
return $this->redirectToRoute('app_setting_list', [], Response::HTTP_SEE_OTHER);
}
}
$setting->setValue($data[$fieldName]);
$this->em->persist($setting);
$this->em->flush();
return $this->redirectToRoute('app_setting_list', [], Response::HTTP_SEE_OTHER);
}
return $this->render('setting/editSetting.html.twig',
[
'form' => $form->createView()
]
);
}
}