PluginProbe
Polylang / 3.0.4
Polylang v3.0.4
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.0.4, at modules/sync/admin-sync.php

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