Skip to content

Commit

Permalink
[DOCS] Add tutorial section
Browse files Browse the repository at this point in the history
Add tutorial section which contains hints/examples
how to setup details of the extension:

* Integration of miniCart
* Prefill address fields from FE user.
* Routing for multistep checkout.
* Product images in cart.

Fixes: extcode#534
  • Loading branch information
rintisch committed Oct 2, 2024
1 parent 8315619 commit 8915b9a
Show file tree
Hide file tree
Showing 7 changed files with 312 additions and 26 deletions.
27 changes: 1 addition & 26 deletions Documentation/Editor/Plugins/Index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,7 @@ Plugin "Cart: Mini Cart"

This plugin can be included as mini cart and gives a shortened view of the cart.

An option to add this plugin is via TypoScript as shown below:

.. code-block:: typoscript
:caption: EXT:sitepackage/Configuration/TypoScript/setup.typoscript
lib.miniCart = COA_INT
lib.miniCart {
10 = USER_INT
10 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
extensionName = Cart
pluginName = MiniCart
vendorName = Extcode
}
}
This TypoScript object can then be used within a Fluid template:

.. code-block:: html
:caption: e.g. EXT:sitepackage/Resources/Private/Partials/Header.html

<header>
<!-- Other elements within your header ... -->
<f:cObject typoscriptObjectPath="lib.miniCart"/>
</header>

For an example of an implementation see :ref:`Integrate a MiniCart <minicart>`.

.. _plugin_cart_orders:

Expand Down
5 changes: 5 additions & 0 deletions Documentation/Index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ extendable shop solution for TYPO3.

Information about existing events to extend functionality.

.. card:: :ref:`Tutorials <tutorials>`

Tutorials for a smooth setup of the extension.

.. card:: :ref:`FAQ <faq>`

Answers to frequently asked questions.
Expand All @@ -94,5 +98,6 @@ extendable shop solution for TYPO3.
Administrator/Index
Developer/Index
Editor/Index
Tutorials/Index
Faq/Index
Changelog/Index
92 changes: 92 additions & 0 deletions Documentation/Tutorials/ImagesInCart/Index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
.. include:: ../../Includes.rst.txt


.. _images-cart-product-list:

=======================================
Images of products in cart product list
=======================================

Usually the cart of online shops shows a small image in the product list.
EXT:cart does this not by default because the use cases for the extension can be
quite diverse and a standard might not fit everyone.

It's easy to implement this functionality with an EventListener and a customized
partial.

The following snippets show an example where the first image of a product is
used:

.. code-block:: php
:caption: EXT:cartintegration/Classes/EventListener/ExtendCartProduct.php
<?php
declare(strict_types=1);
namespace Vendor\Cartintegration\EventListener\Cart\Create;
use Extcode\CartProducts\Event\RetrieveProductsFromRequestEvent;
class ExtendCartProduct
{
public function __invoke(RetrieveProductsFromRequestEvent $event): void
{
$productProduct = $event->getProductProduct();
$cartProduct = $event->getCartProduct();
// Using null safe operator to avoid errors
$imageUid = $productProduct?->getFirstImage()?->getOriginalResource()?->getOriginalFile()?->getUid() ?? null;
if ($imageUid) {
$cartProduct->setAdditional(
'previewImage',
$imageUid
);
}
}
}
.. code-block:: yaml
:caption: EXT:cartintegration/Configuration/Services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
Vendor\Cartintegration\:
resource: '../Classes/*'
exclude: '../Classes/Domain/Model/*'
Vendor\Cartintegration\EventListener\Cart\ExtendCartProduct:
tags:
- name: event.listener
.. code-block:: yaml
:caption: EXT:cartintegration/Resources/Private/Plugins/Cart/Partials/Cart/ProductForm/ProductList.html
// This snippet is simplified and needs adaption for your styling!
<f:section name="withoutVariant">
...
<f:if condition="{product.additionalArray.previewImage}">
<f:image src="{product.additionalArray.previewImage}"/>
</f:if>
...
<f:section name="withVariant">
...
<f:for each="{product.beVariants}" as="variant">
<f:if condition="{product.additionalArray.previewImage}">
<f:image src="{product.additionalArray.previewImage}"/>
</f:if>
...
39 changes: 39 additions & 0 deletions Documentation/Tutorials/Index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.. include:: ../Includes.rst.txt

.. _tutorials:

============
Tutorials
============

.. card-grid::
:columns: 1
:columns-md: 2
:gap: 4
:class: pb-4
:card-height: 100

.. card:: :ref:`Integrate MiniCart <minicart>`

A way to integrate the MiniCart on every page.

.. card:: :ref:`Prefill address fields for Frontend user <prefill-address>`

Prefill address fields with data of an logged-in Frontend user.

.. card:: :ref:`Images of products in the cart <images-cart-product-list>`

A way to render an image of a product in the cart product list.

.. card:: :ref:`Routing for multistep checkout <routing-multistep-checkout>`

A possible setup for routing in multistep checkout

.. toctree::
:maxdepth: 1
:titlesonly:

