Custom column with filter on admin grid in magento

Recently, I have worked on magento admin grid and I want to add custom column with filter on customer grid without adding column in customer table. I have faced lot of issue during this development and after digging continuously 2 hour I found terms addExpressionAttributeToSelect  . This is finally solved my problem.

I did customization on _prepareCollection function and  _prepareColumns function .It worked fine.

In _prepareCollection function, add below expression after getting the $collection

$collection->addExpressionAttributeToSelect('column_column', new Zend_Db_Expr("CUSTOM_MYSQL_EXPRESSSION"), array());

And add following column code in _prepareColumn method.

$this->addColumn('custom_column', array(
'header' => Mage::helper('customer')->__('CUSTOM COLUMN'),
'index' => 'custom_column',
));

Magento 2 : Show multiple store view in admin custom module grid.

Recently, I have created custom module without UI component. I want to add store view field on that. I have added in form easily but put me in trouble little bit during grid. To show multiple store in admin custom module grid, I have used renderer and following changes in grid.php file

 Custom\Slider\Block\Adminhtml\Slide\Grid.php

$this->addColumn(
    'store_ids',
    [
        'header' => __('Store Views'),
        'index' => 'store_ids',                        
        'type' => 'store',
        'store_all' => true,
        'store_view' => true,
        'renderer'=>  'Custom\Slider\Block\Adminhtml\Slide\Edit\Tab\Renderer\Store',
        'filter_condition_callback' => [$this, '_filterStoreCondition']
    ]
);

Custom\Slider\Block\Adminhtml\Slide\Edit\Tab\Renderer\Store.php

