diff --git a/_dev/src/scss/_variables.scss b/_dev/src/scss/_variables.scss index 125083ffc..879fc032d 100644 --- a/_dev/src/scss/_variables.scss +++ b/_dev/src/scss/_variables.scss @@ -55,7 +55,8 @@ $cdk-prefix: "cdk-"; 0.15s ); --#{$ua-prefix}header-height: var(--#{$cdk-prefix}header-height, 3.25rem); - --#{$ua-prefix}header-offset: 10rem; + --#{$ua-prefix}header-offset: 11.25rem; + --#{$ua-prefix}header-offset-mobile: calc(var(--#{$ua-prefix}header-offset) - 1rem); --#{$ua-prefix}bo-background-color: var(--#{$ua-prefix}primary-200); --#{$ua-prefix}error-img-filter: none; --#{$ua-prefix}scrollbar-thumb: var(--#{$ua-prefix}primary-500); @@ -70,6 +71,8 @@ body { --#{$ua-prefix}error-img-filter: invert(69%) sepia(66%) saturate(1340%) hue-rotate(151deg) brightness(88%) contrast(91%); --#{$ua-prefix}header-height: 2.5rem; + --#{$ua-prefix}header-offset: 9rem; + --#{$ua-prefix}header-offset-mobile: calc(var(--#{$ua-prefix}header-offset) - 0.75rem); } &:has(.v1-7-3-0) { @@ -77,6 +80,8 @@ body { --#{$ua-prefix}error-img-filter: invert(75%) sepia(64%) saturate(6023%) hue-rotate(161deg) brightness(96%) contrast(103%); --#{$ua-prefix}header-height: 2.5rem; + --#{$ua-prefix}header-offset: 10rem; + --#{$ua-prefix}header-offset-mobile: calc(var(--#{$ua-prefix}header-offset) + 1rem); } } diff --git a/_dev/src/scss/layouts/_error.scss b/_dev/src/scss/layouts/_error.scss index f14b93058..eaccd52f7 100644 --- a/_dev/src/scss/layouts/_error.scss +++ b/_dev/src/scss/layouts/_error.scss @@ -17,7 +17,6 @@ $e: ".error-page"; &__img { max-width: 100%; height: auto; - filter: var(--#{$ua-prefix}error-img-filter); } &__infos { @@ -67,29 +66,61 @@ $e: ".error-page"; &__buttons { flex-direction: column; } + + &__button { + justify-content: center; + } } } // Handle auto fit height - @container html-height (min-width: 0) { + @container html-block (min-width: 0) { display: grid; + grid-template-rows: 1fr; grid-template-columns: minmax(0, 1fr); + min-height: calc(100cqh - var(--#{$ua-prefix}header-offset-mobile)); + } + + @container html-block (min-width: 1024px) { min-height: calc(100cqh - var(--#{$ua-prefix}header-offset)); } } -// Handle auto fit height +// Enable auto fit height html { &:has(#{$ua-id}) { - &:has(.error-page) { + &:has(#{$e}) { container-type: size; - container-name: html-height; + container-name: html-block; + + #{$ua-id} { + &:not(.v1-7-8-0):not(.v1-7-3-0) { + #{$e} { + padding-block-end: 0; + } + } + } #{$e} { display: grid; height: 100%; container-type: inline-size; container-name: ua-error; + padding-block-end: 0.75rem; + } + + // Custom styles to adapt PrestaShop Back Office + body { + overflow-y: auto; + background-color: var(--#{$ua-prefix}bo-background-color); + + #nav-sidebar { + height: calc(100% - var(--#{$ua-prefix}header-height)); + } + } + + #main { + padding-block-end: 0; } } } diff --git a/_dev/src/scss/layouts/_layout.scss b/_dev/src/scss/layouts/_layout.scss index b3a4c826f..7d362f007 100644 --- a/_dev/src/scss/layouts/_layout.scss +++ b/_dev/src/scss/layouts/_layout.scss @@ -5,6 +5,10 @@ $e: "#ua"; #{$ua-id} { // Default BO theme layout fix padding-inline-end: 5px; + + &:not(.v1-7-8-0):not(.v1-7-3-0) { + padding-inline-end: 0; + } } #{$e} { diff --git a/_dev/src/scss/layouts/_logs-pages.scss b/_dev/src/scss/layouts/_logs-pages.scss index 008eead01..2f7314d54 100644 --- a/_dev/src/scss/layouts/_logs-pages.scss +++ b/_dev/src/scss/layouts/_logs-pages.scss @@ -6,8 +6,9 @@ html { // Need class use in #ua_step_content to make it work &:has(.update-page, .restore-page) { container-type: size; - container-name: html-height; + container-name: html-block; + // Custom styles to adapt PrestaShop Back Office body { overflow-y: auto; background-color: var(--#{$ua-prefix}bo-background-color); @@ -28,19 +29,15 @@ html { // Logs adjustments .logs { flex-grow: 1; - - &__scroll { - container-type: size; - } } - // Page adjustments - @container html-height (min-width: 0) { + // Page adjustments to handle auto fit height + @container html-block (min-width: 0) { #{$ua-id} { display: grid; grid-template-rows: 1fr; grid-template-columns: minmax(0, 1fr); - min-height: calc(100cqh - var(--#{$ua-prefix}header-offset)); + min-height: calc(100cqh - var(--#{$ua-prefix}header-offset-mobile)); #ua_container { flex-grow: 1; @@ -59,6 +56,12 @@ html { } } } + + @container html-block (min-width: 1024px) { + #{$ua-id} { + min-height: calc(100cqh - var(--#{$ua-prefix}header-offset)); + } + } } } } diff --git a/_dev/src/scss/layouts/_welcome.scss b/_dev/src/scss/layouts/_welcome.scss index 0b0dab74f..022cd1020 100644 --- a/_dev/src/scss/layouts/_welcome.scss +++ b/_dev/src/scss/layouts/_welcome.scss @@ -3,6 +3,12 @@ $e: ".welcome-page"; #{$ua-id} { + &:has(.welcome-page) { + #ua_main { + padding-block-start: 0; + } + } + #{$e} { &__card-list { display: flex; diff --git a/_dev/src/ts/api/RequestHandler.ts b/_dev/src/ts/api/RequestHandler.ts index 7d3701860..bfba09d4f 100644 --- a/_dev/src/ts/api/RequestHandler.ts +++ b/_dev/src/ts/api/RequestHandler.ts @@ -32,16 +32,25 @@ export class RequestHandler { data.append('dir', window.AutoUpgradeVariables.admin_dir); try { - const response = await baseApi.post('', data, { + const response = await baseApi.post('', data, { params: { route }, signal }); - const responseData = response.data as ApiResponse; + const responseData = response.data; await this.#handleResponse(responseData, fromPopState); } catch (error) { - // TODO: catch errors - console.error(error); + // A couple or errors are returned in an actual response (i.e 404 or 500) + if (error instanceof AxiosError) { + if (error.response?.data) { + const responseData = error.response.data; + responseData.new_route = 'error-page'; + await this.#handleResponse(responseData, true); + } + } else { + // TODO: catch errors + console.error(error); + } } } diff --git a/_dev/src/ts/pages/ErrorPage.ts b/_dev/src/ts/pages/ErrorPage.ts new file mode 100644 index 000000000..c04d3cbfe --- /dev/null +++ b/_dev/src/ts/pages/ErrorPage.ts @@ -0,0 +1,23 @@ +import DomLifecycle from '../types/DomLifecycle'; +import ErrorPage404 from './error/ErrorPage404'; +import PageAbstract from './PageAbstract'; + +export default class ErrorPage extends PageAbstract { + errorPage?: DomLifecycle; + + constructor() { + super(); + + if (document.getElementById('ua_error_404')) { + this.errorPage = new ErrorPage404(); + } + } + + public mount = (): void => { + this.errorPage?.mount(); + }; + + public beforeDestroy = (): void => { + this.errorPage?.beforeDestroy(); + }; +} diff --git a/_dev/src/ts/pages/error/ErrorPage404.ts b/_dev/src/ts/pages/error/ErrorPage404.ts new file mode 100644 index 000000000..c2845eef7 --- /dev/null +++ b/_dev/src/ts/pages/error/ErrorPage404.ts @@ -0,0 +1,53 @@ +import api from '../../api/RequestHandler'; +import DomLifecycle from '../../types/DomLifecycle'; + +export default class ErrorPage404 implements DomLifecycle { + isOnHomePage: boolean = false; + + public constructor() { + this.isOnHomePage = new URLSearchParams(window.location.search).get('route') === 'home-page'; + } + + public mount = (): void => { + this.#activeActionButton.classList.remove('hidden'); + this.#form.addEventListener('submit', this.#onSubmit); + }; + + public beforeDestroy = (): void => { + this.#form.removeEventListener('submit', this.#onSubmit); + }; + + get #activeActionButton(): HTMLFormElement | HTMLAnchorElement { + return this.isOnHomePage ? this.#exitButton : this.#form; + } + + get #form(): HTMLFormElement { + const form = document.forms.namedItem('home-page-form'); + if (!form) { + throw new Error('Form not found'); + } + + ['routeToSubmit'].forEach((data) => { + if (!form.dataset[data]) { + throw new Error(`Missing data ${data} from form dataset.`); + } + }); + + return form; + } + + get #exitButton(): HTMLAnchorElement { + const link = document.getElementById('exit-button'); + + if (!link || !(link instanceof HTMLAnchorElement)) { + throw new Error('Link is not found or invalid'); + } + return link; + } + + readonly #onSubmit = async (event: Event): Promise => { + event.preventDefault(); + + await api.post(this.#form.dataset.routeToSubmit!, new FormData(this.#form)); + }; +} diff --git a/_dev/src/ts/routing/ScriptHandler.ts b/_dev/src/ts/routing/ScriptHandler.ts index 40ff03464..45c690135 100644 --- a/_dev/src/ts/routing/ScriptHandler.ts +++ b/_dev/src/ts/routing/ScriptHandler.ts @@ -17,6 +17,7 @@ import SendErrorReportDialog from '../dialogs/SendErrorReportDialog'; import { ScriptType, ScriptsMatching, CurrentScripts } from '../types/scriptHandlerTypes'; import { routeHandler } from '../autoUpgrade'; +import ErrorPage from '../pages/ErrorPage'; export default class ScriptHandler { #currentScripts: CurrentScripts = { @@ -41,7 +42,9 @@ export default class ScriptHandler { 'restore-page-backup-selection': RestorePageBackupSelection, 'restore-page-restore': RestorePageRestore, - 'restore-page-post-restore': RestorePagePostRestore + 'restore-page-post-restore': RestorePagePostRestore, + + 'error-page': ErrorPage }, [ScriptType.DIALOG]: { 'restore-backup-dialog': RestoreBackupDialog, @@ -69,10 +72,14 @@ export default class ScriptHandler { * @returns void * @description Loads and mounts the script associated with the specified script name. */ - public loadScript(scriptID: string) { + public loadScript(scriptID: string): void { const scriptType = this.#getScriptTypeByScriptID(scriptID); if (!scriptType) { + console.debug(`No matching class found for ID: ${scriptID}`); + // Outside a hydration, the scriptID matches the route query param. + // If it does not exist, we load the error management script instead. + this.loadScript('error-page'); return; } diff --git a/classes/Router/Router.php b/classes/Router/Router.php index 33c11d906..06d1a1303 100644 --- a/classes/Router/Router.php +++ b/classes/Router/Router.php @@ -27,6 +27,7 @@ namespace PrestaShop\Module\AutoUpgrade\Router; +use PrestaShop\Module\AutoUpgrade\Controller\Error404Controller; use PrestaShop\Module\AutoUpgrade\Controller\ErrorReportController; use PrestaShop\Module\AutoUpgrade\Controller\HomePageController; use PrestaShop\Module\AutoUpgrade\Controller\LogsController; @@ -223,6 +224,11 @@ public function __construct(UpgradeContainer $upgradeContainer) 'controller' => LogsController::class, 'method' => 'getDownloadLogsButton', ], + + Routes::ERROR_404 => [ + 'controller' => Error404Controller::class, + 'method' => 'index', + ], ]; /** @@ -232,7 +238,8 @@ public function __construct(UpgradeContainer $upgradeContainer) */ public function handle(Request $request) { - $route = self::ROUTES[$request->query->get('route')] ?? self::ROUTES[Routes::HOME_PAGE]; + $routeName = $request->query->get('route') ?? Routes::HOME_PAGE; + $route = self::ROUTES[$routeName] ?? self::ROUTES[Routes::ERROR_404]; $method = $route['method']; diff --git a/classes/Router/Routes.php b/classes/Router/Routes.php index e1eecb8d6..5cef73a8f 100644 --- a/classes/Router/Routes.php +++ b/classes/Router/Routes.php @@ -67,4 +67,7 @@ class Routes /* logs */ const DOWNLOAD_LOGS = 'download-logs'; + + /* errors */ + const ERROR_404 = 'error-404'; } diff --git a/classes/Router/UrlGenerator.php b/classes/Router/UrlGenerator.php new file mode 100644 index 000000000..9d1220cdb --- /dev/null +++ b/classes/Router/UrlGenerator.php @@ -0,0 +1,74 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) + */ + +namespace PrestaShop\Module\AutoUpgrade\Router; + +use Symfony\Component\HttpFoundation\Request; + +class UrlGenerator +{ + /** @var string */ + private $shopBasePath; + /** @var string */ + private $adminFolder; + + public function __construct(string $shopBasePath, string $adminFolder) + { + $this->shopBasePath = $shopBasePath; + $this->adminFolder = $adminFolder; + } + + public function getShopAbsolutePathFromRequest(Request $request): string + { + // Determine the subdirectories of the PHP entry point (the script being executed) + // relative to the shop root folder. + // This calculation helps generate a base path that correctly accounts for any subfolder in which + // the shop might be installed. + $subDirs = explode( + DIRECTORY_SEPARATOR, + trim( + str_replace( + $this->shopBasePath, + '', + dirname($request->server->get('SCRIPT_FILENAME', '') + ) + ), DIRECTORY_SEPARATOR) + ); + $numberOfSubDirs = count($subDirs); + + $path = explode('/', $request->getBasePath()); + + $path = array_splice($path, 0, -$numberOfSubDirs); + + return implode('/', $path) ?: '/'; + } + + public function getShopAdminAbsolutePathFromRequest(Request $request): string + { + return rtrim($this->getShopAbsolutePathFromRequest($request), '/') . '/' . $this->adminFolder; + } +} diff --git a/classes/Twig/AssetsEnvironment.php b/classes/Twig/AssetsEnvironment.php index cc8c700e1..414e521a2 100644 --- a/classes/Twig/AssetsEnvironment.php +++ b/classes/Twig/AssetsEnvironment.php @@ -27,18 +27,19 @@ namespace PrestaShop\Module\AutoUpgrade\Twig; +use PrestaShop\Module\AutoUpgrade\Router\UrlGenerator; use Symfony\Component\HttpFoundation\Request; class AssetsEnvironment { const DEV_BASE_URL = 'http://localhost:5173'; - /** @var string */ - private $shopBasePath; + /** @var UrlGenerator */ + protected $urlGenerator; - public function __construct(string $shopBasePath) + public function __construct(UrlGenerator $urlGenerator) { - $this->shopBasePath = $shopBasePath; + $this->urlGenerator = $urlGenerator; } public function isDevMode(): bool @@ -52,31 +53,6 @@ public function getAssetsBaseUrl(Request $request): string return self::DEV_BASE_URL; } - return $this->getShopUrlFromRequest($request) . '/modules/autoupgrade/views'; - } - - private function getShopUrlFromRequest(Request $request): string - { - // Determine the subdirectories of the PHP entry point (the script being executed) - // relative to the shop root folder. - // This calculation helps generate a base path that correctly accounts for any subfolder in which - // the shop might be installed. - $subDirs = explode( - DIRECTORY_SEPARATOR, - trim( - str_replace( - $this->shopBasePath, - '', - dirname($request->server->get('SCRIPT_FILENAME', '') - ) - ), DIRECTORY_SEPARATOR) - ); - $numberOfSubDirs = count($subDirs); - - $path = explode('/', $request->getBasePath()); - - $path = array_splice($path, 0, -$numberOfSubDirs); - - return implode('/', $path); + return rtrim($this->urlGenerator->getShopAbsolutePathFromRequest($request), '/') . '/modules/autoupgrade/views'; } } diff --git a/classes/UpgradeContainer.php b/classes/UpgradeContainer.php index 2d9f8120d..17283b6d7 100644 --- a/classes/UpgradeContainer.php +++ b/classes/UpgradeContainer.php @@ -41,6 +41,7 @@ use PrestaShop\Module\AutoUpgrade\Parameters\UpgradeConfiguration; use PrestaShop\Module\AutoUpgrade\Progress\CompletionCalculator; use PrestaShop\Module\AutoUpgrade\Repository\LocalArchiveRepository; +use PrestaShop\Module\AutoUpgrade\Router\UrlGenerator; use PrestaShop\Module\AutoUpgrade\Services\ComposerService; use PrestaShop\Module\AutoUpgrade\Services\DistributionApiService; use PrestaShop\Module\AutoUpgrade\Services\DownloadService; @@ -270,6 +271,9 @@ class UpgradeContainer */ private $upgradeSelfCheck; + /** @var UrlGenerator */ + private $urlGenerator; + /** * @var PhpVersionResolverService */ @@ -901,7 +905,7 @@ public function getLocalArchiveRepository(): LocalArchiveRepository public function getAssetsEnvironment(): AssetsEnvironment { if (null === $this->assetsEnvironment) { - $this->assetsEnvironment = new AssetsEnvironment($this->getProperty(self::PS_ROOT_PATH)); + $this->assetsEnvironment = new AssetsEnvironment($this->getUrlGenerator()); } return $this->assetsEnvironment; @@ -961,6 +965,21 @@ public function getDownloadService(): DownloadService return $this->downloadService = new DownloadService($this->getTranslator(), $this->getLogger()); } + /** + * @return UrlGenerator + */ + public function getUrlGenerator(): UrlGenerator + { + if (null === $this->urlGenerator) { + $this->urlGenerator = new UrlGenerator( + $this->getProperty(self::PS_ROOT_PATH), + $this->getProperty(self::PS_ADMIN_SUBDIR) + ); + } + + return $this->urlGenerator; + } + /** * Checks if the composer autoload exists, and loads it. * diff --git a/controllers/admin/self-managed/Error404Controller.php b/controllers/admin/self-managed/Error404Controller.php new file mode 100644 index 000000000..9e574031c --- /dev/null +++ b/controllers/admin/self-managed/Error404Controller.php @@ -0,0 +1,65 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) + */ + +namespace PrestaShop\Module\AutoUpgrade\Controller; + +use PrestaShop\Module\AutoUpgrade\Router\Routes; +use Symfony\Component\HttpFoundation\Response; + +class Error404Controller extends AbstractPageController +{ + public function index() + { + $response = parent::index(); + + if ($response instanceof Response) { + $response->setStatusCode(Response::HTTP_NOT_FOUND); + } else { + http_response_code(Response::HTTP_NOT_FOUND); + } + + return $response; + } + + protected function getPageTemplate(): string + { + return 'errors/' . Response::HTTP_NOT_FOUND; + } + + protected function getParams(): array + { + return [ + // TODO: assets_base_path is provided by all controllers. What about a asset() twig function instead? + 'assets_base_path' => $this->upgradeContainer->getAssetsEnvironment()->getAssetsBaseUrl($this->request), + + 'error_code' => Response::HTTP_NOT_FOUND, + + 'exit_to_shop_admin' => $this->upgradeContainer->getUrlGenerator()->getShopAdminAbsolutePathFromRequest($this->request), + 'exit_to_app_home' => Routes::HOME_PAGE, + ]; + } +} diff --git a/controllers/admin/self-managed/RestorePagePostRestoreController.php b/controllers/admin/self-managed/RestorePagePostRestoreController.php index 36ca050ef..f549e5221 100644 --- a/controllers/admin/self-managed/RestorePagePostRestoreController.php +++ b/controllers/admin/self-managed/RestorePagePostRestoreController.php @@ -32,7 +32,6 @@ use PrestaShop\Module\AutoUpgrade\Task\TaskType; use PrestaShop\Module\AutoUpgrade\Twig\Steps\RestoreSteps; use PrestaShop\Module\AutoUpgrade\Twig\Steps\Stepper; -use PrestaShop\Module\AutoUpgrade\UpgradeContainer; class RestorePagePostRestoreController extends AbstractPageWithStepController { @@ -65,7 +64,7 @@ protected function getParams(): array return array_merge( $updateSteps->getStepParams($this::CURRENT_STEP), [ - 'exit_link' => DIRECTORY_SEPARATOR . $this->upgradeContainer->getProperty(UpgradeContainer::PS_ADMIN_SUBDIR) . DIRECTORY_SEPARATOR . 'index.php', + 'exit_link' => $this->upgradeContainer->getUrlGenerator()->getShopAdminAbsolutePathFromRequest($this->request), 'dev_doc_link' => DocumentationLinks::DEV_DOC_UPGRADE_POST_RESTORE_URL, 'download_logs' => $this->upgradeContainer->getLogsService()->getDownloadLogsData(TaskType::TASK_TYPE_RESTORE), ] diff --git a/controllers/admin/self-managed/UpdatePagePostUpdateController.php b/controllers/admin/self-managed/UpdatePagePostUpdateController.php index 11c02c619..942ecd846 100644 --- a/controllers/admin/self-managed/UpdatePagePostUpdateController.php +++ b/controllers/admin/self-managed/UpdatePagePostUpdateController.php @@ -32,7 +32,6 @@ use PrestaShop\Module\AutoUpgrade\Task\TaskType; use PrestaShop\Module\AutoUpgrade\Twig\Steps\Stepper; use PrestaShop\Module\AutoUpgrade\Twig\Steps\UpdateSteps; -use PrestaShop\Module\AutoUpgrade\UpgradeContainer; class UpdatePagePostUpdateController extends AbstractPageWithStepController { @@ -65,7 +64,7 @@ protected function getParams(): array return array_merge( $updateSteps->getStepParams($this::CURRENT_STEP), [ - 'exit_link' => DIRECTORY_SEPARATOR . $this->upgradeContainer->getProperty(UpgradeContainer::PS_ADMIN_SUBDIR) . DIRECTORY_SEPARATOR . 'index.php', + 'exit_link' => $this->upgradeContainer->getUrlGenerator()->getShopAdminAbsolutePathFromRequest($this->request), 'dev_doc_link' => DocumentationLinks::DEV_DOC_UPGRADE_POST_UPGRADE_URL, 'download_logs' => $this->upgradeContainer->getLogsService()->getDownloadLogsData(TaskType::TASK_TYPE_UPDATE), ] diff --git a/controllers/admin/self-managed/UpdatePageVersionChoiceController.php b/controllers/admin/self-managed/UpdatePageVersionChoiceController.php index 44cb86211..37a838872 100644 --- a/controllers/admin/self-managed/UpdatePageVersionChoiceController.php +++ b/controllers/admin/self-managed/UpdatePageVersionChoiceController.php @@ -112,6 +112,7 @@ protected function getParams(): array 'dev_doc_upgrade_web_url' => DocumentationLinks::DEV_DOC_UPGRADE_WEB_URL, 'up_to_date' => !$isNewerVersionAvailableOnline, 'no_local_archive' => !$this->upgradeContainer->getLocalArchiveRepository()->hasLocalArchive(), + // TODO: assets_base_path is provided by all controllers. What about a asset() twig function instead? 'assets_base_path' => $this->upgradeContainer->getAssetsEnvironment()->getAssetsBaseUrl($this->request), 'current_prestashop_version' => $this->getPsVersion(), 'current_php_version' => VersionUtils::getHumanReadableVersionOf(PHP_VERSION_ID), diff --git a/storybook/stories/layouts/Error404.stories.js b/storybook/stories/layouts/Error404.stories.js index 49f375008..0e929fa84 100644 --- a/storybook/stories/layouts/Error404.stories.js +++ b/storybook/stories/layouts/Error404.stories.js @@ -23,7 +23,7 @@ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) */ -import ErrorCode404 from "../../../views/templates/errors/404.html.twig"; +import ErrorCode404 from "../../../views/templates/pages/errors/404.html.twig"; export default { component: ErrorCode404, @@ -31,6 +31,10 @@ export default { args: { psBaseUri: "/", error_code: "404", + assets_base_path: "", + + exit_to_shop_admin: '#', + exit_to_app_home: '#', } }; diff --git a/storybook/stories/layouts/Error500.stories.js b/storybook/stories/layouts/Error500.stories.js index 46aac8348..38ab6ba52 100644 --- a/storybook/stories/layouts/Error500.stories.js +++ b/storybook/stories/layouts/Error500.stories.js @@ -23,7 +23,7 @@ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) */ -import ErrorCode500 from "../../../views/templates/errors/500.html.twig"; +import ErrorCode500 from "../../../views/templates/pages/errors/500.html.twig"; export default { component: ErrorCode500, @@ -31,6 +31,7 @@ export default { args: { psBaseUri: "/", error_code: "500", + assets_base_path: "", } }; diff --git a/tests/unit/Router/UrlGeneratorTest.php b/tests/unit/Router/UrlGeneratorTest.php new file mode 100644 index 000000000..9752a763a --- /dev/null +++ b/tests/unit/Router/UrlGeneratorTest.php @@ -0,0 +1,117 @@ + + * @copyright Since 2007 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) + */ +use PHPUnit\Framework\TestCase; +use PrestaShop\Module\AutoUpgrade\Router\UrlGenerator; +use Symfony\Component\HttpFoundation\Request; + +class UrlGeneratorTest extends TestCase +{ + /** @var UrlGenerator */ + private $urlGenerator; + + protected function setUp() + { + $shopBasePath = '/yo/doge'; + $adminPath = 'wololo'; + $this->urlGenerator = new UrlGenerator($shopBasePath, $adminPath); + } + + public function testGetShopUrlReturnsUrl() + { + $server = [ + 'HTTP_HOST' => 'localhost', + 'SERVER_PORT' => '80', + 'QUERY_STRING' => '', + 'PHP_SELF' => '/admin-wololo/index.php', + 'SCRIPT_FILENAME' => '/yo/doge/admin-wololo/index.php', + 'REQUEST_URI' => 'index.php', + ]; + + $request = new Request([], [], [], [], [], $server); + + $expectedAbsoluteUrlPathToShop = '/'; + $expectedAbsoluteUrlPathToAdmin = '/wololo'; + $this->assertSame($expectedAbsoluteUrlPathToShop, $this->urlGenerator->getShopAbsolutePathFromRequest($request)); + $this->assertSame($expectedAbsoluteUrlPathToAdmin, $this->urlGenerator->getShopAdminAbsolutePathFromRequest($request)); + } + + public function testGetShopUrlReturnsUrlWithShopInSubFolder() + { + $server = [ + 'HTTP_HOST' => 'localhost', + 'SERVER_PORT' => '80', + 'QUERY_STRING' => '', + 'PHP_SELF' => '/hello-world/admin-wololo/index.php', + 'SCRIPT_FILENAME' => '/yo/doge/admin-wololo/index.php', + 'REQUEST_URI' => 'hello-world/index.php', + ]; + + $request = new Request([], [], [], [], [], $server); + + $expectedAbsoluteUrlPathToShop = '/hello-world'; + $expectedAbsoluteUrlPathToAdmin = '/hello-world/wololo'; + $this->assertSame($expectedAbsoluteUrlPathToShop, $this->urlGenerator->getShopAbsolutePathFromRequest($request)); + $this->assertSame($expectedAbsoluteUrlPathToAdmin, $this->urlGenerator->getShopAdminAbsolutePathFromRequest($request)); + } + + public function testGetShopUrlReturnsUrlWithCustomEntrypoint() + { + $server = [ + 'HTTP_HOST' => 'localhost', + 'SERVER_PORT' => '80', + 'QUERY_STRING' => '', + 'PHP_SELF' => '/admin-wololo/autoupgrade/ajax-upgradetab.php', + 'SCRIPT_FILENAME' => '/yo/doge/admin-wololo/autoupgrade/ajax-upgradetab.php', + 'REQUEST_URI' => '/admin-wololo/autoupgrade/ajax-upgradetab.php?route=update-step-backup-submit', + ]; + + $request = new Request([], [], [], [], [], $server); + + $expectedAbsoluteUrlPathToShop = '/'; + $expectedAbsoluteUrlPathToAdmin = '/wololo'; + $this->assertSame($expectedAbsoluteUrlPathToShop, $this->urlGenerator->getShopAbsolutePathFromRequest($request)); + $this->assertSame($expectedAbsoluteUrlPathToAdmin, $this->urlGenerator->getShopAdminAbsolutePathFromRequest($request)); + } + + public function testGetShopUrlReturnsUrlWithShopInSubFolderAndParams() + { + $server = [ + 'HTTP_HOST' => 'localhost', + 'SERVER_PORT' => '80', + 'QUERY_STRING' => '', + 'PHP_SELF' => '/hello-world/admin-wololo/index.php', + 'SCRIPT_FILENAME' => '/yo/doge/admin-wololo/index.php', + 'REQUEST_URI' => 'hello-world/admin-wololo/index.php?controller=AdminSelfUpgrade', + ]; + + $request = new Request([], [], [], [], [], $server); + + $expectedAbsoluteUrlPathToShop = '/hello-world'; + $expectedAbsoluteUrlPathToAdmin = '/hello-world/wololo'; + $this->assertSame($expectedAbsoluteUrlPathToShop, $this->urlGenerator->getShopAbsolutePathFromRequest($request)); + $this->assertSame($expectedAbsoluteUrlPathToAdmin, $this->urlGenerator->getShopAdminAbsolutePathFromRequest($request)); + } +} diff --git a/tests/unit/Twig/AssetsEnvironmentTest.php b/tests/unit/Twig/AssetsEnvironmentTest.php index 37c7b42ae..8217b9937 100644 --- a/tests/unit/Twig/AssetsEnvironmentTest.php +++ b/tests/unit/Twig/AssetsEnvironmentTest.php @@ -24,6 +24,7 @@ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0) */ use PHPUnit\Framework\TestCase; +use PrestaShop\Module\AutoUpgrade\Router\UrlGenerator; use PrestaShop\Module\AutoUpgrade\Twig\AssetsEnvironment; use Symfony\Component\HttpFoundation\Request; @@ -34,7 +35,8 @@ class AssetsEnvironmentTest extends TestCase protected function setUp() { $shopBasePath = '/yo/doge'; - $this->assetsEnvironment = new AssetsEnvironment($shopBasePath); + $adminPath = 'wololo'; + $this->assetsEnvironment = new AssetsEnvironment(new UrlGenerator($shopBasePath, $adminPath)); } protected function tearDown() @@ -72,7 +74,7 @@ public function testGetAssetsBaseUrlReturnsDevUrlInDevMode() public function testGetAssetsBaseUrlReturnsProductionUrl() { - $expectedUrl = '/modules/autoupgrade/views'; + $expectedAbsoluteUrlPathToShop = '/modules/autoupgrade/views'; $server = [ 'HTTP_HOST' => 'localhost', 'SERVER_PORT' => '80', @@ -84,7 +86,7 @@ public function testGetAssetsBaseUrlReturnsProductionUrl() $request = new Request([], [], [], [], [], $server); - $this->assertSame($expectedUrl, $this->assetsEnvironment->getAssetsBaseUrl($request)); + $this->assertSame($expectedAbsoluteUrlPathToShop, $this->assetsEnvironment->getAssetsBaseUrl($request)); } public function testGetAssetsBaseUrlReturnsProductionUrlWithShopInSubFolder() @@ -100,8 +102,8 @@ public function testGetAssetsBaseUrlReturnsProductionUrlWithShopInSubFolder() $request = new Request([], [], [], [], [], $server); - $expectedUrl = '/hello-world/modules/autoupgrade/views'; - $this->assertSame($expectedUrl, $this->assetsEnvironment->getAssetsBaseUrl($request)); + $expectedAbsoluteUrlPathToShop = '/hello-world/modules/autoupgrade/views'; + $this->assertSame($expectedAbsoluteUrlPathToShop, $this->assetsEnvironment->getAssetsBaseUrl($request)); } public function testGetAssetsBaseUrlReturnsProductionUrlWithCustomEntrypoint() @@ -117,8 +119,8 @@ public function testGetAssetsBaseUrlReturnsProductionUrlWithCustomEntrypoint() $request = new Request([], [], [], [], [], $server); - $expectedUrl = '/modules/autoupgrade/views'; - $this->assertSame($expectedUrl, $this->assetsEnvironment->getAssetsBaseUrl($request)); + $expectedAbsoluteUrlPathToShop = '/modules/autoupgrade/views'; + $this->assertSame($expectedAbsoluteUrlPathToShop, $this->assetsEnvironment->getAssetsBaseUrl($request)); } public function testGetAssetsBaseUrlReturnsProductionUrlWithShopInSubFolderAndParams() @@ -134,7 +136,7 @@ public function testGetAssetsBaseUrlReturnsProductionUrlWithShopInSubFolderAndPa $request = new Request([], [], [], [], [], $server); - $expectedUrl = '/hello-world/modules/autoupgrade/views'; - $this->assertSame($expectedUrl, $this->assetsEnvironment->getAssetsBaseUrl($request)); + $expectedAbsoluteUrlPathToShop = '/hello-world/modules/autoupgrade/views'; + $this->assertSame($expectedAbsoluteUrlPathToShop, $this->assetsEnvironment->getAssetsBaseUrl($request)); } } diff --git a/views/templates/errors/404.html.twig b/views/templates/errors/404.html.twig deleted file mode 100644 index cea1e43f9..000000000 --- a/views/templates/errors/404.html.twig +++ /dev/null @@ -1,23 +0,0 @@ -{% extends "@ModuleAutoUpgrade/layouts/error.html.twig" %} - -{% block img %} - -{% endblock %} - -{% block title %} -

