webform_localization.module 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. <?php
  2. /**
  3. * @file
  4. * Webform localization module.
  5. *
  6. * This module provides Localization Features to forms and questionnaires
  7. * generated by the Webform Module.
  8. *
  9. * i18n_string integration based on patch
  10. * http://drupal.org/node/245424#comment-5244256 by Calin Marian.
  11. *
  12. * Further development sponsored by Riot Games.
  13. *
  14. * @author German Martin <gmartin.php@gmail.com>
  15. */
  16. /**
  17. * Implements hook_help().
  18. */
  19. function webform_localization_help($section = 'admin/help#webform_localization', $arg = NULL) {
  20. $output = '';
  21. switch ($section) {
  22. case 'admin/help#webform_localization':
  23. $output = '<p>' . t('The Webform Localization module provides multilingual features to the Webform Module. Special options in the webform and component configuration let you enable different ways to manage translation of forms and questionnaires.') . '</p>';
  24. $output .= '<p>' . t('You can choose two different ways to manage localization that cover this scenarios:') . '</p>';
  25. $output .= '<p>' . t('A) <strong>If you want to keep a single webform across all nodes in a translation set:</strong><br />Use i18n_string integration to translate webform strings. This module expose webform properties, components and emails strings through the i18n module. All submissions results are related to the original node only.<br />(You have a "<em>localization by string translation</em>" fieldset in the form settings to enable this)') . '</p>';
  26. $output .= '<p>' . t('B)<strong> If you want to keep a webform per node per language but synchronized:</strong><br />The entire webform structure is replicated when a translated node is created then you can customize it at will. You can add specific options or components per language and choose to keep sync: webform properties, components properties, roles and emails recipients. In this scenario make no sense of having results attached to one node since each webform could have a different structure with only a few components in sync.<br />(You have a "<em>localization by sync</em>" fieldset in the form settings to enable this)') . '</p>';
  27. break;
  28. }
  29. return $output;
  30. }
  31. /**
  32. * Implements hook_i18n_string_info().
  33. */
  34. function webform_localization_i18n_string_info() {
  35. $groups['webform'] = array(
  36. 'title' => t('Webform Localization'),
  37. 'description' => t('Localizable properties of webforms, like title, select options, and others.'),
  38. // This group doesn't have strings with format.
  39. 'format' => FALSE,
  40. // This group cannot list all strings.
  41. 'list' => FALSE,
  42. 'refresh callback' => 'webform_localization_i18n_string_refresh',
  43. );
  44. return $groups;
  45. }
  46. /**
  47. * Update / create / delete translation source for components.
  48. *
  49. * Refresh callback that regenerates all the translatable poperties of the
  50. * components of the matching webforms configuration.
  51. */
  52. function webform_localization_i18n_string_refresh() {
  53. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  54. // In case updating before UUID support.
  55. if (module_exists('uuid') && !variable_get('webform_localization_using_uuid', FALSE)) {
  56. webform_localization_uuid_update_strings(FALSE);
  57. }
  58. // Get components configured as translatable.
  59. $query = db_select('webform_component', 'wc');
  60. $query->fields('wc');
  61. $query->condition('wl.expose_strings', 0, '>');
  62. $query->innerJoin('webform_localization', 'wl', 'wc.nid = wl.nid');
  63. $components = $query->execute()->fetchAll();
  64. foreach ($components as $component) {
  65. $component = (array) $component;
  66. $component['extra'] = unserialize($component['extra']);
  67. webform_localization_component_update_translation_strings($component);
  68. $component['extra'] = serialize($component['extra']);
  69. drupal_write_record('webform_component', $component, array('nid', 'cid'));
  70. }
  71. // Get emails configured as translatable.
  72. $query = db_select('webform_localization', 'wl');
  73. $query->fields('wl', array('nid'));
  74. $query->condition('wl.expose_strings', 0, '>');
  75. $nid_list = $query->execute()->fetchAllAssoc('nid');
  76. // @todo: Find a more eficient way to manage webform translatable properties.
  77. $nodes = node_load_multiple(array_keys($nid_list));
  78. module_load_include('inc', 'webform_localization', 'includes/webform_localization.sync');
  79. foreach ($nid_list as $nid => $value) {
  80. $emails = _webform_localization_emails_load($nid);
  81. webform_localization_emails_translation_string_refresh($emails, $nid);
  82. $node = $nodes[$nid];
  83. webform_localization_translate_strings($node, TRUE);
  84. }
  85. /**
  86. * NOTE: Delete string for webforms that has disabled i18n translation.
  87. * This is the only moment when we deleted translation for disabled webforms.
  88. * This way we provide the feature to temporally disable the webform i18n
  89. * string without losing custom translated texts.
  90. */
  91. webform_localization_delete_all_strings();
  92. return TRUE;
  93. }
  94. /**
  95. * Implements hook_webform_component_insert().
  96. */
  97. function webform_localization_webform_component_insert($component) {
  98. // Gets webform localization options that match this node ID.
  99. $wl_options = webform_localization_get_config($component['nid']);
  100. // Create translation source for i18n_string for all the translatable
  101. // poperties.
  102. if ($wl_options['expose_strings']) {
  103. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  104. webform_localization_component_update_translation_strings($component);
  105. }
  106. if ($wl_options['sync_components'] && _webform_localization_sync()) {
  107. // Turn Off Sync.
  108. _webform_localization_sync(FALSE);
  109. // Get all versions of the node.
  110. $node = node_load($component['nid']);
  111. $translations = translation_node_get_translations($node->tnid);
  112. if ($translations) {
  113. unset($translations[$node->language]);
  114. foreach ($translations as $trans_c) {
  115. $new_component = $component;
  116. $new_component['nid'] = $trans_c->nid;
  117. webform_component_insert($new_component);
  118. }
  119. }
  120. // Turn On Sync.
  121. _webform_localization_sync(TRUE);
  122. }
  123. }
  124. /**
  125. * Implements hook_webform_component_presave().
  126. */
  127. function webform_localization_webform_component_presave(&$component) {
  128. // If this is an insert, skip handling as this is handled by
  129. // hook_webform_component_insert().
  130. if (empty($component['cid'])) {
  131. return;
  132. }
  133. // Gets webform localization options that match this node ID.
  134. $wl_options = webform_localization_get_config($component['nid']);
  135. // Create translation source for i18n_string for all the translatable
  136. // poperties.
  137. if ($wl_options['expose_strings']) {
  138. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  139. webform_localization_component_update_translation_strings($component);
  140. }
  141. if ($wl_options['sync_components'] && _webform_localization_sync()) {
  142. // Turn Off Sync.
  143. _webform_localization_sync(FALSE);
  144. module_load_include('inc', 'webform_localization', 'includes/webform_localization.component.sync');
  145. // Get all versions of the component across all translations.
  146. $translations = webform_localization_component_get_translations($component);
  147. unset($translations[$component['nid']]);
  148. // Sync the changed component with it's translations versions.
  149. webform_localization_component_sync($component, $translations);
  150. foreach ($translations as $trans_c) {
  151. webform_component_update($trans_c);
  152. }
  153. // Turn On Sync.
  154. _webform_localization_sync(TRUE);
  155. }
  156. }
  157. /**
  158. * Implements hook_webform_component_delete().
  159. */
  160. function webform_localization_webform_component_delete($component) {
  161. // Gets webform localization options that match this node ID.
  162. $wl_options = webform_localization_get_config($component['nid']);
  163. if ($wl_options['expose_strings']) {
  164. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  165. webform_localization_component_delete_translation_strings($component);
  166. }
  167. if ($wl_options['sync_components'] && _webform_localization_sync()) {
  168. module_load_include('inc', 'webform_localization', 'includes/webform_localization.component.sync');
  169. webform_localization_synchronizable_properties_delete($component);
  170. // Turn Off Sync.
  171. _webform_localization_sync(FALSE);
  172. // Get all versions of the node.
  173. $node = node_load($component['nid']);
  174. $translations = translation_node_get_translations($node->tnid);
  175. unset($translations[$node->language]);
  176. foreach ($translations as $trans_c) {
  177. $component_version = webform_localization_component_load($trans_c->nid, $component['cid']);
  178. webform_component_delete($trans_c, $component_version);
  179. }
  180. // Turn On Sync.
  181. _webform_localization_sync(TRUE);
  182. }
  183. }
  184. /**
  185. * Implements hook_node_view().
  186. */
  187. function webform_localization_node_view($node, $view_mode) {
  188. if (!in_array($node->type, webform_variable_get('webform_node_types'))) {
  189. return;
  190. }
  191. // Select all webforms that match the localization configuration.
  192. $query = db_select('webform', 'w');
  193. $query->innerJoin('webform_localization', 'wl', 'w.nid = wl.nid');
  194. $query->fields('w', array('nid'));
  195. $query->condition('wl.single_webform', 0, '<>');
  196. $query->condition('wl.single_webform', $node->tnid, '=');
  197. $query->condition('w.nid', $node->nid, '<>');
  198. $result = $query->execute()->fetchField();
  199. if ($result) {
  200. /**
  201. * NOTE:
  202. * Perhaps not most eficient way.. a possible alternative
  203. * @todo rewrite the webform load and view process as a
  204. * independent function to reuse.
  205. */
  206. $source_node = node_load($result);
  207. // We replace the webform with the node translation source.
  208. $node->webform = $source_node->webform;
  209. // This fool webform_node_view to avoid errors with drafts in between pages.
  210. $translation_nid = $node->nid;
  211. if (($node->webform['allow_draft'] || $node->webform['auto_save']) && $user->uid != 0) {
  212. $node->nid = $source_node->nid;
  213. }
  214. // Call node view implementation to update the $node->content.
  215. webform_node_view($node, $view_mode);
  216. // Reset the nid if we used the drafts fix.
  217. $node->nid = $translation_nid;
  218. }
  219. }
  220. /**
  221. * Implements hook_node_load().
  222. */
  223. function webform_localization_node_load($nodes, $types) {
  224. // Quick check to see if we need to do anything at all for these nodes.
  225. $webform_types = webform_variable_get('webform_node_types');
  226. if (count(array_intersect($types, $webform_types)) == 0) {
  227. return;
  228. }
  229. foreach ($nodes as $nid => &$node) {
  230. // Gets webform localization options that match this node ID.
  231. $wl_options = webform_localization_get_config($nid);
  232. if ($wl_options['expose_strings']) {
  233. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  234. // Translate custom strings.
  235. webform_localization_translate_strings($node);
  236. webform_localization_email_translate_strings($node);
  237. }
  238. }
  239. }
  240. /**
  241. * Implements hook_webform_submission_update().
  242. */
  243. function webform_localization_webform_submission_insert($node, $submission) {
  244. /**
  245. * NOTE:
  246. * We have 2 options here: to use the node language or the language of
  247. * the page... for now make more sense use the node as language source
  248. */
  249. $language = $node->language;
  250. // Update language field when a submission is updated.
  251. db_update('webform_submissions')
  252. ->fields(array(
  253. 'language' => $language,
  254. ))
  255. ->condition('sid', $submission->sid)
  256. ->execute();
  257. }
  258. /**
  259. * Implements hook_webform_submission_load().
  260. */
  261. function webform_localization_webform_submission_load(&$submissions) {
  262. if(empty($submissions)) {
  263. return;
  264. }
  265. $query = db_select('webform_submissions', 's');
  266. $query->fields('s', array('language', 'sid'));
  267. $query->condition('s.sid', array_keys($submissions), 'IN');
  268. $s_languages = $query->execute()->fetchAllAssoc('sid');
  269. foreach ($submissions as $sid => $submission) {
  270. $submissions[$sid]->language = $s_languages[$sid]->language;
  271. }
  272. }
  273. /**
  274. * Implements hook_node_delete().
  275. */
  276. function webform_localization_node_delete($node) {
  277. if (!in_array($node->type, webform_variable_get('webform_node_types'))
  278. || empty($node->webform['components'])) {
  279. return;
  280. }
  281. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  282. // Deletion of webform and emails translatable properties.
  283. webform_localization_delete_translate_strings($node);
  284. // Delete webform localization configuration record.
  285. db_delete('webform_localization')->condition('nid', $node->nid)->execute();
  286. }
  287. /**
  288. * Implements hook_webform_component_render_alter().
  289. */
  290. function webform_localization_webform_component_render_alter(&$element, $component) {
  291. // Gets webform localization options that match this node ID.
  292. $wl_options = webform_localization_get_config($component['nid']);
  293. // Translate the translatable properties.
  294. if ($wl_options['expose_strings']) {
  295. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  296. _webform_localization_translate_component($element, $component);
  297. }
  298. }
  299. /**
  300. * Implements hook_webform_component_display_alter().
  301. */
  302. function webform_localization_webform_component_display_alter(&$display_element, $component) {
  303. // Gets webform localization options that match this node ID.
  304. $wl_options = webform_localization_get_config($component['nid']);
  305. // Translate the translatable properties.
  306. if ($wl_options['expose_strings']) {
  307. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  308. _webform_localization_translate_component($display_element, $component);
  309. }
  310. }
  311. /**
  312. * Implements hook_webform_analysis_component_data_alter().
  313. */
  314. function webform_localization_webform_analysis_component_data_alter(&$data, $node, &$component) {
  315. // Gets webform localization options that match this node ID.
  316. $wl_options = webform_localization_get_config($node->nid);
  317. // Translate the translatable properties.
  318. if ($wl_options['expose_strings']) {
  319. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  320. _webform_localization_translate_analysis_component($data, $component);
  321. }
  322. }
  323. /**
  324. * Implements hook_form_FORM_ID_alter().
  325. *
  326. * Add specific localization options to Webform Configure Form
  327. */
  328. function webform_localization_form_webform_configure_form_alter(&$form, &$form_state, $form_id) {
  329. // Gets webform localization options that match this node ID.
  330. $webform_localization_options = webform_localization_get_config($form['nid']['#value']);
  331. if ($webform_localization_options['expose_strings']) {
  332. // Avoid caching for translatable element values.
  333. entity_get_controller('node')->resetCache(array($form['nid']['#value']));
  334. $form['#node'] = node_load($form['nid']['#value']);
  335. $form['submission']['confirmation']['#default_value'] = $form['#node']->webform['confirmation'];
  336. if ($form['submission']['redirection']['redirect']['#default_value'] == 'url') {
  337. $form['submission']['redirection']['redirect_url']['#default_value'] = $form['#node']->webform['redirect_url'];
  338. }
  339. $form['advanced']['submit_text']['#default_value'] = $form['#node']->webform['submit_text'];
  340. }
  341. $single_webform = 0;
  342. if ($webform_localization_options['single_webform'] > 0) {
  343. $single_webform = 1;
  344. }
  345. $form['localization_by_string'] = array(
  346. '#type' => 'fieldset',
  347. '#title' => t('Localization by String Translation'),
  348. '#collapsible' => TRUE,
  349. '#collapsed' => TRUE,
  350. '#weight' => -6,
  351. '#description' => '<p>' . t('This feature implements an i18n_string integration and let you keep a single webform across several nodes in a translation set.This feature is useful when you want <em>one single webform / node acrossdifferent languages</em>.', array('html' => TRUE)) . '</p>',
  352. );
  353. $form['localization_by_string']['expose_strings'] = array(
  354. '#type' => 'checkbox',
  355. '#title' => t('Expose webform component strings suitable for translation.'),
  356. '#default_value' => $webform_localization_options['expose_strings'],
  357. '#description' => '<p>' . t('Use the i18n module to translate webform component strings.', array('html' => TRUE)) . '</p>',
  358. );
  359. $form['localization_by_string']['single_webform'] = array(
  360. '#type' => 'checkbox',
  361. '#title' => t('Keep a single webform across a translation set.'),
  362. '#default_value' => $single_webform,
  363. '#description' => '<p>' . t('When you use the i18n module to translate webform component strings, you may like to keep a single webform to attach on each node from a translation set.', array('html' => TRUE)) . '</p>',
  364. );
  365. $form['localization_by_sync'] = array(
  366. '#type' => 'fieldset',
  367. '#title' => t('Localization by Sync'),
  368. '#collapsible' => TRUE,
  369. '#collapsed' => TRUE,
  370. '#weight' => -5,
  371. '#description' => '<p>' . t('This feature let you have a webform per language and keeping all of them synchronized at different levels.You can choose to synchronize webform properties, submission roles, e-mail recipients and component properties.This feature is useful when you want <em>a different webform /node per language</em> but keeping some settings synchronized.', array('html' => TRUE)) . '</p>',
  372. );
  373. $form['localization_by_sync']['webform_properties_header'] = array(
  374. '#type' => 'markup',
  375. '#prefix' => t('Synchronize webform properties across node translations.'),
  376. '#markup' => '<div class="description"><p>' . t('You can choose to synchronize specific properties of the webform.') . '</p></div>',
  377. );
  378. $form['localization_by_sync']['webform_properties'] = array(
  379. '#type' => 'checkboxes',
  380. '#options' => $webform_localization_options['webform_properties_structure'],
  381. '#default_value' => $webform_localization_options['webform_properties'],
  382. '#description' => '',
  383. );
  384. $form['localization_by_sync']['sync_components'] = array(
  385. '#type' => 'checkbox',
  386. '#title' => t('Synchronize webform components across node translations.'),
  387. '#default_value' => $webform_localization_options['sync_components'],
  388. '#description' => '<p>' . t('Copy the entire webform structure when a node is translated and synchronize changes on selected components properties.', array('html' => TRUE)) . '</p>',
  389. );
  390. $form['localization_by_sync']['sync_roles'] = array(
  391. '#type' => 'checkbox',
  392. '#title' => t('Synchronize webform submission access roles across node translations.'),
  393. '#default_value' => $webform_localization_options['sync_roles'],
  394. '#description' => '<p>' . t('Keep the roles that can submit a webform synchronized in a translation set.') . '</p>',
  395. );
  396. $form['localization_by_sync']['sync_emails'] = array(
  397. '#type' => 'checkbox',
  398. '#title' => t('Synchronize webform e-mail recipients across node translations.'),
  399. '#default_value' => $webform_localization_options['sync_emails'],
  400. '#description' => '<p>' . t('Keep the webform e-mail recipients synchronized in a translation set.') . '</p>',
  401. );
  402. $form['#submit'][] = '_webform_localization_webform_configure_form_submit';
  403. if ($webform_localization_options['expose_strings']) {
  404. // Using i18n string we need to tweak values before submit.
  405. $submit_array = $form['#submit'];
  406. array_unshift($submit_array, '_webform_localization_webform_configure_form_submit_i18n_tweaks');
  407. $form['#submit'] = $submit_array;
  408. }
  409. }
  410. /**
  411. * Handle specific localization options in Webform Configure Form.
  412. */
  413. function _webform_localization_webform_configure_form_submit($form, &$form_state) {
  414. $webform_properties = $form_state['values']['webform_properties'];
  415. foreach ($webform_properties as $key => $value) {
  416. if (!is_string($value)) {
  417. unset($webform_properties[$key]);
  418. }
  419. }
  420. if (count($webform_properties) == 0) {
  421. $webform_properties = '';
  422. }
  423. else {
  424. $webform_properties = serialize($webform_properties);
  425. }
  426. if ($form_state['values']['single_webform'] > 0) {
  427. $form_state['values']['single_webform'] = $form_state['values']['nid'];
  428. }
  429. $webform_localization_options = array(
  430. 'nid' => $form_state['values']['nid'],
  431. 'expose_strings' => $form_state['values']['expose_strings'],
  432. 'sync_components' => $form_state['values']['sync_components'],
  433. 'sync_roles' => $form_state['values']['sync_roles'],
  434. 'sync_emails' => $form_state['values']['sync_emails'],
  435. 'single_webform' => $form_state['values']['single_webform'],
  436. 'webform_properties' => $webform_properties,
  437. );
  438. $prev_options = webform_localization_get_config($form_state['values']['nid']);
  439. if (isset($prev_options['no_persistent'])) {
  440. drupal_write_record('webform_localization', $webform_localization_options);
  441. }
  442. else {
  443. drupal_write_record('webform_localization', $webform_localization_options, array('nid'));
  444. }
  445. module_load_include('inc', 'webform_localization', 'includes/webform_localization.sync');
  446. webform_localization_webform_properties_sync($form_state['values']['nid']);
  447. $webform_localization_options = webform_localization_get_config($form_state['values']['nid']);
  448. if ($webform_localization_options['sync_roles']) {
  449. webform_localization_roles_sync($form_state['values']['nid']);
  450. }
  451. if ($webform_localization_options['expose_strings']) {
  452. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  453. webform_localization_update_translation_strings($form_state['values']);
  454. }
  455. }
  456. /**
  457. * Handle translated element tweaks in Webform Configure Form.
  458. */
  459. function _webform_localization_webform_configure_form_submit_i18n_tweaks($form, &$form_state) {
  460. global $language;
  461. $default_language = language_default();
  462. if ($default_language->language != $language->language) {
  463. // Webform Configure Form not in default language.
  464. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  465. $name = webform_localization_i18n_string_name($form['#node']->webform['nid'], 'confirmation');
  466. $string_source = i18n_string_get_string($name);
  467. $string_translation = $form_state['values']['confirmation']['value'];
  468. // We reset the source string value before saving the form.
  469. $form_state['values']['confirmation']['value'] = $string_source->get_string();
  470. // We save the translated string using i18n string.
  471. i18n_string_translation_update($name, $string_translation, $language->language);
  472. }
  473. }
  474. /**
  475. * Implements hook_form_FORM_ID_alter().
  476. *
  477. * Add a Submit function to handle localization features.
  478. */
  479. function webform_localization_form_webform_email_edit_form_alter(&$form, &$form_state, $form_id) {
  480. $form['#submit'][] = '_webform_localization_webform_email_edit_form_submit';
  481. }
  482. /**
  483. * Handle emails sync on individual email change.
  484. */
  485. function _webform_localization_webform_email_edit_form_submit($form, &$form_state) {
  486. $node = $form['#node'];
  487. $webform_localization_options = webform_localization_get_config($node->nid);
  488. if ($webform_localization_options['sync_emails']) {
  489. module_load_include('inc', 'webform_localization', 'includes/webform_localization.sync');
  490. webform_localization_emails_sync($node->nid);
  491. }
  492. if ($webform_localization_options['expose_strings']) {
  493. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  494. webform_localization_emails_update_translation_string($form_state['values'] + array('node' => $node));
  495. }
  496. }
  497. /**
  498. * Implements hook_form_FORM_ID_alter().
  499. *
  500. * Add a Submit function to handle sync feature.
  501. */
  502. function webform_localization_form_webform_email_delete_form_alter(&$form, &$form_state, $form_id) {
  503. $form['#submit'][] = '_webform_localization_webform_email_delete_form_submit';
  504. }
  505. /**
  506. * Handle emails localization cleanup / sync on email deletion.
  507. */
  508. function _webform_localization_webform_email_delete_form_submit($form, &$form_state) {
  509. $node = $form['#node'];
  510. $webform_localization_options = webform_localization_get_config($node->nid);
  511. if ($webform_localization_options['sync_emails']) {
  512. module_load_include('inc', 'webform_localization', 'includes/webform_localization.sync');
  513. webform_localization_emails_sync($node->nid);
  514. }
  515. if ($webform_localization_options['expose_strings']) {
  516. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  517. webform_localization_emails_delete_translation_string($form_state['values']['email']['eid'], $node->nid);
  518. }
  519. }
  520. /**
  521. * Implements hook_form_FORM_ID_alter().
  522. *
  523. * Add specific localization options to Webform Component Edit Form.
  524. */
  525. function webform_localization_form_webform_component_edit_form_alter(&$form, &$form_state, $form_id) {
  526. $component = $form_state['build_info']['args'][1];
  527. if (!isset($component['cid'])) {
  528. $component['cid'] = -1;
  529. }
  530. // Gets webform localization options that match this node ID.
  531. $webform_localization_options = webform_localization_get_config($component['nid']);
  532. if ($webform_localization_options['sync_components']) {
  533. module_load_include('inc', 'webform_localization', 'includes/webform_localization.component.sync');
  534. $select_options = webform_localization_synchronizable_properties($component);
  535. $form['localization'] = array(
  536. '#type' => 'fieldset',
  537. '#title' => t('Localization by Sync / Component settings'),
  538. '#collapsible' => TRUE,
  539. '#collapsed' => FALSE,
  540. '#weight' => -4,
  541. '#description' => t('Here you can specified what properties need to be sync for thiscomponent across the several nodes in a translation set. If youare seeing this means that you have enabled the <em>"Synchronizewebform components across node translations"</em> option in thewebform that contains this component.', array('html' => TRUE)),
  542. );
  543. $form['localization']['standar_properties'] = array(
  544. '#type' => 'checkboxes',
  545. '#title' => t('Select properties to synchronize across translations.'),
  546. '#options' => $select_options['standar'],
  547. '#default_value' => $select_options['standar_values'],
  548. '#description' => t('Common properties that applies to all types of components.'),
  549. );
  550. $form['localization']['extra_properties'] = array(
  551. '#type' => 'checkboxes',
  552. '#title' => t('Select especial properties to synchronize across translations.'),
  553. '#options' => $select_options['extra'],
  554. '#default_value' => $select_options['extra_values'],
  555. '#description' => t('Special properties that applies only for this type of component.'),
  556. );
  557. /**
  558. * NOTE:
  559. * First we save the sync options to know what to do with the changes.
  560. */
  561. array_unshift($form['#submit'], '_webform_localization_webform_component_edit_form_submit');
  562. }
  563. }
  564. /**
  565. * Handle specific localization options in Webform Component Edit Form.
  566. */
  567. function _webform_localization_webform_component_edit_form_submit($form, &$form_state) {
  568. module_load_include('inc', 'webform_localization', 'includes/webform_localization.component.sync');
  569. $options = array(
  570. 'nid' => $form_state['values']['nid'],
  571. 'cid' => $form_state['values']['cid'],
  572. 'type' => $form_state['values']['type'],
  573. 'standar_properties' => serialize($form_state['values']['localization']['standar_properties']),
  574. 'extra_properties' => serialize($form_state['values']['localization']['extra_properties']),
  575. );
  576. $prev_options = webform_localization_synchronizable_properties($options);
  577. if (isset($prev_options['no_persistent'])) {
  578. drupal_write_record('webform_component_localization', $options);
  579. }
  580. else {
  581. drupal_write_record('webform_component_localization', $options, array('nid', 'cid'));
  582. }
  583. // We reload cached configuration for this component.
  584. webform_localization_synchronizable_properties($options, TRUE);
  585. }
  586. /**
  587. * Implements hook_field_attach_prepare_translation_alter().
  588. */
  589. function webform_localization_field_attach_prepare_translation_alter(&$entity, $context) {
  590. if ($context['entity_type'] == 'node') {
  591. if (isset($context['source_entity']->webform)) {
  592. $webform_localization_options = webform_localization_get_config($context['source_entity']->nid);
  593. /**
  594. * Copy all Webform settings over to translated versions of this node
  595. * if the configuration match.
  596. */
  597. if ($webform_localization_options['sync_components']) {
  598. /**
  599. * NOTE:
  600. * Perhaps could be interesting to copy only specific properties
  601. * but for now the entire webform make more sense.
  602. */
  603. $entity->webform = $context['source_entity']->webform;
  604. }
  605. }
  606. }
  607. }
  608. /**
  609. * Gets webform localization options that match a node ID.
  610. *
  611. * @staticvar array $webform_localization_options
  612. * An array of webform localization options group by nid.
  613. * @param $nid
  614. * A node Id.
  615. * @param bool $clear_cache
  616. * A flag to force a database reading in case that properties are cached.
  617. *
  618. * @return array
  619. * Webform localization options that match the nid.
  620. */
  621. function webform_localization_get_config($nid, $clear_cache = FALSE) {
  622. static $webform_localization_options = array();
  623. if ($clear_cache || !isset($webform_localization_options[$nid])) {
  624. $defaults = array_keys(webform_node_defaults());
  625. $webform_properties = array();
  626. foreach ($defaults as $key) {
  627. $webform_properties[$key] = $key;
  628. }
  629. unset($webform_properties['components']);
  630. unset($webform_properties['roles']);
  631. unset($webform_properties['emails']);
  632. unset($webform_properties['record_exists']);
  633. // Select webform localization options that match this node ID.
  634. $options = db_select('webform_localization')
  635. ->fields('webform_localization')
  636. ->condition('nid', $nid, '=')
  637. ->execute()
  638. ->fetchAllAssoc('nid', PDO::FETCH_ASSOC);
  639. if (count($options) == 0) {
  640. $webform_localization_options[$nid] = array(
  641. 'nid' => $nid,
  642. 'expose_strings' => 0,
  643. 'single_webform' => 0,
  644. 'sync_components' => 0,
  645. 'sync_roles' => 0,
  646. 'sync_emails' => 0,
  647. 'webform_properties' => array(),
  648. 'webform_properties_structure' => $webform_properties,
  649. 'no_persistent' => TRUE,
  650. );
  651. }
  652. else {
  653. $options[$nid]['webform_properties_structure'] = $webform_properties;
  654. if (empty($options[$nid]['webform_properties'])) {
  655. $options[$nid]['webform_properties'] = array();
  656. }
  657. else {
  658. $options[$nid]['webform_properties'] = unserialize($options[$nid]['webform_properties']);
  659. }
  660. $webform_localization_options[$nid] = $options[$nid];
  661. }
  662. }
  663. return $webform_localization_options[$nid];
  664. }
  665. /**
  666. * Global switch to enable / disable syncing.
  667. *
  668. * This function also check whether we are synching at the moment.
  669. *
  670. * @return bool
  671. * TRUE if we need to run sync operations. FALSE during syncing
  672. * so we don't have recursion.
  673. */
  674. function _webform_localization_sync($status = NULL) {
  675. static $current = TRUE;
  676. if (isset($status)) {
  677. $current = $status;
  678. }
  679. return $current;
  680. }
  681. /**
  682. * Translate webform confirmation field.
  683. */
  684. function webform_localization_preprocess_webform_confirmation(&$vars) {
  685. if (empty($vars['node']->tnid)) {
  686. return;
  687. }
  688. // Select all webforms that match the localization configuration.
  689. $query = db_select('webform', 'w');
  690. $query->innerJoin('webform_localization', 'wl', 'w.nid = wl.nid');
  691. $query->fields('w', array('nid'));
  692. $query->condition('wl.single_webform', $vars['node']->tnid, '=');
  693. $query->condition('w.nid', $vars['node']->nid, '<>');
  694. $result = $query->execute()->fetchField();
  695. if ($result) {
  696. $source_node = node_load($result);
  697. // We replace the webform with the node translation source.
  698. $vars['node']->webform = $source_node->webform;
  699. }
  700. else {
  701. return;
  702. }
  703. $confirmation = check_markup($vars['node']->webform['confirmation'], $vars['node']->webform['confirmation_format'], '', TRUE);
  704. // Strip out empty tags added by WYSIWYG editors if needed.
  705. $vars['confirmation_message'] = drupal_strlen(trim(strip_tags($confirmation))) ? $confirmation : '';
  706. }
  707. /**
  708. * Implements hook_form_webform_client_form_alter().
  709. */
  710. function webform_localization_form_webform_client_form_alter(&$form, &$form_state, $form_id) {
  711. if (!isset($form['#node']->webform['nid'])) {
  712. return;
  713. }
  714. $webform_localization_options = webform_localization_get_config($form['#node']->webform['nid']);
  715. if ($webform_localization_options['single_webform']) {
  716. if (isset($form['details']['nid']['#value']) && $form['#node']->webform['nid'] == $form['#node']->tnid) {
  717. // We keep current language node nid.
  718. $form['details']['current_language_nid'] = array(
  719. '#type' => 'value',
  720. '#value' => $form['details']['nid']['#value'],
  721. );
  722. // Nid from the source webform for webform_validation.
  723. $form['details']['nid']['#value'] = $form['#node']->webform['nid'];
  724. }
  725. }
  726. }
  727. /**
  728. * Implements hook_modules_disabled().
  729. */
  730. function webform_localization_modules_disabled($modules) {
  731. if (in_array('uuid', $modules)) {
  732. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  733. webform_localization_uuid_update_strings(TRUE);
  734. }
  735. }
  736. /**
  737. * Implements hook_modules_enabled().
  738. */
  739. function webform_localization_modules_enabled($modules) {
  740. if (in_array('uuid', $modules)) {
  741. module_load_include('inc', 'webform_localization', 'includes/webform_localization.i18n');
  742. webform_localization_uuid_update_strings(FALSE);
  743. }
  744. }