PluginProbe
Polylang / 1.5
Polylang v1.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 / admin / admin-sync.php

admin-sync.php in Polylang 1.5, at admin/admin-sync.php

245 lines 8.6 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 {
9
10 /*
11 * constructor
12 *
13 * @since 1.2
14 *
15 * @param object $polylang
16 */
17 public function __construct(&$polylang) {
18 $this->model = &$polylang->model;
19 $this->options = &$polylang->options;
20
21 add_filter('wp_insert_post_parent', array(&$this, 'wp_insert_post_parent'));
22 add_action('add_meta_boxes', array(&$this, 'add_meta_boxes'), 10, 2);
23
24 add_action('pll_save_post', array(&$this, 'pll_save_post'), 10, 3);
25
26 if (in_array('taxonomies', $this->options['sync']))
27 add_action('pll_save_term', array(&$this, 'pll_save_term'), 10, 3);
28 }
29
30 /*
31 * translate post parent if exists when using "Add new" (translation)
32 *
33 * @since 0.6
34 */
35 function wp_insert_post_parent($post_parent) {
36 return isset($_GET['from_post'], $_GET['new_lang']) && ($id = wp_get_post_parent_id($_GET['from_post'])) && ($parent = $this->model->get_translation('post', $id, $_GET['new_lang'])) ? $parent : $post_parent;
37 }
38
39 /*
40 * copy post metas, menu order, comment and ping status when using "Add new" (translation)
41 * formerly used dbx_post_advanced deprecated in WP 3.7
42 *
43 * @since 1.2
44 *
45 * @param string $post_type unused
46 * @param object $post current post object
47 */
48 function add_meta_boxes($post_type, $post) {
49 if ('post-new.php' == $GLOBALS['pagenow'] && isset($_GET['from_post'], $_GET['new_lang'])) {
50 if (!$this->model->is_translated_post_type($post->post_type))
51 return;
52
53 // capability check already done in post-new.php
54 $this->copy_post_metas($_GET['from_post'], $post->ID, $_GET['new_lang']);
55
56 $from_post = get_post($_GET['from_post']);
57 foreach (array('menu_order', 'comment_status', 'ping_status') as $property)
58 $post->$property = $from_post->$property;
59
60 if (in_array('sticky_posts', $this->options['sync']) && is_sticky($_GET['from_post']))
61 stick_post($post->ID);
62 }
63 }
64
65 /*
66 * copy or synchronize terms and metas
67 *
68 * @since 0.9
69 *
70 * @param int $from id of the post from which we copy informations
71 * @param int $to id of the post to which we paste informations
72 * @param string $lang language slug
73 * @param bool $sync true if it is synchronization, false if it is a copy, defaults to false
74 */
75 protected function copy_post_metas($from, $to, $lang, $sync = false) {
76 // copy or synchronize terms
77 if (!$sync || in_array('taxonomies', $this->options['sync'])) {
78 // FIXME quite a lot of query in foreach
79 foreach ($this->model->get_translated_taxonomies() as $tax) {
80 $newterms = array();
81 $terms = get_the_terms($from, $tax);
82 if (is_array($terms)) {
83 foreach ($terms as $term) {
84 if ($term_id = $this->model->get_translation('term', $term->term_id, $lang))
85 $newterms[] = (int) $term_id; // cast is important otherwise we get 'numeric' tags
86 }
87 }
88
89 // for some reasons, the user may have untranslated terms in the translation. don't forget them.
90 if ($sync) {
91 $tr_terms = get_the_terms($to, $tax);
92 if (is_array($tr_terms)) {
93 foreach ($tr_terms as $term) {
94 if (!$this->model->get_translation('term', $term->term_id, $this->model->get_post_language($from)))
95 $newterms[] = (int) $term->term_id;
96 }
97 }
98 }
99
100 if (!empty($newterms) || $sync)
101 wp_set_object_terms($to, $newterms, $tax); // replace terms in translation
102 }
103 }
104
105 // copy or synchronize post formats
106 if (!$sync || in_array('post_format', $this->options['sync']))
107 ($format = get_post_format($from)) ? set_post_format($to, $format) : set_post_format($to, '');
108
109 // copy or synchronize post metas and allow plugins to do the same
110 $metas = get_post_custom($from);
111
112 // get public meta keys (including from translated post in case we just deleted a custom field)
113 if (!$sync || in_array('post_meta', $this->options['sync'])) {
114 foreach ($keys = array_unique(array_merge(array_keys($metas), array_keys(get_post_custom($to)))) as $k => $meta_key)
115 if (is_protected_meta($meta_key))
116 unset ($keys[$k]);
117 }
118
119 // add page template and featured image
120 foreach (array('_wp_page_template', '_thumbnail_id') as $meta)
121 if (!$sync || in_array($meta, $this->options['sync']))
122 $keys[] = $meta;
123
124 $keys = array_unique(apply_filters('pll_copy_post_metas', empty($keys) ? array() : $keys, $sync));
125
126 // and now copy / synchronize
127 foreach ($keys as $key) {
128 delete_post_meta($to, $key); // the synchronization process of multiple values custom fields is easier if we delete all metas first
129 if (isset($metas[$key])) {
130 foreach ($metas[$key] as $value) {
131 // important: always maybe_unserialize value coming from get_post_custom. See codex.
132 // thanks to goncalveshugo http://wordpress.org/support/topic/plugin-polylang-pll_copy_post_meta
133 $value = maybe_unserialize($value);
134 // special case for featured images which can be translated
135 add_post_meta($to, $key, ($key == '_thumbnail_id' && $tr_value = $this->model->get_translation('post', $value, $lang)) ? $tr_value : $value);
136 }
137 }
138 }
139 }
140
141 /*
142 * synchronizes terms and metas in translations
143 *
144 * @since 1.2
145 *
146 * @param int $post_id post id
147 * @param object $post post object
148 * @param array translations post translations
149 */
150 public function pll_save_post($post_id, $post, $translations) {
151 global $wpdb;
152
153 // prepare properties to synchronize
154 foreach (array('comment_status', 'ping_status', 'menu_order', 'post_date') as $property)
155 if (in_array($property, $this->options['sync']))
156 $postarr[$property] = $post->$property;
157
158 if (in_array('post_date', $this->options['sync']))
159 $post_arr['post_date_gmt'] = $post->post_date_gmt;
160
161 // synchronise terms and metas in translations
162 foreach ($translations as $lang => $tr_id) {
163 if (!$tr_id)
164 continue;
165
166 // synchronize terms and metas
167 $this->copy_post_metas($post_id, $tr_id, $lang, true);
168
169 // sticky posts
170 if (in_array('sticky_posts', $this->options['sync']))
171 isset($_REQUEST['sticky']) ? stick_post($tr_id) : unstick_post($tr_id);
172
173 // synchronize comment status, ping status, menu order...
174 if (!empty($postarr))
175 $wpdb->update($wpdb->posts, $postarr, array('ID' => $tr_id));
176
177 // FIXME: optimize the 2 db update in 1
178 // post parent
179 // do not udpate the translation parent if the user set a parent with no translation
180 if (in_array('post_parent', $this->options['sync'])) {
181 $post_parent = ($parent_id = wp_get_post_parent_id($post_id)) ? $this->model->get_translation('post', $parent_id, $lang) : 0;
182 if (!($parent_id && !$post_parent))
183 $wpdb->update($wpdb->posts, array('post_parent'=> $post_parent), array( 'ID' => $tr_id ));
184 }
185 }
186 }
187
188 /*
189 * synchronize translations of a term in all posts
190 *
191 * @since 1.2
192 *
193 * @param int $term_id term id
194 * @param string $taxonomy taxonomy name of the term
195 * @param array $translations translations of the term
196 */
197 public function pll_save_term($term_id, $taxonomy, $translations) {
198 // get all posts associated to this term
199 $posts = get_posts(array(
200 'numberposts' => -1,
201 'nopaging' => true,
202 'post_type' => 'any',
203 'post_status' => 'any',
204 'fields' => 'ids',
205 'tax_query' => array(array(
206 'taxonomy' => $taxonomy,
207 'field' => 'id',
208 'terms' => array_merge(array($term_id), array_values($translations)),
209 ))
210 ));
211
212 // associate translated term to translated post
213 // FIXME quite a lot of query in foreach
214 foreach ($this->model->get_languages_list() as $language) {
215 if ($translated_term = $this->model->get_term($term_id, $language)) {
216 foreach ($posts as $post_id) {
217 if ($translated_post = $this->model->get_post($post_id, $language))
218 wp_set_object_terms($translated_post, $translated_term, $taxonomy, true);
219 }
220 }
221 }
222
223 // synchronize parent in translations
224 // calling clean_term_cache *after* this is mandatory otherwise the $taxonomy_children option is not correctly updated
225 // but clean_term_cache can be called (efficiently) only one time due to static array which prevents to update the option more than once
226 // this is the reason to use the edit_term filter and not edited_term
227 // take care that $_POST contains the only valid values for the current term
228 // FIXME can I synchronize parent without using $_POST instead?
229 if (isset($_POST['term_tr_lang'])) {
230 foreach ($_POST['term_tr_lang'] as $lang => $tr_id) {
231 if (!$tr_id)
232 continue;
233
234 if (isset($_POST['parent']) && $_POST['parent'] != -1) // since WP 3.1
235 $term_parent = $this->model->get_translation('term', $_POST['parent'], $lang);
236
237 global $wpdb;
238 $wpdb->update($wpdb->term_taxonomy,
239 array('parent'=> isset($term_parent) ? $term_parent : 0),
240 array('term_taxonomy_id' => get_term($tr_id, $taxonomy)->term_taxonomy_id));
241 }
242 }
243 }
244 }
245