Viewing file: admin-filters-post.php (19.97 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
/** * Manages filters and actions related to posts on admin side * * @since 1.2 */ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base { public $options, $curlang;
/** * Constructor: setups filters and actions * * @since 1.2 * * @param object $polylang */ public function __construct( &$polylang ) { parent::__construct( $polylang ); $this->options = &$polylang->options; $this->curlang = &$polylang->curlang;
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
// Filters posts, pages and media by language add_action( 'parse_query', array( $this, 'parse_query' ) );
// Adds the Languages box in the 'Edit Post' and 'Edit Page' panels add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 2 );
// Ajax response for changing the language in the post metabox add_action( 'wp_ajax_post_lang_choice', array( $this, 'post_lang_choice' ) ); add_action( 'wp_ajax_pll_posts_not_translated', array( $this, 'ajax_posts_not_translated' ) );
// Adds actions and filters related to languages when creating, saving or deleting posts and pages add_action( 'save_post', array( $this, 'save_post' ), 21, 3 ); // Priority 21 to come after advanced custom fields ( 20 ) and before the event calendar which breaks everything after 25 add_filter( 'wp_insert_post_parent', array( $this, 'wp_insert_post_parent' ), 10, 4 ); add_action( 'before_delete_post', array( $this, 'delete_post' ) ); if ( $this->options['media_support'] ) { add_action( 'delete_attachment', array( $this, 'delete_post' ) ); // Action shared with media }
// Filters the pages by language in the parent dropdown list in the page attributes metabox add_filter( 'page_attributes_dropdown_pages_args', array( $this, 'page_attributes_dropdown_pages_args' ), 10, 2 ); }
/** * Outputs a javascript list of terms ordered by language and hierarchical taxonomies * to filter the category checklist per post language in quick edit * Outputs a javascript list of pages ordered by language * to filter the parent dropdown per post language in quick edit * * @since 1.7 */ public function admin_enqueue_scripts() { $screen = get_current_screen();
// Hierarchical taxonomies if ( 'edit' == $screen->base && $taxonomies = get_object_taxonomies( $screen->post_type, 'object' ) ) { // Get translated hierarchical taxonomies foreach ( $taxonomies as $taxonomy ) { if ( $taxonomy->hierarchical && $taxonomy->show_in_quick_edit && $this->model->is_translated_taxonomy( $taxonomy->name ) ) { $hierarchical_taxonomies[] = $taxonomy->name; } }
if ( ! empty( $hierarchical_taxonomies ) ) { $terms = get_terms( $hierarchical_taxonomies, array( 'get' => 'all' ) );
foreach ( $terms as $term ) { if ( $lang = $this->model->term->get_language( $term->term_id ) ) { $term_languages[ $lang->slug ][ $term->taxonomy ][] = $term->term_id; } }
// Send all these data to javascript if ( ! empty( $term_languages ) ) { wp_localize_script( 'pll_post', 'pll_term_languages', $term_languages ); } } }
// Hierarchical post types if ( 'edit' == $screen->base && is_post_type_hierarchical( $screen->post_type ) ) { $pages = get_pages();
foreach ( $pages as $page ) { if ( $lang = $this->model->post->get_language( $page->ID ) ) { $page_languages[ $lang->slug ][] = $page->ID; } }
// Send all these data to javascript if ( ! empty( $page_languages ) ) { wp_localize_script( 'pll_post', 'pll_page_languages', $page_languages ); } } }
/** * Filters posts, pages and media by language * * @since 0.1 * * @param object $query a WP_Query object */ public function parse_query( $query ) { $qvars = &$query->query_vars;
// Do not filter post types such as nav_menu_item if ( isset( $qvars['post_type'] ) && ! $this->model->is_translated_post_type( $qvars['post_type'] ) ) { unset( $qvars['lang'] ); return; }
// Do not filter the query if the language is already specified in another way if ( ! isset( $qvars['lang'] ) ) { $excludes = array( 'p', 'post_parent', 'attachment', 'attachment_id', 'name', 'pagename', 'page_id', 'category_name', 'tag', 'cat', 'tag_id', 'category__in', 'category__and', 'post__in', 'post_name__in', 'tag__in', 'tag__and', 'tag_slug__in', 'tag_slug__and', 'post_parent__in', );
foreach ( $excludes as $k ) { if ( ! empty( $qvars[ $k ] ) ) { return; } }
$taxonomies = array_intersect( $this->model->get_translated_taxonomies(), get_taxonomies( array( '_builtin' => false ) ) );
foreach ( $taxonomies as $tax ) { $tax = get_taxonomy( $tax ); if ( ! empty( $qv[ $tax->query_var ] ) ) { return; } }
if ( ! empty( $qvars['tax_query'] ) && is_array( $qvars['tax_query'] ) && $this->model->have_translated_taxonomy( $qvars['tax_query'] ) ) { return; }
// Filter queries according to the current language if ( isset( $qvars['post_type'] ) && ! empty( $this->curlang ) ) { $qvars['lang'] = $this->curlang->slug; } }
if ( isset( $qvars['lang'] ) && 'all' === $qvars['lang'] ) { unset( $qvars['lang'] ); } }
/** * Adds the Language box in the 'Edit Post' and 'Edit Page' panels ( as well as in custom post types panels ) * Removes the editor for translations of the pages for posts * * @since 0.1 * * @param string $post_type */ public function add_meta_boxes( $post_type, $post ) { if ( $this->model->is_translated_post_type( $post_type ) ) { add_meta_box( 'ml_box', __( 'Languages','polylang' ), array( $this, 'post_language' ), $post_type, 'side', 'high' ); }
if ( ( $page_for_posts = get_option( 'page_for_posts' ) ) && ( $translations = $this->model->post->get_translations( $page_for_posts ) ) && in_array( $post->ID, $translations ) && empty( $post->post_content ) ) { add_action( 'edit_form_after_title', '_wp_posts_page_notice' ); remove_post_type_support( $post_type, 'editor' ); } }
/** * Displays the Languages metabox in the 'Edit Post' and 'Edit Page' panels * * @since 0.1 */ public function post_language() { global $post_ID; $post_id = $post_ID; $post_type = get_post_type( $post_ID );
$lang = ( $lg = $this->model->post->get_language( $post_ID ) ) ? $lg : ( isset( $_GET['new_lang'] ) ? $this->model->get_language( $_GET['new_lang'] ) : $this->pref_lang );
$dropdown = new PLL_Walker_Dropdown();
wp_nonce_field( 'pll_language', '_pll_nonce' );
// NOTE: the class "tags-input" allows to include the field in the autosave $_POST ( see autosave.js ) printf( ' <p><strong>%1$s</strong></p> <label class="screen-reader-text" for="%2$s">%1$s</label> <div id="select-%3$s-language">%4$s</div>', esc_html__( 'Language', 'polylang' ), $id = ( 'attachment' === $post_type ) ? sprintf( 'attachments[%d][language]', $post_ID ) : 'post_lang_choice', 'attachment' === $post_type ? 'media' : 'post', $dropdown->walk( $this->model->get_languages_list(), array( 'name' => $id, 'class' => 'post_lang_choice tags-input', 'selected' => $lang ? $lang->slug : '', 'flag' => true, ) ) );
/** * Fires before displaying the list of translations in the Languages metabox for posts * * @since 1.8 */ do_action( 'pll_before_post_translations', $post_type );
echo '<div id="post-translations" class="translations">'; if ( $lang ) { include PLL_ADMIN_INC . '/view-translations-' . ( 'attachment' == $post_type ? 'media' : 'post' ) . '.php'; } echo '</div>' . "\n"; }
/** * Ajax response for changing the language in the post metabox * * @since 0.2 */ public function post_lang_choice() { check_ajax_referer( 'pll_language', '_pll_nonce' );
global $post_ID; // Obliged to use the global variable for wp_popular_terms_checklist $post_id = $post_ID = (int) $_POST['post_id']; $lang = $this->model->get_language( $_POST['lang'] );
$post_type = $_POST['post_type']; $post_type_object = get_post_type_object( $post_type ); if ( ! current_user_can( $post_type_object->cap->edit_post, $post_ID ) ) { wp_die( -1 ); }
$this->model->post->set_language( $post_ID, $lang ); // Save language, useful to set the language when uploading media from post
ob_start(); if ( $lang ) { include PLL_ADMIN_INC . '/view-translations-' . ( 'attachment' == $post_type ? 'media' : 'post' ) . '.php'; } $x = new WP_Ajax_Response( array( 'what' => 'translations', 'data' => ob_get_contents() ) ); ob_end_clean();
// Categories if ( isset( $_POST['taxonomies'] ) ) { // Not set for pages foreach ( $_POST['taxonomies'] as $taxname ) { $taxonomy = get_taxonomy( $taxname );
ob_start(); $popular_ids = wp_popular_terms_checklist( $taxonomy->name ); $supplemental['populars'] = ob_get_contents(); ob_end_clean();
ob_start(); // Use $post_ID to remember ckecked terms in case we come back to the original language wp_terms_checklist( $post_ID, array( 'taxonomy' => $taxonomy->name, 'popular_cats' => $popular_ids ) ); $supplemental['all'] = ob_get_contents(); ob_end_clean();
$supplemental['dropdown'] = wp_dropdown_categories( array( 'taxonomy' => $taxonomy->name, 'hide_empty' => 0, 'name' => 'new'.$taxonomy->name.'_parent', 'orderby' => 'name', 'hierarchical' => 1, 'show_option_none' => '— '.$taxonomy->labels->parent_item.' —', 'echo' => 0, ) );
$x->Add( array( 'what' => 'taxonomy', 'data' => $taxonomy->name, 'supplemental' => $supplemental ) ); } }
// Parent dropdown list ( only for hierarchical post types ) if ( in_array( $post_type, get_post_types( array( 'hierarchical' => true ) ) ) ) { $post = get_post( $post_ID );
// Args and filter from 'page_attributes_meta_box' in wp-admin/includes/meta-boxes.php of WP 4.2.1 $dropdown_args = array( 'post_type' => $post->post_type, 'exclude_tree' => $post->ID, 'selected' => $post->post_parent, 'name' => 'parent_id', 'show_option_none' => __( '(no parent)' ), 'sort_column' => 'menu_order, post_title', 'echo' => 0, );
/** This filter is documented in wp-admin/includes/meta-boxes.php */ $dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post ); // Since WP 3.3
$x->Add( array( 'what' => 'pages', 'data' => wp_dropdown_pages( $dropdown_args ) ) ); }
// Flag $x->Add( array( 'what' => 'flag', 'data' => empty( $lang->flag ) ? esc_html( $lang->slug ) : $lang->flag ) );
// Sample permalink $x->Add( array( 'what' => 'permalink', 'data' => get_sample_permalink_html( $post_ID ) ) );
$x->send(); }
/** * Ajax response for input in translation autocomplete input box * * @since 1.5 */ public function ajax_posts_not_translated() { check_ajax_referer( 'pll_language', '_pll_nonce' );
if ( ! post_type_exists( $_GET['post_type'] ) ) { die( 0 ); }
$post_language = $this->model->get_language( $_GET['post_language'] ); $translation_language = $this->model->get_language( $_GET['translation_language'] );
// Don't order by title: see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough $args = array( 's' => wp_unslash( $_GET['term'] ), 'suppress_filters' => 0, // To make the post_fields filter work 'lang' => 0, // Avoid admin language filter 'numberposts' => 20, // Limit to 20 posts 'post_status' => 'any', 'post_type' => $_GET['post_type'], 'tax_query' => array( array( 'taxonomy' => 'language', 'field' => 'term_taxonomy_id', // WP 3.5+ 'terms' => $translation_language->term_taxonomy_id, ) ), );
/** * Filter the query args when auto suggesting untranslated posts in the Languages metabox * This should help plugins to fix some edge cases * * @see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough * * @since 1.7 * * @param array $args WP_Query arguments */ $args = apply_filters( 'pll_ajax_posts_not_translated_args', $args ); $posts = get_posts( $args );
$return = array();
foreach ( $posts as $key => $post ) { if ( ! $this->model->post->get_translation( $post->ID, $post_language ) ) { $return[] = array( 'id' => $post->ID, 'value' => $post->post_title, 'link' => $this->links->edit_post_translation_link( $post->ID ), ); } }
// Add current translation in list if ( $post_id = $this->model->post->get_translation( (int) $_GET['pll_post_id'], $translation_language ) ) { $post = get_post( $post_id ); array_unshift( $return, array( 'id' => $post_id, 'value' => $post->post_title, 'link' => $this->links->edit_post_translation_link( $post_id ), ) ); }
wp_die( json_encode( $return ) ); }
/** * Saves language * Checks the terms saved are in the right language * * @since 1.5 * * @param int $post_id * @param array $post */ protected function save_language( $post_id, $post ) { // Security checks are necessary to accept language modifications as 'wp_insert_post' can be called from outside WP admin
// Edit post if ( isset( $_POST['post_lang_choice'], $_POST['post_ID'] ) && $_POST['post_ID'] == $post_id ) { check_admin_referer( 'pll_language', '_pll_nonce' ); $this->model->post->set_language( $post_id, $lang = $this->model->get_language( $_POST['post_lang_choice'] ) ); }
// Quick edit and bulk edit // POST for quick edit, GET for bulk edit elseif ( isset( $_REQUEST['inline_lang_choice'] ) ) { // Bulk edit does not modify the language if ( isset( $_GET['bulk_edit'] ) && -1 == $_REQUEST['inline_lang_choice'] ) { check_admin_referer( 'bulk-posts' ); $lang = $this->model->post->get_language( $post_id ); // Get the post language for later use when saving terms } // A language is set in the language dropdown else { isset( $_GET['bulk_edit'] ) ? check_admin_referer( 'bulk-posts' ) : check_admin_referer( 'inlineeditnonce', '_inline_edit' );
$old_lang = $this->model->post->get_language( $post_id ); // Stores the old language $this->model->post->set_language( $post_id, $lang = $this->model->get_language( $_REQUEST['inline_lang_choice'] ) ); // set new language
// Checks if the new language already exists in the translation group if ( $old_lang && $old_lang->slug != $lang->slug ) { $translations = $this->model->post->get_translations( $post_id );
// If yes, separate this post from the translation group if ( array_key_exists( $lang->slug, $translations ) ) { $this->model->post->delete_translation( $post_id ); }
elseif ( array_key_exists( $old_lang->slug, $translations ) ) { unset( $translations[ $old_lang->slug ] ); $this->model->post->save_translations( $post_id, $translations ); } } } }
// Quick press // 'post-quickpress-save', 'post-quickpress-publish' = backward compatibility WP < 3.8 elseif ( isset( $_REQUEST['action'] ) && in_array( $_REQUEST['action'], array( 'post-quickpress-save', 'post-quickpress-publish', 'post-quickdraft-save' ) ) ) { check_admin_referer( 'add-' . $post->post_type ); $this->model->post->set_language( $post_id, $lang = $this->pref_lang ); // Default language for Quick draft }
else { $this->set_default_language( $post_id ); }
// Make sure we get save terms in the right language (especially tags with same name in different languages) if ( ! empty( $lang ) ) { // FIXME quite a lot of queries in foreach foreach ( $this->model->get_translated_taxonomies() as $tax ) { $terms = get_the_terms( $post_id, $tax );
if ( is_array( $terms ) ) { $newterms = array(); foreach ( $terms as $term ) { // Check if the term is in the correct language or if a translation exist ( mainly for default category ) if ( $newterm = $this->model->term->get( $term->term_id, $lang ) ) { $newterms[] = (int) $newterm; }
// Or choose the correct language for tags ( initially defined by name ) elseif ( $newterm = $this->model->term_exists( $term->name, $tax, $term->parent, $lang ) ) { $newterms[] = (int) $newterm; // Cast is important otherwise we get 'numeric' tags }
// Or create the term in the correct language elseif ( ! is_wp_error( $term_info = wp_insert_term( $term->name, $tax ) ) ) { $newterms[] = (int) $term_info['term_id']; } }
wp_set_object_terms( $post_id, $newterms, $tax ); } } } }
/** * Called when a post ( or page ) is saved, published or updated * saves languages and translations * * @since 0.1 * * @param int $post_id * @param object $post * @param bool $update Whether it is an update or not */ public function save_post( $post_id, $post, $update ) { // Does nothing except on post types which are filterable if ( ! $this->model->is_translated_post_type( $post->post_type ) ) { return; }
if ( $id = wp_is_post_revision( $post_id ) ) { $post_id = $id; }
// Capability check // As 'wp_insert_post' can be called from outside WP admin $post_type_object = get_post_type_object( $post->post_type ); if ( ( $update && current_user_can( $post_type_object->cap->edit_post, $post_id ) ) || ( ! $update && current_user_can( $post_type_object->cap->create_posts ) ) ) { $this->save_language( $post_id, $post );
// Make sure we are saving translations only for the main post currently being edited if ( isset( $_POST['post_tr_lang'], $_POST['post_ID'] ) && $_POST['post_ID'] == $post_id ) { $translations = $this->save_translations( $post_id, $_POST['post_tr_lang'] ); }
/** * Fires after the post language and translations are saved * * @since 1.2 * * @param int $post_id Post id * @param object $post Post object * @param array $translations The list of translations post ids */ do_action( 'pll_save_post', $post_id, $post, empty( $translations ) ? $this->model->post->get_translations( $post_id ) : $translations ); }
// Attempts to set a default language even if no capability else { $this->set_default_language( $post_id ); } }
/** * Make sure that the post parent is in the correct language when using bulk edit * * @since 1.8 * * @param int $post_parent Post parent ID. * @param int $post_id Post ID. * @param array $new_postarr Array of parsed post data. * @param array $postarr Array of sanitized, but otherwise unmodified post data. * @return int */ public function wp_insert_post_parent( $post_parent, $post_id, $new_postarr, $postarr ) { if ( isset( $postarr['bulk_edit'] ) ) { check_admin_referer( 'bulk-posts' ); $lang = -1 == $postarr['inline_lang_choice'] ? $this->model->post->get_language( $post_id ) : $this->model->get_language( $postarr['inline_lang_choice'] ); $post_parent = $this->model->post->get_translation( $post_parent, $lang ); } return $post_parent; }
/** * Called when a post, page or media is deleted * Don't delete translations if this is a post revision thanks to AndyDeGroo who catched this bug * http://wordpress.org/support/topic/plugin-polylang-quick-edit-still-breaks-translation-linking-of-pages-in-072 * * @since 0.1 * * @param int $post_id */ public function delete_post( $post_id ) { if ( ! wp_is_post_revision( $post_id ) ) { $this->model->post->delete_translation( $post_id ); } }
/** * Filters the pages by language in the parent dropdown list in the page attributes metabox * * @since 0.6 * * @param array $dropdown_args Arguments passed to wp_dropdown_pages * @param object $post * @return array Modified arguments */ public function page_attributes_dropdown_pages_args( $dropdown_args, $post ) { $dropdown_args['lang'] = isset( $_POST['lang'] ) ? $this->model->get_language( $_POST['lang'] ) : $this->model->post->get_language( $post->ID ); // ajax or not ? if ( ! $dropdown_args['lang'] ) { $dropdown_args['lang'] = $this->pref_lang; }
return $dropdown_args; } }
|