spryker-demo/shop-theme-feature

Shop theme [feature]

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 1

Forks: 0

Type:metapackage

1.0.0 2025-04-09 16:09 UTC

This package is auto-updated.

Last update: 2025-05-22 16:55:29 UTC


README

Minimum PHP Version

Installation

Install feature

composer require spryker-demo/shop-theme-feature

Add SprykerDemo namespace to configuration

$config[KernelConstants::CORE_NAMESPACES] = [
    'SprykerDemo',
     ...
];

Adjust environment config with filesystem

# config/Shared/config_default.php

$config[FileSystemConstants::FILESYSTEM_SERVICE] = [
    ...
    'logo' => [
        'sprykerAdapterClass' => Aws3v3FilesystemBuilderPlugin::class,
        'root' => '',
        'path' => 'sc-b2b/yves/logo/',
        'key' => getenv('AWS_S3_KEY') ?? '',
        'secret' => getenv('AWS_S3_SECRET') ?? '',
        'bucket' => 'spryker-scb2b',
        'version' => '2006-03-01',
        'region' => 'eu-west-2',
    ],
    ...
];

# config/Shared/config_default.php

$config[FileSystemConstants::FILESYSTEM_SERVICE] = [
    ...
    'logo' => [
        'sprykerAdapterClass' => Aws3v3FilesystemBuilderPlugin::class,
        'root' => '',
        'path' => 'sc-b2b/yves/logo/',
        'key' => getenv('AWS_S3_KEY') ?? '',
        'secret' => getenv('AWS_S3_SECRET') ?? '',
        'bucket' => 'spryker-scb2b',
        'version' => '2006-03-01',
        'region' => 'eu-west-2',
    ],
    ...
];

Add default theme logo path to the environment config

# config/Shared/config_default.php

$config[ShopThemeConstants::DEFAULT_LOGO_PATH] = getenv('SHOP_THEME_DEFAULT_LOGO_PATH');

Wire filesystem reader, writer and stream plugins

# src/Pyz/Service/FileSystem/FileSystemDependencyProvider.php

use Spryker\Service\FileSystem\FileSystemDependencyProvider as SprykerFileSystemDependencyProvider;
use Spryker\Service\Flysystem\Plugin\FileSystem\FileSystemReaderPlugin;
use Spryker\Service\Flysystem\Plugin\FileSystem\FileSystemStreamPlugin;
use Spryker\Service\Flysystem\Plugin\FileSystem\FileSystemWriterPlugin;

class FileSystemDependencyProvider extends SprykerFileSystemDependencyProvider
{
    /**
     * @return \Spryker\Service\Flysystem\Plugin\FileSystem\FileSystemReaderPlugin
     */
    protected function getFileSystemReaderPlugin(): FileSystemReaderPlugin
    {
        return new FileSystemReaderPlugin();
    }

    /**
     * @return \Spryker\Service\Flysystem\Plugin\FileSystem\FileSystemWriterPlugin
     */
    protected function getFileSystemWriterPlugin(): FileSystemWriterPlugin
    {
        return new FileSystemWriterPlugin();
    }

    /**
     * @return \Spryker\Service\Flysystem\Plugin\FileSystem\FileSystemStreamPlugin
     */
    protected function getFileSystemStreamPlugin(): FileSystemStreamPlugin
    {
        return new FileSystemStreamPlugin();
    }
}

Wire the Aws S3 plugin

# src/Pyz/Service/FlySystem/FlySystemDependencyProvider.php

use SprykerDemo\Service\FlysystemAws3v3FileSystem\Plugin\Flysystem\Aws3v3FilesystemBuilderPlugin;
...
    protected function addFilesystemBuilderPluginCollection($container): Container
    {
        $container->set(static::PLUGIN_COLLECTION_FILESYSTEM_BUILDER, function (Container $container) {
            return [
                ...
                new Aws3v3FilesystemBuilderPlugin(),
                ...
            ];
        });

        return $container;
    }

Wire the ShopThemeGui plugins

# src/Pyz/Zed/ShopThemeGui/ShopThemeGuiDependencyProvider.php

use Spryker\Zed\StoreGui\Communication\Plugin\Form\StoreRelationDropdownFormTypePlugin;


    protected function getAclEntityConfigurationExpanderPlugins(): FormTypeInterface
    {
        new StoreRelationDropdownFormTypePlugin();
    }

Wire the publisher plugins

# src/Pyz/Zed/Publisher/PublisherDependencyProvider.php