MiniCart/Index
PrefillAddress/Index
ImagesInCart/Index
RoutingMultistepCheckout/Index
42 changes: 42 additions & 0 deletions Documentation/Tutorials/MiniCart/Index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.. include:: ../../Includes.rst.txt

.. _minicart:

====================
Integrate a MiniCart
====================

:aspect:`Context:`
MiniCart is the (usually tiny) icon somewhere in the header of all pages which
shows how many items the customer has in the cart and which links the cart
itself.

.. NOTE::
The following example will result in a page that is not fully cached.
To get a fully cached site you would need to get the data via AJAX request.
Have a look at :composer:`studiomitte/cart-count`.

.. code-block:: typoscript
:caption: EXT:cartintegration/Configuration/TypoScript/setup.typoscript
lib.miniCart = COA_INT
lib.miniCart {
10 = USER_INT
10 {
userFunc = TYPO3\CMS\Extbase\Core\Bootstrap->run
extensionName = Cart
pluginName = MiniCart
vendorName = Extcode
}
}
.. code-block:: html
:caption: EXT:sitepackage/Resources/Partials/Header.html

<header>
...
<!-- Somewhere in the header of your page -->
<f:cObject typoscriptObjectPath="lib.miniCart"/>

...
<header>
76 changes: 76 additions & 0 deletions Documentation/Tutorials/PrefillAddress/Index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
.. include:: ../../Includes.rst.txt


.. _prefill-address:

========================================
Prefill address fields for Frontend user
========================================

The billing address during the checkout can be prefilled for a logged-in
Frontend user. You have to register a EventListener which listens to the event
`Extcode\Cart\Event\Cart\BeforeShowCartEvent`.

The following snippets show an example:

.. code-block:: php
:caption: EXT:cartintegration/Classes/EventListener/BeforeShowCart.php
<?php
declare(strict_types=1);
namespace Vendor\Cartintegration\EventListener\Cart;
use Extcode\Cart\Event\Cart\BeforeShowCartEvent;
use TYPO3\CMS\Frontend\Authentication\FrontendUserAuthentication;
final class BeforeShowCart
{
public function __invoke(BeforeShowCartEvent $event): void
{
$frontendUser = $this->getFrontendUserAuthenticationFromRequest();
// Hint: The property `user` is marked as internal but it works.
if (!$frontendUser->user) return;
$billingAddress = $event->getBillingAddress();
if ($billingAddress !== null) {
$billingAddress->setFirstName($frontendUser->user['first_name'] ?? '');
$billingAddress->setLastName($frontendUser->user['last_name'] ?? '');
$billingAddress->setEmail($frontendUser->user['email'] ?? '');
$billingAddress->setStreet($frontendUser->user['address'] ?? '');
$billingAddress->setZip($frontendUser->user['zip'] ?? '');
$billingAddress->setCity($frontendUser->user['city'] ?? '');
// Default to Germany if no country stored in database
$billingAddress->setCountry($frontendUser->user['country'] ?? 'DE');
}
}
private function getFrontendUserAuthenticationFromRequest(): FrontendUserAuthentication
{
$request = $GLOBALS['TYPO3_REQUEST'];
return $request->getAttribute('frontend.user');
}
}
.. code-block:: yaml
:caption: EXT:cartintegration/Configuration/Services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
Vendor\Cartintegration\:
resource: '../Classes/*'
exclude: '../Classes/Domain/Model/*'
Vendor\Cartintegration\EventListener\Cart\BeforeShowCart:
tags:
- name: event.listener
57 changes: 57 additions & 0 deletions Documentation/Tutorials/RoutingMultistepCheckout/Index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.. include:: ../../Includes.rst.txt

.. _routing-multistep-checkout:

==============================
Routing for multistep checkout
==============================

The multistep checkout need routeEnhancers for readable urls.

The following example show a multi language snippet.

.. note::
Unfortunately it's not
perfect as the final url `thank-you-for-your-order` is used even if the last
step results in errors. In this case the url-segment `checkout` should be
used but it's not. Otherwise it's working as expected.

.. code-block:: yaml
:caption: config/sites/your-page/config.yaml
routeEnhancers:
Cart:
type: Extbase
limitToPages:
- 123 // PID where the cart plugin is located
extension: Cart
plugin: Cart
routes:
- routePath: '/{localized_thanks}'
_controller: 'Cart\Order::create'
- routePath: '/{step}'
_controller: 'Cart\Cart::show'
_arguments:
product-title: product
defaultController: 'Cart\Cart::show'
aspects:
localized_thanks:
type: LocaleModifier
default: 'thank-you-for-your-order'
localeMap:
- locale: 'de_.*'
value: 'danke-fuer-deine-bestellung'
step:
type: StaticValueMapper
map:
products: 1
address: 2
shipping-and-payment: 3
checkout: 4
localeMap:
- locale: 'de_.*'
map:
artikel: 1
adresse: 2
versand-zahlmethode: 3
pruefung: 4

0 comments on commit 8915b9a

Please sign in to comment.