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

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