use SprykerDemo\Zed\ShopThemeStorage\Communication\Plugin\Publisher\ShopTheme\ShopThemeStorageDeleteByShopThemeStorePublisherPlugin;
use SprykerDemo\Zed\ShopThemeStorage\Communication\Plugin\Publisher\ShopTheme\ShopThemeStorageDeletePublisherPlugin;
use SprykerDemo\Zed\ShopThemeStorage\Communication\Plugin\Publisher\ShopTheme\ShopThemeStorageWriteByThemeStorePublisherPlugin;
use SprykerDemo\Zed\ShopThemeStorage\Communication\Plugin\Publisher\ShopTheme\ShopThemeStorageWritePublisherPlugin;


    protected function getPublisherPlugins(): array
    {
        return array_merge(
            ...
            $this->getShopThemeStoragePlugins(),
        );
    }

    public function getShopThemeStoragePlugins(): array
    {
        return [
            new ShopThemeStorageDeleteByShopThemeStorePublisherPlugin(),
            new ShopThemeStorageDeletePublisherPlugin(),
            new ShopThemeStorageWriteByThemeStorePublisherPlugin(),
            new ShopThemeStorageWritePublisherPlugin(),
        ];
    }


Wire the Acl plugins

# src/Pyz/Zed/AclMerchantPortal/AclMerchantPortalDependencyProvider.php

use SprykerDemo\Zed\ShopTheme\Communication\Plugin\AclMerchantPortal\ShopThemeAclEntityConfigurationExpanderPlugin;


    protected function getAclEntityConfigurationExpanderPlugins(): array
    {
        return [
            ...
            new ShopThemeAclEntityConfigurationExpanderPlugin(),
        ];
    }

Wire the queue plugin

# src/Pyz/Zed/Queue/QueueDependencyProvider.php

use Spryker\Zed\Synchronization\Communication\Plugin\Queue\SynchronizationStorageQueueMessageProcessorPlugin;
use SprykerDemo\Zed\ShopThemeStorage\ShopThemeStorageConfig;

    protected function getProcessorMessagePlugins(Container $container): array
    {
        return [
            ...
            ShopThemeStorageConfig::SHOP_THEME_SYNC_STORAGE_QUEUE => new SynchronizationStorageQueueMessageProcessorPlugin(),
        ];
    }

Wire the synchronization plugin

# src/Pyz/Zed/Synchronization/SynchronizationDependencyProvider.php

use SprykerDemo\Zed\ShopThemeStorage\Communication\Plugin\Synchronization\ShopThemeSynchronizationDataPlugin;

    protected function getSynchronizationDataPlugins(): array
    {
        return [
            ...
            new ShopThemeSynchronizationDataPlugin(),
        ];
    }

Wire the twig extension plugin

# src/Pyz/Zed/Twig/TwigDependencyProvider.php

use SprykerDemo\Zed\ShopThemeGui\Communication\Plugin\Twig\Buttons\Form\BackofficeLogoTwigExtensionPlugin;
use SprykerDemo\Zed\ShopThemeGui\Communication\Plugin\Twig\Buttons\Form\MPLogoTwigExtensionPlugin;

    protected function getTwigPlugins(): array
    {
        return [
            ...
            new BackofficeLogoTwigExtensionPlugin(),
            new MPLogoTwigExtensionPlugin(),
        ];
    }

Adjust navigation configuration file

# config/Zed/navigation.xml

<?xml version="1.0"?>
<config>
    <administration>
        <pages>
            ...
            <shop-theme-gui>
                <label>Themes</label>
                <title>Themes</title>
                <bundle>shop-theme-gui</bundle>
                <controller>index</controller>
                <action>index</action>
            </shop-theme-gui>
        </pages>
    </administration>
</config>

Adjust RabbitMq configuration

# src/Pyz/Client/RabbitMq/RabbitMqConfig.php

use SprykerDemo\Zed\ShopThemeStorage\ShopThemeStorageConfig;
...

protected function getPyzSynchronizationQueueConfiguration(): array
    {
        return [
            ...
            ShopThemeStorageConfig::SHOP_THEME_SYNC_STORAGE_QUEUE,
        ];
    }

Apply Twig customization

# src/Pyz/Yves/CheckoutPage/Theme/default/templates/page-layout-checkout/page-layout-checkout.twig

                    {% block logo %}
                        <div class="col col--sm-4 text-center">
                            {% if findWidget('ShopThemeWidget') %}
                                {% set shopThemeWidget = findWidget('ShopThemeWidget') %}
                            {% endif %}

                            {% include molecule('logo') with {
                                attributes: {
                                    src: shopThemeWidget.data.logoUrl ?? null,
                                },
                            } only %}
                        </div>
                    {% endblock %}