', $scopes) . __(' [deleted]');
            return $out;
        }

        if (empty($origStores) && !$skipEmptyStoresLabel) {
            return '';
        }
        if (!is_array($origStores)) {
            $origStores = [$origStores];
        }

        if (empty($origStores)) {
            return '';
        } elseif (in_array(0, $origStores) && count($origStores) == 1 && !$skipAllStoresLabel) {
            return __('All Store Views');
        }

        $data = $this->_getStoreModel()->getStoresStructure(false, $origStores);

        foreach ($data as $website) {
            $out .= $website['label'] . '
';
            foreach ($website['children'] as $group) {
                $out .= str_repeat(' ', 3) . $group['label'] . '
';
                foreach ($group['children'] as $store) {
                    $out .= str_repeat(' ', 6) . $store['label'] . '
';
                }
            }
        }

        return $out;
    }

    /**
     * Render row store views for export
     *
     * @param \Magento\Framework\DataObject $row
     * @return \Magento\Framework\Phrase|string
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    public function renderExport(\Magento\Framework\DataObject $row)
    {
        $out = '';
        $skipAllStoresLabel = $this->_getShowAllStoresLabelFlag();
        // $origStores = $row->getData($this->getColumn()->getIndex());
        $origStores = explode(',',$row->getData($this->getColumn()->getIndex()));

        if ($origStores === null && $row->getStoreName()) {
            $scopes = [];
            foreach (explode("\n", $row->getStoreName()) as $k => $label) {
                $scopes[] = str_repeat(' ', $k * 3) . $label;
            }
            $out .= implode("\r\n", $scopes) . __(' [deleted]');
            return $out;
        }

        if (!is_array($origStores)) {
            $origStores = [$origStores];
        }

        if (in_array(0, $origStores) && !$skipAllStoresLabel) {
            return __('All Store Views');
        }

        $data = $this->_getStoreModel()->getStoresStructure(false, $origStores);

        foreach ($data as $website) {
            $out .= $website['label'] . "\r\n";
            foreach ($website['children'] as $group) {
                $out .= str_repeat(' ', 3) . $group['label'] . "\r\n";
                foreach ($group['children'] as $store) {
                    $out .= str_repeat(' ', 6) . $store['label'] . "\r\n";
                }
            }
        }

        return $out;
    }
}

Output : store view

Cheers !!!

Sublime Text 3 installation Guide

Installing sublime text 3 on ubuntu.

This tutorial will show you how to install the Sublime Text 3 in Ubuntu. Trusty LTS via PPA repository.

The Sublime Text 3 is currently in beta. Webupd8 Team has made an installer script into PPA which automatically downloads the Sublime Text 3 archive from its website and installs it on Ubuntu. The PPA does not host any Sublime Text 3 files.

Install sublime text 3 in ubuntu

Install Sublime Text 3:

To get started, press Ctrl+Alt+T on your keyboard to open a terminal window. When it opens, copy and paste below command into terminal and hit enter:

sudo add-apt-repository -y ppa:webupd8team/sublime-text-3

Type in your password when prompts and then you’ll get this PPA (Personal Package Archive) into your system.

NOTE: you’ll see nothing when typing passwords in Linux terminal, just type in mind and hit enter to get pass.

install sublime text 3 ubuntu

After added the PPA, run commands to install the script:

sudo apt-get update;
sudo apt-get install -y sublime-text-installer

Once installed, open the editor from Unity Dash or Menu.

To disable new version notifications, add the following to your User Preferences file (Preferences > Settings – User):

“update_check”: false

Ubuntu : Zip, Unzip file using terminal.

Here is way to create zip and unzip recursively. For this, You have to install zip and unzip installation packages with following commands in terminal. Open terminal by pressing Ctrl + Alt + T.

sudo apt-get install zip  // to install zip command packages. 
sudo apt-get uninstall zip // to Unistall unzip command package.

Create a zip file :

Go To the path of that folder which you have to make zip and run following command to make a zip file.

zip -r zip-file-name.zip directory-to-compress/
  • zip :  This is the application name, which we are using to create zip file.
  • -r : For recursive
  • zip-file-name.zip : Name of result zip file name.
  • directory-to-compress/ : Name of the directory which we want to compress.

You can add more than one directory in single archives by following command :

sudo zip -r zip-file-name.zip directory-1/ directory-2/

There is no need of -r (recursive) option for single file archive.

sudo zip a2bizz.zip a2bizz.php

Unzip file

Following command will help you to unzip a file.

sudo unzip a2bizz.zip -d destination_dir/
  • sudo : super user
  • unzip : This is unzip application, which is using to extract a zip file.
  • -d : Shorts for destination
  • destination_dir/: This is the directory where you want to extract files.

You can also use unzip a2bizz.zip to extract data on same dir.

Enjoy :)

 

Fix “System program problem detected” error on Ubuntu

From some last previous days I notice down that there is a error popup coming while I start or restart my system, on my Ubuntu OS. The error is “System program problem detected”. Basically comes up when a certain application crashes. Ubuntu program “apport”, responsible for detecting such crashes and upon user consent, report these crashes to developers. This process intends to get the problem fixed by the developers.

However, the problem is the popup comes up each and every time when the system starts and annoyed a normal user. Really, there is no need to show popup to user when they can’t do anything or it should not come back when the report is submitted regarding the error.

So, today we are here that how to get rid of this popup –

error

 

 

 

 

 

We can remove crash reports which are resided into /var/crash directory. These crash report files cause the error message to appear every time Ubuntu boots.

$cd /var/crash
$ ls
_usr_bin_do-release-upgrade.0.crash
_usr_share_apport_apport-gtk.1001.crash
_usr_bin_update-manager.1001.crash

Just Remove the crash report files .

$sudo rm -rf /var/crash/*

After removing these crash reports, the Popup will stop appearing, but it will reappear again in future when a new crash report generated and added to the directory.

So toget rid of these, we should have to turn off ‘apport’ program which is responsible for detecting crash reports and to popup error message –

$ sudo nano /etc/default/apport

nano will open the file in below manner

#set this to 0 to disable apport, or to 1 to enable it
# you can temporarily override this with
# sudo service apport start force_start=1
enabled=1

Change value of enable=1 to 0 and save the file from the next boot the error message will disappear, if you don’t want to restart system then restart apport from command line –

$sudo restart apport

How much you like this post, Please make your comments, which will help me as an appreciation.

Add external url in navigation menu in magento 2

If you want to add your external linklike static page link or some custom module link in your category navigation menu, you can do it by your self. You have do custom code in custom module. Just follow the instructions and create module files.

  1. app/code/A2bizz/Navigation/registration.php
<?php 
\Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        'A2bizz_Navigation',
        __DIR__
        );

 

2.  app/code/A2bizz/Navigation/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="A2bizz_Navigation"  setup_version="0.0.1">
        <sequence>
            <module name="Magento_Theme"/>
        </sequence>
    </module>
</config>

 

3. Add app\code\A2bizz\Navigation\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="Magento\Theme\Block\Html\Topmenu">
    <plugin name="add_menu_item_plugin" type="A2bizz\Navigation\Plugin\Topmenu" sortOrder="10" disabled="false"/>
</type>
</config>

It is saying that plugin which you have defined in A2bizz\Navigation\Plugin\Topmenu will use when Magento\Theme\Block\Html\Topmenu block is used.

4.  app/code/A2bizz/Navigation/Plugin/Topmenu.php

<?php

namespace A2bizz\Navigation\Plugin;

class Topmenu
{
    public function afterGetHtml(\Magento\Theme\Block\Html\Topmenu $topmenu, $html)
    {
        $html .= "<li class=\"level0 nav-4 level-top parent ui-menu-item\">";
        $html .= "<a href=\"" . "EXTERNAL_URL" . "\" class=\"level-top ui-corner-all\" aria-haspopup=\"true\" tabindex=\"-1\" role=\"menuitem\"><span class=\"ui-menu-icon ui-icon ui-icon-carat-1-e\"></span><span>" . __("EXTERNAL_URL_TITLE") . "</span></a>";
        $html .= "<ul class=\"level0 submenu ui-menu ui-widget ui-widget-content ui-corner-all\" role=\"menu\" aria-expanded=\"false\" style=\"display: none; top: 47px; left: -0.4375px;\" aria-hidden=\"true\">";

        $html .= "<li class=\"level1 nav-5-1 first ui-menu-item\" role=\"presentation\">";
        $html .= "<a href=\"" . "EXTERNAL_URL" . "\" class=\"ui-corner-all\" tabindex=\"-1\" role=\"menuitem\"><span>" . __("EXTERNAL_URL_TITLE") . "</span></a>";
        $html .= "</li>";

        $html .= "<li class=\"level1 nav-5-1 first ui-menu-item\" role=\"presentation\">";
        $html .= "<a href=\"" . "EXTERNAL_URL" . "\" class=\"ui-corner-all\" tabindex=\"-1\" role=\"menuitem\"><span>" . __("EXTERNAL_URL_TITLE") . "</span></a>";
        $html .= "</li>";

        $html .= "<li class=\"level1 nav-5-1 first ui-menu-item\" role=\"presentation\">";
        $html .= "<a href=\"" . "EXTERNAL_URL" . "\" class=\"ui-corner-all\" tabindex=\"-1\" role=\"menuitem\"><span>" . __("EXTERNAL_URL_TITLE") . "</span></a>";
        $html .= "</li>";

        $html .= "</ul>";
        $html .= "</li>";

        return $html;
    }
}

After these changes, you have to do setup upgrade by terminal. Open terminal, go to the root directory of installed mangento and run following command.

php bin/magento setup:upgrade

ENJOY !!!

Product category on cart page in opencart 2.2.0.0

To show product category in cart page, you have to do some custom work i.e. you have to overwrite cart page module. Here is the way, you have to do following things

  1. Add OCMOD file to overwrite
    <?xml version="1.0" encoding="utf-8"?>
    <modification>
        <name>Category_Cart</name>
        <version>1.0</version>
        <code>Category_Cart</code>
        <author>A2bizz</author>
        <link>http://blog.a2bizz.com</link>
        <file path="catalog/view/theme/*/template/checkout/cart.tpl">
            <operation>
                <search><![CDATA[
               <td class="text-left"><?php echo $column_name; ?></td>
                ]]></search>
                <add position="after" offset="0"><![CDATA[
                <td class="text-left"><?php echo $column_category; ?></td>
                ]]></add>
            </operation>
             <operation>
                <search><![CDATA[
               <td class="text-left"><?php echo $product['model']; ?></td>
                ]]></search>
                <add position="before" offset="0"><![CDATA[
                <td class="text-left"><?php echo $product['category_name']; ?></td>
                ]]></add>
            </operation>
        </file>
        <file path="catalog/controller/checkout/cart.php">
            <operation>
                <search><![CDATA[
               $data['column_name'] = $this->language->get('column_name');
                ]]></search>
                <add position="after" offset="0"><![CDATA[
                $data['column_category'] = $this->language->get('column_category');
                ]]></add>
            </operation>
             <operation>
                <search><![CDATA[
               $this->load->model('tool/upload');
                ]]></search>
                <add position="after" offset="0"><![CDATA[
                $this->load->model('catalog/custom');
                ]]></add>
            </operation>
            <operation>
                <search><![CDATA[
               $product_total = 0;
                ]]></search>
                <add position="before" offset="0"><![CDATA[
                $category_name = $this->model_catalog_custom->getproductcategory($product['product_id']);
                ]]></add>
            </operation>
            <operation>
                <search><![CDATA[
               'name'      => $product['name'],
                ]]></search>
                <add position="after" offset="0"><![CDATA[
                'category_name'=>$category_name,
                ]]></add>
            </operation>
        </file>
         <file path="catalog/language/*/checkout/cart.php">
            <operation>
                <search><![CDATA[
               $_['column_name']              = 'Product Name';
                ]]></search>
                <add position="after" offset="0"><![CDATA[
                $_['column_category']              = 'Product Category';
                ]]></add>
            </operation>
        </file>
    </modification>
  2. Add a custom model file under catalog/model/catalog/custom.php

    <?php
    class ModelCatalogCustom extends Model {
        public function getproductcategory($product_id){
            $query = $this->db->query("SELECT * FROM " . DB_PREFIX . "product_to_category WHERE product_id = '" . (int)$product_id . "'");
            $category = $this->getCategory($query->row['category_id']);
            return $category['name'];
        }
    
        public function getCategory($category_id) {
            $query = $this->db->query("SELECT DISTINCT *, (SELECT GROUP_CONCAT(cd1.name ORDER BY level SEPARATOR '&nbsp;&nbsp;&gt;&nbsp;&nbsp;') FROM " . DB_PREFIX . "category_path cp LEFT JOIN " . DB_PREFIX . "category_description cd1 ON (cp.path_id = cd1.category_id AND cp.category_id != cp.path_id) WHERE cp.category_id = c.category_id AND cd1.language_id = '" . (int)$this->config->get('config_language_id') . "' GROUP BY cp.category_id) AS path, (SELECT DISTINCT keyword FROM " . DB_PREFIX . "url_alias WHERE query = 'category_id=" . (int)$category_id . "') AS keyword FROM " . DB_PREFIX . "category c LEFT JOIN " . DB_PREFIX . "category_description cd2 ON (c.category_id = cd2.category_id) WHERE c.category_id = '" . (int)$category_id . "' AND cd2.language_id = '" . (int)$this->config->get('config_language_id') . "'");
    
            return $query->row;
        }
    }
  3. Go to in Admin Dashboard -> Extensions -> Extension installer

    Upload you ocmod.xml file from here.

  4. Go to Admin Dashboard -> Extensions-> Modifications

    Click refresh button to create the new ocmod cache file.
    Product category on cart

