Initial commit: custom PrestaShop 9 EduBox image
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
|||||||
|
FROM prestashop/prestashop:9
|
||||||
|
|
||||||
|
# Apply EduBox patches so PrestaShop 9 works behind the dynamic-domain reverse proxy.
|
||||||
|
COPY edubox-tools.patch \
|
||||||
|
edubox-link.patch \
|
||||||
|
edubox-frontcontroller.patch \
|
||||||
|
edubox-shop.patch \
|
||||||
|
edubox-shopurl.patch \
|
||||||
|
edubox-shopcontext.patch \
|
||||||
|
edubox-asseturl.patch \
|
||||||
|
edubox-install.patch \
|
||||||
|
edubox-install-language.patch \
|
||||||
|
edubox-language.patch \
|
||||||
|
edubox-docker-run.patch \
|
||||||
|
/tmp/
|
||||||
|
RUN patch -p1 -d /var/www/html < /tmp/edubox-tools.patch && \
|
||||||
|
patch -p1 -d /var/www/html < /tmp/edubox-link.patch && \
|
||||||
|
patch -p1 -d /var/www/html < /tmp/edubox-frontcontroller.patch && \
|
||||||
|
patch -p1 -d /var/www/html < /tmp/edubox-shop.patch && \
|
||||||
|
patch -p1 -d /var/www/html < /tmp/edubox-shopurl.patch && \
|
||||||
|
patch -p1 -d /var/www/html < /tmp/edubox-shopcontext.patch && \
|
||||||
|
patch -p1 -d /var/www/html < /tmp/edubox-asseturl.patch && \
|
||||||
|
patch -p1 -d /var/www/html < /tmp/edubox-install.patch && \
|
||||||
|
patch -p1 -d /var/www/html < /tmp/edubox-install-language.patch && \
|
||||||
|
patch -p1 -d /var/www/html < /tmp/edubox-language.patch && \
|
||||||
|
patch -p1 -d / < /tmp/edubox-docker-run.patch && \
|
||||||
|
rm /tmp/edubox-*.patch
|
||||||
|
|
||||||
|
# Apache proxy configuration
|
||||||
|
COPY proxy.conf /etc/apache2/conf-enabled/edubox-proxy.conf
|
||||||
|
|
||||||
|
# Pre-download French translation pack so the installer works offline.
|
||||||
|
# Agents may not have outbound internet access during installation.
|
||||||
|
# The official image copies /tmp/data-ps/prestashop/ into /var/www/html on first
|
||||||
|
# boot, so we place the pack there as well.
|
||||||
|
COPY translations-symfony-fr-FR.zip /tmp/data-ps/prestashop/translations/sf-fr-FR.zip
|
||||||
|
RUN chown -R www-data:www-data /tmp/data-ps/prestashop/translations
|
||||||
|
|
||||||
|
# Early bootstrap normalisation for X-Forwarded-* headers
|
||||||
|
COPY defines_custom.inc.php /var/www/html/config/defines_custom.inc.php
|
||||||
|
|
||||||
|
RUN chown -R www-data:www-data /var/www/html
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
# EduBox PrestaShop 9 Image
|
||||||
|
|
||||||
|
Image Docker patchée basée sur `prestashop/prestashop:9`, conçue pour fonctionner
|
||||||
|
avec le reverse proxy dynamique d'EduBox.
|
||||||
|
|
||||||
|
## Pourquoi une image patchée ?
|
||||||
|
|
||||||
|
PrestaShop 9 (Apache 2.4 + PHP 8.5) a deux problèmes majeurs derrière EduBox :
|
||||||
|
|
||||||
|
1. Les headers `X-Forwarded-*` sont corrompus par Apache/PHP : `$_SERVER` les
|
||||||
|
reçoit sous forme d'arrays au lieu de strings. On contourne ce bug via
|
||||||
|
`getenv()` dans `config/defines_custom.inc.php`.
|
||||||
|
2. PrestaShop utilise partout le domaine stocké en base (`ps_shop_url`) et la
|
||||||
|
configuration `PS_SSL_ENABLED`. Derrière EduBox, le domaine public change à
|
||||||
|
chaque instance (`<id>.alfrednobel.edudeploy.com`) et toutes les requêtes
|
||||||
|
publiques arrivent en HTTPS. Les patches forcent l'utilisation de l'hôte et
|
||||||
|
du protocole de la requête courante.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/edubox/prestashop-image
|
||||||
|
docker build -t edubox-prestashop:9 .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Patches appliqués
|
||||||
|
|
||||||
|
| Patch | Fichier modifié | Objectif |
|
||||||
|
|-------|-----------------|----------|
|
||||||
|
| `edubox-tools.patch` | `classes/Tools.php` | `getShopDomain()` / `getShopDomainSsl()` utilisent `getHttpHost()` dynamiquement. |
|
||||||
|
| `edubox-link.patch` | `classes/Link.php` | `getBaseLink()` utilise `usingSecureMode()` et `getHttpHost()`. |
|
||||||
|
| `edubox-frontcontroller.patch` | `classes/controller/FrontController.php` | Désactive `sslRedirection()` pour éviter les boucles HTTP/HTTPS. |
|
||||||
|
| `edubox-shop.patch` | `classes/shop/Shop.php` | `Shop::initialize()` utilise le shop par défaut sans redirection forcée. |
|
||||||
|
| `edubox-shopcontext.patch` | `src/Core/Context/ShopContext.php` | `getBaseURL()` du BO est reconstruit à partir de la requête courante. |
|
||||||
|
| `edubox-asseturl.patch` | `src/Adapter/Assets/AssetUrlGeneratorTrait.php` | Les assets CCC utilisent le protocole de la requête, pas `PS_SSL_ENABLED`. |
|
||||||
|
| `edubox-install.patch` | `src/PrestaShopBundle/Install/Install.php` | `finalize()` respecte `PS_FOLDER_ADMIN` (évite le bug overlayfs `admin` → `admin-edubox`). |
|
||||||
|
|
||||||
|
## Fichiers injectés
|
||||||
|
|
||||||
|
- `proxy.conf` : Apache truste `X-Forwarded-Proto: https` pour positionner
|
||||||
|
`HTTPS=on` dans l'environnement PHP.
|
||||||
|
- `config/defines_custom.inc.php` : normalise `HTTP_X_FORWARDED_HOST`,
|
||||||
|
`HTTP_X_FORWARDED_PROTO` et `HTTP_HOST` corrompus ; définit
|
||||||
|
`PS_TRUSTED_PROXIES` pour Symfony.
|
||||||
|
|
||||||
|
## Utilisation dans EduBox
|
||||||
|
|
||||||
|
Le template PrestaShop 9 dans `server/prisma/seed.ts` utilise cette image :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
app:
|
||||||
|
image: edubox-prestashop:9
|
||||||
|
```
|
||||||
|
|
||||||
|
## Déploiement sur les agents
|
||||||
|
|
||||||
|
L'image doit être accessible depuis chaque agent étudiant. Deux options :
|
||||||
|
|
||||||
|
1. **Registry privé** (recommandé) : tagger et pousser l'image sur un registry
|
||||||
|
(Docker Hub, registry Gitea, GHCR, etc.) puis mettre à jour
|
||||||
|
`server/prisma/seed.ts` avec le nom complet (`monregistry/edubox-prestashop:9`).
|
||||||
|
2. **Build manuel sur chaque agent** : copier le dossier `prestashop-image` sur
|
||||||
|
l'agent et lancer `docker build` avant le premier déploiement.
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* EduBox reverse proxy normalisation for PrestaShop 9 running behind the
|
||||||
|
* EduBox dynamic-public-domain resolver.
|
||||||
|
*
|
||||||
|
* The official PrestaShop 9 + PHP 8.5 + Apache image has a bug where
|
||||||
|
* X-Forwarded-* headers are exposed to PHP as arrays whose value is the
|
||||||
|
* header name. getenv() returns the correct string, so we use it to
|
||||||
|
* reconstruct $_SERVER entries used by Tools::getHttpHost/ShopDomainSSL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ($val = getenv('HTTP_X_FORWARDED_HOST')) {
|
||||||
|
$_SERVER['HTTP_X_FORWARDED_HOST'] = $val;
|
||||||
|
}
|
||||||
|
if ($val = getenv('HTTP_X_FORWARDED_PROTO')) {
|
||||||
|
$_SERVER['HTTP_X_FORWARDED_PROTO'] = $val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apache/PHP 8.5 sometimes corrupts HTTP_HOST into an array; fall back safely.
|
||||||
|
if (!empty($_SERVER['HTTP_HOST']) && is_array($_SERVER['HTTP_HOST'])) {
|
||||||
|
$_SERVER['HTTP_HOST'] = !empty($_SERVER['SERVER_NAME']) && !is_array($_SERVER['SERVER_NAME'])
|
||||||
|
? $_SERVER['SERVER_NAME']
|
||||||
|
: (getenv('HTTP_X_FORWARDED_HOST') ?: 'localhost');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($_SERVER['HTTPS']) && is_array($_SERVER['HTTPS'])) {
|
||||||
|
$_SERVER['HTTPS'] = 'off';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tell Symfony to trust the EduBox resolver so $request->isSecure() and
|
||||||
|
// $request->getHost() honour X-Forwarded-* headers.
|
||||||
|
putenv('PS_TRUSTED_PROXIES=127.0.0.1,REMOTE_ADDR');
|
||||||
|
$_SERVER['PS_TRUSTED_PROXIES'] = '127.0.0.1,REMOTE_ADDR';
|
||||||
|
$_ENV['PS_TRUSTED_PROXIES'] = '127.0.0.1,REMOTE_ADDR';
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
--- a/src/Adapter/Assets/AssetUrlGeneratorTrait.php
|
||||||
|
+++ b/src/Adapter/Assets/AssetUrlGeneratorTrait.php
|
||||||
|
@@ -49,12 +49,14 @@ trait AssetUrlGeneratorTrait
|
||||||
|
protected function getFQDN()
|
||||||
|
{
|
||||||
|
if (null === $this->fqdn) {
|
||||||
|
- if ($this->configuration->get('PS_SSL_ENABLED') && ToolsLegacy::usingSecureMode()) {
|
||||||
|
- $this->fqdn = $this->configuration->get('_PS_BASE_URL_SSL_');
|
||||||
|
- } else {
|
||||||
|
+ // EduBox: rely on the current request security, not on PS_SSL_ENABLED.
|
||||||
|
+ // Behind the reverse proxy every public request is HTTPS.
|
||||||
|
+ if (ToolsLegacy::usingSecureMode()) {
|
||||||
|
+ $this->fqdn = $this->configuration->get('_PS_BASE_URL_SSL_') ?: $this->configuration->get('_PS_BASE_URL_');
|
||||||
|
+ } else {
|
||||||
|
$this->fqdn = $this->configuration->get('_PS_BASE_URL_');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->fqdn;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
--- a/tmp/docker_run.sh 2026-06-20 17:57:12.682339048 +0000
|
||||||
|
+++ b/tmp/docker_run.sh 2026-06-20 17:57:12.852338398 +0000
|
||||||
|
@@ -21,6 +21,13 @@
|
||||||
|
|
||||||
|
# From now, stop at error
|
||||||
|
set -e
|
||||||
|
+# EduBox: if a previous installation failed, install.lock remains but PrestaShop is not configured.
|
||||||
|
+# Remove the stale lock so the installer can run again on the next start.
|
||||||
|
+if [ -f ./install.lock ] && [ ! -f ./config/settings.inc.php ] && [ ! -f ./app/config/parameters.php ]; then
|
||||||
|
+ echo "\n* Stale install.lock detected, removing it to allow reinstallation ..."
|
||||||
|
+ rm -f ./install.lock
|
||||||
|
+fi
|
||||||
|
+
|
||||||
|
|
||||||
|
if [ ! -f ./config/settings.inc.php ] && [ ! -f ./app/config/parameters.php ] && [ ! -f ./install.lock ]; then
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
--- a/classes/controller/FrontController.php
|
||||||
|
+++ b/classes/controller/FrontController.php
|
||||||
|
@@ -849,18 +849,9 @@
|
||||||
|
*/
|
||||||
|
protected function sslRedirection()
|
||||||
|
{
|
||||||
|
- // If we call a SSL controller without SSL or a non SSL controller with SSL, we redirect with the right protocol
|
||||||
|
- if (Configuration::get('PS_SSL_ENABLED') && $_SERVER['REQUEST_METHOD'] != 'POST' && $this->ssl != Tools::usingSecureMode()) {
|
||||||
|
- $this->context->cookie->disallowWriting();
|
||||||
|
- header('HTTP/1.1 301 Moved Permanently');
|
||||||
|
- header('Cache-Control: no-cache');
|
||||||
|
- if ($this->ssl) {
|
||||||
|
- header('Location: ' . Tools::getShopDomainSsl(true) . $_SERVER['REQUEST_URI']);
|
||||||
|
- } else {
|
||||||
|
- header('Location: ' . Tools::getShopDomain(true) . $_SERVER['REQUEST_URI']);
|
||||||
|
- }
|
||||||
|
- exit;
|
||||||
|
- }
|
||||||
|
+ // EduBox: disabled. Behind the EduBox reverse proxy every request is
|
||||||
|
+ // served over HTTPS publicly, so PrestaShop must never redirect to HTTP.
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
--- a/src/PrestaShopBundle/Install/Install.php 2026-06-20 18:07:13.506985399 +0000
|
||||||
|
+++ b/src/PrestaShopBundle/Install/Install.php 2026-06-20 18:07:22.294363061 +0000
|
||||||
|
@@ -622,17 +622,20 @@
|
||||||
|
'locale' => (string) $xml->locale,
|
||||||
|
];
|
||||||
|
|
||||||
|
- if (file_exists(_PS_TRANSLATIONS_DIR_ . (string) $iso . '.gzip') == false) {
|
||||||
|
- $language = EntityLanguage::downloadLanguagePack($iso, _PS_INSTALL_VERSION_);
|
||||||
|
+ // EduBox: skip legacy language pack download if Symfony pack is bundled
|
||||||
|
+ $errors = [];
|
||||||
|
+ $locale = $params_lang['locale'];
|
||||||
|
+
|
||||||
|
+ if (!EntityLanguage::translationPackIsInCache($locale)) {
|
||||||
|
+ if (file_exists(_PS_TRANSLATIONS_DIR_ . (string) $iso . '.gzip') == false) {
|
||||||
|
+ $language = EntityLanguage::downloadLanguagePack($iso, _PS_INSTALL_VERSION_);
|
||||||
|
|
||||||
|
- if ($language == false) {
|
||||||
|
- throw new PrestashopInstallerException($this->translator->trans('Cannot download language pack "%iso%"', ['%iso%' => $iso], 'Install'));
|
||||||
|
+ if ($language == false) {
|
||||||
|
+ throw new PrestashopInstallerException($this->translator->trans('Cannot download language pack "%iso%"', ['%iso%' => $iso], 'Install'));
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- $errors = [];
|
||||||
|
- $locale = $params_lang['locale'];
|
||||||
|
-
|
||||||
|
/* @todo check if a newer pack is available */
|
||||||
|
if (!EntityLanguage::translationPackIsInCache($locale)) {
|
||||||
|
EntityLanguage::downloadXLFLanguagePack($locale, $errors);
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
--- a/src/PrestaShopBundle/Install/Install.php
|
||||||
|
+++ b/src/PrestaShopBundle/Install/Install.php
|
||||||
|
@@ -1202,7 +1202,7 @@ class Install extends AbstractInstall
|
||||||
|
{
|
||||||
|
- $adminFolder = 'admin-dev';
|
||||||
|
+ $adminFolder = getenv('PS_FOLDER_ADMIN') ?: 'admin-dev';
|
||||||
|
|
||||||
|
// If we need, we generate a random name for admin folder (for security purpose!)
|
||||||
|
if (file_exists(_PS_ROOT_DIR_ . '/admin/')) {
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
--- a/classes/Language.php
|
||||||
|
+++ b/classes/Language.php
|
||||||
|
@@ -1235,6 +1235,12 @@
|
||||||
|
*/
|
||||||
|
public static function downloadXLFLanguagePack($locale, &$errors = [], $type = self::PACK_TYPE_SYMFONY)
|
||||||
|
{
|
||||||
|
+ // EduBox: if the translation pack is already present in the image,
|
||||||
|
+ // do not try to download it (agents may be offline).
|
||||||
|
+ if (static::translationPackIsInCache($locale, $type)) {
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
$file = self::getPathToCachedTranslationPack($locale, $type);
|
||||||
|
$url = (self::PACK_TYPE_EMAILS === $type) ? self::EMAILS_LANGUAGE_PACK_URL : self::SF_LANGUAGE_PACK_URL;
|
||||||
|
$url = str_replace(
|
||||||
|
@@ -1697,7 +1703,9 @@
|
||||||
|
*/
|
||||||
|
public static function translationPackIsInCache(string $locale, string $type = self::PACK_TYPE_SYMFONY): bool
|
||||||
|
{
|
||||||
|
- return file_exists(self::getPathToCachedTranslationPack($locale, $type));
|
||||||
|
+ // EduBox: use runtime constant instead of class constant, because
|
||||||
|
+ // _PS_TRANSLATIONS_DIR_ may not be defined when this file is compiled.
|
||||||
|
+ return file_exists(_PS_TRANSLATIONS_DIR_ . $type . '-' . $locale . '.zip');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -1710,7 +1718,8 @@
|
||||||
|
*/
|
||||||
|
private static function getPathToCachedTranslationPack(string $locale, string $type = self::PACK_TYPE_SYMFONY): string
|
||||||
|
{
|
||||||
|
- return self::TRANSLATION_PACK_CACHE_DIR . $type . '-' . $locale . '.zip';
|
||||||
|
+ // EduBox: use runtime constant instead of class constant.
|
||||||
|
+ return _PS_TRANSLATIONS_DIR_ . $type . '-' . $locale . '.zip';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
--- a/classes/Link.php 2026-06-20 20:05:45.983104609 +0000
|
||||||
|
+++ b/classes/Link.php 2026-06-20 20:05:46.195748630 +0000
|
||||||
|
@@ -862,7 +862,7 @@
|
||||||
|
public function getAdminBaseLink($idShop = null, $ssl = null, $relativeProtocol = false)
|
||||||
|
{
|
||||||
|
if (null === $ssl) {
|
||||||
|
- $ssl = Configuration::get('PS_SSL_ENABLED');
|
||||||
|
+ $ssl = Tools::usingSecureMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE')) {
|
||||||
|
@@ -881,9 +881,10 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($relativeProtocol) {
|
||||||
|
- $base = '//' . ($ssl && $this->ssl_enable ? $shop->domain_ssl : $shop->domain);
|
||||||
|
+ $base = '//' . Tools::getHttpHost(false, false, true);
|
||||||
|
} else {
|
||||||
|
- $base = (($ssl && $this->ssl_enable) ? 'https://' . $shop->domain_ssl : 'http://' . $shop->domain);
|
||||||
|
+ $protocol = Tools::usingSecureMode() ? 'https://' : 'http://';
|
||||||
|
+ $base = $protocol . Tools::getHttpHost(false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $base . $shop->getBaseURI();
|
||||||
|
@@ -1391,7 +1392,7 @@
|
||||||
|
public function getBaseLink($idShop = null, $ssl = null, $relativeProtocol = false)
|
||||||
|
{
|
||||||
|
if (null === $ssl) {
|
||||||
|
- $ssl = Configuration::get('PS_SSL_ENABLED');
|
||||||
|
+ $ssl = Tools::usingSecureMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Configuration::get('PS_MULTISHOP_FEATURE_ACTIVE') && $idShop !== null) {
|
||||||
|
@@ -1401,9 +1402,10 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($relativeProtocol) {
|
||||||
|
- $base = '//' . ($ssl && $this->ssl_enable ? $shop->domain_ssl : $shop->domain);
|
||||||
|
+ $base = '//' . Tools::getHttpHost(false, false, true);
|
||||||
|
} else {
|
||||||
|
- $base = (($ssl && $this->ssl_enable) ? 'https://' . $shop->domain_ssl : 'http://' . $shop->domain);
|
||||||
|
+ $protocol = Tools::usingSecureMode() ? 'https://' : 'http://';
|
||||||
|
+ $base = $protocol . Tools::getHttpHost(false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $base . $shop->getBaseURI();
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
--- a/classes/shop/Shop.php
|
||||||
|
+++ b/classes/shop/Shop.php
|
||||||
|
@@ -411,38 +411,14 @@
|
||||||
|
} else {
|
||||||
|
$shop = new Shop($id_shop);
|
||||||
|
if (!Validate::isLoadedObject($shop) || !$shop->active) {
|
||||||
|
- // No shop found ... too bad, let's redirect to default shop
|
||||||
|
- $default_shop = new Shop((int) Configuration::get('PS_SHOP_DEFAULT'));
|
||||||
|
+ // EduBox: behind a reverse proxy with dynamic public domains,
|
||||||
|
+ // the requested host never matches ps_shop_url. Always use the
|
||||||
|
+ // default shop instead of redirecting to a fixed canonical URL.
|
||||||
|
+ $shop = new Shop((int) Configuration::get('PS_SHOP_DEFAULT'));
|
||||||
|
|
||||||
|
- // Hmm there is something really bad in your Prestashop !
|
||||||
|
- if (!Validate::isLoadedObject($default_shop)) {
|
||||||
|
+ if (!Validate::isLoadedObject($shop)) {
|
||||||
|
throw new PrestaShopException('Shop not found');
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- $params = $_GET;
|
||||||
|
- unset($params['id_shop']);
|
||||||
|
- $url = $default_shop->domain;
|
||||||
|
- if (!Configuration::get('PS_REWRITING_SETTINGS')) {
|
||||||
|
- $url .= $default_shop->getBaseURI() . 'index.php?' . http_build_query($params);
|
||||||
|
- } else {
|
||||||
|
- // Catch url with subdomain "www"
|
||||||
|
- if (strpos($url, 'www.') === 0 && 'www.' . $_SERVER['HTTP_HOST'] === $url || $_SERVER['HTTP_HOST'] === 'www.' . $url) {
|
||||||
|
- $url .= $_SERVER['REQUEST_URI'];
|
||||||
|
- } else {
|
||||||
|
- $url .= $default_shop->getBaseURI();
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (count($params)) {
|
||||||
|
- $url .= '?' . http_build_query($params);
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- $redirect_type = Configuration::get('PS_CANONICAL_REDIRECT');
|
||||||
|
- $redirect_code = ($redirect_type == 1 ? '302' : '301');
|
||||||
|
- $redirect_header = ($redirect_type == 1 ? 'Found' : 'Moved Permanently');
|
||||||
|
- header('HTTP/1.0 ' . $redirect_code . ' ' . $redirect_header);
|
||||||
|
- header('Location: ' . Tools::getShopProtocol() . $url);
|
||||||
|
- exit;
|
||||||
|
} elseif (defined('_PS_ADMIN_DIR_') && empty($shop->physical_uri)) {
|
||||||
|
$shop_default = new Shop((int) Configuration::get('PS_SHOP_DEFAULT'));
|
||||||
|
$shop->physical_uri = $shop_default->physical_uri;
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
--- a/src/Core/Context/ShopContext.php
|
||||||
|
+++ b/src/Core/Context/ShopContext.php
|
||||||
|
@@ -9,6 +9,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace PrestaShop\PrestaShop\Core\Context;
|
||||||
|
|
||||||
|
+use Tools;
|
||||||
|
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopConstraint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -121,11 +122,12 @@ class ShopContext
|
||||||
|
|
||||||
|
public function getBaseURL(): string
|
||||||
|
{
|
||||||
|
- if ($this->secured) {
|
||||||
|
- $url = 'https://' . $this->domainSSL;
|
||||||
|
- } else {
|
||||||
|
- $url = 'http://' . $this->domain;
|
||||||
|
- }
|
||||||
|
+ // EduBox: behind a reverse proxy with dynamic public domains the shop
|
||||||
|
+ // URL stored in the database is never the real public URL. Rebuild the
|
||||||
|
+ // base URL from the current request instead.
|
||||||
|
+ $secure = Tools::usingSecureMode();
|
||||||
|
+ $domain = $secure ? Tools::getShopDomainSsl(false, false) : Tools::getShopDomain(false, false);
|
||||||
|
+ $url = ($secure ? 'https://' : 'http://') . $domain;
|
||||||
|
|
||||||
|
return $url . $this->getBaseURI();
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
--- a/classes/shop/ShopUrl.php 2026-06-20 19:37:00.962339755 +0000
|
||||||
|
+++ b/classes/shop/ShopUrl.php 2026-06-20 19:37:01.182205146 +0000
|
||||||
|
@@ -175,15 +175,14 @@
|
||||||
|
|
||||||
|
public static function getMainShopDomain($id_shop = null)
|
||||||
|
{
|
||||||
|
- ShopUrl::cacheMainDomainForShop($id_shop);
|
||||||
|
-
|
||||||
|
- return self::$main_domain[(int) $id_shop] ?? null;
|
||||||
|
+ // EduBox: dynamic public domain behind reverse proxy.
|
||||||
|
+ // Always use the request host instead of the domain stored in database.
|
||||||
|
+ return Tools::getHttpHost(false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getMainShopDomainSSL($id_shop = null)
|
||||||
|
{
|
||||||
|
- ShopUrl::cacheMainDomainForShop($id_shop);
|
||||||
|
-
|
||||||
|
- return self::$main_domain_ssl[(int) $id_shop] ?? null;
|
||||||
|
+ // EduBox: dynamic public domain behind reverse proxy.
|
||||||
|
+ return Tools::getHttpHost(false, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
--- a/classes/Tools.php
|
||||||
|
+++ b/classes/Tools.php
|
||||||
|
@@ -269,9 +269,7 @@
|
||||||
|
*/
|
||||||
|
public static function getShopDomain($http = false, $entities = false)
|
||||||
|
{
|
||||||
|
- if (!$domain = ShopUrl::getMainShopDomain()) {
|
||||||
|
- $domain = Tools::getHttpHost();
|
||||||
|
- }
|
||||||
|
+ $domain = Tools::getHttpHost(false, false, true);
|
||||||
|
if ($entities) {
|
||||||
|
$domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8');
|
||||||
|
}
|
||||||
|
@@ -292,14 +290,12 @@
|
||||||
|
*/
|
||||||
|
public static function getShopDomainSsl($http = false, $entities = false)
|
||||||
|
{
|
||||||
|
- if (!$domain = ShopUrl::getMainShopDomainSSL()) {
|
||||||
|
- $domain = Tools::getHttpHost();
|
||||||
|
- }
|
||||||
|
+ $domain = Tools::getHttpHost(false, false, true);
|
||||||
|
if ($entities) {
|
||||||
|
$domain = htmlspecialchars($domain, ENT_COMPAT, 'UTF-8');
|
||||||
|
}
|
||||||
|
if ($http) {
|
||||||
|
- $domain = static::getProtocol((bool) Configuration::get('PS_SSL_ENABLED')) . $domain;
|
||||||
|
+ $domain = static::getProtocol(Tools::usingSecureMode()) . $domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $domain;
|
||||||
|
@@ -2246,7 +2242,7 @@
|
||||||
|
$rewrite_settings = (int) Configuration::get('PS_REWRITING_SETTINGS', null, null, (int) $uri['id_shop']);
|
||||||
|
}
|
||||||
|
|
||||||
|
- $domain_rewrite_cond = 'RewriteCond %{HTTP_HOST} ^' . $domain . '$' . PHP_EOL;
|
||||||
|
+ $domain_rewrite_cond = ''; // EduBox: removed HTTP_HOST condition for dynamic domains
|
||||||
|
// Rewrite virtual multishop uri
|
||||||
|
if ($uri['virtual']) {
|
||||||
|
if (!$rewrite_settings) {
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
# EduBox reverse proxy handling
|
||||||
|
# Apache sees HTTP requests from the EduBox resolver. The public request is HTTPS.
|
||||||
|
SetEnvIf X-Forwarded-Proto ^https$ HTTPS=on
|
||||||
|
SetEnvIf X-Forwarded-Proto ^https$ SERVER_PORT=443
|
||||||
|
|
||||||
|
# Enable .htaccess overrides for PrestaShop URL rewriting (images, products, etc.)
|
||||||
|
<Directory /var/www/html>
|
||||||
|
AllowOverride All
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
||||||
Binary file not shown.
Reference in New Issue
Block a user