0

I am writing a new custom module which is dependent on geoip module. I'm trying to add another language negotiation in the language detection configurations which would trigger a callback function defined in the module. Now How do I call the function defined in geoip.module file? I tried calling the function directly and after a module_load_include and both do not work.

/**
 * Implement hook_language_negotiation_info
 */
function my_module_language_negotiation_info() {
  return array(
      'geoip_language_provider' => array(
          'callbacks' => array(
              'language' => '_my_module_language_callback',
          ),
          'file' => drupal_get_path( 'module', 'my_module' ) . '/my_module.module',
          'weight' => -4,
          'name' => t( 'My Module GeoIP Negotiation Provider' ),
          'description'=> t( 'This redirects the user to correct language based on their IP.' ),
          'cache' => 0,
      ),
  );
}

function _my_module_language_callback() {
  module_load_include( 'module', 'geoip' );

  //Returns array of languages based on country code. Eg. array( 'CN' => 'zh-hans',)
  $languages = _my_module_language_mapping();
  $country_code = geoip_country_code();
  $default_langcode = language_default( 'language' );

  if( !isset( $languages[$country_code] ) ) {
    watchdog( 'geoip_language', 'The country code is not in the language mapping.' );
    return $default_langcode;
  }

  return $languages[$country_code];
}
  • Calling a function from a hook is not different from calling a function from another function. As long as you are sure you load the file containing the function, you are all set. What exactly do you mean by do not work? What error do you get? – kiamlaluno Apr 27 '16 at 6:59
  • The error I got was that function geoip_country_code was not defined even though the function is defined in the module. Tried it with module_load_include as well as without it. – Drupal 8 test Apr 27 '16 at 7:35
  • I get you are using the 7.x-1 branch of the module, then. – kiamlaluno Apr 27 '16 at 7:49
  • Ah! Yes, using 7.x-1 branch. Didn't realize that there was a newer version available. I'll update and check the changes that have taken place. – Drupal 8 test Apr 27 '16 at 8:13
1

Not sure if this is the correct reason for this behaviour or not but it seems like the language negotiation process runs before the modules and the themes are bootstrapped in Drupal which would explain why the function is not available by default.

Changed the module_load_include to actually include the file directly by calling drupal_get_filename and requiring the file and it worked.

function _my_module_language_callback() {
  $geoip_file = drupal_get_filename('module', 'geoip');
  if( file_exists( $geoip_file ) ) {
    require_once DRUPAL_ROOT . DIRECTORY_SEPARATOR . $geoip_file;
  }

  $languages = _my_module_language_mapping();
  if( function_exists( 'geoip_country_code' ) ) {
    $country_code = geoip_country_code();
  }
  $default_langcode = language_default( 'language' );

  if( !isset( $country_code ) ) {
    watchdog( 'geoip_language', 'Country Code could not be identified by IP.' );
    return $default_langcode;
  }

  if( !isset( $languages[$country_code] ) ) {
    watchdog( 'geoip_language', 'The country code is not in the language mapping.' );
    return $default_langcode;
  }

  return $languages[$country_code];
}
| improve this answer | |
0

First you have to read the module documentation to see if It provide a way to use It's own functions and instructions on how to use them. Also, you have to check if the function you're calling is in that module or in another file (for example, an inc file). If the function is in an inc file you can call it with something like:

module_load_include('inc', 'geoip');
// this cals geoip.inc

or like

module_load_include('inc', 'geoip.field');
// this cals geoip.field.inc
| improve this answer | |
  • In this case the function is defined in the module's .module file. Ideally, I think we shouldn't even have to call module_load_include but even if we have to call it, it should be module_load_include('module', 'geoip') which is what I tried calling but it seems like it doesn't load the file as the function is still not found. – Drupal 8 test Apr 27 '16 at 7:38
  • Have you read the module documentation to see If they specify how to call and use their functions? – Miquel Correa Casablanca Apr 27 '16 at 7:40
  • Geoip is an API module and this is one of their api functions. This is what it says about this function: API function to return the country code for a given IP. Defaults to using the current user's IP if not specified. This function works with both the country and city level databases. – Drupal 8 test Apr 27 '16 at 7:49
0

Your language negotiation callback is called from drupal_bootstrap() before Drupal is completely bootstrapped; as such not all the enabled modules are loaded. In fact, it is called during the DRUPAL_BOOTSTRAP_LANGUAGE phase, which is right before the DRUPAL_BOOTSTRAP_FULL phase.
You just need to use drupal_load() to load the module file as drupal_load('module', 'geoip').

Keep in mind that your language negotiation callback is also called from authorize.php, via drupal_initialize_language(), the same function used from drupal_bootstrap(). If you are going to load that module in your language negotiation callback, be sure it works also when autorize.php is used from Drupal, which means when installing a module from the user interface, for example.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.