Tag: custom drupal development

Everything You Need To Know About Drupal Mail System

Drupal Mail System

This blog is all about Drupal Mail system. Email sending in Drupal is entirely straightforward. Essentially you just need to manage two stages to send an email to somebody:

In Drupal to sends an email we need to take care of two things:

  • Declare all the required properties (subject, body, headers, etc) under hook_mail().
  • Call drupal_mail() with the argument for actually sending the email.

However, in the situation like greater and complex site, the above strides won’t be sufficient. In any case, Drupal gives us the Flexibility to redo email sending process, before that it’s important to know how stuff functions in the background first, with the help of Drupal you can easily generate custom pdf using the print module. In this blog, I’ll demonstrate to you how you can redo and extend the Drupal mail framework to satisfy your necessities.

The Email Sending Process

While sending an email drupal_mail() function uses system class for sending an email. Each mail framework needs to actualize MailSystemInterface class to define its own mail sending conduct.

MailsystemInterface class utilizes two strategies:

  • format()
  • mail()

The Mail System Module

Mail related settings can be set through Configuration > System > Mail System.

The mail system variable contains two things:

  • default-system => DefaultMailSystem
  • mailsystem_theme => current.

These key-value pairs are the settings you can adjust under the “Mail System Settings” fieldset.

DefaultMailSystem

The default-system email key describes which mail system class will be used by default for all outgoing emails.

If you don’t modify the site-wide mail system class then this one will be used by drupal_mail() by default.

The mailsystem_theme defines which theme will be used to render emails. Let’s say you are using Mime Mail which

uses a specific template file for it’s emails. The Mail System module checks every theme registry entry for a specific

“mail theme” key/property and if it exists in a particular entry then the specified mailsystem_theme value will be used

to search for more specific template files when the theme registry entry related theme hook will be called.

New Class

If you have two or more different mail system classes available in your system provided by different modules.

If you want to use any custom mail class which would use format() method of one mail system class and mail()

method from another class, so here you can use New Class which allows combining two different mail system classes.

New Setting

The Mail System module permits you to effortlessly add new email keys to the mail_system variable by choosing a

module and a particular email key from its hook_mail() execution.

 

Afterward added new email key to the mail_system variable you will ready to choose mail system class for it.

You will have the capacity to see it under all inclusive default MailSystemInterface class settings.

At the point when drupal_mail is called with your demo_custom _mail email key, then the in a roundabout way utilized

drupal_mail_system() function checks if this email_key exists in mail_system variable. It finds the related key then the

related mail system class will be utilized rather than default class.

Hope this helped you to get most out of the system. Feel free to share your reviews and need assistance regarding

Drupal Development Services. #WeDrupalEveryday

Pick the best answer for your requirements.

Tips To Upgrade Commerce Coupon Module In Drupal

Commerce Coupon Module

Commerce coupon module adds Commerce coupon facility to Drupal commerce.

Commerce coupon 7.x-2.x is recommended version. This version depends on Commerce Discount.

Commerce coupon 7.x-2.x has many architectural improvements and new features which include integration with commerce discount, multiple discounts per coupon, integration with inline conditions.

There are no fixed amount coupons or percentage coupons with this version. Instead, we use discounts and use them with coupons.

Upgrading from Commerce coupon 7.x-1.x to Commerce coupon 7.x-2.x is not directly supported. It is two step process.

As per module page on drupal.org, “Commerce Coupon 7.x-2.x-beta2 has an upgrade path from 1.x to 2.x. It works for upgrading relatively simple coupon 1.x sites; mileage may vary if you have a lot of custom coupon functionality though.”

So in order to upgrade to latest commerce coupon, we first need to upgrade to beta2 and then upgrade to latest version.

