Sunday, 24 March 2019

Magento 2 - Admin Menu Search

Today am very happy to announce that my Extension is accepted by Magento Marketplace.
I got this Idea about a year ago, I started developing it. But due to my busy office and personal work I was no able to complete it. 

In the mean time I thought somebody would definitely create it and submit something similar, but luckly no one did. 😊 So then I thought I should definitely complete and submit it for Magento community. After spending some time fixing all the bugs and proper review, I submitted for Magento's approval.

It took over a month for Manual QA and Marketing team's review. QA just found one bug which I fixed it quickly and resubmitted. 

OK, that's the story of it. Here's the link for my simple extension for Magento 2.

A quick brief about the extension, Admin Menu Search. This will help you to search through all the available Links in Admin panel(Backend) Menu(Navigation). I hope this will be extremely helpful for newbies developers, website administrators, content writers, Marketing teams to quickly go through the options available for this in one place.

Detailed description with screenshots is provided on the extension page. Please check out to see its complete list of features.

Please install and try the extension. Comment if it is useful and if you find any bugs.

Monday, 26 March 2018

Add Custom JS on Magento 2 admin

I was creating a new extension that involves customization on Magento 2 Admin panel. As part of it, I needed to add custom javascript on the admin panel.

There are two ways you can add your custom JS on admin panel.

  • Including it with blocks
  • Including it in head and loading by require js

Including it with Blocks

create folder structure like this view/adminhtml/layout/
create new file default.xml inside it.

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nonamespaceschemalocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
         <referencecontainer name="js">
            <block class="Magento\Backend\Block\Template" name="admincustomjs" template="Your_Modulename::system/config/additional_script.phtml">
        </block></referencecontainer>
    </body>
</page>

If you want to include your script in footer just replace the referencecontainer name="footer"

In additional_script.phtml you can include your custom script like this.
<script type="text/javascript">
    require(
        ['jquery'],
        function($) {
            $(function() {
              console.log('custom script included successfully');
            });
          });
</script>

If you see page source of the system config page or any other page in admin panel, you can see there are few custom scripts included by Magento Just above the Footer tag.

Including it in head and loading by require js

When using this method don't use default.xml to include your script in <head> tag. This will load your script BEFORE the main require js is loaded and it will create a JS error.

create folder structure like this  view/adminhtml/layout/adminhtml_system_config_edit.xml

You can change the xml file name inside layout folder as per your admin page action. EG: customer_index_edit.xml


<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
<link src="Your_Modulename::js/custom_require.js"/>
    </head>
    <body/>
</page>


You need to place the custom_require.js inside view/adminhtml/web/js/ 
In custom_require.js use require method to include your custom javascript.

require([
    'Your_Modulename/custom_system_config'
]);
Create custom_system_config.js file inside view/adminhtml/web/
place your custom javascript in this file

define([
  "jquery"
],&nbsp
function($) {
  "use strict";
    $(document).ready(function($){
        console.log("custom script included successfully");
    });
    return;
});
If you want to include any third party min JS files you can place it here and you can call its API. 
Using this method, your custom javascript file will be called using require js.

You can see Magento 2 core modules uses both the methods. 

For First method, you can refer vendor\magento\module-paypal\view\adminhtml\layout\adminhtml_system_config_edit.xml

For Second method, you can refer vendor\magento\module-customer\view\adminhtml\layout\customer_index_edit.xml

Sunday, 2 April 2017

Custom logger in magento 2 | FirePhp | Console log

In my previous post I have explained how to use logger in Magento 2. This post details using FirePHP logging in Magento 2.

This awesome logging will output the Log data on your Browser console. I have tested on Chrome & Firefox. In this post I will be referencing Chrome.

Step 1:
Install Extension for Chrome.
You need to install two extensions, one is regular logging and Other is for logging during Ajax requests.

Step 2:
Now we need to add our codes to ignore the regular logging to files and output the logs on our browser console.
Creating Logger instance using DI is explained in previous post. Please go though if you haven't yet.
Magento 2 includes FirePHP by default. We just need to call it for logging.

After creating the $this->_logger Object. use below code.

$this->_logger->pushHandler(new \Monolog\Handler\FirePHPHandler());
$this->_logger->addDebug('Debug log');

There are multiple types for logging.

