PluginProbe
Polylang / 3.8
Polylang v3.8
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 / src / modules / sync / admin-sync.php

admin-sync.php in Polylang 3.8, at src/modules/sync/admin-sync.php

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