Question

Here's what I'm trying to achieve.

When a product page URL has a parameter added to it like so: https://example.com/This-THI08.html?specialview=1

I'm trying to append a “specialview” class to the element. So that it looks like this:

<body data-container="body" itemtype=" http://schema.org/Product " itemscope="itemscope" class=“specialview page-product-configurable catalog-product-view product-this-thi08 categorypath-best category-best page-layout-1column catalog-print-pdf_active" aria-busy="false">

I only want the body tag there if that parameter is found in the URL of the product page. For example:

If product page is loaded using URL https://example.com/This-THI08.html then do not add the new class

However, if the same product page is loaded using URL https://example.com/This-THI08.html?specialview=1 then I want the additional body class to be added.

Here is what I've done so far, I've appended the body tag below in the catalog product view file:

./app/design/frontend/me/mysite/Magento_Catalog/layout/catalog_product_view.xml

<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
   <head>
       <css src="css/catalog/product.css" media="all"/>
   </head>
   <body>
       <attribute name="class" value="specialview"/>
       <referenceBlock name="catalog.product.related" remove="true" />
       <referenceBlock name="product.info.stock.sku" remove="true" />
       <referenceContainer name="product.info.social" remove="true" />

       <move element="product.info.upsell" destination="columns" after="main" />

       <referenceContainer name="product.info.main">
           <block name="product.info.badge" class="Magento\Catalog\Block\Product\View" template="Magento_Catalog::badge.phtml" />
       </referenceContainer>

       <move element="product.info.badge" destination="product.info.main" after="page.main.title" />
       <move element="view.addto.wishlist" destination="content" />
   </body>
</page>

This applies the body tag to all PDP pages with or without the URL parameter with my new CSS.

I was thinking i could maybe use a plugin to write some logic but this is where i'm a bit stuck. Would this be the best way to go about this? Something like this:

app/code/me/Mymodule/Plugin/Result/Page.php

<?php
namespace me\Mymodule\Plugin\Result;

use Magento\Framework\App\ResponseInterface;

class Page
{
    private $context;

    public function __construct(
        \Magento\Framework\View\Element\Context $context
    ) {
        $this->context = $context;
    }

    public function getCurrentUrl() {
        return $this->_storeManager->getStore()->getCurrentUrl();
    }

    public function beforeRenderResult(
        \Magento\Framework\View\Result\Page $subject,
        ResponseInterface $response
    ){    
        if($this->context->getRequest()->getFullActionName() == 'catalog_product_view' & $block->getRequest()->getUriString() == 'specialview'){
           $subject->getConfig()->addBodyClass('specialview');
        }    
        return [$response];
    }
}

My CSS and jquery would take care of looking for the parameter in the URL and changing the styling.

Just need to make sure the body class switches when it reads the specific parameter in the URL.

Or Something like this would work:

/**
 * Remove CSS class from page body tag
 *
 * @param string $className
 * @return Mage_Adminhtml_Block_Page
 */
public function removeBodyClass($className)
{
    $className = preg_replace('#[^a-z0-9]+#', '-', strtolower($className));

    $existingClassNames = explode(' ', $this->getBodyClass());
    if ($i = array_search($className, $existingClassNames)) {
        unset($existingClassNames[$i]);
        $this->setBodyClass(implode(' ', $existingClassNames));
    }

    return $this;
}
Was it helpful?

Solution

Yes, write a plugin method.

app/code/xxx/StoreCodeBodyClass/registration.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Xxx_StoreCodeBodyClass',
    __DIR__
);

app/code/xxx/StoreCodeBodyClass/etc/module.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Xxx_StoreCodeBodyClass" setup_version="2.0.1">
        <sequence>
            <module name="Magento_Core"/>
        </sequence>
    </module>
</config>

app/code/xxx/StoreCodeBodyClass/etc/frontend/events.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="layout_load_before">
        <observer name="xxx_storecodebodyclass" instance="Xxx\StoreCodeBodyClass\Plugin\StoreCodeBodyClassPlugin" shared="false" />
    </event>
</config>

Place in app/code/xxx/StoreCodeBodyClass/Plugin/StoreCodeBodyClassPlugin.php

<?php

namespace xxx\StoreCodeBodyClass\Plugin;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;
use Magento\Framework\View\Page\Config;
use Magento\Store\Model\StoreManagerInterface;


class StoreCodeBodyClassPlugin implements ObserverInterface
{
    protected $config;
    protected $storeManager;
    protected $request;
    public function __construct(
        Config $config,
        StoreManagerInterface $storeManager,
        \Magento\Framework\App\Request\Http $request
    ){
        $this->config = $config;
        $this->storeManager = $storeManager;
        $this->request = $request;
    }

    public function execute(Observer $observer){

        $specialview = $this->request->getParam('specialview');
        if ($this->request->getFullActionName() == 'catalog_product_view') {
            if ($specialview == 1) {
                $this->config->addBodyClass("specialview");
            }
        }
    }
}

This should work.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top