entity_translation.test 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  1. <?php
  2. /**
  3. * @file
  4. * Tests for Entity translation module.
  5. */
  6. /**
  7. * Base class for entity translation module tests.
  8. */
  9. class EntityTranslationTestCase extends DrupalWebTestCase {
  10. protected $current_user;
  11. protected $admin_user;
  12. protected $translator_user;
  13. /**
  14. * {@inheritdoc}
  15. */
  16. function setUp() {
  17. $args = func_get_args();
  18. call_user_func_array(array('parent', 'setUp'), $args);
  19. // Reset user fields to make test object reusable.
  20. unset($this->current_user);
  21. unset($this->admin_user);
  22. unset($this->translator_user);
  23. }
  24. /**
  25. * Retrieves a Drupal path or an absolute path with language.
  26. *
  27. * @param $language
  28. * Language code or language object.
  29. */
  30. function get($language, $path = '', array $options = array(), array $headers = array()) {
  31. $options['language'] = $this->getLanguage($language);
  32. return $this->drupalGet($path, $options, $headers);
  33. }
  34. /**
  35. * Posts to a Drupal path with language.
  36. */
  37. function post($language, $path, $edit, $submit, array $options = array(), array $headers = array(), $form_html_id = NULL, $extra_post = NULL) {
  38. $options['language'] = $this->getLanguage($language);
  39. $this->drupalPost($path, $edit, $submit, $options, $headers, $form_html_id, $extra_post);
  40. }
  41. /**
  42. * Login the given user only if she has not changed.
  43. */
  44. function login($user) {
  45. if (!isset($this->current_user) || $this->current_user->uid != $user->uid) {
  46. $this->current_user = $user;
  47. $this->drupalLogin($user);
  48. }
  49. }
  50. /**
  51. * Returns a user with administration rights.
  52. *
  53. * @param $permissions
  54. * Additional permissions for administrative user.
  55. */
  56. function getAdminUser(array $permissions = array()) {
  57. if (!isset($this->admin_user)) {
  58. $this->admin_user = $this->drupalCreateUser(array_merge(array(
  59. 'bypass node access',
  60. 'administer nodes',
  61. 'administer fields',
  62. 'administer languages',
  63. 'administer content types',
  64. 'administer blocks',
  65. 'access administration pages',
  66. 'administer site configuration',
  67. ), $permissions));
  68. }
  69. return $this->admin_user;
  70. }
  71. /**
  72. * Returns a user with minimal translation rights.
  73. *
  74. * @param $permissions
  75. * Additional permissions for administrative user.
  76. */
  77. function getTranslatorUser(array $permissions = array()) {
  78. if (!isset($this->translator_user)) {
  79. $this->translator_user = $this->drupalCreateUser(array_merge(array(
  80. 'create page content',
  81. 'edit own page content',
  82. 'delete own page content',
  83. 'translate any entity',
  84. ), $permissions));
  85. }
  86. return $this->translator_user;
  87. }
  88. /**
  89. * Make sure the clean urls are enabled.
  90. */
  91. function enableCleanUrls() {
  92. $this->drupalGet('admin/config/search/clean-urls');
  93. $edit = array();
  94. $edit['clean_url'] = TRUE;
  95. $this->drupalPost(NULL, $edit, t('Save configuration'));
  96. }
  97. /**
  98. * Enable URL language detection.
  99. */
  100. function enableUrlLanguageDetection() {
  101. // Enable URL language detection and selection.
  102. $edit = array(
  103. 'language[enabled][locale-url]' => TRUE,
  104. 'language_content[enabled][locale-interface]' => TRUE
  105. );
  106. $this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings'));
  107. $this->assertRaw(t('Language negotiation configuration saved.'), t('URL language detection enabled.'));
  108. $this->drupalGet('admin/config/regional/language/configure');
  109. // Reset caches.
  110. drupal_static_reset('locale_url_outbound_alter');
  111. drupal_static_reset('language_list');
  112. }
  113. /**
  114. * Get a language object from a language code.
  115. */
  116. public function getLanguage($langcode) {
  117. if (is_object($langcode)) {
  118. return $langcode;
  119. }
  120. else {
  121. $language_list = language_list();
  122. return $language_list[$langcode];
  123. }
  124. }
  125. /**
  126. * Disable a language which is in the language list.
  127. *
  128. * @param string $langcode
  129. * The code of the language to disable, which must exist.
  130. */
  131. function disableLanguage($langcode) {
  132. $edit = array(
  133. 'enabled[' . $langcode . ']' => FALSE,
  134. );
  135. $this->drupalPost('admin/config/regional/language', $edit, 'Save configuration');
  136. }
  137. /**
  138. * Install a specified language if it has not been already, otherwise make sure that the language is enabled.
  139. *
  140. * @param $langcode
  141. * The language code to check.
  142. */
  143. function addLanguage($langcode) {
  144. // Check to make sure that language has not already been installed.
  145. $this->drupalGet('admin/config/regional/language');
  146. if (strpos($this->drupalGetContent(), 'enabled[' . $langcode . ']') === FALSE) {
  147. // Doesn't have language installed so add it.
  148. $edit = array();
  149. $edit['langcode'] = $langcode;
  150. $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
  151. // Make sure we are not using a stale list.
  152. drupal_static_reset('language_list');
  153. $languages = language_list('language');
  154. $this->assertTrue(array_key_exists($langcode, $languages), t('Language was installed successfully.'));
  155. if (array_key_exists($langcode, $languages)) {
  156. $this->assertRaw(t('The language %language has been created and can now be used. More information is available on the <a href="@locale-help">help screen</a>.', array('%language' => $languages[$langcode]->name, '@locale-help' => url('admin/help/locale'))), t('Language has been created.'));
  157. }
  158. }
  159. elseif ($this->xpath('//input[@type="checkbox" and @name=:name and @checked="checked"]', array(':name' => 'enabled[' . $langcode . ']'))) {
  160. // It is installed and enabled. No need to do anything.
  161. $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed and enabled.');
  162. }
  163. else {
  164. // It is installed but not enabled. Enable it.
  165. $this->assertTrue(TRUE, 'Language [' . $langcode . '] already installed.');
  166. $this->drupalPost(NULL, array('enabled[' . $langcode . ']' => TRUE), t('Save configuration'));
  167. $this->assertRaw(t('Configuration saved.'), t('Language successfully enabled.'));
  168. }
  169. }
  170. /**
  171. * Configure the "Basic page" content type for entity translation tests.
  172. */
  173. function configureContentType() {
  174. // Configure the "Basic page" content type to use multilingual support with
  175. // translation.
  176. $edit = array();
  177. $edit['language_content_type'] = ENTITY_TRANSLATION_ENABLED;
  178. $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
  179. $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.'));
  180. // Set body field's cardinality to unlimited and toggle translatability.
  181. $edit = array();
  182. $edit['field[cardinality]'] = FIELD_CARDINALITY_UNLIMITED;
  183. $edit['field[translatable]'] = 1;
  184. $this->drupalPost('admin/structure/types/manage/page/fields/body', $edit, t('Save settings'));
  185. $this->assertRaw(t('Saved %field configuration.', array('%field' => 'Body')), t('Body field settings have been updated.'));
  186. // Check if the setting works.
  187. $this->drupalGet('node/add/page');
  188. $this->assertFieldById('edit-body-en-add-more', t('Add another item'), t('Add another item button found.'));
  189. }
  190. /**
  191. * Create a "Basic page" in the specified language.
  192. *
  193. * @param $title
  194. * Title of the basic page in the specified language.
  195. * @param $body
  196. * Body of the basic page in the specified language.
  197. * @param $langcode
  198. * The language code to be assigned to the specified values.
  199. */
  200. function createPage($title, $body, $langcode) {
  201. $edit = array();
  202. $edit["title"] = $title;
  203. $edit["body[$langcode][0][value]"] = $body;
  204. $edit['language'] = $langcode;
  205. $this->drupalPost('node/add/page', $edit, t('Save'));
  206. $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), t('Basic page created.'));
  207. // Check to make sure the node was created.
  208. $node = $this->drupalGetNodeByTitle($title);
  209. $this->assertTrue($node, t('Node found in database.'));
  210. return $node;
  211. }
  212. /**
  213. * Create a translation.
  214. *
  215. * @param $node
  216. * Node of the basic page to create translation for.
  217. * @param $title
  218. * Title of the basic page in the specified language.
  219. * @param $body
  220. * Body of the basic page in the specified language.
  221. * @param $langcode
  222. * The language code to be assigned to the specified values.
  223. */
  224. function createTranslation($node, $title, $body, $langcode, $source_langcode = 'en') {
  225. $this->drupalGet('node/' . $node->nid . '/edit/add/' . $source_langcode . '/' . $langcode);
  226. $body_key = "body[$langcode][0][value]";
  227. $this->assertFieldByXPath("//textarea[@name='$body_key']", $node->body[$source_langcode][0]['value'], 'Original body value correctly populated.');
  228. $this->assertFieldById('edit-body-' . $langcode . '-add-more', t('Add another item'), t('Add another item button found.'));
  229. $edit = array();
  230. $edit[$body_key] = $body;
  231. $this->drupalPost(NULL, $edit, t('Save'));
  232. $this->drupalGet('node/' . $node->nid . '/translate');
  233. $this->assertLinkByHref('node/' . $node->nid . '/edit/' . $langcode, 0, t('Translation edit link found. Translation created.'));
  234. return $node;
  235. }
  236. }
  237. /**
  238. * Basic tests for the translation creation/editing workflow.
  239. */
  240. class EntityTranslationTranslationTestCase extends EntityTranslationTestCase {
  241. /**
  242. * Return the test information.
  243. */
  244. public static function getInfo() {
  245. return array(
  246. 'name' => 'Entity translation workflow',
  247. 'description' => 'Basic tests for the translation creation/editing workflow.',
  248. 'group' => 'Entity translation',
  249. );
  250. }
  251. function setUp() {
  252. parent::setUp('locale', 'entity_translation');
  253. $this->login($this->getAdminUser());
  254. $this->addLanguage('en');
  255. $this->addLanguage('es');
  256. $this->addLanguage('fr');
  257. $this->disableLanguage('fr');
  258. $this->configureContentType();
  259. $this->login($this->getTranslatorUser());
  260. }
  261. /**
  262. * Test disabled languages.
  263. *
  264. * Make sure disabled languages are not accessible in the language list when
  265. * the option entity_translation_languages_enabled is enabled.
  266. */
  267. function testDisabledLanguages() {
  268. $this->drupalGet('node/add/page');
  269. $this->assertRaw('value="fr"', 'French is available even if the language is disabled');
  270. variable_set('entity_translation_languages_enabled', TRUE);
  271. $this->drupalGet('node/add/page');
  272. $this->assertNoRaw('value="fr"', 'French is not available when the language is disabled and the option entity_translation_languages_enabled is enabled.');
  273. }
  274. /**
  275. * Test if field based translation works.
  276. *
  277. * Enable field based translation for basic pages. Add a field with a
  278. * cardinality higher than 1, to test if field_default_extract_form_values()
  279. * is invoked. Create a basic page and translate it.
  280. */
  281. function testFieldTranslation() {
  282. // Create Basic page in English.
  283. $node_title = $this->randomName();
  284. $node_body = $this->randomName();
  285. $node = $this->createPage($node_title, $node_body, 'en');
  286. // Submit translation in Spanish.
  287. $node_translation_title = $this->randomName();
  288. $node_translation_body = $this->randomName();
  289. $node_translation = $this->createTranslation($node, $node_translation_title, $node_translation_body, 'es');
  290. }
  291. }
  292. /**
  293. * Basic tests for comment related things.
  294. *
  295. * @todo Add tests for comment translation workflow.
  296. */
  297. class EntityTranslationCommentTestCase extends EntityTranslationTestCase {
  298. protected $comment_user;
  299. /**
  300. * Return the test information.
  301. */
  302. public static function getInfo() {
  303. return array(
  304. 'name' => 'Comment translation',
  305. 'description' => 'Basic tests for comment translation/filtering.',
  306. 'group' => 'Entity translation',
  307. );
  308. }
  309. function setUp() {
  310. parent::setUp('locale', 'entity_translation', 'comment');
  311. $this->login($this->getAdminUser());
  312. $this->addLanguage('en');
  313. $this->addLanguage('es');
  314. $this->enableUrlLanguageDetection();
  315. $this->configureContentType();
  316. $this->configureComments(FALSE);
  317. $this->login($this->getTranslatorUser());
  318. }
  319. function tearDown() {
  320. unset($this->comment_user);
  321. parent::tearDown();
  322. }
  323. function getCommentUser() {
  324. if (empty($this->comment_user)) {
  325. $this->comment_user = $this->drupalCreateUser(array(
  326. 'access comments',
  327. 'post comments',
  328. 'edit own comments',
  329. ));
  330. }
  331. return $this->comment_user;
  332. }
  333. /**
  334. * Enable comments and comment filtering by language.
  335. */
  336. function configureComments($filter_by_language = TRUE) {
  337. $edit = array();
  338. $edit['comment'] = COMMENT_NODE_OPEN;
  339. $edit['entity_translation_comment_filter'] = $filter_by_language;
  340. $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
  341. $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')));
  342. $this->drupalGet('admin/structure/types/manage/page');
  343. if ($filter_by_language) {
  344. $this->assertFieldChecked('edit-entity-translation-comment-filter', 'Comment filtering is enabled.');
  345. }
  346. else {
  347. $this->assertNoFieldChecked('edit-entity-translation-comment-filter', 'Comment filtering is disabled.');
  348. }
  349. }
  350. /**
  351. * Add a comment for the given node.
  352. *
  353. * @param $node
  354. * The node for which to add the comment.
  355. * @param $comment_body
  356. * The comment body text.
  357. * @param $language
  358. * The comment language.
  359. */
  360. function postComment($node, $comment_body, $language) {
  361. $edit = array();
  362. $edit['comment_body[' . LANGUAGE_NONE . '][0][value]'] = $comment_body;
  363. $this->post($language, 'comment/reply/' . $node->nid, $edit, t('Save'));
  364. }
  365. /**
  366. * Test comment filtering by language.
  367. */
  368. function testCommentLanguageFiltering() {
  369. $node = $this->createPage($this->randomName(), $this->randomName(), 'en');
  370. $this->login($this->getCommentUser());
  371. // Create comments in different languages.
  372. $comment_en = $this->randomName();
  373. $this->postComment($node, $comment_en, 'en');
  374. $comment_es = $this->randomName();
  375. $this->postComment($node, $comment_es, 'es');
  376. // Check that ALL comments are being displayed when comment language filter
  377. // is disabled (default behavior).
  378. $this->get('en', 'node/' . $node->nid);
  379. $this->assertText($comment_en, 'English comment found.');
  380. $this->assertText($comment_es, 'Spanish comment found.');
  381. // Enable comment filtering by language.
  382. $this->login($this->getAdminUser());
  383. $this->configureComments(TRUE);
  384. $this->login($this->getCommentUser());
  385. // Load page in different languages. Check that only comments matching
  386. // current language are being displayed.
  387. $this->get('en', 'node/' . $node->nid);
  388. $this->assertText($comment_en, 'English comment found.');
  389. $this->assertNoText($comment_es, 'Spanish comment not found.');
  390. $this->get('es', 'node/' . $node->nid);
  391. $this->assertNoText($comment_en, 'English comment not found.');
  392. $this->assertText($comment_es, 'Spanish comment found.');
  393. }
  394. }
  395. /**
  396. * Test CRUD hook invocation.
  397. */
  398. class EntityTranslationHookTestCase extends EntityTranslationTestCase {
  399. /**
  400. * Return the test information.
  401. */
  402. public static function getInfo() {
  403. return array(
  404. 'name' => 'Entity translation hooks',
  405. 'description' => 'Test that entity translation hooks are properly fired.',
  406. 'group' => 'Entity translation',
  407. );
  408. }
  409. function setUp() {
  410. parent::setUp('locale', 'entity_translation', 'entity_translation_test');
  411. $this->login($this->getAdminUser());
  412. $this->addLanguage('it');
  413. $this->addLanguage('es');
  414. $this->configureContentType();
  415. $this->login($this->getTranslatorUser());
  416. }
  417. /**
  418. * Test whether hooks are properly fired in the regular form workflow.
  419. */
  420. function testFormWorkflow() {
  421. // Create Basic page in English.
  422. $node_title = $this->randomName();
  423. $node_body = $this->randomName();
  424. $node = $this->createPage($node_title, $node_body, 'en');
  425. // Submit translation in Italian.
  426. $node_translation_body = $this->randomName();
  427. $this->createTranslation($node, NULL, $node_translation_body, 'it');
  428. $info = $this->getHookInfo();
  429. $this->assertTrue(!empty($info['insert']), t('Insert hook has been properly fired.'));
  430. // Edit translation in Italian.
  431. $edit = array("body[it][0][value]" => $this->randomName());
  432. $this->drupalPost('node/' . $node->nid . '/edit/it', $edit, t('Save'));
  433. $info = $this->getHookInfo();
  434. $this->assertTrue(!empty($info['update']), t('Update hook has been properly fired.'));
  435. // Delete the Basic page.
  436. $edit = array();
  437. $this->drupalPost('node/' . $node->nid . '/delete', $edit, t('Delete'));
  438. $info = $this->getHookInfo('delete');
  439. $this->assertTrue(count($info) == 2 && !empty($info['en']) && !empty($info['it']), t('Delete hook has been properly fired.'));
  440. }
  441. /**
  442. * Test whether hooks are properly fired when using the API.
  443. */
  444. function testAPI() {
  445. // Create Basic page in English.
  446. $node = $this->createPage($this->randomName(), $this->randomName(), 'en');
  447. $handler = entity_translation_get_handler('node', $node);
  448. // Create a translation in Italian.
  449. $translation = array('source' => 'en', 'language' => 'it');
  450. $handler->setTranslation($translation);
  451. $handler->saveTranslations();
  452. $node = node_load($node->nid, NULL, TRUE);
  453. $handler = entity_translation_get_handler('node', $node);
  454. $translations = $handler->getTranslations();
  455. $this->assertTrue(!empty($translations->data['it']), t('An Italian translation has been created'));
  456. $info = $this->getHookInfo();
  457. $this->assertTrue(!empty($info['insert']), t('Insert hook has been properly fired.'));
  458. // Check that the update hook is properly fired.
  459. $translation['status'] = 1;
  460. $handler->setTranslation($translation);
  461. $handler->saveTranslations();
  462. $info = $this->getHookInfo();
  463. $this->assertTrue(!empty($info['update']), t('Update hook has been properly fired.'));
  464. // Create a Spanish translation and update it before saving it.
  465. $translation = array('source' => 'it', 'language' => 'es');
  466. $handler->setTranslation($translation);
  467. $translation['status'] = 1;
  468. $handler->setTranslation($translation);
  469. $handler->saveTranslations();
  470. $node = node_load($node->nid, NULL, TRUE);
  471. $handler = entity_translation_get_handler('node', $node);
  472. $translations = $handler->getTranslations();
  473. $this->assertTrue(!empty($translations->data['es']), t('A Spanish translation has been created'));
  474. $info = $this->getHookInfo();
  475. $this->assertTrue(!empty($info['insert']), t('Insert hook has been properly fired.'));
  476. // Delete a translation after updating it without saving.
  477. $translation['status'] = 0;
  478. $handler->setTranslation($translation);
  479. $handler->removeTranslation('es');
  480. $handler->saveTranslations();
  481. $info = $this->getHookInfo();
  482. $this->assertTrue(empty($info['update']), t('Update hook has not been fired.'));
  483. $info = $this->getHookInfo('delete');
  484. $this->assertTrue(!empty($info['es']), t('Delete hook has been properly fired.'));
  485. }
  486. /**
  487. * Retrieve the information stored by hook implementations.
  488. */
  489. protected function getHookInfo($op = 'save') {
  490. $name = 'entity_translation_test_' . $op;
  491. $info = variable_get($name);
  492. variable_del($name);
  493. return $info;
  494. }
  495. }
  496. /**
  497. * Tests that entity translation handler hierarchy works properly.
  498. */
  499. class EntityTranslationHierarchyTestCase extends EntityTranslationTestCase {
  500. /**
  501. * Return the test information.
  502. */
  503. public static function getInfo() {
  504. return array(
  505. 'name' => 'Entity translation hierarchy',
  506. 'description' => 'Tests that entity translation handler hierarchy works properly.',
  507. 'group' => 'Entity translation',
  508. );
  509. }
  510. /**
  511. * {@inheritdoc}
  512. */
  513. function setUp() {
  514. parent::setUp('locale', 'entity_translation');
  515. }
  516. /**
  517. * Tests the handler hierarchy.
  518. */
  519. public function testHierarchy() {
  520. $entity_type = 'node';
  521. $node = $this->drupalCreateNode();
  522. $factory = EntityTranslationHandlerFactory::getInstance();
  523. $handler = $factory->getHandler($entity_type, $node);
  524. $children = array();
  525. foreach (range(0, 4) as $index) {
  526. $children[$index] = $this->drupalCreateNode();
  527. $handler->addChild($entity_type, $children[$index]);
  528. }
  529. $langcode = 'it';
  530. $handler->setActiveLanguage($langcode);
  531. foreach ($children as $child) {
  532. $child_handler = $factory->getHandler($entity_type, $child);
  533. $this->assertEqual($child_handler->getActiveLanguage(), $langcode);
  534. }
  535. $rm_index = mt_rand(0, count($children) - 1);
  536. $handler->removeChild($entity_type, $children[$rm_index]);
  537. $langcode = 'fr';
  538. $handler->setActiveLanguage($langcode);
  539. foreach ($children as $index => $child) {
  540. $child_handler = $factory->getHandler($entity_type, $child);
  541. $this->assertEqual($child_handler->getActiveLanguage() == $langcode, $index != $rm_index);
  542. }
  543. // @todo Test the other properties.
  544. }
  545. }
  546. /**
  547. * Basic tests for nodes using both content and entity translation.
  548. */
  549. class EntityTranslationContentTranslationTestCase extends EntityTranslationTestCase {
  550. /**
  551. * Return the test information.
  552. */
  553. public static function getInfo() {
  554. return array(
  555. 'name' => 'Content and entity translation',
  556. 'description' => 'Basic tests for nodes using both content and entity translatio.',
  557. 'group' => 'Entity translation',
  558. );
  559. }
  560. /**
  561. * {@inheritdoc}
  562. */
  563. public function setUp() {
  564. // Activate modules and unset users.
  565. parent::setUp('locale', 'translation', 'translation_test', 'entity_translation');
  566. // Create admin and translator users with one extra permission,
  567. // namely the 'translate content' permission.
  568. // These getters works also as setters.
  569. $this->getAdminUser(array(
  570. 'translate content',
  571. ));
  572. $this->getTranslatorUser(array(
  573. 'translate content',
  574. ));
  575. $this->login($this->getAdminUser());
  576. $this->addLanguage('en');
  577. $this->addLanguage('es');
  578. $this->enableUrlLanguageDetection();
  579. $this->configureContentType();
  580. $this->login($this->getTranslatorUser());
  581. }
  582. /**
  583. * Configure the "Basic page" content type for entity translation tests.
  584. */
  585. public function configureContentType() {
  586. // Configure the "Basic page" content type to use multilingual support with
  587. // content translation.
  588. $edit = array();
  589. $edit['language_content_type'] = TRANSLATION_ENABLED;
  590. $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
  591. $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.'));
  592. // Toggle body field's translatability.
  593. $edit = array();
  594. $edit['field[translatable]'] = 1;
  595. $this->drupalPost('admin/structure/types/manage/page/fields/body', $edit, t('Save settings'));
  596. $this->assertRaw(t('Saved %field configuration.', array('%field' => 'Body')), t('Body field settings have been updated.'));
  597. }
  598. /**
  599. * @see TranslationTestCase::createPage()
  600. */
  601. function createPage($title, $body, $language = NULL) {
  602. $edit = array();
  603. $langcode = LANGUAGE_NONE;
  604. $edit["title"] = $title;
  605. $edit["body[$langcode][0][value]"] = $body;
  606. if (!empty($language)) {
  607. $edit['language'] = $language;
  608. }
  609. $this->drupalPost('node/add/page', $edit, t('Save'));
  610. $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), 'Basic page created.');
  611. // Check to make sure the node was created.
  612. $node = $this->drupalGetNodeByTitle($title);
  613. $this->assertTrue($node, 'Node found in database.');
  614. return $node;
  615. }
  616. /**
  617. * Tests copying of source node's body value in the add translation form page.
  618. */
  619. public function testCopyFieldsUsingContentTranslation() {
  620. // Create Basic page in English.
  621. $node_title = $this->randomName();
  622. $node_body = $this->randomName();
  623. $node = $this->createPage($node_title, $node_body, 'en');
  624. // Check that the edit form correctly copies over the field's values from
  625. // the source node.
  626. $target_language = 'es';
  627. $this->drupalGet('node/add/page', array('query' => array('translation' => $node->nid, 'target' => $target_language)));
  628. $body_key = "body[${target_language}][0][value]";
  629. $this->assertFieldByXPath("//textarea[@name='$body_key']", $node_body, "Body field correctly instantiated with the value of the source language.");
  630. }
  631. }
  632. /**
  633. * Tests for integration of Entity Translation with other modules.
  634. */
  635. class EntityTranslationIntegrationTestCase extends EntityTranslationTestCase {
  636. /**
  637. * Return the test information.
  638. */
  639. public static function getInfo() {
  640. return array(
  641. 'name' => 'Integration with other modules',
  642. 'description' => 'Tests for integration of Entity Translation with other modules.',
  643. 'group' => 'Entity translation',
  644. // We need to add this to the test_dependencies[] as well.
  645. 'dependencies' => array('pathauto'),
  646. );
  647. }
  648. /**
  649. * {@inheritdoc}
  650. */
  651. public function setUp() {
  652. // Activate modules.
  653. parent::setUp('locale', 'entity_translation');
  654. // Create admin and translator users with one extra permission,
  655. // namely the 'administer content' permission for the admin, to
  656. // allow enabling the pathauto module during testing. The
  657. // Translator user needs to be able to create url aliases.
  658. $this->getAdminUser(array(
  659. 'administer modules',
  660. ));
  661. $this->getTranslatorUser(array(
  662. 'create url aliases',
  663. ));
  664. $this->login($this->getAdminUser());
  665. $this->addLanguage('en');
  666. $this->addLanguage('es');
  667. $this->enableUrlLanguageDetection();
  668. $this->configureContentType();
  669. $this->login($this->getTranslatorUser());
  670. }
  671. /**
  672. * Returns the role id of an $account object.
  673. */
  674. protected function getUserRole($account) {
  675. return reset($account->roles);
  676. }
  677. /**
  678. * Tests Pathauto integration.
  679. */
  680. public function testPathautoIntegration() {
  681. $languages = language_list();
  682. // Enable the path module to add aliases manually.
  683. $this->login($this->getAdminUser());
  684. if (!module_exists('path')) {
  685. module_enable(array('path'));
  686. }
  687. $this->login($this->getTranslatorUser());
  688. // Create Basic page in English.
  689. $node_title = $this->randomName();
  690. $node_body = $this->randomName();
  691. $node = $this->createPage($node_title, $node_body, 'en');
  692. $node_alias = $this->randomName();
  693. $edit = array(
  694. 'path[alias]' => $node_alias,
  695. );
  696. $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
  697. // Submit translation in Spanish.
  698. $node_translation_body = $this->randomName();
  699. $this->createTranslation($node, $node_title, $node_translation_body, 'es');
  700. $node_translation_alias = $this->randomName();
  701. $edit = array(
  702. 'path[alias]' => $node_translation_alias,
  703. );
  704. $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'), array('language' => $languages['es']));
  705. // Enable the pathauto module.
  706. $this->login($this->getAdminUser());
  707. if (!module_exists('pathauto')) {
  708. module_enable(array('pathauto'));
  709. }
  710. $admin_rid = $this->getUserRole($this->getAdminUser());
  711. user_role_grant_permissions($admin_rid, array('administer url aliases', 'administer pathauto'));
  712. $translator_rid = $this->getUserRole($this->getTranslatorUser());
  713. user_role_grant_permissions($translator_rid, array('create url aliases'));
  714. $this->login($this->getTranslatorUser());
  715. // Create pathauto alias for source node.
  716. $edit = array(
  717. 'path[pathauto]' => TRUE,
  718. );
  719. $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
  720. // Clear the static caches in case they interfere.
  721. drupal_lookup_path('wipe');
  722. $node_pathauto_alias = pathauto_node_update_alias($node, 'return');
  723. $node_translation_pathauto_alias = pathauto_node_update_alias($node, 'return', array('language' => 'es'));
  724. // Check that the new alias for the translation matches the
  725. // pathauto's logic.
  726. $this->assertEqual($this->getUrl(), url(drupal_get_path_alias($node_pathauto_alias), array('absolute' => TRUE)));
  727. // Check that a pathauto alias was created for the source and
  728. // matches the pathauto's logic.
  729. $this->drupalGet('node/' . $node->nid, array('language' => $languages['es']));
  730. $this->assertEqual($this->getUrl(), url(drupal_get_path_alias($node_translation_pathauto_alias), array('absolute' => TRUE, 'language' => $languages['es'])));
  731. // Delete the two aliases.
  732. path_delete(array('source' => 'node/' . $node->nid));
  733. // Create pathauto alias for the translation of the node.
  734. $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'), array('language' => $languages['es']));
  735. // Clear the static caches in case they interfere.
  736. drupal_lookup_path('wipe');
  737. $node_pathauto_alias = pathauto_node_update_alias($node, 'return');
  738. $node_translation_pathauto_alias = pathauto_node_update_alias($node, 'return', array('language' => 'es'));
  739. // Check that the new alias for the translation matches the
  740. // pathauto's logic.
  741. $this->assertEqual($this->getUrl(), url(drupal_get_path_alias($node_translation_pathauto_alias), array('absolute' => TRUE, 'language' => $languages['es'])));
  742. // Check that a pathauto alias was created for the source and
  743. // matches the pathauto's logic.
  744. $this->drupalGet('node/' . $node->nid);
  745. $this->assertEqual($this->getUrl(), url(drupal_get_path_alias($node_pathauto_alias), array('absolute' => TRUE)));
  746. }
  747. }
  748. /**
  749. * Tests for enabling fields to use Entity Translation or disabling them.
  750. */
  751. class EntityTranslationToggleFieldsTranslatabilityTestCase extends EntityTranslationTestCase {
  752. /**
  753. * {@inheritdoc}
  754. */
  755. public static function getInfo() {
  756. return array(
  757. 'name' => 'Fields translatability toggling',
  758. 'description' => 'Tests for enabling fields to use Entity Translation or disabling them.',
  759. 'group' => 'Entity translation',
  760. );
  761. }
  762. /**
  763. * {@inheritdoc}
  764. */
  765. public function setUp() {
  766. // Activate modules.
  767. parent::setUp('locale', 'taxonomy', 'entity_translation', 'entity_translation_test');
  768. $this->login($this->getAdminUser(array(
  769. 'administer taxonomy',
  770. 'toggle field translatability',
  771. )));
  772. $this->login($this->getTranslatorUser(array(
  773. 'administer taxonomy',
  774. )));
  775. }
  776. /**
  777. * Configure the "Basic page" content type for entity translation tests.
  778. */
  779. protected function configureContentTypeForRevisions() {
  780. // Configure the "Basic page" content type to use revisions.
  781. $edit = array(
  782. 'node_options[revision]' => 1,
  783. );
  784. $this->drupalPost('admin/structure/types/manage/page', $edit, t('Save content type'));
  785. $this->assertRaw(t('The content type %type has been updated.', array('%type' => 'Basic page')), t('Basic page content type has been updated.'));
  786. }
  787. /**
  788. * Create a "Basic page" in the specified language.
  789. *
  790. * @param $title
  791. * Title of the basic page in the specified language.
  792. * @param $body
  793. * Body of the basic page in the specified language.
  794. */
  795. protected function createUntranslatedPage($title, $body) {
  796. $edit = array(
  797. 'title' => $title,
  798. 'body[und][0][value]' => $body,
  799. );
  800. $this->drupalPost('node/add/page', $edit, t('Save'));
  801. $this->assertRaw(t('Basic page %title has been created.', array('%title' => $title)), t('Basic page created.'));
  802. // Check to make sure the node was created.
  803. $node = $this->drupalGetNodeByTitle($title);
  804. $this->assertTrue($node, t('Node found in database.'));
  805. return $node;
  806. }
  807. /**
  808. * Create a "Tags" term in the specified language.
  809. *
  810. * @param $name
  811. * Name of the term.
  812. * @param $description
  813. * Description of the term.
  814. * @param $text
  815. * Content for the field_simple_text field.
  816. */
  817. protected function createUntranslatedTag($name, $description, $text) {
  818. $edit = array(
  819. 'name' => $name,
  820. 'description[value]' => $description,
  821. "field_simple_text[und][0][value]" => $text,
  822. );
  823. $this->drupalPost('admin/structure/taxonomy/tags/add', $edit, t('Save'));
  824. // Check to make sure the term was created.
  825. $term = current(entity_load('taxonomy_term', FALSE, array('name' => $name), TRUE));
  826. $this->assertTrue($term, t('Term found in database.'));
  827. return $term;
  828. }
  829. /**
  830. * Tests toggling translatability on fields with data (non-revisionable).
  831. */
  832. public function testTogglingFieldsWithDataNonRevisionable() {
  833. // Create an untranslated Basic page.
  834. $node_title = $this->randomName();
  835. $node_body = $this->randomName();
  836. $node = $this->createUntranslatedPage($node_title, $node_body);
  837. $this->assert(isset($node->body[LANGUAGE_NONE]), t('Found body field data in LANGUAGE_NONE as expected.'));
  838. $this->assertEqual($node->body[LANGUAGE_NONE][0]['value'], $node_body);
  839. // Create an untranslated Tags term.
  840. $term_name = $this->randomName();
  841. $term_description = $this->randomName();
  842. $term_simple_text = $this->randomName();
  843. $term = $this->createUntranslatedTag($term_name, $term_description, $term_simple_text);
  844. $this->assert(isset($term->field_simple_text[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.'));
  845. $this->assertEqual($term->field_simple_text[LANGUAGE_NONE][0]['value'], $term_simple_text);
  846. // Enable translation for field body and check field migration.
  847. $this->login($this->getAdminUser());
  848. $this->drupalGet('admin/structure/types/manage/page/fields/body');
  849. $this->clickLink('Enable translation');
  850. $this->drupalPost(NULL, array(), t('Confirm'));
  851. $node = current(entity_load('node', FALSE, array('title' => $node_title), TRUE));
  852. $this->assert(isset($node->body['en']), t('Found field data in English as expected.'));
  853. $this->assertEqual($node->body['en'][0]['value'], $node_body);
  854. $this->assert(!isset($node->body[LANGUAGE_NONE]), t('No field data in LANGUAGE_NONE found.'));
  855. // Disable translation for body field and check field reverse migration.
  856. $this->drupalGet('admin/structure/types/manage/page/fields/body');
  857. $this->clickLink('Disable translation');
  858. $this->drupalPost(NULL, array(), t('Confirm'));
  859. $node = current(entity_load('node', FALSE, array('title' => $node_title), TRUE));
  860. $this->assert(isset($node->body[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.'));
  861. $this->assertEqual($node->body[LANGUAGE_NONE][0]['value'], $node_body);
  862. $this->assert(!isset($node->body['en']), t('No field data in English found.'));
  863. // Enable translation for field_simple_text and check field migration.
  864. $this->drupalGet('admin/structure/taxonomy/tags/fields/field_simple_text');
  865. $this->clickLink('Enable translation');
  866. $this->drupalPost(NULL, array(), t('Confirm'));
  867. // Clear the field cache in order to load current field data.
  868. field_info_cache_clear();
  869. // Load the term and check that the fields data are under 'en'.
  870. $term = current(entity_load('taxonomy_term', FALSE, array('name' => $term_name), TRUE));
  871. $this->assert(isset($term->field_simple_text['en']), t('Found field data in English as expected.'));
  872. $this->assertEqual($term->field_simple_text['en'][0]['value'], $term_simple_text);
  873. $this->assert(!isset($term->field_simple_text[LANGUAGE_NONE]), t('No field data in LANGUAGE_NONE found.'));
  874. // Disable translation for field_simple_text.
  875. $this->drupalGet('admin/structure/taxonomy/tags/fields/field_simple_text');
  876. $this->clickLink('Disable translation');
  877. $this->drupalPost(NULL, array(), t('Confirm'));
  878. // Load the term and check that the fields data are under LANGUAGE_NONE.
  879. $term = current(entity_load('taxonomy_term', FALSE, array('name' => $term_name), TRUE));
  880. $this->assert(isset($term->field_simple_text[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.'));
  881. $this->assertEqual($term->field_simple_text[LANGUAGE_NONE][0]['value'], $term_simple_text);
  882. $this->assert(!isset($term->field_simple_text['en']), t('No field data in English found.'));
  883. }
  884. /**
  885. * Tests toggling translatability on fields with data (revisionable).
  886. */
  887. public function testTogglingFieldsWithDataRevisionable() {
  888. // Enable revisions for Basic pages.
  889. $this->login($this->getAdminUser());
  890. $this->configureContentTypeForRevisions();
  891. // Create an untranslated Basic page.
  892. $this->login($this->getTranslatorUser());
  893. $node_title = $this->randomName();
  894. $node_body = $this->randomName();
  895. $node = $this->createUntranslatedPage($node_title, $node_body);
  896. $this->assert(isset($node->body[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.'));
  897. $this->assertEqual($node->body[LANGUAGE_NONE][0]['value'], $node_body);
  898. // Create a new revision for the page.
  899. $edit_revision = array(
  900. 'title' => $this->randomName(),
  901. );
  902. $this->drupalPost('node/' . $node->nid . '/edit', $edit_revision, t('Save'));
  903. $node = node_load($node->nid, NULL, TRUE);
  904. $this->assert($node->vid == $node->nid + 1, t('Correct vid attached to the node object.'));
  905. // Enable translation for field body and check field migration on all
  906. // revisions.
  907. $this->login($this->getAdminUser());
  908. $this->drupalGet('admin/structure/types/manage/page/fields/body');
  909. $this->clickLink('Enable translation');
  910. $this->drupalPost(NULL, array(), t('Confirm'));
  911. $node_current_revision = current(entity_load('node', FALSE, array('vid' => $node->vid), TRUE));
  912. $this->assert(isset($node_current_revision->body['en']), t('Found field data in English as expected.'));
  913. $this->assertEqual($node_current_revision->body['en'][0]['value'], $node_body);
  914. $this->assert(!isset($node_current_revision->body[LANGUAGE_NONE]), t('No field data in LANGUAGE_NONE found.'));
  915. $node_previous_revision = current(entity_load('node', FALSE, array('vid' => ($node->vid - 1)), TRUE));
  916. $this->assert(isset($node_previous_revision->body['en']), t('Found field data in English as expected.'));
  917. $this->assertEqual($node_previous_revision->body['en'][0]['value'], $node_body);
  918. $this->assert(!isset($node_previous_revision->body[LANGUAGE_NONE]), t('No field data in LANGUAGE_NONE found.'));
  919. // Disable translation for field_body.
  920. $this->drupalGet('admin/structure/types/manage/page/fields/body');
  921. $this->clickLink('Disable translation');
  922. $this->drupalPost(NULL, array(), t('Confirm'));
  923. // Disable translation for field body and check field reverse migration on
  924. // all revisions.
  925. $node_current_revision = current(entity_load('node', FALSE, array('vid' => $node->vid), TRUE));
  926. $this->assert(isset($node_current_revision->body[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.'));
  927. $this->assertEqual($node_current_revision->body[LANGUAGE_NONE][0]['value'], $node_body);
  928. $this->assert(!isset($node_current_revision->body['en']), t('No field data in English found.'));
  929. $node_previous_revision = current(entity_load('node', FALSE, array('vid' => ($node->vid - 1)), TRUE));
  930. $this->assert(isset($node_previous_revision->body[LANGUAGE_NONE]), t('Found field data in LANGUAGE_NONE as expected.'));
  931. $this->assertEqual($node_previous_revision->body[LANGUAGE_NONE][0]['value'], $node_body);
  932. $this->assert(!isset($node_previous_revision->body['en']), t('No field data in English found.'));
  933. }
  934. }
  935. /**
  936. * Tests for the taxonomy autocomplete translation modes.
  937. */
  938. class EntityTranslationTaxonomyAutocompleteTestCase extends EntityTranslationTestCase {
  939. /**
  940. * Returns the test information.
  941. */
  942. public static function getInfo() {
  943. return array(
  944. 'name' => 'Entity translation taxonomy autocomplete',
  945. 'description' => 'Tests for the taxonomy autocomplete translation modes.',
  946. 'group' => 'Entity translation',
  947. 'dependencies' => array('title'),
  948. );
  949. }
  950. /**
  951. * {@inheritdoc}
  952. */
  953. function setUp() {
  954. parent::setUp('locale', 'entity_translation', 'taxonomy', 'title');
  955. $this->login($this->getAdminUser(array(
  956. 'administer taxonomy',
  957. 'administer entity translation',
  958. )));
  959. $this->addLanguage('en');
  960. $this->addLanguage('it');
  961. $this->addLanguage('fr');
  962. $this->enableUrlLanguageDetection();
  963. $this->configureVocabulary();
  964. $this->configureContentType();
  965. }
  966. /**
  967. * Makes the "Tags" vocabulary translatable.
  968. */
  969. function configureVocabulary() {
  970. $edit = array(
  971. 'entity_translation_entity_types[taxonomy_term]' => TRUE,
  972. );
  973. $this->drupalPost('admin/config/regional/entity_translation', $edit, t('Save configuration'));
  974. $edit = array(
  975. 'entity_translation_taxonomy' => TRUE,
  976. );
  977. $this->drupalPost('admin/structure/taxonomy/tags/edit', $edit, t('Save'));
  978. $edit = array(
  979. 'enabled' => TRUE,
  980. );
  981. $this->drupalPost('admin/structure/taxonomy/tags/fields/replace/name', $edit, t('Save settings'));
  982. $edit = array(
  983. 'enabled' => TRUE,
  984. );
  985. $this->drupalPost('admin/structure/taxonomy/tags/fields/replace/description', $edit, t('Save settings'));
  986. }
  987. /**
  988. * {@inheritdoc}
  989. */
  990. function configureContentType() {
  991. parent::configureContentType();
  992. // Create an untranslatable term reference field with unlimited cardinality.
  993. $edit = array(
  994. 'fields[_add_new_field][label]' => 'Test tags',
  995. 'fields[_add_new_field][field_name]' => 'test_tags',
  996. 'fields[_add_new_field][type]' => 'taxonomy_term_reference',
  997. 'fields[_add_new_field][widget_type]' => 'taxonomy_autocomplete',
  998. );
  999. $this->drupalPost('admin/structure/types/manage/page/fields', $edit, t('Save'));
  1000. $edit = array(
  1001. 'field[settings][allowed_values][0][vocabulary]' => 'tags',
  1002. );
  1003. $this->drupalPost('admin/structure/types/manage/page/fields/field_test_tags/field-settings', $edit, t('Save field settings'));
  1004. // Verify the in-place translation option is available.
  1005. $this->drupalGet('admin/structure/types/manage/page/fields/field_test_tags');
  1006. $this->assertRaw(t('Enable in-place translation of terms'));
  1007. $edit = array(
  1008. 'field[cardinality]' => FIELD_CARDINALITY_UNLIMITED,
  1009. );
  1010. $this->drupalPost(NULL, $edit, t('Save settings'));
  1011. // Ensure entity info is up-to-date.
  1012. drupal_flush_all_caches();
  1013. }
  1014. /**
  1015. * Enables in-place translation.
  1016. */
  1017. function enableInPlaceTranslation() {
  1018. $edit = array(
  1019. 'instance[settings][entity_translation_taxonomy_autocomplete_translate]' => TRUE,
  1020. );
  1021. $this->drupalPost('admin/structure/types/manage/page/fields/field_test_tags', $edit, t('Save settings'));
  1022. }
  1023. /**
  1024. * Tests that in-place translation works as expected.
  1025. */
  1026. function testInPlaceTranslation() {
  1027. $this->enableInPlaceTranslation();
  1028. $this->login($this->getTranslatorUser(array(
  1029. 'administer taxonomy',
  1030. )));
  1031. $values = array(
  1032. 'Red' => 'Rosso',
  1033. 'Green' => 'Verde',
  1034. 'Blue' => 'Blu',
  1035. );
  1036. // Create an English node with a few new tags.
  1037. $edit = array(
  1038. 'title' => 'Test 1',
  1039. 'field_test_tags[' . LANGUAGE_NONE . ']' => implode(', ', array_keys($values)),
  1040. 'language' => 'en',
  1041. );
  1042. $this->drupalPost('node/add/page', $edit, t('Save'));
  1043. $node = $this->drupalGetNodeByTitle($edit['title']);
  1044. // Create an Italian translation and translate the English tags.
  1045. $this->drupalGet('node/' . $node->nid . '/translate');
  1046. $this->clickLink('add', 1);
  1047. $edit = array();
  1048. foreach (array_values($values) as $delta => $value) {
  1049. $edit['field_test_tags[' . LANGUAGE_NONE . '][' . $delta . ']'] = $value;
  1050. }
  1051. $this->drupalPost(NULL, $edit, t('Save'));
  1052. // Verify that the Italian values are correctly stored/displayed.
  1053. foreach ($values as $original => $translation) {
  1054. $this->assertRaw($translation);
  1055. }
  1056. // Verify that the original English values were correctly retained.
  1057. $this->drupalGet('node/' . $node->nid);
  1058. foreach ($values as $original => $translation) {
  1059. $this->assertRaw($original);
  1060. }
  1061. }
  1062. /**
  1063. * That the autocomplete works with translated terms.
  1064. */
  1065. function testTranslatedAutocomplete() {
  1066. $this->login($this->getTranslatorUser(array(
  1067. 'administer taxonomy',
  1068. )));
  1069. $vocabulary = taxonomy_vocabulary_machine_name_load('tags');
  1070. $entity_type = 'taxonomy_term';
  1071. $existing_values = array();
  1072. $translated_values = array(
  1073. 'en' => array(
  1074. 'Red' => 'Rosso',
  1075. 'Green' => 'Verde',
  1076. ),
  1077. 'it' => array(
  1078. 'Blu' => 'Blue',
  1079. ),
  1080. );
  1081. $langcodes = array_keys($translated_values);
  1082. // Create a few existing tags with different original language and translate
  1083. // them accordingly.
  1084. foreach ($translated_values as $langcode => $values) {
  1085. title_active_language($langcode);
  1086. $translation_langcode = current(array_diff($langcodes, array($langcode)));
  1087. foreach ($values as $original => $translation) {
  1088. $term = (object) array(
  1089. 'vid' => $vocabulary->vid,
  1090. 'vocabulary_machine_name' => $vocabulary->machine_name,
  1091. 'name' => $original,
  1092. 'name_field' => array(
  1093. $langcode => array(array('value' => $original)),
  1094. $translation_langcode => array(array('value' => $translation)),
  1095. ),
  1096. );
  1097. $translation = array(
  1098. 'language' => $translation_langcode,
  1099. 'source' => $langcode,
  1100. 'status' => TRUE,
  1101. );
  1102. $handler = entity_translation_get_handler($entity_type, $term);
  1103. $handler->setOriginalLanguage($langcode);
  1104. $handler->initTranslations();
  1105. $handler->setTranslation($translation);
  1106. taxonomy_term_save($term);
  1107. $existing_values[$term->name_field['en'][0]['value']] = $term->name_field['it'][0]['value'];
  1108. }
  1109. }
  1110. // Verify that the English autocomplete route returns results for terms
  1111. // originally created in English.
  1112. $this->autocompleteGet('en', 'Re');
  1113. $this->assertRaw('Red');
  1114. $this->assertRaw('Green');
  1115. // Verify that the English autocomplete route returns results for terms
  1116. // translated into English.
  1117. $this->autocompleteGet('en', 'Blu');
  1118. $this->assertRaw('Blue');
  1119. // Verify that the Italian autocomplete route returns results for terms
  1120. // originally created in Italian.
  1121. $this->autocompleteGet('it', 'Blu');
  1122. $this->assertRaw('Blu');
  1123. $this->assertNoRaw('Blue');
  1124. // Verify that the Italian autocomplete route returns results for terms
  1125. // translated into Italian.
  1126. $this->autocompleteGet('it', 'R');
  1127. $this->assertRaw('Rosso');
  1128. $this->assertRaw('Verde');
  1129. // Verify that existing tags are correctly referenced and new tags are
  1130. // correctly created, when saving an English node.
  1131. $new_values = array(
  1132. 'Cyan' => 'Ciano',
  1133. 'Magenta' => 'Magenta',
  1134. 'Yellow' => 'Giallo',
  1135. 'Black' => 'Nero',
  1136. );
  1137. $all_values = $existing_values + $new_values;
  1138. $edit = array(
  1139. 'title' => 'Test 1',
  1140. 'field_test_tags[' . LANGUAGE_NONE . ']' => implode(', ', array_keys($all_values)),
  1141. 'language' => 'en',
  1142. );
  1143. $this->drupalPost('node/add/page', $edit, t('Save'));
  1144. foreach ($all_values as $original => $translation) {
  1145. $this->assertRaw($original);
  1146. }
  1147. // Verify that existing translated tags are correctly referenced and new
  1148. // tags are correctly created, when translated the node into Italian.
  1149. $node = $this->drupalGetNodeByTitle($edit['title']);
  1150. $this->drupalGet('node/' . $node->nid . '/translate');
  1151. $this->clickLink('add', 1);
  1152. $edit = array(
  1153. 'field_test_tags[' . LANGUAGE_NONE . ']' => implode(', ', $all_values),
  1154. );
  1155. $this->drupalPost(NULL, $edit, t('Save'));
  1156. foreach ($all_values as $original => $translation) {
  1157. $this->assertRaw($translation);
  1158. }
  1159. // Verify that existing (translated) tags were preserved, while new Italian
  1160. // tags replaced the corresponding English versions.
  1161. $this->drupalGet('node/' . $node->nid);
  1162. foreach ($existing_values as $original => $translation) {
  1163. $this->assertRaw($original);
  1164. }
  1165. foreach ($new_values as $original => $translation) {
  1166. $this->assertRaw($translation);
  1167. }
  1168. }
  1169. /**
  1170. * Performs a GET request to the autocomplete path.
  1171. *
  1172. * @param string $langcode
  1173. * The language to use to query results.
  1174. * @param string $query
  1175. * The search query string.
  1176. */
  1177. protected function autocompleteGet($langcode, $query) {
  1178. $path = 'entity_translation/taxonomy_term/autocomplete/' . $langcode . '/field_test_tags/' . $query;
  1179. $languages = language_list();
  1180. $this->drupalGet($path, array('language' => $languages[$langcode]));
  1181. }
  1182. }