diff --git a/translators/file/tmgmt_file.format.xliff.inc b/translators/file/tmgmt_file.format.xliff.inc index a960bce..b53b9c4 100644 --- a/translators/file/tmgmt_file.format.xliff.inc +++ b/translators/file/tmgmt_file.format.xliff.inc @@ -44,17 +44,21 @@ class TMGMTFileformatXLIFF extends XMLWriter implements TMGMTFileFormatInterface */ protected function addTransUnit($key, $element) { + $key_array = tmgmt_ensure_keys_array($key); + $this->startElement('trans-unit'); $this->writeAttribute('id', $key); $this->writeAttribute('resname', $key); $this->startElement('source'); $this->writeAttribute('xml:lang', $this->job->getTranslator()->mapToRemoteLanguage($this->job->source_language)); - $this->writeRaw($element['#text']); + $this->writeRaw($this->processForExport($element['#text'], $key_array[0])); $this->endElement(); $this->startElement('target'); $this->writeAttribute('xml:lang', $this->job->getTranslator()->mapToRemoteLanguage($this->job->target_language)); - $this->writeRaw(!empty($element['#translation']['#text']) ? $element['#translation']['#text'] : $element['#text']); + // @todo - temporary solution, it will be changed in the [#2006786] + $target = (!empty($element['#translation']['#text']) ? $element['#translation']['#text'] : $element['#text']); + $this->writeRaw($this->processForExport($target, $key_array[0])); $this->endElement(); if (isset($element['#label'])) { $this->writeElement('note', $element['#label']); @@ -133,14 +137,14 @@ class TMGMTFileformatXLIFF extends XMLWriter implements TMGMTFileFormatInterface // Register the xliff namespace, required for xpath. $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2'); + $reader = new XMLReader(); $data = array(); foreach ($xml->xpath('//xliff:trans-unit') as $unit) { // Load the result with XMLReader so that we are able to get the inner // xml. - $reader = new XMLReader(); $reader->XML($unit->target->asXML()); $reader->read(); - $data[(string) $unit['id']]['#text'] = $reader->readInnerXml(); + $data[(string) $unit['id']]['#text'] = $this->processForImport($reader->readInnerXml()); } return tmgmt_unflatten_data($data); } @@ -186,8 +190,301 @@ class TMGMTFileformatXLIFF extends XMLWriter implements TMGMTFileFormatInterface return FALSE; } + $reader = new XMLReader(); + $elements_counts = $job->getSetting('elements_counts'); + foreach ($xml->xpath('//xliff:trans-unit') as $unit) { + $count = 0; + $reader->XML($unit->target->asXML()); + while ($reader->read()) { + if ($reader->nodeType == XML_ELEMENT_NODE && $reader->name != 'target') { + $count++; + } + } + + $keys_array = tmgmt_ensure_keys_array((string) $unit['id']); + $tjiid = array_shift($keys_array); + if (!isset($elements_counts[$tjiid]) || $elements_counts[$tjiid] != $count) { + // @todo - Trados studio adds additional elements into the target + // and therefore such validation will fail. Not sure how to deal with + // it, for now leaving commented out. + //return FALSE; + } + } + // Validation successful. return $job; } + /** + * Processes trans-unit/target to rebuild back the HTML. + * + * @param string $translation + * Job data array. + * + * @return string + */ + protected function processForImport($translation) { + $reader = new XMLReader(); + $reader->XML('' . $translation . ''); + $text = ''; + $this->elementsCount = 0; + + while ($reader->read()) { + // Increment the counter if we have a new element. + if ($reader->nodeType == XML_ELEMENT_NODE && $reader->name != 'translation') { + $this->elementsCount++; + } + + // If the current element is text append it to the result text. + if ($reader->name == '#text' || $reader->name == '#cdata-section') { + $text .= $reader->value; + } + elseif ($reader->name == 'x') { + if ($reader->getAttribute('ctype') == 'lb') { + $text .= '
'; + } + } + elseif ($reader->name == 'ph') { + if ($reader->getAttribute('ctype') == 'image') { + $text .= 'moveToNextAttribute()) { + // @todo - we have to use x-html: prefixes for attributes. + if ($reader->name != 'ctype' && $reader->name != 'id') { + $text .= " {$reader->name}=\"{$reader->value}\""; + } + } + $text .= ' />'; + } + } + } + return $text; + } + + /** + * Helper function to process the source text. + * + * @param string $source + * Job data array. + * @param int $tjiid + * Job item ID. + * + * @return string + */ + protected function processForExport($source, $tjiid) { + // The reason why we use DOMDocument object here and not just XMLReader + // is the DOMDocument's ability to deal with broken HTML. + $dom = new DOMDocument(); + // We need to append the head with encoding so that special characters + // are read correctly. + $dom->loadHTML("" . $source . ''); + + $iterator = new RecursiveIteratorIterator( + new RecursiveDOMIterator($dom), + RecursiveIteratorIterator::SELF_FIRST); + + $writer = new XMLWriter(); + $writer->openMemory(); + $writer->startDocument('1.0', 'UTF-8'); + $writer->startElement('wrapper'); + + $tray = array(); + $id = 0; + $non_pair_tags = array('br', 'img'); + $elements_count = 0; + + /** @var DOMElement $node */ + foreach ($iterator as $node) { + + if (in_array($node->nodeName, array('html', 'body', 'head', 'meta'))) { + continue; + } + + if ($node->nodeType === XML_ELEMENT_NODE) { + // We have a new tag, increment the id. + $id++; + // Currently the incremental id and the elementCount has the same + // value. But to make things clear we will keep separated these two + // things. + $elements_count++; + + $is_pair_tag = !in_array($node->nodeName, $non_pair_tags); + + if ($is_pair_tag) { + $this->writeBPT($writer, $node, $id); + } + elseif ($node->nodeName == 'img') { + $this->writeIMG($writer, $node, $id); + } + elseif ($node->nodeName == 'br') { + $this->writeBR($writer, $node, $id); + } + + // Add to tray new element info. + $tray[$id] = array( + 'name' => $node->nodeName, + 'id' => $id, + 'value' => $node->nodeValue, + 'built_text' => '', + 'is_pair_tag' => $is_pair_tag, + ); + + } + // The current node is a text. + elseif ($node->nodeName == '#text') { + // Add the node value to the text output. + $writer->writeCdata($this->toEntities($node->nodeValue)); + foreach ($tray as &$info) { + $info['built_text'] .= $node->nodeValue; + } + } + + // Reverse so that pair tags are closed in the expected order. + $reversed_tray = array_reverse($tray); + foreach ($reversed_tray as $_info) { + // If the build_text equals to the node value and it is not a pair tag + // add the end pair tag markup. + if ($_info['value'] == $_info['built_text'] && $_info['is_pair_tag']) { + // Count also for the elements. + $elements_count++; + $this->writeEPT($writer, $_info['name'], $_info['id']); + // When the end pair tag has been written unset the element info + // from the tray. + unset($tray[$_info['id']]); + } + } + } + + // Set the elements count for the current item into job settings. + $this->job->settings['elements_counts'][$tjiid] = $elements_count; + $this->job->save(); + + $writer->endElement(); + // Load the output with XMLReader so that we can easily get the inner xml. + $reader = new XMLReader(); + $reader->XML($writer->outputMemory()); + $reader->read(); + return $reader->readInnerXml(); + } + + /** + * Writes br tag. + * + * @param XMLWriter $writer + * Writer that writes the output. + * @param DOMElement $node + * Current node. + * @param $id + * Current node id. + */ + protected function writeBR(XMLWriter $writer, DOMElement $node, $id) { + $writer->startElement('x'); + $writer->writeAttribute('id', $id); + $writer->writeAttribute('ctype', 'lb'); + $writer->endElement(); + } + + /** + * Writes beginning pair tag. + * + * @param XMLWriter $writer + * Writer that writes the output. + * @param DOMElement $node + * Current node. + * @param $id + * Current node id. + */ + protected function writeBPT(XMLWriter $writer, DOMElement $node, $id) { + $beginning_tag = '<' . $node->nodeName; + if ($node->hasAttributes()) { + $attributes = array(); + /** @var DOMAttr $attribute */ + foreach ($node->attributes as $attribute) { + $attributes[] = $attribute->name . '="' . $attribute->value . '"'; + } + + $beginning_tag .= ' '. implode(' ', $attributes); + } + $beginning_tag .= '>'; + $writer->startElement('bpt'); + $writer->writeAttribute('id', $id); + $writer->text($beginning_tag); + $writer->endElement(); + } + + /** + * Writes ending pair tag. + * + * @param XMLWriter $writer + * Writer that writes the output. + * @param string $name + * Ending tag name. + * @param $id + * Current node id. + */ + protected function writeEPT(XMLWriter $writer, $name, $id) { + $writer->startElement('ept'); + $writer->writeAttribute('id', $id); + $writer->text(''); + $writer->endElement(); + } + + /** + * Writes img tag. + * + * Note that alt and title attributes are not written as sub elements as + * Trados studio is not able to deal with two sub elements at one level. + * + * @param XMLWriter $writer + * Writer that writes the output. + * @param DOMElement $node + * Current node. + * @param $id + * Current node id. + */ + protected function writeIMG(XMLWriter $writer, DOMElement $node, $id) { + $writer->startElement('ph'); + $writer->writeAttribute('id', $id); + $writer->writeAttribute('ctype', 'image'); + foreach ($node->attributes as $attribute) { + // @todo - uncomment when issue with Trados/sub elements fixed. +// if (in_array($attribute->name, array('title', 'alt'))) { +// continue; +// } + $writer->writeAttribute($attribute->name, $attribute->value); + } +// if ($alt_attribute = $node->getAttribute('alt')) { +// $writer->startElement('sub'); +// $writer->writeAttribute('id', $id . '-img-alt'); +// $writer->writeAttribute('ctype', 'x-img-alt'); +// $writer->text($alt_attribute); +// $writer->endElement(); +// $this->elementsCount++; +// } +// if ($title_attribute = $node->getAttribute('title')) { +// $writer->startElement('sub'); +// $writer->writeAttribute('id', $id . '-img-title'); +// $writer->writeAttribute('ctype', 'x-img-title'); +// $writer->text($title_attribute); +// $writer->endElement(); +// $this->elementsCount++; +// } + $writer->endElement(); + } + + /** + * Convert critical characters to html entities. + * + * DOMDocument will convert html entities to its actual characters. This can + * lead into situation when not allowed characters will appear in the content. + * + * @param string $string + * String to escape. + * + * @return string + * Escaped string. + */ + protected function toEntities($string) { + return str_replace(array('&', '>', '<'), array('&', '>', '<'), $string); + } + } diff --git a/translators/file/tmgmt_file.info b/translators/file/tmgmt_file.info index cd9d511..786d890 100644 --- a/translators/file/tmgmt_file.info +++ b/translators/file/tmgmt_file.info @@ -9,7 +9,5 @@ files[] = tmgmt_file.ui.inc files[] = tmgmt_file.format.interface.inc files[] = tmgmt_file.format.xliff.inc files[] = tmgmt_file.format.html.inc -files[] = tmgmt_file.text_processor.xliff_mask_html.inc -files[] = tmgmt_file.text_processor.interface.inc files[] = tmgmt_file.recursive_iterator.inc files[] = tmgmt_file.test diff --git a/translators/file/tmgmt_file.module b/translators/file/tmgmt_file.module index 7dd6e92..fdadb5c 100644 --- a/translators/file/tmgmt_file.module +++ b/translators/file/tmgmt_file.module @@ -32,92 +32,37 @@ function tmgmt_file_theme() { } /** - * Processes the translation import. - * - * @param TMGMTJob $job - * Job for which we are importing the translation. - * @param TMGMTFileFormatInterface $importer_controller - * The importer controller. - * @param $file - * The file to be imported. - * - * @return bool - * Import result. - */ -function tmgmt_file_process_import(TMGMTJob $job, TMGMTFileFormatInterface $importer_controller, $file) { - $text_processors = $job->getTranslator()->getSetting('text_processor_plugins'); - - // Validate the file. - $validated_job = $importer_controller->validateImport($file->uri); - - // If we passed the importer validation and have processors do the validation - // for each of them. - if (!empty($validated_job) && !empty($text_processors)) { - foreach ($text_processors as $name) { - try { - $controller_class = tmgmt_file_text_processor_controller($name); - /** @var TMGMTFileTextProcessorInterface $processor_controller */ - $processor_controller = new $controller_class; - $processor_controller->validateJobTranslationUponImport($job, $file->uri); - } - catch (TMGMTException $e) { - $job->addMessage($e->getMessage(), array(), 'error'); - $validated_job = FALSE; - break; - } - } - } - - if (!$validated_job) { - $job->addMessage('Failed to validate file, import aborted.', array(), 'error'); - return FALSE; - } - elseif ($validated_job->tjid != $job->tjid) { - $uri = $validated_job->uri(); - $label = $validated_job->label(); - $job->addMessage('Import file is from job @label, import aborted.', array('@url' => url($uri['path']), '@label' => $label)); - return FALSE; - } - else { - try { - // Validation successful, start import. - $job->addTranslatedData($importer_controller->import($file->uri)); - - // If we have processors do the translation text processing. - if (!empty($text_processors)) { - foreach ($text_processors as $name) { - $controller_class = tmgmt_file_text_processor_controller($name); - /** @var TMGMTFileTextProcessorInterface $processor_controller */ - $processor_controller = new $controller_class; - $processor_controller->processJobTranslationUponImport($job); - } - } - - $job->addMessage('Successfully imported file.'); - return TRUE; - } - catch (Exception $e) { - $job->addMessage('File import failed with the following message: @message', array('@message' => $e->getMessage()), 'error'); - } - } - - return FALSE; -} - -/** * Import form submit callback. */ function tmgmt_file_import_form_submit($form, &$form_state) { // Ensure we have the file uploaded. - /** @var TMGMTJob $job */ $job = $form_state['tmgmt_job']; $supported_formats = array_keys(tmgmt_file_format_plugin_info()); if ($file = file_save_upload('file', array('file_validate_extensions' => array(implode(' ', $supported_formats))))) { $extension = pathinfo($file->uri, PATHINFO_EXTENSION); - $importer_controller = tmgmt_file_format_controller($extension); - tmgmt_file_process_import($job, $importer_controller, $file); + $controller = tmgmt_file_format_controller($extension); + if ($controller) { + // Validate the file. + $validated_job = $controller->validateImport($file->uri); + if (!$validated_job) { + $job->addMessage('Failed to validate file, import aborted.', array(), 'error'); + } + elseif ($validated_job->tjid != $job->tjid) { + $uri = $validated_job->uri(); + $label = $validated_job->label(); + $job->addMessage('Import file is from job @label, import aborted.', array('@url' => url($uri['path']), '@label' => $label)); + } + else { + try { + // Validation successful, start import. + $job->addTranslatedData($controller->import($file->uri)); + $job->addMessage('Successfully imported file.'); + } catch (Exception $e) { + $job->addMessage('File import failed with the following message: @message', array('@message' => $e->getMessage()), 'error'); + } + } + } } - foreach ($job->getMessagesSince() as $message) { // Ignore debug messages. if ($message->type == 'debug') { @@ -167,43 +112,6 @@ function tmgmt_file_format_controller($plugin = NULL) { } /** - * Returns information about text processor plugins. - * - * @param $plugin - * (Optional) Name of a plugin/extension. - * - * @return array - * If a plugin name is provided, information about that plugin, an array of - * plugin information otherwise. The information of each plugin consists of - * the label and plugin controller class, keyed by the plugin name which is - * also the text processor name. - */ -function tmgmt_file_text_processor_plugin_info($plugin = NULL) { - return _tmgmt_plugin_info('file_text_processor', $plugin); -} - -/** - * Returns an array of file format plugin labels. - */ -function tmgmt_file_text_processor_plugin_labels() { - return _tmgmt_plugin_labels('file_text_processor'); -} - -/** - * Returns the file format plugin controller. - * - * @param $plugin - * (Optional) Name of a plugin/extension. - * - * @return TMGMTFileTextProcessorInterface - * Either a specific text processor plugin controller instance or an array of - * available controllers. - */ -function tmgmt_file_text_processor_controller($plugin = NULL) { - return _tmgmt_plugin_controller('file_text_processor', $plugin); -} - -/** * Implements hook_tmgmt_file_format_info(). */ function tmgmt_file_tmgmt_file_format_plugin_info() { @@ -220,18 +128,6 @@ function tmgmt_file_tmgmt_file_format_plugin_info() { } /** - * Implements hook_tmgmt_fle_text_processor_plugin_info(). - */ -function tmgmt_file_tmgmt_file_text_processor_plugin_info() { - return array( - 'mask_html_for_xliff' => array( - 'label' => t('Mask HTML for XLIFF export.'), - 'plugin controller class' => 'TMGMTFileXLIFFMaskHTMLProcessor', - ), - ); -} - -/** * Implements hook_tmgmt_job_delete(). */ function tmgmt_file_tmgmt_job_delete(TMGMTJob $job) { diff --git a/translators/file/tmgmt_file.plugin.inc b/translators/file/tmgmt_file.plugin.inc index 3484498..cfb9f65 100644 --- a/translators/file/tmgmt_file.plugin.inc +++ b/translators/file/tmgmt_file.plugin.inc @@ -29,17 +29,6 @@ class TMGMTFileTranslatorPluginController extends TMGMTDefaultTranslatorPluginCo $path = $job->getSetting('scheme') . '://tmgmt_file/' . $name . '.' . $job->getSetting('export_format'); $dirname = dirname($path); if (file_prepare_directory($dirname, FILE_CREATE_DIRECTORY)) { - - // If we have processors do the source text processing. - if ($text_processors = $job->getTranslator()->getSetting('text_processor_plugins')) { - foreach ($text_processors as $name) { - $controller_class = tmgmt_file_text_processor_controller($name); - /** @var TMGMTFileTextProcessorInterface $controller */ - $controller = new $controller_class; - $controller->processJobSourceUponRequest($job); - } - } - $file = file_save_data($export->export($job), $path); file_usage_add($file, 'tmgmt_file', 'tmgmt_job', $job->tjid); $job->submitted('Exported file can be downloaded here.', array('!link' => file_create_url($path))); diff --git a/translators/file/tmgmt_file.recursive_iterator.inc b/translators/file/tmgmt_file.recursive_iterator.inc index ebf6b91..7bde518 100644 --- a/translators/file/tmgmt_file.recursive_iterator.inc +++ b/translators/file/tmgmt_file.recursive_iterator.inc @@ -9,8 +9,9 @@ */ class RecursiveDOMIterator implements RecursiveIterator { /** - * Current Position in DOMNodeList - * @var Integer + * Current Position in DOMNodeList. + * + * @var int */ protected $position; @@ -25,7 +26,7 @@ class RecursiveDOMIterator implements RecursiveIterator { * Constructor. * * @param DOMNode $domNode - * DOMNode to itterate over. + * DOMNode to iterate over. */ public function __construct(DOMNode $domNode) { $this->position = 0; @@ -53,7 +54,7 @@ class RecursiveDOMIterator implements RecursiveIterator { /** * Returns if an iterator can be created for the current entry. * - * @return Boolean + * @return boolean */ public function hasChildren() { return $this->current()->hasChildNodes(); @@ -62,7 +63,7 @@ class RecursiveDOMIterator implements RecursiveIterator { /** * Returns the current position. * - * @return Integer + * @return int */ public function key() { return $this->position; @@ -85,7 +86,7 @@ class RecursiveDOMIterator implements RecursiveIterator { /** * Checks if current position is valid. * - * @return Boolean + * @return boolean */ public function valid() { return $this->position < $this->nodeList->length; diff --git a/translators/file/tmgmt_file.test b/translators/file/tmgmt_file.test index e4a162e..e56c32f 100644 --- a/translators/file/tmgmt_file.test +++ b/translators/file/tmgmt_file.test @@ -24,55 +24,17 @@ class TMGMTFileTestCase extends TMGMTBaseTestCase { $this->setEnvironment('de'); } - function testTextProcessorAPI() { + function testXLIFFTextProcessing() { $translator = $this->createTranslator(); $translator->plugin = 'file'; $translator->settings = array( 'export_format' => 'xlf', - 'text_processor_plugins' => array('test'), ); $translator->save(); - $job = $this->createJob(); - $job->translator = $translator->name; - $job->addItem('test_source', 'test', '1'); - - $job->requestTranslation(); - - $data = $job->getData(); - // The text should be updated with "{processed}". - $this->assertEqual($this->findSourceText($data), 'Text for job item with type test and id 1.{processed}'); - - $job = $this->importTranslatedFile($job); - $data = $job->getData(); - // The translation should be without "{processed}". - $this->assertEqual($this->findTranslationText($data), 'Text for job item with type test and id 1.'); - - // Update settings so that translator does not use any text processor. - $translator->settings = array( - 'export_format' => 'xlf', - 'text_processor_plugins' => array(), - ); - $translator->save(); - - $job = $this->createJob(); - $job->translator = $translator->name; - $job->addItem('test_source', 'test', '1'); - - $job->requestTranslation(); - $data = $job->getData(); - // There should be no {processed} in the text - $this->assertEqual($this->findSourceText($data), 'Text for job item with type test and id 1.'); - } - - function testXLIFFTextProcessor() { - $translator = $this->createTranslator(); - $translator->plugin = 'file'; - $translator->settings = array( - 'export_format' => 'xlf', - 'text_processor_plugins' => array('mask_html_for_xliff'), - ); - $translator->save(); + // Create the reader instance, it will be used through the tests. + $reader = new XMLReader(); + $xliff_elements = array('bpt', 'ept', 'ph', 'x', '#text', '#cdata-section', 'content'); // ==== First test the whole cycle ==== // $job = $this->createJob(); @@ -85,48 +47,45 @@ class TMGMTFileTestCase extends TMGMTBaseTestCase { // Requesting translation will mask the html. $job->requestTranslation(); - // Make sure the masking process happened. - $text = $this->findSourceText($job->getData()); - $this->assertTrue(strpos($text, 'assertTrue(strpos($text, 'importTranslatedFile($job); - - // Do the comparison of the translation text and the source. - $processed_text = trim($this->findTranslationText($job->getData())); - $source_text = trim(file_get_contents(drupal_get_path('module', 'tmgmt') . '/tests/testing_html/sample.html')); - $this->assertEqual($processed_text, $source_text); - - // ==== Test for tags being replaced ==== // - $job = $this->createJob(); - $job->translator = $translator->name; - $job->addItem('test_source', 'test_html', '1'); - $job->requestTranslation(); - // Go through the source text and make sure all HTML tags are masked. - $text = $this->findSourceText($job->getData()); - $reader = new XMLReader(); - $reader->XML('' . $text . ''); + $content = $this->getTransUnitsContent($job); + // Test that the exported trans unit contains only xliff elements. + $reader->XML('' . $content[0]['source'] . ''); while ($reader->read()) { - // There should not be any other elements then those listed. - $this->assertTrue(in_array($reader->name, array('bpt', 'ept', 'ph', 'x', '#text', '#cdata-section', 'content'))); + if (!in_array($reader->name, $xliff_elements)) { + $this->fail(t('The source contains unexpected element %element', array('%element' => $reader->name))); + } } - - $job = $this->importTranslatedFile($job); - $text = $this->findTranslationText($job->getData()); - // Make sure we have non malformed special characters and html entities - // present in the translation text. - $this->assertTrue(strpos($text, 'äöüľščťžýáíéäňú©«®™»') !== FALSE); - $this->assertTrue(strpos($text, '&<>') !== FALSE); - $reader = new XMLReader(); - $reader->XML('' . $text . ''); + $reader->XML('' . $content[0]['target'] . ''); while ($reader->read()) { - // There should not be any xliff elements now. - $this->assertTrue(!in_array($reader->name, array('bpt', 'ept', 'ph', 'x'))); + if (!in_array($reader->name, $xliff_elements)) { + $this->fail(t('The target contains unexpected element %element', array('%element' => $reader->name))); + } } + // Import the file, make sure all the html has been revealed and no xliff + // elements are present in the job translation. + $messages = $job->getMessages(); + $message = reset($messages); + $download_url = $message->variables['!link']; + $xml = simplexml_load_file($download_url); + $translated_file = 'public://tmgmt_file/translated.xlf'; + $xml->asXML($translated_file); + $uri = $job->uri(); + $edit = array( + 'files[file]' => $translated_file, + ); + $this->drupalPost($uri['path'] . '/manage', $edit, t('Import')); + // Reset caches and reload job. + entity_get_controller('tmgmt_job')->resetCache(); + entity_get_controller('tmgmt_job_item')->resetCache(); + $job = tmgmt_job_load($job->tjid); + + // Do the comparison of the translation text and the source. I must be the + // same as there was change done to the translation. + $item_data = $job->getData(array(1, 'dummy', 'deep_nesting')); + $source_text = trim(file_get_contents(drupal_get_path('module', 'tmgmt') . '/tests/testing_html/sample.html')); + $this->assertEqual(trim($item_data[1]['#text']), trim($source_text)); + // ==== Test integrity check ==== // $job = $this->createJob(); $job->translator = $translator->name; @@ -154,7 +113,7 @@ class TMGMTFileTestCase extends TMGMTBaseTestCase { $integrity_check_failed = FALSE; /** @var TMGMTMessage $message */ foreach ($job->getMessages() as $message) { - if(strpos($message->getMessage(), 'Integrity check for job item') !== FALSE) { + if ($message->getMessage() == t('Failed to validate file, import aborted.')) { $integrity_check_failed = TRUE; } } @@ -169,30 +128,33 @@ class TMGMTFileTestCase extends TMGMTBaseTestCase { } /** - * Helper function to import "translated" xliff file. - * - * @param TMGMTJob $job - * Translation job for which to import the file. - * - * @return TMGMTJob - * Translation job with import. + * Gets trans-unit content from the xliff file that has been exported for the + * given job as last. */ - protected function importTranslatedFile(TMGMTJob $job) { + protected function getTransUnitsContent(TMGMTJob $job) { $messages = $job->getMessages(); $message = reset($messages); $download_url = $message->variables['!link']; - $xml = simplexml_load_file($download_url); - $translated_file = 'public://tmgmt_file/translated.xlf'; - $xml->asXML($translated_file); - $uri = $job->uri(); - $edit = array( - 'files[file]' => $translated_file, - ); - $this->drupalPost($uri['path'] . '/manage', $edit, t('Import')); + $xml_string = file_get_contents($download_url); + $xml = simplexml_load_string($xml_string); - entity_get_controller('tmgmt_job')->resetCache(); - entity_get_controller('tmgmt_job_item')->resetCache(); - return tmgmt_job_load($job->tjid); + // Register the xliff namespace, required for xpath. + $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2'); + + $reader = new XMLReader(); + $data = array(); + $i = 0; + foreach ($xml->xpath('//xliff:trans-unit') as $unit) { + $reader->XML($unit->source->asXML()); + $reader->read(); + $data[$i]['source'] = $reader->readInnerXml(); + $reader->XML($unit->target->asXML()); + $reader->read(); + $data[$i]['target'] = $reader->readInnerXml(); + $i++; + } + + return $data; } /** @@ -403,50 +365,4 @@ class TMGMTFileTestCase extends TMGMTBaseTestCase { $this->assertText(t('Finished')); $this->assertNoText(t('Needs review')); } - - /** - * Helper function to find #text in the job data. - * - * @param array $data - * Job data. - * - * @return string - * Source text. - */ - protected function findSourceText($data) { - if (isset($data['#text'])) { - return $data['#text']; - } - else { - foreach (element_children($data) as $key) { - if ($text = $this->findSourceText($data[$key])) { - return $text; - } - } - } - return NULL; - } - - /** - * Helper function to find #translation][#text in the job data. - * - * @param array $data - * Job data. - * - * @return string - * Translation text. - */ - protected function findTranslationText($data) { - if (isset($data['#translation']['#text'])) { - return $data['#translation']['#text']; - } - else { - foreach (element_children($data) as $key) { - if ($text = $this->findTranslationText($data[$key])) { - return $text; - } - } - } - return NULL; - } } diff --git a/translators/file/tmgmt_file.ui.inc b/translators/file/tmgmt_file.ui.inc index 1d83d6d..d1a10b4 100644 --- a/translators/file/tmgmt_file.ui.inc +++ b/translators/file/tmgmt_file.ui.inc @@ -44,15 +44,6 @@ class TMGMTFileTranslatorUIController extends TMGMTDefaultTranslatorUIController ); } - $text_processors = $translator->getSetting('text_processor_plugins'); - $form['text_processor_plugins'] = array( - '#type' => 'checkboxes', - '#title' => t('Text processors'), - '#description' => t('Identify which text processors should be used during the import/export operations.'), - '#options' => tmgmt_file_text_processor_plugin_labels(), - '#default_value' => is_array($text_processors) ? $text_processors : array(), - ); - return parent::pluginSettingsForm($form, $form_state, $translator); }