Below are the steps to upgrade normal commerce coupon setup without any additional customization.

  • First things first, take a backup.
  • Upgrade to Commerce coupon 7.x-2.x-beta3 following standard upgrade process. You will need to add commerce discounts and inline conditions modules installed before upgrading commerce coupon.
  • Once updates are run, you will see your old coupons converted into new coupon and discount systems. Discounts are created for previous fixed and percentage coupons.
  • Upgrade to latest commerce coupon version following standard upgrade process.
  • Make sure to give permission to required user roles to “Redeem coupon”.

This process assumes that there is no custom coupon functionality is added and no additional modules are used along-w

ith commerce coupon. The Success of upgrade process largely depends on how coupon module is used and customization is done on it.

Below are the steps to upgrade commerce coupon with Commerce Coupon by product reference module installed.

  • Take a backup.
  • Delete product reference fields from coupons.
  • Disable Commerce Coupon by product reference module.
  • Upgrade commerce coupon as outlined in steps 2,3 and 4 in upgrade normal commerce coupon.
  • Edit required discounts and add products.

This makes sure that this discount applies to specific products only.

  • Give appropriate user roles permission to “Redeem coupon”.

Since inline conditions are also installed, you can create coupons while creating discounts.

You can also consider adding Commerce discount Extra module which provides various common discount condition And offers types.

Need more assistance regarding Drupal Commerce Module Development Contact us now and Feel free to share your views/feedback for any further queries.

Guide To Customize Google Map Style And Custom Zoom Bar

custom-zoom

Google map theming and configuration with custom zoom controls, please follow the below details:

Styling google map allows us to change standard google map style and customize maps visual display like road, water, park and etc.

To make changes in standard google map style, we can use json array as per below:

var styledMapType = new google.maps.StyledMapType([
  { elementType: 'geometry', stylers: [{color: '#EBE5E2'}]},
  { elementType: 'labels.text.fill', stylers: [{color: '#520000'}]},
  { elementType: 'labels.text.stroke', stylers: [{color: '#F5E8DA'}]},
  {
    featureType: 'administrative',
    elementType: 'geometry.stroke',
    stylers: [{color: '#C9A193'}]
  },
  {
    featureType: 'administrative.land_parcel',
    elementType: 'geometry.stroke',
    stylers: [{color: '#DCD6B2'}]
  },
  {
    featureType: 'administrative.land_parcel',
    elementType: 'labels.text.fill',
    stylers: [{color: '#AEA5A0'}]
  },
  {
    featureType: 'landscape.natural',
    elementType: 'geometry',
    stylers: [{color: '#DFDFBB'}]
  },
  {
    featureType: 'poi',
    elementType: 'geometry',
    stylers: [{color: '#DFC47F'}]
  },
  {
    featureType: 'poi',
    elementType: 'labels.text.fill',
    stylers: [{color: '#93746E'}]
  },
  {
    featureType: 'poi.park',
    elementType: 'geometry.fill',
    stylers: [{color: '#9DB04A'}]
  },
  {
    featureType: 'poi.park',
    elementType: 'labels.text.fill',
    stylers: [{color: '#197515'}]
  },
  {
    featureType: 'road',
    elementType: 'geometry',
    stylers: [{color: '#F5E4BF'}]
  },
  {
    featureType: 'road.arterial',
    elementType: 'geometry',
    stylers: [{color: '#FDFBF3'}]
  },
  {
    featureType: 'road.highway',
    elementType: 'geometry',
    stylers: [{color: '#F8C452'}]
  },
  {
    featureType: 'road.highway',
    elementType: 'geometry.stroke',
    stylers: [{color: '#E9BF79'}]
  },
  {
    featureType: 'road.highway.controlled_access',
    elementType: 'geometry',
    stylers: [{color: '#E97741'}]
  },
  {
    featureType: 'road.highway.controlled_access',
    elementType: 'geometry.stroke',
    stylers: [{color: '#DBA37F'}]
  },
  {
    featureType: 'road.local',
    elementType: 'labels.text.fill',
    stylers: [{color: '#80544F'}]
  },
  {
    featureType: 'transit.line',
    elementType: 'geometry',
    stylers: [{color: '#DFCD95'}]
  },
  {
    featureType: 'transit.line',
    elementType: 'labels.text.fill',
    stylers: [{color: '#8F726D'}]
  },
  {
    featureType: 'transit.line',
    elementType: 'labels.text.stroke',
    stylers: [{color: '#EBD9B0'}]
  },
  {
    featureType: 'transit.station',
    elementType: 'geometry',
    stylers: [{color: '#DFD2A9'}]
  },
  {
    featureType: 'water',
    elementType: 'geometry.fill',
    stylers: [{color: '#BAD3C2'}]
  },
  {
    featureType: 'water',
    elementType: 'labels.text.fill',
    stylers: [{color: '#8E9985'}]
  }
]);

