<?php

/**
 * Implementation of hook_features_api().
 */
function features_translations_features_api() {
  $translations = array();
  // Legacy option - we don't write to it anymore.
  $translations['translations'] = array(
    'name' => t('Translations'),
    'default_hook' => 'translations_defaults',
    'feature_source' => TRUE,
    'default_file' => FEATURES_DEFAULTS_INCLUDED,
  );
  foreach (language_list() as $langcode => $language) {
    $machine_langcode = strtr($langcode, array('-' => '_'));
    $translations["translations_{$machine_langcode}"] = array(
      'name' => t('Translations: !name', array('!name' => t($language->name))),
      'default_hook' => "translations_{$machine_langcode}_defaults",
      'feature_source' => TRUE,
      'base' => 'translations',
      'default_file' => FEATURES_DEFAULTS_INCLUDED,
      'supersedes' => 'translations',
    );
  }
  return $translations;
}

/**
 * Implementation of hook_features_export_options().
 */
function translations_features_export_options($component) {
  // Ignore legacy option.
  if ($component == 'translations') return array();

  $options = array();
  $textgroups = module_invoke_all('locale', 'groups');
  list(,$machine_langcode) = explode('_', $component, 2);
  $langcode = strtr($machine_langcode, array('_' => '-'));
  $languages = language_list();
  $language = $languages[$langcode];
  foreach ($textgroups as $textgroup => $label) {
    if ($textgroup == 'default' && $langcode == 'en') continue;
    if ($textgroup != 'default' && $langcode == translations_features_string_source_language()) continue;
    $options[$machine_langcode . ':' . $textgroup] = t($language->name) . ': ' . $label;
  }
  return $options;
}

/**
 * Helper to return site's string source language.
 */
function translations_features_string_source_language() {
  if (module_exists('i18n_string')) {
    return i18n_string_source_language();
  }
  return language_default('language');
}

/**
 * Implementation of hook_features_export().
 */
function translations_features_export($data, &$export, $module_name) {
  foreach ($data as $component) {
    list($machine_langcode,) = explode(':', $component);
    $export['features']["translations_{$machine_langcode}"][$component] = $component;
  }
  $export['dependencies']['features'] = 'features';
  $export['dependencies']['features_translations'] = 'features_translations';
  return array();
}

/**
 * Implementation of hook_features_export_render().
 */
function translations_features_export_render($module_name, $data, $export = NULL) {
  $languages = language_list();
  $code = array(
    '  $translations = array();',
    '  $translatables = array();',
  );
  $machine_langcode = ''; // won't change in the loop
  foreach ($data as $component) {
    list($machine_langcode, $textgroup) = explode(':', $component);
    $langcode = strtr($machine_langcode, array('_' => '-'));
    $strings = _features_translations_locale_export_get_strings($languages[$langcode], $textgroup);
    foreach ($strings as $md5 => $string) {
      $code[] = "  \$translations['{$machine_langcode}:{$textgroup}']['{$md5}'] = " . features_var_export($string, '  ') . ";";
      // potx compatibility
      $code[] = "  \$translatables[] = t('" .
                str_replace("'", "\'", $string->source) .
                "', array(), array('context' => '" .
                str_replace("'", "\'", $string->context) .
                "'));";
    }
  }
  $code[] = '  return $translations;';
  $code = implode("\n", $code);
  return array("translations_{$machine_langcode}_defaults" => $code);
}

/**
 * Implementation of hook_features_revert().
 */
function translations_features_revert($module_name, $component) {
  include_once('includes/locale.inc');

  $translations = features_get_default($component, $module_name);
  if (!empty($translations)) {
    $report = array('updates' => 0, 'skips' => 0, 'additions' => 0, 'deletes' => 0);
    $lids = array();
    foreach ($translations as $key => $strings) {
      list($machine_langcode, $textgroup) = explode(':', $key);
      $langcode = strtr($machine_langcode, array('_' => '-'));
      foreach ($strings as $md5 => $string) {
        if (!empty($string['plid'])) {
          if (!isset($lids[$string['plid']])) {
            watchdog('features', 'Translations: importing plid %plid not found for string %source', array(
              '%plid' => $string['plid'], 
              '%source' => $string['source'],
            ), WATCHDOG_WARNING);
            $string['plid'] = 0;
          }
          else {
            $string['plid'] = $lids[$string['plid']];
          }
        }
        $lids[$md5] = _locale_import_one_string_db(
          $report, 
          $langcode, 
          $string['context'], 
          $string['source'], 
          $string['translation'], 
          $textgroup, 
          $string['location'], 
          LOCALE_IMPORT_OVERWRITE, 
          $string['plid'],
          $string['plural']
        );
        if (module_exists('l10n_update')) {
          // Set the "string is customized" flag so featured translations can roundtrip.
          db_update('locales_target')
            ->fields(array(
              // Use literal here as the named constant is not available globally in some versions.
              'l10n_status' => 1,
            ))
            ->condition('language', $langcode)
            ->condition('lid', $lids[$md5])
            ->execute();
        }

      }
    }
    watchdog('features', 'Translations: results for importing feature %feature: %report', array(
      '%feature' => $module_name . ':' . $component,
      '%report' => var_export($report, TRUE),
    ), WATCHDOG_INFO);
  }
  return TRUE;
}

/**
 * Helper to return translated strings in given language and group.
 */
function _features_translations_locale_export_get_strings($language, $group) {
  $query = db_select('locales_source', 's');
  $query->join('locales_target', 't', 's.lid = t.lid');
  $query->fields('s', array('lid', 'source', 'context', 'location'));
  $query->fields('t', array('translation', 'plid', 'plural'));
  $query->addExpression('MD5(CONCAT(s.source, s.context))', 'source_md5');
  $query->condition('t.language', $language->language);
  $query->condition('s.textgroup', $group);
  //exclude unchanged lids
  if (module_exists('l10n_update')) {
    // Use literal here as the named constant is not available globally in some versions.
    $query->condition('t.l10n_status', 0, '<>');
  }
  $query->orderBy('t.plural', 'ASC')->orderBy('source_md5', 'ASC');
  $result = $query->execute()->fetchAll();
  $strings = array();
  $lids = array();
  foreach ($result as $string) {
    $md5 = $string->source_md5;
    $lids[$string->lid] = $md5;
    if (!empty($string->plid)) {
      if (!isset($lids[$string->plid])) {
        watchdog('features', 'Translations: exporting plid %plid not found for string %source.', array('%plid' => $string->plid, '%source' => $string->source));
        $string->plid = 0;
      }
      else {
        $string->plid = $lids[$string->plid];
      }
    }
    unset($string->lid, $string->source_md5); // don't want those in the export
    $strings[$md5] = $string;
  }
  return $strings;
}
