Tuesday 1 December 2015

Check wether the module exist or not in drupal 8


\Drupal::moduleHandler()->moduleExists("module_name");

How to set/get weight for modules and how to enable module programatically in druapl 8


In Druapl 7 the "system" table will have all the module enable and disable status. In druapl 8
 
Description: 
If you were running any queries against the {system} table, these won't work any more. For example:
Drupal 7:
<?php
  // Enable the admin theme.
  db_update('system')
    ->fields(array('status' => 1))
    ->condition('type', 'theme')
    ->condition('name', 'seven')
    ->execute();
?>

Drupal 8:
<?php
  theme_enable(array('seven'));
?>
 
Enable Module: 
 module_enable(array($module), FALSE); 

 module_enable($module_list, $enable_dependencies = TRUE) 

Reff: http://www.drupalcontrib.org/api/drupal/drupal!core!includes!module.inc/function/module_enable/8

Setting module weights:
Drupal 7:
<?php
  // Set a module's weight.
  db_update('system')
    ->fields(array('weight' => $weight))
    ->condition('name', $mymodule)
    ->execute();
?>
Drupal 8:
<?php
  module_set_weight($mymodule, $weight);
?>
To set a module's weight relative to another, a module_get_weight function is planned.

Source : https://www.drupal.org/node/1813642
 
 

Thursday 26 November 2015

How to log error message in Drupal 8 (watchdog in druapl 8)

hook_watchdog() and watchdog() removed

in drupal 8

In Drupal 8 watchdog has been refactored to an OO, PSR-3 compatible framework.
In the paragraphs below, a "channel" refers to what used to be the $type argument to watchdog(). For logging you would have done with simple watchdog() statements in Drupal 7, look at the example for injecting a specific channel.
The switch to PSR-3 logging has resulted in the following API changes:
  1. hook_watchdog() is gone. For a module to implement a logger, it has to register a service tagged as logger. eg
    services:

      logger.mylog:
        class: Drupal\mylog\Logger\MyLog
        tags:
          - { name: logger }
    This class must implement \Psr\Log\LoggerInterface. like this:
    <?php
    namespace Drupal\mylog\Logger;
    
    use Drupal\Core\Logger\RfcLoggerTrait;
    use Psr\Log\LoggerInterface;
    
    class MyLog implements LoggerInterface {
      use RfcLoggerTrait;
    
      /**
       * {@inheritdoc}
       */
      public function log($level, $message, array $context = array()) {
        // Do stuff
      }
    
    }
    ?>
  2. watchdog($type, $message, $variables, $severity, $link) has been removed in favor of \Drupal::logger($type)->log($severity, $message, $variables)
    D7
    <?php
    // Logs a notice
    watchdog('my_module', $message, array());
    // Logs an error
    watchdog('my_module', $message, array(), WATCHDOG_ERROR);
    ?>

    D8 - procedural
    <?php
    // Logs a notice
    \Drupal::logger('my_module')->notice($message);
    // Logs an error
    \Drupal::logger('my_module')->error($message);
    ?>

    D8 - injecting the whole factory
    services:
      myservice_that_needs_to_log_to_multiple_channels:
        class: Drupal\mymodule\MyService
        arguments: ['@logger.factory']

    <?php
    class MyService {
      public function __construct($factory) {
        $this->loggerFactory = $factory;
      }
    
      public function doStuff() {
        // Logs a notice to "my_module" channel.
        $this->loggerFactory->get('my_module')->notice($message);
         // Logs an error to "my_other_module" channel.
        $this->loggerFactory->get('my_other_module')->error($message);
      }
    }
    ?>
    D8 - injecting a specific channel
    Drupal core registers only one channel in core.services.yml for "system" channel.
    There might be cases where you don't want to inject the whole factory to your class, but just a specific channel.
    In that case you can easily register this channel with something like this:
    services:
      logger.channel.mymodule:
        parent: logger.channel_base
        arguments: ['mymodule']

    And then inject logger.channel.mymodule to your services.
    services:
      myservice_that_needs_specific_channel:
        class: Drupal\mymodule\MyService
        arguments: ['@logger.channel.mymodule']

    <?php
    class MyService {
      public function __construct($logger) {
        $this->logger = $logger;
      }
    
      public function doStuff() {
        // Logs a notice.
        $this->logger->notice($message);
         // Logs an error.
        $this->logger->error($message);
      }
    }
    ?>
  3. WATCHDOG_* constants and watchdog_severity_levels() are removed
    D7
    <?php
    $severity = WATCHDOG_EMERGENCY;
    $severity = WATCHDOG_ALERT;
    $severity = WATCHDOG_CRITICAL;
    $severity = WATCHDOG_ERROR;
    $severity = WATCHDOG_WARNING;
    $severity = WATCHDOG_NOTICE;
    $severity = WATCHDOG_INFO;
    $severity = WATCHDOG_DEBUG;
    $levels = watchdog_severity_levels();
    ?>

    D8
    <?php
    use Drupal\Core\Logger\RfcLogLevel;
    $severity = RfcLogLevel::EMERGENCY;
    $severity = RfcLogLevel::ALERT;
    $severity = RfcLogLevel::CRITICAL;
    $severity = RfcLogLevel::ERROR;
    $severity = RfcLogLevel::WARNING;
    $severity = RfcLogLevel::NOTICE;
    $severity = RfcLogLevel::INFO;
    $severity = RfcLogLevel::DEBUG;
    $levels = RfcLogLevel::getLevels();
    ?>

 Source : https://www.drupal.org/node/2270941 


Friday 30 October 2015

