PluginProbe
Polylang / 1.3
Polylang v1.3
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.3, at admin/admin-sync.php

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