Initial Commit

This commit is contained in:
2019-11-21 12:25:31 +01:00
commit f4aabcb9b1
13959 changed files with 787761 additions and 0 deletions

View File

@@ -0,0 +1,82 @@
<?php
namespace Sitemap\Controller;
use Propel\Runtime\ActiveQuery\Criteria;
use Propel\Runtime\ActiveQuery\Join;
use Thelia\Model\Map\CategoryTableMap;
use Thelia\Model\Map\RewritingUrlTableMap;
use Thelia\Model\RewritingUrl;
use Thelia\Model\RewritingUrlQuery;
use Thelia\Tools\URL;
/**
* Trait CategorySitemapTrait
* @package Sitemap\Controller
* @author Etienne Perriere <eperriere@openstudio.fr>
*/
trait CategorySitemapTrait
{
/**
* Get categories
*
* @param $sitemap
* @param $locale
* @throws \Propel\Runtime\Exception\PropelException
*/
protected function setSitemapCategories(&$sitemap, $locale)
{
// Prepare query - get categories URL
$query = RewritingUrlQuery::create()
->filterByView('category')
->filterByRedirected(null)
->filterByViewLocale($locale);
// Join with visible categories
self::addJoinCategory($query, $locale);
// Get categories last update
$query->withColumn(CategoryTableMap::UPDATED_AT, 'CATEGORY_UPDATE_AT');
// Execute query
$results = $query->find();
// For each result, hydrate XML file
/** @var RewritingUrl $result */
foreach ($results as $result) {
// Open new sitemap line & set category URL & update date
$sitemap[] = '
<url>
<loc>'.URL::getInstance()->absoluteUrl($result->getUrl()).'</loc>
<lastmod>'.date('c', strtotime($result->getVirtualColumn('CATEGORY_UPDATE_AT'))).'</lastmod>
</url>';
}
}
/**
* Join categories and their URLs
*
* @param Criteria $query
*/
protected function addJoinCategory(Criteria &$query)
{
// Join RewritingURL with Category to have only visible categories
$join = new Join();
$join->addExplicitCondition(
RewritingUrlTableMap::TABLE_NAME,
'VIEW_ID',
null,
CategoryTableMap::TABLE_NAME,
'ID',
null
);
$join->setJoinType(Criteria::INNER_JOIN);
$query->addJoinObject($join, 'categoryJoin');
// Get only visible categories
$query->addJoinCondition('categoryJoin', CategoryTableMap::VISIBLE, 1, Criteria::EQUAL, \PDO::PARAM_INT);
}
}

View File

