PluginProbe
Polylang / 3.2.2
Polylang v3.2.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 / include / translated-post.php

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

304 lines 8.2 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 PLL_Model $model PLL_Model instance.
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|PLL_Language $lang Language (term_id or slug or object).
47 * @return void
48 */
49 public function set_language( $post_id, $lang ) {
50 $post_id = $this->sanitize_int_id( $post_id );
51
52 if ( empty( $post_id ) ) {
53 return;
54 }
55
56 $old_lang = $this->get_language( $post_id );
57 $old_lang = $old_lang ? $old_lang->slug : '';
58
59 $lang = $this->model->get_language( $lang );
60 $lang = $lang ? $lang->slug : '';
61
62 if ( $old_lang !== $lang ) {
63 wp_set_post_terms( $post_id, $lang, $this->tax_language );
64 }
65 }
66
67 /**
68 * Returns the language of a post
69 *
70 * @since 0.1
71 *
72 * @param int $post_id post id
73 * @return PLL_Language|false PLL_Language object, false if no language is associated to that post
74 */
75 public function get_language( $post_id ) {
76 $post_id = $this->sanitize_int_id( $post_id );
77
78 if ( empty( $post_id ) ) {
79 return false;
80 }
81
82 $lang = $this->get_object_term( $post_id, $this->tax_language );
83 return ! empty( $lang ) ? $this->model->get_language( $lang ) : false;
84 }
85
86 /**
87 * Deletes a translation.
88 *
89 * @since 0.5
90 *
91 * @param int $id Post id.
92 * @return void
93 */
94 public function delete_translation( $id ) {
95 $id = $this->sanitize_int_id( $id );
96
97 if ( empty( $id ) ) {
98 return;
99 }
100
101 parent::delete_translation( $id );
102 wp_set_object_terms( $id, array(), $this->tax_translations );
103 }
104
105 /**
106 * A join clause to add to sql queries when filtering by language is needed directly in query
107 *
108 * @since 1.2
109 *
110 * @param string $alias Alias for $wpdb->posts table
111 * @return string join clause
112 */
113 public function join_clause( $alias = '' ) {
114 global $wpdb;
115 if ( empty( $alias ) ) {
116 $alias = $wpdb->posts;
117 }
118 return " INNER JOIN $wpdb->term_relationships AS pll_tr ON pll_tr.object_id = $alias.ID";
119 }
120
121 /**
122 * Register the language taxonomy
123 *
124 * @since 1.2
125 *
126 * @return void
127 */
128 public function register_taxonomy() {
129 register_taxonomy(
130 $this->tax_language,
131 $this->model->get_translated_post_types(),
132 array(
133 'labels' => array(
134 'name' => __( 'Languages', 'polylang' ),
135 'singular_name' => __( 'Language', 'polylang' ),
136 'all_items' => __( 'All languages', 'polylang' ),
137 ),
138 'public' => false,
139 'show_ui' => false, // hide the taxonomy on admin side, needed for WP 4.4.x
140 'show_in_nav_menus' => false, // no metabox for nav menus, needed for WP 4.4.x
141 'publicly_queryable' => true, // since WP 4.5
142 'query_var' => 'lang',
143 'rewrite' => $this->model->options['force_lang'] < 2, // no rewrite for domains and sub-domains
144 '_pll' => true, // polylang taxonomy
145 )
146 );
147 }
148
149 /**
150 * Check if registered post type must be translated
151 *
152 * @since 1.2
153 *
154 * @param string $post_type post type name
155 * @return void
156 */
157 public function registered_post_type( $post_type ) {
158 if ( $this->model->is_translated_post_type( $post_type ) ) {
159 register_taxonomy_for_object_type( $this->tax_language, $post_type );
160 register_taxonomy_for_object_type( $this->tax_translations, $post_type );
161 }
162 }
163
164 /**
165 * Forces calling 'update_object_term_cache' when querying posts or pages.
166 * This is especially useful for nav menus with a lot of pages as, without doing this,
167 * we would have one query per page in the menu to get the page language for the permalink.
168 *
169 * @since 1.8
170 *
171 * @param WP_Query $query Reference to the query object.
172 * @return void
173 */
174 public function pre_get_posts( $query ) {
175 if ( ! empty( $query->query['post_type'] ) && $this->model->is_translated_post_type( $query->query['post_type'] ) ) {
176 $query->query_vars['update_post_term_cache'] = true;
177 }
178 }
179
180 /**
181 * Checks if the current user can read the post
182 *
183 * @since 1.5
184 *
185 * @param int $post_id Post ID
186 * @param string $context Optional, 'edit' or 'view', defaults to 'view'.
187 * @return bool
188 */
189 public function current_user_can_read( $post_id, $context = 'view' ) {
190 $post_id = $this->sanitize_int_id( $post_id );
191
192 if ( empty( $post_id ) ) {
193 return false;
194 }
195
196 $post = get_post( $post_id );
197
198 if ( empty( $post ) ) {
199 return false;
200 }
201
202 if ( 'inherit' === $post->post_status && $post->post_parent ) {
203 $post = get_post( $post->post_parent );
204
205 if ( empty( $post ) ) {
206 return false;
207 }
208 }
209
210 if ( 'inherit' === $post->post_status || in_array( $post->post_status, get_post_stati( array( 'public' => true ) ) ) ) {
211 return true;
212 }
213
214 // Follow WP practices, which shows links to private posts ( when readable ), but not for draft posts ( ex: get_adjacent_post_link() )
215 if ( in_array( $post->post_status, get_post_stati( array( 'private' => true ) ) ) ) {
216 if ( ! is_user_logged_in() ) {
217 return false;
218 }
219
220 $user = wp_get_current_user();
221
222 if ( (int) $user->ID === (int) $post->post_author ) {
223 return true;
224 }
225
226 $post_type_object = get_post_type_object( $post->post_type );
227
228 return ! empty( $post_type_object ) && current_user_can( $post_type_object->cap->read_private_posts );
229 }
230
231 // In edit context, show draft and future posts.
232 if ( 'edit' === $context ) {
233 $states = get_post_stati(
234 array(
235 'protected' => true,
236 'show_in_admin_all_list' => true,
237 )
238 );
239
240 if ( in_array( $post->post_status, $states ) ) {
241 $user = wp_get_current_user();
242 return is_user_logged_in() && ( current_user_can( 'edit_posts' ) || $user->ID == $post->post_author ); // Comparison must not be strict!
243 }
244 }
245
246 return false;
247 }
248
249 /**
250 * Returns a list of posts in a language ( $lang )
251 * not translated in another language ( $untranslated_in ).
252 *
253 * @since 2.6
254 *
255 * @param string $type Post type.
256 * @param PLL_Language $untranslated_in The language the posts must not be translated in.
257 * @param PLL_Language $lang Language of the searched posts.
258 * @param string $search Limit the results to the posts matching this string.
259 * @return WP_Post[] Array of posts.
260 */
261 public function get_untranslated( $type, $untranslated_in, $lang, $search = '' ) {
262 $return = array();
263
264 // Don't order by title: see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
265 $args = array(
266 's' => $search,
267 'suppress_filters' => 0, // To make the post_fields filter work
268 'lang' => 0, // Avoid admin language filter
269 'numberposts' => 20, // Limit to 20 posts
270 'post_status' => 'any',
271 'post_type' => $type,
272 'tax_query' => array(
273 array(
274 'taxonomy' => $this->tax_language,
275 'field' => 'term_taxonomy_id', // WP 3.5+
276 'terms' => $lang->term_taxonomy_id,
277 ),
278 ),
279 );
280
281 /**
282 * Filter the query args when auto suggesting untranslated posts in the Languages metabox
283 * This should help plugins to fix some edge cases
284 *
285 * @see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
286 *
287 * @since 1.7
288 *
289 * @param array $args WP_Query arguments
290 */
291 $args = apply_filters( 'pll_ajax_posts_not_translated_args', $args );
292 $posts = get_posts( $args );
293
294 foreach ( $posts as $post ) {
295 if ( $post instanceof WP_Post && ! $this->get_translation( $post->ID, $untranslated_in ) && $this->current_user_can_read( $post->ID, 'edit' ) ) {
296 $return[] = $post;
297 }
298 }
299
300 return $return;
301 }
302
303 }
304