PluginProbe
Polylang / 3.3.1
Polylang v3.3.1
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 / sync.php

sync.php in Polylang 3.3.1, at modules/sync/sync.php

269 lines 7.4 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 on front
8 *
9 * @since 2.4
10 */
11 class PLL_Sync {
12 /**
13 * @var PLL_Sync_Tax
14 */
15 public $taxonomies;
16
17 /**
18 * @var PLL_Sync_Post_Metas
19 */
20 public $post_metas;
21
22 /**
23 * @var PLL_Sync_Term_Metas
24 */
25 public $term_metas;
26
27 /**
28 * Stores the plugin options.
29 *
30 * @var array
31 */
32 protected $options;
33
34 /**
35 * @var PLL_Model
36 */
37 protected $model;
38
39 /**
40 * Constructor
41 *
42 * @since 1.2
43 *
44 * @param object $polylang
45 */
46 public function __construct( &$polylang ) {
47 $this->model = &$polylang->model;
48 $this->options = &$polylang->options;
49
50 $this->taxonomies = new PLL_Sync_Tax( $polylang );
51 $this->post_metas = new PLL_Sync_Post_Metas( $polylang );
52 $this->term_metas = new PLL_Sync_Term_Metas( $polylang );
53
54 add_filter( 'wp_insert_post_parent', array( $this, 'can_sync_post_parent' ), 10, 3 );
55 add_filter( 'wp_insert_post_data', array( $this, 'can_sync_post_data' ), 10, 2 );
56
57 add_action( 'pll_save_post', array( $this, 'pll_save_post' ), 10, 3 );
58 add_action( 'created_term', array( $this, 'sync_term_parent' ), 10, 3 );
59 add_action( 'edited_term', array( $this, 'sync_term_parent' ), 10, 3 );
60
61 add_action( 'pll_duplicate_term', array( $this->term_metas, 'copy' ), 10, 3 );
62
63 if ( $this->options['media_support'] ) {
64 add_action( 'pll_translate_media', array( $this->taxonomies, 'copy' ), 10, 3 );
65 add_action( 'pll_translate_media', array( $this->post_metas, 'copy' ), 10, 3 );
66 add_action( 'edit_attachment', array( $this, 'edit_attachment' ) );
67 }
68
69 add_filter( 'pre_update_option_sticky_posts', array( $this, 'sync_sticky_posts' ), 10, 2 );
70 }
71
72 /**
73 * Get post fields to synchronize.
74 *
75 * @since 2.4
76 *
77 * @param WP_Post $post Post object.
78 * @return array
79 */
80 protected function get_fields_to_sync( $post ) {
81 $postarr = array();
82
83 foreach ( array( 'comment_status', 'ping_status', 'menu_order' ) as $property ) {
84 if ( in_array( $property, $this->options['sync'] ) ) {
85 $postarr[ $property ] = $post->$property;
86 }
87 }
88
89 if ( in_array( 'post_date', $this->options['sync'] ) ) {
90 $postarr['post_date'] = $post->post_date;
91 $postarr['post_date_gmt'] = $post->post_date_gmt;
92 }
93
94 if ( in_array( 'post_parent', $this->options['sync'] ) ) {
95 $postarr['post_parent'] = wp_get_post_parent_id( $post->ID );
96 }
97
98 return $postarr;
99 }
100
101 /**
102 * Prevents synchronized post parent modification if the current user hasn't enough rights
103 *
104 * @since 2.6
105 *
106 * @param int $post_parent Post parent ID
107 * @param int $post_id Post ID, unused
108 * @param array $postarr Array of parsed post data
109 * @return int
110 */
111 public function can_sync_post_parent( $post_parent, $post_id, $postarr ) {
112 if ( ! empty( $postarr['ID'] ) && ! $this->model->post->current_user_can_synchronize( $postarr['ID'] ) ) {
113 $tr_ids = $this->model->post->get_translations( $postarr['ID'] );
114 foreach ( $tr_ids as $tr_id ) {
115 if ( $tr_id !== $postarr['ID'] && $post = get_post( $tr_id ) ) {
116 $post_parent = $post->post_parent;
117 break;
118 }
119 }
120 }
121 return $post_parent;
122 }
123
124 /**
125 * Prevents synchronized post data modification if the current user hasn't enough rights
126 *
127 * @since 2.6
128 *
129 * @param array $data An array of slashed post data.
130 * @param array $postarr An array of sanitized, but otherwise unmodified post data.
131 * @return array
132 */
133 public function can_sync_post_data( $data, $postarr ) {
134 if ( ! empty( $postarr['ID'] ) && ! $this->model->post->current_user_can_synchronize( $postarr['ID'] ) ) {
135 foreach ( $this->model->post->get_translations( $postarr['ID'] ) as $tr_id ) {
136 if ( $tr_id !== $postarr['ID'] && $post = get_post( $tr_id ) ) {
137 $to_sync = $this->get_fields_to_sync( $post );
138 $data = array_merge( $data, $to_sync );
139 break;
140 }
141 }
142 }
143 return $data;
144 }
145
146 /**
147 * Synchronizes post fields in translations.
148 *
149 * @since 2.4
150 *
151 * @param int $post_id Post id.
152 * @param WP_Post $post Post object.
153 * @param int[] $translations Post translations.
154 * @return void
155 */
156 public function pll_save_post( $post_id, $post, $translations ) {
157 global $wpdb;
158
159 if ( $this->model->post->current_user_can_synchronize( $post_id ) ) {
160 $postarr = $this->get_fields_to_sync( $post );
161
162 if ( ! empty( $postarr ) ) {
163 foreach ( $translations as $lang => $tr_id ) {
164 if ( ! $tr_id || $tr_id === $post_id ) {
165 continue;
166 }
167
168 $tr_arr = $postarr;
169 unset( $tr_arr['post_parent'] );
170
171 // Do not udpate the translation parent if the user set a parent with no translation.
172 if ( isset( $postarr['post_parent'] ) ) {
173 $post_parent = $postarr['post_parent'] ? $this->model->post->get_translation( $postarr['post_parent'], $lang ) : 0;
174 if ( ! ( $postarr['post_parent'] && ! $post_parent ) ) {
175 $tr_arr['post_parent'] = $post_parent;
176 }
177 }
178
179 // Update all the rows at once.
180 if ( ! empty( $tr_arr ) ) {
181 // Don't use wp_update_post to avoid infinite loop.
182 $wpdb->update( $wpdb->posts, $tr_arr, array( 'ID' => $tr_id ) );
183 clean_post_cache( $tr_id );
184 }
185 }
186 }
187 }
188 }
189
190 /**
191 * Synchronize term parent in translations
192 * Calling clean_term_cache *after* this is mandatory otherwise the $taxonomy_children option is not correctly updated
193 *
194 * @since 2.3
195 *
196 * @param int $term_id Term id.
197 * @param int $tt_id Term taxonomy id, not used.
198 * @param string $taxonomy Taxonomy name.
199 * @return void
200 */
201 public function sync_term_parent( $term_id, $tt_id, $taxonomy ) {
202 global $wpdb;
203
204 if ( is_taxonomy_hierarchical( $taxonomy ) && $this->model->is_translated_taxonomy( $taxonomy ) ) {
205 $term = get_term( $term_id );
206
207 if ( $term instanceof WP_Term ) {
208 $translations = $this->model->term->get_translations( $term_id );
209
210 foreach ( $translations as $lang => $tr_id ) {
211 if ( ! empty( $tr_id ) && $tr_id !== $term_id ) {
212 $tr_parent = $this->model->term->get_translation( $term->parent, $lang );
213 $tr_term = get_term( (int) $tr_id, $taxonomy );
214
215 if ( $tr_term instanceof WP_Term && ! ( $term->parent && empty( $tr_parent ) ) ) {
216 $wpdb->update(
217 $wpdb->term_taxonomy,
218 array( 'parent' => $tr_parent ? $tr_parent : 0 ),
219 array( 'term_taxonomy_id' => $tr_term->term_taxonomy_id )
220 );
221
222 clean_term_cache( $tr_id, $taxonomy ); // OK since WP 3.9.
223 }
224 }
225 }
226 }
227 }
228 }
229
230 /**
231 * Synchronizes terms and metas in translations for media
232 *
233 * @since 1.8
234 *
235 * @param int $post_id post id
236 * @return void
237 */
238 public function edit_attachment( $post_id ) {
239 $this->pll_save_post( $post_id, get_post( $post_id ), $this->model->post->get_translations( $post_id ) );
240 }
241
242 /**
243 * Synchronize sticky posts.
244 *
245 * @since 2.3
246 *
247 * @param int[] $value New option value.
248 * @param int[] $old_value Old option value.
249 * @return int[]
250 */
251 public function sync_sticky_posts( $value, $old_value ) {
252 if ( in_array( 'sticky_posts', $this->options['sync'] ) ) {
253 // Stick post
254 if ( $sticked = array_diff( $value, $old_value ) ) {
255 $translations = $this->model->post->get_translations( reset( $sticked ) );
256 $value = array_unique( array_merge( $value, array_values( $translations ) ) );
257 }
258
259 // Unstick post
260 if ( $unsticked = array_diff( $old_value, $value ) ) {
261 $translations = $this->model->post->get_translations( reset( $unsticked ) );
262 $value = array_unique( array_diff( $value, array_values( $translations ) ) );
263 }
264 }
265
266 return $value;
267 }
268 }
269