@@ -0,0 +1,83 @@
<?php
namespace Sitemap\Controller;
use Propel\Runtime\ActiveQuery\Criteria;
use Propel\Runtime\ActiveQuery\Join;
use Thelia\Model\Map\ContentTableMap;
use Thelia\Model\Map\RewritingUrlTableMap;
use Thelia\Model\RewritingUrl;
use Thelia\Model\RewritingUrlQuery;
use Thelia\Tools\URL;
/**
* Class ContentSitemapTrait
* @package Sitemap\Controller
* @author Etienne Perriere <eperriere@openstudio.fr>
*/
trait ContentSitemapTrait
{
/**
* Get contents
*
* @param $sitemap
* @param $locale
* @throws \Propel\Runtime\Exception\PropelException
*/
protected function setSitemapContents(&$sitemap, $locale)
{
// Prepare query - get contents URL
$query = RewritingUrlQuery::create()
->filterByView('content')
->filterByRedirected(null)
->filterByViewLocale($locale);
// Join with visible contents
self::addJoinContent($query);
// Get contents last update
$query->withColumn(ContentTableMap::UPDATED_AT, 'CONTENT_UPDATE_AT');
// Execute query
$results = $query->find();
// For each result, hydrate XML file
/** @var RewritingUrl $result */
foreach ($results as $result) {
// Open new sitemap line & set content URL & update date
$sitemap[] = '
<url>
<loc>'.URL::getInstance()->absoluteUrl($result->getUrl()).'</loc>
<lastmod>'.date('c', strtotime($result->getVirtualColumn('CONTENT_UPDATE_AT'))).'</lastmod>
</url>';
}
}
/**
* Join contents and their URLs
*
* @param Criteria $query
*/
protected function addJoinContent(Criteria &$query)
{
// Join RewritingURL with Content to have only visible contents
$join = new Join();
$join->addExplicitCondition(
RewritingUrlTableMap::TABLE_NAME,
'VIEW_ID',
null,
ContentTableMap::TABLE_NAME,
'ID',
null
);
$join->setJoinType(Criteria::INNER_JOIN);
$query->addJoinObject($join, 'contentJoin');
// Get only visible products
$query->addJoinCondition('contentJoin', ContentTableMap::VISIBLE, 1, Criteria::EQUAL, \PDO::PARAM_INT);
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace Sitemap\Controller;
use Propel\Runtime\ActiveQuery\Criteria;
use Propel\Runtime\ActiveQuery\Join;
use Thelia\Model\Map\FolderTableMap;
use Thelia\Model\Map\RewritingUrlTableMap;
use Thelia\Model\RewritingUrl;
use Thelia\Model\RewritingUrlQuery;
use Thelia\Tools\URL;
/**
* Class FolderSitemapTrait
* @package Sitemap\Controller
* @author Etienne Perriere <eperriere@openstudio.fr>
*/
trait FolderSitemapTrait
{
/**
* Get folders
*
* @param $sitemap
* @param $locale
* @throws \Propel\Runtime\Exception\PropelException
*/
protected function setSitemapFolders(&$sitemap, $locale)
{
// Prepare query - get folders URL
$query = RewritingUrlQuery::create()
->filterByView('folder')
->filterByRedirected(null)
->filterByViewLocale($locale);
// Join with visible folders
self::addJoinFolder($query);
// Get folders last update
$query->withColumn(FolderTableMap::UPDATED_AT, 'FOLDER_UPDATE_AT');
// Execute query
$results = $query->find();
// For each result, hydrate XML file
/** @var RewritingUrl $result */
foreach ($results as $result) {
// Open new sitemap line & set folder URL & update date
$sitemap[] = '
<url>
<loc>'.URL::getInstance()->absoluteUrl($result->getUrl()).'</loc>
<lastmod>'.date('c', strtotime($result->getVirtualColumn('FOLDER_UPDATE_AT'))).'</lastmod>
</url>';
}
}
/**
* Join folders and their URLs
*
* @param Criteria $query
*/
protected function addJoinFolder(Criteria &$query)
{
// Join RewritingURL with Folder to have only visible folders
$join = new Join();
$join->addExplicitCondition(
RewritingUrlTableMap::TABLE_NAME,
'VIEW_ID',
null,
FolderTableMap::TABLE_NAME,
'ID',
null
);
$join->setJoinType(Criteria::INNER_JOIN);
$query->addJoinObject($join, 'folderJoin');
// Get only visible folders
$query->addJoinCondition('folderJoin', FolderTableMap::VISIBLE, 1, Criteria::EQUAL, \PDO::PARAM_INT);
}
}

View File

@@ -0,0 +1,129 @@
<?php
namespace Sitemap\Controller;
use Propel\Runtime\ActiveQuery\Criteria;
use Propel\Runtime\ActiveQuery\Join;
use Sitemap\Sitemap;
use Thelia\Model\Map\ProductI18nTableMap;
use Thelia\Model\Map\ProductImageTableMap;
use Thelia\Model\Map\ProductTableMap;
use Thelia\Model\Map\RewritingUrlTableMap;
use Thelia\Model\RewritingUrl;
use Thelia\Model\RewritingUrlQuery;
/**
* Class ProductImageTrait
* @package Sitemap\Controller
* @author Etienne Perriere <eperriere@openstudio.fr>
*/
trait ProductImageTrait
{
protected function setSitemapProductImages(&$sitemap, $locale)
{
// Change timeout for this script
ini_set('max_execution_time', Sitemap::getConfigValue('timeout', 30));
// Prepare query - get products URL
$query = RewritingUrlQuery::create()
->filterByView('product')
->filterByRedirected(null)
->filterByViewLocale($locale);
// Join with visible products
self::addJoinProductI18n($query);
// Get products title & image file name
$query->withColumn(ProductI18nTableMap::TITLE, 'PRODUCT_TITLE');
$query->addDescendingOrderByColumn(ProductImageTableMap::POSITION);
$query->addGroupByColumn(RewritingUrlTableMap::VIEW_ID);
$query->withColumn(ProductImageTableMap::FILE, 'PRODUCT_FILE');
// Execute query
$results = $query->find();
// Get image generation configuration values
$configValues = [];
$configValues['width'] = Sitemap::getConfigValue('width');
$configValues['height'] = Sitemap::getConfigValue('height');
$configValues['quality'] = Sitemap::getConfigValue('quality', 75);
$configValues['rotation'] = Sitemap::getConfigValue('rotation', 0);
$configValues['resizeMode'] = Sitemap::getConfigValue('resize_mode', \Thelia\Action\Image::EXACT_RATIO_WITH_BORDERS);
$configValues['bgColor'] = Sitemap::getConfigValue('background_color');
$configValues['allowZoom'] = Sitemap::getConfigValue('allow_zoom', false);
// For each result, hydrate XML file
/** @var RewritingUrl $result */
foreach ($results as $result) {
// Generate image data
$this->generateSitemapImage('product', $result, $configValues, $sitemap);
}
}
/**
* Join products and their URLs
*
* @param Criteria $query
*/
protected function addJoinProductI18n(Criteria &$query)
{
// Join RewritingURL with Product to have only visible products
$join = new Join();
$join->addExplicitCondition(
RewritingUrlTableMap::TABLE_NAME,
'VIEW_ID',
null,
ProductTableMap::TABLE_NAME,
'ID',
null
);
$join->setJoinType(Criteria::INNER_JOIN);
$query->addJoinObject($join, 'productJoin');
$query->addJoinCondition('productJoin', ProductTableMap::VISIBLE, 1, Criteria::EQUAL, \PDO::PARAM_INT);
// Join RewritingURL with ProductI18n to have product title for it's image
$joinI18n = new Join();
$joinI18n->addExplicitCondition(
RewritingUrlTableMap::TABLE_NAME,
'VIEW_ID',
null,
ProductI18nTableMap::TABLE_NAME,
'ID',
null
);
$joinI18n->addExplicitCondition(
RewritingUrlTableMap::TABLE_NAME,
'VIEW_LOCALE',
null,
ProductI18nTableMap::TABLE_NAME,
'LOCALE',
null
);
$joinI18n->setJoinType(Criteria::INNER_JOIN);
$query->addJoinObject($joinI18n);
// Join RewritingURL with ProductImage to have image file
$joinImage = new Join();
$joinImage->addExplicitCondition(
RewritingUrlTableMap::TABLE_NAME,
'VIEW_ID',
null,
ProductImageTableMap::TABLE_NAME,
'PRODUCT_ID',
null
);
$joinImage->setJoinType(Criteria::INNER_JOIN);
$query->addJoinObject($joinImage, 'productImageJoin');
$query->addJoinCondition('productImageJoin', ProductImageTableMap::VISIBLE, 1, Criteria::EQUAL, \PDO::PARAM_INT);
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace Sitemap\Controller;
use Propel\Runtime\ActiveQuery\Criteria;
use Propel\Runtime\ActiveQuery\Join;
use Thelia\Model\Map\ProductTableMap;
use Thelia\Model\Map\RewritingUrlTableMap;
use Thelia\Model\RewritingUrl;
use Thelia\Model\RewritingUrlQuery;
use Thelia\Tools\URL;
/**
* Trait ProductSitemapTrait
* @package Sitemap\Controller
* @author Etienne Perriere <eperriere@openstudio.fr>
*/
trait ProductSitemapTrait
{
/**
* Get products
*
* @param $sitemap
* @param $locale
* @throws \Propel\Runtime\Exception\PropelException
*/
protected function setSitemapProducts(&$sitemap, $locale)
{
// Prepare query - get products URL
$query = RewritingUrlQuery::create()
->filterByView('product')
->filterByRedirected(null)
->filterByViewLocale($locale);
// Join with visible products
self::addJoinProduct($query);
// Get products last update
$query->withColumn(ProductTableMap::UPDATED_AT, 'PRODUCT_UPDATE_AT');
// Execute query
$results = $query->find();
// For each result, hydrate XML file
/** @var RewritingUrl $result */
foreach ($results as $result) {
// Open new sitemap line & set product URL & update date
$sitemap[] = '
<url>
<loc>'.URL::getInstance()->absoluteUrl($result->getUrl()).'</loc>
<lastmod>'.date('c', strtotime($result->getVirtualColumn('PRODUCT_UPDATE_AT'))).'</lastmod>
</url>';
}
}
/**
* Join products and their URLs
*
* @param Criteria $query
*/
protected function addJoinProduct(Criteria &$query)
{
// Join RewritingURL with Product to have only visible products
$join = new Join();
$join->addExplicitCondition(
RewritingUrlTableMap::TABLE_NAME,
'VIEW_ID',
null,
ProductTableMap::TABLE_NAME,
'ID',
null
);
$join->setJoinType(Criteria::INNER_JOIN);
$query->addJoinObject($join, 'productJoin');
// Get only visible products
$query->addJoinCondition('productJoin', ProductTableMap::VISIBLE, 1, Criteria::EQUAL, \PDO::PARAM_INT);
}
}

View File

@@ -0,0 +1,137 @@
<?php
namespace Sitemap\Controller;
use Sitemap\Sitemap;
use Thelia\Controller\Admin\BaseAdminController;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Exception\FormValidationException;
/**
* Class SitemapConfigController
* @package Sitemap\Controller
* @author Etienne Perriere <eperriere@openstudio.fr>
*/
class SitemapConfigController extends BaseAdminController
{
public function defaultAction()
{
if (null !== $response = $this->checkAuth([AdminResources::MODULE], ["sitemap"], AccessManager::VIEW)) {
return $response;
}
// Get resize mode name
switch (Sitemap::getConfigValue('resize_mode')) {
case 1:
$resizeMode = 'borders';
break;
case 2:
$resizeMode = 'crop';
break;
case 3:
$resizeMode = 'none';
break;
default:
$resizeMode = '';
break;
}
// Build form
$form = $this->createForm(
"sitemap_config_form",
'form',
[
'timeout' => Sitemap::getConfigValue('timeout'),
'width' => Sitemap::getConfigValue('width'),
'height' => Sitemap::getConfigValue('height'),
'quality' => Sitemap::getConfigValue('quality'),
'rotation' => Sitemap::getConfigValue('rotation'),
'resize_mode' => $resizeMode,
'background_color' => Sitemap::getConfigValue('background_color'),
'allow_zoom' => Sitemap::getConfigValue('allow_zoom')
]
);
$this->getParserContext()->addForm($form);
return $this->render("sitemap-configuration");
}
/**
* Save data
*
* @return mixed|\Thelia\Core\HttpFoundation\Response
*/
public function saveAction()
{
if (null !== $response = $this->checkAuth([AdminResources::MODULE], ["sitemap"], AccessManager::UPDATE)) {
return $response;
}
$baseForm = $this->createForm("sitemap_config_form");
$errorMessage = null;
// Get current edition language locale
$locale = $this->getCurrentEditionLocale();
try {
$form = $this->validateForm($baseForm);
$data = $form->getData();
// Get resize mode
switch ($data["resize_mode"]) {
case 'none':
$resizeMode = \Thelia\Action\Image::KEEP_IMAGE_RATIO;
break;
case 'crop':
$resizeMode = \Thelia\Action\Image::EXACT_RATIO_WITH_CROP;
break;
case 'borders':
default:
$resizeMode = \Thelia\Action\Image::EXACT_RATIO_WITH_BORDERS;
break;
}
// Save data
Sitemap::setConfigValue('timeout', $data['timeout']);
Sitemap::setConfigValue('width', $data['width']);
Sitemap::setConfigValue('height', $data['height']);
Sitemap::setConfigValue('quality', $data['quality']);
Sitemap::setConfigValue('rotation', $data['rotation']);
Sitemap::setConfigValue('resize_mode', $resizeMode);
Sitemap::setConfigValue('background_color', $data['background_color']);
Sitemap::setConfigValue('allow_zoom', $data['allow_zoom']);
} catch (FormValidationException $ex) {
// Invalid data entered
$errorMessage = $this->createStandardFormValidationErrorMessage($ex);
} catch (\Exception $ex) {
// Any other error
$errorMessage = $this->getTranslator()->trans('Sorry, an error occurred: %err', ['%err' => $ex->getMessage()], Sitemap::DOMAIN_NAME, $locale);
}
if (null !== $errorMessage) {
// Mark the form as with error
$baseForm->setErrorMessage($errorMessage);
// Send the form and the error to the parser
$this->getParserContext()
->addForm($baseForm)
->setGeneralError($errorMessage)
;
} else {
$this->getParserContext()
->set("success", true)
;
}
return $this->defaultAction();
}
}

View File

@@ -0,0 +1,270 @@
<?php
namespace Sitemap\Controller;
use Doctrine\Common\Cache\FilesystemCache;
use Thelia\Controller\Front\BaseFrontController;
use Thelia\Core\Event\Image\ImageEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Model\ConfigQuery;
use Thelia\Model\LangQuery;
use Thelia\Model\RewritingUrl;
use Thelia\Tools\URL;
/**
* Class SitemapController
* @package Sitemap\Controller
* @author Etienne Perriere <eperriere@openstudio.fr>
*/
class SitemapController extends BaseFrontController
{
use CategorySitemapTrait;
use ProductSitemapTrait;
use FolderSitemapTrait;
use ContentSitemapTrait;
use ProductImageTrait;
/** Folder name for sitemap cache */
const SITEMAP_CACHE_DIR = "sitemap";
/** Key prefix for sitemap cache */
const SITEMAP_CACHE_KEY = "sitemap";
/** Folder name for sitemap image cache */
const SITEMAP_IMAGE_CACHE_DIR = "sitemap-image";
/** Key prefix for sitemap image cache */
const SITEMAP_IMAGE_CACHE_KEY = "sitemap-image";
protected $useFallbackTemplate = true;
/**
* Generate sitemap
*/
public function generateAction()
{
return $this->generateSitemap(self::SITEMAP_CACHE_KEY, self::SITEMAP_CACHE_DIR);
}
/**
* Generate sitemap image
*/
public function generateImageAction()
{
return $this->generateSitemap(self::SITEMAP_IMAGE_CACHE_KEY, self::SITEMAP_IMAGE_CACHE_DIR);
}
/**
* Check if cached sitemap can be used or generate a new one and cache it
*
* @param $cacheKey
* @param $cacheDirName
* @return Response
*/
public function generateSitemap($cacheKey, $cacheDirName)
{
// Get and check locale
$locale = $this->getSession()->getLang()->getLocale();
if ("" !== $locale) {
if (! $this->checkLang($locale)){
$this->pageNotFound();
}
}
// Get sitemap cache information
$sitemapContent = false;
$cacheDir = $this->getCacheDir($cacheDirName);
$cacheKey .= $locale;
$cacheExpire = intval(ConfigQuery::read("sitemap_ttl", '7200')) ?: 7200;
$cacheDriver = new FilesystemCache($cacheDir);
// Check if sitemap has to be deleted
if (!($this->checkAdmin() && "" !== $this->getRequest()->query->get("flush", ""))){
// Get cached sitemap
$sitemapContent = $cacheDriver->fetch($cacheKey);
} else {
$cacheDriver->delete($cacheKey);
}
// If not in cache, generate and cache it
if (false === $sitemapContent){
// Check if we generate the standard sitemap or the sitemap image
switch ($cacheDirName) {
// Image
case self::SITEMAP_IMAGE_CACHE_DIR:
$sitemap = $this->hydrateSitemapImage($locale);
break;
// Standard
case self::SITEMAP_CACHE_DIR:
default:
$sitemap = $this->hydrateSitemap($locale);
break;
}
$sitemapContent = implode("\n", $sitemap);
// Save cache
$cacheDriver->save($cacheKey, $sitemapContent, $cacheExpire);
}
// Render
$response = new Response();
$response->setContent($sitemapContent);
$response->headers->set('Content-Type', 'application/xml');
return $response;
}
/* ------------------ */
/**
* Build sitemap array
*
* @param $locale
* @return array
*/
protected function hydrateSitemap($locale)
{
// Begin sitemap
$sitemap = ['<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated on : '. date('Y-m-d H:i:s') .' -->
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>'.URL::getInstance()->getIndexPage().'</loc>
</url>'
];
// Hydrate sitemap
$this->setSitemapCategories($sitemap, $locale);
$this->setSitemapProducts($sitemap, $locale);
$this->setSitemapFolders($sitemap, $locale);
$this->setSitemapContents($sitemap, $locale);
// End sitemap
$sitemap[] = "\t".'</urlset>';
return $sitemap;
}
/**
* Build sitemap image array
*
* @param $locale
* @return array
*/
protected function hydrateSitemapImage($locale)
{
// Begin sitemap image
$sitemap = ['<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated on : '. date('Y-m-d H:i:s') .' -->
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
<url>
<loc>'.URL::getInstance()->getIndexPage().'</loc>
</url>'
];
// Hydrate sitemap image
$this->setSitemapProductImages($sitemap, $locale);
// End sitemap image
$sitemap[] = "\t".'</urlset>';
return $sitemap;
}
/* ------------------ */
/**
* @param $type
* @param RewritingUrl $result
* @param $configValues
* @param $sitemap
*/
protected function generateSitemapImage($type, $result, $configValues, &$sitemap)
{
$event = new ImageEvent();
$event
->setWidth($configValues['width'])
->setHeight($configValues['height'])
->setQuality($configValues['quality'])
->setRotation($configValues['rotation'])
->setResizeMode($configValues['resizeMode'])
->setBackgroundColor($configValues['bgColor'])
->setAllowZoom($configValues['allowZoom']);
// Put source image file path
$source_filepath = sprintf("%s%s/%s/%s",
THELIA_ROOT,
ConfigQuery::read('images_library_path', 'local/media/images'),
$type,
$result->getVirtualColumn('PRODUCT_FILE')
);
$event->setSourceFilepath($source_filepath);
$event->setCacheSubdirectory($type);
try {
// Dispatch image processing event
$this->dispatch(TheliaEvents::IMAGE_PROCESS, $event);
// New sitemap image entry
$sitemap[] = '
<url>
<loc>'.URL::getInstance()->absoluteUrl($result->getUrl()).'</loc>
<image:image>
<image:loc>'.$event->getFileUrl().'</image:loc>
<image:title>'.htmlspecialchars($result->getVirtualColumn('PRODUCT_TITLE')).'</image:title>
</image:image>
</url>';
} catch (\Exception $ex) {
}
}
/* ------------------ */
/**
* @param $locale
* @return bool true if the language is used, otherwise false
*/
protected function checkLang($locale)
{
// Load locales
$locale = LangQuery::create()
->findOneByLocale($locale);
return (null !== $locale);
}
/**
* Get the cache directory for sitemap
*
* @param $cacheDirName
* @return mixed|string
*/
protected function getCacheDir($cacheDirName)
{
$cacheDir = $this->container->getParameter("kernel.cache_dir");
$cacheDir = rtrim($cacheDir, '/');
$cacheDir .= '/' . $cacheDirName . '/';
return $cacheDir;
}
/**
* Check if current user has ADMIN role
*
* @return bool
*/
protected function checkAdmin(){
return $this->getSecurityContext()->hasAdminUser();
}
}