PluginProbe
Polylang / 2.9
Polylang v2.9
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 / include / translated-post.php

translated-post.php in Polylang 2.9, at include/translated-post.php

257 lines 7.5 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 * Setups the posts languages and translations model
8 *
9 * @since 1.8
10 */
11 class PLL_Translated_Post extends PLL_Translated_Object {
12
13 /**
14 * Constructor
15 *
16 * @since 1.8
17 *
18 * @param object $model
19 */
20 public function __construct( &$model ) {
21 // init properties
22 $this->object_type = null; // For taxonomies
23 $this->type = 'post'; // For capabilities
24 $this->tax_language = 'language';
25 $this->tax_translations = 'post_translations';
26 $this->tax_tt = 'term_taxonomy_id';
27
28 parent::__construct( $model );
29
30 // registers completely the language taxonomy
31 add_action( 'setup_theme', array( $this, 'register_taxonomy' ), 1 );
32
33 // setups post types to translate
34 add_action( 'registered_post_type', array( $this, 'registered_post_type' ) );
35
36 // forces updating posts cache
37 add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) );
38 }
39
40 /**
41 * Store the post language in the database
42 *
43 * @since 0.6
44 *
45 * @param int $post_id post id
46 * @param int|string|object $lang language ( term_id or slug or object )
47 */
48 public function set_language( $post_id, $lang ) {
49 $old_lang = $this->get_language( $post_id );
50 $old_lang = $old_lang ? $old_lang->slug : '';
51 $lang = $lang ? $this->model->get_language( $lang )->slug : '';
52
53 if ( $old_lang !== $lang ) {
54 wp_set_post_terms( (int) $post_id, $lang, 'language' );
55 }
56 }
57
58 /**
59 * Returns the language of a post
60 *
61 * @since 0.1
62 *
63 * @param int $post_id post id
64 * @return bool|object PLL_Language object, false if no language is associated to that post
65 */
66 public function get_language( $post_id ) {
67 $lang = $this->get_object_term( $post_id, 'language' );
68 return ( $lang ) ? $this->model->get_language( $lang ) : false;
69 }
70
71 /**
72 * Deletes a translation
73 *
74 * @since 0.5
75 *
76 * @param int $id post id
77 */
78 public function delete_translation( $id ) {
79 parent::delete_translation( $id );
80 wp_set_object_terms( $id, null, $this->tax_translations );
81 }
82
83 /**
84 * A join clause to add to sql queries when filtering by language is needed directly in query
85 *
86 * @since 1.2
87 *
88 * @param string $alias Alias for $wpdb->posts table
89 * @return string join clause
90 */
91 public function join_clause( $alias = '' ) {
92 global $wpdb;
93 if ( empty( $alias ) ) {
94 $alias = $wpdb->posts;
95 }
96 return " INNER JOIN $wpdb->term_relationships AS pll_tr ON pll_tr.object_id = $alias.ID";
97 }
98
99 /**
100 * Register the language taxonomy
101 *
102 * @since 1.2
103 */
104 public function register_taxonomy() {
105 register_taxonomy(
106 'language',
107 $this->model->get_translated_post_types(),
108 array(
109 'labels' => array(
110 'name' => __( 'Languages', 'polylang' ),
111 'singular_name' => __( 'Language', 'polylang' ),
112 'all_items' => __( 'All languages', 'polylang' ),
113 ),
114 'public' => false,
115 'show_ui' => false, // hide the taxonomy on admin side, needed for WP 4.4.x
116 'show_in_nav_menus' => false, // no metabox for nav menus, needed for WP 4.4.x
117 'publicly_queryable' => true, // since WP 4.5
118 'query_var' => 'lang',
119 'rewrite' => $this->model->options['force_lang'] < 2, // no rewrite for domains and sub-domains
120 '_pll' => true, // polylang taxonomy
121 )
122 );
123 }
124
125 /**
126 * Check if registered post type must be translated
127 *
128 * @since 1.2
129 *
130 * @param string $post_type post type name
131 */
132 public function registered_post_type( $post_type ) {
133 if ( $this->model->is_translated_post_type( $post_type ) ) {
134 register_taxonomy_for_object_type( 'language', $post_type );
135 register_taxonomy_for_object_type( 'post_translations', $post_type );
136 }
137 }
138
139 /**
140 * Forces calling 'update_object_term_cache' when querying posts or pages
141 * this is especially useful for nav menus with a lot of pages
142 * without doing this, we would have one query per page in the menu to get the page language for the permalink
143 *
144 * @since 1.8
145 *
146 * @param object $query reference to the query object
147 */
148 public function pre_get_posts( $query ) {
149 if ( ! empty( $query->query['post_type'] ) && $this->model->is_translated_post_type( $query->query['post_type'] ) ) {
150 $query->query_vars['update_post_term_cache'] = true;
151 }
152 }
153
154 /**
155 * Checks if the current user can read the post
156 *
157 * @since 1.5
158 *
159 * @param int $post_id Post ID
160 * @param string $context Optional, 'edit' or 'view', defaults to 'view'.
161 * @return bool
162 */
163 public function current_user_can_read( $post_id, $context = 'view' ) {
164 $post = get_post( $post_id );
165
166 if ( empty( $post ) ) {
167 return false;
168 }
169
170 if ( 'inherit' === $post->post_status && $post->post_parent ) {
171 $post = get_post( $post->post_parent );
172 }
173
174 if ( 'inherit' === $post->post_status || in_array( $post->post_status, get_post_stati( array( 'public' => true ) ) ) ) {
175 return true;
176 }
177
178 // Follow WP practices, which shows links to private posts ( when readable ), but not for draft posts ( ex: get_adjacent_post_link() )
179 if ( in_array( $post->post_status, get_post_stati( array( 'private' => true ) ) ) ) {
180 $post_type_object = get_post_type_object( $post->post_type );
181 $user = wp_get_current_user();
182 return is_user_logged_in() && ( current_user_can( $post_type_object->cap->read_private_posts ) || $user->ID == $post->post_author ); // Comparison must not be strict!
183 }
184
185 // In edit context, show draft and future posts.
186 if ( 'edit' === $context ) {
187 $states = get_post_stati(
188 array(
189 'protected' => true,
190 'show_in_admin_all_list' => true,
191 )
192 );
193
194 if ( in_array( $post->post_status, $states ) ) {
195 $user = wp_get_current_user();
196 return is_user_logged_in() && ( current_user_can( 'edit_posts' ) || $user->ID == $post->post_author ); // Comparison must not be strict!
197 }
198 }
199
200 return false;
201 }
202
203 /**
204 * Returns a list of posts in a language ( $lang )
205 * not translated in another language ( $untranslated_in )
206 *
207 * @since 2.6
208 *
209 * @param string $type Post type
210 * @param string $untranslated_in The posts must not be translated in this language
211 * @param string $lang Language of the search posts
212 * @param string $search Limit results to posts matching this string
213 * @return array Array of posts
214 */
215 public function get_untranslated( $type, $untranslated_in, $lang, $search = '' ) {
216 $return = array();
217
218 // Don't order by title: see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
219 $args = array(
220 's' => $search,
221 'suppress_filters' => 0, // To make the post_fields filter work
222 'lang' => 0, // Avoid admin language filter
223 'numberposts' => 20, // Limit to 20 posts
224 'post_status' => 'any',
225 'post_type' => $type,
226 'tax_query' => array(
227 array(
228 'taxonomy' => 'language',
229 'field' => 'term_taxonomy_id', // WP 3.5+
230 'terms' => $lang->term_taxonomy_id,
231 ),
232 ),
233 );
234
235 /**
236 * Filter the query args when auto suggesting untranslated posts in the Languages metabox
237 * This should help plugins to fix some edge cases
238 *
239 * @see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
240 *
241 * @since 1.7
242 *
243 * @param array $args WP_Query arguments
244 */
245 $args = apply_filters( 'pll_ajax_posts_not_translated_args', $args );
246 $posts = get_posts( $args );
247
248 foreach ( $posts as $post ) {
249 if ( ! $this->get_translation( $post->ID, $untranslated_in ) && $this->current_user_can_read( $post->ID, 'edit' ) ) {
250 $return[] = $post;
251 }
252 }
253
254 return $return;
255 }
256 }
257