/**
  * Gets locale strings.
  *
  * @param string $textgroup
  *   The locale textgroup.
  * @param string $search_label
  *   Label to search for.
  * @param string $missing_target_language
  *   Missing translation language.
  *
  * @return array
  *   List of i18n strings data.
  */
 function getStrings($search_label = NULL, $missing_target_language = NULL)
 {
     $langcodes = array_keys(\Drupal::languageManager()->getLanguages());
     $languages = array_combine($langcodes, $langcodes);
     $select = db_select('locales_source', 'ls')->fields('ls', array('lid', 'source'));
     if (!empty($search_label)) {
         $select->condition('ls.source', "%{$search_label}%", 'LIKE');
     }
     if (!empty($missing_target_language) && in_array($missing_target_language, $languages)) {
         $select->isNull("lt_{$missing_target_language}.language");
     }
     // Join locale targets for each language.
     // We want all joined fields to be named as langcodes, but langcodes could
     // contain hyphens in their names, which is not allowed by the most database
     // engines. So we create a langcode-to-filed_alias map, and rename fields
     // later.
     $langcode_to_filed_alias_map = array();
     foreach ($languages as $langcode) {
         $table_alias = $select->leftJoin('locales_target', db_escape_field("lt_{$langcode}"), "ls.lid = %alias.lid AND %alias.language = '{$langcode}'");
         $langcode_to_filed_alias_map[$langcode] = $select->addField($table_alias, 'language');
     }
     unset($field_alias);
     $rows = $select->extend('Drupal\\Core\\Database\\Query\\PagerSelectExtender')->limit(\Drupal::config('tmgmt.settings')->get('source_list_limit', 20))->execute()->fetchAll();
     foreach ($rows as $row) {
         foreach ($langcode_to_filed_alias_map as $langcode => $field_alias) {
             $row->{$langcode} = $row->{$field_alias};
             unset($row->{$field_alias});
         }
     }
     unset($row);
     return $rows;
 }
 /**
  * Returns the query for translatable entities of a given type.
  *
  * Additionally you can specify entity property conditions.
  *
  * @param string $entity_type_id
  *   Drupal entity type.
  * @param array $property_conditions
  *   Entity properties. There is no value processing so caller must make sure
  *   the provided entity property exists for given entity type and its value
  *   is processed.
  *
  * @return \Drupal\Core\Entity\Query\QueryInterface|NULL
  *   The query for translatable entities or NULL if the query can not be
  *   built for this entity type.
  */
 public static function buildTranslatableEntitiesQuery($entity_type_id, $property_conditions = array())
 {
     // If given entity type does not have entity translations enabled, no reason
     // to continue.
     $enabled_types = \Drupal::service('plugin.manager.tmgmt.source')->createInstance('content')->getItemTypes();
     if (!isset($enabled_types[$entity_type_id])) {
         return NULL;
     }
     $langcodes = array_keys(\Drupal::languageManager()->getLanguages());
     $languages = array_combine($langcodes, $langcodes);
     $entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
     $label_key = $entity_type->getKey('label');
     $id_key = $entity_type->getKey('id');
     $query = db_select($entity_type->getBaseTable(), 'e');
     $query->addTag('tmgmt_entity_get_translatable_entities');
     $query->addField('e', $id_key);
     $langcode_table_alias = 'e';
     if ($data_table = $entity_type->getDataTable()) {
         $langcode_table_alias = $query->innerJoin($data_table, 'data_table', '%alias.' . $id_key . ' = e.' . $id_key . ' AND %alias.default_langcode = 1');
     }
     $property_conditions += array('langcode' => $langcodes);
     // Searching for sources with missing translation.
     if (!empty($property_conditions['target_status']) && !empty($property_conditions['target_language']) && in_array($property_conditions['target_language'], $languages)) {
         $translation_table_alias = db_escape_field('translation_' . $property_conditions['target_language']);
         $query->leftJoin($data_table, $translation_table_alias, "%alias.{$id_key}= e.{$id_key} AND %alias.langcode = :language", array(':language' => $property_conditions['target_language']));
         // Exclude entities with having source language same as the target language
         // we search for.
         $query->condition($langcode_table_alias . '.langcode', $property_conditions['target_language'], '<>');
         if ($property_conditions['target_status'] == 'untranslated_or_outdated') {
             $or = db_or();
             $or->isNull("{$translation_table_alias}.langcode");
             $or->condition("{$translation_table_alias}.content_translation_outdated", 1);
             $query->condition($or);
         } elseif ($property_conditions['target_status'] == 'outdated') {
             $query->condition("{$translation_table_alias}.content_translation_outdated", 1);
         } elseif ($property_conditions['target_status'] == 'untranslated') {
             $query->isNull("{$translation_table_alias}.langcode");
         }
     }
     // Remove the condition so we do not try to add it again below.
     unset($property_conditions['target_language']);
     unset($property_conditions['target_status']);
     // Searching for the source label.
     if (!empty($label_key) && isset($property_conditions[$label_key])) {
         $search_tokens = explode(' ', $property_conditions[$label_key]);
         $or = db_or();
         foreach ($search_tokens as $search_token) {
             $search_token = trim($search_token);
             if (strlen($search_token) > 2) {
                 $or->condition($label_key, "%{$search_token}%", 'LIKE');
             }
         }
         if ($or->count() > 0) {
             $query->condition($or);
         }
         unset($property_conditions[$label_key]);
     }
     if ($bundle_key = $entity_type->getKey('bundle')) {
         $bundles = array();
         $content_translation_manager = \Drupal::service('content_translation.manager');
         foreach (array_keys(\Drupal::entityManager()->getBundleInfo($entity_type_id)) as $bundle) {
             if ($content_translation_manager->isEnabled($entity_type_id, $bundle)) {
                 $bundles[] = $bundle;
             }
         }
         if (!$bundles) {
             return NULL;
         }
         // If we have type property add condition.
         if (isset($property_conditions[$bundle_key])) {
             $query->condition('e.' . $bundle_key, $property_conditions[$bundle_key]);
             // Remove the condition so we do not try to add it again below.
             unset($property_conditions[$bundle_key]);
         } else {
             $query->condition('e.' . $bundle_key, $bundles, 'IN');
         }
     }
     // Add remaining query conditions which are expected to be handled in a
     // generic way.
     foreach ($property_conditions as $property_name => $property_value) {
         $alias = $property_name == 'langcode' ? $langcode_table_alias : 'e';
         $query->condition($alias . '.' . $property_name, (array) $property_value, 'IN');
     }
     $query->orderBy($entity_type->getKey('id'), 'DESC');
     return $query;
 }