<?php
namespace App\Controller;
use App\Dictionary\ForbiddenEmails;
use App\Dictionary\PageDictionary;
use App\Dictionary\RedisKey;
use App\Redis\RedisBlogArticle;
use App\Redis\RedisCategory;
use App\Redis\RedisPageMetadata;
use Doctrine\ORM\EntityManagerInterface;
use App\Service\PageStatus;
use App\Entity\Category;
use App\Entity\Offer;
use App\Dictionary\TypeDictionary;
use App\Entity\Page;
use App\Form\ContactForm;
use Doctrine\ORM\EntityNotFoundException;
use Psr\Cache\InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Default controller for each subpage on website
*/
class PageController extends AbstractController
{
private const TWIG_TEMPLATE_PATH = 'content/';
private const DB_COLUMN_SYSTEM_NAME = 'systemName';
/**
* @var EntityManagerInterface
*/
private $em;
/**
* @var RequestStack
*/
private $requestStack;
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var Page|null
*/
private $page;
/**
* @var SessionInterface
*/
private $session;
/**
* @var PageStatus
*/
private $pageStatus;
/**
* @var ContactFormMailerController
*/
private $pageMailer;
/**
* @var string|null
*/
private $requestedPageName;
/**
* @var RedisBlogArticle
*/
private $blogArticle;
/**
* @var RedisPageMetadata
*/
private RedisPageMetadata $redisPageMetadata;
/**
* @var string
*/
private string $pageType;
/**
* @var RedisCategory
*/
private RedisCategory $redisCategory;
/**
* @param RequestStack $requestStack
* @param LoggerInterface $logger
* @param EntityManagerInterface $em
* @param SessionInterface $session
* @param PageStatus $pageStatus
* @param ContactFormMailerController $pageMailer
* @param RedisBlogArticle $blogArticle
* @param RedisPageMetadata $redisPageMetadata
* @param RedisCategory $redisCategory
* @param string $pageType
*/
public function __construct(
RequestStack $requestStack,
LoggerInterface $logger,
EntityManagerInterface $em,
SessionInterface $session,
PageStatus $pageStatus,
ContactFormMailerController $pageMailer,
RedisBlogArticle $blogArticle,
RedisPageMetadata $redisPageMetadata,
RedisCategory $redisCategory,
$pageType = TypeDictionary::PAGE_TYPE_WWW
)
{
$this->requestStack = $requestStack;
$this->requestedPageName = $requestStack->getCurrentRequest()->get('page_name');
$this->logger = $logger;
$this->em = $em;
$this->session = $session;
$this->pageStatus = $pageStatus;
$this->pageMailer = $pageMailer;
$this->blogArticle = $blogArticle;
$this->redisPageMetadata = $redisPageMetadata;
$this->pageType = $pageType;
/** Nie można uzyć session managera, gdyz ta sesja jest wywoływana bezpośrednio ze stałej globalnej $_SESSION */
if (isset($_SESSION['ogloszenie_filtr'])) {
unset($_SESSION['ogloszenie_filtr']);
}
$this->redisCategory = $redisCategory;
}
/**
* Default action run on each subpage
*
* @param Request $request
*
* @return RedirectResponse|Response
* @throws EntityNotFoundException
* @throws InvalidArgumentException
*/
public function indexAction(Request $request)
{
/** @var null|Category $category */
$category = $this->redisCategory->getRedisItem(RedisKey::OFFER_CATEGORIES, $this->requestedPageName);
/** Przekierowanie na stronę wyszukiwania z branżą, jeżeli ktoś wpisze przyjazny adres np. /sale-weselne */
if ($category !== null) {
return $this->redirect(PageDictionary::ADRES_STRONY_WWW . '/' . $this->requestedPageName, 301);
}
/** @var Page Looking for an existing page page */
$this->page = $this->redisPageMetadata->getRedisItem(RedisKey::PAGES_METADATA, $this->requestedPageName);
if ($this->pageStatus->checkPageAvailability() === false) {
return $this->render("elements/page_not_available_error.html.twig");
}
if ($this->page === null || $this->page->getStatus() !== 'T') {
return $this->render("bundles/TwigBundle/Exception/error404.html.twig");
}
$contactForm = $this->createForm(ContactForm::class);
$contactForm->handleRequest($request);
if ($contactForm->isSubmitted() && $contactForm->isValid()) {
$email = $contactForm->getData()['email'] ?? '';
$message = $contactForm->getData()['description'] ?? '';
if ($this->validateFrobiddenDomains($email) === false && $this->validateForbiddenStrings($message) === false) {
$this->sendContactEmail($contactForm);
}
}
return $this->render('default/index.html.twig', [
'page' => $this->page,
'theme_name' => self::TWIG_TEMPLATE_PATH . $this->page->getThemeName(),
'menu_data' => [
'blog_articles' => $this->blogArticle->getRedisItems(RedisKey::BLOG_ARTICLES),
'categories' => $this->redisCategory->getRedisItems(RedisKey::OFFER_CATEGORIES),
'comments' => $this->getLastOpinion(3)
],
'form' => $contactForm->createView(),
'messages' => [],
]);
}
/**
* Sending emails via contact form
*
* @param FormInterface $contactForm
*/
private function sendContactEmail(FormInterface $contactForm)
{
try {
$this->pageMailer->sendMailToAdministrator($contactForm->getData());
$this->pageMailer->sendMailToSender($contactForm->getData());
$this->addFlash('success', 'Formularz kontaktowy został wysłany.');
} catch (\Swift_TransportException | \Swift_RfcComplianceException | \Swift_SwiftException $e) {
$this->logger->error('Blad wysylki emaila z formularza kontaktowego', $e->getMessage());
$this->addFlash('error', 'Błąd podczas wysyłki formularza kontaktowego. Prosimy spróbować ponownie.');
}
}
/**
* @param int $numbersOpinions
*
* @return array
* @todo Zrefaktoryzować poniższy kod, przpeisać na ORM, bardziej obiektowo
*
* Pobieranie ostatnio dodanyhch komentarzy
*
*/
private function getLastOpinion(int $numbersOpinions = 3)
{
$offerRepository = $this->em->getRepository(Offer::class);
$lastOfferRate = $offerRepository->getLastRateOffer($numbersOpinions);
$offersId = array_column($lastOfferRate, 'oferta_id');
return [
'offer_rate_details' => $offerRepository->getLastRateOfferDetails($offersId),
'offer_rate' => $lastOfferRate
];
}
/**
* Sprawdzenie zakazanych domen, które nie będą wysyłały e-maili poprzez formularzk ontaktowy
*
* @param string $email
*
* @return bool
*/
private function validateFrobiddenDomains(string $email = ''): bool
{
$emailDomain = substr($email, strpos($email, '@') + 1, 255);
if (in_array(strtolower($emailDomain), ForbiddenEmails::FORBIDDEN_EMAIL_DOMAINS)) {
return true;
}
return false;
}
/**
* Sprawdzenie czy dany fragment tekstu, wystepuje w treści wiadomości
*
* @param string $emailMessage
*
* @return bool
*/
private function validateForbiddenStrings(string $emailMessage = ''): bool
{
$emailMessage = strtolower($emailMessage);
foreach (ForbiddenEmails::FORBIDDEN_STRINGS as $string) {
$strPosition = strpos($emailMessage, strtolower($string));
if ($strPosition !== false) {
return true;
}
}
return false;
}
}