SlideShare a Scribd company logo
1 of 30
Download to read offline
Developing a Sticker plug-in
Sticker plug-in for Magento 2
Best practice
Giorgio Bignozzi
Technical Manager | Marketing Informatico
https://www.marketinginformatico.it
@GiorgioBignozzi
Michele Fantetti
Magento Developer at Maggioli Editore
http://www.fantetti.net
@WaP_oNe
Who we are
Abstract:
Our aim was to create an extension that adds the classical label to the product image in the
different layouts concerning products (product page, category page, related products,
upsell products, cross-sell products, widget, search results).
Goals:
• To create two labels (“Discount” and “New”) with different shapes and positions
• To have a separate graphic management of these labels (custom label or image). If you
choose a custom label, you can set two labels with a configurable text, text colour and
background colour
• To display the label on sale products or products associated to certain categories
(“Discount”)
• To display the label on products associated to certain categories (“New”)
• To enable/disable automatically (with programmable date and time) one or both the
stickers.
Our project: Stickers
Desiderata: category page
Desiderata: product page
Desiderata: widget
Desiderata: related / cross-sell / upsell
Desiderata: search results
• ISSUE #1: how to add the label (HTML code) without modifying layout files in
multiple pages and making the plugin independent
• SOLUTION #1: when rendering product attributes, upload HTML code that will
be completed lately via script JS.
• ISSUE #2: how and where to insert this HTML code
• SOLUTION #2: thanks to Magento 2 PLUGIN, beforeGetProductPrice() and
afterGetProductPrice().
Development: problems and solutions (1)
• ISSUE #3: how to insert extra code to this HTML code
• SOLUTION #3: requireJS
• ISSUE #4: enable/disable some configurable fields depending on which fields
you have valued before
• SOLUTION #4: upload a JS in the layout of the configuration page of the plugin
Development: problems and solutions (2)
File System: M1 VS M2
Differences in file
system organization
in M1 e M2
(Vanilla installation)
• registration.php
• etc/module.xml
Development: M1 vs M2 structure for plug-in registration
In M2 we need to modify only
one folder (app/code)
app/code/Mainf/Stickers/Model/Stickers.php
It manages every feature of the sticker (isInCategory(), isDiscounted(),
getDiscountAmount() etc.) in addition to inserting HTML code:
protected function _getHTML($stickerLayoutType, $class, $firstLabel = '', $secondLabel = '') {
switch ($stickerLayoutType) {
case self::STICKER_IMAGE:
$html = "<input type='hidden' class='".$class."' value='1' />";
break;
case self::STICKER_AREA:
$html = "<input type='hidden' class='".$class."' value='" . $this->getConfigValue($firstLabel) . "<br
/>" . $this->getConfigValue($secondLabel) . "' />";
break;
case self::STICKER_CALCULATED:
$html = "<input type='hidden' class='".$class."' value='" . $this->getDiscountAmount() . "' />";
break;
default:
$html = "<input type='hidden' class='".$class."' value='1' />";
break;
}
return $html;
}
Development : model class Stickers
app/code/Mainf/Stickers/Plugin/ProductStickersPlugin.php
namespace MainfStickersPlugin;
class ProductStickersPlugin extends MainfStickersModelStickers
{
const DISCOUNT_ACTIVATION = "stickers/stickers_discount_page/discount_activation";
const LATEST_ACTIVATION = "stickers/stickers_latest_page/latest_activation";
public function beforeGetProductPrice(
MagentoCatalogBlockProductAbstractProduct $abstractProduct,
MagentoCatalogModelProduct $product
) {
$this->_product = $product;
}
public function afterGetProductPrice(MagentoCatalogBlockProductAbstractProduct $product, $result)
{
if($this->isStickerActive(self::DISCOUNT_ACTIVATION)) {
$result .= $this->_setDiscountStickerHTML();
}
if($this->isStickerActive(self::LATEST_ACTIVATION)) {
$result .= $this->_setLatestStickerHTML();
}
return $result;
}
}
Development : PLUGIN (Dependency Injection)
app/code/Mainf/Stickers/view/frontend/layout/default.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<head>
<css src="Mainf_Stickers::css/mainf-stickers.css"/>
<link src="https://fonts.googleapis.com/css?family=Oswald:400,700,300" rel="stylesheet" type="text/css"
src_type="url" />
</head>
<body>
<referenceContainer name="content">
<block name="category.discount.sticker" class="MainfStickersBlockDiscount"
template="Mainf_Stickers::categoryDiscount.phtml" cacheable="false" after="-" />
<block name="category.latest.sticker" class="MainfStickersBlockLatest"
template="Mainf_Stickers::categoryLatest.phtml" cacheable="false" after="-" />
</referenceContainer>
</body>
</page>
Other layout files: catalog_product_view.xml e checkout_cart_index.xml
Development: layout
app/code/Mainf/Stickers/view/frontend/templates/categoryDiscount.phtml
if($block->isDiscountActive()):
$discountImage = "<div class='mainf-sticker-wrapper top-right'>";
$discountImage .= "<img class='categoryDiscountImage' alt='".__('Discount')."' src='".$this-
>getUrl('pub/media')."mainf/stickers/images/".$block->getStickerImage()."' />";
$discountImage .= "</div>";
$discountArea = "<div class='mainf-sticker-wrapper top-right'>";
$discountArea .= "<div class='mainf-sticker discount-product' style='background-color: #".$block->getStickerBackground()."; color: #".$block-
>getStickerText().";'></div>";
$discountArea .= "</div>";
?>
Development: template
<script type="text/x-magento-init">
{
"*":{
"categoryPageDiscount":{
"imageTag": {
"discountImage": "<?php /* @escapeNotVerified */ echo $discountImage; ?>",
"discountArea": "<?php /* @escapeNotVerified */ echo $discountArea; ?>"
}}}}
</script>
<?php
endif;
app/code/Mainf/Stickers/view/frontend/requirejs-config.js
var config = {
map: {
'*': {
categoryPageDiscount: 'Mainf_Stickers/js/categoryPageDiscount',
categoryPageLatest: 'Mainf_Stickers/js/categoryPageLatest',
viewPageDiscount: 'Mainf_Stickers/js/viewPageDiscount',
viewPageLatest: 'Mainf_Stickers/js/viewPageLatest'
}
}
};
Development: RequireJS (1)
app/code/Mainf/Stickers/view/frontend/web/js/categoryPageDiscount.js
define(
['jquery'],
function ($) {
$.widget(
'mainf.categoryPageStickers',
{
_create: function () {
var self = this;
$(".categoryPageDiscount").each(function () {
if ($(this).val() == 1) {
$($(this).parent().parent().find("a").find("span").find("span"))
.prepend(self.options.imageTag.discountImage);
} else {
var discountAmount = $(this).val();
$($(this).parent().parent().find("a").find("span").find("span"))
.prepend(self.options.imageTag.discountArea);
$(".discount-product").html(discountAmount);
}
});
}
}
);
return $.mainf.categoryPageStickers;
}
);
Development: RequireJS (2)
Backend: module configuration & customization (1)
Backend: module configuration & customization (2)
app/code/Mainf/Stickers/etc/adminhtml/system.xml
<system>
<tab>..</tab>
<section><group><field>..</field></ group></section>
</system>
<source_model>MainfStickersModelConfigBackendStickerType</source_model>
app/code/Mainf/Stickers/Model/Config/Backend/StickerType.php
<?php
namespace MainfStickersModelConfigBackend;
use MagentoFrameworkOptionArrayInterface;
class StickerType implements ArrayInterface
{
public function toOptionArray()
{
$stickerTypes = array();
$stickerTypes[] = ['value' => 'image','label' => __('Image')];
$stickerTypes[] = ['value' => 'custom','label' => __('Custom Label')];
return $stickerTypes;
}
}
Development: module configuration & source model
Issue: to create a hierarchy when enabling/disabling fields
Solution: to upload a template in the layout of the configuration page
(adminhtml_system_config_edit.xml):
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left"
xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="footer">
<block class="MainfStickersBlockConfig" template="Mainf_Stickers::js.phtml"/>
</referenceContainer>
</body>
</page>
In js.phtml template insert the JS code:
<script type="text/javascript">
require(
['jquery'],
function($) {
$(function() {
..
});
}
);
</script>
Development: module configuration & customization
• crontab.xml file creation (new!):
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd">
<group id="default">
<job name="mainf_stickers_activation" instance="MainfStickersModelObserver”
method="checkStickersActivation">
<schedule>*/5 * * * *</schedule>
</job>
</group>
</config>
• Observer.php file creation:
control of the status of the sticker (enabled/disabled)
comparison of date
enabling/disabling the sticker
flush of date field
Development: Observer
Basic CSS:
.product.media .mainf-sticker-wrapper.top-right {
top: 13px;
right: 13px;
}
.product.media .mainf-sticker-wrapper.top-left {
bottom: 200px;
}
.mainf-sticker.discount-product {
width: 66px;
border: #FFF 2px solid;
border-radius: 50%;
box-shadow: 2px 2px 2px #CCC;
text-align: center;
height: 60px;
padding: 10px 5px;
}
.mainf-sticker.latest-product {
min-width: 66px;
max-width: 130px;
min-height: 76px;
padding: 5px;
border: #FFF 2px solid;
box-shadow: 2px 2px 2px #CCC;
text-align:left;
}
Graphic changes
Basic CSS 1° option:
.product.media .mainf-sticker-wrapper.top-right {
top: 150px;
right: 150px;
}
Graphic changes
Basic CSS 2° option:
.product.media .mainf-sticker-wrapper.top-right {
top: 400px;
right: 150px;
}
.product.media .mainf-sticker-wrapper.top-left {
bottom: 600px;
}
.mainf-sticker.latest-product {
min-width: 66px;
max-width: 130px;
width: 150px;
min-height: 76px;
padding: 5px;
border: #FFF 2px solid;
box-shadow: 2px 2px 2px #CCC;
text-align:left;
}
Graphic changes
• Structural improvements for the development of extensions:
all files for each extension in the same folder;
substitution of controllers/ folder with Controller/ ;
use of XML Style Definition (XSD) within xml file;
split of config.xml in multiple xml files, each with a precise task (module.xml,
routes.xml, crontab.xml etc.) ;
one file for each action;
bin/magento
• Lots of bugs still open (1695 in GitHub, our is #8370), community not ready
as it is for M1 and a lot of doubts.
Conclusions
You can download the extension “Stickers” here:
https://github.com/WaPoNe/module-stickers
Or you can buy the extension “Stickers Pro” here:
http://www.magentostoremanager.it/module-stickers-
pro.html
Discount coupon for you: MMIT17
Reference
Write us at:
giorgio.bignozzi@marketinginformatico.it
michele.fantetti@maggioli.it
Marketing Informatico
Milano | Bologna | Rimini | Bari
Any question?

More Related Content

Viewers also liked

Angelo Coletta - Dalla Mass production alla mass customization
Angelo Coletta - Dalla Mass production alla mass customizationAngelo Coletta - Dalla Mass production alla mass customization
Angelo Coletta - Dalla Mass production alla mass customization
Meet Magento Italy
 

Viewers also liked (20)

Alessandro La Ciura - Live Chat ed Ecommerce: (ma) la chat vende veramente di...
Alessandro La Ciura - Live Chat ed Ecommerce: (ma) la chat vende veramente di...Alessandro La Ciura - Live Chat ed Ecommerce: (ma) la chat vende veramente di...
Alessandro La Ciura - Live Chat ed Ecommerce: (ma) la chat vende veramente di...
 
Giovanni Cappellotto - Come gestire le recommendation e le personalizzazioni ...
Giovanni Cappellotto - Come gestire le recommendation e le personalizzazioni ...Giovanni Cappellotto - Come gestire le recommendation e le personalizzazioni ...
Giovanni Cappellotto - Come gestire le recommendation e le personalizzazioni ...
 
Oleksii Korshenko - Magento 2 Backwards Compatible Policy
Oleksii Korshenko - Magento 2 Backwards Compatible PolicyOleksii Korshenko - Magento 2 Backwards Compatible Policy
Oleksii Korshenko - Magento 2 Backwards Compatible Policy
 
Gian Mario Infelici - Marketing automation e omnicanalità: come unire i canal...
Gian Mario Infelici - Marketing automation e omnicanalità: come unire i canal...Gian Mario Infelici - Marketing automation e omnicanalità: come unire i canal...
Gian Mario Infelici - Marketing automation e omnicanalità: come unire i canal...
 
Max Pronko - Best practices for checkout customisation in Magento 2
Max Pronko - Best practices for checkout customisation in Magento 2Max Pronko - Best practices for checkout customisation in Magento 2
Max Pronko - Best practices for checkout customisation in Magento 2
 
R.Grassi - P.Sardo - One integration: every wat to pay
R.Grassi - P.Sardo - One integration: every wat to payR.Grassi - P.Sardo - One integration: every wat to pay
R.Grassi - P.Sardo - One integration: every wat to pay
 
Piotr Karwatka - Managing IT project with no doubts. How to work with Agency,...
Piotr Karwatka - Managing IT project with no doubts. How to work with Agency,...Piotr Karwatka - Managing IT project with no doubts. How to work with Agency,...
Piotr Karwatka - Managing IT project with no doubts. How to work with Agency,...
 
Alejandro Cordero - Secure Electronic Commerce New Business and Repeat Busine...
Alejandro Cordero - Secure Electronic Commerce New Business and Repeat Busine...Alejandro Cordero - Secure Electronic Commerce New Business and Repeat Busine...
Alejandro Cordero - Secure Electronic Commerce New Business and Repeat Busine...
 
Igor Bondarenko - Magento2 Performance Bottlenecks: How to avoid it
Igor Bondarenko - Magento2 Performance Bottlenecks: How to avoid itIgor Bondarenko - Magento2 Performance Bottlenecks: How to avoid it
Igor Bondarenko - Magento2 Performance Bottlenecks: How to avoid it
 
Dirk Pinamonti - User Experience, Mobile, Cross Border: grow your business wi...
Dirk Pinamonti - User Experience, Mobile, Cross Border: grow your business wi...Dirk Pinamonti - User Experience, Mobile, Cross Border: grow your business wi...
Dirk Pinamonti - User Experience, Mobile, Cross Border: grow your business wi...
 
Alan Rhode: Ecommerce export: IVA, dazi doganali, accise e altri importanti t...
Alan Rhode: Ecommerce export: IVA, dazi doganali, accise e altri importanti t...Alan Rhode: Ecommerce export: IVA, dazi doganali, accise e altri importanti t...
Alan Rhode: Ecommerce export: IVA, dazi doganali, accise e altri importanti t...
 
Eugene Shakhsuvarov - Improving enterprise store scalability using AMQP and A...
Eugene Shakhsuvarov - Improving enterprise store scalability using AMQP and A...Eugene Shakhsuvarov - Improving enterprise store scalability using AMQP and A...
Eugene Shakhsuvarov - Improving enterprise store scalability using AMQP and A...
 
Angelo Coletta - Dalla Mass production alla mass customization
Angelo Coletta - Dalla Mass production alla mass customizationAngelo Coletta - Dalla Mass production alla mass customization
Angelo Coletta - Dalla Mass production alla mass customization
 
Vitalyi Golomoziy - Integration tests in Magento 2
Vitalyi Golomoziy - Integration tests in Magento 2Vitalyi Golomoziy - Integration tests in Magento 2
Vitalyi Golomoziy - Integration tests in Magento 2
 
William Sbarzaglia - Le buyer personas nell'e-commerce
William Sbarzaglia - Le buyer personas nell'e-commerceWilliam Sbarzaglia - Le buyer personas nell'e-commerce
William Sbarzaglia - Le buyer personas nell'e-commerce
 
Iacopo Pecchi - Aprire un E-commerce in CINA dalla A alla Z
Iacopo Pecchi - Aprire un E-commerce in CINA dalla A alla ZIacopo Pecchi - Aprire un E-commerce in CINA dalla A alla Z
Iacopo Pecchi - Aprire un E-commerce in CINA dalla A alla Z
 
Francesca Bazzi - Lo scenario e-commerce in Italia e nel mondo: dati, trend e...
Francesca Bazzi - Lo scenario e-commerce in Italia e nel mondo: dati, trend e...Francesca Bazzi - Lo scenario e-commerce in Italia e nel mondo: dati, trend e...
Francesca Bazzi - Lo scenario e-commerce in Italia e nel mondo: dati, trend e...
 
Improved Layered Navigation: Magento Extension by Amasty. User Guide.
Improved Layered Navigation: Magento Extension by Amasty. User Guide.Improved Layered Navigation: Magento Extension by Amasty. User Guide.
Improved Layered Navigation: Magento Extension by Amasty. User Guide.
 
Building with Virtual Development Environments
Building with Virtual Development EnvironmentsBuilding with Virtual Development Environments
Building with Virtual Development Environments
 
User Experience
User ExperienceUser Experience
User Experience
 

Similar to Giorgio Bignozzi - How to develop a Sticker plug-in for Magento 2: best practice

4 coding101 fewd_lesson4_j_query_and_buttons 20210105
4 coding101 fewd_lesson4_j_query_and_buttons 202101054 coding101 fewd_lesson4_j_query_and_buttons 20210105
4 coding101 fewd_lesson4_j_query_and_buttons 20210105
John Picasso
 
WordCamp ABQ 2013: Making the leap from Designer to Designer/Developer
WordCamp ABQ 2013: Making the leap from Designer to Designer/DeveloperWordCamp ABQ 2013: Making the leap from Designer to Designer/Developer
WordCamp ABQ 2013: Making the leap from Designer to Designer/Developer
my easel
 
Rp 6 session 2 naresh bhatia
Rp 6  session 2 naresh bhatiaRp 6  session 2 naresh bhatia
Rp 6 session 2 naresh bhatia
sapientindia
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
Chris Alfano
 
PRG 420 Week 3 Individual Assignment Netbeans Project (annual co.docx
PRG 420 Week 3 Individual Assignment Netbeans Project (annual co.docxPRG 420 Week 3 Individual Assignment Netbeans Project (annual co.docx
PRG 420 Week 3 Individual Assignment Netbeans Project (annual co.docx
harrisonhoward80223
 

Similar to Giorgio Bignozzi - How to develop a Sticker plug-in for Magento 2: best practice (20)

4 coding101 fewd_lesson4_j_query_and_buttons 20210105
4 coding101 fewd_lesson4_j_query_and_buttons 202101054 coding101 fewd_lesson4_j_query_and_buttons 20210105
4 coding101 fewd_lesson4_j_query_and_buttons 20210105
 
Wordcamp abq cf-cpt
Wordcamp abq cf-cptWordcamp abq cf-cpt
Wordcamp abq cf-cpt
 
Building Potent WordPress Websites
Building Potent WordPress WebsitesBuilding Potent WordPress Websites
Building Potent WordPress Websites
 
WordCamp ABQ 2013: Making the leap from Designer to Designer/Developer
WordCamp ABQ 2013: Making the leap from Designer to Designer/DeveloperWordCamp ABQ 2013: Making the leap from Designer to Designer/Developer
WordCamp ABQ 2013: Making the leap from Designer to Designer/Developer
 
Code Generation in Magento 2
Code Generation in Magento 2Code Generation in Magento 2
Code Generation in Magento 2
 
Extend sdk
Extend sdkExtend sdk
Extend sdk
 
Rp 6 session 2 naresh bhatia
Rp 6  session 2 naresh bhatiaRp 6  session 2 naresh bhatia
Rp 6 session 2 naresh bhatia
 
Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011Jarv.us Showcase — SenchaCon 2011
Jarv.us Showcase — SenchaCon 2011
 
Introduction to Mangento
Introduction to Mangento Introduction to Mangento
Introduction to Mangento
 
Mangento
MangentoMangento
Mangento
 
Odoo Experience 2018 - From a Web Controller to a Full CMS
Odoo Experience 2018 - From a Web Controller to a Full CMSOdoo Experience 2018 - From a Web Controller to a Full CMS
Odoo Experience 2018 - From a Web Controller to a Full CMS
 
Benefits of Google Tag Manager
Benefits of Google Tag ManagerBenefits of Google Tag Manager
Benefits of Google Tag Manager
 
PRG 420 Week 3 Individual Assignment Netbeans Project (annual co.docx
PRG 420 Week 3 Individual Assignment Netbeans Project (annual co.docxPRG 420 Week 3 Individual Assignment Netbeans Project (annual co.docx
PRG 420 Week 3 Individual Assignment Netbeans Project (annual co.docx
 
Miva ReadyThemes for Store Owners
Miva ReadyThemes for Store OwnersMiva ReadyThemes for Store Owners
Miva ReadyThemes for Store Owners
 
Custom PrimeFaces components
Custom PrimeFaces componentsCustom PrimeFaces components
Custom PrimeFaces components
 
Fragments: Why, How, What For?
Fragments: Why, How, What For?Fragments: Why, How, What For?
Fragments: Why, How, What For?
 
How to-create-a-simple-module-in-magento-2.0
How to-create-a-simple-module-in-magento-2.0How to-create-a-simple-module-in-magento-2.0
How to-create-a-simple-module-in-magento-2.0
 
Refactor Large apps with Backbone
Refactor Large apps with BackboneRefactor Large apps with Backbone
Refactor Large apps with Backbone
 
Refactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.jsRefactoring Large Web Applications with Backbone.js
Refactoring Large Web Applications with Backbone.js
 
Refactor Large applications with Backbone
Refactor Large applications with BackboneRefactor Large applications with Backbone
Refactor Large applications with Backbone
 

More from Meet Magento Italy

Giulio Gargiullo - Strategie di marketing digitale per avviare l’e-commerce i...
Giulio Gargiullo - Strategie di marketing digitale per avviare l’e-commerce i...Giulio Gargiullo - Strategie di marketing digitale per avviare l’e-commerce i...
Giulio Gargiullo - Strategie di marketing digitale per avviare l’e-commerce i...
Meet Magento Italy
 

More from Meet Magento Italy (20)

Dirk Pinamonti - Come affrontare la sfida del nuovo mercato multicanale e del...
Dirk Pinamonti - Come affrontare la sfida del nuovo mercato multicanale e del...Dirk Pinamonti - Come affrontare la sfida del nuovo mercato multicanale e del...
Dirk Pinamonti - Come affrontare la sfida del nuovo mercato multicanale e del...
 
Vinai Kopp - How i develop M2 modules
Vinai Kopp - How i develop M2 modules Vinai Kopp - How i develop M2 modules
Vinai Kopp - How i develop M2 modules
 
Eugene Shaksuvarov - Tuning Magento 2 for Maximum Performance
Eugene Shaksuvarov - Tuning Magento 2 for Maximum PerformanceEugene Shaksuvarov - Tuning Magento 2 for Maximum Performance
Eugene Shaksuvarov - Tuning Magento 2 for Maximum Performance
 
Muliadi jeo - How to sell online in Indonesia
Muliadi jeo - How to sell online in IndonesiaMuliadi jeo - How to sell online in Indonesia
Muliadi jeo - How to sell online in Indonesia
 
Max Pronko - 10 migration mistakes from Magento 1 to Magento 2
Max Pronko - 10 migration mistakes from Magento 1 to Magento 2Max Pronko - 10 migration mistakes from Magento 1 to Magento 2
Max Pronko - 10 migration mistakes from Magento 1 to Magento 2
 
Alessandro La Ciura - Progettare la migliore integrazione tra live chat ed e-...
Alessandro La Ciura - Progettare la migliore integrazione tra live chat ed e-...Alessandro La Ciura - Progettare la migliore integrazione tra live chat ed e-...
Alessandro La Ciura - Progettare la migliore integrazione tra live chat ed e-...
 
Bodin - Hullin & Potencier - Magento Performance Profiling and Best Practices
Bodin - Hullin & Potencier - Magento Performance Profiling and Best PracticesBodin - Hullin & Potencier - Magento Performance Profiling and Best Practices
Bodin - Hullin & Potencier - Magento Performance Profiling and Best Practices
 
Giulio Gargiullo - Strategie di marketing digitale per avviare l’e-commerce i...
Giulio Gargiullo - Strategie di marketing digitale per avviare l’e-commerce i...Giulio Gargiullo - Strategie di marketing digitale per avviare l’e-commerce i...
Giulio Gargiullo - Strategie di marketing digitale per avviare l’e-commerce i...
 
Vinai Kopp - FPC Hole punching in Magento 2
Vinai Kopp - FPC Hole punching in Magento 2Vinai Kopp - FPC Hole punching in Magento 2
Vinai Kopp - FPC Hole punching in Magento 2
 
Jacopo Nardiello - From CI to Prod: Running Magento at scale with Kubernetes
Jacopo Nardiello - From CI to Prod: Running Magento at scale with KubernetesJacopo Nardiello - From CI to Prod: Running Magento at scale with Kubernetes
Jacopo Nardiello - From CI to Prod: Running Magento at scale with Kubernetes
 
James Zetlen - PWA Studio Integration…With You
James Zetlen - PWA Studio Integration…With YouJames Zetlen - PWA Studio Integration…With You
James Zetlen - PWA Studio Integration…With You
 
Talesh Seeparsan - The Hound of the Malwarevilles
Talesh Seeparsan - The Hound of the MalwarevillesTalesh Seeparsan - The Hound of the Malwarevilles
Talesh Seeparsan - The Hound of the Malwarevilles
 
Miguel Balparda - A day in support
Miguel Balparda - A day in supportMiguel Balparda - A day in support
Miguel Balparda - A day in support
 
Volodymyr Kublytskyi - Develop Product, Design Platform
Volodymyr Kublytskyi - Develop Product, Design PlatformVolodymyr Kublytskyi - Develop Product, Design Platform
Volodymyr Kublytskyi - Develop Product, Design Platform
 
Rosario Toscano - Processi di ottimizzazione per una crescita continua
Rosario Toscano - Processi di ottimizzazione per una crescita continuaRosario Toscano - Processi di ottimizzazione per una crescita continua
Rosario Toscano - Processi di ottimizzazione per una crescita continua
 
Henrik Feld Jakobsen - How to sell online Scandinavia
Henrik Feld Jakobsen - How to sell online ScandinaviaHenrik Feld Jakobsen - How to sell online Scandinavia
Henrik Feld Jakobsen - How to sell online Scandinavia
 
Rabia Qureshi - How to sell online in UK
Rabia Qureshi - How to sell online in UKRabia Qureshi - How to sell online in UK
Rabia Qureshi - How to sell online in UK
 
Matteo Schuerch - How to sell online in Switzerland
Matteo Schuerch - How to sell online in SwitzerlandMatteo Schuerch - How to sell online in Switzerland
Matteo Schuerch - How to sell online in Switzerland
 
Il data-driven nell’e-commerce: il caso studio Alessi
Il data-driven nell’e-commerce: il caso studio AlessiIl data-driven nell’e-commerce: il caso studio Alessi
Il data-driven nell’e-commerce: il caso studio Alessi
 
Philippe Bernou - Seamless omnichannel solutions with Magento order management
Philippe Bernou - Seamless omnichannel solutions with Magento order managementPhilippe Bernou - Seamless omnichannel solutions with Magento order management
Philippe Bernou - Seamless omnichannel solutions with Magento order management
 

Recently uploaded

Recently uploaded (11)

The Influence and Evolution of Mogul Press in Contemporary Public Relations.docx
The Influence and Evolution of Mogul Press in Contemporary Public Relations.docxThe Influence and Evolution of Mogul Press in Contemporary Public Relations.docx
The Influence and Evolution of Mogul Press in Contemporary Public Relations.docx
 
Deciding The Topic of our Magazine.pptx.
Deciding The Topic of our Magazine.pptx.Deciding The Topic of our Magazine.pptx.
Deciding The Topic of our Magazine.pptx.
 
DAY 0 8 A Revelation 05-19-2024 PPT.pptx
DAY 0 8 A Revelation 05-19-2024 PPT.pptxDAY 0 8 A Revelation 05-19-2024 PPT.pptx
DAY 0 8 A Revelation 05-19-2024 PPT.pptx
 
SaaStr Workshop Wednesday with CEO of Guru
SaaStr Workshop Wednesday with CEO of GuruSaaStr Workshop Wednesday with CEO of Guru
SaaStr Workshop Wednesday with CEO of Guru
 
Databricks Machine Learning Associate Exam Dumps 2024.pdf
Databricks Machine Learning Associate Exam Dumps 2024.pdfDatabricks Machine Learning Associate Exam Dumps 2024.pdf
Databricks Machine Learning Associate Exam Dumps 2024.pdf
 
Microsoft Fabric Analytics Engineer (DP-600) Exam Dumps 2024.pdf
Microsoft Fabric Analytics Engineer (DP-600) Exam Dumps 2024.pdfMicrosoft Fabric Analytics Engineer (DP-600) Exam Dumps 2024.pdf
Microsoft Fabric Analytics Engineer (DP-600) Exam Dumps 2024.pdf
 
TSM unit 5 Toxicokinetics seminar by Ansari Aashif Raza.pptx
TSM unit 5 Toxicokinetics seminar by  Ansari Aashif Raza.pptxTSM unit 5 Toxicokinetics seminar by  Ansari Aashif Raza.pptx
TSM unit 5 Toxicokinetics seminar by Ansari Aashif Raza.pptx
 
2024-05-15-Surat Meetup-Hyperautomation.pptx
2024-05-15-Surat Meetup-Hyperautomation.pptx2024-05-15-Surat Meetup-Hyperautomation.pptx
2024-05-15-Surat Meetup-Hyperautomation.pptx
 
Understanding Poverty: A Community Questionnaire
Understanding Poverty: A Community QuestionnaireUnderstanding Poverty: A Community Questionnaire
Understanding Poverty: A Community Questionnaire
 
ACM CHT Best Inspection Practices Kinben Innovation MIC Slideshare.pdf
ACM CHT Best Inspection Practices Kinben Innovation MIC Slideshare.pdfACM CHT Best Inspection Practices Kinben Innovation MIC Slideshare.pdf
ACM CHT Best Inspection Practices Kinben Innovation MIC Slideshare.pdf
 
ServiceNow CIS-Discovery Exam Dumps 2024
ServiceNow CIS-Discovery Exam Dumps 2024ServiceNow CIS-Discovery Exam Dumps 2024
ServiceNow CIS-Discovery Exam Dumps 2024
 

Giorgio Bignozzi - How to develop a Sticker plug-in for Magento 2: best practice

  • 1.
  • 2. Developing a Sticker plug-in Sticker plug-in for Magento 2 Best practice
  • 3. Giorgio Bignozzi Technical Manager | Marketing Informatico https://www.marketinginformatico.it @GiorgioBignozzi Michele Fantetti Magento Developer at Maggioli Editore http://www.fantetti.net @WaP_oNe Who we are
  • 4. Abstract: Our aim was to create an extension that adds the classical label to the product image in the different layouts concerning products (product page, category page, related products, upsell products, cross-sell products, widget, search results). Goals: • To create two labels (“Discount” and “New”) with different shapes and positions • To have a separate graphic management of these labels (custom label or image). If you choose a custom label, you can set two labels with a configurable text, text colour and background colour • To display the label on sale products or products associated to certain categories (“Discount”) • To display the label on products associated to certain categories (“New”) • To enable/disable automatically (with programmable date and time) one or both the stickers. Our project: Stickers
  • 8. Desiderata: related / cross-sell / upsell
  • 10. • ISSUE #1: how to add the label (HTML code) without modifying layout files in multiple pages and making the plugin independent • SOLUTION #1: when rendering product attributes, upload HTML code that will be completed lately via script JS. • ISSUE #2: how and where to insert this HTML code • SOLUTION #2: thanks to Magento 2 PLUGIN, beforeGetProductPrice() and afterGetProductPrice(). Development: problems and solutions (1)
  • 11. • ISSUE #3: how to insert extra code to this HTML code • SOLUTION #3: requireJS • ISSUE #4: enable/disable some configurable fields depending on which fields you have valued before • SOLUTION #4: upload a JS in the layout of the configuration page of the plugin Development: problems and solutions (2)
  • 12. File System: M1 VS M2 Differences in file system organization in M1 e M2 (Vanilla installation)
  • 13. • registration.php • etc/module.xml Development: M1 vs M2 structure for plug-in registration In M2 we need to modify only one folder (app/code)
  • 14. app/code/Mainf/Stickers/Model/Stickers.php It manages every feature of the sticker (isInCategory(), isDiscounted(), getDiscountAmount() etc.) in addition to inserting HTML code: protected function _getHTML($stickerLayoutType, $class, $firstLabel = '', $secondLabel = '') { switch ($stickerLayoutType) { case self::STICKER_IMAGE: $html = "<input type='hidden' class='".$class."' value='1' />"; break; case self::STICKER_AREA: $html = "<input type='hidden' class='".$class."' value='" . $this->getConfigValue($firstLabel) . "<br />" . $this->getConfigValue($secondLabel) . "' />"; break; case self::STICKER_CALCULATED: $html = "<input type='hidden' class='".$class."' value='" . $this->getDiscountAmount() . "' />"; break; default: $html = "<input type='hidden' class='".$class."' value='1' />"; break; } return $html; } Development : model class Stickers
  • 15. app/code/Mainf/Stickers/Plugin/ProductStickersPlugin.php namespace MainfStickersPlugin; class ProductStickersPlugin extends MainfStickersModelStickers { const DISCOUNT_ACTIVATION = "stickers/stickers_discount_page/discount_activation"; const LATEST_ACTIVATION = "stickers/stickers_latest_page/latest_activation"; public function beforeGetProductPrice( MagentoCatalogBlockProductAbstractProduct $abstractProduct, MagentoCatalogModelProduct $product ) { $this->_product = $product; } public function afterGetProductPrice(MagentoCatalogBlockProductAbstractProduct $product, $result) { if($this->isStickerActive(self::DISCOUNT_ACTIVATION)) { $result .= $this->_setDiscountStickerHTML(); } if($this->isStickerActive(self::LATEST_ACTIVATION)) { $result .= $this->_setLatestStickerHTML(); } return $result; } } Development : PLUGIN (Dependency Injection)
  • 16. app/code/Mainf/Stickers/view/frontend/layout/default.xml <?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <head> <css src="Mainf_Stickers::css/mainf-stickers.css"/> <link src="https://fonts.googleapis.com/css?family=Oswald:400,700,300" rel="stylesheet" type="text/css" src_type="url" /> </head> <body> <referenceContainer name="content"> <block name="category.discount.sticker" class="MainfStickersBlockDiscount" template="Mainf_Stickers::categoryDiscount.phtml" cacheable="false" after="-" /> <block name="category.latest.sticker" class="MainfStickersBlockLatest" template="Mainf_Stickers::categoryLatest.phtml" cacheable="false" after="-" /> </referenceContainer> </body> </page> Other layout files: catalog_product_view.xml e checkout_cart_index.xml Development: layout
  • 17. app/code/Mainf/Stickers/view/frontend/templates/categoryDiscount.phtml if($block->isDiscountActive()): $discountImage = "<div class='mainf-sticker-wrapper top-right'>"; $discountImage .= "<img class='categoryDiscountImage' alt='".__('Discount')."' src='".$this- >getUrl('pub/media')."mainf/stickers/images/".$block->getStickerImage()."' />"; $discountImage .= "</div>"; $discountArea = "<div class='mainf-sticker-wrapper top-right'>"; $discountArea .= "<div class='mainf-sticker discount-product' style='background-color: #".$block->getStickerBackground()."; color: #".$block- >getStickerText().";'></div>"; $discountArea .= "</div>"; ?> Development: template <script type="text/x-magento-init"> { "*":{ "categoryPageDiscount":{ "imageTag": { "discountImage": "<?php /* @escapeNotVerified */ echo $discountImage; ?>", "discountArea": "<?php /* @escapeNotVerified */ echo $discountArea; ?>" }}}} </script> <?php endif;
  • 18. app/code/Mainf/Stickers/view/frontend/requirejs-config.js var config = { map: { '*': { categoryPageDiscount: 'Mainf_Stickers/js/categoryPageDiscount', categoryPageLatest: 'Mainf_Stickers/js/categoryPageLatest', viewPageDiscount: 'Mainf_Stickers/js/viewPageDiscount', viewPageLatest: 'Mainf_Stickers/js/viewPageLatest' } } }; Development: RequireJS (1)
  • 19. app/code/Mainf/Stickers/view/frontend/web/js/categoryPageDiscount.js define( ['jquery'], function ($) { $.widget( 'mainf.categoryPageStickers', { _create: function () { var self = this; $(".categoryPageDiscount").each(function () { if ($(this).val() == 1) { $($(this).parent().parent().find("a").find("span").find("span")) .prepend(self.options.imageTag.discountImage); } else { var discountAmount = $(this).val(); $($(this).parent().parent().find("a").find("span").find("span")) .prepend(self.options.imageTag.discountArea); $(".discount-product").html(discountAmount); } }); } } ); return $.mainf.categoryPageStickers; } ); Development: RequireJS (2)
  • 20. Backend: module configuration & customization (1)
  • 21. Backend: module configuration & customization (2)
  • 22. app/code/Mainf/Stickers/etc/adminhtml/system.xml <system> <tab>..</tab> <section><group><field>..</field></ group></section> </system> <source_model>MainfStickersModelConfigBackendStickerType</source_model> app/code/Mainf/Stickers/Model/Config/Backend/StickerType.php <?php namespace MainfStickersModelConfigBackend; use MagentoFrameworkOptionArrayInterface; class StickerType implements ArrayInterface { public function toOptionArray() { $stickerTypes = array(); $stickerTypes[] = ['value' => 'image','label' => __('Image')]; $stickerTypes[] = ['value' => 'custom','label' => __('Custom Label')]; return $stickerTypes; } } Development: module configuration & source model
  • 23. Issue: to create a hierarchy when enabling/disabling fields Solution: to upload a template in the layout of the configuration page (adminhtml_system_config_edit.xml): <?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceContainer name="footer"> <block class="MainfStickersBlockConfig" template="Mainf_Stickers::js.phtml"/> </referenceContainer> </body> </page> In js.phtml template insert the JS code: <script type="text/javascript"> require( ['jquery'], function($) { $(function() { .. }); } ); </script> Development: module configuration & customization
  • 24. • crontab.xml file creation (new!): <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Cron:etc/crontab.xsd"> <group id="default"> <job name="mainf_stickers_activation" instance="MainfStickersModelObserver” method="checkStickersActivation"> <schedule>*/5 * * * *</schedule> </job> </group> </config> • Observer.php file creation: control of the status of the sticker (enabled/disabled) comparison of date enabling/disabling the sticker flush of date field Development: Observer
  • 25. Basic CSS: .product.media .mainf-sticker-wrapper.top-right { top: 13px; right: 13px; } .product.media .mainf-sticker-wrapper.top-left { bottom: 200px; } .mainf-sticker.discount-product { width: 66px; border: #FFF 2px solid; border-radius: 50%; box-shadow: 2px 2px 2px #CCC; text-align: center; height: 60px; padding: 10px 5px; } .mainf-sticker.latest-product { min-width: 66px; max-width: 130px; min-height: 76px; padding: 5px; border: #FFF 2px solid; box-shadow: 2px 2px 2px #CCC; text-align:left; } Graphic changes
  • 26. Basic CSS 1° option: .product.media .mainf-sticker-wrapper.top-right { top: 150px; right: 150px; } Graphic changes
  • 27. Basic CSS 2° option: .product.media .mainf-sticker-wrapper.top-right { top: 400px; right: 150px; } .product.media .mainf-sticker-wrapper.top-left { bottom: 600px; } .mainf-sticker.latest-product { min-width: 66px; max-width: 130px; width: 150px; min-height: 76px; padding: 5px; border: #FFF 2px solid; box-shadow: 2px 2px 2px #CCC; text-align:left; } Graphic changes
  • 28. • Structural improvements for the development of extensions: all files for each extension in the same folder; substitution of controllers/ folder with Controller/ ; use of XML Style Definition (XSD) within xml file; split of config.xml in multiple xml files, each with a precise task (module.xml, routes.xml, crontab.xml etc.) ; one file for each action; bin/magento • Lots of bugs still open (1695 in GitHub, our is #8370), community not ready as it is for M1 and a lot of doubts. Conclusions
  • 29. You can download the extension “Stickers” here: https://github.com/WaPoNe/module-stickers Or you can buy the extension “Stickers Pro” here: http://www.magentostoremanager.it/module-stickers- pro.html Discount coupon for you: MMIT17 Reference
  • 30. Write us at: giorgio.bignozzi@marketinginformatico.it michele.fantetti@maggioli.it Marketing Informatico Milano | Bologna | Rimini | Bari Any question?