Below is the example of google style:

Before style applied

After style applying:

Google map provides ease level of customization.

We can make changes as per our need easily. I have provided an example to configure zoom, scroll, street view and etc options to change default google map.

// Create a map object, and include the MapTypeId to add
// to the map type control.
var map = new google.maps.Map(document.getElementById('gmap'), {
  center: {lat: 23.028349, lng: 72.559097},
  zoom: 11,
  mapTypeControlOptions: {
    mapTypeIds: ['roadmap', 'satellite', 'hybrid', 'terrain', 'styled_map'],
  },
  scrollwheel: true,
  mapTypeControl: true,
  mapTypeControlOptions: {
      style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
      position: google.maps.ControlPosition.LEFT_TOP
  },
  zoomControl: false,
  // zoomControlOptions: {
  //     style: google.maps.ZoomControlStyle.LARGE,
  //     position: google.maps.ControlPosition.LEFT_TOP
  // },
  scaleControl: true,
  streetViewControl: true,
  streetViewControlOptions: {
      position: google.maps.ControlPosition.LEFT_TOP
  },
  fullscreenControl: false
});

To Add Custom zoom bar:

To add custom zoom bar on the map we can add custom element and use this element we can handle zoom controls.

I have added example code to add custom zoom controls.

// To customize google zoom bar to slider and search controlls
var centerControlDiv = document.createElement('div');
centerControlDiv.setAttribute("class", "gm-custom-controlls");
centerControlDiv.index = 1;

// Add custom zoom controlls
var centerControl = new ZoomControl(centerControlDiv, map, map.minZoom, map.maxZoom, map.zoom);

// map custom controlls to map
map.controls[google.maps.ControlPosition.BOTTOM].push(centerControlDiv);
// Zoom controlls
function ZoomControl(controlDiv, map, min, max, currentZoom) {

  var parentDiv = document.createElement('div');
  parentDiv.setAttribute("class", "gm-zoom-slider");

  var controlUI = document.createElement('input');
  controlUI.type = 'range';
  controlUI.value = currentZoom;
  controlUI.min = min;
  controlUI.max = max;
  controlUI.style.width = "400px";

  // Add zoom controlls
  var incControlls = document.createElement('div');
  incControlls.id = 'gm-zoom-inc';
  incControlls.innerHTML = '+';

  var decControlls = document.createElement('div');
  decControlls.id = 'gm-zoom-dec';
  decControlls.innerHTML = '-';

  parentDiv.appendChild(decControlls);
  parentDiv.appendChild(controlUI);
  parentDiv.appendChild(incControlls);

  controlDiv.appendChild(parentDiv);

  // Click event listner for side-bar
  controlUI.addEventListener('click', function() {
    map.setZoom(parseFloat(controlUI.value));
  });

  // Click event listner for inc button
  incControlls.addEventListener('click', function() {
    map.setZoom(parseFloat(controlUI.value) + 1 );
  });

  // Click event listner for dec button
  decControlls.addEventListener('click', function() {
    map.setZoom(parseFloat(controlUI.value) - 1 );
  });

  // Set slider value on zoom change 
  google.maps.event.addListener(map, 'zoom_changed', function(){
    controlUI.value = map.getZoom();
  });
}