Enjoy !

Changes in opencart version 2.2.0.0

Opencart 2.2.0.0 has been released. It has a lots of changes. Here, we have mention all the changes.

Changes in files and Structure

  1. Opencart 2.2.0.0 is compatible with composer. Here two version of opencart 2.2.0.0 are available (complied or non-compiled).
  2. There are too much changes in index.php. It has only 22 line of code.
    <?php
    // Version
    define('VERSION', '2.2.0.0');
    
    // Configuration
    if (is_file('config.php')) {
        require_once('config.php');
    }
    
    // Install
    if (!defined('DIR_APPLICATION')) {
        header('Location: install/index.php');
        exit;
    }
    
    // Startup
    require_once(DIR_SYSTEM . 'startup.php');
    
    $application_config = 'catalog';
    
    // Application
    require_once(DIR_SYSTEM . 'framework.php');
    
    
  3.  startup new folder added catalog/controller/startup with following files.
    1. startup.php
    2. session.php
    3. seo_url.php
    4. router.php
    5. maintenance.php
    6. event.php
    7. error.php
  4. event folder added catalog/controller/event with following files.
    1. thmem.php
    2. debug.php
  5.  New class is added system/engine/proxy.php
  6. Cart folder is added under system/library/cart with following files.
    1. weight.php
    2. user.php
    3. tax.php4. length.php
    5. customer.php
    6. currency.php
    7. cart.php
    8. affiliate.php
  7. session folder added system/library/session with following files.
    1.db.php
    2.file.php
  8.  Localisation is now language/en-gb instead of language/english.

 

