PluginProbe
Polylang / 3.7.2
Polylang v3.7.2
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / modules / sync / admin-sync.php

admin-sync.php in Polylang 3.7.2, at modules/sync/admin-sync.php

249 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 /**
7 * Manages copy and synchronization of terms and post metas
8 *
9 * @since 1.2
10 */
11 class PLL_Admin_Sync extends PLL_Sync {
12 /**
13 * @var PLL_Admin_Links
14 */
15 private $links;
16
17 /**
18 * Constructor
19 *
20 * @since 1.2
21 *
22 * @param object $polylang The Polylang object.
23 */
24 public function __construct( &$polylang ) {
25 parent::__construct( $polylang );
26
27 $this->links = &$polylang->links;
28
29 add_filter( 'wp_insert_post_parent', array( $this, 'wp_insert_post_parent' ), 10, 3 );
30 add_filter( 'wp_insert_post_data', array( $this, 'wp_insert_post_data' ) );
31 add_filter( 'use_block_editor_for_post', array( $this, 'new_post_translation' ), 5000 ); // After content duplication.
32 }
33
34 /**
35 * Translates the post parent if it exists when using "Add new" (translation).
36 *
37 * @since 0.6
38 *
39 * @param int $post_parent Post parent ID.
40 * @param int $post_id Post ID, unused.
41 * @param array $postarr Array of parsed post data.
42 * @return int
43 */
44 public function wp_insert_post_parent( $post_parent, $post_id, $postarr ) {
45 $context_data = $this->links->get_data_from_new_post_translation_request( $postarr['post_type'] ?? '' );
46
47 if ( empty( $context_data ) ) {
48 return $post_parent;
49 }
50
51 // Make sure not to impact media translations created at the same time.
52 $parent_id = wp_get_post_parent_id( $context_data['from_post'] );
53
54 if ( empty( $parent_id ) ) {
55 return $post_parent;
56 }
57
58 $tr_parent = $this->model->post->get_translation( $parent_id, $context_data['new_lang'] );
59
60 if ( empty( $tr_parent ) ) {
61 return $post_parent;
62 }
63
64 return $tr_parent;
65 }
66
67 /**
68 * Copies menu order, comment, ping status and optionally the date when creating a new translation.
69 *
70 * @since 2.5
71 *
72 * @param array $data An array of slashed post data.
73 * @return array
74 */
75 public function wp_insert_post_data( $data ) {
76 $context_data = $this->links->get_data_from_new_post_translation_request( $data['post_type'] ?? '' );
77
78 if ( empty( $context_data ) ) {
79 return $data;
80 }
81
82 foreach ( array( 'menu_order', 'comment_status', 'ping_status' ) as $property ) {
83 $data[ $property ] = $context_data['from_post']->$property;
84 }
85
86 // Copy the date only if the synchronization is activated.
87 if ( in_array( 'post_date', $this->options['sync'], true ) ) {
88 $data['post_date'] = $context_data['from_post']->post_date;
89 $data['post_date_gmt'] = $context_data['from_post']->post_date_gmt;
90 }
91
92 return $data;
93 }
94
95 /**
96 * Copies post metas and taxonomies when using "Add new" (translation).
97 *
98 * @since 2.5
99 * @since 3.1 Use of use_block_editor_for_post filter instead of rest_api_init which is triggered too early in WP 5.8.
100 *
101 * @param bool $is_block_editor Whether the post can be edited or not.
102 * @return bool
103 */
104 public function new_post_translation( $is_block_editor ) {
105 global $post;
106 static $done = array();
107
108 if ( empty( $post ) ) {
109 return $is_block_editor;
110 }
111
112 $context_data = $this->links->get_data_from_new_post_translation_request( $post->post_type );
113
114 if ( empty( $context_data ) || ! empty( $done[ $context_data['from_post']->ID ] ) ) {
115 return $is_block_editor;
116 }
117
118 $lang = $this->model->get_language( $context_data['new_lang'] );
119
120 if ( empty( $lang ) ) {
121 return $is_block_editor;
122 }
123
124 $done[ $context_data['from_post']->ID ] = true; // Avoid a second duplication in the block editor. Using an array only to allow multiple phpunit tests.
125
126 $this->taxonomies->copy( $context_data['from_post']->ID, $post->ID, $lang->slug );
127 $this->post_metas->copy( $context_data['from_post']->ID, $post->ID, $lang->slug );
128
129 if ( is_sticky( $context_data['from_post']->ID ) ) {
130 stick_post( $post->ID );
131 }
132
133 return $is_block_editor;
134 }
135
136 /**
137 * Get post fields to synchronize.
138 *
139 * @since 2.4
140 *
141 * @param WP_Post $post Post object.
142 * @return array Fields to synchronize.
143 */
144 protected function get_fields_to_sync( $post ) {
145 global $wpdb;
146
147 $postarr = parent::get_fields_to_sync( $post );
148 $context_data = $this->links->get_data_from_new_post_translation_request( $post->post_type );
149
150 // For new drafts, save the date now otherwise it is overridden by WP. Thanks to JoryHogeveen. See #32.
151 if ( ! empty( $context_data ) && in_array( 'post_date', $this->options['sync'], true ) ) {
152 unset( $postarr['post_date'] );
153 unset( $postarr['post_date_gmt'] );
154
155 $wpdb->update(
156 $wpdb->posts,
157 array(
158 'post_date' => $context_data['from_post']->post_date,
159 'post_date_gmt' => $context_data['from_post']->post_date_gmt,
160 ),
161 array( 'ID' => $post->ID )
162 );
163 }
164
165 if ( isset( $GLOBALS['post_type'] ) ) {
166 $post_type = $GLOBALS['post_type'];
167 } elseif ( isset( $_REQUEST['post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
168 // 2nd case for quick edit.
169 $post_type = sanitize_key( $_REQUEST['post_type'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
170 }
171
172 // Make sure not to impact media translations when creating them at the same time as post
173 if ( in_array( 'post_parent', $this->options['sync'], true ) && ( ! isset( $post_type ) || $post_type !== $post->post_type ) ) {
174 unset( $postarr['post_parent'] );
175 }
176
177 return $postarr;
178 }
179
180 /**
181 * Synchronizes post fields in translations.
182 *
183 * @since 1.2
184 *
185 * @param int $post_id Post id.
186 * @param WP_Post $post Post object.
187 * @param int[] $translations Post translations.
188 */
189 public function pll_save_post( $post_id, $post, $translations ) {
190 parent::pll_save_post( $post_id, $post, $translations );
191
192 // Sticky posts
193 if ( in_array( 'sticky_posts', $this->options['sync'] ) ) {
194 $stickies = get_option( 'sticky_posts' );
195 if ( isset( $_REQUEST['sticky'] ) && 'sticky' === $_REQUEST['sticky'] ) { // phpcs:ignore WordPress.Security.NonceVerification
196 $stickies = array_merge( $stickies, array_values( $translations ) );
197 } else {
198 $stickies = array_diff( $stickies, array_values( $translations ) );
199 }
200 update_option( 'sticky_posts', array_unique( $stickies ) );
201 }
202 }
203
204 /**
205 * Some backward compatibility with Polylang < 2.3
206 * allows to call PLL()->sync->copy_post_metas() and PLL()->sync->copy_taxonomies()
207 * used for example in Polylang for WooCommerce
208 * the compatibility is however only partial as the 4th argument $sync is lost
209 *
210 * @since 2.3
211 *
212 * @param string $func Function name
213 * @param array $args Function arguments
214 * @return mixed|void
215 */
216 public function __call( $func, $args ) {
217 $obj = substr( $func, 5 );
218
219 if ( is_object( $this->$obj ) && method_exists( $this->$obj, 'copy' ) ) {
220 if ( WP_DEBUG ) {
221 $debug = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
222 $i = 1 + empty( $debug[1]['line'] ); // The file and line are in $debug[2] if the function was called using call_user_func
223
224 trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
225 sprintf(
226 '%1$s was called incorrectly in %3$s on line %4$s: the call to PLL()->sync->%1$s() has been deprecated in Polylang 2.3, use PLL()->sync->%2$s->copy() instead.' . "\nError handler",
227 esc_html( $func ),
228 esc_html( $obj ),
229 esc_html( $debug[ $i ]['file'] ),
230 absint( $debug[ $i ]['line'] )
231 )
232 );
233 }
234 return call_user_func_array( array( $this->$obj, 'copy' ), $args );
235 }
236
237 $debug = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
238 trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
239 sprintf(
240 'Call to undefined function PLL()->sync->%1$s() in %2$s on line %3$s' . "\nError handler",
241 esc_html( $func ),
242 esc_html( $debug[0]['file'] ),
243 absint( $debug[0]['line'] )
244 ),
245 E_USER_ERROR
246 );
247 }
248 }
249