Zoom bar will be displayed as per below screenshot:



Read more regarding Drupal Development Service

How To Show Facets On Non-Search Page As Normal Widget Instead Of List

Show facets on non-search page

Facets allow users to search the site based on selected criteria. Using Facet API module we can add facets on site. For each field that is indexed, we can have facets. These facets can be configured and displayed on search pages. We have various configuration options available for this.

Many times we need to show these facets on pages that are not Search pages. Facet API module does provide this functionality. You need to create a view display of type “Facet blocks”. Below are the steps to do so.

1 – Create a view of search index and a display of type “Facets Block”. You can make this display in the same view as the search page.

2 – Configure “Facet field” and “Search page path”. Search page path is the path of the search page.

The block is then available to be assigned to the region in blocks page.

However, there are several limitations to this:

  1. The facet links will always be styled as a list, no rewrite or format selection is possible.
  2. It is also not possible to use the normal Facet API widgets for these facets. This is because re-using the Facet API components from outside of the Facet API cannot be easily achieved.

In many cases, Professional Web Development need to show facets on the non-search pages as normal facets instead of the list. To achieve this, follow steps below:

  1. Create a facet block as mentioned above.
  2. Show this block on the non-search page as usual.
  3. Make sure that facets blocks are displaying on non-search page as well. Also, make sure that facet block is showing above views facets blocks i.e weight of facets block is higher than the views facets block.
  4. Edit the facet block and set “Display for searches of facets” to “All search page”.

Doing this will make both the blocks visible on the non-search page. You can hide the block showing list using CSS. This solution works for Search API Database Search and Search API Solr Search.

The final result is something like this:

Read more Blogs https://goo.gl/jhRmqR

How to Use External Invite for User in Drupal 7?

Imagine a scenario where you need to invite some of site users to accept some role on the site. You do not want to go and edit every such users and assign them said role. You also want leave the choice with users if they want to new role on site or not.
Enters User External Invite module.
This module allows users with proper permission to invite other users. Users have specified time before the invite expires. Inviting users also have option to cancel invite and resent invites
Below is step is step guide to install and use this module.
1 – Download the module and install as usual.
Download the module from here: http://drupal.org/project/user_external_invite and install as usual.
2 – Configuration
Go to “admin/people/permissions” and set permission for required roles to send invite.
Go to admin/config/people/invite and set configurations as required.
Select which user roles can be invited, default role, expiration times and templates.
You can customise the emails that will be sent on various occasions here as well.
3 – Invite users
To invite users go to admin/people/invite and add address you want to invite.
You can select role for which invite is being sent. You can also add custom message. This message will be added in email that is being sent to invited users.
4 – Manage Invites
You can manage invites from admin/people/invite/operations.
On this page, you can see list of all invites that are sent and status of each invite. From this page you can either cancel an invite or resent the invite.
The module also implements various checks such as you can not disable module till you have pending invites, making sure that roles are not changed when invites are pending for that role etc.
The module also provides a hook which can be used in case inviting email id is not present in the system.
Hope this article has helped you. Need more assistance regarding drupal development services..!

Migrate Locations From Drupal 6 site to Drupal 8 site

Migrate locations from D6 to D8

Recently i had a problem where i need to migrate locations added by “Location” module in Drupal 6 site to Drupal 8 site. Currently “Location” module does not provide Drupal 8 version, so i used “Address” module in Drupal 8, but still i need to get all contents.

To solve this, i have created a custom module in Drupal 8. Steps to update locations:
  1. Create a folder /modules/custom/MODULENAME
  2. Create “MODULENAME.info.yml” file inside MODULENAME folder with following details:
           name: MODULE NAME (This can be anything you want)
           Description: MODULE DESCRIPTION
