PluginProbe
Polylang / 2.3
Polylang v2.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 / include / filters.php

filters.php in Polylang 2.3, at include/filters.php

272 lines 9.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Setup filters common to admin and frontend
5 *
6 * @since 1.4
7 */
8 class PLL_Filters {
9 public $links_model, $model, $options, $curlang;
10
11 /**
12 * Constructor: setups filters
13 *
14 * @since 1.4
15 *
16 * @param object $polylang
17 */
18 public function __construct( &$polylang ) {
19 $this->links_model = &$polylang->links_model;
20 $this->model = &$polylang->model;
21 $this->options = &$polylang->options;
22 $this->curlang = &$polylang->curlang;
23
24 // Filters the comments according to the current language
25 add_action( 'parse_comment_query', array( $this, 'parse_comment_query' ) );
26 add_filter( 'comments_clauses', array( $this, 'comments_clauses' ), 10, 2 );
27
28 // Filters the get_pages function according to the current language
29 add_filter( 'get_pages', array( $this, 'get_pages' ), 10, 2 );
30
31 // Rewrites next and previous post links to filter them by language
32 add_filter( 'get_previous_post_join', array( $this, 'posts_join' ), 10, 5 );
33 add_filter( 'get_next_post_join', array( $this, 'posts_join' ), 10, 5 );
34 add_filter( 'get_previous_post_where', array( $this, 'posts_where' ), 10, 5 );
35 add_filter( 'get_next_post_where', array( $this, 'posts_where' ), 10, 5 );
36
37 // Converts the locale to a valid W3C locale
38 add_filter( 'language_attributes', array( $this, 'language_attributes' ) );
39
40 // Prevents deleting all the translations of the default category
41 add_filter( 'map_meta_cap', array( $this, 'fix_delete_default_category' ), 10, 4 );
42
43 // Translate the site title in emails sent to users
44 add_filter( 'password_change_email', array( $this, 'translate_user_email' ) );
45 add_filter( 'email_change_email', array( $this, 'translate_user_email' ) );
46 }
47
48 /**
49 * Get the language to filter a comments query
50 *
51 * @since 2.0
52 *
53 * @param object $query
54 * @return object|bool the language(s) to use in the filter, false otherwise
55 */
56 protected function get_comments_queried_language( $query ) {
57 // Don't filter comments if comment ids or post ids are specified
58 $plucked = wp_array_slice_assoc( $query->query_vars, array( 'comment__in', 'parent', 'post_id', 'post__in', 'post_parent' ) );
59 $fields = array_filter( $plucked );
60 if ( ! empty( $fields ) ) {
61 return false;
62 }
63
64 // Don't filter comments if a non translated post type is specified
65 if ( ! empty( $query->query_vars['post_type'] ) && ! $this->model->is_translated_post_type( $query->query_vars['post_type'] ) ) {
66 return false;
67 }
68
69 return empty( $query->query_vars['lang'] ) ? $this->curlang : $this->model->get_language( $query->query_vars['lang'] );
70 }
71
72 /**
73 * Adds language dependent cache domain when querying comments
74 * Useful as the 'lang' parameter is not included in cache key by WordPress
75 * Needed since WP 4.6 as comments have been added to persistent cache. See #36906, #37419
76 *
77 * @since 2.0
78 *
79 * @param object $query
80 */
81 public function parse_comment_query( $query ) {
82 if ( $lang = $this->get_comments_queried_language( $query ) ) {
83 $key = '_' . ( is_array( $lang ) ? implode( ',', $lang ) : $this->model->get_language( $lang )->slug );
84 $query->query_vars['cache_domain'] = empty( $query->query_vars['cache_domain'] ) ? 'pll' . $key : $query->query_vars['cache_domain'] . $key;
85 }
86 }
87
88 /**
89 * Filters the comments according to the current language
90 * Used by the recent comments widget and admin language filter
91 *
92 * @since 0.2
93 *
94 * @param array $clauses sql clauses
95 * @param object $query WP_Comment_Query object
96 * @return array modified $clauses
97 */
98 public function comments_clauses( $clauses, $query ) {
99 global $wpdb;
100
101 $lang = $this->get_comments_queried_language( $query );
102
103 if ( ! empty( $lang ) ) {
104 // If this clause is not already added by WP
105 if ( ! strpos( $clauses['join'], '.ID' ) ) {
106 $clauses['join'] .= " JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
107 }
108
109 $clauses['join'] .= $this->model->post->join_clause();
110 $clauses['where'] .= $this->model->post->where_clause( $lang );
111 }
112 return $clauses;
113 }
114
115 /**
116 * Filters get_pages per language
117 *
118 * @since 1.4
119 *
120 * @param array $pages an array of pages already queried
121 * @param array $args get_pages arguments
122 * @return array modified list of pages
123 */
124 public function get_pages( $pages, $args ) {
125 if ( isset( $args['lang'] ) && empty( $args['lang'] ) ) {
126 return $pages;
127 }
128
129 $language = empty( $args['lang'] ) ? $this->curlang : $this->model->get_language( $args['lang'] );
130
131 if ( empty( $language ) || empty( $pages ) || ! $this->model->is_translated_post_type( $args['post_type'] ) ) {
132 return $pages;
133 }
134
135 static $once = false;
136
137 // Obliged to redo the get_pages query if we want to get the right number
138 if ( ! empty( $args['number'] ) && ! $once ) {
139 $once = true; // avoid infinite loop
140
141 $r = array(
142 'lang' => 0, // So this query is not filtered
143 'numberposts' => -1,
144 'nopaging' => true,
145 'post_type' => $args['post_type'],
146 'fields' => 'ids',
147 'tax_query' => array(
148 array(
149 'taxonomy' => 'language',
150 'field' => 'term_taxonomy_id', // Since WP 3.5
151 'terms' => $language->term_taxonomy_id,
152 'operator' => 'NOT IN',
153 ),
154 ),
155 );
156
157 $args['exclude'] = array_merge( $args['exclude'], get_posts( $r ) );
158 $pages = get_pages( $args );
159 }
160
161 $ids = wp_list_pluck( $pages, 'ID' );
162
163 // Filters the queried list of pages by language
164 if ( ! $once ) {
165 $ids = array_intersect( $ids, $this->model->post->get_objects_in_language( $language ) );
166
167 foreach ( $pages as $key => $page ) {
168 if ( ! in_array( $page->ID, $ids ) ) {
169 unset( $pages[ $key ] );
170 }
171 }
172
173 $pages = array_values( $pages ); // In case 3rd parties suppose the existence of $pages[0]
174 }
175
176 // Not done by WP but extremely useful for performance when manipulating taxonomies
177 update_object_term_cache( $ids, $args['post_type'] );
178
179 $once = false; // In case get_pages is called another time
180 return $pages;
181 }
182
183 /**
184 * Modifies the sql request for get_adjacent_post to filter by the current language
185 *
186 * @since 0.1
187 *
188 * @param string $sql The JOIN clause in the SQL.
189 * @param bool $in_same_term Whether post should be in a same taxonomy term.
190 * @param array $excluded_terms Array of excluded term IDs.
191 * @param string $taxonomy Taxonomy. Used to identify the term used when `$in_same_term` is true.
192 * @param WP_Post $post WP_Post object.
193 * @return string modified JOIN clause
194 */
195 public function posts_join( $sql, $in_same_term, $excluded_terms, $taxonomy = '', $post = null ) {
196 return $this->model->is_translated_post_type( $post->post_type ) && ! empty( $this->curlang ) ? $sql . $this->model->post->join_clause( 'p' ) : $sql;
197 }
198
199 /**
200 * Modifies the sql request for wp_get_archives and get_adjacent_post to filter by the current language
201 *
202 * @since 0.1
203 *
204 * @param string $sql The WHERE clause in the SQL.
205 * @param bool $in_same_term Whether post should be in a same taxonomy term.
206 * @param array $excluded_terms Array of excluded term IDs.
207 * @param string $taxonomy Taxonomy. Used to identify the term used when `$in_same_term` is true.
208 * @param WP_Post $post WP_Post object.
209 * @return string modified WHERE clause
210 */
211 public function posts_where( $sql, $in_same_term, $excluded_terms, $taxonomy = '', $post = null ) {
212 return $this->model->is_translated_post_type( $post->post_type ) && ! empty( $this->curlang ) ? $sql . $this->model->post->where_clause( $this->curlang ) : $sql;
213 }
214
215 /**
216 * Converts WordPress locale to valid W3 locale in html language attributes
217 *
218 * @since 1.8
219 *
220 * @param string $output language attributes
221 * @return string
222 */
223 public function language_attributes( $output ) {
224 if ( $language = $this->model->get_language( get_locale() ) ) {
225 $output = str_replace( '"' . get_bloginfo( 'language' ) . '"', '"' . $language->get_locale( 'display' ) . '"', $output );
226 }
227 return $output;
228 }
229
230
231 /**
232 * Prevents deleting all the translations of the default category
233 *
234 * @since 2.1
235 *
236 * @param array $caps The user's actual capabilities.
237 * @param string $cap Capability name.
238 * @param int $user_id The user ID.
239 * @param array $args Adds the context to the cap. The category id.
240 * @return array
241 */
242 public function fix_delete_default_category( $caps, $cap, $user_id, $args ) {
243 if ( 'delete_term' === $cap ) {
244 $term = get_term( reset( $args ) ); // Since WP 4.4, we can get the term to get the taxonomy
245 if ( $term instanceof WP_Term ) {
246 $default_cat = get_option( 'default_' . $term->taxonomy );
247 if ( $default_cat && array_intersect( $args, $this->model->term->get_translations( $default_cat ) ) ) {
248 $caps[] = 'do_not_allow';
249 }
250 }
251 }
252
253 return $caps;
254 }
255
256 /**
257 * Translates the site title in emails sent to the user (change email, reset password)
258 * It is necessary to filter the email because WP evaluates the site title before calling switch_to_locale()
259 *
260 * @since 2.1.3
261 *
262 * @param array $email
263 * @return array
264 */
265 function translate_user_email( $email ) {
266 $blog_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
267 $email['subject'] = sprintf( $email['subject'], $blog_name );
268 $email['message'] = str_replace( '###SITENAME###', $blog_name, $email['message'] );
269 return $email;
270 }
271 }
272