"Error: Invalid form POST data" in ajax login form

 When using ajax login form we are getting the warning "Error: Invalid form POST data" to resolve that we need to implement hook_exit()


/**
 * Implements hook_exit().
 */
function module_exit($destination = NULL) {
  if (arg(0) == 'system' && arg(1) == 'ajax') {
    $is_user_login_form_submission = isset($_POST) && isset($_POST['name']) && isset($_POST['pass']) && isset($_POST['form_build_id']);
    if ($is_user_login_form_submission && user_is_anonymous()) {
      $form_build_id = $_POST['form_build_id'];
      $form_state = form_state_defaults();
      $form_state['values'] = $_POST; // Important!
      $form = form_get_cache($form_build_id, $form_state);

      if (!$form) {
        watchdog(__FUNCTION__, 'User login AJAX form submission failed. Trying again...', array(), WATCHDOG_WARNING);

        $form = drupal_rebuild_form('user_login_form', $form_state);
        $form['#build_id_old'] = $form['#build_id']; // Important!

        // Try form submission again after it is rebuilt above
        $commands[] = ajax_command_update_build_id($form);
        $commands[] = ajax_command_invoke('form#user-login-form', 'trigger', array('submit'));

        print ajax_render($commands);
      }
    }
  }
}

Refference Link

https://www.drupal.org/node/1939254
http://drupal.stackexchange.com/questions/152785/invalid-form-post-data-ajax-for-authenticated-users
http://drupal.stackexchange.com/questions/36830/invalid-form-post-data-in-ajax-login-form

Tuesday 20 October 2015

Drupal update the user email and name using user id UID

This is a small function used to update the user email
 /*
@param $uid Is the user id of the particular user
@param $email New email address to change to the particular user UID
*/
function UpdateUserEmail($uid, $email){
  // load user object
$existingUser = user_load($uid);

// create an array of properties to update you can add what ever user property you want to edit in this array.
$edit = array(
  'name' => $email,
  'mail' => $email,
  'init' => $email,
);

// save existing user
  user_save(
    (object) array('uid' => $existingUser->uid),
    $edit);
// load user object
}

Refference links

https://www.drupal.org/node/1969192
 

Friday 2 October 2015

How to validate and submit a form using AJAX in Drupal ?

Drupal convert your form in to ajax 
 
Below is the example of ajaxifying your drupal form. all you have to do is write the call back
wrapper Form api will ajaxify your form.  
 
function test_form($form, &$fstate) {
  $form["wrapper"] = array("#markup" => "<div id='test-ajax'></div>");
  $form["name"] = array("#type" => "textfield", "#required" => true, "#title" => "Name");
  $form["submit"] = array(
    "#type" => "submit", 
    "#value" => "Send", 
    "#ajax" => array(
    "callback" => "test_form_callback", 
    "wrapper" => "test-ajax",
    "effect" => "fade"));
  return $form;
}

function test_form_callback($form, &$fstate) {
  return "<div id='test-ajax'>Wrapper Div</div>";
}

function form_validate($form, &$fstate) {
  form_set_error("name", "your  error to display.");
}
 
Reference Links: 
 
http://drupal.stackexchange.com/questions/12289/how-to-validate-and-submit-a-form-using-ajax

http://drupal.stackexchange.com/questions/6327/how-to-ajaxify-webform-submit-in-drupal-7
 
https://www.drupal.org/node/2081275

https://gist.github.com/pascalduez/1517513

Tuesday 29 September 2015

Filter out specific errors during validation or modify any error message

This is one of the way to alter the error message in any of the forms.

In my example I have added a custom validate to validate the user login functinality.

1. filter out validation
<?php/**
 * Custom Form Validation.
 * Removes all form validation errors caused by a 'foo][bar' form element.
 */function my_module_form_validate($form, &$form_state) {
  $errors = form_get_errors();
  if ($errors) {
    // Clear errors.
    form_clear_error();
    // Clear error messages.
    $error_messages = drupal_get_messages('error');
    // Initialize an array where removed error messages are stored.
    $removed_messages = array();

    // Remove all errors originated by the 'foo][bar' element.
    foreach ($errors as $name => $error_message) {
      if ($name == 'foo][bar') {
        $removed_messages[] = $error_message;
        unset($errors[$name]);
      }
    }

    // Reinstate remaining errors.
    foreach ($errors as $name => $error) {
      form_set_error($name, $error);
      // form_set_error() calls drupal_set_message(), so we have to filter out
      // these from the error messages as well.
      $removed_messages[] = $error;
    }

    // Reinstate remaining error messages (which, at this point, are messages that
    // were originated outside of the validation process).
    foreach (array_diff($error_messages['error'], $removed_messages) as $message) {
      drupal_set_message($message, 'error');      
    }
  }
}?>
 
2. To modify the error message : 
 
 in the above code replace this code
 
 // Remove all errors originated by the 'foo][bar' element.
    foreach ($errors as $name => $error_message) {
      if ($name == 'foo][bar') {
        $removed_messages[] = $error_message;
        unset($errors[$name]);
      }
    }
 
with this one 
 // Remove all errors originated by the 'foo][bar' element. used this in user form alter custom validation
    foreach ($errors as $name => $error_message) {
      if ($name == 'name') {
       $errors[$name] = "<p>We can't find a user with that email.";
        $removed_messages[] = $error_message;
       // unset($errors[$name]);
      }
    } 
 This will replace the default error message "Sorry, Unrecognized username and password with the above text
 
Reference link : https://api.drupal.org/comment/28464#comment-28464  

Drupal - How to create or apply patches

This Url has a definitive guide for applying patch in the  drupal.org

https://www.drupal.org/project/drupal/git-instructions