Package: Custom
           type: module
core: 8.x
           dependencies:
– address:address
           More info on creating modules .info.yml file can be found here.
      3. Now, as i need to migrate data on cron run, i created “MODULENAME.module” file and implemented hook_cron.
   <?php
/**
 * @file
 * File to migrate contents
 */

    function MODULENAME_cron() {
        Write code here…..
}
We need to connect to Drupal 6 database for exporting its content. Add the following code in /sites/default/settings.php along with the default database connection:
  $databases['external']['default'] = array (
  'database' => ‘DATABASENAME’,
  'username' => ‘USERNAME’,
  'password' => ‘PASSWORD’,
  'prefix' => '',
  'host' => 'localhost',
  'port' => ‘PORT’,
  'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
  'driver' => 'mysql',
);
We have used “External” for connecting to Drupal 6 database. “Default” is used for Drupal 8 database connection. So now there will be 2 database connections in settings.php
Code to switch to Drupal 6 database connection:
    // Switch to external database
\Drupal\Core\Database\Database::setActiveConnection('external');

// Get a connection going
$db = \Drupal\Core\Database\Database::getConnection();

Database Query to fetch locations from Drupal 6 database:

// Query to fetch all locations
  $query = $db->select('location', 'l');
  $query->join('location_instance', 'li', 'l.lid = li.lid');
  $query->fields('l', array('name', 'street', 'additional', 'city', 'province', 'postal_code', 'country', 'latitude', 'longitude'));
  $query->fields('li', array('nid', 'vid'));
  $location = $query->execute()->fetchAll();

Switch back to Drupal 8 database connection:

// Switch back
\Drupal\Core\Database\Database::setActiveConnection();
Code to update locations in Drupal 8 database:
 // Query to import locations
  $last_location = count($location);
  foreach ($location as $key => $value) {
    // UK code is changed to GB in Drupal 8
    if ($value->country == 'uk') {
      $value->country = 'GB';
    }
    $node = node_load($value->nid);
    
    db_merge('node__field_location')
      ->key(array('entity_id' => $value->nid))
      ->fields(array(
          'bundle' => $node->getType(),
          'deleted' => '0',
          'entity_id' => $value->nid,
          'revision_id' => $value->vid,
          'langcode' => 'en',
          'delta' => '0',
          'field_location_address_line1' => $value->name,
          'field_location_address_line2' => $value->street,
          'field_location_locality' => $value->city,
          'field_location_postal_code' => $value->postal_code,
          'field_location_country_code' => strtoupper($value->country),
      ))
      ->execute();

    db_merge('node_revision__field_location')
      ->key(array('entity_id' => $value->nid))
      ->fields(array(
          'bundle' => $node->getType(),
          'deleted' => '0',
          'entity_id' => $value->nid,
          'revision_id' => $value->vid,
          'langcode' => 'en',
          'delta' => '0',
          'field_location_address_line1' => $value->name,
          'field_location_address_line2' => $value->street,
          'field_location_locality' => $value->city,
          'field_location_postal_code' => $value->postal_code,
          'field_location_country_code' => strtoupper($value->country),
      ))
      ->execute();

    // Show a message on screen once all the locations are updated.
    if ($key == ($last_location - 1)) {
      drupal_set_message('Migrated locations');
    }
  }
Note: I had same nids on drupal 6 & drupal 8 site as i used drupal 8 core migration.

4. Run Cron to import all locations.