$this->_logger->addInfo();
$this->_logger->addNotice();
$this->_logger->addError();
$this->_logger->addWarning();
$this->_logger->addEmergency();
$this->_logger->addCritical();
$this->_logger->addAlert();

NOTE: If you want to log an array(), you need to pass it as a second argument which is optional.

$this->_logger->addDebug('Debug array', $arrayVar);

Example output















Friday, 31 March 2017

Magento 2 cannot login on frontend

After installing Sample data on localhost, I was not able to login with the dummy user login.
Am using xampp on windows 7, and working on Chrome browser.

Recently I found I cannot add any products to cart and found a solution for it.

The same solution applies here. This issue is due to form key mismatch. As I suggested in previous post, this is recommended only for testing environment i.e only on your localhost.

Quick Fix.


Go to vendor/magento/module-customer/Controller/Account/LoginPost.php execute() method.
Comment out the first if condition which checks the session and posted form key.

// if ($this->session->isLoggedIn() || !$this->formKeyValidator->validate($this->getRequest())) {

      // /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */

      // $resultRedirect = $this->resultRedirectFactory->create();

      // $resultRedirect->setPath('*/*/');

      // return $resultRedirect;

// } 

Magento 2 cannot add products to cart

On localhost environment, there is this annoying issue on CHROME browser. When you add products to cart, you will see no errors displayed, but products will not be added to cart.

Few of the stack overflow post suggest to change the localhost URL to 127.0.0.1 OR adding a vhost entry to change the localhost url to something else. I have found a quick fix for this issue. This fix is not recommended for Production environment.  This is only for the developers who are working on their local environment.


Problem


There is a form_key mismatch. Form key which gets posted during add to cart action and the stored Session value form key is mismatched.


Quick fix.


Go to vendor/magento/module-checkout/Controller/Cart/Add.php execute() method.
Comment out the first if condition which checks the session and posted form key.

//if (!$this->_formKeyValidator->validate($this->getRequest())) {

        //return $this->resultRedirectFactory->create()->setPath('*/*/');

//}

Wednesday, 3 June 2015

Get system config values in magento 2

How to get data from Magento 2 System Configuration ? Here's how to.

We need to call the default method available.

Just Use \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
In your constructor argument and create an Object $this->scopeConfig = $scopeConfig;

Now to Get the configuration value just use
$this->_scopeConfig->getValue('dev/debug/template_hints', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);

First argument is the value which we need from system configuration and the Second argument is the Store scope.

Demo

public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
) {
$this->_scopeConfig = $scopeConfig;
}


public function helloWorld(){

   $showTemplateHint =  $this->_scopeConfig->getValue('dev/debug/template_hints', \Magento\Store\Model\ScopeInterface::SCOPE_STORE);

}

Friday, 29 May 2015

Logging in magento 2 including FirePHP

Magento 2 uses Monolog library to log messages. More information about the monolog is here

You can find the Library package in the following location in Magento 2
MAGENTO2_ROOT/vendor/monolog

Log files will be created inside var/log folder.

To add logging to your class we need to add an instance of the monolog class. As magento 2 uses Dependency Injection(DI)  we need to pass the instance in the constructor of your class.

Just for testing, we are going to add this in one of the magento's default class. Go to app/code/Magento/Cms/Block/Page.php

And add the below lines After Protected $pageConfig


/**
* @var \Psr\Log\LoggerInterface
*/
protected $_logger;

And add this line \Psr\Log\LoggerInterface $logger,  as the parameter of the __construct() 

Now we need to create an object. so add these line inside the function

$this->_logger = $logger;
$this->_logger->addDebug('some text or variable');

So Finally our Constructor function will look like this.


public function __construct(
        \Magento\Framework\View\Element\Context $context,
        \Magento\Cms\Model\Page $page,
        \Magento\Cms\Model\Template\FilterProvider $filterProvider,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Cms\Model\PageFactory $pageFactory,
        \Magento\Framework\View\Page\Config $pageConfig,
        \Psr\Log\LoggerInterface $logger,
        array $data = []
    ) {
        parent::__construct($context, $data);
        // used singleton (instead factory) because there exist dependencies on \Magento\Cms\Helper\Page
        $this->_page = $page;
        $this->_filterProvider = $filterProvider;
        $this->_storeManager = $storeManager;
        $this->_pageFactory = $pageFactory;
        $this->pageConfig = $pageConfig;
        $this->_logger = $logger;
        $this->_logger->addDebug('some text or variable');
    }

