✨ feat(shop): Ajoute une note sur les ventes soutenant l'association et compresse le HTML.
This commit is contained in:
25
src/EventSubscriber/RequestSubscriber.php
Normal file
25
src/EventSubscriber/RequestSubscriber.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\EventSubscriber;
|
||||
use App\Service\Compressor\HtmlCompressor;
|
||||
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
|
||||
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
|
||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||
|
||||
#[AsEventListener(event: ResponseEvent::class, method: 'onResponse', priority: 10)]
|
||||
class RequestSubscriber
|
||||
{
|
||||
public function __construct(private HtmlCompressor $htmlCompressor)
|
||||
{
|
||||
}
|
||||
|
||||
public function onResponse(ResponseEvent $event): void
|
||||
{
|
||||
if($_ENV['APP_ENV'] == "prod") {
|
||||
$response = $event->getResponse();
|
||||
$response->setContent($this->htmlCompressor->compress($response->getContent()));
|
||||
$event->setResponse($response);
|
||||
$event->stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
42
src/Service/Compressor/HtmlCompressor.php
Normal file
42
src/Service/Compressor/HtmlCompressor.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\Compressor;
|
||||
|
||||
/**
|
||||
* Classe HtmlCompressor
|
||||
* Permet de minifier le contenu HTML en supprimant les commentaires et les espaces
|
||||
* inutiles entre les balises.
|
||||
*/
|
||||
class HtmlCompressor
|
||||
{
|
||||
/**
|
||||
* Minifie une chaîne de caractères contenant du HTML.
|
||||
* * Cette méthode effectue les étapes suivantes :
|
||||
* 1. Suppression des commentaires HTML (sauf les commentaires conditionnels IE).
|
||||
* 2. Suppression des sauts de ligne, retours chariot et tabulations.
|
||||
* 3. Suppression des espaces multiples.
|
||||
* 4. Suppression des espaces autour des balises (entre > et <).
|
||||
*
|
||||
* @param string $html Le contenu HTML à minifier.
|
||||
* @return string Le contenu HTML minifié.
|
||||
*/
|
||||
public function compress(string $html): string
|
||||
{
|
||||
// 1. Supprime les commentaires HTML, tout en préservant les commentaires conditionnels (<!--[if ...)
|
||||
$html = preg_replace('/<!--(?!\[if|<!\[endif).*?-->/s', '', $html);
|
||||
|
||||
// 2. Supprime tous les sauts de ligne, retours chariot et tabulations
|
||||
$html = str_replace(array("\r\n", "\r", "\n", "\t"), '', $html);
|
||||
|
||||
// 3. Remplace les multiples espaces par un seul espace
|
||||
$html = preg_replace('/\s+/', ' ', $html);
|
||||
|
||||
// 4. Supprime les espaces qui se trouvent juste après '>' ou juste avant '<'
|
||||
// Cela compresse l'espace entre les balises.
|
||||
$html = preg_replace('/>\s</', '><', $html);
|
||||
|
||||
return trim($html);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -37,7 +37,7 @@
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ asset('favicon/apple-touch-icon.png') }}"/>
|
||||
<meta name="apple-mobile-web-app-title" content="E-Cosplay"/>
|
||||
<link rel="manifest" href="{{ asset('site.webmanifest') }}"/>
|
||||
<link rel="stylesheet" href="{{ asset('assets/css/all.min.css') }}" crossorigin="anonymous"
|
||||
<link rel="stylesheet" href="{{ asset('assets/icons/css/fontawesome.min.css') }}" crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"/>
|
||||
<meta name="google-site-verification" content="D6YvgLKg4oj2Ksk_cYhO3fijbmxZWib7wqqHTJyfftQ"/>
|
||||
<meta name="env" content="{{ app.environment }}">
|
||||
@@ -134,7 +134,7 @@
|
||||
{# LOGO / NOM DU SITE #}
|
||||
<div class="flex-shrink-0 flex items-center">
|
||||
<a href="{{ path('app_home') }}" class="flex items-center space-x-2 text-xl font-bold text-gray-900">
|
||||
<img class="h-8 w-auto" src="{{ asset('assets/images/logo.jpg') | imagine_filter('webp') }}"
|
||||
<img class="h-8 w-auto" width="57px" height="32px" src="{{ asset('assets/images/logo.jpg') | imagine_filter('webp') }}"
|
||||
alt="E-Cosplay Logo">
|
||||
{# Le texte du nom du site peut rester en noir pour la lisibilité #}
|
||||
<span class="text-gray-900">E-Cosplay</span>
|
||||
|
||||
@@ -125,10 +125,10 @@
|
||||
{# BOUCLE SUR LES PARTENAIRES #}
|
||||
{# NOTE: La variable `partners` doit être passée par le contrôleur (e.g., [ { image: '/asset/partenair/house-of-geek.jpg', name: 'House Of Geek', facebook_link: 'lien' }, ... ] ) #}
|
||||
{% for partner in partners|default([
|
||||
{ 'image': '/assets/partenair/house-of-geek.jpg', 'name': 'House Of Geek', 'facebook_link': 'https://www.facebook.com/houseofgeek02' },
|
||||
{ 'image': '/assets/partenair/cosplay-familly.jpg', 'name': 'Cosplays family arts', 'facebook_link': 'https://www.facebook.com/profile.php?id=61568494078902' },
|
||||
{ 'image': '/assets/partenair/couronnes-d-or.jpg', 'name': 'Le Comité des Couronnes D’or', 'facebook_link': 'https://www.facebook.com/p/Le-Comit%C3%A9-des-Couronnes-Dor-61576548182126/' },
|
||||
{ 'image': '/assets/partenair/siteconseil.png', 'name': 'SARL SITECONSEIL', 'facebook_link': 'https://www.facebook.com/siteconseil','website':'https://www.siteconseil.fr' }
|
||||
{ 'w':64,'h':64, 'image': '/assets/partenair/house-of-geek.jpg', 'name': 'House Of Geek', 'facebook_link': 'https://www.facebook.com/houseofgeek02' },
|
||||
{ 'w':64,'h':64, 'image': '/assets/partenair/cosplay-familly.jpg', 'name': 'Cosplays family arts', 'facebook_link': 'https://www.facebook.com/profile.php?id=61568494078902' },
|
||||
{ 'w':64,'h':64, 'image': '/assets/partenair/couronnes-d-or.jpg', 'name': 'Le Comité des Couronnes D’or', 'facebook_link': 'https://www.facebook.com/p/Le-Comit%C3%A9-des-Couronnes-Dor-61576548182126/' },
|
||||
{ 'w':64,'h':64, 'image': '/assets/partenair/siteconseil.png', 'name': 'SARL SITECONSEIL', 'facebook_link': 'https://www.facebook.com/siteconseil','website':'https://www.siteconseil.fr' }
|
||||
]) %}
|
||||
{# Conteneur du partenaire #}
|
||||
<a href=" {% if partner.website is defined and partner.website %}{{ partner.website }}{% else %}{{ partner.facebook_link ?? '#' }}{% endif %}" target="_blank" class="col-span-1 flex flex-col items-center justify-center py-6 px-4 bg-white rounded-xl shadow-md border border-gray-100 hover:shadow-lg hover:border-indigo-200 transition duration-300 group">
|
||||
@@ -137,6 +137,8 @@
|
||||
<img class="max-h-16 w-auto object-contain mb-3"
|
||||
src="{{ partner.image | imagine_filter('webp') }}"
|
||||
alt="{{ partner.name }}"
|
||||
width="{{ partner.w }}"
|
||||
height="{{ partner.h }}"
|
||||
onerror="this.style.display='none'; this.nextElementSibling.style.display='block';"
|
||||
>
|
||||
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
{{ product.price | number_format(2, ',', ' ') }} € TTC
|
||||
</span>
|
||||
<a href="{{ path('app_product_show', {'slug': (product.name|lower|replace({' ': '-'}))~"-"~product.id}) }}" class="text-indigo-600 hover:text-indigo-800 text-sm font-semibold inline-flex items-center group">
|
||||
En savoir plus
|
||||
{{ 'shop_more'|trans }}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right ml-1 group-hover:translate-x-0.5 transition-transform"><path d="m9 18l6-6-6-6"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
@@ -177,7 +177,18 @@
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mt-12 mb-8 p-6 bg-indigo-50 border-l-4 border-indigo-500 rounded-lg shadow-inner">
|
||||
<h3 class="text-xl font-bold text-indigo-800 mb-3 flex items-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-heart-handshake mr-2"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5"/><path d="M12 20v-6h3a1 1 0 0 1 1 1v4h1a2 2 0 0 1 2 2v0a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v0a2 2 0 0 1 2-2h1.5l1.5-4h2.8l-3.5 6H22"/></svg>
|
||||
{{ 'shop.sales_note_title'|trans }}
|
||||
</h3>
|
||||
<p class="text-gray-700 leading-relaxed">
|
||||
{{ 'shop.sales_note_main'|trans|raw }}
|
||||
</p>
|
||||
<p class="mt-3 text-sm italic text-gray-600">
|
||||
{{ 'shop.sales_note_details'|trans }}
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -610,3 +610,9 @@ product_short_desc_title: "快速概览"
|
||||
product_long_desc_title: "详细描述"
|
||||
product_estimated_delivery: "预计交货时间:2-5个工作日。"
|
||||
product_shipping_methods: "通过 Mondial Relay / Colissimo 交付,起价 6€ TTC"
|
||||
shop.sales_note_title: "我们的销售收入将用于支持协会"
|
||||
shop.sales_note_main: >
|
||||
本店大部分商品的全部销售收入(100%利润)将用于支持本协会。这些资金将用于网站开发、活动组织以及举办比赛。
|
||||
shop.sales_note_details: >
|
||||
请注意,针对特定的 Cosplay 写真印品销售,收益分配如下:5% 用于支付协会的银行手续费,95% 直接返还给制作该印品的会员。
|
||||
shop_more: '了解更多'
|
||||
|
||||
@@ -678,3 +678,9 @@ product_short_desc_title: "Quick Overview"
|
||||
product_long_desc_title: "Detailed Description"
|
||||
product_estimated_delivery: "Estimated delivery: 2-5 working days."
|
||||
product_shipping_methods: "Shipping via Mondial Relay / Colissimo starting from €6 incl. tax"
|
||||
shop.sales_note_title: "Our Sales for the Association"
|
||||
shop.sales_note_main: >
|
||||
The entirety of sales (100% of the profit) from the majority of the shop's items is intended to support the association. These funds are used for website development, event organization, and setting up contests.
|
||||
shop.sales_note_details: >
|
||||
Please note that for specific cosplay print sales, the distribution is as follows: 5% of the amount covers the association's banking fees, and 95% is directly remitted to the member who created the print.
|
||||
shop_more: 'Learn more'
|
||||
|
||||
@@ -612,3 +612,9 @@ product_short_desc_title: "Aperçu rapide"
|
||||
product_long_desc_title: "Description détaillée"
|
||||
product_estimated_delivery: "Livraison estimée : 2-5 jours ouvrés."
|
||||
product_shipping_methods: "Livraison par Mondial Relay / Colissimo à partir de 6€ TTC"
|
||||
shop.sales_note_title: "Nos Ventes pour l'Association"
|
||||
shop.sales_note_main: >
|
||||
La totalité des ventes (100% du bénéfice) de la majorité des articles de la boutique est destinée à soutenir l'association. Ces fonds servent au développement du site internet, à l'organisation d'événements, ainsi qu'à la mise en place de jeux concours.
|
||||
shop.sales_note_details: >
|
||||
Notez que pour les ventes de prints cosplay spécifiques, la répartition est la suivante : 5% du montant couvre les frais bancaires de l'association, et 95% est reversé directement à l'adhérent créateur du print.
|
||||
shop_more: 'En savoir plus'
|
||||
|
||||
Reference in New Issue
Block a user