#src/Pyz/Yves/ShopUi/Theme/default/components/organisms/header/header.twig

                 {% block logo %}
                     {% include molecule('logo') with {
                         class: 'col ' ~  config.name ~ '__logo',
                         modifiers: ['main'],
                     } only %}
                 {% endblock %}

#src/Pyz/Yves/ShopUi/Theme/default/templates/page-layout-main/page-layout-main.twig

{% block headStyles %}
    {{ parent() }}

    {% if findWidget('ShopThemeWidget') %}
        {% widget 'ShopThemeWidget' only %}{% endwidget %}
    {% endif %}
{% endblock %}
...
{% block body %}

    {% if findWidget('ShopThemeWidget') %}
        {% set shopThemeWidget = findWidget('ShopThemeWidget') %}
    {% endif %}
    ...
                 {% block logo %}
                     {% include molecule('logo') with {
                         class: 'col ' ~  config.name ~ '__logo',
                         modifiers: ['main'],
                         attributes: {
                             src: embed.logoSrc,
                         }
                     } only %}
                 {% endblock %}

#src/Pyz/Zed/Gui/Presentation/Partials/menu.twig

{%- macro leaf(node, depth=0) -%}
    {%- import _self as menu -%}

    {%- if node is defined %}
        {%- if menu_highlight is defined -%}
            {%- if menu_highlight == node.uri -%}
                <li class="item active">
            {%- else -%}
                <li class="item">
            {%- endif -%}
        {%- else-%}
            <li class="item{{ node.is_active is defined and node.is_active ? " active" : "" }}">
        {%- endif -%}
        <a href="{{ node.uri }}"{% if node.shortcut is defined %} data-hotkey="{{ node.shortcut }}"{% endif %}>
            {{ menu.getNodeIcon(node) }}
            <span class="nav-label">{{ node.label | trans }}</span>
        </a>
        </li>
    {% endif -%}
{%- endmacro -%}

{%- macro branch(node, depth=0) -%}
    {%- import _self as menu -%}

    {%- if node is defined %}
        <li class="{{ node.is_active is defined and node.is_active ? " active" : "" }}">
            <a href="javascript:void(0)">
                {{ menu.getNodeIcon(node) }}
                <span class="nav-label">{{ node.label | trans }}</span>
                <span class="fa arrow"></span>
            </a>

            <ul class="nav nav-second-level collapse">
                {{ menu.tree(node.children, (depth + 1)) }}
            </ul>
        </li>
    {% endif -%}
{%- endmacro -%}

{%- macro tree(root) -%}
    {%- import _self as menu -%}

    {%- for child in root -%}
        {%- if child.children is defined and child.children is not empty -%}
            {{ menu.branch(child, 0) }}
        {%- else -%}
            {{ menu.leaf(child, 0) }}
        {%- endif -%}
    {%- endfor -%}
{%- endmacro -%}

{%- macro getNodeIcon(node) -%}
    {%- set defaultIcon = 'fa-angle-double-right' -%}
    {%- if node.icon is defined and node.icon != '' -%}
        <i class="fa {{ node.icon }}"></i>
    {%- else -%}
        <i class="fa {{ defaultIcon }}"></i>
    {%- endif -%}
{%- endmacro -%}

{%- import _self as menu -%}
<nav class="navbar-default navbar-static-side" role="navigation">
    <div class="sidebar-collapse">
        <ul tabindex="0" class="nav metismenu" id="side-menu">
            <li class="nav-header">
                <div class="dropdown profile-element">

                    {{ backofficeLogo() }}

                    <ul class="dropdown-menu animated fadeInRight m-t-xs">
                        <li><a href="/auth/logout">{{ 'Logout' | trans }}</a></li>
                    </ul>
                </div>
                <div class="logo-element">
                    SP
                </div>
            </li>
            {{ menu.tree(navigation.menu) }}
        </ul>
    </div>
</nav>

#src/Pyz/Zed/SecurityGui/Presentation/Layout/layout.twig