TO USE FIREPHP LOGGING

Detailed Article here

Monolog has inbuilt FirePHP logging library. FirePHP is used to send log messages to the FireBug Console. More information here. Install FirePHP Firefox / Chrome addon to use this.

Now to Use FirePHP in Magento 2 just use this line
$this->_logger->pushHandler(new \Monolog\Handler\FirePHPHandler());
above
$this->_logger->addDebug('some text here');

You can see the message available on the Firebug Console panel, instead of creating a log file.

Friday, 22 May 2015

Configurable Product not adding to cart

Community edition 1.9 and Enterprise edition 1.14 both have this problem. There will be a memory exhausted issue or the browser keeps loading forever.

There is a patch for this fix which is available on github.
More discussion can be found on the magento.stackexchange website.

Remove maintenance mode in magento 2

Removing Maintenance mode in Magento 2 is extremely simple as in previous Magento versions.

The .maintenance.flag file is located under var folder in Magento 2. Delete this file to remove the maintenance mode.

Thursday, 22 January 2015

Set / Change Meta title and description in Magento 2


SET PAGE META VIA BLOCK


You need to place this code inside your _prepareLayout() function in your Block file. Below is the complete function.

public function _prepareLayout()
{

   //set page Meta's
   $this->pageConfig->setKeywords('Hello Metakeyword');
   $this->pageConfig->setDescription('Hello Metadescription');

   return parent::_prepareLayout();

} 

SET PAGE META VIA LAYOUT XML

Open your xml file inside your layout folder and place this code above the body tag.

<head>
    <meta name="description" content="XML Hello metadesc"/>
    <meta name="keywords" content="XML Hello keywords"/>

</head>

NOTE:  When you try to add title via both the methods first preference will be given to the block method(php file).

Sunday, 18 January 2015

Set page title on Magento 2

I was working on creating a simple Hello world module in Magento 2. Tutorials from other websites, there was only instructions to create the module and then I found the page title was empty.

I did a little search in the core files and found the code to set page title.

SET PAGE TITLE VIA BLOCK

$this->pageConfig->getTitle()->set(__('Hello World'));

You need to place this code inside your _prepareLayout() function in your Block file. Below is the complete function.

public function _prepareLayout()
{

   //set page title
   $this->pageConfig->getTitle()->set(__('Hello Index Test'));

   return parent::_prepareLayout();

} 

SET PAGE TITLE VIA LAYOUT XML

Open your xml file inside your layout folder and place this code above the body tag.

<head>
    <title>SAMPLE TITLE</title>

</head>

NOTE:  When you try to add title via both the methods first preference will be given to the block method(php file).

Monday, 12 January 2015

Set/Enable developer mode in Magento 2

Magento 2 is already out for developers for testing and contributing improvements. After installing magento 2, you need to enable the Developer mode to show the errors on browser. Else, the errors will be logged into a separate file under var/report.

There are multiple ways to enable a developer mode
Via Console
Run the following command "php bin\magento deploy:mode:developer"

Edit env.php
'MAGE_MODE' => 'developer'  add this line on your env.php file below 'x-frame-options'

OR
Just add this below line on your index.php file
$_SERVER['MAGE_MODE'] = 'developer';

Place the code above on line 1. Above all the codes which was there already.

Wednesday, 7 January 2015

Magento 2 Installation Guide.

Magento 2 is under development phase and there are beta release on Github which are free to explore. You can download Magento 2 here.

INSTALLATION

* Once you have downloaded magento2 zip file from Github, you can extract it to your htdocs folder(in xampp).

* Next thing is to Install the Composer. Without installing composer we cannot run Magento 2.

* Steps for Installing Composer on Windows machine can be found here. Follow steps from 1 to 5 if  latest xampp version is installed.

* Step for Installing Composer on Linux machine can be found here.

* Once Composer is installed properly, Now you can install magento 2. Find the composer.JSON file inside your extracted magento 2 folder and Right click on it and select composer Install.

* Now the composer will install the necessary library files and you are good to go.

* Run the file via your Browser like the usual magento Installation.


NOTE: Magento 2 requires PHP version 5.4 or higher.

Complete installation instructions with Screenshots is available on Magestore website.

You can get the Usefull links to study and get to know more about Magento 2 from my next post. Click here.

