diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..9ab59b180fb670006ac910a2bc4524a1376dcea0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,15 @@ + +# Ignore developer files when exporting +.gitattributes export-ignore +.gitignore export-ignore +.gitlab-ci.yml export-ignore +.phive export-ignore +captainhook.json export-ignore +phpcs.xml.dist export-ignore +phpstan-baseline.neon export-ignore +phpstan.dist.neon export-ignore +phpunit.dist.xml export-ignore +tests export-ignore + +# Explicitly set file type and line endings for PHP files, improves git diff output +*.php text eol=lf diff=php \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..b9f7c5c4723a7ff60166164bae8afaeec189067a --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ + +tools/ + +phpstan.neon + +.phpunit.result.cache + +phpunit.xml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b8d20acb6c365ad8036a7b36d47dabd876d08efa..b5a64b401e554341447c74d7cf93a89ac95a3fdb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,3 +1,17 @@ include: - - project: 'quiqqer/stabilization/semantic-release' - file: '/ci-templates/.gitlab-ci.yml' + - component: dev.quiqqer.com/quiqqer/stabilization/ci-cd-components/quiqqer-package-bundle/quiqqer-package-bundle@main + +# Remove the entire phpunit-php8.1 block, to allow PHPUnit to run on PHP 8.1 in your pipeline +phpunit-php8.1: + rules: + - when: never + +# Remove the entire phpunit-php8.2 block, to allow PHPUnit to run on PHP 8.2 in your pipeline +phpunit-php8.2: + rules: + - when: never + +# Remove the entire phpunit-php8.3 block, to allow PHPUnit to run on PHP 8.3 in your pipeline +phpunit-php8.3: + rules: + - when: never \ No newline at end of file diff --git a/.phive/phars.xml b/.phive/phars.xml new file mode 100644 index 0000000000000000000000000000000000000000..5bfa092bfad10dad9d23240281a5a2041acb815b --- /dev/null +++ b/.phive/phars.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<phive xmlns="https://phar.io/phive"> + <phar name="phpstan" version="1.11.8" installed="1.11.8" location="./tools/phpstan" copy="false"/> + <phar name="phpunit" version="^10.5.20" installed="10.5.20" location="./tools/phpunit" copy="false"/> + <phar name="phpcs" version="^3.10.1" installed="3.10.1" location="./tools/phpcs" copy="false"/> + <phar name="phpcbf" version="^3.10.1" installed="3.10.1" location="./tools/phpcbf" copy="false"/> + <phar name="captainhook" version="^5.23.3" installed="5.23.3" location="./tools/captainhook" copy="false"/> +</phive> diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..4a69a59b440e5beec561eca1e341509bd5a18688 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contributing + +This package follows the [QUIQQER contribution guidelines](https://dev.quiqqer.com/quiqqer/stabilization/documentation/-/wikis/home). \ No newline at end of file diff --git a/bin/css/frontend-users.css b/bin/css/frontend-users.css index 629acd054308d2ca0bb6a525f770252ed8e880e6..c8cde74ca385435d28c1ec9231d52b2d55fdf4e6 100644 --- a/bin/css/frontend-users.css +++ b/bin/css/frontend-users.css @@ -245,12 +245,12 @@ /*****************/ /* Login control */ /*****************/ -.quiqqer-fu-login-container, -.quiqqer-fu-registrationSignUp { +:where(.loginAndRegister) .quiqqer-fu-login-container, +:where(.loginAndRegister) .quiqqer-fu-registrationSignUp { padding: 1.5rem 2rem; } -.quiqqer-fu-login-container { +:where(.loginAndRegister) .quiqqer-fu-login-container { background: #f8f8f8; border: 1px solid #ddd; max-width: 400px; @@ -258,7 +258,7 @@ width: 100%; } -.quiqqer-frontendUsers-login .quiqqer-fu-login-container { +:where(.loginAndRegister) .quiqqer-frontendUsers-login .quiqqer-fu-login-container { background: none; border: none; margin: 0 auto; @@ -266,7 +266,7 @@ } @media screen and (max-width: 767px) { - .quiqqer-fu-registrationSignUp { + :where(.loginAndRegister) .quiqqer-fu-registrationSignUp { padding: 0; } } @@ -274,7 +274,7 @@ /******************/ /* reset password */ /******************/ -.quiqqer-fu-login-container .quiqqer-fu-login-forget-password-reset [name="cancel"] { +:where(.loginAndRegister) .quiqqer-fu-login-container .quiqqer-fu-login-forget-password-reset [name="cancel"] { background: none; border: none; color: inherit; @@ -284,7 +284,7 @@ position: initial; } -.quiqqer-fu-login-container .quiqqer-fu-login-forget-password-reset [type="submit"] { +:where(.loginAndRegister) .quiqqer-fu-login-container .quiqqer-fu-login-forget-password-reset [type="submit"] { margin-top: 1rem; } diff --git a/bin/css/order.css b/bin/css/order.css index b4e912fc188eebd52b61d24c5ec38823e80178c3..04032a9a245e9473b93731ad81372a543060f7b3 100644 --- a/bin/css/order.css +++ b/bin/css/order.css @@ -69,6 +69,21 @@ th.quiqqer-order-basket-articles-header-price { width: 60px; } +.quiqqer-order-basket-articles-header-image { + width: var(--_qui-order-basket-articles-image-width); +} + +.quiqqer-order-basket-articles-article-image { + width: var(--_qui-order-basket-articles-image-width); + text-align: center; +} + +.quiqqer-order-basket-articles-article-image__img { + width: var(--_qui-order-basket-articles-image-width); + height: var(--_qui-order-basket-articles-image-height); + object-fit: contain; +} + .quiqqer-order-basket-articles-article-quantity { text-align: center; width: 100px; @@ -439,6 +454,17 @@ table.articles-article { vertical-align: top; } +.articles-article-image { + width: var(--_qui-order-basket-articles-image-width); + text-align: center; +} + +.articles-article-image__img { + width: var(--_qui-order-articles-image-width); + height: var(--_qui-order-articles-image-height); + object-fit: contain; +} + td.articles-article-information { text-align: left; } @@ -514,7 +540,7 @@ th.articles-article-header-information { padding: 10px; } -.articles-sum { +:where(.quiqqer-order-step-checkout-article) .articles-sum { background: #f8f8f8; border: 1px solid #ddd; float: right; diff --git a/bin/css/variables.css b/bin/css/variables.css index 9cc5728744d16da5d5e48d308ceab9d4faca83d4..47ad80ed9784bc75d2eeaa7ea1048a4ca481ded1 100644 --- a/bin/css/variables.css +++ b/bin/css/variables.css @@ -16,4 +16,11 @@ /* background */ --bg-primary: #ddd; --bg-secondary: #f5f5f5; + + + /* ecoyn / ecommerce */ + --_qui-order-basket-articles-image-width: var(--qui-order-basket-articles-image-width, 100px); + --_qui-order-basket-articles-image-height: var(--qui-order-basket-articles-image-height, 100px); + --_qui-order-articles-image-width: var(--qui-order-articles-image-width, 100px); + --_qui-order-articles-image-height: var(--qui-order-articles-image-height, 100px); } \ No newline at end of file diff --git a/captainhook.json b/captainhook.json new file mode 100644 index 0000000000000000000000000000000000000000..3702e1a358868bedd5ff4c7eae40bb1abb589267 --- /dev/null +++ b/captainhook.json @@ -0,0 +1,13 @@ +{ + "pre-commit": { + "enabled": true, + "actions": [ + { + "action": "\\CaptainHook\\App\\Hook\\PHP\\Action\\Linting" + }, + { + "action": "composer test" + } + ] + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index 0c520071e471dca7d75e5ef83c2533e8702e38f6..5689cd44fe9d0ae901bcffce55db4e49bdf0b9aa 100644 --- a/composer.json +++ b/composer.json @@ -1,38 +1,80 @@ { - "name": "quiqqer/template-cologne", - "type": "quiqqer-template", - "description": "The QUIQQER Cologne E-Commerce Template", - "license": "GPLv3", - "authors": [ - { - "name": "Henning Leutz", - "email": "support@pcsg.de", - "homepage": "https://www.pcsg.de", - "role": "Developer" + "name": "quiqqer/template-cologne", + "type": "quiqqer-template", + "description": "The QUIQQER Cologne E-Commerce Template", + "license": "GPLv3", + "authors": [ + { + "name": "Henning Leutz", + "email": "support@pcsg.de", + "homepage": "https://www.pcsg.de", + "role": "Developer" + } + ], + "support": { + "email": "support@pcsg.de", + "url": "https://www.pcsg.de" + }, + "require": { + "php": "^8.1", + "quiqqer/core": "^2", + "quiqqer/erp": "^3", + "quiqqer/products": "^2", + "quiqqer/order": "^2", + "quiqqer/product-bricks": "^2", + "quiqqer/frontend-users": "^2", + "quiqqer/menu": "^3", + "quiqqer/sitetypes": "^2", + "quiqqer/unsemantic": "^2", + "quiqqer-asset/fastclick": "^1", + "quiqqer/tooltips": "^2", + "quiqqer/currency": "^2" + }, + "autoload": { + "psr-4": { + "QUI\\TemplateCologne\\": "src/QUI/TemplateCologne" + } + }, + "scripts": { + "test": [ + "@dev:lint", + "@dev:phpunit" + ], + "dev:phpunit": "./tools/phpunit", + "dev:lint": [ + "@dev:lint:phpstan", + "@dev:lint:style" + ], + "dev:lint:phpstan": "./tools/phpstan", + "dev:lint:style": "./tools/phpcs", + "dev:lint:style:fix": "./tools/phpcbf", + "dev:init": [ + "@dev:init:check-requirements", + "@dev:init:tools", + "@dev:init:git-hooks" + ], + "dev:init:check-requirements": [ + "which composer > /dev/null || (echo 'Error: composer has to be globally installed'; exit 1)", + "which phive > /dev/null || (echo 'Error: PHIVE has to be globally installed'; exit 1)" + ], + "dev:init:tools": "phive install --temporary", + "dev:init:git-hooks": "./tools/captainhook install --only-enabled --force" + }, + "scripts-aliases": { + "test": [ + "dev:test" + ] + }, + "scripts-descriptions": { + "test": "Runs linting, static analysis, and unit tests.", + "dev:phpunit": "Run PHPUnit test suites", + "dev:lint": "Run PHPStan and code style check", + "dev:lint:phpstan": "Run PHPStan", + "dev:lint:style": "Run code style check (PHP_CodeSniffer)", + "dev:lint:style:fix": "Try to fix code style errors automatically", + "dev:init": "Initialize the developer tooling (tools and git hooks)", + "dev:init:check-requirements": "Check if the necessary requirements are met", + "dev:init:tools": "Install all developer tools (requires PHIVE)", + "dev:init:git-hooks": "Install all git hooks (may require tools to be installed)" } - ], - "support": { - "email": "support@pcsg.de", - "url": "https://www.pcsg.de" - }, - "require": { - "php": "^8.1", - "quiqqer/core": "^2", - "quiqqer/erp": "^3", - "quiqqer/products": "^2", - "quiqqer/order": "^2", - "quiqqer/product-bricks": "^2", - "quiqqer/frontend-users": "^2", - "quiqqer/menu": "^3", - "quiqqer/sitetypes": "^2", - "quiqqer/unsemantic": "^2", - "quiqqer-asset/fastclick": "^1", - "quiqqer/tooltips": "^2", - "quiqqer/currency": "^2" - }, - "autoload": { - "psr-4": { - "QUI\\TemplateCologne\\": "src/QUI/TemplateCologne" - } - } -} +} \ No newline at end of file diff --git a/index.php b/index.php index a49e56fec0764332379ba4b0900bd272e4185675..722a87936c0c95ad8badaaab4453caa4df6f6d72 100644 --- a/index.php +++ b/index.php @@ -37,7 +37,7 @@ $independentMenuId = $Project->getConfig('templateCologne.settings.menuId'); if ($enableIndependentMenu && $independentMenuId) { - $menuParams['menuId'] = $enableIndependentMenu; + $menuParams['menuId'] = $independentMenuId; $menuParams['showFirstLevelIcons'] = $Project->getConfig('templateCologne.settings.showFirstLevelIcons'); $menuParams['showStart'] = false; } diff --git a/locale.xml b/locale.xml index 8b106bf679acf6449961f41b31e7a8360496b0db..45a994ed5adabd209b40ae360bf3959591a77f7c 100644 --- a/locale.xml +++ b/locale.xml @@ -500,6 +500,15 @@ <en><![CDATA[Compact (only icon)]]></en> </locale> + <locale name="settings.shop.order.basket.showImages"> + <de><![CDATA[Produktbilder im Warenkorb anzeigen]]></de> + <en><![CDATA[Show product images in basket]]></en> + </locale> + <locale name="settings.shop.order.basket.showImages.desc"> + <de><![CDATA[Wenn aktiviert, werden in Warenkorb und Bestellung die Produktbilder angezeigt.]]></de> + <en><![CDATA[If the option ist enabled, the product images are displayed in the shopping basket and order.]]></en> + </locale> + <!-- basket open --> <locale name="settings.shop.basketOpen"> <de><![CDATA[Aktion bei Klick auf Warenkorb]]></de> diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000000000000000000000000000000000000..d48084fbdc86a2dbfb78dd89ab2e0b0ff2322ba7 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,23 @@ +<?xml version="1.0"?> +<ruleset> + <!-- Use PSR-12 ruleset --> + <rule ref="PSR12"/> + + <!-- Only scan *.php files --> + <arg name="extensions" value="php"/> + + <!-- Ignore warnings --> + <arg name="warning-severity" value="0"/> + + <!-- Process 64 (or number of CPU cores) files in parallel --> + <arg name="parallel" value="64"/> + + <!-- Output relative file paths, by setting the current folder as the basepath --> + <arg name="basepath" value="."/> + + <!-- Show colored output --> + <arg name="colors"/> + + <!-- Scan everything in the current folder --> + <file>.</file> +</ruleset> diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000000000000000000000000000000000000..0fa167e4334aba70f2e8321bce11f980e22fd2f9 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,51 @@ +parameters: + ignoreErrors: + - + message: "#^Call to an undefined method QUI\\\\Interfaces\\\\Projects\\\\Site\\:\\:getCachePath\\(\\)\\.$#" + count: 1 + path: src/QUI/TemplateCologne/Controls/Menu/Categories.php + + - + message: "#^Access to constant PRODUCT_FIELD_SHIPPING_TIME on an unknown class QUI\\\\ERP\\\\Shipping\\\\Shipping\\.$#" + count: 1 + path: src/QUI/TemplateCologne/Utils.php + + - + message: "#^Access to constant PRODUCT_FIELD_STOCK on an unknown class QUI\\\\ERP\\\\StockManagement\\\\StockManager\\.$#" + count: 1 + path: src/QUI/TemplateCologne/Utils.php + + - + message: "#^Call to method setProduct\\(\\) on an unknown class QUI\\\\ERP\\\\StockManagement\\\\Products\\\\Fields\\\\StockView\\.$#" + count: 1 + path: src/QUI/TemplateCologne/Utils.php + + - + message: "#^Call to static method getShippingTimeFrontendViewByProduct\\(\\) on an unknown class QUI\\\\ERP\\\\StockManagement\\\\StockManager\\.$#" + count: 1 + path: src/QUI/TemplateCologne/Utils.php + + - + message: "#^Method QUI\\\\TemplateCologne\\\\Utils\\:\\:getStockFrontendView\\(\\) should return QUI\\\\ERP\\\\Products\\\\Field\\\\View\\|false but returns QUI\\\\ERP\\\\StockManagement\\\\Products\\\\Fields\\\\StockView\\.$#" + count: 1 + path: src/QUI/TemplateCologne/Utils.php + + - + message: "#^PHPDoc tag @var for variable \\$StockView contains unknown class QUI\\\\ERP\\\\StockManagement\\\\Products\\\\Fields\\\\StockView\\.$#" + count: 1 + path: src/QUI/TemplateCologne/Utils.php + + - + message: "#^PHPDoc tag @var has invalid value \\(\\$Site Site\\)\\: Unexpected token \"\\$Site\", expected type at offset 9$#" + count: 1 + path: src/QUI/TemplateCologne/Utils.php + + - + message: "#^Variable \\$Project might not be defined\\.$#" + count: 2 + path: src/QUI/TemplateCologne/settings.css.php + + - + message: "#^Variable \\$Site might not be defined\\.$#" + count: 1 + path: src/QUI/TemplateCologne/settings.css.php diff --git a/phpstan.dist.neon b/phpstan.dist.neon new file mode 100644 index 0000000000000000000000000000000000000000..dc33bb4eaabd6fab16696f6e9ea5b43071cfdf84 --- /dev/null +++ b/phpstan.dist.neon @@ -0,0 +1,11 @@ +includes: + - phpstan-baseline.neon + +parameters: + level: 5 + paths: + - src + - ajax + bootstrapFiles: + - tests/phpstan-bootstrap.php + tipsOfTheDay: false diff --git a/phpunit.dist.xml b/phpunit.dist.xml new file mode 100644 index 0000000000000000000000000000000000000000..f6c7becf0c12757beb871a9333e2d81e02aa7cae --- /dev/null +++ b/phpunit.dist.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<phpunit bootstrap="tests/phpunit-bootstrap.php"> + <testsuites> + <testsuite name="Tests"> + <directory>tests/</directory> + </testsuite> + </testsuites> +</phpunit> diff --git a/quiqqer/faq/types/category.html b/quiqqer/faq/types/category.html index dffa9454835d7876595023fa8007c5b81332bc3f..ae7c9f1347a6822b382956555c1dbd75f38ce6af 100644 --- a/quiqqer/faq/types/category.html +++ b/quiqqer/faq/types/category.html @@ -6,28 +6,14 @@ {* Template: default*} {if $faqTemplate == 'default'} - {if $offset} - {* - This CSS is used to scroll the page down a bit when accessed with a # in the url. - By doing this the menu no longer hides the linked content. - *} - <style type="text/css"> - :target::before { - content: ''; - display: block; - height: {$offset}px; - margin-top: -{$offset}px; - } - </style> - {/if} - - <section itemscope itemtype="http://schema.org/ItemList" + <section itemscope itemtype="https://schema.org/ItemList" class="content-template quiqqer-faq clear-fix cologne-quiqqer-faq" data-qui="package/quiqqer/faq/bin/Category" data-qui-options-offset="{$offset}" + {if $offset}style="--_qui-faq-scrollOffset: var(--qui-faq-scrollOffset, {$offset}px);"{/if} > {if count($entries)} - <ul class="quiqqer-faq-list" id="faqList" name="faqList"> + <ul class="quiqqer-faq-list" id="faqList"> {foreach $entries as $Faq} <li> <a href="{url site=$Site}#faq{$Faq->getId()}"> @@ -40,7 +26,7 @@ {/if} {foreach $entries as $Faq} - <article id="faq{$Faq->getId()}" class="clear-fix"> + <article id="faq{$Faq->getId()}" class="quiqqer-faq__entry"> <header> <h2><span class="fa fa-file-text"></span> {$Faq->getAttribute('title')}</h2> </header> @@ -65,6 +51,10 @@ {/if} {/foreach} + + {if $faqStructuredData} + {$faqStructuredData} + {/if} </section> {/if} diff --git a/quiqqer/order/src/QUI/ERP/Order/Controls/Basket/Basket.html b/quiqqer/order/src/QUI/ERP/Order/Controls/Basket/Basket.html new file mode 100644 index 0000000000000000000000000000000000000000..d06d5283ad797a814d8ad2b7054c5a05d84d6630 --- /dev/null +++ b/quiqqer/order/src/QUI/ERP/Order/Controls/Basket/Basket.html @@ -0,0 +1,242 @@ +{template_event name="quiqqer::order::basket::begin" Basket=$Basket} + +{if $Products->count()} +<table class="quiqqer-order-basket-articles"> + <thead> + <tr class="quiqqer-order-basket-articles-header"> + <th class="quiqqer-order-basket-articles-header-pos" + title="{locale group='quiqqer/erp' var='article.list.articles.header.pos'}" + > + {locale group="quiqqer/erp" var="article.list.articles.header.pos"} + </th> + {if QUI\TemplateCologne\Utils::getSetting('order.basket.showImages')} + <th class="quiqqer-order-basket-articles-header-image" + title="{locale group='quiqqer/erp' var='article.list.articles.header.image'}" + > + {locale group="quiqqer/erp" var="article.list.articles.header.image"} + </th> + {/if} + <th class="quiqqer-order-basket-articles-header-information" + title="{locale group='quiqqer/erp' var='article.list.articles.header.description'}" + > + {locale group="quiqqer/erp" var="article.list.articles.header.description"} + </th> + <th class="quiqqer-order-basket-articles-header-quantity" + title="{locale group='quiqqer/erp' var='article.list.articles.header.quantity'}" + > + {locale group="quiqqer/erp" var="article.list.articles.header.quantity"} + </th> + <th class="quiqqer-order-basket-articles-unitPrice" + title="{locale group='quiqqer/erp' var='article.list.articles.header.unitprice'}" + > + {locale group="quiqqer/erp" var="article.list.articles.header.unitprice"} + </th> + <th class="quiqqer-order-basket-articles-header-price" + title="{locale group='quiqqer/erp' var='article.list.articles.header.price'}" + > + {locale group="quiqqer/erp" var="article.list.articles.header.price"} + </th> + {if $this->getAttribute('editable')} + <th class="quiqqer-order-basket-articles-header-action"></th> + {/if} + </tr> + </thead> + <tbody> + {assign var=pos value=1} + {foreach $products as $product} + <tr class="quiqqer-order-basket-articles-article" data-pos="{$pos}"> + <td class="quiqqer-order-basket-articles-article-pos" + data-label="{locale group='quiqqer/erp' var='article.list.articles.header.pos'}" + > + {$pos} + </td> + {if QUI\TemplateCologne\Utils::getSetting('order.basket.showImages')} + <td class="quiqqer-order-basket-articles-article-image" + data-label="{locale group='quiqqer/erp' var='article.list.articles.header.image'}" + > + {image src=$product.imageSrc width=300 height=300 class="quiqqer-order-basket-articles-article-image__img"} + </td> + {/if} + <td class="quiqqer-order-basket-articles-article-data" + data-label="{locale group='quiqqer/erp' var='article.list.articles.header.description'}" + > + <div class="quiqqer-order-basket-articles-article-title">{$product.title}</div> + <div class="quiqqer-order-basket-articles-article-description"> + {$product.description} + </div> + + <ul class="quiqqer-order-basket-articles-article-fields"> + {foreach $product.attributes as $attribute} + <li class="quiqqer-order-basket-articles-article-fields-field"> + <span>{$attribute.title}:</span> + <span>{$this->getValueText($attribute.valueText)}</span> + </li> + {/foreach} + </ul> + + {if $showArticleNumber && !empty($product.productNo)} + <div class="quiqqer-order-basket-articles-article-productno"> + {locale group="quiqqer/order" var="basket.articles.articleNo"} {$product.productNo} + </div> + {/if} + </td> + <td class="quiqqer-order-basket-articles-article-quantity" + data-label="{locale group='quiqqer/erp' var='article.list.articles.header.quantity'}" + > + {assign var=maxQuantity value=""} + {assign var=maxQuantityAttr value=""} + {if isset($product.maximumQuantity) && $product.maximumQuantity && $product.maximumQuantity !== true} + {assign var=maxQuantityAttr value=" max='{$product.maximumQuantity}'"} + {assign var=maxQuantity value=(int)$product.maximumQuantity} + {/if} + + {if $Utils->isBasketProductEditable($product) && $this->getAttribute('editable') && $maxQuantity != 1} + <label> + <input type="number" + name="quantity" + min="0" + value="{$product.quantity}" + {$maxQuantityAttr} + /> + </label> + {else} + <div class="quiqqer-order-basket-articles-article-quantity-value"> + {$product.quantity} + </div> + {/if} + </td> + <td class="quiqqer-order-basket-articles-article-price" + data-label="{locale group='quiqqer/erp' var='article.list.articles.header.unitprice'}" + > + {if !isset($product.displayPrice) || $product.displayPrice} + {$product.price} + {/if} + </td> + <td class="quiqqer-order-basket-articles-article-sum" + data-label="{locale group='quiqqer/erp' var='article.list.articles.header.price'}" + > + {if !isset($product.displayPrice) || $product.displayPrice} + <span>{$product.sum}</span> + {/if} + + {if !isset($product.hasOfferPrice) || $product.hasOfferPrice} + <span class="offer-original-price"> + {$product.originalPrice} + </span> + {/if} + </td> + {if $this->getAttribute('editable')} + <td class="quiqqer-order-basket-articles-article-remove"> + <button type="button"> + <span class="fa fa-trash"></span> + </button> + </td> + {/if} + </tr> + {assign var=pos value=$pos+1} + {/foreach} + </tbody> +</table> + +{template_event name="quiqqer::order::basket::middle" Basket=$Basket} + +<table class="quiqqer-order-basket-total"> + <tr class="quiqqer-order-basket-total-subSum"> + <td class="quiqqer-order-basket-total-firstCell"> + <span class="quiqqer-order-basket-total-subSum-text"> + {locale group="quiqqer/order" var="control.order.overview.subSum"} + </span> + </td> + <td class="quiqqer-order-basket-total-secondCell"> + <span class="quiqqer-order-basket-total-subSum-value"> + {$data.subSum} + </span> + </td> + </tr> + + {foreach $data.attributes as $attribute} + <tr> + <td> + {$attribute.title} {if !empty($attribute.valueText)}({$attribute.valueText}){/if} + </td> + <td> + {$attribute.value} + </td> + </tr> + {/foreach} + + {if count($data.attributes)} + <tr> + <td colspan="2"><br/></td> + </tr> + {/if} + + {foreach $data.vat as $vat} + <tr> + <td> + {$vat.text} + </td> + <td> + {$vat.value} + </td> + </tr> + {/foreach} + + + {if isset($data.grandTotalFactors) && count($data.grandTotalFactors)} + <tr class="quiqqer-order-basket-total-grandSubSum"> + <td class="quiqqer-order-basket-total-firstCell"> + <span class="quiqqer-order-basket-total-grandSubSum-text"> + {locale group="quiqqer/order" var="control.order.overview.grandSubSum"} + </span> + </td> + <td class="quiqqer-order-basket-total-secondCell"> + <span class="quiqqer-order-basket-total-grandSubSum-value"> + {$data.grandSubSum} + </span> + </td> + </tr> + {foreach $data.grandTotalFactors as $attribute} + <tr> + <td> + {$attribute.title} {if !empty($attribute.valueText) && $attribute.valueText !== + '-'}({$attribute.valueText}){/if} + </td> + <td> + {$attribute.value} + </td> + </tr> + {/foreach} + {/if} + + + {if count($data.attributes)} + <tr> + <td colspan="2"><br/></td> + </tr> + {/if} + <tr class="quiqqer-order-basket-total-sum"> + <td> + <span class="quiqqer-order-basket-total-sum-text"> + {locale group="quiqqer/order" var="control.order.overview.sum"} + </span> + </td> + <td> + <span class="quiqqer-order-basket-total-sum-value"> + {$data.sum} + </span> + </td> + </tr> +</table> + +{elseif $this->isGuest() && $this->isLoading()} +<div class="quiqqer-order-basket-isLoading"> + <span class="fa fa-spinner fa-spin"></span> +</div> +{else} +<div class="quiqqer-order-basket-isEmpty"> + {locale group="quiqqer/order" var="message.basket.is.empty"} +</div> +{/if} + +{template_event name="quiqqer::order::basket::end" Basket=$Basket} diff --git a/settings.xml b/settings.xml index 6700b587f0a5cc330e88aad7d6b3f8b41300a202..3f0a34b1a347e13ebf3bd208cf94519132e3f173 100644 --- a/settings.xml +++ b/settings.xml @@ -36,6 +36,10 @@ <type><![CDATA[string]]></type> <defaultvalue>full</defaultvalue> </conf> + <conf name="order.basket.showImages"> + <type><![CDATA[bool]]></type> + <defaultvalue>1</defaultvalue> + </conf> <conf name="basketOpen"> <type><![CDATA[integer]]></type> <defaultvalue>2</defaultvalue> @@ -437,6 +441,19 @@ </option> </select> + <input conf="templateCologne.settings.order.basket.showImages" type="checkbox"> + <text> + <locale group="quiqqer/template-cologne" + var="settings.shop.order.basket.showImages" + /> + </text> + <description> + <locale group="quiqqer/template-cologne" + var="settings.shop.order.basket.showImages.desc" + /> + </description> + </input> + <!-- basket open (nothing order window, order page)--> <select conf="templateCologne.settings.basketOpen"> <text> diff --git a/src/QUI/TemplateCologne/Utils.php b/src/QUI/TemplateCologne/Utils.php index f0fc42ba72615cb104959ad084175c380d9f88c2..bfa1bfa51a30193db9b6b0bb8fa0a99254ff8111 100644 --- a/src/QUI/TemplateCologne/Utils.php +++ b/src/QUI/TemplateCologne/Utils.php @@ -699,4 +699,38 @@ public static function convertBrickCSSClass(array $classes): string return $text; } + + /** + * Get template setting for given string. + * By passing setting name you can omit template prefix setting name ("templateCologne.settings.") + * + * Usage: + * QUI\TemplateCologne\Utils::getSettings('homeLink'); + * or + * QUI\TemplateCologne\Utils::getSettings('templateCologne.settings.homeLink'); + * + * @param string $settingName + * @return bool|array|int|string + */ + public static function getSetting(string $settingName): bool|array|int|string + { + if (empty($settingName)) { + return false; + } + + $a = strpos($settingName, 'templateCologne.settings.'); + if (!str_contains($settingName, 'templateCologne.settings.')) { + $settingName = 'templateCologne.settings.' . $settingName; + } + + try { + $Project = QUI::getRewrite()->getProject(); + + return $Project->getConfig($settingName); + } catch (\Exception $Exception) { + QUI\System\Log::writeException($Exception); + + return ''; + } + } } diff --git a/template/topBar.html b/template/topBar.html index 0098f71dc3fa225f8cc33c06a95f61be75eb70ae..3c6d4878b1baddb3ec0ab2a816ce34c3c4e2119e 100644 --- a/template/topBar.html +++ b/template/topBar.html @@ -24,7 +24,7 @@ {/if} {* END language & currency switch *} - <span class="cologne-header-control-user"> + <div class="cologne-header-control-user"> {if $User->getId()} {$Avatar->create()} {else} @@ -34,6 +34,6 @@ <span class="cologne-header-control-user-loader"> <span class="fa fa-pulse fa-circle-o-notch"></span> </span> - </span> + </div> </div> </div> \ No newline at end of file diff --git a/tests/phpstan-bootstrap.php b/tests/phpstan-bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..b61ff4b8300a965e0f46025ba64745a22b118e74 --- /dev/null +++ b/tests/phpstan-bootstrap.php @@ -0,0 +1,13 @@ +<?php + +if (!defined('QUIQQER_SYSTEM')) { + define('QUIQQER_SYSTEM', true); +} + +if (!defined('QUIQQER_AJAX')) { + define('QUIQQER_AJAX', true); +} + +putenv("QUIQQER_OTHER_AUTOLOADERS=KEEP"); + +require_once __DIR__ . '/../../../../bootstrap.php'; diff --git a/tests/phpunit-bootstrap.php b/tests/phpunit-bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..eca92fd67bed8ae4ec424ed82d300119d792f042 --- /dev/null +++ b/tests/phpunit-bootstrap.php @@ -0,0 +1,11 @@ +<?php + +if (!defined('QUIQQER_SYSTEM')) { + define('QUIQQER_SYSTEM', true); +} + +if (!defined('QUIQQER_AJAX')) { + define('QUIQQER_AJAX', true); +} + +require_once __DIR__ . '/../../../../bootstrap.php';