<!DOCTYPE html>
 <html>
 <head>

     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">

     <title>{% block head_title %}{% if title is defined %}{{ title | trans }}{% endif %}{% endblock %}</title>

     {% block head_css %}
         <link rel="stylesheet" href="{{ assetsPath('css/spryker-zed-gui-commons.css') }}">
         <link href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700;900&family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
     {% endblock %}

 </head>
 <body class="login">

 <div class="login__wrapper">
     <div class="login__container">
         {{ backofficeLogo('login__logo') }}

         {% include '@Messenger/Partials/flash-messages.twig' %}

         <div class="login-box">
             {% block login_heading %}
                 <div class="login-box__heading">
                     <h1 class="login-box__title">{{ 'Login' | trans }}</h1>
                 </div>
             {% endblock %}
             <div class="login-box__content">
                 {% block content %}{% endblock %}
             </div>
         </div>
     </div>
 </div>

 {% block footer_js %}
     <script src="{{ assetsPath('js/spryker-zed-gui-commons.js') }}"></script>
 {% endblock %}

 </body>
 </html>

 #src/Pyz/Zed/ZedUi/Presentation/Layout/merchant-layout-centered.twig

 {% extends '@ZedUi/Layout/merchant-layout.twig' %}

 {% block body %}
    {{ mpLogo() }}
    <web-mp-merchant-layout-centered cloak>
        {% block content %}{% endblock %}

        {% block footer %}
            <span footer>Copyright Spryker Systems GmbH © {{ 'now' | date('Y') }}</span>
        {% endblock %}
    </web-mp-merchant-layout-centered>
 {% endblock %}

 #src/Pyz/Zed/ZedUi/Presentation/Layout/merchant-layout-main.twig

 {% extends '@ZedUi/Layout/merchant-layout.twig' %}

 {% block body %}
    {{ mpLogo() }}
    {% if app.twig.getFunction('navigation') != false %}
        {% set navigationConfig = render_navigation_component_config(navigation('main').menu) %}
        {% set userMenuNavigationItems = navigation('secondary').menu %}

        {% block merchantLayoutMain %}
            <web-mp-merchant-layout-main cloak navigation-config="{{ navigationConfig }}">
                {% block logo %}
                    <web-spy-logo cloak logo></web-spy-logo>
                {% endblock %}

                {% block header %}
                    <header header>
                        {% block headerMenu %}
                            <web-mp-header-menu cloak menu>
                                {% block infoPrimary %}
                                    {% if username is not empty %}
                                        <span info-primary>{{ username }}</span>
                                    {% endif %}
                                {% endblock %}

                                {% block infoSecondary %}
                                    {% if userEmail is not empty %}
                                        <span info-secondary>{{ userEmail }}</span>
                                    {% endif %}
                                {% endblock %}

                                {% block userMenuList %}
                                    {% for userMenuNavigationItem in userMenuNavigationItems %}
                                        {% block userMenuLink %}
                                            <a href="{{ userMenuNavigationItem.uri }}" class="user-menu-link">
                                                {% block userMenuLinkInner %}
                                                    {{ userMenuNavigationItem.title }}
                                                {% endblock %}
                                            </a>
                                        {% endblock %}
                                    {% endfor %}

                                    {% block logoutLink %}
                                        <a href="/security-merchant-portal-gui/logout" class="user-menu-link user-menu-link--danger">
                                            {% block logoutLinkInner %}
                                                {{ 'Logout' | trans }}
                                            {% endblock %}
                                        </a>
                                    {% endblock %}
                                {% endblock %}
                            </web-mp-header-menu>
                        {% endblock %}
                    </header>
                {% endblock %}

                {% block flashMessages %}
                    {% include '@ZedUi/Partials/FlashMessages/flash-messages.twig' %}
                {% endblock %}

                {% block content %}{% endblock %}
            </web-mp-merchant-layout-main>
        {% endblock %}
    {% endif %}
 {% endblock %}

Add behaviors to the database definition schemas

#src/Pyz/Zed/ShopTheme/Persistence/Propel/Schema/spy_shop_theme.schema.xml

<?xml version="1.0"?>
<database xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          name="zed"
          xsi:noNamespaceSchemaLocation="http://static.spryker.com/schema-01.xsd"
          namespace="Orm\Zed\ShopTheme\Persistence"
          package="src.Orm.Zed.ShopTheme.Persistence">

    <table name="spy_shop_theme">
        <behavior name="event">
            <parameter name="spy_shop_theme_all" column="*"/>
        </behavior>
    </table>

    <table name="spy_shop_theme_store">
        <behavior name="event">
            <parameter name="spy_shop_theme_store_all" column="*"/>
        </behavior>
    </table>

</database>