Magento 2 study guide & useful websites to get to know about it


The new version of Magento has a significant changes in the architecture when comparing to its 1.* versions. I have started learning Magento 2 and found some of the websites that explains the changes and improvements very clearly. These are from the Masters of Magento.

Am not going to explain the changes that are in Magento 2, instead I will give you all the Links that are useful for you to explore and learn it by yourself.

OFFICIAL WIKI
It's good to have the Magento have their own well formatted Wiki for Magento 2. The Wiki explains all the technology changes in Magento 2. You can go to the Official WIKI page here.

THE MASTERS

I have also found other websites that are extremely useful to study magento 2. They are,
* The Alan Kent's Blog. (Magento's chief architect)
* The Inchooers website.
* Magestore's website.
* An Awesome explanation for Dependency Injection(DI) can be found here. The website explains the DI for Symphony, Yet the concept for the DI is the Same for all. More explanation for DI can be found from the Jeff More Presentation.

START EXPLORING WITH THESE INITIATIVES

Magestore have developed a banner module for Magento 2. You can visit their website here to View the Demo and download the banner module.

You can get the THEME for Magento 2 here. Uber theme offers this free Magento 2 theme and the Live Demo of the theme can be found on the link provided.

SAMPLE DATA FOR MAGENTO 2

Uber theme also provides the Sample data for magento 2. You can visit their website here. This website clearly explains the installation steps and configuring magento 2 with Screenshots.

Go crazy on New Magento 2.

Friday, 19 December 2014

Magento remove selected items from shopping cart

When you have too many products in you shopping cart and you want to remove particular products out of it, you only need to do it one-by-one. And its really frustrating especially for testers. Magento does not provide the feature to remove selected products by default.

I have developed a code that could allow users to select the products which they want to remove by simply checking the products and click the remove button. And they all will be removed at a time.


Please download the extension here. Extract it and move it inside appropriate folders.
Tested on Version 1.7.2 and 1.8.1 community edition.

Monday, 8 December 2014

Magento update backorder programatically

To update a products backorder status i wrote a custom script. My script reads the SKU's from the csv file and checks if the product exists and updates its backorder status.

Below is the code.

$products = Mage::getModel('catalog/product')->loadByAttribute('sku', $sku);
if($products)
{     
   // get product's stock data such quantity, in_stock etc
   $stockData = Mage::getModel('cataloginventory/stock_item')->loadByProduct($products);
           
   //to update backorder
   $stockData->setData('use_config_backorders', '0'); //not to use config settings           
   /*0 = No Backorders
   1 = Allow Qty Below 0
   2 = Allow Qty Below 0 and Notify Customer*/
   $stockData->setData('backorders', '1');
                       
   // then set product's stock data to update
   $stockData->save();
           
   // call save() method to save your product with updated data
   $products->save();                
}


You can download the complete code here.  It reads the csv file and checks for the products, If it is found the data are updated. Upon running this file. It will output all the products status (Found, Not found, How many not found) in the webpage. It also Writes the missing sku's in a new CSV file.

Tuesday, 25 November 2014

Magento CSV import error show which row value is skipped

During the Batch CSV import, some of the rows will be skipped due to missing required values or any such errors. On the import process page magento will throw error message like below by default.

BEFORE
From this error message we won't be able to identify exactly which row is skipped. So I have made a modification to the magento files and after that

AFTER

Now we will know which row is skipped and can check for errors in it. Let me explain the few modification which i did to achieve this.

Step 1:

copy the file Customer.php which is under the path "app/code/core/Mage/Customer/Model/Convert/Adaptor/" to this path "app/code/local/Mage/Customer/Model/Convert/Adaptor/"

DO NOT EDIT THE CORE FILE. ALWAYS OVERRIDE IT USING LOCAL FOLDER

Step 2:

open the Customer.php in your editor and look for the function name "saveRow". It will be around line 418.
Inside this function you will see the error messages text. For Example:

 $message = Mage::helper('customer')->__('Skipping import row, required field "%s" is not defined. ', 'website');

Replace above line with this.

 $message = Mage::helper('customer')->__('Skipping import row, required field "%s" is not defined. Unique value to identify in CSV <strong>%s</strong> ', 'website', $importData['email']);

There will be similar error messages thrown for various reasons like customer group not found. website id does not exist and so on.. You can use the above customization to all those errors thrown.

