<?php
namespace App\Controller;
use App\Service\Internal\CmsService;
use App\Service\Internal\HomePageService;
use App\Service\Internal\LineService;
use App\Service\Internal\SiteMapService;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use App\Service\Internal\NetworkService;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\Translation\TranslatorInterface;
class SiteMapController extends AbstractController
{
public const SITEMAP_PATH = '/public/sitemap/';
public const LINE_SCHEDULES_FILE_NAME = 'lines-schedules.txt';
public const STOPS_FILE_NAME = 'stops.html';
public const CITIES_FILE_NAME = 'cities.txt';
public const PAGES_FILE_NAME = 'pages.txt';
/** Cache duration in hours **/
public const CACHE_DURATION = 24;
/**
* Get sitemap
*/
public function getContent(
HomePageService $newsPageService,
SiteMapService $siteMapService,
NetworkService $networkService
): Response {
$parameters = $newsPageService->getRenderParameters();
$parameters['isXmlHttpMode'] = true;
$subNetworks = $networkService->getSubNetworks();
$subNetworksName = [];
foreach ($subNetworks as $subNetwork) {
$subNetworksName[$subNetwork['id']]['name'] = $siteMapService->cleanStr($subNetwork['name']);
}
$parameters['subNetworks'] = $subNetworks;
$parameters['subNetworksName'] = $subNetworksName;
return $this->render('pages/sitemap/sitemap.html.twig', $parameters);
}
/**
* Get subNetwork Lines
*/
public function subNetworkLines(
$id,
HomePageService $newsPageService,
SiteMapService $siteMapService,
NetworkService $networkService
): Response {
$parameters = $newsPageService->getRenderParameters();
$parameters['isXmlHttpMode'] = true;
$subNetwork = $networkService->getSubNetwork($id);
$lines = $networkService->getSubNetworkLines($id);
$parameters['subNetwork'] = $subNetwork;
$parameters['subNetworkName'] = $siteMapService->cleanStr($subNetwork[0]['name']);
$parameters['lines'] = $lines;
return $this->render('pages/sitemap/subnetwork-lines.html.twig', $parameters);
}
/**
* Get lines schedules sitemap
*/
public function getLinesSchedules(
Request $request,
LineService $lineService,
SiteMapService $siteMapService,
TranslatorInterface $translator
): BinaryFileResponse {
$locale = $request->getLocale();
$networkId = $this->getParameter('network_id');
$baseUrl = 'https://' . $request->getHost();
$translator->setLocale($locale);
$publicResourcesFolderPath = $this->getParameter(
'kernel.project_dir'
) . self::SITEMAP_PATH . $networkId . '/' . $locale . '/';
$filename = self::LINE_SCHEDULES_FILE_NAME;
$file = $publicResourcesFolderPath . $filename;
$currentTime = time();
if (file_exists($file)) {
$fileTime = filemtime($file);
$seconds = $currentTime - $fileTime;
$hours = floor($seconds / 3600);
if ($hours < self::CACHE_DURATION) {
return new BinaryFileResponse($file);
}
}
// get translated url elements
$sSchedules = $translator->trans('route.schedules');
$sLine = $translator->trans('route.line');
$sDirection = $translator->trans('route.direction');
$fileSystem = new Filesystem();
$root = $this->getParameter('kernel.project_dir');
try {
$fileSystem->mkdir($root . '/public/temp/');
} catch (IOExceptionInterface $exception) {
echo "An error occurred while creating your directory at " . $exception->getPath();
}
// temporary file will be deleted
$tempFile = $root . '/public/temp/sitemap-' . $networkId . '-' . $locale . '-lines-schedules.txt';
// final file will be stored
$file = $root . self::SITEMAP_PATH . $networkId . '/' . $locale . '/' . $filename;
try {
$fileSystem->touch($tempFile);
} catch (IOExceptionInterface $exception) {
echo "An error occurred while creating your file at " . $exception->getPath();
}
// get all network lines
$response = $lineService->getAllLines();
$lines = $response['lines'];
foreach ($lines as $line) {
$subNetwork = $siteMapService->cleanStr($line['subNetwork']['name']);
$lineName = $siteMapService->cleanStr($line['sName']);
// write url to bo stored on sitemap file
$content = $baseUrl . "/" . $locale . "/" . $sSchedules . "/" .
$subNetwork . "/" . $line['mode'] . "/" .
$sLine . "/" . $lineName . "/" . $sDirection . "/OUTWARD/" . $line['id'];
$url = str_replace([" ", "'"], "-", $content);
$fileSystem->appendToFile($tempFile, $url . PHP_EOL);
}
$fileSystem->copy($tempFile, $file);
$fileSystem->remove($tempFile);
return new BinaryFileResponse($file);
}
/**
* Get Cities sitemap
*/
public function getCities(
Request $request,
SiteMapService $siteMapService,
NetworkService $networkService,
TranslatorInterface $translator
): BinaryFileResponse {
$locale = $request->getLocale();
$networkId = $this->getParameter('network_id');
$baseUrl = 'https://' . $request->getHost();
$translator->setLocale($locale);
$publicResourcesFolderPath = $this->getParameter(
'kernel.project_dir'
) . self::SITEMAP_PATH . $networkId . '/' . $locale . '/';
$filename = self::CITIES_FILE_NAME;
$file = $publicResourcesFolderPath . $filename;
$currentTime = time();
if (file_exists($file)) {
$fileTime = filemtime($file);
$seconds = $currentTime - $fileTime;
$hours = floor($seconds / 3600);
if ($hours < self::CACHE_DURATION) {
return new BinaryFileResponse($file);
}
}
// get translated url elements
$sSchedules = $translator->trans('route.schedules');
$sLinesMap = $translator->trans('route.lines_plan');
$fileSystem = new Filesystem();
$root = $this->getParameter('kernel.project_dir');
try {
$fileSystem->mkdir($root . '/public/temp/');
} catch (IOExceptionInterface $exception) {
echo "An error occurred while creating your directory at " . $exception->getPath();
}
// temporary file will be deleted
$tempFile = $root . '/public/temp/sitemap-' . $networkId . '-' . $locale . '-cities.txt';
// final file will be stored
$file = $root . self::SITEMAP_PATH . $networkId . '/' . $locale . '/' . $filename;
try {
$fileSystem->touch($tempFile);
} catch (IOExceptionInterface $exception) {
echo "An error occurred while creating your file at " . $exception->getPath();
}
$localities = $networkService->getLocalities();
foreach ($localities as $locality) {
$localityName = $siteMapService->cleanStr($locality['name']);
// write url to bo stored on sitemap file
$content = $baseUrl . "/" . $locale . "/" . $sSchedules . "/" . $localityName . "/" . $sLinesMap . "/" . $locality['id'];
$url = str_replace([" ", "'"], "-", $content);
$fileSystem->appendToFile($tempFile, $url . PHP_EOL);
}
$fileSystem->copy($tempFile, $file);
$fileSystem->remove($tempFile);
return new BinaryFileResponse($file);
}
/**
* Get Pages sitemap
*/
public function getPages(
Request $request,
TranslatorInterface $translator,
CmsService $cmsService
): BinaryFileResponse {
$locale = $request->getLocale();
$networkId = $this->getParameter('network_id');
$baseUrl = 'https://' . $request->getHost();
$translator->setLocale($locale);
$publicResourcesFolderPath = $this->getParameter(
'kernel.project_dir'
) . self::SITEMAP_PATH . $networkId . '/' . $locale . '/';
$filename = self::PAGES_FILE_NAME;
$file = $publicResourcesFolderPath . $filename;
$currentTime = time();
if (file_exists($file)) {
$fileTime = filemtime($file);
$seconds = $currentTime - $fileTime;
$hours = floor($seconds / 3600);
}
// get translated url elements
$sSitemap = $translator->trans('route.sitemap');
$sNews = $translator->trans('route.news');
$sPage = $translator->trans('route.page');
$fileSystem = new Filesystem();
$root = $this->getParameter('kernel.project_dir');
try {
$fileSystem->mkdir($root . '/public/temp/');
} catch (IOExceptionInterface $exception) {
echo "An error occurred while creating your directory at " . $exception->getPath();
}
// temporary file will be deleted
$tempFile = $root . '/public/temp/sitemap-' . $networkId . '-' . $locale . '-pages.txt';
// final file will be stored
$file = $root . self::SITEMAP_PATH . $networkId . '/' . $locale . '/' . $filename;
try {
$fileSystem->touch($tempFile);
} catch (IOExceptionInterface $exception) {
echo "An error occurred while creating your file at " . $exception->getPath();
}
// Add site map url to xml sitemap
$sitemapUrl = $baseUrl . "/" . $locale . "/" . $sSitemap;
$fileSystem->appendToFile($tempFile, $sitemapUrl . PHP_EOL);
// Add news url to xml sitemap
$newsUrl = $baseUrl . "/" . $locale . "/" . $sNews;
$fileSystem->appendToFile($tempFile, $newsUrl . PHP_EOL);
$pages = $cmsService->getPages();
foreach ($pages as $page) {
// write url to bo stored on sitemap file
$content = $baseUrl . "/" . $locale . "/" . $sPage . "/" . $page->id;
$fileSystem->appendToFile($tempFile, $content . PHP_EOL);
}
$fileSystem->copy($tempFile, $file);
$fileSystem->remove($tempFile);
return new BinaryFileResponse($file);
}
/**
* Get StopAreas
*/
public function stopAreas(
Request $request,
HomePageService $newsPageService,
SiteMapService $siteMapService,
NetworkService $networkService
): BinaryFileResponse {
$locale = $request->getLocale();
$networkId = $this->getParameter('network_id');
$publicResourcesFolderPath = $this->getParameter(
'kernel.project_dir'
) . self::SITEMAP_PATH . $networkId . '/' . $locale . '/';
$filename = self::STOPS_FILE_NAME;
$file = $publicResourcesFolderPath . $filename;
if (!file_exists($file) || (file_exists($file) && floor(
(time() - filemtime($file)) / 3600
) > self::CACHE_DURATION)) {
$parameters = $newsPageService->getRenderParameters();
$parameters['isXmlHttpMode'] = true;
$stopAreas = $networkService->getStopAreas();
$letters = array();
foreach ($stopAreas as $item) {
$firstLetter = substr($item['name'], 0, 1);
$firstLetter = $siteMapService->cleanStr($firstLetter);
$letters[strtoupper($firstLetter)][] = [
'id' => $item['id'],
'name' => $item['name'],
'city' => $item['city']
];
}
$stopAreasName = [];
$citiesName = [];
foreach ($stopAreas as $stopArea) {
$stopArea['name'] = empty(!$stopArea['name']) ? $stopArea['name'] : '-';
$stopArea['city'] = empty(!$stopArea['city']) ? $stopArea['city'] : '-';
$stopAreasName[$stopArea['id']]['name'] = $siteMapService->cleanStr($stopArea['name']);
$citiesName[$stopArea['id']]['city'] = $siteMapService->cleanStr($stopArea['city']);
}
$parameters['letters'] = $letters;
$parameters['stopAreas'] = $stopAreas;
$parameters['stopAreasName'] = $stopAreasName;
$parameters['citiesName'] = $citiesName;
$html = $this->render('pages/sitemap/stopareas.html.twig', $parameters)->getContent();
// Create cache file
if (!is_dir($publicResourcesFolderPath)) {
try {
mkdir($publicResourcesFolderPath, 0777, true);
} catch (\ErrorException $ex) {
echo "Error: " . $ex->getMessage();
}
}
$cacheFile = fopen($file, 'w');
fputs($cacheFile, $this->sanitize_output($html));
fclose($cacheFile);
}
return new BinaryFileResponse($file);
}
/**
* @param $buffer
* @return null|string|string[]
*/
private function sanitize_output($buffer)
{
$search = array(
'/\>[^\S ]+/s', // strip whitespaces after tags, except space
'/[^\S ]+\</s', // strip whitespaces before tags, except space
'/(\s)+/s', // shorten multiple whitespace sequences
'/<!--(.|\s)*?-->/' // Remove HTML comments
);
$replace = array(
'>',
'<',
'\\1',
''
);
$buffer = preg_replace($search, $replace, $buffer);
return $buffer;
}
/**
* Get Localities
*/
public function localities(
HomePageService $newsPageService,
SiteMapService $siteMapService,
NetworkService $networkService
): Response {
$parameters = $newsPageService->getRenderParameters();
$parameters['isXmlHttpMode'] = true;
$localities = $networkService->getLocalities();
asort($localities);
$localitiesName = [];
$letters = array();
foreach ($localities as $item) {
$firstLetter = substr($item['name'], 0, 1);
$firstLetter = $siteMapService->cleanStr($firstLetter);
$letters[strtoupper($firstLetter)][] = ['id' => $item['id'], 'name' => $item['name']];
}
foreach ($localities as $locality) {
$locality['name'] = empty(!$locality['name']) ? $locality['name'] : '-';
$localitiesName[$locality['id']]['name'] = $siteMapService->cleanStr($locality['name']);
}
$parameters['letters'] = $letters;
$parameters['localities'] = $localities;
$parameters['localitiesName'] = $localitiesName;
return $this->render('pages/sitemap/localities.html.twig', $parameters);
}
}