We sacrifice by not doing any other technology, so that you get the best of Magento.

We sacrifice by not doing any other technology, so that you get the best of Magento.

    Magento 2.3.5 Refused to load the script because it violates the following Content Security Policy directive.

    In case if you get titled error, you can follow the below process.

    Please add a file in your module or any existing module in app/code directory

    Create the file app/code/Namespace/Module/etc/csp_whitelist.xml

    <?xml version="1.0"?>
    <!--
    /**
     * Copyright  Magento, Inc. All rights reserved.
     * See COPYING.txt for license details.
     */
    -->
    <csp_whitelist xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Csp/etc/csp_whitelist.xsd">
        <policies>
            <policy id="script-src">
                <values>
                    <!--CDN-->
                    <value id="cloudflare" type="host">*.cloudflare.com</value>
    
                    <!--Google-->
                    <value id="google-analytics" type="host">www.google-analytics.com</value>
    
                    <!--Functions-->
                    <value id="trustedshops" type="host">*.trustedshops.com</value>
                    <value id="usercentrics" type="host">*.usercentrics.eu</value>
                </values>
            </policy>
            <policy id="style-src">
                <values>
                    <!--CDN-->
                    <value id="cloudflare" type="host">*.cloudflare.com</value>
    
                    <!--Design-->
                    <value id="typekit" type="host">*.typekit.net</value>
    
                    <!--Functions-->
                    <value id="trustedshops" type="host">*.trustedshops.com</value>
                    <value id="usercentrics" type="host">*.usercentrics.eu</value>
                </values>
            </policy>
            <policy id="img-src">
                <values>
                    <!--CDN-->
                    <value id="cloudflare" type="host">*.cloudflare.com</value>
                    <value id="klarna-base" type="host">https://cdn.klarna.com</value>
    
                    <!--Payments-->
                    <value id="paypal" type="host">*.paypal.com</value>
    
                    <!--Video-->
                    <value id="vimeocdn" type="host">*.vimeocdn.com</value>
                    <value id="youtube-img" type="host">https://s.ytimg.com</value>
    
                    <!--Functions-->
                    <value id="usercentrics" type="host">*.usercentrics.eu</value>
                </values>
            </policy>
            <policy id="connect-src">
                <values>
                    <!--CDN-->
                    <value id="cloudflare" type="host">*.cloudflare.com</value>
    
                    <!--Payments-->
                    <value id="paypal" type="host">*.paypal.com</value>
                </values>
            </policy>
            <policy id="font-src">
                <values>
                    <!--CDN-->
                    <value id="cloudflare" type="host">*.cloudflare.com</value>
    
                    <!--Design-->
                    <value id="typekit" type="host">*.typekit.net</value>
    
                    <!--Functions-->
                    <value id="trustedshops" type="host">*.trustedshops.com</value>
                </values>
            </policy>
        </policies>
    </csp_whitelist>

     

    Magento 2: add new custom field in cms pages

    If you need to add custom field in cms pages then follow below steps:

    1, You need to create a module for that so create module folders app/code/Magemonkey/CmspageBanner

    2, Add registration.php file in your module Magemonkey/CmspageBanner

    <?php 
    /**
     * @author Magemonkey Team
     * @package Magemonkey_CmspageBanner
     */
    MagentoFrameworkComponentComponentRegistrar::register(
     MagentoFrameworkComponentComponentRegistrar::MODULE,
     'Magemonkey_CmspageBanner',
     __DIR__
    );

    3, Add module.xml file in your module Magemonkey/CmspageBanner/etc

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
     <module name="Magemonkey_CmspageBanner" setup_version="1.0.1">
     </module>
    </config>

    4, Then create new schema file InstallSchema.php in  Magemonkey/CmspageBanner/setup

    <?php
    namespace MagemonkeyCmspageBannerSetup;
    
    use MagentoFrameworkSetupInstallSchemaInterface;
    use MagentoFrameworkSetupModuleContextInterface;
    use MagentoFrameworkSetupSchemaSetupInterface;
    
    class InstallSchema implements InstallSchemaInterface
    {
     /**
     * Add Secondary Custom Content
     */
     public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
     {
     $installer = $setup;
    
     $installer->startSetup();
    
     $setup->getConnection()->addColumn(
     $setup->getTable('cms_page'),
     'banner_block',
     [
     'type' => MagentoFrameworkDBDdlTable::TYPE_TEXT,
     'length' => 255,
     'nullable' => true,
     'comment' => 'Banner Block Identifier'
     ]
     );
    
     $installer->endSetup();
     }
    }

    5, Then add your need to add a field in ui_component form file cms_page_form.xml in Magemonkey/CmspageBanner/vew/adminhtml/ui_component

    <?xml version="1.0" encoding="UTF-8"?>
    <form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
     <fieldset name="general">
     <field name="banner_block">
     <argument name="data" xsi:type="array">
     <item name="config" xsi:type="array">
     <item name="dataType" xsi:type="string">text</item>
     <item name="label" xsi:type="string" translate="true">Banner Block Identifier</item>
     <item name="formElement" xsi:type="string">input</item>
     <item name="source" xsi:type="string">page</item>
     <item name="dataScope" xsi:type="string">banner_block</item>
     </item>
     </argument>
     </field>
     </fieldset>
    </form>

    6, Then you need to create one block file for the call that field in the frontend, Banner.php in Magemonkey/CmspageBanner/Block

    <?php
    namespace MagemonkeyCmspageBannerBlock;
    
    use MagentoStoreModelScopeInterface;
    
    class Banner extends MagentoFrameworkViewElementTemplate
    {
     /**
     * @var MagentoCmsModelTemplateFilterProvider
     */
     protected $_filterProvider;
    
     /**
     * @var MagentoCmsModelPage
     */
     protected $_page;
    
     /**
     * Store manager
     *
     * @var MagentoStoreModelStoreManagerInterface
     */
     protected $_storeManager;
    
     /**
     * Page factory
     *
     * @var MagentoCmsModelPageFactory
     */
     protected $_pageFactory;
    
     /**
     * @var MagentoFrameworkViewPageConfig
     */
     protected $pageConfig;
    
     /**
     * Construct
     *
     * @param MagentoFrameworkViewElementTemplate $context
     * @param MagentoCmsModelPage $page
     * @param MagentoCmsModelTemplateFilterProvider $filterProvider
     * @param MagentoStoreModelStoreManagerInterface $storeManager
     * @param MagentoCmsModelPageFactory $pageFactory
     * @param MagentoFrameworkViewPageConfig $pageConfig
     * @param array $data
     */
     public function __construct(
     MagentoFrameworkViewElementTemplateContext $context,
     MagentoCmsModelPage $page,
     MagentoCmsModelTemplateFilterProvider $filterProvider,
     MagentoStoreModelStoreManagerInterface $storeManager,
     MagentoCmsModelPageFactory $pageFactory,
     MagentoFrameworkViewPageConfig $pageConfig,
     array $data = []
     ) {
     // used singleton (instead factory) because there exist dependencies on MagentoCmsHelperPage
     $this->_page = $page;
     $this->_filterProvider = $filterProvider;
     $this->_storeManager = $storeManager;
     $this->_pageFactory = $pageFactory;
     $this->pageConfig = $pageConfig;
     parent::__construct($context);
     }
    
     /**
     * Retrieve Page instance
     *
     * @return MagentoCmsModelPage
     */
     public function getPageData()
     {
     if (!$this->hasData('page')) {
     if ($this->getPageId()) {
     /** @var MagentoCmsModelPage $page */
     $page = $this->_pageFactory->create();
     $page->setStoreId($this->_storeManager->getStore()->getId())->load($this->getPageId(), 'identifier');
     } else {
     $page = $this->_page;
     }
     $this->setData('page', $page);
     }
     return $this->getData('page');
     }
    }

    After that you need to run setup:upgrade command

    Then after you can call that block in your cms page Like:

    <block class="MagemonkeyCmspageBannerBlockBanner" name="page.banner" template="Magemonkey_CmspageBanner::html/banner.phtml" after="-" />

    How to Enable Exception printing in Magento 2?

    This is similar to Magento 1 but file is located in a different folder pub/errorsIn Magento 1 file is located at a different location.

    All you need to do is to rename the following file to enable exception printing:

    Please rename file pub/errors/local.xml.sample to pub/errors/local.xml
    

    By renaming Above File you can see Error without going to check var/report.

    Thank You.

    Magento 2: How to solve the Invalid response line returned from server: HTTP/2 200 error.

    Create the following file:

    lib/internal/Magento/Framework/HTTP/Client/Curl.php

    Add the below code:

    <?php
    /**
     * Copyright © Magento, Inc. All rights reserved.
     * See COPYING.txt for license details.
     */
    namespace MagentoFrameworkHTTPClient;
    
    /**
     * Class to work with HTTP protocol using curl library
     *
     * @author      Magento Core Team <core@magentocommerce.com>
     * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
     */
    class Curl implements MagentoFrameworkHTTPClientInterface
    {
        /**
         * Max supported protocol by curl CURL_SSLVERSION_TLSv1_2
         * @var int
         */
        private $sslVersion;
    
        /**
         * Hostname
         * @var string
         */
        protected $_host = 'localhost';
    
        /**
         * Port
         * @var int
         */
        protected $_port = 80;
    
        /**
         * Stream resource
         * @var object
         */
        protected $_sock = null;
    
        /**
         * Request headers
         * @var array
         */
        protected $_headers = [];
    
        /**
         * Fields for POST method - hash
         * @var array
         */
        protected $_postFields = [];
    
        /**
         * Request cookies
         * @var array
         */
        protected $_cookies = [];
    
        /**
         * Response headers
         * @var array
         */
        protected $_responseHeaders = [];
    
        /**
         * Response body
         * @var string
         */
        protected $_responseBody = '';
    
        /**
         * Response status
         * @var int
         */
        protected $_responseStatus = 0;
    
        /**
         * Request timeout
         * @var int type
         */
        protected $_timeout = 300;
    
        /**
         * TODO
         * @var int
         */
        protected $_redirectCount = 0;
    
        /**
         * Curl
         * @var resource
         */
        protected $_ch;
    
        /**
         * User overrides options hash
         * Are applied before curl_exec
         *
         * @var array
         */
        protected $_curlUserOptions = [];
    
        /**
         * Header count, used while parsing headers
         * in CURL callback function
         * @var int
         */
        protected $_headerCount = 0;
    
        /**
         * Set request timeout, msec
         *
         * @param int $value
         * @return void
         */
        public function setTimeout($value)
        {
            $this->_timeout = (int)$value;
        }
    
        /**
         * @param int|null $sslVersion
         */
        public function __construct($sslVersion = null)
        {
            $this->sslVersion = $sslVersion;
        }
    
        /**
         * Set headers from hash
         *
         * @param array $headers
         * @return void
         */
        public function setHeaders($headers)
        {
            $this->_headers = $headers;
        }
    
        /**
         * Add header
         *
         * @param string $name name, ex. "Location"
         * @param string $value value ex. "http://google.com"
         * @return void
         */
        public function addHeader($name, $value)
        {
            $this->_headers[$name] = $value;
        }
    
        /**
         * Remove specified header
         *
         * @param string $name
         * @return void
         */
        public function removeHeader($name)
        {
            unset($this->_headers[$name]);
        }
    
        /**
         * Authorization: Basic header
         *
         * Login credentials support
         *
         * @param string $login username
         * @param string $pass password
         * @return void
         */
        public function setCredentials($login, $pass)
        {
            $val = base64_encode("{$login}:{$pass}");
            $this->addHeader("Authorization", "Basic {$val}");
        }
    
        /**
         * Add cookie
         *
         * @param string $name
         * @param string $value
         * @return void
         */
        public function addCookie($name, $value)
        {
            $this->_cookies[$name] = $value;
        }
    
        /**
         * Remove cookie
         *
         * @param string $name
         * @return void
         */
        public function removeCookie($name)
        {
            unset($this->_cookies[$name]);
        }
    
        /**
         * Set cookies array
         *
         * @param array $cookies
         * @return void
         */
        public function setCookies($cookies)
        {
            $this->_cookies = $cookies;
        }
    
        /**
         * Clear cookies
         *
         * @return void
         */
        public function removeCookies()
        {
            $this->setCookies([]);
        }
    
        /**
         * Make GET request
         *
         * @param string $uri uri relative to host, ex. "/index.php"
         * @return void
         */
        public function get($uri)
        {
            $this->makeRequest("GET", $uri);
        }
    
        /**
         * Make POST request
         *
         * String type was added to parameter $param in order to support sending JSON or XML requests.
         * This feature was added base on Community Pull Request https://github.com/magento/magento2/pull/8373
         *
         * @param string $uri
         * @param array|string $params
         * @return void
         *
         * @see MagentoFrameworkHTTPClient#post($uri, $params)
         */
        public function post($uri, $params)
        {
            $this->makeRequest("POST", $uri, $params);
        }
    
        /**
         * Get response headers
         *
         * @return array
         */
        public function getHeaders()
        {
            return $this->_responseHeaders;
        }
    
        /**
         * Get response body
         *
         * @return string
         */
        public function getBody()
        {
            return $this->_responseBody;
        }
    
        /**
         * Get cookies response hash
         *
         * @return array
         */
        public function getCookies()
        {
            if (empty($this->_responseHeaders['Set-Cookie'])) {
                return [];
            }
            $out = [];
            foreach ($this->_responseHeaders['Set-Cookie'] as $row) {
                $values = explode("; ", $row);
                $c = count($values);
                if (!$c) {
                    continue;
                }
                list($key, $val) = explode("=", $values[0]);
                if ($val === null) {
                    continue;
                }
                $out[trim($key)] = trim($val);
            }
            return $out;
        }
    
        /**
         * Get cookies array with details
         * (domain, expire time etc)
         *
         * @return array
         */
        public function getCookiesFull()
        {
            if (empty($this->_responseHeaders['Set-Cookie'])) {
                return [];
            }
            $out = [];
            foreach ($this->_responseHeaders['Set-Cookie'] as $row) {
                $values = explode("; ", $row);
                $c = count($values);
                if (!$c) {
                    continue;
                }
                list($key, $val) = explode("=", $values[0]);
                if ($val === null) {
                    continue;
                }
                $out[trim($key)] = ['value' => trim($val)];
                array_shift($values);
                $c--;
                if (!$c) {
                    continue;
                }
                for ($i = 0; $i < $c; $i++) {
                    list($subkey, $val) = explode("=", $values[$i]);
                    $out[trim($key)][trim($subkey)] = trim($val);
                }
            }
            return $out;
        }
    
        /**
         * Get response status code
         *
         * @see libMagentoFrameworkHTTPClient#getStatus()
         *
         * @return int
         */
        public function getStatus()
        {
            return $this->_responseStatus;
        }
    
        /**
         * Make request
         *
         * String type was added to parameter $param in order to support sending JSON or XML requests.
         * This feature was added base on Community Pull Request https://github.com/magento/magento2/pull/8373
         *
         * @param string $method
         * @param string $uri
         * @param array|string $params - use $params as a string in case of JSON or XML POST request.
         *
         * @return void
         * @SuppressWarnings(PHPMD.CyclomaticComplexity)
         * @SuppressWarnings(PHPMD.NPathComplexity)
         */
        protected function makeRequest($method, $uri, $params = [])
        {
            $this->_ch = curl_init();
            $this->curlOption(CURLOPT_URL, $uri);
            if ($method == 'POST') {
                $this->curlOption(CURLOPT_POST, 1);
                $this->curlOption(CURLOPT_POSTFIELDS, is_array($params) ? http_build_query($params) : $params);
            } elseif ($method == "GET") {
                $this->curlOption(CURLOPT_HTTPGET, 1);
            } else {
                $this->curlOption(CURLOPT_CUSTOMREQUEST, $method);
            }
    
            if (count($this->_headers)) {
                $heads = [];
                foreach ($this->_headers as $k => $v) {
                    $heads[] = $k . ': ' . $v;
                }
                $this->curlOption(CURLOPT_HTTPHEADER, $heads);
            }
    
            if (count($this->_cookies)) {
                $cookies = [];
                foreach ($this->_cookies as $k => $v) {
                    $cookies[] = "{$k}={$v}";
                }
                $this->curlOption(CURLOPT_COOKIE, implode(";", $cookies));
            }
    
            if ($this->_timeout) {
                $this->curlOption(CURLOPT_TIMEOUT, $this->_timeout);
            }
    
            if ($this->_port != 80) {
                $this->curlOption(CURLOPT_PORT, $this->_port);
            }
    
            $this->curlOption(CURLOPT_RETURNTRANSFER, 1);
            $this->curlOption(CURLOPT_HEADERFUNCTION, [$this, 'parseHeaders']);
            if ($this->sslVersion !== null) {
                $this->curlOption(CURLOPT_SSLVERSION, $this->sslVersion);
            }
    
            if (count($this->_curlUserOptions)) {
                foreach ($this->_curlUserOptions as $k => $v) {
                    $this->curlOption($k, $v);
                }
            }
    
            $this->_headerCount = 0;
            $this->_responseHeaders = [];
            $this->_responseBody = curl_exec($this->_ch);
            $err = curl_errno($this->_ch);
            if ($err) {
                $this->doError(curl_error($this->_ch));
            }
            curl_close($this->_ch);
        }
    
        /**
         * Throw error exception
         *
         * @param string $string
         * @return void
         * @throws Exception
         */
        public function doError($string)
        {
            throw new Exception($string);
        }
    
        /**
         * Parse headers - CURL callback function
         *
         * @param resource $ch curl handle, not needed
         * @param string $data
         * @return int
         * @throws Exception
         * @SuppressWarnings(PHPMD.UnusedFormalParameter)
         */
        protected function parseHeaders($ch, $data)
        {
            if ($this->_headerCount == 0) {
                $line = explode(" ", trim($data), 3);
                if (count($line) < 2) {
                    $this->doError("Invalid response line returned from server: " . $data);
                }
                $this->_responseStatus = (int)$line[1];
            } else {
                $name = $value = '';
                $out = explode(": ", trim($data), 2);
                if (count($out) == 2) {
                    $name = $out[0];
                    $value = $out[1];
                }
    
                if (strlen($name)) {
                    if ("Set-Cookie" == $name) {
                        if (!isset($this->_responseHeaders[$name])) {
                            $this->_responseHeaders[$name] = [];
                        }
                        $this->_responseHeaders[$name][] = $value;
                    } else {
                        $this->_responseHeaders[$name] = $value;
                    }
                }
            }
            $this->_headerCount++;
    
            return strlen($data);
        }
    
        /**
         * Set curl option directly
         *
         * @param string $name
         * @param string $value
         * @return void
         */
        protected function curlOption($name, $value)
        {
            curl_setopt($this->_ch, $name, $value);
        }
    
        /**
         * Set curl options array directly
         *
         * @param array $arr
         * @return void
         */
        protected function curlOptions($arr)
        {
            curl_setopt_array($this->_ch, $arr);
        }
    
        /**
         * Set CURL options overrides array
         *
         * @param array $arr
         * @return void
         */
        public function setOptions($arr)
        {
            $this->_curlUserOptions = $arr;
        }
    
        /**
         * Set curl option
         *
         * @param string $name
         * @param string $value
         * @return void
         */
        public function setOption($name, $value)
        {
            $this->_curlUserOptions[$name] = $value;
        }
    }

     

    Ajax search product on compare page and add it to the comparison list like GSM Arena.

    Let’s say we want the compare page like GSM Arena Smartphone to compare tool in Magento 2.

    So we have fixed the compare column in Magento at 4 as per our requirement. And we have added the search block to compare the list page.

    We have achieved this type of functionality through Mirasvit Search Autocomplete.

    Please follow the below steps.

    Step 1: Add the search block in list.phtml of compare module by overriding the file in your theme or module and add the below code in the for each of compare item.

    <?php echo $this->getLayout()->createBlock('MagentoFrameworkViewElementTemplate')->setTemplate('Magento_Search::form.mini.phtml')->toHtml(); ?>

    Step 2: You have to make the changes for the injection template so you have to add the below code of layout file which is “catalog_product_compare_index.xml”.

    We have created a different injection template for compare list page so when you search the product and click on it it would not redirect so you can make an ajax call from it.

    <referenceContainer name="after.body.start">
                <block class="MirasvitSearchAutocompleteBlockInjection" name="autocomplete.injection.template" as="autocomplete.injection.template"
                       template="Mirasvit_SearchAutocomplete::injection_templates_compare.phtml"/>          
            </referenceContainer>

    Step 3: You have to copy-paste the injection_template.phtml to code into injection_templates_compare.phtml file and remove the href from <a> tag to stop the redirection from search results.

    step 4: Add the below script to list.phtml of compare module by overriding in your theme or module.

    <script type="text/javascript">
            require(['jquery'], function($){
                /* For Add Product using Search on Compare page */
                $(document).on('click', '.general', function(e){
                    
                    var ttd = $(this).closest('td')[0];
                    //alert(ttd.id);
    
                    var removeproductId = ttd.id;     
                    //alert(removeproductId);
                    
                    var productId = $(this).attr("id");  
                    //alert(productId);                    
    
                    var removeaddUrl = "<?php echo $this->getUrl();?>" + 'compareajax/index/addRemoveBoth/product/' + productId + '?isAjax=true';
                    //alert(removeaddUrl);
                    
                    jQuery.ajax({
                        url: removeaddUrl,
                        type: "POST",                
                        dataType: 'json',
                        data: {
                          removeproduct: removeproductId,
                          product: productId
                        },
                        showLoader: true,
                        success: function (response) {
                            if(response.error == false)
                            {
                                // do something here
                                location.reload(true);
                            }
                            else
                            {
                                alert(response.message);
                            }        
                        },
                        error: function (response) {
                            alert(response.message);                    
                        }
                    });
                });
            });
        </script>

    Step 5: To remove the previous product and to add new searched product in the compare list create a front controller named “AddRemoveBoth.php” on this path “app/code/Magemonkeys/Compareajax/Controller/Index”

    <?php
    
    namespace MagemonkeysCompareajaxControllerIndex;
    
    use MagentoCatalogApiProductRepositoryInterface;
    use MagentoFrameworkDataFormFormKeyValidator;
    use MagentoFrameworkViewResultPageFactory;
    use MagentoFrameworkControllerResultJsonFactory;
    use MagentoFrameworkExceptionNoSuchEntityException;
    use MagentoFrameworkEventManagerInterface as EventManager;
    
    class AddRemoveBoth extends MagentoFrameworkAppActionAction
    {
        /**
         * @var JsonFactory
         */
        protected $resultJsonFactory;
    
        /**
        * @var EventManager
        */
        private $eventManager;
    
        /**
         * Customer id
         *
         * @var null|int
         */
        protected $_customerId = null;
    
        /**
         * Catalog session
         *
         * @var MagentoCatalogModelSession
         */
        protected $_catalogSession;
    
        /**
         * Catalog product compare list
         *
         * @var MagentoCatalogModelProductCompareListCompare
         */
        protected $_catalogProductCompareList;
    
        /**
         * Customer visitor
         *
         * @var MagentoCustomerModelVisitor
         */
        protected $_customerVisitor;
    
        /**
         * Customer session
         *
         * @var MagentoCustomerModelSession
         */
        protected $_customerSession;
    
        /**
         * Item collection factory
         *
         * @var MagentoCatalogModelResourceModelProductCompareItemCollectionFactory
         */
        protected $_itemCollectionFactory;
    
        /**
         * Compare item factory
         *
         * @var MagentoCatalogModelProductCompareItemFactory
         */
        protected $_compareItemFactory;
    
        /**
         * @var MagentoStoreModelStoreManagerInterface
         */
        protected $_storeManager;
    
        /**
         * @var Validator
         */
        protected $_formKeyValidator;
    
        /**
         * @var MagentoFrameworkViewResultPageFactory
         */
        protected $resultPageFactory;
    
        /**
         * @var ProductRepositoryInterface
         */
        protected $productRepository;
    
        protected $_compareHelper;
    
        protected $_urlInterface;
    
        protected $_blockFactory;
    
        public function __construct(
            MagentoFrameworkAppActionContext $context,
            MagentoCatalogModelProductCompareItemFactory $compareItemFactory,
            MagentoCatalogModelResourceModelProductCompareItemCollectionFactory $itemCollectionFactory,
            MagentoCustomerModelSession $customerSession,
            MagentoCustomerModelVisitor $customerVisitor,
            MagentoCatalogModelProductCompareListCompare $catalogProductCompareList,
            MagentoCatalogModelSession $catalogSession,
            MagentoStoreModelStoreManagerInterface $storeManager,
            Validator $formKeyValidator,
            PageFactory $resultPageFactory,
            ProductRepositoryInterface $productRepository,
            JsonFactory $resultJsonFactory,
            EventManager $eventManager,
            MagentoCatalogHelperProductCompare $compareHelper,
            MagentoFrameworkUrlInterface $urlInterface,
            MagentoFrameworkViewElementBlockFactory $blockFactory
        ) {
            $this->resultJsonFactory = $resultJsonFactory;
            $this->_storeManager = $storeManager;
            $this->_compareItemFactory = $compareItemFactory;
            $this->_itemCollectionFactory = $itemCollectionFactory;
            $this->_customerSession = $customerSession;
            $this->_customerVisitor = $customerVisitor;
            $this->_catalogProductCompareList = $catalogProductCompareList;
            $this->_catalogSession = $catalogSession;
            $this->_formKeyValidator = $formKeyValidator;
            $this->resultPageFactory = $resultPageFactory;
            $this->productRepository = $productRepository;
            $this->eventManager = $eventManager;
            $this->_compareHelper = $compareHelper;
            $this->_urlInterface = $urlInterface;
            $this->_blockFactory = $blockFactory;
            parent::__construct($context);
        }
    
        public function execute()
        {
            $resultJson = $this->resultJsonFactory->create();
    
            $result = array();
            $error = true;
            $message = '';
    
            // TODO: Validate this is a POST request.
    
            $removeproductId = (int)$this->getRequest()->getParam('removeproduct');
            if ($removeproductId) {
                $storeId = $this->_storeManager->getStore()->getId();
                try {
                    $product = $this->productRepository->getById($removeproductId, false, $storeId);
                } catch (NoSuchEntityException $e) {
                    $product = null;
                    $message = __('Product does not exist');
                    $error = true;
                }
    
                if ($product) {
                    $item = $this->_compareItemFactory->create();
                    if ($this->_customerSession->isLoggedIn()) {
                        $item->setCustomerId($this->_customerSession->getCustomerId());
                    } elseif ($this->_customerId) {
                        $item->setCustomerId($this->_customerId);
                    } else {
                        $item->addVisitorId($this->_customerVisitor->getId());
                    }
    
                    $item->loadByProduct($product);
    
                    if ($item->getId()) {
                        $item->delete();
                        $productName = $this->_objectManager->get(MagentoFrameworkEscaper::class)
                            ->escapeHtml($product->getName());
                        $message = __('You removed product %1 from the comparison list.', $productName);
                        $this->_eventManager->dispatch('catalog_product_compare_remove_product',['product' => $item]);
                        $this->_objectManager->get('MagentoCatalogHelperProductCompare')->calculate();
                    }
    
                    $removehtml = '';
                    if($this->_compareHelper->hasItems()){ 
                        $compItem = $this->_compareHelper->getItemCollection();
                        $i = 1;
                        $responseArray = array();
                        foreach($compItem->getData() as $comitem){
                            $productNew = $this->_objectManager->get('MagentoCatalogModelProduct')->load($comitem['entity_id']);
                            $imageBlock = $this->_blockFactory->createBlock('MagentoCatalogBlockProductListProduct');
                            $productImage = $imageBlock->getImage($productNew, 'product_comparison_list');
                            $imageUrl = $productImage->getImageUrl();
                            $responseArray[$i]['id'] = $comitem["entity_id"];
                            $responseArray[$i]['url'] = $imageUrl;
                            $i++;
                        }
    
                        for ($j = 1; $j <= 4; $j++)
                        {
                            if(isset($responseArray[$j]))
                            {
                                $removehtml .= '<div class="compare-item active" data-itemid="'.$responseArray[$j]['id'].'">
                                    <div class="compare-item-number">'. $j .'</div>
                                    <a class="compare-item-remove removecompareajaxlink" href="javascript:void(0)" data-productid="'.$responseArray[$j]['id'].'" data-url="'. $this->_urlInterface->getUrl().'compareajax/index/removeCompare/product/'.$responseArray[$j]['id'] .'?isAjax=true"><i class="fa fa-remove"></i></a>
                                    <img src="'. $responseArray[$j]['url'] .'" class="imageCompare" />
                                </div>';
                            }
                            else
                            {
                                $removehtml .= '<div class="compare-item active" data-itemid="">
                                    <div class="compare-item-number">'. $j .'</div>
                                </div>';
                            }
                        }
                    }
                    $message = __('You removed product from the comparison list.');
                    $result = array('html'=>$removehtml,'id'=>$removeproductId);
                    $error = false;
                }
    
            }
    
    
            /*************************************************/
    
    
    
            $count = $this->_compareHelper->getItemCount();
            if($count >= 4) {
                $message = __('You can add the compared products under 4 item(s)');
                $error = true;
                return $resultJson->setData([
                    'message' => $message,
                    'data' => $result,
                    'error' => $error
                ]);
            }
    
            $productId = (int)$this->getRequest()->getParam('product');
            if ($productId && ($this->_customerVisitor->getId() || $this->_customerSession->isLoggedIn())) {
                $storeId = $this->_storeManager->getStore()->getId();
                try {
                    $product = $this->productRepository->getById($productId, false, $storeId);
                } catch (NoSuchEntityException $e) {
                    $product = null;
                    $message = __('Product does not exist');
                    $error = true;
                }
    
                if ($product) {
                    $this->_catalogProductCompareList->addProduct($product);
                    $this->_eventManager->dispatch('catalog_product_compare_add_product', ['product' => $product]);
                }
    
                $this->_objectManager->get('MagentoCatalogHelperProductCompare')->calculate();
                $html = '';
                if($this->_compareHelper->hasItems()){ 
                    $compItem = $this->_compareHelper->getItemCollection();
                    $i = 1;
                    $responseArray = array();
                    foreach($compItem->getData() as $comitem){
                        $productNew = $this->_objectManager->get('MagentoCatalogModelProduct')->load($comitem['entity_id']);
                        $imageBlock = $this->_blockFactory->createBlock('MagentoCatalogBlockProductListProduct');
                        $productImage = $imageBlock->getImage($productNew, 'product_comparison_list');
                        $imageUrl = $productImage->getImageUrl();
                        $responseArray[$i]['id'] = $comitem["entity_id"];
                        $responseArray[$i]['url'] = $imageUrl;
                        $i++;
                    }
    
                    for ($j = 1; $j <= 4; $j++)
                    {
                        if(isset($responseArray[$j]))
                        {
                            $html .= '<div class="compare-item active" data-itemid="'.$responseArray[$j]['id'].'">
                                <div class="compare-item-number">'. $j .'</div>
                                <a class="compare-item-remove removecompareajaxlink" href="javascript:void(0)" data-productid="'.$responseArray[$j]['id'].'" data-url="'. $this->_urlInterface->getUrl().'compareajax/index/removeCompare/product/'.$responseArray[$j]['id'] .'?isAjax=true"><i class="fa fa-remove"></i></a>
                                <img src="'. $responseArray[$j]['url'] .'" class="imageCompare" />
                            </div>';
                        }
                        else
                        {
                            $html .= '<div class="compare-item active" data-itemid="">
                                <div class="compare-item-number">'. $j .'</div>
                            </div>';
                        }
                    }
                }
                $message = __('Product successfully added in comparison list');
                $result = array('html'=>$html,'id'=>$productId);
                $error = false;
            }
    
            return $resultJson->setData([
                        'message' => $message,
                        'data' => $result,
                        'error' => $error
            ]);
        }
    }
    ?>

    You can change or modify the above steps as per your requirement.

     

    How to Detect Mobile Device in Magento 2?

    I created Index.php controller for that at app/code/Vendor/Modulename/Controller/Index/ and add this below code :

    <?php
    
    namespace VendorModulenameControllerIndex;
    
    class Index extends MagentoFrameworkAppActionAction {
    
        /**
         * @var MagentoFrameworkViewResultPageFactory
         */
        protected $resultPageFactory;
    
        /**
         * @var MagentoFrameworkHTTPHeader
         */
        protected $httpHeader;
    
        /**
         * @param MagentoFrameworkAppActionContext      $context
         * @param MagentoFrameworkHTTPHeader             $httpHeader
         * @param MagentoFrameworkViewResultPageFactory $resultPageFactory
         */
        public function __construct(
            MagentoFrameworkAppActionContext $context,
            MagentoFrameworkHTTPHeader $httpHeader,
            MagentoFrameworkViewResultPageFactory $resultPageFactory
        ) {
            $this->httpHeader = $httpHeader;
            $this->resultPageFactory = $resultPageFactory;
            parent::__construct($context);
        }
        /**
         * Detect Mobile view or Desktop View
         *
         * @return void
         */
        public function execute() {
            $resultPage = $this->resultPageFactory->create();
            $userAgent = $this->httpHeader->getHttpUserAgent();
            $isMobile = Zend_Http_UserAgent_Mobile::match($userAgent, $_SERVER);
            if ($isMobile) {
                $resultPage->getConfig()->getTitle()->prepend(__("Mobile View")); // Mobile view logic add here
            } else {
                $resultPage->getConfig()->getTitle()->prepend(__("Desktop View")); // Desktop view logic add here
            }
            return $resultPage;
        }
    
    }

    You can add this above code in your controller or any file. You need to inject MagentoFrameworkHTTPHeader class into your construct.

    How to get category by url key in Magento 2?

    Here is the code for getting category by category URL key.

    The module name is: Magemonkeys_Categorydata

    Create a block file: Categoryurl.php

    <?php
    namespace  MagemonkeysCategorydataBlockIndex;
    
    class Categoryurl extends MagentoFrameworkViewElementTemplate {
    {
     protected $filter;
     public function __construct(
          MagentoCatalogBlockProductContext $context,
          MagentoCatalogModelCategoryFactory $categoryFactory,
          array $data = []
        ) {
         parent::__construct($context, $data);
         $this->categoryFactory = $categoryFactory;
     }
     public function getCategory($urlKey)
     {
       $categories = $this->categoryFactory->create()->getCollection()
                 ->addAttributeToFilter('url_key', $urlKey)
                 ->addAttributeToSelect(['entity_id']);
         return $categories;
     }
    }

    Now you can get category by using this function getCategory($urlKey) in your phtml file

    $urlKey = 'bags';
    $category = $this->getCategory($urlKey);
    print_r($category->getData());

    You can get an array of category data.

     

    How to set custom tab on product detail page to download and show pdf links?

    If you want to set one more custom tab to show pdf & download them then follow the below steps.

    Step 1: Create a file like  app/code/Magemonkeys/Custompdftab/registration.php

    <?php 
    MagentoFrameworkComponentComponentRegistrar::register(
        MagentoFrameworkComponentComponentRegistrar::MODULE,
        'Magemonkeys_Custompdftab',
        __DIR__
    );
    ?>

    Step 2: Create a file like app/code/Magemonkeys/Custompdftab/etc/module.xml

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

    Step 3: Create a file like  app/code/Magemonkeys/Custompdftab/Helper/Data.php

    <?php
    
    namespace MagemonkeysCustompdftabHelper;
    
    use MagentoFrameworkAppHelperAbstractHelper;
    use MagentoFrameworkAppHelperContext;
    
    class Data extends AbstractHelper
    {
        public function stringToTable($text, $colSeparator = '|', $rowSeparator = '||')
        {
            $rows = explode($rowSeparator, $text);
            if (!$rows) return false;
            $html = '<table>';
            foreach ($rows as $row) {
                if ($row) {
                    $html .= '<tr>';
                    $columns = explode($colSeparator, $row);
                    $w=count($columns);
                    foreach ($columns as $column) {
                        $html .= '<td style="width:'. 100/$w .'%">' . $column . '</td>';
                    }
                    $html .= '</tr>';
                }
            }
            $html .= '</table>';
    
            return $html;
        }
    
        public function applicationsRender($applications,  $separator = "||"){
    
            //echo 'called';exit;
            if(!$applications)
                return;
    
            $html = '';
            $_elements = '';
    
            if(strpos($applications,':') > 0) {
                $_items = explode('.',$applications);
                natcasesort($_items);
                foreach($_items as $_item){
                    $_item = explode(':',$_item);
    
                    if($_item[0] == '')
                        continue;
    
                    $html .= '<ul class="applications">';
                    $html .= trim($_item[0]).': ';
                    $_elements = @explode($separator,$_item[1]);
    
                    foreach ($_elements as $element){
                        $html .= '<li>'.trim($element).'</li>';
                    }
                    $html .= '</ul>';
                }
            } else {
                $html .= '<ul class="applications">';
                $_items = explode($separator,$applications);
                natcasesort($_items);
                foreach ($_items as $_item){
                    $html .= '<li>'.$_item.'</li>';
                }
                $html .= '</ul>';
            }
    
            return $html;
    
        }
    }

    Step 4: Create a file like  app/code/Magemonkeys/Custompdftab/view/frontend/layout/catalog_product_view.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">
        <body>
            <referenceBlock name="product.info.details">
                <block class="MagentoCatalogBlockProductView" name="custom-tab" template="Magemonkeys_Custompdftab::product/view/details/custom_tab.phtml" group="detailed_info">
                    <arguments>
                        <argument name="css_class" xsi:type="string">newtabclass</argument>
                        <argument translate="true" name="title" xsi:type="string">Documentatie</argument>
                        <argument name="sort_order" xsi:type="string">60</argument>
                    </arguments>
                </block>
            </referenceBlock>
        </body>
    </page>

    Step 5 : Create file like  app/code/Magemonkeys/Custompdftab/view/frontend/templates/product/view/details/custom_tab.phtml

    <?php 
        $_product = $block->getProduct();
        $sku = $_product->getSku();
        $file = $_product->getAgreementFile();
        $objectManager = MagentoFrameworkAppObjectManager::getInstance();
    
        $fileSystem = $objectManager->create('MagentoFrameworkFilesystem');
        $mediaPath = $fileSystem->getDirectoryRead(MagentoFrameworkAppFilesystemDirectoryList::MEDIA)->getAbsolutePath();
    
        $dir = '/'.$mediaPath.'/'.'catalog/product/file/'.$file;
        $dir2 = '/'.$mediaPath.'/'.'file/'.$sku;
    
        $flag = FALSE;
        $flag1 = true;
    ?>
    <?php if(file_exists($dir) && $file != ''):{
            $flag1 = false;
            if($file){ $flag = TRUE; } ?>
            <a class="download-file" href="<?php echo $block->getBaseUrl(); ?>pub/media/catalog/product/file/<?php echo basename($file) ?>" target="_blank"><?php echo str_replace('.pdf', '', $file) ?></a>
        <?php } elseif(file_exists($dir2) && $flag1):{
          if ($dh = opendir($dir2)){   
            while (($file = readdir($dh)) !== false){
              if ($file != '.' && $file != '..') {
                if($file){ $flag = TRUE;  }?>
                <a class="download-file1" href="<?php echo $block->getBaseUrl(); ?>pub/media/file/<?php echo $sku.'/'.basename($file) ?>" target="_blank"><?php echo str_replace('.pdf', '', $file) ?></a>
        <?php 
                }     
              }
            }
          }
        ?>
    <?php else: ?>
        <?php echo "There is no file"; ?>
    <?php endif; ?>
    
    <?php if($flag == TRUE): ?>
        <script>
            require(['jquery', 'jquery/ui'], function($){
               $('#tab-label-custom-tab').css('display','block');
            });
        </script>
    <?php endif; ?>

    That’s it…

    Now, you can check your product detail page. Your custom tab will be showing after all default tabs.

    How to check programmatically elasticsearch is enabled or not in Magento2?

    If your site has installed a third-party search engine and you want to know the elastic search is enabled or not, you can identify it.

    First, you need to instantiate the MagentoElasticsearchModelConfig class to your __construct() method.

    And then you can use the below code.

    <?php
    namespace MagemonkeysElasticsearchModel;
    
    use MagentoElasticsearchModelConfig;
    
    class ConfigData
    {
        /**
         * @var Config
         */
        private $config;
    
        public function __construct(
            Config $config
        ) {
            $this->config = $config;
        }
    
        /**
         * @return bool
         */
        public function isElasticsearchEnabled()
        {
            return $this->config->isElasticsearchEnabled();
        }
    }

    Now, you need to call below command.

    $result = $this->isElasticsearchEnabled();

    The result will be true if your site has enabled elastic search.

    How to create custom link for my account section in Magento 2?

    In this tutorial, we are going to discuss that how can we create a custom link for ‘my account’ section in Magento 2 for customer’s dashboard.

    The first thing we need to do is to create a layout XML file in our theme. Let’s call it customer_account.xml

    Path & file: app/design/frontend/Magemonkeys/magetheme/Magento_Customer/layout/customer_account.xml

    Add below code in your layout XML file.

    <referenceBlock name="customer_account_navigation">
        <block class="MagentoFrameworkViewElementHtmlLinkCurrent" name="customer-account-navigation-custom-link" after="-" >
             <arguments>
                 <argument name="label" xsi:type="string" translate="true">Custom Label</argument>
                 <argument name="path" xsi:type="string">custom-link-path</argument>
             </arguments>
        </block>
    </referenceBlock>

    That’s it. Hope you will able to create a custom link by using the above method.