PluginProbe
Polylang / 2.9
Polylang v2.9
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 2.9, at modules/sync/admin-sync.php

223 lines 7.3 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 foreach ( array( 'menu_order', 'comment_status', 'ping_status' ) as $property ) {
66 $data[ $property ] = $from_post->$property;
67 }
68
69 // Copy the date only if the synchronization is activated
70 if ( in_array( 'post_date', $this->options['sync'] ) ) {
71 $data['post_date'] = $from_post->post_date;
72 $data['post_date_gmt'] = $from_post->post_date_gmt;
73 }
74 }
75
76 return $data;
77 }
78
79 /**
80 * Copy post metas, and taxonomies when using "Add new" ( translation )
81 *
82 * @since 2.5
83 */
84 public function new_post_translation() {
85 global $post;
86 static $done = array();
87
88 if ( isset( $GLOBALS['pagenow'], $_GET['from_post'], $_GET['new_lang'] ) && 'post-new.php' === $GLOBALS['pagenow'] && $this->model->is_translated_post_type( $post->post_type ) ) {
89 check_admin_referer( 'new-post-translation' );
90
91 // Capability check already done in post-new.php
92 $from_post_id = (int) $_GET['from_post'];
93 $lang = $this->model->get_language( sanitize_key( $_GET['new_lang'] ) );
94
95 if ( ! $from_post_id || ! $lang || ! empty( $done[ $from_post_id ] ) ) {
96 return;
97 }
98
99 $done[ $from_post_id ] = true; // Avoid a second duplication in the block editor. Using an array only to allow multiple phpunit tests.
100
101 $this->taxonomies->copy( $from_post_id, $post->ID, $lang->slug );
102 $this->post_metas->copy( $from_post_id, $post->ID, $lang->slug );
103
104 if ( is_sticky( $from_post_id ) ) {
105 stick_post( $post->ID );
106 }
107 }
108 }
109
110 /**
111 * Get post fields to synchronize
112 *
113 * @since 2.4
114 *
115 * @param object $post Post object
116 * @return array
117 */
118 protected function get_fields_to_sync( $post ) {
119 global $wpdb;
120
121 $postarr = parent::get_fields_to_sync( $post );
122
123 // For new drafts, save the date now otherwise it is overriden by WP. Thanks to JoryHogeveen. See #32.
124 if ( in_array( 'post_date', $this->options['sync'] ) && isset( $GLOBALS['pagenow'], $_GET['from_post'], $_GET['new_lang'] ) && 'post-new.php' === $GLOBALS['pagenow'] ) {
125 check_admin_referer( 'new-post-translation' );
126
127 unset( $postarr['post_date'] );
128 unset( $postarr['post_date_gmt'] );
129
130 $original = get_post( (int) $_GET['from_post'] );
131 $wpdb->update(
132 $wpdb->posts,
133 array(
134 'post_date' => $original->post_date,
135 'post_date_gmt' => $original->post_date_gmt,
136 ),
137 array( 'ID' => $post->ID )
138 );
139 }
140
141 if ( isset( $GLOBALS['post_type'] ) ) {
142 $post_type = $GLOBALS['post_type'];
143 } elseif ( isset( $_REQUEST['post_type'] ) ) {
144 $post_type = sanitize_key( $_REQUEST['post_type'] ); // 2nd case for quick edit
145 }
146
147 // Make sure not to impact media translations when creating them at the same time as post
148 if ( in_array( 'post_parent', $this->options['sync'] ) && ( ! isset( $post_type ) || $post_type !== $post->post_type ) ) {
149 unset( $postarr['post_parent'] );
150 }
151
152 return $postarr;
153 }
154
155 /**
156 * Synchronizes post fields in translations
157 *
158 * @since 1.2
159 *
160 * @param int $post_id post id
161 * @param object $post post object
162 * @param array $translations post translations
163 */
164 public function pll_save_post( $post_id, $post, $translations ) {
165 parent::pll_save_post( $post_id, $post, $translations );
166
167 // Sticky posts
168 if ( in_array( 'sticky_posts', $this->options['sync'] ) ) {
169 $stickies = get_option( 'sticky_posts' );
170 if ( isset( $_REQUEST['sticky'] ) && 'sticky' === $_REQUEST['sticky'] ) { // phpcs:ignore WordPress.Security.NonceVerification
171 $stickies = array_merge( $stickies, array_values( $translations ) );
172 } else {
173 $stickies = array_diff( $stickies, array_values( $translations ) );
174 }
175 update_option( 'sticky_posts', array_unique( $stickies ) );
176 }
177 }
178
179 /**
180 * Some backward compatibility with Polylang < 2.3
181 * allows to call PLL()->sync->copy_post_metas() and PLL()->sync->copy_taxonomies()
182 * used for example in Polylang for WooCommerce
183 * the compatibility is however only partial as the 4th argument $sync is lost
184 *
185 * @since 2.3
186 *
187 * @param string $func Function name
188 * @param array $args Function arguments
189 */
190 public function __call( $func, $args ) {
191 $obj = substr( $func, 5 );
192
193 if ( is_object( $this->$obj ) && method_exists( $this->$obj, 'copy' ) ) {
194 if ( WP_DEBUG ) {
195 $debug = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
196 $i = 1 + empty( $debug[1]['line'] ); // The file and line are in $debug[2] if the function was called using call_user_func
197
198 trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
199 sprintf(
200 '%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",
201 esc_html( $func ),
202 esc_html( $obj ),
203 esc_html( $debug[ $i ]['file'] ),
204 absint( $debug[ $i ]['line'] )
205 )
206 );
207 }
208 return call_user_func_array( array( $this->$obj, 'copy' ), $args );
209 }
210
211 $debug = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
212 trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
213 sprintf(
214 'Call to undefined function PLL()->sync->%1$s() in %2$s on line %3$s' . "\nError handler",
215 esc_html( $func ),
216 esc_html( $debug[0]['file'] ),
217 absint( $debug[0]['line'] )
218 ),
219 E_USER_ERROR
220 );
221 }
222 }
223