Update node from ajax and model popup Drupal 7

I have seen a couple of question-related to “How to edit node in ajax model popup ? and How to edit node while embedding it in ctool”. I have found two way to approach this. I am giving complete code here so it can help others as well.

First Approach

In this implementation, I will open the embedded node in popup using ajax, will save the node and close the popup.

We need to create a custom button to the form.


$form['actions']['edit'] = array(
  '#type' => 'submit',
  '#value' => t('Edit Embedded Photo'),
  '#ajax' => array(
  'callback' => 'getEditContent',
      'event' => 'click',
  '#attributes' => array(
    'selected_node_id' => $entity->nid),

// Now we need to create a callback method.

function getEditContent($js = NULL,$form){
// we are checking for Js as well because if JS is not there the flow should not break , it will open page in new URL
  if (!$js) {
      return drupal_goto('node/'.$form['buttons'][2]['#attributes']['selected_node_id'].'/edit/');
    $force_page_reload = FALSE;
    $node = node_load($form['buttons'][2]['#attributes']['selected_node_id']);
    $type_name = node_type_get_name($node);
    $title = t('<em>Edit @type</em> @title', array('@type' => $type_name, '@title' => $node->title));

// implementing hook_node_form here. so when you are using this, replace my_module with your module name.
    my_module_node_form($node, $title, $force_page_reload);

// opening node in the popup to edit
// We can do all this code in ajax callback method (above one) but keeping this separate so we can use it somewhere else if needed.

function my_module_node_form($node, $title, $force_page_reload = FALSE) {
  $commands = array();
  ctools_include('node.pages', 'node', '');
  $form_state = array(
    'title' => $title,
    'ajax'  => TRUE,
    'build_info' => array(
      'args'  => array($node),
  form_load_include($form_state, 'inc', 'node', 'node.pages');
  $commands = ctools_modal_form_wrapper($node->type . '_node_form', $form_state);
  // add CSS class to Modal-Frame  if we need to provide some extra style 
  $commands[] = ajax_command_invoke('#modalContent', 'addClass', array('custom-module-node', 'custom-module-node-form'));
  print ajax_render($commands);



By applying above embedded node will open in new pop in edit mode, you can edit this and save this. Once you will click on save button node will get updated but the opened popup will not close. To close this opened popup we need to make one more changes:


// implementing  hook_node_update()

function my_module_node_update($node){

$updated_node_id = variable_get("embedded_photo_node_id") ?? 0;
if (($updated_node_id !=0) && ($node->nid === $updated_node_id) && ($node->type === 'embedded node type')){
    drupal_add_js(drupal_get_path('module', 'my_module') . '/js/js_utility.js');

create a new file with the name ‘js_utility.js’ under your module folder and js folder. so the complete path will be


Add below code in the js file

(function ($) {

Clear your Drupal cache and Enjoy!

Second Approach

In this approach, we will not open the node edit form in a popup, instead of popup we will open this in the existing embedded popup.

In the same as first, with ajax callback

$form['edit'] = array(
   '#type' => 'submit',
   '#value' => t('Edit Embedded Photo'),
   '#ajax' => array(
   'callback' => 'getEditContent',
   'event' => 'click',
           'wrapper'=> 'edit-entity',
   '#attributes' => array(
   'selected_node_id' => $entity->nid),

// Ajax callback

function getEditContent($form){
  $node = node_load($form['edit']['#attributes']['selected_node_id']);
  $type_name = node_type_get_name($node);
//  drupal_set_title(t('<em>Edit @type</em> @title', array('@type' => $type_name, '@title' => $node->title)), PASS_THROUGH);

// Render the form
$form_state = array();
$form_state['build_info']['args'] = array($node);

form_load_include($form_state, 'inc', 'node', 'node.pages');
return drupal_build_form($node->type . '_node_form', $form_state);


function mymodule_asaf_form_ajax_commands_alter(&$commands, $form, &$form_state, $form_id) {
  foreach($commands as $key => $command) {
      if ($command['command'] == 'asafRedirect' || 'asafRefresh') {



To make the above solution completely, we need a contributed module Asaf (ajax submit for any form) (https://www.drupal.org/project/asaf) otherwise after form save our popup will get close and will get redirect to the Home page of your application. Setting $form_state[‘redirection’] would not work.

After installing the above module we need to add this form id there. Please see the image.

Create a Drush alias to connect private Remote IP via ssh

What is Drush ?

Drush is a very cool command line utility to perform actions to your Drupal Application.

Drush is a very good friend of Developer. We can do perform below tasks using Drush:

  • Drush helps to manage Drupal website remotely
  • You can Install/enable module(s) using drush. You don’t need to an FTP client to do this
  • You can clear cache using Drush.
  • Check installed modules/themes, you can disable modules using this
  • Drush Provides easier way to code review and Diffs.
  • Maintaining patches using drush is very easy
  • A drush alias is a shortcut to a remote Drupal application, which can be accessible via tunnel or VPN.

    It’s great, that you found it interesting. To use drush from local machine to your private IP like your private EC2 instance.

    Here i am assuming that Drush is already installed to remote machine (If not follow the same step to configure to remote as well). I am going to explain installation, configuration and uses of drush on your local machine to remote machine.

    Install Drush via composer

    Open terminal and run below command

    curl -sS https://getcomposer.org/installer | php 
    mv composer.phar /usr/local/bin/composer
    cd ~/
    touch .bash_profile
    nano .bash_profile
    export PATH="$HOME/.composer/vendor/bin:$PATH"
    composer global require drush/drush:dev-master
    composer global require drush/drush:8.*

    Now Drush is installed on your machine. Now accessing private ip from your Drush alias. Now we are going to create a drush alias that will connect to your remote IP(via VPN) Assuming you already have VPN access to your remote IP.

    To write a drush alias, Open terminal by default your path will be /Users/username/. Now go to the drush folder. Tupe below command for that.

     cd /Users/kundan/.drush 

    Now you are in your Drush directory. create a new drush alais file. file naming convention will be filename.aliases.drushrc.php. To create a file run below command on terminal

    vim filename.aliases.drushrc.php 
    #Alias for dev.test.com
    $aliases['aliasname'] = array(
      'root' => '/var/www/html/drupal',  //path to remote drupal site
      'uri' => 'dev.test.com',          // URL 
      'remote-user' => 'username',      // ssh username
      'remote-host'=> 'XX.XXX.XX.XXX,   // Your private IP 
      'ssh-options' => '-o PasswordAuthentication=yes'

    To run this alias, First connect to VPN with your credentials and go to terminal.

    and run

    drush @aliasname status

    It will ask your ssh password and display detail information about your Drupal site.

    In the same way you can run all drush commands. Some are listed below:

    drush @aliasname status
    drush @aliasname cc all
    drush @aliasname pm-list
    drush @aliasname update

    So all this command is getting execute from local to your remote private Server. You can create multiple drush alias in a single file E.g.

    #Alias for dev.tes1.com
    $aliases['aliasname'] = array(
      'root' => '/var/www/html/drupal',  //path to remote drupal site
      'uri' => 'dev.test.com',          // URL 
      'remote-user' => 'username',      // ssh username
      'remote-host'=> 'XX.XXX.XX.XXX,   // Your private IP 
      'ssh-options' => '-o PasswordAuthentication=yes'
    #Alias for dev.test1.com
    $aliases['aliasname1'] = array(
      'root' => '/var/www/html/drupal1',  //path to remote drupal site
      'uri' => 'dev.test1.com',          // URL 
      'remote-user' => 'username',      // ssh username
      'remote-host'=> 'XX.YYY.XX.XXX,   // Your private IP 
      'ssh-options' => '-o PasswordAuthentication=yes'
    #Alias for dev.test2.com
    $aliases['aliasname2'] = array(
      'root' => '/var/www/html/drupal2',  //path to remote drupal site
      'uri' => 'dev.test3.com',          // URL 
      'remote-user' => 'username',      // ssh username
      'remote-host'=> 'XX.XXX.XX.XXX,   // Your private IP 
      'ssh-options' => '-o PasswordAuthentication=yes'

    Performance Optimisation In Drupal

    If your server has good configuration but your Drupal website is loading slow, you need to figure this out.

    we need to care about speeding up Drupal application because, the speed of your website greatly affects your traffic, conversions, revenue, and even SEO rankings!

    • Shopzilla saw a 12% revenue increase after improving average page load times from 6 seconds to 1.2 seconds.
    • Google says they lose 20% of their traffic for each additional 100 milliseconds it takes a page to load. Speed matters. Google also incorporates your page-load time into your site’s search rankings.

    Steps to speedup your Drupal website:

    1. Always use latest version:

    It is very important you are always running latest version of of drupal and it’s contributed modules, because drupal is an opensource CMS. Contributes always tries to optimise the things with latest security update. You can check the available update for drupal in reports menu on below path:

    Home » Administration » Reports

    It is showing that drupal core is not updated. We should not have such situation. We should always update drupal core as well as contributed modules.

    2. Use caching mechanism :

    Like other CMS drupal comes with some basic page caching and block cacking. You can use this caching by enabling this and set cache expiration time. you can find this under performance option.

    Home » Administration » Configuration » Development

    There are various cache modules available in drupal you can use those module Drupal modules for caching View caching modules is widely using. You can cache the views using this module. If you are using panels then you can also cache the panel itself.

    Apart from above caching there are multiple cache available. You can configure all below caching mechanism and get speedup your website drastically

    3. Content Delivery Network (CDN):

    A content delivery network or content distribution network (CDN) is a globally distributed network of proxy servers deployed in multiple data centers. The goal of a CDN is to serve content to end-users with high availability and high performance. You can put you assets like js,css, image, video file on CDN.

    Configure CDN is a easy task. I am explaining this little bit here and assuming that you are using CDN from Amazon.

    • Login to Amazon console.
    • Create a bucket.
    • create a cloud front for the same.

    Download and configure CDN module

    4. Gzip Compression:

    Gzip is a method of compressing files (making them smaller) for faster network transfers. It is also a file format. Compression allows your web server to provide smaller file sizes which load faster for your website users. Enabling gzip compression is a standard practice. If you are running on Apache you can enable compression by adding the following to your .htaccess file.

      # Compress HTML, CSS, JavaScript, Text, XML and fonts
      AddOutputFilterByType DEFLATE application/javascript
      AddOutputFilterByType DEFLATE application/rss+xml
      AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
      AddOutputFilterByType DEFLATE application/x-font
      AddOutputFilterByType DEFLATE application/x-font-opentype
      AddOutputFilterByType DEFLATE application/x-font-otf
      AddOutputFilterByType DEFLATE application/x-font-truetype
      AddOutputFilterByType DEFLATE application/x-font-ttf
      AddOutputFilterByType DEFLATE application/x-javascript
      AddOutputFilterByType DEFLATE application/xhtml+xml
      AddOutputFilterByType DEFLATE application/xml
      AddOutputFilterByType DEFLATE font/opentype
      AddOutputFilterByType DEFLATE font/otf
      AddOutputFilterByType DEFLATE font/ttf
      AddOutputFilterByType DEFLATE image/svg+xml
      AddOutputFilterByType DEFLATE image/x-icon
      AddOutputFilterByType DEFLATE text/css
      AddOutputFilterByType DEFLATE text/html
      AddOutputFilterByType DEFLATE text/javascript
      AddOutputFilterByType DEFLATE text/plain
      AddOutputFilterByType DEFLATE text/xml
      # Remove browser bugs (only needed for really old browsers)
      BrowserMatch ^Mozilla/4 gzip-only-text/html
      BrowserMatch ^Mozilla/4\.0[678] no-gzip
      BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
      Header append Vary User-Agent

    If you are running on Nginx You can enable compression by adding the following to your nginx.conf file.

    gzip on;
    gzip_comp_level 2;
    gzip_http_version 1.0;
    gzip_proxied any;
    gzip_min_length 1100;
    gzip_buffers 16 8k;
    gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
    gzip_disable "MSIE [1-6].(?!.*SV1)";
    gzip_vary on;

    Set Header Expiration time Expire headers tell the browser whether they should request a file from the server or grab it from the browser’s cache.

         ExpiresActive On
         ## Add default Expires header
         ## http://developer.yahoo.com/performance/rules.html#expires
         ExpiresDefault "access plus 1 year"

    5. Use Lazy loading :

    Lazy loading images dramatically increase your page load times by ensuring the image will only load when it is visible to the browser window. There is contributed modules available for Lazy loading

    6. Compress js and css and use aggregation both:

    You should compress and aggregate your JS and css it helps to increase the performance and reduce the page load time.

    7. Uninstalled unused module :

    You should uninstalled all those module that is not being use for the website.

    8. view module vs custom Query :

    If you application is very larger and you need to hit multiple view the it’s better to use custom query rather then using a view.

    Field template in Drupal.


    What is field templating

    Some time we need to change the layout/design of a field. We can create a complete node–contetntype.tpl But it is not the best practice. If we need to design a single field the we need to create a field template file.

    How to do this???

    Suppose we have a field departments and user can be select multiple departments and we need to display this departments field in a table format with some different styles. Then we need to create a field template file.

    How to do this

    We need to create a file under theme folder i.e. project_name/sites/all/themes/theme_name/ .

    What should be the name of this file.

    we will have to create a file with fiels–field_name.tpl.php. Suppose my field name is ‘field-department-list‘ then my file name will be field–field-department-list.tpl.php and the complete path for this file will be project_name/sites/all/themes/theme_name/field–field-department-list.tpl.php

    <?php if (!$label_hidden): ?>
        <div class="field-label"<?php print $title_attributes; ?>><h4>Department Info</h4></div>
      <?php endif; ?>
    <table class="field-group-format group_additional">
      <div class="field-items"<?php print $content_attributes; ?>>
        <?php foreach ($items as $delta => $item): ?>
        <th class="field-label">Department</th>
        <td class="field-items">
          <div class="field-item <?php print $delta % 2 ? 'odd' : 'even'; ?>"<?php print $item_attributes[$delta]; ?>><?php print render($item); ?></div>
      <?php endforeach; ?>

    6 Biggest Drupal Mistakes

    Drupal is a open source CMS. It is famous world wide. Although Drupal is very famous and used by famous companies but Drupal developer do these mistakes while developing web application:

    Too much custom coding

    The fire has already being invented. No need to invent it again. We just need to use fire in our daily work. Same way drupal has more then 20500 contributed modules so every thing that you need is already developed just need to find it and integrate it with your application.

    • Say No to custom module because it is difficult ti maintain.

    • Say Yes to Contrib modules because it is already tested and voted by many users and developers.


    It has been observed that drupalers doesn’t care about security. That lead a attacked on the application. There are various modules available to implement security and when you use custom coding use drupal standers to avoid any attack on the application.


    It is a vital part of the application. There are multiple tool available to analysis. Common approaches to Optimize your application.

    Infrastructure for the web application:

    Best practice for your web application to include caching layers like varnish and Memcached to the application. It helps to improve the application response time and provide a great user experience.

    Life cycle of a web application

    It includes the best practice throughout the life of application. It includes development , deployment and maintenance phase. It has been observed that most of the developers don’t use any repository like Git or SVN to maintain the version of code. Ideally it should be used.

    SEO Friendly

    Last but the not list is SEO friendly. There are multiple modules available in drupal for SEO. We should use those modules in our web application.

    How to configure Varnish cache on SSL.

    Varnish is a HTTP reverse Proxy or HTTP accelerator. It is used to increase performance of the web application and reduce the time it takes to serve content to a user. The main technique it uses is caching responses from a web or application server in memory, so future requests for the same content can be served without having to retrieve it from the web server.

    Actually Varnish stand between user request and Apache. When request come varnish check for caching if caching available for the request it server from varnish but if caching not available for that request then request goes to Apache and return to varnish and serve to the user. Varnish keeps the cache for this request so for the next time response served from varnish and it reduce the time to response of any request.

    Varnish cache server.

    How will be achieve this:

    Actually we will keep Nginx server before varnish. So when request comes from HTTPS it will fall on Nginx, Nginx will call varnish if cache available to varnish it server from there. If there is no cache available to varnish request goes to Apache and process fall back.

    Now the Varnish cache system will look like :

    Got it but how to do this ?

    There are some commands you need to run and some configuration (UBUNTU):

    Install Varnish


    sudo apt-get update
    sudo apt-get install varnish

    By default varnish runs on port 6081.

    Configure Varnish

    First, we will configure Varnish to use our LAMP.

    The configuration file of vanish is located at /etc/varnish/default.vcl. Let’s edit it now:

    sudo vi /etc/varnish/default.vcl

    We need to change belwo lines:

    backend default {
        .host = "";
        .port = "8080";

    And change the values of host and port match your LAMP server private IP address and listening port, respectively. Note that we are assuming that your web application is listening on its private IP address and port 80. If this is not the case, modify the configuration to match your needs:

    backend default {
        .host = "LAMP_VPS_private_IP";
        .port = "80";

    Like Apache, Varnish has also “grace mode” that, when enabled, instructs Varnish to serve a cached copy of requested pages if your web server backend goes down and becomes unavailable. Let’s enable that now.

    sub vcl_backend_response {
        set beresp.ttl = 10s;
        set beresp.grace = 1h;

    Save and exit the default.vcl file.

    We will want to set Varnish to listen on the default HTTP port (80), so your users will be able to access your site without adding an unusual port number to your URL. This can be set in the /etc/default/varnish file. Let’s edit it now:

    sudo vi /etc/default/varnish

    We will various commented line. Find the following DAEMON_OPTS line (it should be uncommented already):

    DAEMON_OPTS="-a :6081 \

    The -a option is used to assign the address and port that Varnish will listen for requests on. Let’s change it to listen to the default HTTP port, port 80. After your modification, it should look like this:

    DAEMON_OPTS="-a :80 \

    Save and exit.

    Now restart Varnish to put the changes into effect:

    sudo service varnish restart

    Now test it out with a web browser, by visiting your Varnish server by its public IP address, on port 80 (HTTP) this time:

    Install Nginx

    sudo apt-get install nginx

    After installing Nginx, you will notice that it is not running. This is because it is configured to listen on port 80 by default, but Varnish is already using that port. This is fine because we want to listen on the default HTTPS port, port 443.

    Let’s generate the SSL certificate that we will use.

    Generate Self-signed SSL Certificate

    On Varnish_VPS, create a directory where SSL certificate can be placed:

    sudo mkdir /etc/nginx/ssl

    Generate a self-signed, 2048-bit SSL key and certicate pair:

    sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

    Make sure that you set common name to match your domain name. This particular certificate will expire in a year.

    Configure Nginx

    Open the default Nginx server block configuration for editing:

    sudo vi /etc/nginx/sites-enabled/default

    Delete everything in the file and replace it with the following (and change the server_name to match your domain name):

    server {
            listen 443 ssl;
            server_name example.com;
            ssl_certificate /etc/nginx/ssl/nginx.crt;
            ssl_certificate_key /etc/nginx/ssl/nginx.key;
            location / {
                proxy_set_header X-Real-IP  $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto https;
                proxy_set_header X-Forwarded-Port 443;
                proxy_set_header Host $host;

    Save and exit. The above configuration explained below in more detail:

    • ssl_certificate: specifies SSL certificate location
    • sslcertificatekey: specifies SSL key location
    • listen 443 ssl: configures Nginx to listen on port 443
    • server_name: specifies your server name, and should match the common name of your SSL certificate
    • proxy_pass;: redirects traffic to Varnish (which is running on port 80 of (i.e. localhost)

    Now re-start the Nginx

    sudo service nginx start

    How to create sub tab in Drupal 7

    What is Sub tabs.

    Sub tabs are a menu style which looks like tab.

    How it Looks ???

    Got It…. But how to implement this ??

    Let us assume i have uploaded a .xls file and i want to give an option for user to download this file in different format. I will create separate sub tabs for this like below:

    I am going to give an example to create sub-tab.

    Create a module for this and call hook_menu() first and in the hook_menu() write below lines:

    function hook_menu() {
    $items['node/%yourmodule/download/csv'] = array(
        'title' => t('Download CSV'),
        'page callback' => 'change_formater',
        'page arguments' => array(1,2),
        'access arguments' => array(1),
        'file' => 'your_file.inc',
        'access callback'=>'check_downlodable_callback',
        'type' => MENU_LOCAL_TASK,

    Description of every line:

    • In first line we are reserving a slug. Slug is nothing but a URL. On the click of this tab the URL will get called.
    • In the Second line we are giving title(lebel) for this sub tab. Wee always include any printable statement with t(); method.
    • In the Third line is a page callback. Page callback is nothing but a method name that you have written for your purpose.
    • Page argument: We are sending page argument to that method. It starts from 0index. so index we have download and on 2nd we have csv. So in your callback method change_formater() you will have have to receive two argument.
    • Wee are checking that this sub tab is only show on the selected content type. SO we have passed access argument =array (1). in our access callback we will get entire node. So we can get node type from there and bind a condition. So that only selected content type will have this this subtab.
    • Next is file so Best practice is to create your .inc file and keep your logic in this file. Same as keep your all download conversion logic in this .inc file.
    • access callback: Here we define a method name. In this method we will check the accessibility of this tab.
    • Type is MENU_LOCAL_TASK. It will generate a subtab.

    Here is the access callback method so that you can understand it more clear.

    function check_downlodable_callback($node){
      if ($node->type=='resource')
        return true;
        return false;

    As i have said that passing 1 in array for access argument. We will get the entire node in method. I have checked that if node type is resource only then this subtab will display.

    Hope it will help You. Will share some more help full stuff.