In this guide we provide you with all essential information you need to keep your plugins Shopware 5.3 compatible.
To migrate the bootstrap.php we create a new plugin base file which has the technical name of the plugin.
Make sure the namespace and the class is called like the technical name of your plugin.
Extend the class from Shopware\Components\Plugin\Plugin
.
<?php
namespace SwagUpdatePlugin;
use Shopware\Components\Plugin;
class SwagUpdatePlugin extends Plugin
{
public function activate(ActivateContext $context)
{
$context->scheduleClearCache(InstallContext::CACHE_LIST_DEFAULT);
}
}
To ensure your templates files are extensible, neither extendsTemplate nor extendsBlock methods should be used for responsive template. Instead, you should use Shopware's auto loading mechanism. The following example shows how template extension plugins need to be updated to achieve the best possible result for Shopware 5.3 templates. The following source code displays a top seller slider and a banner in the product detail page:
Use the early "Enlight_Controller_Action_PreDispatch" event to register the template directory of your plugin.
<?php
namespace SwagUpdatePlugin\Subscriber;
use Enlight\Event\SubscriberInterface;
use Enlight_Template_Manager;
class TemplateRegistration implements SubscriberInterface
{
/**
* @var Enlight_Template_Manager
*/
private $templateManager;
/**
* @var string
*/
private $pluginBaseDirectory;
/**
* @param Enlight_Template_Manager $templateManager
* @param string $pluginBaseDirectory
*/
public function __construct(Enlight_Template_Manager $templateManager, $pluginBaseDirectory)
{
$this->templateManager = $templateManager;
$this->pluginBaseDirectory = $pluginBaseDirectory;
}
/**
* Use the early "Enlight_Controller_Action_PreDispatch" event to register the template directory of the plugin.
*
* @inheritdoc
*/
public static function getSubscribedEvents()
{
return [
'Enlight_Controller_Action_PreDispatch' => 'onPreDispatch'
];
}
public function onPreDispatch()
{
$this->templateManager->addTemplateDir($this->pluginBaseDirectory . '/Resources/views');
}
}
Register the event subscriber file by using the services.xml
. To register a event subscriber use the "shopware.event_subscriber" tag.
/.../SwagUpdatePlugin/Resources/services.xml
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="swag_update_plugin.subscriber.template_registration"
class="SwagUpdatePlugin\Subscriber\TemplateRegistration">
<argument type="service" id="template"/>
<argument>%swag_update_plugin.plugin_dir%</argument>
<tag name="shopware.event_subscriber"/>
</service>
</services>
</container>
The goal is to make this plugin compatible with the new Shopware 5 templates. For this purpose, the following should be considered:
Inside the PostDispatch event, we have to load the corresponding template files.
The extendsTemplate function should not be used in the new template, otherwise the plugin template cannot be overwritten by other templates.
In order for the plugin template to be easily extended by others, the template adjustments should be extracted into a separate file.
First, the template structure is revised. The example1.tpl file is now divided into two new files:
*SwagExample1/Resources/views/frontend/detail/index.tpl (Entry point to extend the template)
*SwagExample1/Resources/views/frontend/swag_example1/detail_extension.tpl (Contains the source code for the extension)
The new files contain the following source code:
/.../SwagUpdatePlugin/Resources/views/frontend/detail/index.tpl
{extends file="parent:frontend/detail/index.tpl"}
{block name="frontend_detail_index_detail"}
{include file="frontend/swag_example1/detail_extension.tpl"}
{/block}
/.../SwagUpdatePlugin/Resources/views/frontend/swag_example1/detail_extension.tpl
{block name="frontend_detail_example"}
<div class="example--own-topseller">
{block name="frontend_detail_example_headline"}
<h1 class="own-topseller--headline">My topseller</h1>
{/block}
{block name="frontend_detail_example_img"}
<img class="own-topseller--img" src="{link file={$mediaSelection}}" alt="Test" />
{/block}
{block name="frontend_detail_example_topseller"}
<div class="own-topseller--container">
{action module=widgets controller=listing action=top_seller sCategory=3}
</div>
{/block}
</div>
{/block}
Notice: Template extensions for the responsive template are loaded via the inheritance hierarchy based on the file system. Therefore, this template should be extends via {extends file = ".."}.
The SwagExample1/Resources/views/frontend/detail/index.tpl file serve only as entry points into the original template. The source code for displaying the top seller sliders and the banner element, which was previously located directly in the extended template file, has now been made available globally in a separate template file, and is now simply included by the template. This has the following advantages:
Avoid duplicate source code
Extensible plugin template for other developers
Notice: To allow other templates to easily extend your templates, you should provide your code in a separate file. Include that file in other templates, inside Smarty blocks, thus allowing different entry point.
For adding plugin configuration you add a new xml file to the Resources directory.
/.../SwagUpdatePlugin/Resources/config.xml
<?xml version="1.0" encoding="utf-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/shopware5/shopware/5.3/engine/Shopware/Components/Plugin/schema/config.xsd">
<elements>
<element type="mediaselection">
<name>mediaSelection</name>
<label lang="de">Bildauswahl</label>
<label lang="en">MediaSelection</label>
</element>
</elements>
</config>
Add a new element of the type mediaselection
, set the name and the label.
For more information about plugin configuration have a look here.
Now we can read the configuration from the the DBALConfigReader
and assign the value to the view.
For this we create a new subscriber file called DetailSubscriber. In this file, we register the 'Enlight_Controller_Action_PostDispatchSecure_Frontend_Detail' event and append our configurations variable to the view.
/.../SwagUpdatePlugin/Resources/services.xml
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="swag_update_plugin.subscriber.template_registration"
class="SwagUpdatePlugin\Subscriber\TemplateRegistration">
<argument type="service" id="template"/>
<argument>%swag_update_plugin.plugin_dir%</argument>
<tag name="shopware.event_subscriber"/>
</service>
<service id="swag_update_plugin.subscriber.detail_subscriber"
class="SwagUpdatePlugin\Subscriber\DetailSubscriber">
<argument type="service" id="shopware.plugin.config_reader"/>
<argument>%swag_update_plugin.plugin_name%</argument>
<tag name="shopware.event_subscriber"/>
</service>
</services>
</container>
/.../SwagUpdatePlugin/Subscriber/DetailSubscriber.php
<?php
namespace SwagUpdatePlugin\Subscriber;
use Enlight\Event\SubscriberInterface;
use Shopware\Components\Plugin\DBALConfigReader;
class DetailSubscriber implements SubscriberInterface
{
/**
* @var DBALConfigReader
*/
private $configReader;
/**
* @var string
*/
private $pluginName;
/**
* @param DBALConfigReader $configReader
* @param $pluginName
*/
public function __construct(DBALConfigReader $configReader, $pluginName)
{
$this->configReader = $configReader;
$this->pluginName = $pluginName;
}
public static function getSubscribedEvents()
{
return [
'Enlight_Controller_Action_PostDispatchSecure_Frontend_Detail' => 'onPostDispatchFrontendDetail'
];
}
public function onPostDispatchFrontendDetail(\Enlight_Event_EventArgs $args)
{
/** @var \Shopware_Controllers_Frontend_Detail $subject */
$subject = $args->get('subject');
$config = $this->configReader->getByPluginName($this->pluginName);
$subject->View()->assign('mediaSelection', $config['mediaSelection']);
}
}
During the uninstall process, the user will now be prompted which data he wishes to remove.
Existing uninstall() method should remove all data.
Use the UninstallContext
which contains the keepUserData() method. If the return value is true
you should only remove non-user related data.
<?php
namespace SwagUpdatePlugin; // Set the namespace like the technical name of your plugin
use Shopware\Components\Plugin;
use Shopware\Components\Plugin\Context\ActivateContext;
use Shopware\Components\Plugin\Context\UninstallContext;
// Call the class and file like the technical name of your plugin and extend from Shopware\Components\Plugin\Plugin
class SwagUpdatePlugin extends Plugin
{
public function activate(ActivateContext $context)
{
$context->scheduleClearCache(InstallContext::CACHE_LIST_DEFAULT);
}
public function uninstall(UninstallContext $context)
{
if ($context->keepUserData()) {
return;
}
// Delete all data.
}
}
Less and Js file registration will be done automatically. Just place the resources into the following directories:
/.../SwagUpdatePlugin/Resources/frontend/css/**.css
/.../SwagUpdatePlugin/Resources/frontend/js/**.js
/.../SwagUpdatePlugin/Resources/frontend/less/all.less
The css and js directories may contain arbitrary sub directories. @imports in all.less will be resolved.
Besides traditional CSS, Shopware 5 includes Less support in new templates. Less is a CSS pre-processor, which can be used when styling your Shopware 5 templates. Less is a very powerful tool, and Shopware 5 extends its default feature set by adding some commonly used functions.
For more information on how to use Less, have a look here.
Like in the example above, in most cases there is only one .less file to compile - the all.less. It includes additional files named by their content. Most likely the all.less file includes the modules.less and variables.less files, which are often needed by default. These files include additional files from same named directories, e.g. modules.less includes files from the directory called "_modules/".
As an example, if the file contains styles for Shopware's checkout page, it would be called "checkout.less" and place in the _modules directory. The files inside ___variables/__ should only contain variable definitions made in Less.
Directory/File | Utility |
---|---|
_modules | Contains less styles of modules |
_variables | Contains less variables |
all.less | Includes "modules.less" and "variables.less" |
modules.less | Includes all files in "_modules" |
variables.less | Includes all files in "_variables" |
@import "modules";
@import "_modules/checkout";
.yourOwnSelector {
width: 100%;
}
Our responsive template uses media queries with specific breakpoint, so you can implement different styles for different browser window sizes.
@phoneLandscapeViewportWidth: 30em; // 480px
@tabletViewportWidth: 48em; // 768px
@tabletLandscapeViewportWidth: 64em; // 1024px
@desktopViewportWidth: 78.75em; // 1260px
.myOwnElement {
width: 90%;
}
@media screen and (min-width: @tabletViewportWidth) {
.myOwnElement {
width: 70%;
}
}
Each child theme of the Shopware responsive template has access to some very useful mixins like '.unitize()' or '.clearfix()' A mixin is a useful function being used in our .less files. E.g. our new "unitize" mixin can be used to calculate rem values, which we use in our new template, replacing px values.
.myOwnElement {
//Would output font-size: 0.625rem;
//First parameter is your desired px value, in this case 10px.
//Second parameter is the base value which, in this case, means the default font-size of 16px.
//You won't have to change the second parameter in most of the cases. The .unitize-method now calculates 10/16 = 0.625.
//Third parameter is the actual style to be used
.unitize(10, 16, font-size);
//For more examples of "unitize" mixin usage, please refer to yourShopSystem/Themes/Frontend/Responsive/frontend/_public/src/less/_mixins/unitize.less
}
In Themes/Frontend/Responsive/frontend/_public/src/less/_mixins you can find other useful mixins provided by Shopware 5.
If you want to display message to the shop customer, you can use the messages template file. Examples:
{include file="frontend/_includes/messages.tpl" type="success" content="{s name='PasswordInfoSuccess'}{/s}"}
{include file="frontend/_includes/messages.tpl" type="warning" content="{s name='OrdersInfoEmpty'}{/s}"}
{include file="frontend/_includes/messages.tpl" type="error" content="{s name='BlogInfoFailureFields'}{/s}"}
Additional documentation can be found in Themes/Frontend/Bare/frontend/_includes/messages.tpl.
Shopware 5 already includes several jQuery plugins you can use to implement useful features, like sliders or search fields. All of these can be found in the 'Themes/Frontend/Responsive/frontend/_public/src/js/' directory.
If you want to write your own jQuery plugin, you should use our new plugin base class. It provides all the basic operations every jQuery plugin needs to have.
// Register your plugin
$.plugin('yourName', {
defaults: { exampleValue: 'value' },
init: function() {
// ...initialization code
//The applyDataAttributes function merges data attributes into plugin options. Example element: <div class="test" data-exampleValue="value2"></div>
//The default "exampleValue" variable will be overwritten with "value2".
//This value is then available in this.opts.exampleValue variable
this.applyDataAttributes();
},
destroy: function() {
// ...your destruction code
// Use the force! Use the internal destroy method.
me._destroy();
}
});
// Call the plugin
$('.test').yourName();
In Shopware 5, Javascript files are no longer parsed by Smarty. To assign a Smarty variable value to a Javascript variable, use the HTML5 Data attributes (accessible in Javascript with "me.applyDataAttributes()"). Refer to the previous code snippet for an usage example.
Implement as many (useful) Smarty blocks as possible, so your templates are extensible.
In listings, you should use the new listing logic (Conditions, ConditionHandler, Facet, FacetHandler, etc.). Keep the required additional data in mind, e.g. the new view variable "pageSizes".
For more information about the searchBundle, have a look here
For further questions you should read the complete Shopware 5 upgrade guide.