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.

    FIVE Tips to Boost Magento Store’s Security

    Magento is a very safe & stable eCommerce platform adopted by 250,000+ businesses globally. But, it’s very much possible that a Magento store can get hacked or compromised if the server/site/system left unaudited.

    Only in the previous month, we received tons of calls from different Magento store owner whose store were hacked. In today’s article, we’re writing Major tips that can help your store to achieve a shield against any future hack.

    1. Upgrade Magento store to the latest version:
    In many types of research, it’s very much clear that non-upgraded stores (Magento 1.X) have the HIGHEST chances of getting hacked.  Thus, upgrade your store with the latest version of Magento as in the latest version Magento has introduced tons of security patches.

    2. IP restriction:
    Make sure your Magento’s admin panel should be opened with limited numbers of IP(s) of yours & your staff. This won’t allow hackers or bots to access your system.

    3. Install a malware & vulnerability monitor:
    Have a malware & vulnerability monitor installed in your Magento store so that you will be alerted asap when something will go wrong?

    4. Basic admin-level changes:
    Make admin-level changes such as,
    – Using unique admin panel route
    – Enable ReCaptcha to bypass bots.
    – Disable Admin Account Sharing
    – Enable the Add Secret Key to URLs

    5. Regular audit & testing:
    Audit & test your Magento store at regular intervals which will help you to understand if there is any security bug with the order flow or not.

    CONCLUSION

    We suggest you hire Magento developer to process the above tasks. Because a certified developer has an eye to identifying the weak coding parts or security bugs. And he/she can make your site functional as per Magento’s coding standards.

    Everything you should know about Magento Migration

    If you’re still on Magento 1, take notice that Adobe officially announced it will stop Magento 1 support at the end of June 2020. After that, your eCommerce store could be more vulnerable to security violations, performance problems, and module updates as you maintain it on your own.

    OVERVIEW OF THE MIGRATION PROCESS
    The process of Magento 1 to Magento 2 migration includes three major steps: pre-migration, migration, and post-migration.

    Pre-migration: During this stage, we review the website’s data and content to get a clear idea of how much manual labor should be performed, prepare design specifications, and write a project outline with major stages and deadlines for each phase.

    Migration: The migration process starts with setting up a testing environment by moving Magento 2 to a new server. Then themes, extensions, plugins, data, and content are moved from Magento 1 to Magento 2.

    Post-migration: Last but not least is synchronizing your order history and customer data to perform a smooth shift from Magento 1 to Magento 2.

    Breakdown of Magento Migration Timeline

    1. Drawing up a migration plan: 3 weeks
    2. Preparing a test environment: 1-2 days
    3. Implementing extensions and custom development: 3 weeks
    4. Migrating data: 1-2 days
    5. Creating a design for Magento 2: 2-4 weeks
    6. Additional database synchronization: 1-2 days
    7. Magento 2 store launch on a live server: ~1 week

    Why do you need a certified agency to perform migration?

    MIGRATION IS NOT COPY-PASTE:

    Magento 2 data migration is the crucial stage in the transfer process. One needs to have sufficient technical knowledge and extensive experience to react quickly in case you lose database assets — specifically, the customer and product data. Moreover, your blog content, meta titles, and customer orders should be transported inseparably.

    MESSY CODE AND SHODDY DATA STRUCTURE:

    During the migration period, one can face numerous problems related to the data structure. For example, if the core Magento 1 code is messy or inappropriately configured, then the standard Migration Tool and scripts won’t work. There may be a number of situations where the data structure was so screwed up that we had to reinstall Magento 1 to structure the data properly before starting Magento 2 migration. A certified Magento expert knows how to handle such situations.

    SEO:

    If migration doesn’t perform by any expert then there are chances that your store’s URL may get changed which could create a disaster for your site’s current ranking. An expert knows how to handle such situations.

    Apart from the above three, there are many technical reasons why migration should be done by expert agencies only. Magento 2 users are availing sales benefits after migration, so if you are still on Magento 1 then don’t delay it further and migrate it today.

    Add cms page via install script in magento 2

    Today we are going to share that how to add CMS page via install script in CMS page admin area.

    This is our module : Magemonkeys_Cmspagescript

    So we need to create InstallData.php file in setup folder

    Here is code

    <?php
    
    namespace MagemonkeysCmspagescriptSetup;
    
    use MagentoCmsModelPageFactory;
    use MagentoFrameworkSetupInstallDataInterface;
    use MagentoFrameworkSetupModuleContextInterface;
    use MagentoFrameworkSetupModuleDataSetupInterface;
    
    class InstallData implements InstallDataInterface
    {
        private $pageFactory;
        
        public function __construct(PageFactory $pageFactory)
        {
            $this->pageFactory = $pageFactory;
        }
    
        public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
        {
            $cmsPageDataarray = [
                'title' => 'My cms page', 
                'page_layout' => '1column', 
                'meta_keywords' => 'My Page keywords',
                'meta_description' => 'My Page description',
                'identifier' => 'my-page',
                'content_heading' => 'my cms page',
                'content' => "<h1>This is hello world my page</h1>",
                'is_active' => 1,
                'stores' => [0],
                'sort_order' => 0
            ];
    
            $this->pageFactory->create()->setData($cmsPageDataarray)->save();
        }
    }

    Now all we have to do is to run below commands:

    php bin/magento setup:upgrade
    php bin/magento cache:clean

    That’s it. Hope that helps!

    Magento 2 move wishlist link after add to cart button in product detail page

    Today I am going to share that how we can move wishlist icon under product info using xml.

    For moving wishlist block you have to create catalog_product_view.xml in your custom theme or custom module.

    Create app/design/frontend/[Theme Vendor Name]/[Theme Name]/Magento_Catalog/layout/catalog_product_view.xml and add below code:

    <?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>
            <move element="product.info.social" destination="product.info.form.content" after="product.info.addtocart" />
        </body>
    </page>

    After doing above process, run the below commands.

    php bin/magento cache:clean
    php bin/magento cache:flush

    There you will find wishlist link shown after add to cart button.

    How to add category drop down in system configuration Magento 2?

    For any custom module we can add category drop down selection in system configuration.

    Let’s start with creating a module names Magemonkeys_Categorydropdown

    in adminhtml we can create file system.xml

    Here is code for call category selection

    <group id="categoryselection_setting" translate="label" type="text" default="1" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
        <label>Setting</label>
        <field id="categorylist" translate="label" type="multiselect" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Please Select Category</label>
            <source_model>MagemonkeysCategorydropdownModelConfigSourceCategorylist</source_model>
        </field>
    </group>

    and then we can create file Categorylist.php in MagemonkeysCategorydropdownModelConfigSource

    <?php
    namespace MagemonkeysCategorydropdownModelConfigSource;
    
    use MagentoFrameworkOptionArrayInterface;
    
    class Categorylist implements ArrayInterface
    {
        protected $_categoryHelper;
    
        public function __construct(MagentoCatalogHelperCategory $catalogCategory)
        {
            $this->_categoryHelper = $catalogCategory;
        }
    
        public function getStoreCategories($sorted = false, $asCollection = false, $toLoad = true)
        {
            return $this->_categoryHelper->getStoreCategories($sorted , $asCollection, $toLoad);
        }
    
        public function toOptionArray()
        {
    
            $arr = $this->toArray();
            $ret = [];
    
            foreach ($arr as $key => $value)
            {
    
                $ret[] = [
                    'value' => $key,
                    'label' => $value
                ];
            }
    
            return $ret;
        }
    
        public function toArray()
        {
    
            $categories = $this->getStoreCategories(true,false,true);
    
            $catagoryList = array();
            foreach ($categories as $category){
    
                $catagoryList[$category->getEntityId()] = __($category->getName());
            }
    
            return $catagoryList;
        }
    
    }

    That’s it.

    How to add custom product sorter in magento 2?

    This article is a solution If you want to add new custom sorter or filter options such as below:

    New product,
    Name, Instock,
    Price Low to high,
    Price High to Low.

    Create a custom module and follow the below step.

    1. Create file di.xml on app/code/Magemonkeys/Sorting/etc

    <?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="MagentoCatalogModelConfig">
            <plugin name="Magemonkeys_Sorting::addCustomSortOptions" type="MagemonkeysSortingPluginModelConfig" />
        </type>
        <type name="MagentoCatalogBlockProductProductListToolbar">
            <plugin name="Magemonkeys_Sorting::implementCustomSortOptions" type="MagemonkeysSortingPluginProductProductListToolbar" />
        </type>
    </config>

    2. Create file Config.php on app/code/Magemonkeys/Sorting/Plugin

    <?php
    namespace MagemonkeysSortingPluginModel;
    
    class Config
    {    
        public function afterGetAttributeUsedForSortByArray(MagentoCatalogModelConfig $catalogConfig, $options)
        {
            //Remove default sorting options
            unset($options['position']);
            unset($options['name']);
            unset($options['price']);
    
            //New sorting options
            $options['newest'] = __('New product');        
            $options['is_salable'] = __('Stock');
            $options['name'] = __('Name');        
            $options['price_desc'] = __('Price High to Low');
            $options['price_asc'] = __('Price Low to High');
    
            return $options;
        }
    }

    3. Create file Toolbar.php on app/code/Magemonkeys/Sorting/Product/ProductList

    <?php
    namespace MagemonkeysSortingPluginProductProductList;
    
    class Toolbar
    {    
        public function aroundSetCollection(
            MagentoCatalogBlockProductProductListToolbar $toolbar,
            Closure $proceed,
            $collection
        ) {
            $this->_collection = $collection;
            $currentOrder = $toolbar->getCurrentOrder();
            $currentDirection = $toolbar->getCurrentDirection();
            $result = $proceed($collection);
    
            if ($currentOrder) {
                switch ($currentOrder) {
    
                case 'newest':
                    if ($currentDirection == 'desc') {
                        $this->_collection->getSelect()->order('e.created_at ASC');
                    } elseif ($currentDirection == 'asc') {
                        $this->_collection->getSelect()->order('e.created_at DESC');
                    }
                break;
    
                case 'is_salable': 
                    if ($currentDirection == 'desc') {
                        $this->_collection->getSelect()->order('qty ASC');
                    } elseif ($currentDirection == 'asc') {
                        $this->_collection->getSelect()->order('qty DESC');
                    }               
                              
                break;            
    
                case 'name':
                    if ($currentDirection == 'desc') {
                        $this->_collection->getSelect()->order('name ASC');
                    } elseif ($currentDirection == 'asc') {
                        $this->_collection->getSelect()->order('name DESC');
                    }
                break;
    
                case 'price_desc':            
                    if ($currentDirection == 'desc') {
                        $this->_collection->getSelect()->order('price ASC');
                    } elseif ($currentDirection == 'asc') {
                        $this->_collection->getSelect()->order('price DESC');
                    }
                break;
    
                case 'price_asc':
                    if ($currentDirection == 'desc') {
                        $this->_collection->getSelect()->order('price DESC');
                    } elseif ($currentDirection == 'asc') {
                        $this->_collection->getSelect()->order('price ASC');
                    }
                break;            
    
                default:        
                    $this->_collection
                        ->setOrder($currentOrder, $currentDirection);
                break;
    
                }
            }        
            //var_dump($currentDirection);
            return $result;
        }
    }

     

    Solve : Call to a member function setUseContainer() on boolean in customer wishlist page

    If you face this type of fatal error on customer wishlish page.

    Fatal error: Uncaught Error: Call to a member function setUseContainer() on boolean in /var/www/vhosts/test.com/vendor/magento/module-wishlist/Block/Customer/Wishlist.php:127 Stack trace: #0 /var/www/vhosts/test.com/vendor/magento/framework/View/Element/AbstractBlock.php(286): MagentoWishlistBlockCustomerWishlist->_prepareLayout() #1 /var/www/vhosts/test.com/vendor/magento/framework/View/Layout/Generator/Block.php(149): MagentoFrameworkViewElementAbstractBlock->setLayout(Object(MagentoFrameworkViewLayoutInterceptor)) #2 /var/www/vhosts/test.com/vendor/magento/framework/View/Layout/GeneratorPool.php(81): MagentoFrameworkViewLayoutGeneratorBlock->process(Object(MagentoFrameworkViewLayoutReaderContext), Object(MagentoFrameworkViewLayoutGeneratorContext)) #3 /var/www/vhosts/test.com/vendor/magento/framework/View/Layout.php(352): MagentoFrameworkViewLayoutGeneratorPool->process(Object(Mag in /var/www/vhosts/test.com/vendor/magento/module-wishlist/Block/Customer/Wishlist.php on line 127

    Then, follow below instruction to solve it.

    Override wishlist_index_index.xml file in your theme and paste below code

    .
    .
    .
        <block class="MagentoWishlistBlockCustomerWishlist" name="customer.wishlist" template="view.phtml" cacheable="false">
            <block class="MagentoThemeBlockHtmlPager" name="wishlist_item_pager"/>
    .
    .
    .

    in app/design/frontend/Magestore/theme/Magento_Wishlist/layout/wishlist_index_index.xml

    After processing above steps, run below commands

    - php bin/magento setup:upgrade
    - php bin/magento setup:di:compile
    - php bin/magento cache:clean

    That’s it. Now, you can check your customer wishlist page. Your wishlist page error should be resolved.

    FAQ(s) you should know before upgrading your Magento store

    Thinking to upgrade your Magento store? Have a look at the below questions before you do it.

    Q1. How much time does it take to upgrade a Magento store to the latest version?

    A1. It depends on how big your site is, but on average, it can take between 1 to 3 months.

    Q2. Will my web store speed get affected after upgrading Magento?

    A2. It will get affected, but positively. Speed will improve.

    Q3. Will my store’s extension work the same way after upgrading the Magento store?

    A3. Majorly every Magento extension in the market is compatible, but if your store’s any specific extension won’t be compatible, then we’ll share alternatives in advance.

    Q4. Will my store face downtime during the upgrade process?

    A4. No, we’ll run the process on our local server so your live web store won’t get affected.

    Q5. How frequently will I need to upgrade?

    A5. Adobe acquired Magento frequently and launched an upgrade. If your store is not in Magento 2, then we suggest you do it once. Upgradation in internal versions of Magento 2 can wait.

    Q6. What if I don’t want to upgrade and still want my store to secure?

    A6. Well, in that case, we suggest you opt for Mage Monkeys M1 Support

    PayPlug and PayPal problem while checkout in Magento 2.3.3 and above version

    Checkout this article if you face an error like below.


    [2020-09-23 21:55:18] main.CRITICAL: Report ID: webapi-5f6bc446bb808; Message: Property "DisableTmpl" does not have accessor method "getDisableTmpl" in class "MagentoQuoteApiDataPaymentInterface". {"exception":"[object] (Exception(code: 0): Report ID: webapi-5f6bc446bb808; Message: Property "DisableTmpl" does not have accessor method "getDisableTmpl" in class "Magento\Quote\Api\Data\PaymentInterface". at /home/solivrfrpa/www/vendor/magento/framework/Webapi/ErrorProcessor.php:208, LogicException(code: 0): Property "DisableTmpl" does not have accessor method "getDisableTmpl" in class "Magento\Quote\Api\Data\PaymentInterface". at /home/solivrfrpa/www/vendor/magento/framework/Reflection/NameFinder.php:100)"} []

    Follow below step-by-step guide to solve the issue.

    Step 1 : Go to this path /vendor/magento/module-checkout/view/frontend/web/js/action/select-payment-method.js

    Step 2 : Overwrite this select-payment-method.js in your theme  /app/design/frontend/[VendorName]/[theme]/Magento_Checkout/web/js/action/select-payment-method.js

    Step 3 : Comment below mention code in line no.15 approx.

    /*
    if (paymentMethod) {
        paymentMethod.__disableTmpl = {
            title: true
        };
    }
    */

    Step 4 : After that run below mentioned commands

    - php bin/magento setup:upgrade
    - php bin/magento setup:di:compile
    - php bin/magento cache:clean

    That’s it…

    Now, you can check your payment method while placing the order on checkout page. Your payment method related issue should have resolved.

    Magento 2: add new custom product attribute in product tabs

    If you want to add a new custom attribute in product tabs, then you you need to add the below code:

    <referenceBlock name="product.info.details"> 
     <block class="MagentoCatalogBlockProductView" name="product.info.keyfeature" as="keyfeature" template="Magento_Catalog::product/view/attribute.phtml" group="detailed_info">
     <arguments>
     <argument name="at_call" xsi:type="string">getKeyFeatures</argument>
     <argument name="at_code" xsi:type="string">key_features</argument>
     <argument name="css_class" xsi:type="string">keyfeature</argument>
     <argument name="title" translate="true" xsi:type="string">Key Features</argument>
     <argument name="sort_order" xsi:type="string">20</argument>
     </arguments>
     </block>
     </referenceBlock>

    in your theme/Magento_Catalog/layout/catalog_product_view.xml file between the body tag.

    Here I have set “key_features” product attribute in product tabs.