diff --git a/translators/tmgmt_local/includes/tmgmt_local.entity.inc b/translators/tmgmt_local/includes/tmgmt_local.entity.inc
index 639b98a..a6701f8 100644
--- a/translators/tmgmt_local/includes/tmgmt_local.entity.inc
+++ b/translators/tmgmt_local/includes/tmgmt_local.entity.inc
@@ -93,7 +93,24 @@ class TMGMTLocalTask extends Entity {
* Overrides Entity::defaultLabel().
*/
protected function defaultLabel() {
- return t('Task for @job assigned to @translator', array('@job' => $this->getJob()->label(), '@translator' => entity_label('user', user_load($this->tuid))));
+ if (empty($this->tuid)) {
+ if (empty($this->title)) {
+ return t('Task for @job', array('@job' => $this->getJob()->label()));
+ }
+ else {
+ return $this->title;
+ }
+ }
+ else {
+ if (empty($this->title)) {
+ return t('Task for @job assigned to @translator', array('@job' => $this->getJob()->label(), '@translator' => entity_label('user', user_load($this->tuid))));
+ }
+ else {
+ return t('@title assigned to @translator', array('@title' => $this->title, '@translator' => entity_label('user', user_load($this->tuid))));
+ }
+ }
+
+
}
/**
@@ -461,4 +478,62 @@ class TMGMTLocalTaskItem extends Entity {
public function completed() {
$this->status = TMGMT_LOCAL_TASK_ITEM_STATUS_COMPLETED;
}
-}
\ No newline at end of file
+
+ /**
+ * Updates the values for a specific substructure in the data array.
+ *
+ * The values are either set or updated but never deleted.
+ *
+ * @param $key
+ * Key pointing to the item the values should be applied.
+ * The key can be either be an array containing the keys of a nested array
+ * hierarchy path or a string with '][' or '|' as delimiter.
+ * @param $values
+ * Nested array of values to set.
+ */
+ public function updateData($key, $values = array()) {
+ foreach ($values as $index => $value) {
+ // In order to preserve existing values, we can not aplly the values array
+ // at once. We need to apply each containing value on its own.
+ // If $value is an array we need to advance the hierarchy level.
+ if (is_array($value)) {
+ $this->updateData(array_merge(tmgmt_ensure_keys_array($key), array($index)), $value);
+ }
+ // Apply the value.
+ else {
+ drupal_array_set_nested_value($this->data, array_merge(tmgmt_ensure_keys_array($key), array($index)), $value);
+ }
+ }
+ }
+
+ /**
+ * Array of translations.
+ *
+ * The structure is similar to the form API in the way that it is a possibly
+ * nested array with the following properties whose presence indicate that the
+ * current element is a text that might need to be translated.
+ *
+ * - #text: The translated text of the corresponding entry in the job item.
+ * - #status: The status of the translation.
+ *
+ * The key can be an alphanumeric string.
+ *
+ * @param array $key
+ * If present, only the subarray identified by key is returned.
+ * @param string $index
+ * Optional index of an attribute below $key.
+ *
+ * @return array
+ * A structured data array.
+ */
+ public function getData(array $key = array(), $index = null) {
+ if (empty($key)) {
+ return $this->data;
+ }
+ if ($index) {
+ $key = array_merge($key, array($index));
+ }
+ return drupal_array_get_nested_value($this->data, $key);
+ }
+
+}
diff --git a/translators/tmgmt_local/includes/tmgmt_local.pages.inc b/translators/tmgmt_local/includes/tmgmt_local.pages.inc
index 78df224..310fff4 100644
--- a/translators/tmgmt_local/includes/tmgmt_local.pages.inc
+++ b/translators/tmgmt_local/includes/tmgmt_local.pages.inc
@@ -34,6 +34,7 @@ function tmgmt_local_task_form($form, &$form_state, TMGMTLocalTask $task, $op =
'#type' => 'textfield',
'#title' => t('Title'),
'#default_value' => $task->title,
+ '#access' => user_access('administer tmgmt') || user_access('administer translation tasks'),
);
$form['status'] = array(
@@ -41,6 +42,7 @@ function tmgmt_local_task_form($form, &$form_state, TMGMTLocalTask $task, $op =
'#title' => t('Status'),
'#options' => tmgmt_local_task_statuses(),
'#default_value' => $wrapper->status->value(),
+ '#access' => user_access('administer tmgmt') || user_access('administer translation tasks'),
);
$translators = tmgmt_local_translators($task->getJob()->source_language, $task->getJob()->target_language);
@@ -50,6 +52,7 @@ function tmgmt_local_task_form($form, &$form_state, TMGMTLocalTask $task, $op =
'#options' => $translators,
'#empty_option' => t('- Select user -'),
'#default_value' => $task->tuid,
+ '#access' => user_access('administer tmgmt') || user_access('administer translation tasks'),
);
if ($view = views_get_view('tmgmt_local_task_items')) {
@@ -57,7 +60,7 @@ function tmgmt_local_task_form($form, &$form_state, TMGMTLocalTask $task, $op =
'#type' => 'item',
'#title' => $view->get_title(),
'#prefix' => '
',
- '#markup' => $view->preview('block'),
+ '#markup' => $view->preview('block', $task->tltid),
'#attributes' => array('class' => array('tmgmt-local-task-items')),
'#suffix' => '
',
'#weight' => 10,
@@ -66,6 +69,7 @@ function tmgmt_local_task_form($form, &$form_state, TMGMTLocalTask $task, $op =
// Add the buttons and action links.
$form['actions']['#type'] = 'actions';
+ $form['actions']['#access'] = user_access('administer tmgmt') || user_access('administer translation tasks');
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => t('Save task'),
@@ -89,6 +93,11 @@ function tmgmt_local_task_form($form, &$form_state, TMGMTLocalTask $task, $op =
*/
function tmgmt_local_task_form_submit($form, &$form_state) {
$task = entity_ui_form_submit_build_entity($form, $form_state);
+ // If the task isn't assigned to anyone but doesn't have the unassigned status
+ // update it.
+ if ($task->tuid == 0 && !$task->isUnassigned()) {
+ $task->unassign();
+ }
$task->save();
}
@@ -149,7 +158,7 @@ function tmgmt_local_translation_form($form, &$form_state, TMGMTLocalTaskItem $t
// Reverse the order to get the correct order.
foreach (array_reverse(element_children($data)) as $key) {
$flattened = tmgmt_flatten_data($data[$key], $key);
- $form['translation'][$key] = tmgmt_local_translation_form_element($flattened, $job_item, $zebra);
+ $form['translation'][$key] = tmgmt_local_translation_form_element($flattened, $task_item, $zebra);
}
// Add the form actions as well.
@@ -197,19 +206,19 @@ function tmgmt_local_translation_form_save_as_completed_submit($form, &$form_sta
$task = $form_state['task'];
/**
- * @var TMGMTLocalTaskItem $item.
+ * @var TMGMTLocalTaskItem $task_item.
*/
$task_item = $form_state['task_item'];
$task_item->translated();
$task_item->save();
/**
- * @var TMGMTJobItem $item.
+ * @var TMGMTJobItem $job_item.
*/
$job_item = $form_state['job_item'];
- // Set the job item to 'needs review' and task to finished states.
- $job_item->needsReview();
+ // Add the translations to the job item.
+ $job_item->addTranslatedData($task_item->getData());
// Mark the task as completed if all assigned job items are at needs done.
$all_done = TRUE;
@@ -235,27 +244,25 @@ function tmgmt_local_translation_form_save_as_completed_submit($form, &$form_sta
*/
function tmgmt_local_translation_form_save_submit($form, &$form_state) {
/**
- * @var TMGMTJobItem $item.
+ * @var TMGMTTaskItem $task_item.
*/
- $job_item = $form_state['job_item'];
+ $task_item = $form_state['task_item'];
// Write the translated data into the task item.
$values = $form_state['values'];
foreach ($values as $key => $value) {
if (isset($value['translation'])) {
- $update['#translation'] = array(
- '#text' => $value['translation'],
- );
- $job_item->updateData($key, $update);
+ $update['#text'] = $value['translation'];
+ $task_item->updateData($key, $update);
}
}
- $job_item->save();
+ $task_item->save();
}
/**
* Builds a translation form element.
*/
-function tmgmt_local_translation_form_element($data, TMGMTJobItem $item, &$zebra) {
+function tmgmt_local_translation_form_element($data, TMGMTLocalTaskItem $item, &$zebra) {
static $flip = array(
'even' => 'odd',
'odd' => 'even',
@@ -263,7 +270,7 @@ function tmgmt_local_translation_form_element($data, TMGMTJobItem $item, &$zebra
$form = array();
- $job = $item->getJob();
+ $job = $item->getJobItem()->getJob();
$language_list = language_list();
foreach (element_children($data) as $key) {
@@ -292,14 +299,15 @@ function tmgmt_local_translation_form_element($data, TMGMTJobItem $item, &$zebra
$form[$target_key]['translation'] = array(
'#type' => 'textarea',
'#title' => $target_language->name,
- '#default_value' => isset($data[$key]['#translation']['#text']) ? $data[$key]['#translation']['#text'] : '',
+ '#default_value' => $item->getData(tmgmt_ensure_keys_array($key), '#text'),
//'#required' => TRUE,
);
$form[$target_key]['actions'] = array(
'#type' => 'container',
);
- $completed = !empty($data[$key]['#status']) && $data[$key]['#status'] == TMGMT_DATA_ITEM_STATE_TRANSLATED;
+ $status = $item->getData(tmgmt_ensure_keys_array($key), '#status');
+ $completed = $status == TMGMT_DATA_ITEM_STATE_TRANSLATED;
if ($completed) {
$form[$target_key]['actions']['reject-' . $target_key] = array(
'#type' => 'submit',
@@ -345,9 +353,9 @@ function tmgmt_local_translation_form_update_state_submit($form, &$form_state) {
$values = $form_state['values'];
/**
- * @var TMGMTJobItem $item.
+ * @var TMGMTLocalTaskItem $item.
*/
- $item = $form_state['item'];
+ $item = $form_state['task_item'];
$action = $form_state['triggering_element']['#tmgmt_local_action'];
$key = $form_state['triggering_element']['#tmgmt_local_key'];
@@ -355,10 +363,7 @@ function tmgmt_local_translation_form_update_state_submit($form, &$form_state) {
// Write the translated data into the job item.
if (isset($values[$key]) && is_array($values[$key]) && isset($values[$key]['translation'])) {
$update['#status'] = $action == 'finish' ? TMGMT_DATA_ITEM_STATE_TRANSLATED : TMGMT_DATA_ITEM_STATE_PENDING;
- $update['#translation'] = array(
- '#text' => $values[$key]['translation'],
- );
-
+ $update['#text'] = $values[$key]['translation'];
$item->updateData($key, $update);
$item->save();
@@ -375,7 +380,7 @@ function tmgmt_local_translation_form_update_state_ajax($form, &$form_state) {
$commands = array();
$render_data = drupal_array_get_nested_value($form, $key);
$commands[] = ajax_command_replace(NULL, drupal_render($render_data));
- tmgmt_ui_write_request_messages($form_state['item']->getJob());
+ tmgmt_ui_write_request_messages($form_state['job_item']->getJob());
$commands[] = ajax_command_html('#tmgmt-status-messages-' . strtolower($render_data['#parent_label'][0]), theme('status_messages'));
return array('#type' => 'ajax', '#commands' => $commands);
}
diff --git a/translators/tmgmt_local/includes/tmgmt_local_ui.controller.inc b/translators/tmgmt_local/includes/tmgmt_local_ui.controller.inc
index bdb9079..d22c790 100644
--- a/translators/tmgmt_local/includes/tmgmt_local_ui.controller.inc
+++ b/translators/tmgmt_local/includes/tmgmt_local_ui.controller.inc
@@ -30,6 +30,14 @@ class TMGMTLocalTaskUIController extends EntityDefaultUIController {
'access arguments' => array('delete', $this->entityType, $id_count),
'type' => MENU_CALLBACK,
);
+ $items[$this->path . '/' . $wildcard . '/unassign'] = array(
+ 'page callback' => 'drupal_get_form',
+ 'page arguments' => array($this->entityType . '_operation_form', $this->entityType, $id_count, $id_count + 1),
+ 'load arguments' => array($this->entityType),
+ 'access callback' => 'entity_access',
+ 'access arguments' => array('unassign', $this->entityType, $id_count),
+ 'type' => MENU_CALLBACK,
+ );
return $items;
}
@@ -41,6 +49,9 @@ class TMGMTLocalTaskUIController extends EntityDefaultUIController {
case 'delete':
$confirm_question = t('Are you sure you want to delete the translation task %label?', array('%label' => $entity->label()));
return confirm_form($form, $confirm_question, $this->path);
+ case 'unassign':
+ $confirm_question = t('Are you sure you want to unassign from the translation task %label?', array('%label' => $entity->label()));
+ return confirm_form($form, $confirm_question, $this->path);
}
drupal_not_found();
exit;
@@ -54,6 +65,10 @@ class TMGMTLocalTaskUIController extends EntityDefaultUIController {
case 'delete':
$entity->delete();
return t('Deleted the translation local task %label.', array('%label' => $entity->label()));
+ case 'unassign':
+ $entity->unassign();
+ $entity->save();
+ return t('Unassigned from translation local task %label.', array('%label' => $entity->label()));
}
return FALSE;
}
diff --git a/translators/tmgmt_local/tmgmt_local.install b/translators/tmgmt_local/tmgmt_local.install
index 247a28c..36ade11 100644
--- a/translators/tmgmt_local/tmgmt_local.install
+++ b/translators/tmgmt_local/tmgmt_local.install
@@ -191,7 +191,7 @@ function tmgmt_local_update_7000() {
* Create local task items.
*/
function tmgmt_local_update_7001() {
- $result = db_query('SELECT lt.tltid, ji.tjiid, ji.state from {tmgmt_local_task} lt INNER JOIN {tmgmt_job} j ON j.tjid = lt.tjid INNER JOIN {tmgmt_job_item} ji ON ji.tjid = j.tjid');
+ $result = db_query('SELECT lt.tltid, ji.tjiid, ji.state, ji.data from {tmgmt_local_task} lt INNER JOIN {tmgmt_job} j ON j.tjid = lt.tjid INNER JOIN {tmgmt_job_item} ji ON ji.tjid = j.tjid');
$insert = db_insert('tmgmt_local_task_item')
->fields(array('tltid', 'tjiid', 'status', 'data'));
foreach ($result as $row) {
@@ -210,12 +210,46 @@ function tmgmt_local_update_7001() {
$status = 0;
break;
}
+ $translation = (array)_tmgmt_local_translated_data_7001(unserialize($row->data));
$insert->values(array(
'tltid' => $row->tltid,
'tjiid' => $row->tjiid,
'status' => $status,
- 'data' => serialize(array()),
+ 'data' => serialize($translation),
));
}
$insert->execute();
}
+
+/**
+ * Data parsing helper function for tmgmt_local_update_7001().
+ *
+ * Copies #translation texts from the source data array to the translation
+ * data array.
+ *
+ * @param array $source
+ * The original source data array of the job item.
+ *
+ * @return array
+ * The filled translation data array.
+ */
+function _tmgmt_local_translated_data_7001($source) {
+ if (!empty($source['#translation']['#text'])) {
+ $translation['#text'] = $source['#translation']['#text'];
+ if ((!empty($source['#status']))) {
+ $translation['#status'] = $source['#status'];
+ }
+ return $translation;
+ }
+ else {
+ $translation = array();
+ foreach (element_children($source) as $key) {
+ if ($return = _tmgmt_local_translated_data_7001($source[$key])) {
+ $translation[$key] = $return;
+ }
+ }
+ if (!empty($translation)) {
+ return $translation;
+ }
+ }
+}
diff --git a/translators/tmgmt_local/tmgmt_local.module b/translators/tmgmt_local/tmgmt_local.module
index d3e349e..9821059 100644
--- a/translators/tmgmt_local/tmgmt_local.module
+++ b/translators/tmgmt_local/tmgmt_local.module
@@ -466,12 +466,19 @@ function tmgmt_local_task_access($op, $task = NULL, $account = NULL) {
return TRUE;
}
+ if (!$account) {
+ global $user;
+ $account = $user;
+ }
+
// @todo - probably need refinement when we introduce more module permissions.
switch ($op) {
case 'view':
case 'update':
return user_access('provide translation services', $account);
break;
+ case 'unassign':
+ return !empty($task->tuid) && $task->tuid == $account->uid && user_access('provide translation services', $account);
}
}
diff --git a/translators/tmgmt_local/tmgmt_local.test b/translators/tmgmt_local/tmgmt_local.test
index 78d0594..3c3517d 100644
--- a/translators/tmgmt_local/tmgmt_local.test
+++ b/translators/tmgmt_local/tmgmt_local.test
@@ -280,6 +280,16 @@ class TMGMTLocalTestCase extends TMGMTBaseTestCase {
$this->assertText(t('Completed'));
$this->assertText(t('Untranslated'));
+ // Check the job data, which should not yet contain the translation.
+ entity_get_controller('tmgmt_job')->resetCache(array($job->tjid));
+ entity_get_controller('tmgmt_job_item')->resetCache();
+ $job = tmgmt_job_load($job->tjid);
+ list($item1, $item2) = array_values($job->getItems());
+ // The text in the first item should be available for review, the
+ // translation of the second item not.
+ $this->assertEqual($item1->getData(array('dummy', 'deep_nesting', '#translation', '#text')), $translation1);
+ $this->assertEqual($item2->getData(array('dummy', 'deep_nesting', '#translation', '#text')), '');
+
// Check the overview page, the task should still show in progress.
$this->drupalGet('translate');
$this->assertText(t('Pending'));
diff --git a/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_field_item_operations.inc b/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_field_item_operations.inc
index 9bbeba4..5fbd0d6 100644
--- a/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_field_item_operations.inc
+++ b/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_field_item_operations.inc
@@ -8,6 +8,7 @@
class tmgmt_local_task_handler_field_item_operations extends views_handler_field_entity {
function render($values) {
+ global $user;
/**
* @var TMGMTLocalTaskItem $item
*/
@@ -15,15 +16,16 @@ class tmgmt_local_task_handler_field_item_operations extends views_handler_field
$element = array();
$element['#theme'] = 'links';
- $element['#attributes'] = array('class' => array('inline'));
- if ($item->isUntranslated() && entity_access('view', 'tmgmt_local_task_item', $item)) {
+ $element['#attributes'] = array('class' => array('links', 'inline'));
+ // Only allow to translate if the job is assigned to this user.
+ if (entity_access('view', 'tmgmt_local_task_item', $item) && $item->getTask()->tuid == $user->uid) {
$element['#links']['translate'] = array(
'href' => 'translate/' . $item->tltid . '/item/' . $item->tltiid,
'query' => array('destination' => current_path()),
'attributes' => array(
- 'title' => t('Translate'),
+ 'title' => $item->isUntranslated() ? t('Translate') : t('View'),
),
- 'title' => t('translate'),
+ 'title' => $item->isUntranslated() ? t('translate') : t('view'),
);
}
return drupal_render($element);
diff --git a/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_field_operations.inc b/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_field_operations.inc
index 48bc58c..1fae5a9 100644
--- a/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_field_operations.inc
+++ b/translators/tmgmt_local/views/handlers/tmgmt_local_task_handler_field_operations.inc
@@ -17,7 +17,7 @@ class tmgmt_local_task_handler_field_operations extends views_handler_field_enti
$element = array();
$element['#theme'] = 'links';
- $element['#attributes'] = array('class' => array('inline'));
+ $element['#attributes'] = array('class' => array('links', 'inline'));
$uri = $task->uri();
if (entity_access('view', 'tmgmt_local_task', $task)) {
$element['#links']['view'] = array(
@@ -26,13 +26,6 @@ class tmgmt_local_task_handler_field_operations extends views_handler_field_enti
'title' => t('view'),
);
}
- if (entity_access('delete', 'tmgmt_local_task', $task)) {
- $element['#links']['delete'] = array(
- 'href' => $uri['path'] . '/delete',
- 'query' => array('destination' => current_path()),
- 'title' => t('delete'),
- );
- }
if (user_access('administer translation tasks') && tmgmt_local_translation_access($task) && empty($task->tuid)) {
$element['#links']['assign'] = array(
'href' => 'manage-translate/assign-tasks/' . $task->tltid,
@@ -63,7 +56,7 @@ class tmgmt_local_task_handler_field_operations extends views_handler_field_enti
'title' => t('assign'),
);
}
- if (tmgmt_local_translation_access($task) && !empty($task->tuid)) {
+ if (!empty($task->tuid) && entity_access('unassign', 'tmgmt_local_task', $task)) {
$element['#links']['unassign'] = array(
'href' => 'translate/' . $task->tltid . '/unassign',
'query' => array('destination' => current_path()),
@@ -73,6 +66,13 @@ class tmgmt_local_task_handler_field_operations extends views_handler_field_enti
'title' => t('unassign'),
);
}
+ if (entity_access('delete', 'tmgmt_local_task', $task)) {
+ $element['#links']['delete'] = array(
+ 'href' => $uri['path'] . '/delete',
+ 'query' => array('destination' => current_path()),
+ 'title' => t('delete'),
+ );
+ }
return drupal_render($element);
}
diff --git a/translators/tmgmt_local/views/tmgmt_local_task_items.view.inc b/translators/tmgmt_local/views/tmgmt_local_task_items.view.inc
index fa238b8..18feb5a 100644
--- a/translators/tmgmt_local/views/tmgmt_local_task_items.view.inc
+++ b/translators/tmgmt_local/views/tmgmt_local_task_items.view.inc
@@ -42,6 +42,15 @@ $handler->display->display_options['fields']['status']['field'] = 'status';
$handler->display->display_options['fields']['operations']['id'] = 'operations';
$handler->display->display_options['fields']['operations']['table'] = 'tmgmt_local_task_item';
$handler->display->display_options['fields']['operations']['field'] = 'operations';
+/* Contextual filter: Translation Task Item: Tltid */
+$handler->display->display_options['arguments']['tltid']['id'] = 'tltid';
+$handler->display->display_options['arguments']['tltid']['table'] = 'tmgmt_local_task_item';
+$handler->display->display_options['arguments']['tltid']['field'] = 'tltid';
+$handler->display->display_options['arguments']['tltid']['default_action'] = 'empty';
+$handler->display->display_options['arguments']['tltid']['default_argument_type'] = 'fixed';
+$handler->display->display_options['arguments']['tltid']['summary']['number_of_records'] = '0';
+$handler->display->display_options['arguments']['tltid']['summary']['format'] = 'default_summary';
+$handler->display->display_options['arguments']['tltid']['summary_options']['items_per_page'] = '25';
/* Display: Block */
$handler = $view->new_display('block', 'Block', 'block');
@@ -64,11 +73,10 @@ $translatables['tmgmt_local_task_items'] = array(
t('last ยป'),
t('Translation Task'),
t('Translation Management Job Item'),
- t('Translation task item ID'),
- t('.'),
- t(','),
+ t('Label'),
t('Status'),
t('Operations'),
- t('Label'),
+ t('All'),
t('Block'),
);
+