PluginProbe
Polylang / 2.3.2
Polylang v2.3.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 / filters.php

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

273 lines 9.3 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 // Take care that 'exclude' argument accepts integer or strings too
158 $args['exclude'] = array_merge( wp_parse_id_list( $args['exclude'] ), get_posts( $r ) );
159 $pages = get_pages( $args );
160 }
161
162 $ids = wp_list_pluck( $pages, 'ID' );
163
164 // Filters the queried list of pages by language
165 if ( ! $once ) {
166 $ids = array_intersect( $ids, $this->model->post->get_objects_in_language( $language ) );
167
168 foreach ( $pages as $key => $page ) {
169 if ( ! in_array( $page->ID, $ids ) ) {
170 unset( $pages[ $key ] );
171 }
172 }
173
174 $pages = array_values( $pages ); // In case 3rd parties suppose the existence of $pages[0]
175 }
176
177 // Not done by WP but extremely useful for performance when manipulating taxonomies
178 update_object_term_cache( $ids, $args['post_type'] );
179
180 $once = false; // In case get_pages is called another time
181 return $pages;
182 }
183
184 /**
185 * Modifies the sql request for get_adjacent_post to filter by the current language
186 *
187 * @since 0.1
188 *
189 * @param string $sql The JOIN clause in the SQL.
190 * @param bool $in_same_term Whether post should be in a same taxonomy term.
191 * @param array $excluded_terms Array of excluded term IDs.
192 * @param string $taxonomy Taxonomy. Used to identify the term used when `$in_same_term` is true.
193 * @param WP_Post $post WP_Post object.
194 * @return string modified JOIN clause
195 */
196 public function posts_join( $sql, $in_same_term, $excluded_terms, $taxonomy = '', $post = null ) {
197 return $this->model->is_translated_post_type( $post->post_type ) && ! empty( $this->curlang ) ? $sql . $this->model->post->join_clause( 'p' ) : $sql;
198 }
199
200 /**
201 * Modifies the sql request for wp_get_archives and get_adjacent_post to filter by the current language
202 *
203 * @since 0.1
204 *
205 * @param string $sql The WHERE clause in the SQL.
206 * @param bool $in_same_term Whether post should be in a same taxonomy term.
207 * @param array $excluded_terms Array of excluded term IDs.
208 * @param string $taxonomy Taxonomy. Used to identify the term used when `$in_same_term` is true.
209 * @param WP_Post $post WP_Post object.
210 * @return string modified WHERE clause
211 */
212 public function posts_where( $sql, $in_same_term, $excluded_terms, $taxonomy = '', $post = null ) {
213 return $this->model->is_translated_post_type( $post->post_type ) && ! empty( $this->curlang ) ? $sql . $this->model->post->where_clause( $this->curlang ) : $sql;
214 }
215
216 /**
217 * Converts WordPress locale to valid W3 locale in html language attributes
218 *
219 * @since 1.8
220 *
221 * @param string $output language attributes
222 * @return string
223 */
224 public function language_attributes( $output ) {
225 if ( $language = $this->model->get_language( get_locale() ) ) {
226 $output = str_replace( '"' . get_bloginfo( 'language' ) . '"', '"' . $language->get_locale( 'display' ) . '"', $output );
227 }
228 return $output;
229 }
230
231
232 /**
233 * Prevents deleting all the translations of the default category
234 *
235 * @since 2.1
236 *
237 * @param array $caps The user's actual capabilities.
238 * @param string $cap Capability name.
239 * @param int $user_id The user ID.
240 * @param array $args Adds the context to the cap. The category id.
241 * @return array
242 */
243 public function fix_delete_default_category( $caps, $cap, $user_id, $args ) {
244 if ( 'delete_term' === $cap ) {
245 $term = get_term( reset( $args ) ); // Since WP 4.4, we can get the term to get the taxonomy
246 if ( $term instanceof WP_Term ) {
247 $default_cat = get_option( 'default_' . $term->taxonomy );
248 if ( $default_cat && array_intersect( $args, $this->model->term->get_translations( $default_cat ) ) ) {
249 $caps[] = 'do_not_allow';
250 }
251 }
252 }
253
254 return $caps;
255 }
256
257 /**
258 * Translates the site title in emails sent to the user (change email, reset password)
259 * It is necessary to filter the email because WP evaluates the site title before calling switch_to_locale()
260 *
261 * @since 2.1.3
262 *
263 * @param array $email
264 * @return array
265 */
266 function translate_user_email( $email ) {
267 $blog_name = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES );
268 $email['subject'] = sprintf( $email['subject'], $blog_name );
269 $email['message'] = str_replace( '###SITENAME###', $blog_name, $email['message'] );
270 return $email;
271 }
272 }
273