wpml.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. <?php
  2. if ( ! defined( 'ABSPATH' ) ) {
  3. exit; // Exit if accessed directly
  4. }
  5. if ( ! class_exists( 'ACF_WPML_Compatibility' ) ) :
  6. class ACF_WPML_Compatibility {
  7. /**
  8. * __construct
  9. *
  10. * Sets up the class functionality.
  11. *
  12. * @date 23/06/12
  13. * @since 3.1.8
  14. *
  15. * @param void
  16. * @return void
  17. */
  18. function __construct() {
  19. // global
  20. global $sitepress;
  21. // update settings
  22. acf_update_setting( 'default_language', $sitepress->get_default_language() );
  23. acf_update_setting( 'current_language', $sitepress->get_current_language() );
  24. // localize data
  25. acf_localize_data(
  26. array(
  27. 'language' => $sitepress->get_current_language(),
  28. )
  29. );
  30. // switch lang during AJAX action
  31. add_action( 'acf/verify_ajax', array( $this, 'verify_ajax' ) );
  32. // prevent 'acf-field' from being translated
  33. add_filter( 'get_translatable_documents', array( $this, 'get_translatable_documents' ) );
  34. // check if 'acf-field-group' is translatable
  35. if ( $this->is_translatable() ) {
  36. // actions
  37. add_action( 'acf/upgrade_500_field_group', array( $this, 'upgrade_500_field_group' ), 10, 2 );
  38. add_action( 'icl_make_duplicate', array( $this, 'icl_make_duplicate' ), 10, 4 );
  39. // filters
  40. add_filter( 'acf/settings/save_json', array( $this, 'settings_save_json' ) );
  41. add_filter( 'acf/settings/load_json', array( $this, 'settings_load_json' ) );
  42. }
  43. }
  44. /**
  45. * is_translatable
  46. *
  47. * Returns true if the acf-field-group post type is translatable.
  48. * Also adds compatibility with ACF4 settings
  49. *
  50. * @date 10/04/2015
  51. * @since 5.2.3
  52. *
  53. * @param void
  54. * @return bool
  55. */
  56. function is_translatable() {
  57. // global
  58. global $sitepress;
  59. // vars
  60. $post_types = $sitepress->get_setting( 'custom_posts_sync_option' );
  61. // return false if no post types
  62. if ( ! acf_is_array( $post_types ) ) {
  63. return false;
  64. }
  65. // prevent 'acf-field' from being translated
  66. if ( ! empty( $post_types['acf-field'] ) ) {
  67. $post_types['acf-field'] = 0;
  68. $sitepress->set_setting( 'custom_posts_sync_option', $post_types );
  69. }
  70. // when upgrading to version 5, review 'acf' setting
  71. // update 'acf-field-group' if 'acf' is translatable, and 'acf-field-group' does not yet exist
  72. if ( ! empty( $post_types['acf'] ) && ! isset( $post_types['acf-field-group'] ) ) {
  73. $post_types['acf-field-group'] = 1;
  74. $sitepress->set_setting( 'custom_posts_sync_option', $post_types );
  75. }
  76. // return true if acf-field-group is translatable
  77. if ( ! empty( $post_types['acf-field-group'] ) ) {
  78. return true;
  79. }
  80. // return
  81. return false;
  82. }
  83. /**
  84. * upgrade_500_field_group
  85. *
  86. * Update the icl_translations table data when creating the field groups.
  87. *
  88. * @date 10/04/2015
  89. * @since 5.2.3
  90. *
  91. * @param array $field_group The new field group array.
  92. * @param object $ofg The old field group WP_Post object.
  93. * @return void
  94. */
  95. function upgrade_500_field_group( $field_group, $ofg ) {
  96. // global
  97. global $wpdb;
  98. // get translation rows (old acf4 and new acf5)
  99. $old_row = $wpdb->get_row(
  100. $wpdb->prepare(
  101. "SELECT * FROM {$wpdb->prefix}icl_translations WHERE element_type=%s AND element_id=%d",
  102. 'post_acf',
  103. $ofg->ID
  104. ),
  105. ARRAY_A
  106. );
  107. $new_row = $wpdb->get_row(
  108. $wpdb->prepare(
  109. "SELECT * FROM {$wpdb->prefix}icl_translations WHERE element_type=%s AND element_id=%d",
  110. 'post_acf-field-group',
  111. $field_group['ID']
  112. ),
  113. ARRAY_A
  114. );
  115. // bail early if no rows
  116. if ( ! $old_row || ! $new_row ) {
  117. return;
  118. }
  119. // create reference of old trid to new trid
  120. // trid is a simple int used to find associated objects
  121. if ( empty( $this->trid_ref ) ) {
  122. $this->trid_ref = array();
  123. }
  124. // update trid
  125. if ( isset( $this->trid_ref[ $old_row['trid'] ] ) ) {
  126. // this field group is a translation of another, update it's trid to match the previously inserted group
  127. $new_row['trid'] = $this->trid_ref[ $old_row['trid'] ];
  128. } else {
  129. // this field group is the first of it's translations, update the reference for future groups
  130. $this->trid_ref[ $old_row['trid'] ] = $new_row['trid'];
  131. }
  132. // update icl_translations
  133. // Row is created by WPML, and much easier to tweak it here due to the very complicated and nonsensical WPML logic
  134. $table = "{$wpdb->prefix}icl_translations";
  135. $data = array(
  136. 'trid' => $new_row['trid'],
  137. 'language_code' => $old_row['language_code'],
  138. );
  139. $where = array( 'translation_id' => $new_row['translation_id'] );
  140. $data_format = array( '%d', '%s' );
  141. $where_format = array( '%d' );
  142. // allow source_language_code to equal NULL
  143. if ( $old_row['source_language_code'] ) {
  144. $data['source_language_code'] = $old_row['source_language_code'];
  145. $data_format[] = '%s';
  146. }
  147. // update wpdb
  148. $result = $wpdb->update( $table, $data, $where, $data_format, $where_format );
  149. }
  150. /**
  151. * settings_save_json
  152. *
  153. * Modifies the json path.
  154. *
  155. * @date 19/05/2014
  156. * @since 5.0.0
  157. *
  158. * @param string $path The json save path.
  159. * @return string
  160. */
  161. function settings_save_json( $path ) {
  162. // bail early if dir does not exist
  163. if ( ! is_writable( $path ) ) {
  164. return $path;
  165. }
  166. // ammend
  167. $path = untrailingslashit( $path ) . '/' . acf_get_setting( 'current_language' );
  168. // make dir if does not exist
  169. if ( ! file_exists( $path ) ) {
  170. mkdir( $path, 0777, true );
  171. }
  172. // return
  173. return $path;
  174. }
  175. /**
  176. * settings_load_json
  177. *
  178. * Modifies the json path.
  179. *
  180. * @date 19/05/2014
  181. * @since 5.0.0
  182. *
  183. * @param string $path The json save path.
  184. * @return string
  185. */
  186. function settings_load_json( $paths ) {
  187. // loop
  188. if ( $paths ) {
  189. foreach ( $paths as $i => $path ) {
  190. $paths[ $i ] = untrailingslashit( $path ) . '/' . acf_get_setting( 'current_language' );
  191. }
  192. }
  193. // return
  194. return $paths;
  195. }
  196. /**
  197. * icl_make_duplicate
  198. *
  199. * description
  200. *
  201. * @date 26/02/2014
  202. * @since 5.0.0
  203. *
  204. * @param void
  205. * @return void
  206. */
  207. function icl_make_duplicate( $master_post_id, $lang, $postarr, $id ) {
  208. // bail early if not acf-field-group
  209. if ( $postarr['post_type'] != 'acf-field-group' ) {
  210. return;
  211. }
  212. // update the lang
  213. acf_update_setting( 'current_language', $lang );
  214. // duplicate field group specifying the $post_id
  215. acf_duplicate_field_group( $master_post_id, $id );
  216. // always translate independately to avoid many many bugs!
  217. // - translation post gets a new key (post_name) when origional post is saved
  218. // - local json creates new files due to changed key
  219. global $iclTranslationManagement;
  220. $iclTranslationManagement->reset_duplicate_flag( $id );
  221. }
  222. /**
  223. * verify_ajax
  224. *
  225. * Sets the correct language during AJAX requests.
  226. *
  227. * @type function
  228. * @date 7/08/2015
  229. * @since 5.2.3
  230. *
  231. * @param void
  232. * @return void
  233. */
  234. function verify_ajax() {
  235. // phpcs:disable WordPress.Security.NonceVerification.Recommended -- Verified elsewhere.
  236. // set the language for this AJAX request
  237. // this will allow get_posts to work as expected (load posts from the correct language)
  238. if ( isset( $_REQUEST['lang'] ) ) {
  239. global $sitepress;
  240. $sitepress->switch_lang( sanitize_text_field( $_REQUEST['lang'] ) );
  241. }
  242. // phpcs:enable WordPress.Security.NonceVerification.Recommended
  243. }
  244. /**
  245. * get_translatable_documents
  246. *
  247. * Removes 'acf-field' from the available post types for translation.
  248. *
  249. * @type function
  250. * @date 17/8/17
  251. * @since 5.6.0
  252. *
  253. * @param array $icl_post_types The array of post types.
  254. * @return array
  255. */
  256. function get_translatable_documents( $icl_post_types ) {
  257. // unset
  258. unset( $icl_post_types['acf-field'] );
  259. // return
  260. return $icl_post_types;
  261. }
  262. }
  263. acf_new_instance( 'ACF_WPML_Compatibility' );
  264. endif; // class_exists check