- {{ 'Something went wrong...'|trans({}) }} -

-{% endblock %} - -{% block description %} -

- {{ 'The page you requested cannot be found.'|trans({}) }} -

-{% endblock %} - -{% block button %} - - {{ 'Go back to Update assistant'|trans({}) }} - -{% endblock %} diff --git a/views/templates/layouts/error.html.twig b/views/templates/layouts/error.html.twig index 3b0cee274..b50c90208 100644 --- a/views/templates/layouts/error.html.twig +++ b/views/templates/layouts/error.html.twig @@ -1,23 +1,27 @@ -
-
- {% block img %} - {# Default image can go here, or it can be left empty so that children can override it #} - {% endblock %} +{% extends "@ModuleAutoUpgrade/layouts/page.html.twig" %} -
- {% block title %} - {# Default title can go here, or it can be left empty so that children can override it #} +{% block update_assistant %} +
+
+ {% block img %} + {# Default image can go here, or it can be left empty so that children can override it #} {% endblock %} - {% block description %} - {# Default description can go here, or it can be left empty so that children can override it #} - {% endblock %} +
+ {% block title %} + {# Default title can go here, or it can be left empty so that children can override it #} + {% endblock %} -
- {% block button %} - {# Default button can go here, or it can be left empty so that children can override it #} + {% block description %} + {# Default description can go here, or it can be left empty so that children can override it #} {% endblock %} + +
+ {% block button %} + {# Default button can go here, or it can be left empty so that children can override it #} + {% endblock %} +
-
+{% endblock %} diff --git a/views/templates/layouts/layout.html.twig b/views/templates/layouts/layout.html.twig index 4a0ae175b..c752a2835 100644 --- a/views/templates/layouts/layout.html.twig +++ b/views/templates/layouts/layout.html.twig @@ -1,9 +1,3 @@
- {% if page == "home" %} - {% include "@ModuleAutoUpgrade/pages/home.html.twig" %} - {% elseif page == "update" %} - {% include "@ModuleAutoUpgrade/pages/update.html.twig" %} - {% elseif page == "restore" %} - {% include "@ModuleAutoUpgrade/pages/restore.html.twig" %} - {% endif %} + {% include "@ModuleAutoUpgrade/pages/" ~ page ~ ".html.twig" %}
diff --git a/views/templates/layouts/page.html.twig b/views/templates/layouts/page.html.twig index 0696c09fa..f556d284c 100644 --- a/views/templates/layouts/page.html.twig +++ b/views/templates/layouts/page.html.twig @@ -20,6 +20,6 @@
{% endblock %}
- -
{% endblock %} + +
diff --git a/views/templates/pages/errors/404.html.twig b/views/templates/pages/errors/404.html.twig new file mode 100644 index 000000000..3c889cd5c --- /dev/null +++ b/views/templates/pages/errors/404.html.twig @@ -0,0 +1,30 @@ +{% extends "@ModuleAutoUpgrade/layouts/error.html.twig" %} + +{% block img %} + +{% endblock %} + +{% block title %} +

+ {{ 'Something went wrong...'|trans({}) }} +

+{% endblock %} + +{% block description %} +

+ {{ 'The page you requested cannot be found.'|trans({}) }} +

+{% endblock %} + +{% block button %} + + + +{% endblock %} diff --git a/views/templates/errors/500.html.twig b/views/templates/pages/errors/500.html.twig similarity index 100% rename from views/templates/errors/500.html.twig rename to views/templates/pages/errors/500.html.twig