Here is the full code written in hook_cron():
function MODULENAME_cron() {
  // Switch to external database
  \Drupal\Core\Database\Database::setActiveConnection('external');

  // Get a connection going
  $db = \Drupal\Core\Database\Database::getConnection();

  // Query to fetch all locations
  $query = $db->select('location', 'l');
  $query->join('location_instance', 'li', 'l.lid = li.lid');
  $query->fields('l', array('name', 'street', 'additional', 'city', 'province', 'postal_code', 'country', 'latitude', 'longitude'));
  $query->fields('li', array('nid', 'vid'));
  $location = $query->execute()->fetchAll();

  // Switch back
  \Drupal\Core\Database\Database::setActiveConnection();

  // Query to import locations
  $last_location = count($location);
  foreach ($location as $key => $value) {
    // UK code is changed to GB in Drupal 8
    if ($value->country == 'uk') {
      $value->country = 'GB';
    }
    $node = node_load($value->nid);
    
    db_merge('node__field_location')
      ->key(array('entity_id' => $value->nid))
      ->fields(array(
          'bundle' => $node->getType(),
          'deleted' => '0',
          'entity_id' => $value->nid,
          'revision_id' => $value->vid,
          'langcode' => 'en',
          'delta' => '0',
          'field_location_address_line1' => $value->name,
          'field_location_address_line2' => $value->street,
          'field_location_locality' => $value->city,
          'field_location_postal_code' => $value->postal_code,
          'field_location_country_code' => strtoupper($value->country),
      ))
      ->execute();

    db_merge('node_revision__field_location')
      ->key(array('entity_id' => $value->nid))
      ->fields(array(
          'bundle' => $node->getType(),
          'deleted' => '0',
          'entity_id' => $value->nid,
          'revision_id' => $value->vid,
          'langcode' => 'en',
          'delta' => '0',
          'field_location_address_line1' => $value->name,
          'field_location_address_line2' => $value->street,
          'field_location_locality' => $value->city,
          'field_location_postal_code' => $value->postal_code,
          'field_location_country_code' => strtoupper($value->country),
      ))
      ->execute();

    // Show a message on screen once all the locations are updated.
    if ($key == ($last_location - 1)) {
      drupal_set_message('Migrated locations');
    }
  }
}

 

Hope this code helps you to make things work..!!! Need more assistance regarding web development service…!

Drupal 7 – Data Migration Through Feeds

Working with Drupal, often times we are required to import a large set of data in site. We have various ways to import data. Feeds module is simple and easy to use. Feeds out of the box supports many features which can cover a variety of scenarios. The module is well documented and you can access documentation here.

 

In this part, we are going to explain basics for how to import data using feeds.
To use feeds module, we need ctools and job scheduler module enabled.
The first step in the process is to turn required modules enabled. Enable Feeds, Feeds Admin UI. If you want an example of node importer and user importer then turn Feeds Import enabled.

 

Next step is to add an importer that lets you import data. To do this, go to “admin/structure/feeds” and click on “Add importer”. If you have turned Feeds Import on, you will see example importers here.
Next step is to configure importer. There are various parts in this.
  1. Basic Settings
  2. Fetcher
  3. Parser
  4. Processor
Each is explained in detail below:
These are basic settings for importers:
Name and description are what you specified while creating the importer. “Attach to content type” is used to determine whether we want to attach importer to any content type form or use standalone form.
We use the standalone form if we want to import by using a form that comes with the custom drupal module development at /import path. If we go with content type then import is executed by creating a node of selected content type.
Periodic updates are used to run import periodically. Proper cron configuration is required to run periodic updates. Keep periodic updates off if you are importing data one time only.
Import on submission will start importing process as soon as the form is submitted. There is an option to run the process in the background. This is particularly helpful when importing large data.
Fetcher
The Fetcher is where your feed is fetched from. We have two options here: File upload and HTTP fetcher.
We get a template sample on this page which helps in CSV file construction. Upload the CSV file in required format and import content. Upon completion, a status message is displayed.
In case, we want to delete all nodes that we imported we can do so by going to “Delete Items” tab on import page.
Feeds module out of the box provides many features and is very powerful. There are various other modules available that enhances feeds module functionality.
Hope this helps you, feel free to share your valuable feedback and inputs.
For read more, Click Here