PluginProbe
Polylang / 1.5.2
Polylang v1.5.2
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-filters-post.php

admin-filters-post.php in Polylang 1.5.2, at admin/admin-filters-post.php

374 lines 12.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * manages filters and actions related to posts on admin side
5 *
6 * @since 1.2
7 */
8 class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
9 public $options, $curlang;
10
11 /*
12 * constructor: setups filters and actions
13 *
14 * @since 1.2
15 *
16 * @param object $polylang
17 */
18 public function __construct(&$polylang) {
19 parent::__construct($polylang);
20 $this->options = &$polylang->options;
21 $this->curlang = &$polylang->curlang;
22
23 // filters posts, pages and media by language
24 add_filter('parse_query',array(&$this,'parse_query'));
25
26 // adds the Languages box in the 'Edit Post' and 'Edit Page' panels
27 add_action('add_meta_boxes', array(&$this, 'add_meta_boxes'));
28
29 // ajax response for changing the language in the post metabox
30 add_action('wp_ajax_post_lang_choice', array(&$this,'post_lang_choice'));
31 add_action('wp_ajax_pll_posts_not_translated', array(&$this,'ajax_posts_not_translated'));
32
33 // adds actions and filters related to languages when creating, saving or deleting posts and pages
34 add_action('save_post', array(&$this, 'save_post'), 21, 2); // priority 21 to come after advanced custom fields (20) and before the event calendar which breaks everything after 25
35 add_action('before_delete_post', array(&$this, 'delete_post'));
36 if ($this->options['media_support'])
37 add_action('delete_attachment', array(&$this, 'delete_post')); // action shared with media
38
39 // filters the pages by language in the parent dropdown list in the page attributes metabox
40 add_filter('page_attributes_dropdown_pages_args', array(&$this, 'page_attributes_dropdown_pages_args'), 10, 2);
41 }
42
43 /*
44 * filters posts, pages and media by language
45 *
46 * @since 0.1
47 *
48 * @param object $query a WP_Query object
49 */
50 public function parse_query($query) {
51 $qvars = &$query->query_vars;
52
53 // do not filter post types such as nav_menu_item
54 if (isset($qvars['post_type']) && !$this->model->is_translated_post_type($qvars['post_type'])) {
55 unset ($qvars['lang']);
56 return;
57 }
58
59 if (isset($qvars['post_type']) && !isset($qvars['lang'])) {
60 // filters the list of media (or wp-links) by language when uploading from post
61 if (isset($_REQUEST['pll_post_id']) && $lang = $this->model->get_post_language($_REQUEST['pll_post_id']))
62 $query->set('lang', $lang->slug);
63
64 elseif (!empty($this->curlang))
65 $qvars['lang'] = $this->curlang->slug;
66 }
67
68 if (isset($qvars['lang']) && 'all' === $qvars['lang'])
69 unset ($qvars['lang']);
70 }
71
72 /*
73 * adds the Language box in the 'Edit Post' and 'Edit Page' panels (as well as in custom post types panels)
74 *
75 * @since 0.1
76 *
77 * @param string $post_type
78 */
79 public function add_meta_boxes($post_type) {
80 if ($this->model->is_translated_post_type($post_type))
81 add_meta_box('ml_box', __('Languages','polylang'), array(&$this, 'post_language'), $post_type, 'side', 'high');
82 }
83
84 /*
85 * displays the Languages metabox in the 'Edit Post' and 'Edit Page' panels
86 *
87 * @since 0.1
88 */
89 public function post_language() {
90 global $post_ID;
91 $post_id = $post_ID;
92 $post_type = get_post_type($post_ID);
93
94 $lang = ($lg = $this->model->get_post_language($post_ID)) ? $lg :
95 (isset($_GET['new_lang']) ? $this->model->get_language($_GET['new_lang']) :
96 $this->pref_lang);
97
98 $dropdown = new PLL_Walker_Dropdown();
99
100 wp_nonce_field('pll_language', '_pll_nonce');
101
102 // NOTE: the class "tags-input" allows to include the field in the autosave $_POST (see autosave.js)
103 printf('
104 <p><strong>%s</strong></p>
105 %s
106 <div id="post-translations" class="translations">',
107 __('Language', 'polylang'),
108 $dropdown->walk($this->model->get_languages_list(), array(
109 'name' => $post_type == 'attachment' ? sprintf('attachments[%d][language]', $post_ID) : 'post_lang_choice',
110 'class' => $post_type == 'attachment' ? 'media_lang_choice' : 'tags-input',
111 'selected' => $lang ? $lang->slug : ''
112 ))
113 );
114 if ($lang)
115 include(PLL_ADMIN_INC.'/view-translations-'.($post_type == 'attachment' ? 'media' : 'post').'.php');
116 echo '</div>'."\n";
117 }
118
119 /*
120 * ajax response for changing the language in the post metabox
121 *
122 * @since 0.2
123 */
124 public function post_lang_choice() {
125 check_ajax_referer('pll_language', '_pll_nonce');
126
127 global $post_ID; // obliged to use the global variable for wp_popular_terms_checklist
128 $post_ID = $_POST['post_id'];
129 $post_type = get_post_type($post_ID);
130 $lang = $this->model->get_language($_POST['lang']);
131
132 $post_type_object = get_post_type_object($post_type);
133 if (!current_user_can($post_type_object->cap->edit_posts) || !current_user_can($post_type_object->cap->create_posts))
134 wp_die(-1);
135
136 $this->model->set_post_language($post_ID, $lang); // save language, useful to set the language when uploading media from post
137
138 ob_start();
139 if ($lang)
140 include(PLL_ADMIN_INC.'/view-translations-post.php');
141 $x = new WP_Ajax_Response(array('what' => 'translations', 'data' => ob_get_contents()));
142 ob_end_clean();
143
144 // categories
145 if (isset($_POST['taxonomies'])) {
146 // not set for pages
147 foreach ($_POST['taxonomies'] as $taxname) {
148 $taxonomy = get_taxonomy($taxname);
149
150 ob_start();
151 $popular_ids = wp_popular_terms_checklist($taxonomy->name);
152 $supplemental['populars'] = ob_get_contents();
153 ob_end_clean();
154
155 ob_start();
156 // use $post_ID to remember ckecked terms in case we come back to the original language
157 wp_terms_checklist( $post_ID, array( 'taxonomy' => $taxonomy->name, 'popular_cats' => $popular_ids ));
158 $supplemental['all'] = ob_get_contents();
159 ob_end_clean();
160
161 $supplemental['dropdown'] = wp_dropdown_categories(array(
162 'taxonomy' => $taxonomy->name,
163 'hide_empty' => 0,
164 'name' => 'new'.$taxonomy->name.'_parent',
165 'orderby' => 'name',
166 'hierarchical' => 1,
167 'show_option_none' => '&mdash; '.$taxonomy->labels->parent_item.' &mdash;',
168 'echo' => 0
169 ));
170
171 $x->Add(array('what' => 'taxonomy', 'data' => $taxonomy->name, 'supplemental' => $supplemental));
172 }
173 }
174
175 // parent dropdown list (only for hierarchical post types)
176 if (in_array($post_type, get_post_types(array('hierarchical' => true)))) {
177 require_once( ABSPATH . 'wp-admin/includes/meta-boxes.php' );
178 ob_start();
179 page_attributes_meta_box(get_post($post_ID));
180 $x->Add(array('what' => 'pages', 'data' => ob_get_contents()));
181 ob_end_clean();
182 }
183
184 $x->send();
185 }
186
187 /*
188 * ajax response for input in translation autocomplete input box
189 *
190 * @since 1.5
191 */
192 public function ajax_posts_not_translated() {
193 check_ajax_referer('pll_language', '_pll_nonce');
194
195 $posts = get_posts(array(
196 's' => $_REQUEST['term'],
197 'suppress_filters' => 0, // to make the post_fields filter work
198 'lang' => 0, // avoid admin language filter
199 'numberposts' => 10, // limit to 10 posts
200 'post_status' => 'any',
201 'post_type' => $_REQUEST['post_type'],
202 'orderby' => 'title',
203 'order' => 'ASC',
204 'tax_query' => array(array(
205 'taxonomy' => 'language',
206 'field' => 'term_taxonomy_id', // WP 3.5+
207 'terms' => $this->model->get_language($_REQUEST['translation_language'])->term_taxonomy_id
208 ))
209 ));
210
211 $return = array();
212
213 foreach ($posts as $key => $post) {
214 if (!$this->model->get_translation('post', $post->ID, $_REQUEST['post_language']))
215 $return[] = array('id' => $post->ID, 'value' => $post->post_title, 'link' => $this->edit_translation_link($post->ID));
216 }
217
218 // add current translation in list
219 if ($post_id = $this->model->get_translation('post', $_REQUEST['pll_post_id'],$_REQUEST['translation_language'])) {
220 $post = get_post($post_id);
221 array_unshift($return, array(
222 'id' => $post_id,
223 'value' => $post->post_title,
224 'link' => $this->edit_translation_link($post_id)
225 ));
226 }
227
228 wp_die(json_encode($return));
229 }
230
231 /*
232 * saves language
233 * checks the terms saved are in the right language
234 *
235 * @since 1.5
236 *
237 * @param int $post_id
238 * @param array $post
239 */
240 protected function save_language($post_id, $post) {
241 // security checks are necessary to accept language modifications
242 // as 'wp_insert_post' can be called from outside WP admin
243
244 // edit post
245 if (isset($_REQUEST['post_lang_choice'])) {
246 check_admin_referer('pll_language', '_pll_nonce');
247 $this->model->set_post_language($post_id, $lang = $_REQUEST['post_lang_choice']);
248 }
249
250 // quick edit and bulk edit
251 elseif (isset($_REQUEST['inline_lang_choice'])) {
252 // bulk edit does not modify the language
253 if (isset($_REQUEST['bulk_edit']) && $_REQUEST['inline_lang_choice'] == -1)
254 return;
255
256 isset($_REQUEST['bulk_edit']) ? check_admin_referer('bulk-posts') : check_admin_referer('inlineeditnonce', '_inline_edit');
257
258 if (($old_lang = $this->model->get_post_language($post_id)) && $old_lang->slug != $_REQUEST['inline_lang_choice'])
259 $this->model->delete_translation('post', $post_id);
260
261 $this->model->set_post_language($post_id, $lang = $_REQUEST['inline_lang_choice']);
262 }
263
264 // quick press
265 // 'post-quickpress-save', 'post-quickpress-publish' = backward compatibility WP < 3.8
266 elseif (isset($_REQUEST['action']) && in_array($_REQUEST['action'], array('post-quickpress-save', 'post-quickpress-publish', 'post-quickdraft-save'))) {
267 check_admin_referer('add-' . $post->post_type);
268 $this->model->set_post_language($post_id, $this->pref_lang); // default language for Quick draft
269 }
270
271 else
272 $this->set_default_language($post_id);
273
274 // make sure we get save terms in the right language (especially tags with same name in different languages)
275 if (!empty($lang)) {
276 // FIXME quite a lot of queries in foreach
277 foreach ($this->model->get_translated_taxonomies() as $tax) {
278 $terms = get_the_terms($post_id, $tax);
279
280 if (is_array($terms)) {
281 $newterms = array();
282 foreach ($terms as $term) {
283 if ($newterm = $this->model->term_exists($term->name, $tax, $term->parent, $lang))
284 $newterms[] = (int) $newterm; // cast is important otherwise we get 'numeric' tags
285
286 elseif (!is_wp_error($term_info = wp_insert_term($term->name, $tax))) // create the term in the correct language
287 $newterms[] = (int) $term_info['term_id'];
288 }
289
290 wp_set_object_terms($post_id, $newterms, $tax);
291 }
292 }
293 }
294 }
295
296 /*
297 * called when a post (or page) is saved, published or updated
298 * saves languages and translations
299 *
300 * @since 0.1
301 *
302 * @param int $post_id
303 * @param object $post
304 */
305 public function save_post($post_id, $post) {
306 // does nothing except on post types which are filterable
307 if (!$this->model->is_translated_post_type($post->post_type))
308 return;
309
310 // capability check
311 // as 'wp_insert_post' can be called from outside WP admin
312 $post_type_object = get_post_type_object($post->post_type);
313 if (!current_user_can($post_type_object->cap->edit_posts) || !current_user_can($post_type_object->cap->create_posts))
314 wp_die( __( 'Cheatin&#8217; uh?' ) );
315
316 if ($id = wp_is_post_revision($post_id))
317 $post_id = $id;
318
319 $this->save_language($post_id, $post);
320
321 if (isset($_POST['post_tr_lang']))
322 $translations = $this->save_translations($post_id, $_POST['post_tr_lang']);
323
324 do_action('pll_save_post', $post_id, $post, empty($translations) ? $this->model->get_translations('post', $post_id) : $translations);
325 }
326
327 /*
328 * called when a post, page or media is deleted
329 * don't delete translations if this is a post revision thanks to AndyDeGroo who catched this bug
330 * http://wordpress.org/support/topic/plugin-polylang-quick-edit-still-breaks-translation-linking-of-pages-in-072
331 *
332 * @since 0.1
333 *
334 * @param int $post_id
335 */
336 public function delete_post($post_id) {
337 if (!wp_is_post_revision($post_id))
338 $this->model->delete_translation('post', $post_id);
339 }
340
341 /*
342 * filters the pages by language in the parent dropdown list in the page attributes metabox
343 *
344 * @since 0.6
345 *
346 * @param array $dropdown_args arguments passed to wp_dropdown_pages
347 * @param object $post
348 * @return array modified arguments
349 */
350 public function page_attributes_dropdown_pages_args($dropdown_args, $post) {
351 $dropdown_args['lang'] = isset($_POST['lang']) ? $this->model->get_language($_POST['lang']) : $this->model->get_post_language($post->ID); // ajax or not ?
352 if (!$dropdown_args['lang'])
353 $dropdown_args['lang'] = $this->pref_lang;
354
355 return $dropdown_args;
356 }
357
358 /*
359 * returns html markup for a translation link
360 *
361 * @since 1.4
362 *
363 * @param int $post_id translation post id
364 * @return string
365 */
366 public function edit_translation_link($post_id) {
367 return sprintf(
368 '<a href="%1$s" class="pll_icon_edit" title="%2$s"></a>',
369 esc_url(get_edit_post_link($post_id)),
370 __('Edit', 'polylang')
371 );
372 }
373 }
374