<?php
namespace Web\Core\Engine;
use Application\Modules\Advertisement\Model\Advertisement as ApplicationAdvertisementModel;
use Common\Exception\RedirectException;
use IcebirdCMS\App\KernelLoader;
use Web\Core\Engine\Block\ModuleExtraInterface;
use Web\Core\Header\Header;
use Web\Core\Language\Language;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\KernelInterface;
use Web\Core\Engine\Block\ExtraInterface as WebBlockExtra;
use Web\Core\Engine\Block\Widget as WebBlockWidget;
use Application\Core\Engine\Model as ApplicationModel;
use Web\Modules\Advertisement\Model\Advertisement as WebAdvertisementModel;
use Web\Modules\Profiles\Model\Authentication as WebAuthenticationModel;
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
class Page extends KernelLoader
{
protected $breadcrumb;
protected $extras = [];
protected $footer;
protected $header;
protected $pageId;
protected $record = [];
protected $templatePath;
protected $statusCode = Response::HTTP_OK;
protected $template;
protected $url;
public function __construct(KernelInterface $kernel)
{
parent::__construct($kernel);
$this->getContainer()->set('page', $this);
$this->template = $this->getContainer()->get('templating');
$this->url = $this->getContainer()->get('url');
}
public function load(): void
{
Model::getVisitorId();
$this->header = new Header($this->getKernel());
try {
$this->handlePage(Navigation::getPageId(implode('/', $this->url->getPages())));
} catch (NotFoundHttpException $notFoundHttpException) {
$this->handlePage(Response::HTTP_NOT_FOUND);
} catch (InsufficientAuthenticationException $insufficientAuthenticationException) {
$this->redirectToLogin();
}
}
private function handlePage(int $pageId)
{
$this->record = $this->getPageContent($pageId);
if (empty($this->record)) {
throw new NotFoundHttpException('No page was found for the page id:' . $pageId);
}
$this->checkAuthentication();
$this->pageId = (int)$this->record['id'];
if ($this->pageId === Response::HTTP_NOT_FOUND) {
$this->statusCode = Response::HTTP_NOT_FOUND;
if (extension_loaded('newrelic')) {
newrelic_name_transaction('404');
}
}
$this->breadcrumb = new Breadcrumb($this->getKernel());
$this->footer = new Footer($this->getKernel());
$this->processPage();
array_map([$this, 'processExtra'], $this->extras);
}
private function checkAuthentication(): void
{
if (!isset($this->record['data']['auth_required'])
|| !$this->record['data']['auth_required']
|| !ApplicationModel::isModuleInstalled('Profiles')
) {
return;
}
if (!WebAuthenticationModel::isLoggedIn()) {
throw new InsufficientAuthenticationException('You must log in to see this page');
}
if (empty($this->record['data']['auth_groups'])) {
return;
}
foreach ($this->record['data']['auth_groups'] as $group) {
if (WebAuthenticationModel::getProfile()->isInGroup($group)) {
return;
}
}
throw new NotFoundHttpException('The current page is not available to the logged in profile');
}
public function getCookie()
{
$cookie = $this->getContainer()->get('database')->getRecord(
'SELECT a.*
FROM cookie_consent AS a
WHERE a.language = ?',
array(WEB_LANGUAGE)
);
$cookie['exclude_pages'] = unserialize($cookie['exclude_pages']);
$this->template->assignGlobal('cookieConsent', $cookie);
}
public function isMarketingCookie()
{
$this->template->assignGlobal('isMarketingCookie', isset($_COOKIE['COOKIE_MARKETING']) ? $_COOKIE['COOKIE_MARKETING'] : false);
}
public function display(): Response
{
try {
$this->template->assignGlobal('isPage' . $this->pageId, true);
$this->template->assignGlobal('isChildOfPage' . $this->record['parent_id'], true);
//CookieConsent module
if (ApplicationModel::isModuleInstalled('CookieConsent')) {
$this->getCookie();
$this->isMarketingCookie();
}
$this->template->assignGlobal(
'cookieBarHide',
!$this->get('icebird.settings')->get('Core', 'show_cookie_bar', false)
|| $this->getContainer()->get('icebird.cookie')->hasHiddenCookieBar()
);
$this->parsePositions();
$unusedPositions = array_diff(
$this->record['template_data']['names'],
array_keys($this->record['positions'])
);
foreach ($unusedPositions as $position) {
$this->template->assign('position' . \SpoonFilter::ucfirst($position), []);
}
$this->header->parse();
$this->breadcrumb->parse();
$this->parseLanguages();
$this->footer->parse();
return new Response(
$this->template->getContent($this->templatePath),
$this->statusCode
);
} catch (NotFoundHttpException $notFoundHttpException) {
$this->handlePage(Response::HTTP_NOT_FOUND);
return $this->display();
} catch (InsufficientAuthenticationException $insufficientAuthenticationException) {
$this->redirectToLogin();
}
}
private function redirectToLogin()
{
$this->redirect(
Navigation::getUrlForBlock('Profiles', 'Login') . '?queryString=' . Model::getRequest()->getRequestUri(),
Response::HTTP_TEMPORARY_REDIRECT
);
}
public function getExtras(): array
{
return $this->extras;
}
public function getId(): int
{
return $this->pageId;
}
private function getPageRecord(int $pageId): array
{
if ($this->url->getParameter('page_revision', 'int') === null) {
return Model::getPage($pageId);
}
$this->header->addMetaData(['name' => 'robots', 'content' => 'noindex, nofollow'], true);
return Model::getPageRevision($this->url->getParameter('page_revision', 'int'));
}
protected function getPageContent(int $pageId): array
{
$record = $this->getPageRecord($pageId);
if (empty($record)) {
return [];
}
if ($this->allPositionsAreEmpty($record['positions'])) {
$firstChildId = Navigation::getFirstChildId($record['id']);
if ($firstChildId !== 0) {
$this->redirect(Navigation::getUrl($firstChildId));
}
}
return $record;
}
private function allPositionsAreEmpty(array $positions): bool
{
foreach ($positions as $blocks) {
foreach ($blocks as $block) {
if ($block['extra_type'] === 'block'
|| $block['extra_type'] === 'widget'
|| trim($block['html']) !== ''
) {
return false;
}
}
}
return true;
}
public function getRecord(): array
{
return $this->record;
}
public function getStatusCode(): int
{
return $this->statusCode;
}
protected function parseLanguages(): void
{
if (!$this->getContainer()->getParameter('site.multilanguage') || count(Language::getActiveLanguages()) === 1) {
return;
}
$this->template->assignGlobal(
'languages',
array_map(
function (string $language) {
return [
'url' => $language != SITE_DEFAULT_LANGUAGE ? '/' . $language . '/' : '/',
'label' => $language,
'name' => Language::msg(mb_strtoupper($language)),
'current' => $language === LANGUAGE,
];
},
Language::getActiveLanguages()
)
);
}
protected function parsePositions(): void
{
$positions = [];
$mainVariables = $this->template->getAssignedVariables();
foreach ($this->record['positions'] as $position => $blocks) {
foreach ($blocks as $i => $block) {
$positions[$position][$i] = $this->parseBlock($block, $mainVariables);
}
$this->template->assign('position' . \SpoonFilter::ucfirst($position), $positions[$position]);
}
$category = '';
if (!empty($this->url->getParameter(1)))
$category = WebAdvertisementModel::getCategory($this->url->getParameter(1));
elseif ($this->getContainer()->get('request_stack')->getCurrentRequest()->getPathInfo() == '/bedrijven' && $this->getContainer()->get('request_stack')->getCurrentRequest()->query->has('adres')) {
$category = ApplicationAdvertisementModel::getCategoryByName($this->getContainer()->get('request_stack')->getCurrentRequest()->query->get('adres'));
}
if (!empty($category)) {
$banners = ApplicationAdvertisementModel::getMediaByRubriek($category['id'], 'banner');
$bannersBig = ApplicationAdvertisementModel::getMediaByRubriek($category['id'], 'banner_big');
$leaderboards = ApplicationAdvertisementModel::getMediaByRubriek($category['id'], 'leaderboard');
if (!empty($banners)) {
unset($positions['logogridsidebar']);
foreach ($banners as $banner) {
$title = $banner['title'];
$url = '/src/Web/Files/Advertisement/banner/' . $category['id'] . '/source/' . $banner['filename'];
$html = '<div onclick="stats(\'banner\', false, \'' . $title . '\')" class="single-logo-overzichtspagina-grid" data-href="' . strtolower($banner['url']) . '">
<img class="logo-bedrijf" src="' . $url . '" alt="placeholder" data-label="Logo bedrijf (225px X 110px)" data-type="image" style="display: block;">
<div class="single-logo-overzichtspagina-grid-link">
<a href="' . strtolower($banner['url']) . '" target="_blank" class="hidden" data-label="Link naar bedrijf advertentie" data-type="link">' . $banner['title'] . '</a>
</div>
</div>';
$positions['logogridsidebar'][]['html'] = $html;
}
}
if (!empty($bannersBig)) {
unset($positions['biglogossidebar']);
foreach ($bannersBig as $bannerBig) {
$title = $bannerBig['title'];
$url = '/src/Web/Files/Advertisement/banner_big/' . $category['id'] . '/source/' . $bannerBig['filename'];
$html = '<div onclick="stats(\'banner_big\', false, \'' . $title . '\')" class="single-logo-overzichtspagina-groot" data-href="' . strtolower($bannerBig['url']) . '">
<img class="logo-bedrijf-groot" src="' . $url . '" alt="placeholder" data-label="Logo bedrijf (480px X 380px)" data-type="image" style="display: block;">
<div class="single-logo-overzichtspagina-groot-link">
<a href="' . strtolower($bannerBig['url']) . '" class="hidden" data-label="Link naar bedrijf advertentie" data-type="link">' . $bannerBig['title'] . '</a>
</div>
</div>';
$positions['biglogossidebar'][]['html'] = $html;
}
}
if (!empty($leaderboards)) {
unset($positions['advertentieafbeelding']);
foreach ($leaderboards as $leaderboard) {
$title = $leaderboard['title'];
$url = '/src/Web/Files/Advertisement/leaderboard/' . $category['id'] . '/source/' . $leaderboard['filename'];
$html = '<div onclick="stats(\'leaderboard\', false, \'' . $title . '\')" class="slider-overzichtspagina-top-container blank-data-href"><img class="single-advertentie-overzichtspagina hide-670" src="'.$url.'" alt="placeholder" data-label="'.$title.'" data-type="image" style="display: block;">
<div class="single-advertentie-overzichtspagina-link">
<a href="' . strtolower($leaderboard['url']) . '" class="hidden" data-label="Link naar bedrijf '.$title.'" data-type="link">' . strtolower($leaderboard['url']) . '</a>
</div></div>';
$positions['advertentieafbeelding'][]['html'] = $html;
}
}
}
$this->template->assign('positions', $positions);
}
private function parseBlock(array $block, array $mainVariables): array
{
if (!isset($block['extra'])) {
$parsedBlock = $block;
if (array_key_exists('blockContent', $block)) {
$parsedBlock['html'] = $block['blockContent'];
}
return $parsedBlock;
}
$block['extra']->execute();
$extraVariables = $block['extra']->getTemplate()->getAssignedVariables();
$block['extra']->getTemplate()->assignArray($mainVariables);
$block['extra']->getTemplate()->assignArray($extraVariables);
return [
'variables' => $block['extra']->getTemplate()->getAssignedVariables(),
'blockIsEditor' => false,
'html' => $block['extra']->getContent(),
];
}
protected function processExtra(ModuleExtraInterface $extra): void
{
$this->getContainer()->get('logger.public')->info(
'Executing ' . get_class($extra) . " '{$extra->getAction()}' for module '{$extra->getModule()}'."
);
if (is_callable([$extra, 'getOverwrite']) && $extra->getOverwrite()) {
$this->templatePath = $extra->getTemplatePath();
}
}
private function addAlternateLinks(): void
{
if (!$this->getContainer()->getParameter('site.multilanguage')) {
return;
}
array_map([$this, 'addAlternateLinkForLanguage'], Language::getActiveLanguages());
}
private function addAlternateLinkForLanguage(string $language): void
{
if ($language === LANGUAGE) {
return;
}
$pageInfo = Model::getPage($this->pageId);
if (isset($pageInfo['data']['hreflang_' . $language])) {
$url = Navigation::getUrl($pageInfo['data']['hreflang_' . $language], $language);
} else {
$url = Navigation::getUrl($this->pageId, $language);
}
if ($this->pageId !== Response::HTTP_NOT_FOUND
&& $url === Navigation::getUrl(Response::HTTP_NOT_FOUND, $language)) {
return;
}
if (strpos($url, '/') === 0) {
$url = SITE_URL . $url;
}
$this->header->addLink(['rel' => 'alternate', 'hreflang' => $language, 'href' => $url]);
}
private function assignPageMeta(): void
{
$this->header->setPageTitle(
$this->record['meta_title'],
$this->record['meta_title_overwrite']
);
$this->header->addMetaDescription(
$this->record['meta_description'],
$this->record['meta_description_overwrite']
);
$this->header->addMetaKeywords(
$this->record['meta_keywords'],
$this->record['meta_keywords_overwrite']
);
$this->header->setMetaCustom($this->record['meta_custom']);
if (isset($this->record['meta_seo_index'])) {
$this->header->addMetaData(
['name' => 'robots', 'content' => $this->record['meta_seo_index']]
);
}
if (isset($this->record['meta_seo_follow'])) {
$this->header->addMetaData(
['name' => 'robots', 'content' => $this->record['meta_seo_follow']]
);
}
}
protected function processPage(): void
{
$this->assignPageMeta();
new Navigation($this->getKernel());
$this->addAlternateLinks();
$pageInfo = Navigation::getPageInfo($this->record['id']);
$this->record['has_children'] = $pageInfo['has_children'];
$this->template->assignGlobal('page', $this->record);
$this->templatePath = $this->record['template_path'];
foreach ($this->record['positions'] as $position => &$blocks) {
if (!in_array($position, $this->record['template_data']['names'])) {
continue;
}
$blocks = array_map(
function (array $block) {
if ($block['extra_id'] === null) {
return [
'blockIsEditor' => true,
'blockContent' => $block['html'],
];
}
$block = ['extra' => $this->getExtraForBlock($block)];
$this->extras[] = $block['extra'];
return $block;
},
$blocks
);
}
}
private function getExtraForBlock(array $block): ModuleExtraInterface
{
if ($block['extra_type'] === 'block') {
if (extension_loaded('newrelic')) {
newrelic_name_transaction($block['extra_module'] . '::' . $block['extra_action']);
}
return new WebBlockExtra(
$this->getKernel(),
$block['extra_module'],
$block['extra_action'],
$block['extra_data']
);
}
return new WebBlockWidget(
$this->getKernel(),
$block['extra_module'],
$block['extra_action'],
$block['extra_data']
);
}
private function redirect(string $url, int $code = RedirectResponse::HTTP_FOUND): void
{
throw new RedirectException('Redirect', new RedirectResponse($url, $code));
}
}