The $importData['email'] is the one which contains the row value which is unique in case on Customer import. you can also use $importData['firstname'] or $importData['lastname'] according to your needs. The values inside the quotes are the column names from the CSV.

Similarly For Product batch import you can modify the file which is under. app/code/core/Mage/Ccatalog/Model/Convert/Adaptor/Product.php 

NOTE: When you import the CSV. look for any Special characters. This may cause errors during import. To import CSV with special characters edit your .htaccess file and add this line to it AddDefaultCharset UTF-8

Magento Customer Import - Convert plain text password to magento format.

One of my recent task is to import about 10k customers into Magento database.

First thing came into my mind is to export the existing customer from magento and use the csv file to fill in the new customer values and import them back.
But after exporting the few existing customers, i came to know that the CSV header fields which Magento exported is not suitable for the import and missing fields for password, customer address etc.

After few searches, i found this SAMPLE CSV file. click to download

Filled in the CSV file and for the password_hash field, I had to develop a customer script to convert plain text password to Magento format password.

My custom script is below. It reads the CSV file which contains plain text password, Encrypts it and writes to a new CSV file. After you CSV file is ready go to the admin panel. In the menu select System -> Import/Export -> Dataflow- Profiles. You will see "import customer". Click on it and upload your CSV file and click "save & continue edit" button. Then Choose the imported file from the dropdown and click Run.

All the customers will be imported with their previous password and addresses.

<?php
$row = 1;
$fp = fopen('var/log/ss1-pass.csv', 'w');
$csvHeader = array('Text','Encrypted');
fputcsv( $fp, $csvHeader,",");

//generate random string for salt
function generateRandomString($length = 2) {
    $characters = '123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
        $randomString .= $characters[rand(0, strlen($characters) - 1)];
    }
    return $randomString;
}

if (($handle = fopen("ss1.csv", "r")) !== FALSE) {

    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
      $row++;
      $plainText =  trim($data[0]);
      $salt = generateRandomString(2);
      $encrypted = md5($salt.$plainText).":".$salt;
      fputcsv($fp, array($plainText,$encrypted), ",");
      //if($row==20){break;}
    }
   
 fclose($handle);
 fclose($fp);
}
?>


Friday, 18 July 2014

Magento fedex SoapFault exception

Well, when it comes to any third party Shipping API's it a big headache for the developers. Especially when the worlds largest Shipping company FedEx changed their URL for the webservice request without any prior notification and the URL's are hardcoded.

So, How does it affect Magento ?

I was using the FedEx shipping method and everything works good in the Frontend of the website. But when i create a Shipping Label from the Admin i got an error message "An error occured while creating shipping label". And when i checked the LOG file, there was only EXCEPTION log created.

Ok, so after checking the exception log i found that there was a "SoapFault exception" error.
Later i found that it was the FedEx the culprit.

FIXES

Go to the path: app/code/core/Mage/Usa/Model/Shipping/Carrier
open Fedex.php file

On the line number 135 you will find such code with the fedex webservice url hardcoded

$client->__setLocation($this->getConfigFlag('sandbox_mode')
            ? 'https://wsbeta.fedex.com:443/web-services/rate'
            : 'https://ws.fedex.com:443/web-services/rate'
        );

Replace this with this new code.

$client->__setLocation($this->getConfigFlag('sandbox_mode')
            ? 'https://wsbeta.fedex.com:443/web-services'
            : 'https://ws.fedex.com:443/web-services'
        );


and that's it. The error must be Fixed. If it still exists please check your server configuration for the SOAP and WSDL configuration. It must be using older version. Try upgrading it.

NOTE: If you are creating Shipping Labels you Need to change the URL on the WSDL file also. The URL will be found at the very bottom of the code. 

Tuesday, 1 July 2014

Magento Add to cart not working for new products block

I came across this Add to cart issue after upgrading from version 1.7.2 to 1.8.1.
Then after a long time search, luckly i found the cause.

In Magento version 1.8.1 there was an update to the add to cart feature with the inclusion of "Form keys". Magento has implemented this feature to prevent XSS attacks.

To know more about Form keys click here.

SOLUTION : Change the button type from "button" to "submit"

NOTE : Enabling All cache type may not solve the issue. Disable only "Blocks HTML output", you can enable other cache types.