updated core to 7.58 (right after the site was hacked)
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
.tmgmt-entity-sources-wrapper .form-item {
|
||||
float: left;
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
|
||||
.tmgmt-entity-sources-wrapper #edit-search-submit {
|
||||
margin: 26px 10px 0 10px;
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
name = "Entity source plugin tests"
|
||||
description = "Support module for entity source testing."
|
||||
package = Testing
|
||||
core = 7.x
|
||||
hidden = TRUE
|
||||
|
||||
; Information added by Drupal.org packaging script on 2016-09-21
|
||||
version = "7.x-1.0-rc2+1-dev"
|
||||
core = "7.x"
|
||||
project = "tmgmt"
|
||||
datestamp = "1474446494"
|
||||
|
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Tests module for the Entity Source plugin.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_entity_info_alter().
|
||||
*/
|
||||
function tmgmt_entity_test_entity_info_alter(&$entity_info) {
|
||||
if (isset($entity_info['taxonomy_term']) && empty($entity_info['taxonomy_term']['translation'])) {
|
||||
$entity_info['taxonomy_term']['translation'] = array(
|
||||
'tmgmt_entity_test_translation' => array(
|
||||
'base path' => 'taxonomy/term/%taxonomy_term',
|
||||
'alias' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Hooks provided by the Entity Translation Management module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup tmgmt_source
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Allows to alter $query used to list entities on specific entity type overview
|
||||
* pages.
|
||||
*
|
||||
* @see TMGMTEntityDefaultSourceUIController
|
||||
*/
|
||||
function hook_tmgmt_entity_type_list_query_alter(EntityFieldQuery $query) {
|
||||
$query->entityCondition('type', array('article', 'page'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup tmgmt_source".
|
||||
*/
|
@@ -0,0 +1,27 @@
|
||||
name = Entity Source
|
||||
description = Entity source plugin for the Translation Management system.
|
||||
package = Translation Management
|
||||
core = 7.x
|
||||
|
||||
dependencies[] = tmgmt
|
||||
dependencies[] = tmgmt_field
|
||||
dependencies[] = entity
|
||||
dependencies[] = entity_translation
|
||||
|
||||
test_dependencies[] = pathauto
|
||||
test_dependencies[] = file_entity
|
||||
test_dependencies[] = entityreference
|
||||
|
||||
files[] = tmgmt_entity.source.test
|
||||
files[] = tmgmt_entity.source.none.test
|
||||
files[] = tmgmt_entity.pathauto.test
|
||||
files[] = tmgmt_entity.suggestions.test
|
||||
files[] = tmgmt_entity.plugin.inc
|
||||
files[] = tmgmt_entity.ui.inc
|
||||
|
||||
; Information added by Drupal.org packaging script on 2016-09-21
|
||||
version = "7.x-1.0-rc2+1-dev"
|
||||
core = "7.x"
|
||||
project = "tmgmt"
|
||||
datestamp = "1474446494"
|
||||
|
@@ -0,0 +1,332 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Source plugin for the Translation Management system that handles entities.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_tmgmt_source_plugin_info().
|
||||
*/
|
||||
function tmgmt_entity_tmgmt_source_plugin_info() {
|
||||
$info['entity'] = array(
|
||||
'label' => t('Entity'),
|
||||
'description' => t('Source handler for entities.'),
|
||||
'plugin controller class' => 'TMGMTEntitySourcePluginController',
|
||||
'item types' => array(),
|
||||
);
|
||||
|
||||
$entity_types = array_filter(variable_get('entity_translation_entity_types', array()));
|
||||
|
||||
foreach ($entity_types as $entity_key) {
|
||||
$entity_info = entity_get_info($entity_key);
|
||||
$info['entity']['item types'][$entity_key] = $entity_info['label'];
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_form_ID_alter().
|
||||
*
|
||||
* Alters comment node type select box to filter out comment types that belongs
|
||||
* to non entity translatable node types.
|
||||
*/
|
||||
function tmgmt_entity_form_tmgmt_ui_entity_source_comment_overview_form_alter(&$form, &$form_state) {
|
||||
|
||||
if (!isset($form['search_wrapper']['search']['node_type'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Change the select name to "type" as in the query submitted value will be
|
||||
// passed into node.type condition.
|
||||
$form['search_wrapper']['search']['type'] = $form['search_wrapper']['search']['node_type'];
|
||||
unset($form['search_wrapper']['search']['node_type']);
|
||||
|
||||
// Set new default value.
|
||||
$form['search_wrapper']['search']['type']['#default_value'] = isset($_GET['type']) ? $_GET['type'] : NULL;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get entity translatable bundles.
|
||||
*
|
||||
* Note that for comment entity type it will return the same as for node as
|
||||
* comment bundles have no use (i.e. in queries).
|
||||
*
|
||||
* @param string $entity_type
|
||||
* Drupal entity type.
|
||||
*
|
||||
* @return array
|
||||
* Array of key => values, where key is type and value its label.
|
||||
*/
|
||||
function tmgmt_entity_get_translatable_bundles($entity_type) {
|
||||
|
||||
// If given entity type does not have entity translations enabled, no reason
|
||||
// to continue.
|
||||
if (!in_array($entity_type, variable_get('entity_translation_entity_types', array()))) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$entity_info = entity_get_info($entity_type);
|
||||
$translatable_bundle_types = array();
|
||||
|
||||
foreach ($entity_info['bundles'] as $bundle_type => $bundle_definition) {
|
||||
|
||||
if ($entity_type == 'comment') {
|
||||
$bundle_type = str_replace('comment_node_', '', $bundle_type);
|
||||
if (variable_get('language_content_type_' . $bundle_type) == ENTITY_TRANSLATION_ENABLED) {
|
||||
$translatable_bundle_types[$bundle_type] = $bundle_definition['label'];
|
||||
}
|
||||
}
|
||||
elseif ($entity_type == 'node') {
|
||||
if (variable_get('language_content_type_' . $bundle_type) == ENTITY_TRANSLATION_ENABLED) {
|
||||
$translatable_bundle_types[$bundle_type] = $bundle_definition['label'];
|
||||
}
|
||||
}
|
||||
else {
|
||||
$translatable_bundle_types[$bundle_type] = $bundle_definition['label'];
|
||||
}
|
||||
}
|
||||
|
||||
return $translatable_bundle_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets translatable entities of a given type.
|
||||
*
|
||||
* Additionally you can specify entity property conditions, pager and limit.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* 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.
|
||||
* @param bool $pager
|
||||
* Flag to determine if pager will be used.
|
||||
*
|
||||
* @return array
|
||||
* Array of translatable entities.
|
||||
*/
|
||||
function tmgmt_entity_get_translatable_entities($entity_type, $property_conditions = array(), $pager = FALSE) {
|
||||
|
||||
if (!in_array($entity_type, variable_get('entity_translation_entity_types', array()))) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$languages = drupal_map_assoc(array_keys(language_list()));
|
||||
|
||||
$entity_info = entity_get_info($entity_type);
|
||||
$label_key = isset($entity_info['entity keys']['label']) ? $entity_info['entity keys']['label'] : NULL;
|
||||
|
||||
$id_key = $entity_info['entity keys']['id'];
|
||||
$query = db_select($entity_info['base table'], 'e');
|
||||
$query->addTag('tmgmt_entity_get_translatable_entities');
|
||||
$query->addField('e', $id_key);
|
||||
|
||||
// Language neutral entities are not translatable. Filter them out. To do
|
||||
// that: join {entity_translation} table, but only records with source column
|
||||
// empty. The {entity_translation}.language will represent the original entity
|
||||
// language in that case.
|
||||
$source_table_alias = $query->leftJoin('entity_translation', NULL, "%alias.entity_type = :entity_type AND %alias.entity_id = e.$id_key AND %alias.source = ''", array(':entity_type' => $entity_type));
|
||||
$query->condition("$source_table_alias.language", LANGUAGE_NONE, '<>');
|
||||
|
||||
// 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('et_' . $property_conditions['target_language']);
|
||||
$query->leftJoin('entity_translation', $translation_table_alias, "%alias.entity_type = :entity_type AND %alias.entity_id = e.$id_key AND %alias.language = :language",
|
||||
array(':entity_type' => $entity_type, ':language' => $property_conditions['target_language']));
|
||||
|
||||
// Exclude entities with having source language same as the target language
|
||||
// we search for.
|
||||
$query->condition('e.language', $property_conditions['target_language'], '<>');
|
||||
|
||||
if ($property_conditions['target_status'] == 'untranslated_or_outdated') {
|
||||
$or = db_or();
|
||||
$or->isNull("$translation_table_alias.language");
|
||||
$or->condition("$translation_table_alias.translate", 1);
|
||||
$query->condition($or);
|
||||
}
|
||||
elseif ($property_conditions['target_status'] == 'outdated') {
|
||||
$query->condition("$translation_table_alias.translate", 1);
|
||||
}
|
||||
elseif ($property_conditions['target_status'] == 'untranslated') {
|
||||
$query->isNull("$translation_table_alias.language");
|
||||
}
|
||||
}
|
||||
|
||||
// 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]);
|
||||
}
|
||||
|
||||
// Searching by taxonomy bundles - we need to switch to vid as the bundle key.
|
||||
if ($entity_type == 'taxonomy_term' && !empty($property_conditions['vocabulary_machine_name'])) {
|
||||
$property_name = 'vid';
|
||||
$vocabulary = taxonomy_vocabulary_machine_name_load($property_conditions['vocabulary_machine_name']);
|
||||
$property_value = $vocabulary->vid;
|
||||
$query->condition('e.' . $property_name, $property_value);
|
||||
// Remove the condition so we do not try to add it again below.
|
||||
unset($property_conditions['vocabulary_machine_name']);
|
||||
}
|
||||
// Searching by the node bundles - that applies for node entities as well as
|
||||
// comment.
|
||||
elseif (in_array($entity_type, array('comment', 'node'))) {
|
||||
$node_table_alias = 'e';
|
||||
|
||||
// For comments join node table so that we can filter based on type.
|
||||
if ($entity_type == 'comment') {
|
||||
$query->join('node', 'n', 'e.nid = n.nid');
|
||||
$node_table_alias = 'n';
|
||||
}
|
||||
|
||||
// Get translatable node types and check if it is worth to continue.
|
||||
$translatable_node_types = array_keys(tmgmt_entity_get_translatable_bundles('node'));
|
||||
if (empty($translatable_node_types)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// If we have type property add condition.
|
||||
if (isset($property_conditions['type'])) {
|
||||
$query->condition($node_table_alias . '.type', $property_conditions['type']);
|
||||
// Remove the condition so we do not try to add it again below.
|
||||
unset($property_conditions['type']);
|
||||
}
|
||||
// If not, query db only for translatable node types.
|
||||
else {
|
||||
$query->condition($node_table_alias . '.type', $translatable_node_types);
|
||||
}
|
||||
}
|
||||
|
||||
// Add remaining query conditions which are expected to be handled in a
|
||||
// generic way.
|
||||
foreach ($property_conditions as $property_name => $property_value) {
|
||||
$query->condition('e.' . $property_name, $property_value);
|
||||
}
|
||||
|
||||
if ($pager) {
|
||||
$query = $query->extend('PagerDefault')->limit(variable_get('tmgmt_source_list_limit', 20));
|
||||
}
|
||||
else {
|
||||
$query->range(0, variable_get('tmgmt_source_list_limit', 20));
|
||||
}
|
||||
|
||||
$query->orderBy($entity_info['entity keys']['id'], 'DESC');
|
||||
$entity_ids = $query->execute()->fetchCol();
|
||||
$entities = array();
|
||||
|
||||
if (!empty($entity_ids)) {
|
||||
$entities = entity_load($entity_type, $entity_ids);
|
||||
}
|
||||
|
||||
return $entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_tmgmt_source_suggestions()
|
||||
*/
|
||||
function tmgmt_entity_tmgmt_source_suggestions(array $items, TMGMTJob $job) {
|
||||
$suggestions = array();
|
||||
// Get all translatable entity types.
|
||||
$entity_types = array_filter(variable_get('entity_translation_entity_types', array()));
|
||||
|
||||
foreach ($items as $item) {
|
||||
if (($item instanceof TMGMTJobItem) && ($item->plugin == 'entity') || ($item->plugin == 'node')) {
|
||||
// Load the entity and extract the bundle name to get all fields from the
|
||||
// current entity.
|
||||
$entity = entity_load_single($item->item_type, $item->item_id);
|
||||
list(, , $bundle) = entity_extract_ids($item->item_type, $entity);
|
||||
$field_instances = field_info_instances($item->item_type, $bundle);
|
||||
|
||||
|
||||
// Loop over all fields, check if they are NOT translatable. Only if a
|
||||
// field is not translatable we may suggest a referenced entity. If so,
|
||||
// check for a supported field type (image and file currently here).
|
||||
foreach ($field_instances as $instance) {
|
||||
$field = field_info_field($instance['field_name']);
|
||||
$field_type = $field['type'];
|
||||
$field_name = $field['field_name'];
|
||||
switch ($field_type) {
|
||||
case 'file':
|
||||
case 'image':
|
||||
// 'File' (and images) must be translatable entity types.
|
||||
// Other files we not suggest here. Get all field items from the
|
||||
// current field and suggest them as translatable.
|
||||
if (isset($entity_types['file']) && ($field_items = field_get_items($item->item_type, $entity, $field_name))) {
|
||||
// Add all files as a suggestion.
|
||||
foreach ($field_items as $field_item) {
|
||||
$file_entity = entity_load_single('file', $field_item['fid']);
|
||||
|
||||
// Check if there is already a translation available for this
|
||||
// file. If so, just continue with the next file.
|
||||
$handler = entity_translation_get_handler('file', $file_entity);
|
||||
if ($handler instanceof EntityTranslationHandlerInterface) {
|
||||
$translations = $handler->getTranslations();
|
||||
if (isset($translations->data[$job->target_language])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the translation as a suggestion.
|
||||
$suggestions[] = array(
|
||||
'job_item' => tmgmt_job_item_create('entity', 'file', $file_entity->fid),
|
||||
'reason' => t('Field @label', array('@label' => $instance['label'])),
|
||||
'from_item' => $item->tjiid,
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'entityreference':
|
||||
$target_type = $field['settings']['target_type'];
|
||||
// Make sure only tranlatable entity types are suggested.
|
||||
if (isset($entity_types[$target_type]) && ($field_items = field_get_items($item->item_type, $entity, $field_name))) {
|
||||
// Add all referenced entities as suggestion.
|
||||
foreach ($field_items as $field_item) {
|
||||
$ref_entity = entity_load_single($target_type, $field_item['target_id']);
|
||||
|
||||
// Check if there is already a translation available for this
|
||||
// entity. If so, just continue with the next one.
|
||||
$handler = entity_translation_get_handler($target_type, $ref_entity);
|
||||
if ($handler instanceof EntityTranslationHandlerInterface) {
|
||||
$translations = $handler->getTranslations();
|
||||
if (isset($translations->data[$job->target_language])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Add suggestion.
|
||||
$suggestions[] = array(
|
||||
'job_item' => tmgmt_job_item_create('entity', $target_type, $field_item['target_id']),
|
||||
'reason' => t('Field @label', array('@label' => $instance['label'])),
|
||||
'from_item' => $item->tjiid,
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $suggestions;
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Tests integration with pathauto.
|
||||
*/
|
||||
class TMGMTEntitySourcePathAutoTestCase extends TMGMTEntityTestCaseUtility {
|
||||
|
||||
static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Entity Source Pathauto tests',
|
||||
'description' => 'Verifies that the correct aliases are generated for entity transations',
|
||||
'group' => 'Translation Management',
|
||||
'dependencies' => array('entity_translation', 'pathauto'),
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('tmgmt_entity', 'entity_translation', 'pathauto'));
|
||||
$this->loginAsAdmin();
|
||||
$this->createNodeType('article', 'Article', ENTITY_TRANSLATION_ENABLED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that pathauto aliases are correctly created.
|
||||
*/
|
||||
function testAliasCreation() {
|
||||
$this->setEnvironment('de');
|
||||
|
||||
// Create a translation job.
|
||||
$job = $this->createJob();
|
||||
$job->translator = $this->default_translator->name;
|
||||
$job->settings = array();
|
||||
$job->save();
|
||||
|
||||
// Create a node.
|
||||
$node = $this->createNode('article');
|
||||
// Create a job item for this node and add it to the job.
|
||||
$job->addItem('entity', 'node', $node->nid);
|
||||
|
||||
// Translate the job.
|
||||
$job->requestTranslation();
|
||||
|
||||
// Check the translated job items.
|
||||
foreach ($job->getItems() as $item) {
|
||||
$item->acceptTranslation();
|
||||
}
|
||||
|
||||
// Make sure that the correct url aliases were created.
|
||||
$aliases = db_query('SELECT * FROM {url_alias} where source = :source', array(':source' => 'node/' . $node->nid))->fetchAllAssoc('language');
|
||||
$this->assertEqual(2, count($aliases));
|
||||
$this->assertTrue(isset($aliases['en']), 'English alias created.');
|
||||
$this->assertTrue(isset($aliases['de']), 'German alias created.');
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides the Entity source controller.
|
||||
*/
|
||||
|
||||
class TMGMTEntitySourcePluginController extends TMGMTDefaultSourcePluginController {
|
||||
|
||||
public function getLabel(TMGMTJobItem $job_item) {
|
||||
if ($entity = entity_load_single($job_item->item_type, $job_item->item_id)) {
|
||||
return entity_label($job_item->item_type, $entity);
|
||||
}
|
||||
}
|
||||
|
||||
public function getUri(TMGMTJobItem $job_item) {
|
||||
if ($entity = entity_load_single($job_item->item_type, $job_item->item_id)) {
|
||||
return entity_uri($job_item->item_type, $entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Returns the data from the fields as a structure that can be processed by
|
||||
* the Translation Management system.
|
||||
*/
|
||||
public function getData(TMGMTJobItem $job_item) {
|
||||
$entity = entity_load_single($job_item->item_type, $job_item->item_id);
|
||||
if (!$entity) {
|
||||
throw new TMGMTException(t('Unable to load entity %type with id %id', array('%type' => $job_item->item_type, $job_item->item_id)));
|
||||
}
|
||||
if (entity_language($job_item->item_type, $entity) == LANGUAGE_NONE) {
|
||||
throw new TMGMTException(t('Entity %entity could not be translated because it is language neutral', array('%entity' => entity_label($job_item->item_type, $entity))));
|
||||
}
|
||||
return tmgmt_field_get_source_data($job_item->item_type, $entity, $job_item->getJob()->source_language, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function saveTranslation(TMGMTJobItem $job_item) {
|
||||
$entity = entity_load_single($job_item->item_type, $job_item->item_id);
|
||||
$job = tmgmt_job_load($job_item->tjid);
|
||||
|
||||
tmgmt_field_populate_entity($job_item->item_type, $entity, $job->target_language, $job_item->getData());
|
||||
|
||||
// Change the active language of the entity to the target language.
|
||||
$handler = entity_translation_get_handler($job_item->item_type, $entity);
|
||||
$handler->setFormLanguage($job_item->getJob()->target_language);
|
||||
|
||||
entity_save($job_item->item_type, $entity);
|
||||
|
||||
$translation = array(
|
||||
// @todo Improve hardcoded values.
|
||||
'translate' => 0,
|
||||
'status' => TRUE,
|
||||
'language' => $job_item->getJob()->target_language,
|
||||
'source' => $job_item->getJob()->source_language,
|
||||
);
|
||||
$handler->setTranslation($translation);
|
||||
$handler->saveTranslations();
|
||||
$job_item->accepted();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getType(TMGMTJobItem $job_item) {
|
||||
if ($entity = entity_load_single($job_item->item_type, $job_item->item_id)) {
|
||||
$bundles = tmgmt_entity_get_translatable_bundles($job_item->item_type);
|
||||
$info = entity_get_info($job_item->item_type);
|
||||
list(, , $bundle) = entity_extract_ids($job_item->item_type, $entity);
|
||||
// Display entity type and label if we have one and the bundle isn't
|
||||
// the same as the entity type.
|
||||
if (isset($bundles[$bundle]) && $bundle != $job_item->item_type) {
|
||||
return t('@type (@bundle)', array('@type' => $info['label'], '@bundle' => $bundles[$bundle]));
|
||||
}
|
||||
// Otherwise just display the entity type label.
|
||||
elseif (isset($info['label'])) {
|
||||
return $info['label'];
|
||||
}
|
||||
return parent::getType($job_item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSourceLangCode(TMGMTJobItem $job_item) {
|
||||
$entity = entity_load_single($job_item->item_type, $job_item->item_id);
|
||||
return isset($entity->translations->original) ? $entity->translations->original : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getExistingLangCodes(TMGMTJobItem $job_item) {
|
||||
if ($entity = entity_load_single($job_item->item_type, $job_item->item_id)) {
|
||||
$entity_info = entity_get_info($job_item->item_type);
|
||||
if (isset($entity_info['entity keys']['translations'])){
|
||||
$translations_key = $entity_info['entity keys']['translations'];
|
||||
return array_keys($entity->{$translations_key}->data);
|
||||
}
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
}
|
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Entity source LANGUAGE_NONE tests.
|
||||
*
|
||||
* Splitted into a separate test because of https://www.drupal.org/node/2675230.
|
||||
*/
|
||||
class TMGMTEntitySourceLanguageNoneTestCase extends TMGMTEntityTestCaseUtility {
|
||||
|
||||
public $vocabulary;
|
||||
|
||||
static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Entity Source Neutral tests',
|
||||
'description' => 'Tests that LANGUAGE_NONE entities can not be translated',
|
||||
'group' => 'Translation Management',
|
||||
'dependencies' => array('entity_translation'),
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('tmgmt_entity', 'taxonomy', 'entity_translation'));
|
||||
|
||||
// Admin user to perform settings on setup.
|
||||
$this->loginAsAdmin(array('administer entity translation'));
|
||||
|
||||
$this->vocabulary = $this->createTaxonomyVocab(strtolower($this->randomName()), $this->randomName(), array(FALSE, TRUE, TRUE, TRUE));
|
||||
|
||||
// Enable entity translations for taxonomy.
|
||||
$edit['entity_translation_entity_types[taxonomy_term]'] = 1;
|
||||
$this->drupalPost('admin/config/regional/entity_translation', $edit, t('Save configuration'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if language neutral entities are not allowed for translation.
|
||||
*
|
||||
* That behaviour is described in the entity_translation documentation:
|
||||
* https://www.drupal.org/node/1280934
|
||||
*/
|
||||
function testLanguageNeutral() {
|
||||
$this->setEnvironment('de');
|
||||
|
||||
// Structure: array({entity-type} => array({source-langcode} => {entity}))
|
||||
$test_data = array();
|
||||
|
||||
$this->createNodeType('article', 'Article', ENTITY_TRANSLATION_ENABLED);
|
||||
$test_data['node'][LANGUAGE_NONE] = $this->createNode('article', LANGUAGE_NONE);
|
||||
$test_data['node']['en'] = $this->createNode('article', 'en');
|
||||
$test_data['node']['de'] = $this->createNode('article', 'de');
|
||||
|
||||
$test_data['taxonomy_term'][LANGUAGE_NONE] = $this->createTaxonomyTerm($this->vocabulary, LANGUAGE_NONE);
|
||||
$test_data['taxonomy_term']['en'] = $this->createTaxonomyTerm($this->vocabulary, 'en');
|
||||
$test_data['taxonomy_term']['de'] = $this->createTaxonomyTerm($this->vocabulary, 'de');
|
||||
|
||||
// Test if tmgmt_entity_get_translatable_entities() function excludes
|
||||
// language neutral entities.
|
||||
foreach ($test_data as $entity_type => $entities) {
|
||||
$translatable_entities = tmgmt_entity_get_translatable_entities($entity_type);
|
||||
foreach ($entities as $langcode => $entity) {
|
||||
list($id, , ) = entity_extract_ids($entity_type, $entity);
|
||||
if ($langcode == LANGUAGE_NONE) {
|
||||
$this->assert(!isset($translatable_entities[$id]), "Language neutral $entity_type entity does not exist in the translatable entities list.");
|
||||
}
|
||||
else {
|
||||
$this->assert(isset($translatable_entities[$id]), "$langcode $entity_type entity exists in the translatable entities list.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test if language neutral entities can't be added to a translation job.
|
||||
$job = $this->createJob();
|
||||
$job->translator = $this->default_translator->name;
|
||||
$job->settings = array();
|
||||
$job->save();
|
||||
foreach ($test_data as $entity_type => $entities) {
|
||||
foreach ($entities as $langcode => $entity) {
|
||||
list($id, , ) = entity_extract_ids($entity_type, $entity);
|
||||
try {
|
||||
$job->addItem('entity', $entity_type, $id);
|
||||
if ($langcode == LANGUAGE_NONE) {
|
||||
$this->fail("Adding of language neutral $entity_type entity to a translation job did not fail.");
|
||||
}
|
||||
else {
|
||||
$this->pass("Adding of $langcode $entity_type entity node to a translation job did not fail.");
|
||||
}
|
||||
}
|
||||
catch (TMGMTException $e) {
|
||||
if ($langcode == LANGUAGE_NONE) {
|
||||
$this->pass("Adding of language neutral $entity_type entity to a translation job did fail.");
|
||||
}
|
||||
else {
|
||||
$this->fail("Adding of $langcode $entity_type entity node to a translation job did fail.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$GLOBALS['TMGMT_DEBUG'] = FALSE;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Basic Entity Source tests.
|
||||
*/
|
||||
class TMGMTEntitySourceTestCase extends TMGMTEntityTestCaseUtility {
|
||||
|
||||
public $vocabulary;
|
||||
|
||||
static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Entity Source tests',
|
||||
'description' => 'Exporting source data from entities and saving translations back to entities.',
|
||||
'group' => 'Translation Management',
|
||||
'dependencies' => array('entity_translation'),
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('tmgmt_entity', 'taxonomy', 'entity_translation'));
|
||||
|
||||
// Admin user to perform settings on setup.
|
||||
$this->loginAsAdmin(array('administer entity translation'));
|
||||
|
||||
$this->vocabulary = $this->createTaxonomyVocab(strtolower($this->randomName()), $this->randomName(), array(FALSE, TRUE, TRUE, TRUE));
|
||||
|
||||
// Enable entity translations for taxonomy.
|
||||
$edit['entity_translation_entity_types[taxonomy_term]'] = 1;
|
||||
$this->drupalPost('admin/config/regional/entity_translation', $edit, t('Save configuration'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests nodes field translation.
|
||||
*/
|
||||
function testEntitySourceNode() {
|
||||
$this->setEnvironment('de');
|
||||
|
||||
$this->createNodeType('article', 'Article', ENTITY_TRANSLATION_ENABLED);
|
||||
|
||||
// Create a translation job.
|
||||
$job = $this->createJob();
|
||||
$job->translator = $this->default_translator->name;
|
||||
$job->settings = array();
|
||||
$job->save();
|
||||
|
||||
// Create some nodes.
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$node = $this->createNode('article');
|
||||
// Create a job item for this node and add it to the job.
|
||||
$item = $job->addItem('entity', 'node', $node->nid);
|
||||
$this->assertEqual(t('@type (@bundle)', array('@type' => t('Node'), '@bundle' => 'Article')), $item->getSourceType());
|
||||
}
|
||||
|
||||
// Translate the job.
|
||||
$job->requestTranslation();
|
||||
|
||||
// Check the translated job items.
|
||||
foreach ($job->getItems() as $item) {
|
||||
// The source is available only for en.
|
||||
$this->assertJobItemLangCodes($item, 'en', array('en'));
|
||||
$item->acceptTranslation();
|
||||
$this->assertTrue($item->isAccepted());
|
||||
$entity = entity_load_single($item->item_type, $item->item_id);
|
||||
$data = $item->getData();
|
||||
$this->checkTranslatedData($entity, $data, 'de');
|
||||
$this->checkUntranslatedData($entity, $this->field_names['node']['article'], $data, 'de');
|
||||
// The source is now available for both en and de.
|
||||
$this->assertJobItemLangCodes($item, 'en', array('de', 'en'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests taxonomy terms field translation.
|
||||
*/
|
||||
function testEntitySourceTerm() {
|
||||
$this->setEnvironment('de');
|
||||
|
||||
// Create the job.
|
||||
$job = $this->createJob();
|
||||
$job->translator = $this->default_translator->name;
|
||||
$job->settings = array();
|
||||
$job->save();
|
||||
|
||||
$term = NULL;
|
||||
|
||||
//Create some terms.
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$term = $this->createTaxonomyTerm($this->vocabulary);
|
||||
// Create the item and assign it to the job.
|
||||
$item = $job->addItem('entity', 'taxonomy_term', $term->tid);
|
||||
$this->assertEqual(t('@type (@bundle)', array('@type' => t('Taxonomy term'), '@bundle' => $this->vocabulary->name)), $item->getSourceType());
|
||||
}
|
||||
// Request the translation and accept it.
|
||||
$job->requestTranslation();
|
||||
|
||||
// Check if the fields were translated.
|
||||
foreach ($job->getItems() as $item) {
|
||||
$this->assertJobItemLangCodes($item, 'en', array('en'));
|
||||
$item->acceptTranslation();
|
||||
$entity = entity_load_single($item->item_type, $item->item_id);
|
||||
$data = $item->getData();
|
||||
$this->checkTranslatedData($entity, $data, 'de');
|
||||
$this->checkUntranslatedData($entity, $this->field_names['taxonomy_term'][$this->vocabulary->machine_name], $data, 'de');
|
||||
$this->assertJobItemLangCodes($item, 'en', array('de', 'en'));
|
||||
}
|
||||
}
|
||||
|
||||
function testAddingJobItemsWithEmptySourceText() {
|
||||
$this->setEnvironment('de');
|
||||
|
||||
// Create term with empty texts.
|
||||
$empty_term = new stdClass();
|
||||
$empty_term->name = $this->randomName();
|
||||
$empty_term->description = $this->randomName();
|
||||
$empty_term->vid = $this->vocabulary->vid;
|
||||
taxonomy_term_save($empty_term);
|
||||
|
||||
// Create the job.
|
||||
$job = tmgmt_job_create('en', NULL);
|
||||
try {
|
||||
$job->addItem('entity', 'taxonomy_term', $empty_term->tid);
|
||||
$this->fail('Job item added with empty source text.');
|
||||
}
|
||||
catch (TMGMTException $e) {
|
||||
$this->assert(empty($job->tjid), 'After adding a job item with empty source text its tjid has to be unset.');
|
||||
}
|
||||
|
||||
// Create term with populated source content.
|
||||
$populated_content_term = $this->createTaxonomyTerm($this->vocabulary);
|
||||
|
||||
// Lets reuse the last created term with populated source content.
|
||||
$job->addItem('entity', 'taxonomy_term', $populated_content_term->tid);
|
||||
$this->assert(!empty($job->tjid), 'After adding another job item with populated source text its tjid must be set.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the source is able to pull content in requested language.
|
||||
*/
|
||||
function testRequestDataForSpecificLanguage() {
|
||||
$this->setEnvironment('de');
|
||||
$this->setEnvironment('cs');
|
||||
|
||||
$this->createNodeType('article', 'Article', ENTITY_TRANSLATION_ENABLED);
|
||||
|
||||
// Create a translation job.
|
||||
$job = $this->createJob('en', 'de');
|
||||
$job->translator = $this->default_translator->name;
|
||||
$job->settings = array();
|
||||
$job->save();
|
||||
|
||||
$node = $this->createNode('article', 'cs');
|
||||
$node->body['en'][0]['value'] = 'en translation';
|
||||
node_save($node);
|
||||
$job->addItem('entity', 'node', $node->nid);
|
||||
|
||||
$data = $job->getData();
|
||||
$this->assertEqual($data[1]['body'][0]['value']['#text'], 'en translation');
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the data from an entity with the translated data.
|
||||
*
|
||||
* @param $tentity
|
||||
* The translated entity object.
|
||||
* @param $data
|
||||
* An array with the translated data.
|
||||
* @param $langcode
|
||||
* The code of the target language.
|
||||
*/
|
||||
function checkTranslatedData($tentity, $data, $langcode) {
|
||||
foreach (element_children($data) as $field_name) {
|
||||
foreach (element_children($data[$field_name]) as $delta) {
|
||||
foreach (element_children($data[$field_name][$delta]) as $column) {
|
||||
$column_value = $data[$field_name][$delta][$column];
|
||||
if (!empty($column_value['#translate'])) {
|
||||
$this->assertEqual($tentity->{$field_name}[$langcode][$delta][$column], $column_value['#translation']['#text'], format_string('The field %field:%delta has been populated with the proper translated data.', array('%field' => $field_name, 'delta' => $delta)));
|
||||
}
|
||||
else {
|
||||
$this->assertEqual($tentity->{$field_name}[$langcode][$delta][$column], $column_value['#text'], format_string('The field %field:%delta has been populated with the proper untranslated data.', array('%field' => $field_name, 'delta' => $delta)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the fields that should not be translated.
|
||||
*
|
||||
* @param $tentity
|
||||
* The translated entity object.
|
||||
* @param $fields
|
||||
* An array with the field names to check.
|
||||
* @param $translation
|
||||
* An array with the translated data.
|
||||
* @param $langcode
|
||||
* The code of the target language.
|
||||
*/
|
||||
function checkUntranslatedData($tentity, $fields, $data, $langcode) {
|
||||
foreach ($fields as $field_name) {
|
||||
$field_info = field_info_field($field_name);
|
||||
if (!$field_info['translatable']) {
|
||||
// Avoid some PHP warnings.
|
||||
if (isset($data[$field_name])) {
|
||||
$this->assertNull($data[$field_name]['#translation']['#text'], 'The not translatable field was not translated.');
|
||||
}
|
||||
if (isset($tentity->{$field_name}[$langcode])) {
|
||||
$this->assertNull($tentity->{$field_name}[$langcode], 'The entity has translated data in a field that is translatable.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,274 @@
|
||||
<?php
|
||||
/*
|
||||
* @file
|
||||
* Contains tests for Translation management
|
||||
*/
|
||||
|
||||
/**
|
||||
* Basic Source-Suggestions tests.
|
||||
*/
|
||||
class TMGMTSuggestionsTestCase extends TMGMTBaseTestCase {
|
||||
|
||||
static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Entity Suggestions tests',
|
||||
'description' => 'Tests suggestion implementation for the entity source plugin',
|
||||
'group' => 'Translation Management',
|
||||
'dependencies' => array(
|
||||
'file_entity',
|
||||
'entityreference',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp(array('file_entity', 'tmgmt_entity', 'tmgmt_ui', 'entityreference', 'tmgmt_i18n_string', 'i18n_menu'));
|
||||
$this->loginAsAdmin(array('administer entity translation'));
|
||||
|
||||
$this->setEnvironment('de');
|
||||
|
||||
// Enable entity translations for nodes and comments.
|
||||
$edit = array();
|
||||
$edit['entity_translation_entity_types[node]'] = 1;
|
||||
$edit['entity_translation_entity_types[file]'] = 1;
|
||||
$this->drupalPost('admin/config/regional/entity_translation', $edit, t('Save configuration'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a node to get suggestions from.
|
||||
*
|
||||
* Creates a node with two file fields. The first one is not translatable,
|
||||
* the second one is. Both fields got two files attached, where one has
|
||||
* translatable content (title and atl-text) and the other one not.
|
||||
*
|
||||
* @return object
|
||||
* The node which is prepared with all needed fields for the suggestions.
|
||||
*/
|
||||
protected function prepareTranslationSuggestions() {
|
||||
// Create a content type with fields.
|
||||
// Only the first field is a translatable reference.
|
||||
$type = $this->drupalCreateContentType();
|
||||
|
||||
$field1 = field_create_field(array(
|
||||
'field_name' => 'field1',
|
||||
'type' => 'file',
|
||||
'cardinality' => -1,
|
||||
));
|
||||
$field2 = field_create_field(array(
|
||||
'field_name' => 'field2',
|
||||
'type' => 'file',
|
||||
'cardinality' => -1,
|
||||
'translatable' => TRUE,
|
||||
));
|
||||
$field3 = field_create_field(array(
|
||||
'field_name' => 'field3',
|
||||
'type' => 'entityreference',
|
||||
'cardinality' => -1,
|
||||
'settings' => array(
|
||||
'target_type' => 'node',
|
||||
'handler' => 'base',
|
||||
'handler_settings' => array(
|
||||
'target_bundles' => array($type->type => $type->type),
|
||||
'sort' => array('type' => 'none'),
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
// Create field instances on the content type.
|
||||
field_create_instance(array(
|
||||
'field_name' => $field1['field_name'],
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $type->type,
|
||||
'label' => 'Field 1',
|
||||
'widget' => array('type' => 'file'),
|
||||
'settings' => array(),
|
||||
));
|
||||
field_create_instance(array(
|
||||
'field_name' => $field2['field_name'],
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $type->type,
|
||||
'label' => 'Field 2',
|
||||
'widget' => array('type' => 'file'),
|
||||
'settings' => array(),
|
||||
));
|
||||
field_create_instance(array(
|
||||
'field_name' => $field3['field_name'],
|
||||
'entity_type' => 'node',
|
||||
'bundle' => $type->type,
|
||||
'label' => 'Field 3',
|
||||
'settings' => array(),
|
||||
'widget' => array('type' => 'entityreference_autocomplete_tags'),
|
||||
));
|
||||
|
||||
// Make the body field translatable from node.
|
||||
$info = field_info_field('body');
|
||||
$info['translatable'] = TRUE;
|
||||
field_update_field($info);
|
||||
|
||||
// Make the file entity fields translatable.
|
||||
$info = field_info_field('field_file_image_alt_text');
|
||||
$info['translatable'] = TRUE;
|
||||
field_update_field($info);
|
||||
|
||||
$info = field_info_field('field_file_image_title_text');
|
||||
$info['translatable'] = TRUE;
|
||||
field_update_field($info);
|
||||
|
||||
// Create and save files - two with some text and two with no text.
|
||||
list($file1, $file2, $file3, $file4) = $this->drupalGetTestFiles('image');
|
||||
$file2->field_file_image_alt_text['en'][0] = array(
|
||||
'value' => $this->randomName(),
|
||||
'type' => 'plain_text',
|
||||
);
|
||||
$file2->field_file_image_title_text['en'][0] = array(
|
||||
'value' => $this->randomName() . ' ' . $this->randomName(),
|
||||
'type' => 'plain_text',
|
||||
);
|
||||
|
||||
$file4->field_file_image_alt_text['en'][0] = array(
|
||||
'value' => $this->randomName(),
|
||||
'type' => 'plain_text',
|
||||
);
|
||||
$file4->field_file_image_title_text['en'][0] = array(
|
||||
'value' => $this->randomName() . ' ' . $this->randomName(),
|
||||
'type' => 'plain_text',
|
||||
);
|
||||
|
||||
file_save($file1);
|
||||
file_save($file2);
|
||||
file_save($file3);
|
||||
file_save($file4);
|
||||
|
||||
// Create a dummy node that will be referenced
|
||||
$referenced_node = $this->drupalCreateNode(array(
|
||||
'type' => $type->type,
|
||||
'language' => 'en',
|
||||
'body' => array(
|
||||
'en' => array(
|
||||
array('value' => $this->randomName() . ' ' . $this->randomName()),
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
// Create a node with two translatable and two non-translatable files.
|
||||
$node = $this->drupalCreateNode(array(
|
||||
'type' => $type->type,
|
||||
'language' => 'en',
|
||||
'body' => array('en' => array(
|
||||
array(
|
||||
'value' => $this->randomName(),
|
||||
),
|
||||
)),
|
||||
$field1['field_name'] => array(LANGUAGE_NONE => array(
|
||||
array(
|
||||
'fid' => $file1->fid,
|
||||
'display' => 1,
|
||||
'description' => '',
|
||||
),
|
||||
array(
|
||||
'fid' => $file2->fid,
|
||||
'display' => 1,
|
||||
'description' => '',
|
||||
),
|
||||
)),
|
||||
$field2['field_name'] => array(LANGUAGE_NONE => array(
|
||||
array(
|
||||
'fid' => $file3->fid,
|
||||
'display' => 1,
|
||||
'description' => '',
|
||||
),
|
||||
array(
|
||||
'fid' => $file4->fid,
|
||||
'display' => 1,
|
||||
'description' => '',
|
||||
),
|
||||
)),
|
||||
$field3['field_name'] => array(LANGUAGE_NONE => array(
|
||||
array('target_id' => $referenced_node->nid),
|
||||
)),
|
||||
));
|
||||
|
||||
// Create a translatable menu.
|
||||
$config = array(
|
||||
'menu_name' => 'translatable-menu',
|
||||
'title' => 'Translatable menu',
|
||||
'description' => $this->randomName(),
|
||||
'i18n_mode' => I18N_MODE_MULTIPLE,
|
||||
);
|
||||
menu_save($config);
|
||||
$menu = menu_load($config['menu_name']);
|
||||
|
||||
// Create a menu link for the node.
|
||||
$menu_link = array(
|
||||
'link_path' => 'node/' . $node->nid,
|
||||
'link_title' => 'Menu link one',
|
||||
// i18n_menu_link::get_title() uses the title, set that too.
|
||||
'title' => 'Menu link one',
|
||||
'menu_name' => $menu['menu_name'],
|
||||
'customized' => TRUE,
|
||||
);
|
||||
$node->link = menu_link_load(menu_link_save($menu_link));
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test suggested entities from a translation job.
|
||||
*/
|
||||
public function testSuggestions() {
|
||||
// Prepare a job and a node for testing.
|
||||
$job = $this->createJob();
|
||||
$node = $this->prepareTranslationSuggestions();
|
||||
$item = $job->addItem('entity', 'node', $node->nid);
|
||||
|
||||
// Get all suggestions and clean the list.
|
||||
$suggestions = $job->getSuggestions();
|
||||
$job->cleanSuggestionsList($suggestions);
|
||||
|
||||
// Check for suggestions.
|
||||
$this->assertEqual(count($suggestions), 4, 'Found four suggestions.');
|
||||
|
||||
// Check for valid attributes on the suggestions.
|
||||
foreach ($suggestions as $suggestion) {
|
||||
switch ($suggestion['reason']) {
|
||||
case 'Field Field 1':
|
||||
$this->assertEqual($suggestion['job_item']->getWordCount(), 3, 'Three translatable words in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->plugin, 'entity', 'Got an entity as plugin in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->item_type, 'file', 'Got a file in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->item_id, $node->field1[LANGUAGE_NONE][1]['fid'], 'File id match between node and suggestion.');
|
||||
break;
|
||||
case 'Field Field 2':
|
||||
$this->assertEqual($suggestion['job_item']->getWordCount(), 3, 'Three translatable words in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->plugin, 'entity', 'Got an entity as plugin in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->item_type, 'file', 'Got a file in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->item_id, $node->field2[LANGUAGE_NONE][1]['fid'], 'File id match between node and suggestion.');
|
||||
break;
|
||||
case 'Field Field 3':
|
||||
$this->assertEqual($suggestion['job_item']->getWordCount(), 2, 'Two translatable words in the suggestion');
|
||||
$this->assertEqual($suggestion['job_item']->plugin, 'entity', 'Got an entity as plugin in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->item_type, 'node', 'Got a node in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->item_id, $node->field3[LANGUAGE_NONE][0]['target_id'], 'File id match between node and suggestion.');
|
||||
break;
|
||||
case 'Menu link Menu link one':
|
||||
$this->assertEqual($suggestion['job_item']->getWordCount(), 3, 'Three translatable words in the suggestion' . $suggestion['job_item']->plugin . $suggestion['job_item']->item_type);
|
||||
$this->assertEqual($suggestion['job_item']->plugin, 'i18n_string', 'Got a string as plugin in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->item_type, 'menu_link', 'Got a menu link in the suggestion.');
|
||||
$this->assertEqual($suggestion['job_item']->item_id, 'menu:item:'. $node->link['mlid'], 'Menu link id match between menu link and suggestion.');
|
||||
break;
|
||||
default:
|
||||
$this->fail('Found an invalid suggestion.');
|
||||
break;
|
||||
}
|
||||
$this->assertEqual($suggestion['from_item'], $item->tjiid);
|
||||
$job->addExistingItem($suggestion['job_item']);
|
||||
}
|
||||
|
||||
// Re-get all suggestions.
|
||||
$suggestions = $job->getSuggestions();
|
||||
$job->cleanSuggestionsList($suggestions);
|
||||
|
||||
// Check for no more suggestions.
|
||||
$this->assertEqual(count($suggestions), 0, 'Found no more suggestion.');
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,257 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Abstract entity ui controller class for source plugin that provides
|
||||
* getEntity() method to retrieve list of entities of specific type. It also
|
||||
* allows to implement alter hook to alter the entity query for a specific type.
|
||||
*
|
||||
* @ingroup tmgmt_source
|
||||
*/
|
||||
abstract class TMGMTEntityDefaultSourceUIController extends TMGMTDefaultSourceUIController {
|
||||
|
||||
/**
|
||||
* Entity source list items limit.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $pagerLimit = 25;
|
||||
|
||||
/**
|
||||
* Gets entities data of provided type needed to build overview form list.
|
||||
*
|
||||
* @param $type
|
||||
* Entity type for which to get list of entities.
|
||||
* @param array $property_conditions
|
||||
* Array of key => $value pairs passed into
|
||||
* tmgmt_entity_get_translatable_entities() as the second parameter.
|
||||
*
|
||||
* @return array
|
||||
* Array of entities.
|
||||
*/
|
||||
public function getEntitiesTranslationData($type, $property_conditions = array()) {
|
||||
|
||||
$return_value = array();
|
||||
$entities = tmgmt_entity_get_translatable_entities($type, $property_conditions, TRUE);
|
||||
|
||||
$entity_info = entity_get_info($type);
|
||||
$bundles = tmgmt_entity_get_translatable_bundles($type);
|
||||
|
||||
// For retrieved entities add translation specific data.
|
||||
foreach ($entities as $entity) {
|
||||
|
||||
list($entity_id, , $bundle) = entity_extract_ids($type, $entity);
|
||||
$entity_uri = entity_uri($type, $entity);
|
||||
|
||||
// This occurs on user entity type.
|
||||
if (empty($entity_id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @var EntityTranslationDefaultHandler $handler
|
||||
*/
|
||||
$handler = entity_translation_get_handler($type, $entity);
|
||||
|
||||
// Get existing translations and current job items for the entity
|
||||
// to determine translation statuses
|
||||
$translations = $handler->getTranslations();
|
||||
$source_lang = entity_language($type, $entity);
|
||||
$current_job_items = tmgmt_job_item_load_latest('entity', $type, $entity_id, $source_lang);
|
||||
|
||||
// Load basic entity data.
|
||||
$return_value[$entity_id] = array(
|
||||
'entity_type' => $type,
|
||||
'entity_id' => $entity_id,
|
||||
'entity_label' => entity_label($type, $entity),
|
||||
'entity_uri' => $entity_uri['path'],
|
||||
);
|
||||
|
||||
if (count($bundles) > 1) {
|
||||
$return_value[$entity_id]['bundle'] = isset($bundles[$bundle]) ? $bundles[$bundle] : t('Unknown');
|
||||
}
|
||||
|
||||
// Load entity translation specific data.
|
||||
foreach (language_list() as $langcode => $language) {
|
||||
|
||||
$translation_status = 'current';
|
||||
|
||||
if ($langcode == $source_lang) {
|
||||
$translation_status = 'original';
|
||||
}
|
||||
elseif (!isset($translations->data[$langcode])) {
|
||||
$translation_status = 'missing';
|
||||
}
|
||||
elseif (!empty($translations->data[$langcode]['translate'])) {
|
||||
$translation_status = 'outofdate';
|
||||
}
|
||||
|
||||
$return_value[$entity_id]['current_job_items'][$langcode] = isset($current_job_items[$langcode]) ? $current_job_items[$langcode]: NULL;
|
||||
$return_value[$entity_id]['translation_statuses'][$langcode] = $translation_status;
|
||||
}
|
||||
}
|
||||
|
||||
return $return_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds search form for entity sources overview.
|
||||
*
|
||||
* @param array $form
|
||||
* Drupal form array.
|
||||
* @param $form_state
|
||||
* Drupal form_state array.
|
||||
* @param $type
|
||||
* Entity type.
|
||||
*
|
||||
* @return array
|
||||
* Drupal form array.
|
||||
*/
|
||||
public function overviewSearchFormPart($form, &$form_state, $type) {
|
||||
|
||||
// Add search form specific styling.
|
||||
drupal_add_css(drupal_get_path('module', 'tmgmt_entity') . '/css/tmgmt_entity.admin.entity_source_search_form.css');
|
||||
|
||||
$form = array();
|
||||
// Add entity type value into form array so that it is available in
|
||||
// the form alter hook.
|
||||
$form_state['entity_type'] = $type;
|
||||
|
||||
$form['search_wrapper'] = array(
|
||||
'#prefix' => '<div class="tmgmt-sources-wrapper tmgmt-entity-sources-wrapper">',
|
||||
'#suffix' => '</div>',
|
||||
'#weight' => -15,
|
||||
);
|
||||
$form['search_wrapper']['search'] = array(
|
||||
'#tree' => TRUE,
|
||||
);
|
||||
|
||||
$form['search_wrapper']['search_submit'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Search'),
|
||||
'#weight' => 10,
|
||||
);
|
||||
$form['search_wrapper']['search_cancel'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Cancel'),
|
||||
'#weight' => 11,
|
||||
);
|
||||
|
||||
$entity_info = entity_get_info($type);
|
||||
|
||||
$label_key = isset($entity_info['entity keys']['label']) ? $entity_info['entity keys']['label'] : NULL;
|
||||
|
||||
if (!empty($label_key)) {
|
||||
$form['search_wrapper']['search'][$label_key] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('@entity_name title', array('@entity_name' => $entity_info['label'])),
|
||||
'#size' => 25,
|
||||
'#default_value' => isset($_GET[$label_key]) ? $_GET[$label_key] : NULL,
|
||||
);
|
||||
}
|
||||
|
||||
$language_options = array();
|
||||
foreach (language_list() as $langcode => $language) {
|
||||
$language_options[$langcode] = $language->name;
|
||||
}
|
||||
|
||||
$form['search_wrapper']['search']['language'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Source Language'),
|
||||
'#options' => $language_options,
|
||||
'#empty_option' => t('All'),
|
||||
'#default_value' => isset($_GET['language']) ? $_GET['language'] : NULL,
|
||||
);
|
||||
|
||||
$bundle_key = $entity_info['entity keys']['bundle'];
|
||||
$bundle_options = tmgmt_entity_get_translatable_bundles($type);
|
||||
|
||||
if (count($bundle_options) > 1) {
|
||||
$form['search_wrapper']['search'][$bundle_key] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('@entity_name type', array('@entity_name' => $entity_info['label'])),
|
||||
'#options' => $bundle_options,
|
||||
'#empty_option' => t('All'),
|
||||
'#default_value' => isset($_GET[$bundle_key]) ? $_GET[$bundle_key] : NULL,
|
||||
);
|
||||
}
|
||||
// In case entity translation is not enabled for any of bundles
|
||||
// display appropriate message.
|
||||
elseif (count($bundle_options) == 0) {
|
||||
drupal_set_message(t('Entity translation is not enabled for any of existing content types. To use this functionality go to Content types administration and enable entity translation for desired content types.'), 'warning');
|
||||
unset($form['search_wrapper']);
|
||||
}
|
||||
|
||||
$options = array();
|
||||
foreach (language_list() as $langcode => $language) {
|
||||
$options[$langcode] = $language->name;
|
||||
}
|
||||
|
||||
$form['search_wrapper']['search']['target_language'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Target language'),
|
||||
'#options' => $options,
|
||||
'#empty_option' => t('Any'),
|
||||
'#default_value' => isset($_GET['target_language']) ? $_GET['target_language'] : NULL,
|
||||
);
|
||||
$form['search_wrapper']['search']['target_status'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Target status'),
|
||||
'#options' => array(
|
||||
'untranslated_or_outdated' => t('Untranslated or outdated'),
|
||||
'untranslated' => t('Untranslated'),
|
||||
'outdated' => t('Outdated'),
|
||||
),
|
||||
'#default_value' => isset($_GET['target_status']) ? $_GET['target_status'] : NULL,
|
||||
'#states' => array(
|
||||
'invisible' => array(
|
||||
':input[name="search[target_language]"]' => array('value' => ''),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs redirect with search params appended to the uri.
|
||||
*
|
||||
* In case of triggering element is edit-search-submit it redirects to
|
||||
* current location with added query string containing submitted search form
|
||||
* values.
|
||||
*
|
||||
* @param array $form
|
||||
* Drupal form array.
|
||||
* @param $form_state
|
||||
* Drupal form_state array.
|
||||
* @param $type
|
||||
* Entity type.
|
||||
*/
|
||||
public function overviewSearchFormRedirect($form, &$form_state, $type) {
|
||||
if ($form_state['triggering_element']['#id'] == 'edit-search-cancel') {
|
||||
drupal_goto($_GET['q']);
|
||||
}
|
||||
elseif ($form_state['triggering_element']['#id'] == 'edit-search-submit') {
|
||||
|
||||
$query = array();
|
||||
|
||||
foreach ($form_state['values']['search'] as $key => $value) {
|
||||
$query[$key] = $value;
|
||||
}
|
||||
|
||||
drupal_goto($_GET['q'], array('query' => $query));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hook_menu() {
|
||||
$items = parent::hook_menu();
|
||||
if (isset($items['admin/tmgmt/sources/entity_node'])) {
|
||||
// We assume that nodes are the most important overview if enabled, so
|
||||
// make sure they show up first.
|
||||
$items['admin/tmgmt/sources/entity_node']['weight'] = -20;
|
||||
}
|
||||
return $items;
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
name = Entity Source User Interface
|
||||
description = User Interface for the entity translation source plugin.
|
||||
package = Translation Management
|
||||
core = 7.x
|
||||
|
||||
dependencies[] = tmgmt_entity
|
||||
dependencies[] = tmgmt_ui
|
||||
dependencies[] = views_bulk_operations
|
||||
|
||||
files[] = tmgmt_entity_ui.test
|
||||
files[] = tmgmt_entity_ui.list.test
|
||||
files[] = tmgmt_entity_ui.ui.inc
|
||||
|
||||
|
||||
; Information added by Drupal.org packaging script on 2016-09-21
|
||||
version = "7.x-1.0-rc2+1-dev"
|
||||
core = "7.x"
|
||||
project = "tmgmt"
|
||||
datestamp = "1474446494"
|
||||
|
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
|
||||
|
||||
class TMGMTEntitySourceListTestCase extends TMGMTEntityTestCaseUtility {
|
||||
|
||||
protected $nodes = array();
|
||||
|
||||
static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Entity Source List tests',
|
||||
'description' => 'Tests the user interface for entity translation lists.',
|
||||
'group' => 'Translation Management',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('tmgmt_entity_ui', 'translation', 'comment', 'taxonomy'));
|
||||
$this->loginAsAdmin(array('administer entity translation'));
|
||||
|
||||
$this->setEnvironment('de');
|
||||
$this->setEnvironment('fr');
|
||||
|
||||
// Enable entity translations for nodes and comments.
|
||||
$edit = array();
|
||||
$edit['entity_translation_entity_types[comment]'] = 1;
|
||||
$edit['entity_translation_entity_types[node]'] = 1;
|
||||
$edit['entity_translation_entity_types[taxonomy_term]'] = 1;
|
||||
$this->drupalPost('admin/config/regional/entity_translation', $edit, t('Save configuration'));
|
||||
|
||||
$this->createNodeType('article', 'Article', ENTITY_TRANSLATION_ENABLED);
|
||||
$this->createNodeType('page', 'Page', TRANSLATION_ENABLED);
|
||||
|
||||
// Create nodes that will be used during tests.
|
||||
// NOTE that the order matters as results are read by xpath based on
|
||||
// position in the list.
|
||||
$this->nodes['page']['en'][] = $this->createNode('page');
|
||||
$this->nodes['article']['de'][0] = $this->createNode('article', 'de');
|
||||
$this->nodes['article']['fr'][0] = $this->createNode('article', 'fr');
|
||||
$this->nodes['article']['en'][3] = $this->createNode('article', 'en');
|
||||
$this->nodes['article']['en'][2] = $this->createNode('article', 'en');
|
||||
$this->nodes['article']['en'][1] = $this->createNode('article', 'en');
|
||||
$this->nodes['article']['en'][0] = $this->createNode('article', 'en');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the term bundle filter works.
|
||||
*/
|
||||
function testTermBundleFilter() {
|
||||
|
||||
$vocabulary1 = entity_create('taxonomy_vocabulary', array(
|
||||
'machine_name' => 'vocab1',
|
||||
'name' => $this->randomName(),
|
||||
));
|
||||
taxonomy_vocabulary_save($vocabulary1);
|
||||
|
||||
$term1 = entity_create('taxonomy_term', array(
|
||||
'name' => $this->randomName(),
|
||||
'vid' => $vocabulary1->vid,
|
||||
));
|
||||
taxonomy_term_save($term1);
|
||||
|
||||
$vocabulary2 = (object) array(
|
||||
'machine_name' => 'vocab2',
|
||||
'name' => $this->randomName(),
|
||||
);
|
||||
taxonomy_vocabulary_save($vocabulary2);
|
||||
|
||||
$term2 = entity_create('taxonomy_term', array(
|
||||
'name' => $this->randomName(),
|
||||
'vid' => $vocabulary2->vid,
|
||||
));
|
||||
taxonomy_term_save($term2);
|
||||
|
||||
$this->drupalGet('admin/tmgmt/sources/entity_taxonomy_term');
|
||||
// Both terms should be displayed with their bundle.
|
||||
$this->assertText($term1->name);
|
||||
$this->assertText($term2->name);
|
||||
$this->assertTrue($this->xpath('//td[text()=@vocabulary]', array('@vocabulary' => $vocabulary1->name)));
|
||||
$this->assertTrue($this->xpath('//td[text()=@vocabulary]', array('@vocabulary' => $vocabulary2->name)));
|
||||
|
||||
// Limit to the first vocabulary.
|
||||
$edit = array();
|
||||
$edit['search[vocabulary_machine_name]'] = $vocabulary1->machine_name;
|
||||
$this->drupalPost(NULL, $edit, t('Search'));
|
||||
// Only term 1 should be displayed now.
|
||||
$this->assertText($term1->name);
|
||||
$this->assertNoText($term2->name);
|
||||
$this->assertTrue($this->xpath('//td[text()=@vocabulary]', array('@vocabulary' => $vocabulary1->name)));
|
||||
$this->assertFalse($this->xpath('//td[text()=@vocabulary]', array('@vocabulary' => $vocabulary2->name)));
|
||||
|
||||
}
|
||||
|
||||
function testAvailabilityOfEntityLists() {
|
||||
|
||||
$this->drupalGet('admin/tmgmt/sources/entity_comment');
|
||||
// Check if we are at comments page.
|
||||
$this->assertText(t('Comment overview (Entity)'));
|
||||
// No comments yet - empty message is expected.
|
||||
$this->assertText(t('No entities matching given criteria have been found.'));
|
||||
|
||||
$this->drupalGet('admin/tmgmt/sources/entity_node');
|
||||
// Check if we are at nodes page.
|
||||
$this->assertText(t('Node overview (Entity)'));
|
||||
// We expect article title as article node type is entity translatable.
|
||||
$this->assertText($this->nodes['article']['en'][0]->title);
|
||||
// Page node type should not be listed as it is not entity translatable.
|
||||
$this->assertNoText($this->nodes['page']['en'][0]->title);
|
||||
}
|
||||
|
||||
function testTranslationStatuses() {
|
||||
|
||||
// Test statuses: Source, Missing.
|
||||
$this->drupalGet('admin/tmgmt/sources/entity_node');
|
||||
$langstatus_en = $this->xpath('//table[@id="tmgmt-entities-list"]/tbody/tr[1]/td[@class="langstatus-en"]');
|
||||
$langstatus_de = $this->xpath('//table[@id="tmgmt-entities-list"]/tbody/tr[1]/td[@class="langstatus-de"]');
|
||||
|
||||
$this->assertEqual($langstatus_en[0]->div['title'], t('Source language'));
|
||||
$this->assertEqual($langstatus_de[0]->div['title'], t('Not translated'));
|
||||
|
||||
// Test status: Active job item.
|
||||
$job = $this->createJob('en', 'de');
|
||||
$job->translator = $this->default_translator->name;
|
||||
$job->settings = array();
|
||||
$job->save();
|
||||
|
||||
$job->addItem('entity', 'node', $this->nodes['article']['en'][0]->nid);
|
||||
$job->requestTranslation();
|
||||
|
||||
$this->drupalGet('admin/tmgmt/sources/entity_node');
|
||||
$langstatus_de = $this->xpath('//table[@id="tmgmt-entities-list"]/tbody/tr[1]/td[@class="langstatus-de"]/a');
|
||||
|
||||
$items = $job->getItems();
|
||||
$wrapper = entity_metadata_wrapper('tmgmt_job_item', array_shift($items));
|
||||
$label = t('Active job item: @state', array('@state' => $wrapper->state->label()));
|
||||
|
||||
$this->assertEqual($langstatus_de[0]->div['title'], $label);
|
||||
|
||||
// Test status: Current
|
||||
foreach ($job->getItems() as $job_item) {
|
||||
$job_item->acceptTranslation();
|
||||
}
|
||||
|
||||
$this->drupalGet('admin/tmgmt/sources/entity_node');
|
||||
$langstatus_de = $this->xpath('//table[@id="tmgmt-entities-list"]/tbody/tr[1]/td[@class="langstatus-de"]');
|
||||
|
||||
$this->assertEqual($langstatus_de[0]->div['title'], t('Translation up to date'));
|
||||
}
|
||||
|
||||
function testTranslationSubmissions() {
|
||||
|
||||
// Simple submission.
|
||||
$nid = $this->nodes['article']['en'][0]->nid;
|
||||
$edit = array();
|
||||
$edit["items[$nid]"] = 1;
|
||||
$this->drupalPost('admin/tmgmt/sources/entity_node', $edit, t('Request translation'));
|
||||
$this->assertText(t('One job needs to be checked out.'));
|
||||
|
||||
// Submission of two entities of the same source language.
|
||||
$nid1 = $this->nodes['article']['en'][0]->nid;
|
||||
$nid2 = $this->nodes['article']['en'][1]->nid;
|
||||
$edit = array();
|
||||
$edit["items[$nid1]"] = 1;
|
||||
$edit["items[$nid2]"] = 1;
|
||||
$this->drupalPost('admin/tmgmt/sources/entity_node', $edit, t('Request translation'));
|
||||
$this->assertText(t('One job needs to be checked out.'));
|
||||
|
||||
// Submission of several entities of different source languages.
|
||||
$nid1 = $this->nodes['article']['en'][0]->nid;
|
||||
$nid2 = $this->nodes['article']['en'][1]->nid;
|
||||
$nid3 = $this->nodes['article']['en'][2]->nid;
|
||||
$nid4 = $this->nodes['article']['en'][3]->nid;
|
||||
$nid5 = $this->nodes['article']['de'][0]->nid;
|
||||
$nid6 = $this->nodes['article']['fr'][0]->nid;
|
||||
$edit = array();
|
||||
$edit["items[$nid1]"] = 1;
|
||||
$edit["items[$nid2]"] = 1;
|
||||
$edit["items[$nid3]"] = 1;
|
||||
$edit["items[$nid4]"] = 1;
|
||||
$edit["items[$nid5]"] = 1;
|
||||
$edit["items[$nid6]"] = 1;
|
||||
$this->drupalPost('admin/tmgmt/sources/entity_node', $edit, t('Request translation'));
|
||||
$this->assertText(t('@count jobs need to be checked out.', array('@count' => '3')));
|
||||
}
|
||||
|
||||
function testNodeEntityListings() {
|
||||
|
||||
// Turn off the entity translation.
|
||||
$edit = array();
|
||||
$edit['language_content_type'] = TRANSLATION_ENABLED;
|
||||
$this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type'));
|
||||
|
||||
// Check if we have appropriate message in case there are no entity
|
||||
// translatable content types.
|
||||
$this->drupalGet('admin/tmgmt/sources/entity_node');
|
||||
$this->assertText(t('Entity translation is not enabled for any of existing content types. To use this functionality go to Content types administration and enable entity translation for desired content types.'));
|
||||
|
||||
// Turn on the entity translation for both - article and page - to test
|
||||
// search form.
|
||||
$edit = array();
|
||||
$edit['language_content_type'] = ENTITY_TRANSLATION_ENABLED;
|
||||
$this->drupalPost('admin/structure/types/manage/article', $edit, t('Save content type'));
|
||||
$this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
// Create page node after entity translation is enabled.
|
||||
$page_node_translatable = $this->createNode('page');
|
||||
|
||||
$this->drupalGet('admin/tmgmt/sources/entity_node');
|
||||
// We have both listed - one of articles and page.
|
||||
$this->assertText($this->nodes['article']['en'][0]->title);
|
||||
$this->assertText($page_node_translatable->title);
|
||||
|
||||
// Try the search by content type.
|
||||
$edit = array();
|
||||
$edit['search[type]'] = 'article';
|
||||
$this->drupalPost('admin/tmgmt/sources/entity_node', $edit, t('Search'));
|
||||
// There should be article present.
|
||||
$this->assertText($this->nodes['article']['en'][0]->title);
|
||||
// The page node should not be listed.
|
||||
$this->assertNoText($page_node_translatable->title);
|
||||
|
||||
// Try cancel button - despite we do post content type search value
|
||||
// we should get nodes of botch content types.
|
||||
$this->drupalPost('admin/tmgmt/sources/entity_node', $edit, t('Cancel'));
|
||||
$this->assertText($this->nodes['article']['en'][0]->title);
|
||||
$this->assertText($page_node_translatable->title);
|
||||
}
|
||||
|
||||
function testEntitySourceListSearch() {
|
||||
|
||||
// We need a node with title composed of several words to test
|
||||
// "any words" search.
|
||||
$title_part_1 = $this->randomName('4');
|
||||
$title_part_2 = $this->randomName('4');
|
||||
$title_part_3 = $this->randomName('4');
|
||||
|
||||
$this->nodes['article']['en'][0]->title = "$title_part_1 $title_part_2 $title_part_3";
|
||||
node_save($this->nodes['article']['en'][0]);
|
||||
|
||||
// Submit partial node title and see if we have a result.
|
||||
$edit = array();
|
||||
$edit['search[title]'] = "$title_part_1 $title_part_3";
|
||||
$this->drupalPost('admin/tmgmt/sources/entity_node', $edit, t('Search'));
|
||||
$this->assertText("$title_part_1 $title_part_2 $title_part_3", 'Searching on partial node title must return the result.');
|
||||
|
||||
// Check if there is only one result in the list.
|
||||
$search_result_rows = $this->xpath('//table[@id="tmgmt-entities-list"]/tbody/tr');
|
||||
$this->assert(count($search_result_rows) == 1, 'The search result must return only one row.');
|
||||
|
||||
// To test if other entity types work go for simple comment search.
|
||||
$comment = new stdClass();
|
||||
$comment->comment_body[LANGUAGE_NONE][0]['value'] = $this->randomName();
|
||||
$comment->subject = $this->randomName();
|
||||
// We need to associate the comment with entity translatable node object.
|
||||
$comment->nid = $this->nodes['article']['en'][0]->nid;
|
||||
// Set defaults - without these we will get Undefined property notices.
|
||||
$comment->is_anonymous = TRUE;
|
||||
$comment->cid = 0;
|
||||
$comment->pid = 0;
|
||||
$comment->uid = 0;
|
||||
// Will add further comment variables.
|
||||
$comment = comment_submit($comment);
|
||||
comment_save($comment);
|
||||
// Do search for the comment.
|
||||
$edit = array();
|
||||
$edit['search[subject]'] = $comment->subject;
|
||||
$this->drupalPost('admin/tmgmt/sources/entity_comment', $edit, t('Search'));
|
||||
$this->assertText($comment->subject, 'Searching for a comment subject.');
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Main module file for the translation management entity source plugin user
|
||||
* interface.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements hook_page_alter().
|
||||
*/
|
||||
function tmgmt_entity_ui_page_alter(&$page) {
|
||||
if (entity_access('create', 'tmgmt_job')) {
|
||||
// Translation tabs for nodes.
|
||||
if (isset($page['content']['system_main']['entity_translation_overview'])) {
|
||||
module_load_include('inc', 'tmgmt_entity_ui', 'tmgmt_entity_ui.pages');
|
||||
$page['content']['system_main']['entity_translation_overview'] = drupal_get_form('tmgmt_entity_ui_translate_form', $page['content']['system_main']);
|
||||
}
|
||||
// Support the context module: when context is used for placing the
|
||||
// system_main block, then block contents appear nested one level deeper
|
||||
// under another 'content' key.
|
||||
elseif (isset($page['content']['system_main']['content']['entity_translation_overview'])) {
|
||||
module_load_include('inc', 'tmgmt_entity_ui', 'tmgmt_entity_ui.pages');
|
||||
$page['content']['system_main']['content']['entity_translation_overview'] = drupal_get_form('tmgmt_entity_ui_translate_form', $page['content']['system_main']['content']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements tmgmt_entity_tmgmt_source_plugin_info_alter().
|
||||
*/
|
||||
function tmgmt_entity_ui_tmgmt_source_plugin_info_alter(&$info) {
|
||||
|
||||
// Define ui controller class to handle Drupal entities.
|
||||
$info['entity']['ui controller class'] = 'TMGMTEntitySourceUIController';
|
||||
|
||||
// Alter file and file path info so that tmgmt_entity_ui module is targeted
|
||||
// for page callback.
|
||||
$info['entity']['file'] = 'tmgmt_entity_ui.pages.inc';
|
||||
$info['entity']['file path'] = drupal_get_path('module', 'tmgmt_entity_ui');
|
||||
}
|
||||
|
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Provides page and form callbacks for the Translation Management Tool Entity
|
||||
* Source User Interface module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Entity translation overview form.
|
||||
*/
|
||||
function tmgmt_entity_ui_translate_form($form, &$form_state, $build) {
|
||||
// Store the entity in the form state so we can easily create the job in the
|
||||
// submit handler.
|
||||
$form_state['entity_type'] = $build['#entity_type'];
|
||||
$form_state['entity'] = $build['#entity'];
|
||||
|
||||
$overview = $build['entity_translation_overview'];
|
||||
|
||||
list($id, $vid, $bundle) = entity_extract_ids($form_state['entity_type'], $form_state['entity']);
|
||||
|
||||
$form['top_actions']['#type'] = 'actions';
|
||||
$form['top_actions']['#weight'] = -10;
|
||||
tmgmt_ui_add_cart_form($form['top_actions'], $form_state, 'entity', $build['#entity_type'], $id);
|
||||
|
||||
// Inject our additional column into the header.
|
||||
array_splice($overview['#header'], -1, 0, array(t('Pending Translations')));
|
||||
// Make this a tableselect form.
|
||||
$form['languages'] = array(
|
||||
'#type' => 'tableselect',
|
||||
'#header' => $overview['#header'],
|
||||
'#options' => array(),
|
||||
);
|
||||
$languages = language_list();
|
||||
// Check if there is a job / job item that references this translation.
|
||||
$entity_language = entity_language($form_state['entity_type'], $form_state['entity']);
|
||||
$items = tmgmt_job_item_load_latest('entity', $form_state['entity_type'], $id, $entity_language);
|
||||
foreach ($languages as $langcode => $language) {
|
||||
if ($langcode == LANGUAGE_NONE) {
|
||||
// Never show language neutral on the overview.
|
||||
continue;
|
||||
}
|
||||
// Since the keys are numeric and in the same order we can shift one element
|
||||
// after the other from the original non-form rows.
|
||||
$option = array_shift($overview['#rows']);
|
||||
if ($langcode == $entity_language) {
|
||||
$additional = '<strong>' . t('Source') . '</strong>';
|
||||
// This is the source object so we disable the checkbox for this row.
|
||||
$form['languages'][$langcode] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#disabled' => TRUE,
|
||||
);
|
||||
}
|
||||
elseif (isset($items[$langcode])) {
|
||||
$item = $items[$langcode];
|
||||
$uri = $item->uri();
|
||||
$wrapper = entity_metadata_wrapper('tmgmt_job_item', $item);
|
||||
$additional = l($wrapper->state->label(), $uri['path'], array('query' => array('destination' => current_path())));
|
||||
// Disable the checkbox for this row since there is already a translation
|
||||
// in progress that has not yet been finished. This way we make sure that
|
||||
// we don't stack multiple active translations for the same item on top
|
||||
// of each other.
|
||||
$form['languages'][$langcode] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#disabled' => TRUE,
|
||||
);
|
||||
}
|
||||
else {
|
||||
// There is no translation job / job item for this target language.
|
||||
$additional = t('None');
|
||||
}
|
||||
// Inject the additional column into the array.
|
||||
|
||||
// The generated form structure has changed, support both an additional
|
||||
// 'data' key (that is not supported by tableselect) and the old version
|
||||
// without.
|
||||
if (isset($option['data'])) {
|
||||
array_splice($option['data'], -1, 0, array($additional));
|
||||
// Append the current option array to the form.
|
||||
$form['languages']['#options'][$langcode] = $option['data'];
|
||||
}
|
||||
else {
|
||||
array_splice($option, -1, 0, array($additional));
|
||||
// Append the current option array to the form.
|
||||
$form['languages']['#options'][$langcode] = $option;
|
||||
}
|
||||
}
|
||||
$form['actions']['#type'] = 'actions';
|
||||
$form['actions']['request'] = array(
|
||||
'#type' => 'submit',
|
||||
'#value' => t('Request translation'),
|
||||
'#submit' => array('tmgmt_entity_ui_translate_form_submit'),
|
||||
'#validate' => array('tmgmt_entity_ui_translate_form_validate'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation callback for the entity translation overview form.
|
||||
*/
|
||||
function tmgmt_entity_ui_translate_form_validate($form, &$form_state) {
|
||||
$selected = array_filter($form_state['values']['languages']);
|
||||
if (empty($selected)) {
|
||||
form_set_error('languages', t('You have to select at least one language for requesting a translation.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit callback for the entity translation overview form.
|
||||
*/
|
||||
function tmgmt_entity_ui_translate_form_submit($form, &$form_state) {
|
||||
$entity = $form_state['entity'];
|
||||
$entity_type = $form_state['entity_type'];
|
||||
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
|
||||
$values = $form_state['values'];
|
||||
$jobs = array();
|
||||
foreach (array_keys(array_filter($values['languages'])) as $langcode) {
|
||||
// Create the job object.
|
||||
$job = tmgmt_job_create(entity_language($entity_type, $entity), $langcode, $GLOBALS['user']->uid);
|
||||
try {
|
||||
// Add the job item.
|
||||
$job->addItem('entity', $entity_type, $id);
|
||||
// Append this job to the array of created jobs so we can redirect the user
|
||||
// to a multistep checkout form if necessary.
|
||||
$jobs[$job->tjid] = $job;
|
||||
}
|
||||
catch (TMGMTException $e) {
|
||||
watchdog_exception('tmgmt', $e);
|
||||
$languages = language_list();
|
||||
$target_lang_name = $languages[$langcode]->language;
|
||||
drupal_set_message(t('Unable to add job item for target language %name. Make sure the source content is not empty.', array('%name' => $target_lang_name)), 'error');
|
||||
}
|
||||
}
|
||||
tmgmt_ui_job_checkout_and_redirect($form_state, $jobs);
|
||||
}
|
@@ -0,0 +1,328 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Basic Node Source tests.
|
||||
*
|
||||
*/
|
||||
class TMGMTEntitySourceUITestCase extends TMGMTEntityTestCaseUtility {
|
||||
|
||||
static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Entity Source UI tests',
|
||||
'description' => 'Tests the user interface for entity translation sources.',
|
||||
'group' => 'Translation Management',
|
||||
'dependencies' => array('entity_translation'),
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
parent::setUp(array('tmgmt_entity_ui', 'block', 'comment'));
|
||||
variable_set('language_content_type_page', ENTITY_TRANSLATION_ENABLED);
|
||||
variable_set('language_content_type_article', ENTITY_TRANSLATION_ENABLED);
|
||||
|
||||
$this->loginAsAdmin(array(
|
||||
'create translation jobs',
|
||||
'submit translation jobs',
|
||||
'accept translation jobs',
|
||||
'administer blocks',
|
||||
'administer entity translation',
|
||||
'toggle field translatability',
|
||||
));
|
||||
|
||||
$this->setEnvironment('de');
|
||||
$this->setEnvironment('fr');
|
||||
$this->setEnvironment('es');
|
||||
$this->setEnvironment('el');
|
||||
|
||||
$this->createNodeType('page', st('Page'), ENTITY_TRANSLATION_ENABLED);
|
||||
$this->createNodeType('article', st('Article'), ENTITY_TRANSLATION_ENABLED);
|
||||
|
||||
// Enable path locale detection.
|
||||
$edit = array(
|
||||
'language[enabled][locale-url]' => TRUE,
|
||||
'language_content[enabled][locale-interface]' => TRUE,
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings'));
|
||||
|
||||
// @todo Re-enable this when switching to testing profile.
|
||||
// Enable the main page content block for hook_page_alter() to work.
|
||||
$edit = array(
|
||||
'blocks[system_main][region]' => 'content',
|
||||
);
|
||||
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the translate tab for a single checkout.
|
||||
*/
|
||||
function testNodeTranslateTabSingleCheckout() {
|
||||
|
||||
$this->loginAsTranslator(array('translate node entities'));
|
||||
|
||||
// Create an english source node.
|
||||
$node = $this->createNode('page', 'en');
|
||||
// Create a nodes that will not be translated to test the missing
|
||||
// translation filter.
|
||||
$node_not_translated = $this->createNode('page', 'en');
|
||||
$node_german = $this->createNode('page', 'de');
|
||||
|
||||
// Go to the translate tab.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->clickLink('Translate');
|
||||
|
||||
// Assert some basic strings on that page.
|
||||
$this->assertText(t('Translations of @title', array('@title' => $node->title)));
|
||||
$this->assertText(t('Pending Translations'));
|
||||
|
||||
// Request a translation for german.
|
||||
$edit = array(
|
||||
'languages[de]' => TRUE,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Request translation'));
|
||||
|
||||
// Verify that we are on the translate tab.
|
||||
$this->assertText(t('One job needs to be checked out.'));
|
||||
$this->assertText($node->title);
|
||||
|
||||
// Submit.
|
||||
$this->drupalPost(NULL, array(), t('Submit to translator'));
|
||||
|
||||
// Make sure that we're back on the translate tab.
|
||||
$this->assertEqual(url('node/' . $node->nid . '/translate', array('absolute' => TRUE)), $this->getUrl());
|
||||
$this->assertText(t('Test translation created.'));
|
||||
$this->assertText(t('The translation of @title to @language is finished and can now be reviewed.', array('@title' => $node->title, '@language' => t('German'))));
|
||||
|
||||
// Verify that the pending translation is shown.
|
||||
$this->clickLink(t('Needs review'));
|
||||
$this->drupalPost(NULL, array(), t('Save as completed'));
|
||||
|
||||
$this->assertText(t('The translation for @title has been accepted.', array('@title' => $node->title)));
|
||||
|
||||
// German node should now be listed and be clickable.
|
||||
// @todo Improve detection of the link, e.g. use xpath on the table or the
|
||||
// title module to get a better title.
|
||||
$this->clickLink('view', 1);
|
||||
$this->assertText('de_' . $node->body['en'][0]['value']);
|
||||
|
||||
// Test that the destination query argument does not break the redirect
|
||||
// and we are redirected back to the correct page.
|
||||
$this->drupalGet('node/' . $node->nid . '/translate', array('query' => array('destination' => 'node')));
|
||||
|
||||
// Request a spanish translation.
|
||||
$edit = array(
|
||||
'languages[es]' => TRUE,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Request translation'));
|
||||
|
||||
// Verify that we are on the checkout page.
|
||||
$this->assertText(t('One job needs to be checked out.'));
|
||||
$this->assertText($node->title);
|
||||
$this->drupalPost(NULL, array(), t('Submit to translator'));
|
||||
|
||||
// Make sure that we're back on the originally defined destination URL.
|
||||
$this->assertEqual(url('node', array('absolute' => TRUE)), $this->getUrl());
|
||||
|
||||
// Test the missing translation filter.
|
||||
$this->drupalGet('admin/tmgmt/sources');
|
||||
$this->assertText($node->title);
|
||||
$this->assertText($node_not_translated->title);
|
||||
$this->drupalPost(NULL, array(
|
||||
'search[target_language]' => 'de',
|
||||
'search[target_status]' => 'untranslated',
|
||||
), t('Search'));
|
||||
$this->assertNoText($node->title);
|
||||
$this->assertNoText($node_german->title);
|
||||
$this->assertText($node_not_translated->title);
|
||||
// Update the the translate flag of the translated node and test if it is
|
||||
// listed among sources with missing translation.
|
||||
db_update('entity_translation')->fields(array('translate' => 1))
|
||||
->condition('entity_type', 'node')->condition('entity_id', $node->nid)->execute();
|
||||
$this->drupalPost(NULL, array(
|
||||
'search[target_language]' => 'de',
|
||||
'search[target_status]' => 'outdated',
|
||||
), t('Search'));
|
||||
$this->assertText($node->title);
|
||||
$this->assertNoText($node_german->title);
|
||||
$this->assertNoText($node_not_translated->title);
|
||||
|
||||
$this->drupalPost(NULL, array(
|
||||
'search[target_language]' => 'de',
|
||||
'search[target_status]' => 'untranslated_or_outdated',
|
||||
), t('Search'));
|
||||
$this->assertText($node->title);
|
||||
$this->assertNoText($node_german->title);
|
||||
$this->assertText($node_not_translated->title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the translate tab for a single checkout.
|
||||
*/
|
||||
function testNodeTranslateTabMultipeCheckout() {
|
||||
// Allow auto-accept.
|
||||
$default_translator = tmgmt_translator_load('test_translator');
|
||||
$default_translator->settings = array(
|
||||
'auto_accept' => TRUE,
|
||||
);
|
||||
$default_translator->save();
|
||||
|
||||
$this->loginAsTranslator(array('translate node entities'));
|
||||
|
||||
// Create an english source node.
|
||||
$node = $this->createNode('page', 'en');
|
||||
|
||||
// Go to the translate tab.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$this->clickLink('Translate');
|
||||
|
||||
// Assert some basic strings on that page.
|
||||
$this->assertText(t('Translations of @title', array('@title' => $node->title)));
|
||||
$this->assertText(t('Pending Translations'));
|
||||
|
||||
// Request a translation for german.
|
||||
$edit = array(
|
||||
'languages[de]' => TRUE,
|
||||
'languages[es]' => TRUE,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Request translation'));
|
||||
|
||||
// Verify that we are on the translate tab.
|
||||
$this->assertText(t('2 jobs need to be checked out.'));
|
||||
|
||||
// Submit all jobs.
|
||||
$this->assertText($node->title);
|
||||
$this->drupalPost(NULL, array(), t('Submit to translator and continue'));
|
||||
$this->assertText($node->title);
|
||||
$this->drupalPost(NULL, array(), t('Submit to translator'));
|
||||
|
||||
// Make sure that we're back on the translate tab.
|
||||
$this->assertEqual(url('node/' . $node->nid . '/translate', array('absolute' => TRUE)), $this->getUrl());
|
||||
$this->assertText(t('Test translation created.'));
|
||||
$this->assertNoText(t('The translation of @title to @language is finished and can now be reviewed.', array('@title' => $node->title, '@language' => t('Spanish'))));
|
||||
$this->assertText(t('The translation for @title has been accepted.', array('@title' => $node->title)));
|
||||
|
||||
// Translated nodes should now be listed and be clickable.
|
||||
// @todo Use links on translate tab.
|
||||
$this->drupalGet('de/node/' . $node->nid);
|
||||
$this->assertText('de_' . $node->body['en'][0]['value']);
|
||||
|
||||
$this->drupalGet('es/node/' . $node->nid);
|
||||
$this->assertText('es_' . $node->body['en'][0]['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test translating comments.
|
||||
*
|
||||
* @todo: Disabled pending resolution of http://drupal.org/node/1760270.
|
||||
*/
|
||||
function dtestCommentTranslateTab() {
|
||||
|
||||
// Login as admin to be able to submit config page.
|
||||
$this->loginAsAdmin(array('administer entity translation'));
|
||||
// Enable comment translation.
|
||||
$edit = array(
|
||||
'entity_translation_entity_types[comment]' => TRUE
|
||||
);
|
||||
$this->drupalPost('admin/config/regional/entity_translation', $edit, t('Save configuration'));
|
||||
|
||||
// Change comment_body field to be translatable.
|
||||
$comment_body = field_info_field('comment_body');
|
||||
$comment_body['translatable'] = TRUE;
|
||||
field_update_field($comment_body);
|
||||
|
||||
// Create a user that is allowed to translate comments.
|
||||
$permissions = array('translate comment entities', 'create translation jobs', 'submit translation jobs', 'accept translation jobs', 'post comments', 'skip comment approval', 'edit own comments', 'access comments');
|
||||
$entity_translation_permissions = entity_translation_permission();
|
||||
// The new translation edit form of entity_translation requires a new
|
||||
// permission that does not yet exist in older versions. Add it
|
||||
// conditionally.
|
||||
if (isset($entity_translation_permissions['edit original values'])) {
|
||||
$permissions[] = 'edit original values';
|
||||
}
|
||||
$this->loginAsTranslator($permissions, TRUE);
|
||||
|
||||
// Create an english source term.
|
||||
$node = $this->createNode('article', 'en');
|
||||
|
||||
// Add a comment.
|
||||
$this->drupalGet('node/' . $node->nid);
|
||||
$edit = array(
|
||||
'subject' => $this->randomName(),
|
||||
'comment_body[en][0][value]' => $this->randomName(),
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Save'));
|
||||
$this->assertText(t('Your comment has been posted.'));
|
||||
|
||||
// Go to the translate tab.
|
||||
$this->clickLink('edit');
|
||||
$this->assertTrue(preg_match('|comment/(\d+)/edit$|', $this->getUrl(), $matches), 'Comment found');
|
||||
$comment = comment_load($matches[1]);
|
||||
$this->clickLink('Translate');
|
||||
|
||||
// Assert some basic strings on that page.
|
||||
$this->assertText(t('Translations of @title', array('@title' => $comment->subject)));
|
||||
$this->assertText(t('Pending Translations'));
|
||||
|
||||
// Request a translation for german.
|
||||
$edit = array(
|
||||
'languages[de]' => TRUE,
|
||||
'languages[es]' => TRUE,
|
||||
);
|
||||
$this->drupalPost(NULL, $edit, t('Request translation'));
|
||||
|
||||
// Verify that we are on the translate tab.
|
||||
$this->assertText(t('2 jobs need to be checked out.'));
|
||||
|
||||
// Submit all jobs.
|
||||
$this->assertText($comment->subject);
|
||||
$this->drupalPost(NULL, array(), t('Submit to translator and continue'));
|
||||
$this->assertText($comment->subject);
|
||||
$this->drupalPost(NULL, array(), t('Submit to translator'));
|
||||
|
||||
// Make sure that we're back on the translate tab.
|
||||
$this->assertEqual(url('comment/' . $comment->cid . '/translate', array('absolute' => TRUE)), $this->getUrl());
|
||||
$this->assertText(t('Test translation created.'));
|
||||
$this->assertNoText(t('The translation of @title to @language is finished and can now be reviewed.', array('@title' => $comment->subject, '@language' => t('Spanish'))));
|
||||
$this->assertText(t('The translation for @title has been accepted.', array('@title' => $comment->subject)));
|
||||
|
||||
// @todo Use links on translate tab.
|
||||
$this->drupalGet('de/comment/' . $comment->cid);
|
||||
$this->assertText('de_' . $comment->comment_body['en'][0]['value']);
|
||||
|
||||
// @todo Use links on translate tab.
|
||||
$this->drupalGet('es/node/' . $comment->cid);
|
||||
$this->assertText('es_' . $comment->comment_body['en'][0]['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the entity source specific cart functionality.
|
||||
*/
|
||||
function testCart() {
|
||||
$this->loginAsTranslator(array('translate node entities'));
|
||||
|
||||
$nodes = array();
|
||||
for ($i = 0; $i < 4; $i++) {
|
||||
$nodes[$i] = $this->createNode('page');
|
||||
}
|
||||
|
||||
// Test the source overview.
|
||||
$this->drupalGet('admin/tmgmt/sources/entity');
|
||||
$this->drupalPost('admin/tmgmt/sources/entity', array(
|
||||
'items[' . $nodes[1]->nid . ']' => TRUE,
|
||||
'items[' . $nodes[2]->nid . ']' => TRUE,
|
||||
), t('Add to cart'));
|
||||
|
||||
$this->drupalGet('admin/tmgmt/cart');
|
||||
$this->assertText($nodes[1]->title);
|
||||
$this->assertText($nodes[2]->title);
|
||||
|
||||
// Test the translate tab.
|
||||
$this->drupalGet('node/' . $nodes[3]->nid . '/translate');
|
||||
$this->assertRaw(t('There are @count items in the <a href="@url">translation cart</a>.',
|
||||
array('@count' => 2, '@url' => url('admin/tmgmt/cart'))));
|
||||
|
||||
$this->drupalPost(NULL, array(), t('Add to cart'));
|
||||
$this->assertRaw(t('@count content source was added into the <a href="@url">cart</a>.', array('@count' => 1, '@url' => url('admin/tmgmt/cart'))));
|
||||
$this->assertRaw(t('There are @count items in the <a href="@url">translation cart</a> including the current item.',
|
||||
array('@count' => 3, '@url' => url('admin/tmgmt/cart'))));
|
||||
}
|
||||
}
|
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Generic entity ui controller class for source plugin.
|
||||
*
|
||||
* @ingroup tmgmt_source
|
||||
*/
|
||||
class TMGMTEntitySourceUIController extends TMGMTEntityDefaultSourceUIController {
|
||||
|
||||
/**
|
||||
* Gets overview form header.
|
||||
*
|
||||
* @return array
|
||||
* Header array definition as expected by theme_tablesort().
|
||||
*/
|
||||
public function overviewFormHeader($type) {
|
||||
$languages = array();
|
||||
foreach (language_list() as $langcode => $language) {
|
||||
$languages['langcode-' . $langcode] = array(
|
||||
'data' => check_plain($language->name),
|
||||
);
|
||||
}
|
||||
|
||||
$entity_info = entity_get_info($type);
|
||||
|
||||
$header = array(
|
||||
'title' => array('data' => t('Title (in source language)')),
|
||||
);
|
||||
|
||||
// Show the bundle if there is more than one for this entity type.
|
||||
if (count(tmgmt_entity_get_translatable_bundles($type)) > 1) {
|
||||
$header['bundle'] = array('data' => t('@entity_name type', array('@entity_name' => $entity_info['label'])));
|
||||
}
|
||||
|
||||
$header += $languages;
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a table row for overview form.
|
||||
*
|
||||
* @param array $data
|
||||
* Data needed to build the list row.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function overviewRow($data) {
|
||||
$label = $data['entity_label'] ? $data['entity_label'] : t('@type: @id', array('@type' => $data['entity_type'], '@id' => $data['entity_id']));
|
||||
|
||||
$row = array(
|
||||
'id' => $data['entity_id'],
|
||||
'title' => l($label, $data['entity_uri']),
|
||||
);
|
||||
|
||||
if (isset($data['bundle'])) {
|
||||
$row['bundle'] = $data['bundle'];
|
||||
}
|
||||
|
||||
foreach (language_list() as $langcode => $language) {
|
||||
$row['langcode-' . $langcode] = array(
|
||||
'data' => theme('tmgmt_ui_translation_language_status_single', array(
|
||||
'translation_status' => $data['translation_statuses'][$langcode],
|
||||
'job_item' => isset($data['current_job_items'][$langcode]) ? $data['current_job_items'][$langcode] : NULL,
|
||||
)),
|
||||
'class' => array('langstatus-' . $langcode),
|
||||
);
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function overviewForm($form, &$form_state, $type) {
|
||||
|
||||
$form += $this->overviewSearchFormPart($form, $form_state, $type);
|
||||
|
||||
$form['items'] = array(
|
||||
'#type' => 'tableselect',
|
||||
'#header' => $this->overviewFormHeader($type),
|
||||
'#empty' => t('No entities matching given criteria have been found.'),
|
||||
'#attributes' => array('id' => 'tmgmt-entities-list'),
|
||||
);
|
||||
|
||||
// Load search property params which will be passed into
|
||||
$search_property_params = array();
|
||||
$exclude_params = array('q', 'page');
|
||||
foreach ($_GET as $key => $value) {
|
||||
// Skip exclude params, and those that have empty values, as these would
|
||||
// make it into query condition instead of being ignored.
|
||||
if (in_array($key, $exclude_params) || $value === '') {
|
||||
continue;
|
||||
}
|
||||
$search_property_params[$key] = $value;
|
||||
}
|
||||
|
||||
foreach ($this->getEntitiesTranslationData($type, $search_property_params) as $data) {
|
||||
$form['items']['#options'][$data['entity_id']] = $this->overviewRow($data);
|
||||
}
|
||||
|
||||
$form['pager'] = array('#markup' => theme('pager', array('tags' => NULL)));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function overviewFormValidate($form, &$form_state, $type) {
|
||||
if (!empty($form_state['values']['search']['target_language']) && $form_state['values']['search']['language'] == $form_state['values']['search']['target_language']) {
|
||||
form_set_error('search[target_language]', t('The source and target languages must not be the same.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function overviewFormSubmit($form, &$form_state, $type) {
|
||||
|
||||
// Handle search redirect.
|
||||
$this->overviewSearchFormRedirect($form, $form_state, $type);
|
||||
|
||||
$jobs = array();
|
||||
$entities = entity_load($type, $form_state['values']['items']);
|
||||
$source_lang_registry = array();
|
||||
|
||||
// Loop through entities and create individual jobs for each source language.
|
||||
foreach ($entities as $entity) {
|
||||
/**
|
||||
* @var EntityTranslationDefaultHandler $handler
|
||||
*/
|
||||
$handler = entity_translation_get_handler($type, $entity);
|
||||
$source_lang = entity_language($type, $entity);
|
||||
list($entity_id, ,) = entity_extract_ids($type, $entity);
|
||||
|
||||
try {
|
||||
|
||||
// For given source lang no job exists yet.
|
||||
if (!isset($source_lang_registry[$source_lang])) {
|
||||
// Create new job.
|
||||
$job = tmgmt_job_create($source_lang, NULL, $GLOBALS['user']->uid);
|
||||
// Add initial job item.
|
||||
$job->addItem('entity', $type, $entity_id);
|
||||
// Add job identifier into registry
|
||||
$source_lang_registry[$source_lang] = $job->tjid;
|
||||
// Add newly created job into jobs queue.
|
||||
$jobs[$job->tjid] = $job;
|
||||
}
|
||||
// We have a job for given source lang, so just add new job item for the
|
||||
// existing job.
|
||||
else {
|
||||
$jobs[$source_lang_registry[$source_lang]]->addItem('entity', $type, $entity_id);
|
||||
}
|
||||
}
|
||||
catch (TMGMTException $e) {
|
||||
watchdog_exception('tmgmt', $e);
|
||||
$entity_label = entity_label($type, $entity);
|
||||
drupal_set_message(t('Unable to add job item for entity %name: %error.', array('%name' => $entity_label, '%error' => $e->getMessage())), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// If necessary, do a redirect.
|
||||
$redirects = tmgmt_ui_job_checkout_multiple($jobs);
|
||||
if ($redirects) {
|
||||
tmgmt_ui_redirect_queue_set($redirects, current_path());
|
||||
$form_state['redirect'] = tmgmt_ui_redirect_queue_dequeue();
|
||||
|
||||
drupal_set_message(format_plural(count($redirects), t('One job needs to be checked out.'), t('@count jobs need to be checked out.')));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user