Changes in Admin area :

  1.  Theme route has been change now admin/index.php?route=theme/theme_default
  2.  Add new payment methods
    1. Lay-Buy
    2. Cardinity
    3. Eway
  3.  New modules added :
    1. Lay-Buy
    2. sagepay

Changes in code :

  1. Link creation has been changed
    from

    $data['href'] => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], 'SSL');

    to

    $data['href'] => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], true);

    ssl is included in the constructor of the library : system/library/url.php

    public function __construct($ssl = false) {
  2. Template loading has been changed

    before :

    $this->response->setOutput($this->load->view('catalog/product_form.tpl', $data));

    now :

    $this->response->setOutput($this->load->view('analytics/google_analytics', $data));

    we do not need to write extension name of template file, it is automatically add. Template render adopter file has been changed now

    before :
    /system/library/template/basic.php

    now :
    /system/library/template.php

    public function render($template) {
    return $this->adaptor->render($template);
    }
  3. Changes in language loading : now you can load the language using $this->load->language('catalog/attribute_group'); instead of $this->language->load('catalog/attribute_group');
  4. Changes in event : Add event
    was

    if (version_compare(VERSION, '2.0.1', '>=')) {
      $this->load->model('extension/event');
      $this->model_extension_event->addEvent('openbay', 'post.admin.product.delete', 'extension/openbay/eventDeleteProduct');
      $this->model_extension_event->addEvent('openbay', 'post.admin.product.edit', 'extension/openbay/eventEditProduct');
    } else {
      $this->load->model('tool/event');
      $this->model_tool_event->addEvent('openbay', 'post.product.delete', 'extension/openbay/eventDeleteProduct');
      $this->model_tool_event->addEvent('openbay', 'post.product.edit', 'extension/openbay/eventEditProduct');
    }

    and now :

    $this->load->model('extension/event');
    $this->model_extension_event->addEvent('openbay', 'admin/model/catalog/product/deleteProduct/before', 'extension/openbay/eventDeleteProduct');
    $this->model_extension_event->addEvent('openbay', 'admin/model/catalog/product/editProduct/before', 'extension/openbay/eventEditProduct');
  5. Changes in event : Delete event
    was

    if (version_compare(VERSION, '2.0.1', '>=')) {
      $this->load->model('extension/event');
      $this->model_extension_event->deleteEvent('openbay');
    } else {
      $this->load->model('tool/event');
      $this->model_tool_event->deleteEvent('openbay');
    }

    and now :

    $this->model_extension_event->deleteEvent('openbay');
  6. Changes in trigger: Adding

    was :

    $this->event->trigger('pre.view.' . str_replace('/', '.', $template), $data);

    now :

    $result = $this->registry->get('event')->trigger('view/' . $route . '/before', array(&$route, &$data))
    Triggers files has been changes. Now triggers are in following files
    
    1. system/engine/loader.php
    2. catalog/model/openbay/etsy_order.php
    3. catalog/model/openbay/ebay_openbay.php
    4. catalog/controller/startup/router.php
    5. admin/controller/startup/router.php
  7. Changes in email validation
    before :

    if (utf8_strlen($email) > 0 && preg_match('/^[^\@]+@.*.[a-z]{2,15}$/i', $email)) {

    now

    if (utf8_strlen($email) > 0 && filter_var($email, FILTER_VALIDATE_EMAIL)) {

Deploy static view files in magento 2

Overview

The static view files deployment command enables you to write static files to the Magento file system when the Magento software is set for production mode.

Static view files are located in the <Magento root dir>/pub/static directory, and some are cached in the <Magento root dir>/var/view_preprocessed directory as well.

Here is two types of  mode of deploying static content.

  1. Developer Mode:  Magento generates them on demand, but the rest are cached in a file for speed of access.
  2. Default or Production Mode : Static files are not generated or cached.

 

Deploy static view files :

Log in magneto serer as magento file system owner and remove following

  1. Remove pub/static
  2. Remove var/cache
  3. Remove var/composer_home
  4. Remove var/generation
  5. Remove var/page_cache
  6. Remove var/view_preprocessed

Run php bin/magento setup:static-content:deploy

You can deploy static content for specific language like en_US. By default magento takes en_US. You can use following command for other languages. For example to deploy nl_NL language

php bin/magento setup:static-content:deploy nl_NL

 

Magento : Custom Stock Status

In Magento, once I was working Product Detail page, and used to see, status of a Product “In Stock” or “Out of Stock” What I want was to modify these Stock status messages, and go through all of the admin but don’t get any column there to modify these messages, but later on I find out solution in below manner, Please check it out –

You should have some basic knowledge of using FTP –

Open your FTP, and go through the below given path –

/app/design/frontend/{your_package}/{your_theme}/template/catalog/product/view/type/availability/default.phtml

Here your_package is package used by your Magento setup, and your_theme is a theme assigned to the magento.

open file, here you will see that “In Stock” and “Out of Stock” are written in a different conditions, Just change these string according to you –

$_product = $this->getProduct(); ?>
<?php if ($this->displayProductStockStatus()): ?>
    <?php if ($_product->isAvailable()): ?>
        <p class="availability in-stock">
            <span class="label"><?php echo $this->helper('catalog')->__('Availability:') ?></span>
            <span class="value"><?php echo $this->helper('catalog')->__('In stock') ?></span>
        </p>
    <?php else: ?>
        <p class="availability out-of-stock">
            <span class="label"><?php echo $this->helper('catalog')->__('Availability:') ?></span>
            <span class="value"><?php echo $this->helper('catalog')->__('Out of stock') ?></span>
        </p>
    <?php endif; ?>
<?php endif; ?>