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: How to detect user is from mobile or desktop? A way to display content based on device

    If you want to show the different contents for Mobile and Desktop devices.
    Please follow the below code.

    Create a controller in your custom module and add the below code.
    <?php
    namespace VendorModuleControllerIndex;
    
    use MagentoFrameworkAppActionContext;
    use MagentoFrameworkViewResultPageFactory;
    
    class Devicedetect extends MagentoFrameworkAppActionAction
    {
        /**
         * @var PageFactory
         */
        protected $_pageFactory;
    
        /**
         * initialization
         *
         * @param Context $context
         * @param PageFactory $pageFactory
         */
        public function __construct(
            Context $context,
            PageFactory $pageFactory
        ) {
            $this->_pageFactory = $pageFactory;
            parent::__construct($context);
        }
        
        /**
         * Execute method
         */
        public function execute()
        {
            $resultPage = $this->_pageFactory->create();
            $userAgent  = $this->getRequest()->getHeader('useragent');
            $server     = $this->getRequest()->getServer();
             
            //Check device is Desktop
            $isDesktopDevice = Zend_Http_UserAgent_Desktop::match($userAgent, $server);
            if ($isDesktopDevice) {
                $resultPage->getConfig()->getTitle()->set(__("Desktop Detect"));
            }
            //Check device is Mobile
            $isMobileDevice = Zend_Http_UserAgent_Mobile::match($userAgent, $server);
            if ($isMobileDevice) {
                $resultPage->getConfig()->getTitle()->set(__("Mobile Detect"));
            }  
            return $resultPage;
        }
    }

     

    Magento 2: Grid UI Component Filter issue while collection which is using JOINs with some additional tables

    – The Filter issues persist when your collections come up with multiple tables by join queries.

    Please check the following changes in the collections file as below:
    You can force the table alias using this addFilterToMap() Method. 
    Apply this addFilterToMap() method in your _initSelect() Method of your main collection class.

    Add the following code to Your collection class :

    protected function _initSelect()
    {
        $this->addFilterToMap('xyz', 'main_table.xyz');
    
        parent::_initSelect();
    }

     

    Please let us know if this article is helpful to you.

    Thanks!

    Set shipping fields read-only and set default values for checkout page

    Please follow the below steps to set static value for shipping address fields and set default values on checkout page.

    Step 1: Create a module and in app/code/Magemonkeys/Customfield/di.xml put the below code in it.

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
        <type name="MagentoCheckoutBlockCheckoutLayoutProcessor">
            <plugin name="room_number" type="MagemonkeysCustomfieldPluginCheckoutModelLayoutProcessor" sortOrder="100"/>
        </type>
    </config>

    Step 2: Create a LayoutProcessor.php at this location app/code/Magemonkeys/Customfield/Plugin/Checkout/Model.

    <?php
    
    namespace MagemonkeysCustomfieldPluginCheckoutModel;
    
    use MagentoCheckoutBlockCheckoutLayoutProcessor as ChekcoutLayerprocessor;
    
    class LayoutProcessor
    {
    
        public function afterProcess(ChekcoutLayerprocessor $subject, array $jsLayout)
        {
    		
    		
    
    		$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
                ['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['street']['children'][0]['value'] = 'Street Name';
    			
    			
    			$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
                ['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['city']['value'] = 'City Name';
    			
    			$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
                ['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['postcode']['value'] = '12345';
    			
    			$jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']
                ['children']['shippingAddress']['children']['shipping-address-fieldset']['children']['region_id']['value'] = 14;
    			
    		
    
            $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children']
            ['shippingAddress']['children']['shipping-address-fieldset']['children']['room_number'] = [
                'component' => 'Magento_Ui/js/form/element/abstract',
                'config' => [
                    'customScope' => 'shippingAddress',
                    'template' => 'ui/form/field',
                    'elementTmpl' => 'Magemonkeys_Customfield/form/room_button',
                    'options' => [],
                    'id' => 'room_number'
                ],
                'dataScope' => 'shippingAddress.room_number',
                'label' => 'Room Number if known',
                'provider' => 'checkoutProvider',
                'visible' => true,
                'validation' => [],
                'sortOrder' => 50,
                'id' => 'room_number'
            ];
    
            return $jsLayout;
        }
    }

     

    Magento 2: Disable payment method based on customer group using observer

    Create the events.xml file in your custom module and add the below code.
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
        <event name="payment_method_is_active">
            <observer name="cust_payment_disable" instance="VendorModuleObserverPaymentDisable" />
        </event>
    </config>
    Create observer PaymentDisable.php file in your customer module and add below code.
    <?php
    namespace VendorModuleObserver;
    use MagentoFrameworkEventObserver;
    use MagentoFrameworkEventObserverInterface;
    
    class PaymentDisable implements ObserverInterface {
        protected $_customerSession;
        public function __construct(
           MagentoCustomerModelSession $customerSession,
           MagentoCustomerModelGroupRegistry $groupRegistry
        ) {
           $this->_customerSession = $customerSession;
           $this->groupRegistry = $groupRegistry;
        }
        public function execute(Observer $observer) {
           $payment_method_code = $observer->getEvent()->getMethodInstance()->getCode();
           if ($payment_method_code == 'purchaseorder') {
               $result = $observer->getEvent()->getResult();
                if ($this->_customerSession->isLoggedIn()) {
                    $customer = $this->_customerSession->getCustomer();
                    $customerGroup = $customer->getGroupId();
                    if($customerGroup == 4){
                        $result->setData('is_available', false);
                    }
                }
            }
        }
    }

     

    How to get and retrive WYSIWYG editor data in Magento 2 frontend?

    If you are trying to print WYSIWYG editor content into the reading format in the code condition when content is added from the WYSIWYG editor from the admin panel, and content displays something weird, then you can solve the issue by following below steps.

    Step 1: Create Registration

    Create registration.php file in the app/code/Magemonkeys/Wysiwygdata folder with the following code.

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

     

    Step 2: Create a module

    Create a module.xml file in the app/code/Magemonkeys/Wysiwygdata/etc folder with the following code.

    <?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="Magemonkeys_Wysiwygdata" setup_version="1.0.0"></module>
    </config>

     

    Step 3: Create a Helper

    Create a Data.php file in the app/code/Magemonkeys/Wysiwygdata/Helper with the following code.

    Add a dependency Zend_Filter_Interface to your block

    <?php
        namespace MagemonkeysWysiwygdataHelper;
     
        use MagentoFrameworkAppHelperAbstractHelper;
        
        class Data extends AbstractHelper
        {
            protected $templateProcessor;
            public function __construct(
                Context $context,
                Zend_Filter_Interface $templateProcessor
            )
            {
                $this->templateProcessor = $templateProcessor;
                parent::__construct($context);
            }
            public function getWysiwygContent($content)
            {
                try{
                    return $this->templateProcessor($content);
                }catch (Exception $e){
                    return false;
                }
            }
     
        }

     

    Now when you need to retrive data, you will just need to load helper and use getWysiwygContent() function by passing content

    For Example,

    Load helper “MagemonkeysWysiwygdataHelperData” using $_helper object

    after loading helper you can access

    $_helper->getWysiwygContent($content);

    Magento 2: How to add close button on error and success message?

    Step1 : Override message.js in current theme file on the following path.

    – /app/design/frontend/Magemonkey/child/Magento_Theme/web/js/view/

    – Add the below code:

    /**
     * Copyright © Magento, Inc. All rights reserved.
     * See COPYING.txt for license details.
     */
    
    /**
     * @api
     */
    define([
        'jquery',
        'uiComponent',
        'Magento_Customer/js/customer-data',
        'underscore',
        'escaper',
        'jquery/jquery-storageapi'
    ], function ($, Component, customerData, _, escaper) {
        'use strict';
    
        return Component.extend({
            defaults: {
                cookieMessages: [],
                messages: [],
                allowedTags: ['div', 'span', 'b', 'strong', 'i', 'em', 'u', 'a']
            },
    
            /**
             * Extends Component object by storage observable messages.
             */
            initialize: function () {
                this._super();
    
                this.cookieMessages = _.unique($.cookieStorage.get('mage-messages'), 'text');
                this.messages = customerData.get('messages').extend({
                    disposableCustomerData: 'messages'
                });
    
                // Force to clean obsolete messages
                if (!_.isEmpty(this.messages().messages)) {
                    customerData.set('messages', {});
                }
    
                $.mage.cookies.set('mage-messages', '', {
                    samesite: 'strict',
                    domain: ''
                });
            },
    
            RemoveMessage: function () {
                setTimeout(function () {
                    $('.page.messages').hide()
                }, 1000);
            },
            /**
             * Prepare the given message to be rendered as HTML
             *
             * @param {String} message
             * @return {String}
             */
            prepareMessageForHtml: function (message) {
                return escaper.escapeHtml(message, this.allowedTags);
            }
        });
    });

    Step2 : Override messages.phtml in current theme file on the following path.

    – /app/design/frontend/Magemonkey/child/Magento_Theme/templates/

    – Add the below code:

    <?php
    /**
     * Copyright © Magento, Inc. All rights reserved.
     * See COPYING.txt for license details.
     */
    ?>
    <div data-bind="scope: 'messages'">
        
            <!-- ko if: cookieMessages && cookieMessages.length > 0 -->
            <div aria-atomic="true" role="alert" data-bind="foreach: { data: cookieMessages, as: 'message' }" class="messages">
                <div data-bind="attr: {
                    class: 'message-' + message.type + ' ' + message.type + ' message',
                    'data-ui-id': 'message-' + message.type
                }">
                    <div data-bind="html: $parent.prepareMessageForHtml(message.text)"></div>
                   <div class="close"  data-bind="click: $parent.RemoveMessage"></div> 
                </div>
            </div>
            
            <!-- /ko -->
    
            <!-- ko if: messages().messages && messages().messages.length > 0 -->
            <div aria-atomic="true" role="alert" class="messages" data-bind="foreach: {
                data: messages().messages, as: 'message'
            }">
                <div data-bind="attr: {
                    class: 'message-' + message.type + ' ' + message.type + ' message',
                    'data-ui-id': 'message-' + message.type
                }">
                    <div data-bind="html: $parent.prepareMessageForHtml(message.text)"></div>
                    <div class="close"  data-bind="click: $parent.RemoveMessage"></div>
                </div>
            </div>
            
            <!-- /ko -->
        
    </div>
    <script type="text/x-magento-init">
        {
            "*": {
                "Magento_Ui/js/core/app": {
                    "components": {
                            "messages": {
                                "component": "Magento_Theme/js/view/messages"
                            }
                        }
                    }
                }
        }
    </script>

    that’s it

    Here is message design and output :

    Magento 2 : Get request params in your controller file

    If you want get query string params in controller file, then you can try like below.

    <?php
    namespace MageMonkeyCheckReqControllerIndex;
    
    use MagentoFrameworkControllerResultFactory;
    use MagentoFrameworkAppActionContext;
    use MagentoFrameworkViewResultPageFactory;
     
    class Index extends MagentoFrameworkAppActionAction
    {
         protected $resultPageFactory;
        
        public function __construct(
            Context $context,
            PageFactory $resultPageFactory
        ) {
        
            parent::__construct($context);
            $this->resultPageFactory = $resultPageFactory;
        }
        
        public function execute()
        {	
            $params = $this->getRequest()->getParams();
            /* print_r($params); die */
            $this->_view->loadLayout();        
            $this->_view->getLayout()->initMessages();
            $this->_view->renderLayout();
        }
    }

    Magento 2 : Redirect custom page after login using plugin

    Create di.xml and add the below code
    Magemonkey/Redirect/etc/frontend/di.xml

    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
      <type name="MagentoCustomerControllerAccountLoginPost">
        <plugin name="redirect_custom_url" type="MagemonkeyRedirectPluginRedirectCustomUrl" sortOrder="1" />
      </type>
    </config>

    Create the plugin
    Magemonkey/Redirect/Plugin/RedirectCustomUrl.php

    <?php
    namespace MagemonkeyRedirectPlugin;
    class RedirectCustomUrl
    {
        public function __construct(
            MagentoStoreModelStoreManagerInterface $storeManager,
            MagentoFrameworkAppHttpContext $authContext,
            MagentoFrameworkAppResponseRedirectInterface $redirect,
            MagentoFrameworkAppRequestInterface $request        
        ){
    
            $this->storeManager = $storeManager;
            $this->authContext = $authContext;
            $this->redirect = $redirect;
            $this->_request = $request;        
        }
        public function afterExecute(MagentoCustomerControllerAccountLoginPost $subject,$result)
        {
            $currentWebsiteId = $this->storeManager->getStore()->getWebsiteId();
            $isLoggedIn = $this->authContext->getValue(MagentoCustomerModelContext::CONTEXT_AUTH);
            if ($isLoggedIn){
                $customUrl = 'customurl.html';
                $result->setPath($customUrl);
        	}
            return $result;
        }
    }

     

    Magento 2 – How to change local date to UTC date?

    You can try below code to change local date to UTC date.

    <?php
    namespace MagemonkeyUtcDateModel;
    
    use MagentoFrameworkStdlibDateTimeTimezoneLocalizedDateToUtcConverterInterface;
    
    class UtcDate
    {
        /**
         * @var LocalizedDateToUtcConverterInterface
         */
        private $localtoutc;
    
        public function __construct(
            LocalizedDateToUtcConverterInterface $localtoutc
        ) {
            $this->localtoutc = $localtoutc;
        }
    
        /**
         * convert UTC Date
         *
         * @return string
         */
        public function convertUTCdate(): string
        {
            $localDate = date('m-d-Y');
            return $this->localtoutc->convertLocalizedDateToUtc($localDate);
        }
    }

     

    How to change order status using cron?

    Step 1: First you need to add registration.php file in the following path: app/code/Magemonkey/Orderstatus/

    Add below code in it.

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

    Step 2: Next, you need to add module.xml file in the following path:
    app/code/Magemonkey/Orderstatus/etc/

    Add below code in it.

    <?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="Magemonkey_Orderstatus" setup_version="1.0.0">
        </module>
    </config>

     

    Step 3: Now you need to add Orderstatus.php file in the following path: app/code/Magemonkey/Orderstatus/Cron/

    Add below code in it.

    <?php
    
    namespace MagemonkeyOrderstatusCron;
    
    class Orderstatus
    {
    	protected $_logger;
    	protected $_orderCollectionFactory;
    	protected $orderObj;
    	protected $timezoneInterface;
       	
       	public function __construct(
           PsrLogLoggerInterface $logger,
           MagentoSalesModelResourceModelOrderCollectionFactory $orderCollectionFactory,
           MagentoSalesModelOrder $orderObj,
           MagentoFrameworkStdlibDateTimeTimezoneInterface $timezoneInterface
       	) 
        {
         	$this->_logger = $logger;
         	$this->_orderCollectionFactory = $orderCollectionFactory;
         	$this->_orderObj = $orderObj;
         	$this->_timezoneInterface = $timezoneInterface;
        }
    
    	public function execute()
    	{
    		$paymentMethod = 'stripe_payments_sofort';
    		/* get order collection */
    		$collection = $this->_orderCollectionFactory->create()->addFieldToSelect('*')
    		->addFieldToFilter('status', ['in' => 'pending']);
    
    	     /* join with payment table */
    	    $collection->getSelect()
    	    ->join(
    	        ["sop" => "sales_order_payment"],
    	        'main_table.entity_id = sop.parent_id',
    	        array('method')
    	    )
    	    ->where('sop.method = ?',$paymentMethod);
    
    	    /* get current date time */
    	    $current_datetime = $this->_timezoneInterface->date()->format('Y-m-d H:i:s');
    	    
    	    /* set default time in second */
    		$set_default_time = 3600;
    	    foreach ($collection->getData() as $key => $orders) {
    	    	
    	    	$created_at = $orders['created_at'];
    			$dateTimeZone_order = $this->_timezoneInterface->date(new DateTime($created_at))->format('Y-m-d H:i:s');
    
    			/* get time diff from order datetime and current datetime */
    			$time_diff = strtotime($current_datetime) - strtotime($dateTimeZone_order);
    
    			/* change order status to processing */
    			if($set_default_time <= $time_diff){
    				/* @var $order MagentoSalesModelOrder */
    				$order = $this->_orderObj->load($orders['entity_id']);
    			    $order->setStatus("processing");
    			    $order->save();
    			}
    	    }
    	}
    }