<?php
namespace App\Controller;
use Twig\Environment;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Finder\Finder;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use App\Repository\UserRepository;
use App\Service\UserService;
use Vanilla\JsConnect\JsConnect;
use Vanilla\JsConnect\JsConnectJSONP;
final class PageGeneratorController extends AbstractController
{
private const CONTACT_EMAIL = 'info@hephaestos.eu';
/** @var Environment */
private $twig;
/** @var ChannelContextInterface */
private $channelContext;
private Jsconnect $jsconnect;
public function __construct(Environment $twig, Jsconnect $jsconnect, ChannelContextInterface $channelContext)
{
$this->twig = $twig;
$this->jsconnect = $jsconnect;
$this->channelContext = $channelContext;
}
public function menuAction(): Response
{
return $this->render('@SyliusShop/Menu/_pageMenu.html.twig');
}
/**
* Subscription page disabled for the beta-only release.
*/
public function subscriptionAction(): Response
{
throw $this->createNotFoundException();
}
/**
* @Route("/beta-testers", name="beta_testers")
*/
public function betaTestersAction(Request $request, \Swift_Mailer $mailer): Response
{
$formData = [
'firstName' => '',
'lastName' => '',
'email' => '',
'company' => '',
'role' => '',
'showType' => '',
'operatingSystem' => '',
'hardware' => '',
'features' => '',
'usage' => '',
'feedback' => '',
'availability' => '',
];
if ($request->isMethod('POST')) {
$formData = array_map(
static fn ($value): string => trim((string) $value),
array_intersect_key($request->request->all(), $formData)
) + $formData;
$honeypot = trim((string) $request->request->get('website', ''));
$requiredFields = ['firstName', 'lastName', 'email', 'role', 'operatingSystem', 'usage', 'feedback'];
$missingFields = array_filter($requiredFields, static fn (string $field): bool => '' === $formData[$field]);
if ('' !== $honeypot) {
$this->addFlash('success', 'beta.form.success');
return $this->redirectToRoute('beta_testers');
}
if (!$this->isCsrfTokenValid('beta_tester_application', (string) $request->request->get('_token'))) {
$this->addFlash('error', 'beta.form.csrf_error');
} elseif ([] !== $missingFields || false === filter_var($formData['email'], FILTER_VALIDATE_EMAIL)) {
$this->addFlash('error', 'beta.form.error');
} else {
$messageBody = $this->renderView('Email/beta_tester_application.html.twig', [
'data' => $formData,
]);
$message = (new \Swift_Message('Nouvelle candidature beta testeur Hephaestos'))
->setFrom([self::CONTACT_EMAIL => 'Hephaestos'])
->setTo([self::CONTACT_EMAIL])
->setReplyTo([$formData['email']])
->setBody($messageBody, 'text/html');
try {
if (0 === $mailer->send($message)) {
throw new \RuntimeException('Beta email was not accepted by the transport.');
}
} catch (\Throwable $exception) {
$this->addFlash('error', 'beta.form.mail_error');
return $this->redirectToRoute('beta_testers');
}
$this->addFlash('success', 'beta.form.success');
return $this->redirectToRoute('beta_testers');
}
}
return $this->render('page_generator/beta_testers.html.twig', [
'formData' => $formData,
]);
}
/**
* @Route("/formation/demande", name="formation_request")
*/
public function formationRequestAction(Request $request, \Swift_Mailer $mailer): Response
{
$formData = [
'firstName' => '',
'lastName' => '',
'email' => '',
'company' => '',
'subject' => '',
'needs' => '',
'availability' => '',
];
if ($request->isMethod('POST')) {
$formData = array_map(
static fn ($value): string => trim((string) $value),
array_intersect_key($request->request->all(), $formData)
) + $formData;
$honeypot = trim((string) $request->request->get('website', ''));
$requiredFields = ['firstName', 'lastName', 'email', 'subject', 'needs'];
$missingFields = array_filter($requiredFields, static fn (string $field): bool => '' === $formData[$field]);
if ('' !== $honeypot) {
$this->addFlash('success', 'formation.request.success');
return $this->redirectToRoute('formation_request');
}
if (!$this->isCsrfTokenValid('formation_request', (string) $request->request->get('_token'))) {
$this->addFlash('error', 'formation.request.csrf_error');
} elseif ([] !== $missingFields || false === filter_var($formData['email'], FILTER_VALIDATE_EMAIL)) {
$this->addFlash('error', 'formation.request.error');
} else {
$messageBody = $this->renderView('Email/formation_request.html.twig', [
'data' => $formData,
]);
$message = (new \Swift_Message('Nouvelle demande de formation Hephaestos'))
->setFrom([self::CONTACT_EMAIL => 'Hephaestos'])
->setTo([self::CONTACT_EMAIL])
->setReplyTo([$formData['email']])
->setBody($messageBody, 'text/html');
try {
if (0 === $mailer->send($message)) {
throw new \RuntimeException('Training request email was not accepted by the transport.');
}
} catch (\Throwable $exception) {
$this->addFlash('error', 'formation.request.mail_error');
return $this->redirectToRoute('formation_request');
}
$this->addFlash('success', 'formation.request.success');
return $this->redirectToRoute('formation_request');
}
}
return $this->render('page_generator/formation_request.html.twig', [
'formData' => $formData,
]);
}
private function getChannel(): mixed
{
return $this->channelContext->getChannel();
}
/**
* @Route("/old_version", name="old_version")
*/
public function oldversionAction(Request $request): Response
{
$finderwindows64 = new Finder();
$windowsfiles64 = $finderwindows64->files()->name('*.zip')->in($this->get('kernel')->getProjectDir() . "/public/versions/old/Windows/x64");
$finderwindows32 = new Finder();
$windowsfiles32 = $finderwindows32->files()->name('*.zip')->in($this->get('kernel')->getProjectDir() . "/public/versions/old/Windows/x86");
$findermac = new Finder();
$macfiles = $findermac->files()->name('*.zip')->in($this->get('kernel')->getProjectDir() . "/public/versions/old/OSX");
return $this->render('page_generator/oldversion.html.twig', array('windowsfiles64' => $windowsfiles64,'windowsfiles32' => $windowsfiles32, 'macfiles' => $macfiles));
}
/**
* @Route("/download", name="download")
public function downloadAction(Request $request): Response
{
return $this->render('page_generator/download.html.twig');
}
*/
/**
* @Route("/formation", name="formation")
*/
public function formationAction(Request $request): Response
{
$locale = $request->getLocale();
$template = str_starts_with((string) $locale, 'en')
? 'page_generator/formation.en.html.twig'
: 'page_generator/formation.html.twig';
return $this->render($template);
}
/**
* @Route("/forum", name="forum")
*/
public function forumAction(Request $request, UserService $userService): Response
{
$forumRoot = rtrim((string) $this->getParameter('forumdomain'), '/');
$forumUrl = $forumRoot . '/';
$user = $this->getUser();
if ($user === null || !is_object($user) || !method_exists($user, 'isVerified') || !$user->isVerified()) {
return new RedirectResponse($forumUrl);
}
$customer = $userService->getCustomerByUser($user);
$forumName = method_exists($customer, 'getPseudo') ? trim((string) $customer->getPseudo()) : '';
if ('' === $forumName) {
$this->addFlash('error', 'customer.pseudo.required_for_forum');
return $this->redirectToRoute('sylius_shop_account_profile_update');
}
$forumEmail = $this->resolveForumEmail($customer, $user);
$ssoToken = $this->createForumSsoToken([
'sub' => (string) $user->getId(),
'name' => $forumName,
'email' => $forumEmail,
]);
$forumSsoPath = '/app.php/hephaestos/sso/login';
$forumSsoUrl = $forumRoot . $forumSsoPath . '?token=' . rawurlencode($ssoToken) . '&return=' . rawurlencode('/');
return new RedirectResponse($forumSsoUrl);
}
private function resolveForumEmail(object $customer, object $user): string
{
$candidates = [
method_exists($customer, 'getEmail') ? $customer->getEmail() : null,
method_exists($user, 'getEmail') ? $user->getEmail() : null,
method_exists($user, 'getUsername') ? $user->getUsername() : null,
];
foreach ($candidates as $candidate) {
$candidate = trim((string) $candidate);
if ('' !== $candidate) {
return $candidate;
}
}
return 'forum-user-' . (method_exists($user, 'getId') ? (string) $user->getId() : 'hephaestos') . '@hephaestos.local';
}
private function resolveForumName(object $customer, object $user): string
{
$candidates = [
method_exists($customer, 'getPseudo') ? $customer->getPseudo() : null,
method_exists($customer, 'getFullName') ? $customer->getFullName() : null,
trim(sprintf(
'%s %s',
method_exists($customer, 'getFirstName') ? (string) $customer->getFirstName() : '',
method_exists($customer, 'getLastName') ? (string) $customer->getLastName() : ''
)),
method_exists($customer, 'getEmail') ? $customer->getEmail() : null,
method_exists($user, 'getEmail') ? $user->getEmail() : null,
method_exists($user, 'getUsername') ? $user->getUsername() : null,
'user-' . (method_exists($user, 'getId') ? (string) $user->getId() : 'hephaestos'),
];
foreach ($candidates as $candidate) {
$candidate = trim((string) $candidate);
if ('' !== $candidate) {
return $candidate;
}
}
return 'Hephaestos user';
}
private function createForumSsoToken(array $identity): string
{
$now = time();
$payload = [
'sub' => (string) ($identity['sub'] ?? ''),
'name' => (string) ($identity['name'] ?? ''),
'email' => (string) ($identity['email'] ?? ''),
'iat' => $now,
'exp' => $now + 120,
'nonce' => bin2hex(random_bytes(8)),
];
$payloadJson = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
if (false === $payloadJson) {
throw new \RuntimeException('Unable to encode forum SSO payload.');
}
$payloadB64 = rtrim(strtr(base64_encode($payloadJson), '+/', '-_'), '=');
$secret = (string) $this->getParameter('forum_sso_secret');
$signature = hash_hmac('sha256', $payloadB64, $secret);
return $payloadB64 . '.' . $signature;
}
/**
* @Route("/wiki", name="wiki")
*/
public function wikiAction(Request $request): Response
{
return $this->render('page_generator/wiki.html.twig');
}
/**
* @Route("/redirectlogin", name="redirectlogin")
*/
public function redirectloginAction(Request $request): Response
{
$context = new RequestContext();
$context->fromRequest(Request::createFromGlobals());
$url = $this->generateUrl('sylius_shop_login', [
'_locale' => 'fr',
], UrlGeneratorInterface::ABSOLUTE_URL);
$js = '<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script><script type="text/javascript">jQuery(document).ready( function() {
top.location = "' . $url . '";});</script>';
$response = new Response();
$response->prepare($request);
$response->setContent($js);
$response->send();
return $this->redirect($url);
//return $this->redirectToRoute('sylius_shop_login', [], 301);
}
/**
* @Route("/redirectlogout", name="redirectlogout")
*/
public function redirectlogoutAction(Request $request): Response
{
$context = new RequestContext();
$context->fromRequest(Request::createFromGlobals());
$url = $this->generateUrl('sylius_shop_logout', ['_locale' => 'fr',], UrlGeneratorInterface::ABSOLUTE_URL);
$js = '<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script><script type="text/javascript">jQuery(document).ready( function() {
top.location = "' . $url . '";});</script>';
$response = new Response();
$response->prepare($request);
$response->setContent($js);
$response->send();
}
/**
* @Route("/redirectregister", name="redirectregister")
*/
public function redirectregisterAction(Request $request): Response
{
$context = new RequestContext();
$context->fromRequest(Request::createFromGlobals());
$url = $this->generateUrl('sylius_shop_register', ['_locale' => 'fr',], UrlGeneratorInterface::ABSOLUTE_URL);
$js = '<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script><script type="text/javascript">jQuery(document).ready( function() { top.location = "' . $url . '";});</script>';
$response = new Response();
$response->prepare($request);
$response->setContent($js);
$response->send();
// return $this->redirect($url);
//return $this->redirectToRoute('sylius_shop_register', [], 301);
}
/**
* @Route("/electronique", name="electronique")
*/
public function electroniqueAction(Request $request): Response
{
$code = array('Board_Taxons','DMX_HF','PWM_DIMMER_Taxon', 'HF_PROJECTOR__Taxon','books');
return $this->render('page_generator/electronique.html.twig', array('code' => $code, 'maxresult' => -1));
}
/**
* @Route("/features", name="features")
*/
public function featuresAction(Request $request): Response
{
return $this->render('page_generator/features.html.twig');
}
/**
* @Route("/about", name="about")
*/
public function aboutAction(Request $request): Response
{
return $this->render('page_generator/about.html.twig');
}
/**
* @Route("/shipping", name="shipping")
*/
public function deliveryAction(Request $request): Response
{
return $this->render('page_generator/shipping.html.twig');
}
/**
* @Route("/FAQ", name="FAQ")
*/
public function FAQAction(Request $request): Response
{
return $this->render('page_generator/FAQ.html.twig');
}
/**
* @Route("/privacy", name="privacy")
*/
public function privacyAction(Request $request): Response
{
return $this->render('page_generator/privacy.html.twig');
}
/**
* @Route("/return", name="return")
*/
public function returnAction(Request $request): Response
{
return $this->render('page_generator/return.html.twig');
}
/**
* @Route("/terms", name="terms")
*/
public function termsAction(Request $request): Response
{
return $this->render('page_generator/terms.html.twig');
}
/**
* @Route("/confirmationresend", name="confirmationresend", methods={"POST"})
*/
public function resendVerificationTokenfromMailAction(Request $request): Response
{
if (!$this->isCsrfTokenValid('resend_verification_email', (string) $request->request->get('_token'))) {
$this->addTranslatedFlash('error', 'Invalid security token.');
return $this->redirectToRoute('sylius_shop_login');
}
$email = trim((string) $request->request->get('emailverif', ''));
if ('' === $email || false === filter_var($email, FILTER_VALIDATE_EMAIL)) {
// Neutral response to avoid user enumeration.
$this->addTranslatedFlash('success', 'sylius.user.verify_email_request');
return $this->redirectToRoute('sylius_shop_login');
}
$cooldownKey = 'resend_verification_last_' . sha1(strtolower($email) . '|' . (string) $request->getClientIp());
$cooldownSeconds = 60;
if ($request->hasSession()) {
$lastAttemptAt = (int) $request->getSession()->get($cooldownKey, 0);
if ($lastAttemptAt > 0 && (time() - $lastAttemptAt) < $cooldownSeconds) {
$this->addTranslatedFlash('success', 'sylius.user.verify_email_request');
return $this->redirectToRoute('sylius_shop_login');
}
$request->getSession()->set($cooldownKey, time());
}
$customer = $this->container->get('sylius.repository.customer')->findOneBy(['email' => $email]);
$user = null !== $customer ? $customer->getUser() : null;
if (null !== $user && null === $user->getVerifiedAt()) {
$sender = $this->container->get('sylius.email_sender');
$logpath = 'https://www.hephaestos.eu/build/img/baniere1024x768.png';
$localeCode = $this->get('sylius.context.locale')->getLocaleCode();
$channel = $this->container->get('sylius.context.channel')->getChannel();
$sender->send(\Sylius\Bundle\UserBundle\Mailer\Emails::EMAIL_VERIFICATION_TOKEN, [$email], ['user' => $user, 'channel' => $channel, 'localeCode' => $localeCode, 'image_src' => $logpath]);
}
$this->addTranslatedFlash('success', 'sylius.user.verify_email_request');
return $this->redirectToRoute('sylius_shop_login');
}
/**
* {@inheritdoc}
*/
protected function addTranslatedFlash(string $type, string $message): void
{
$translator = $this->container->get('translator');
$this->container->get('session')->getFlashBag()->add($type, @$this->translator->trans($message, [], 'flashes'));
}
}