PluginProbe
Polylang / 3.6.7
Polylang v3.6.7
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 / frontend / frontend.php

frontend.php in Polylang 3.6.7, at frontend/frontend.php

288 lines 8.4 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 * Main Polylang class when on frontend, accessible from @see PLL().
8 *
9 * @since 1.2
10 */
11 class PLL_Frontend extends PLL_Base {
12 /**
13 * Current language.
14 *
15 * @var PLL_Language|null
16 */
17 public $curlang;
18
19 /**
20 * @var PLL_Frontend_Auto_Translate|null
21 */
22 public $auto_translate;
23
24 /**
25 * The class selecting the current language.
26 *
27 * @var PLL_Choose_Lang|null
28 */
29 public $choose_lang;
30
31 /**
32 * @var PLL_Frontend_Filters|null
33 */
34 public $filters;
35
36 /**
37 * @var PLL_Frontend_Filters_Links|null
38 */
39 public $filters_links;
40
41 /**
42 * @var PLL_Frontend_Filters_Search|null
43 */
44 public $filters_search;
45
46 /**
47 * @var PLL_Frontend_Links|null
48 */
49 public $links;
50
51 /**
52 * @var PLL_Frontend_Nav_Menu|null
53 */
54 public $nav_menu;
55
56 /**
57 * @var PLL_Frontend_Static_Pages|null
58 */
59 public $static_pages;
60
61 /**
62 * @var PLL_Frontend_Filters_Widgets|null
63 */
64 public $filters_widgets;
65
66 /**
67 * Constructor.
68 *
69 * @since 1.2
70 *
71 * @param PLL_Links_Model $links_model Reference to the links model.
72 */
73 public function __construct( &$links_model ) {
74 parent::__construct( $links_model );
75
76 add_action( 'pll_language_defined', array( $this, 'pll_language_defined' ), 1 );
77
78 // Avoids the language being the queried object when querying multiple taxonomies
79 add_action( 'parse_tax_query', array( $this, 'parse_tax_query' ), 1 );
80
81 // Filters posts by language
82 add_action( 'parse_query', array( $this, 'parse_query' ), 6 );
83
84 // Not before 'check_canonical_url'
85 if ( ! defined( 'PLL_AUTO_TRANSLATE' ) || PLL_AUTO_TRANSLATE ) {
86 add_action( 'template_redirect', array( $this, 'auto_translate' ), 7 );
87 }
88
89 add_action( 'admin_bar_menu', array( $this, 'remove_customize_admin_bar' ), 41 ); // After WP_Admin_Bar::add_menus
90
91 /*
92 * Static front page and page for posts.
93 *
94 * Early instantiated to be able to correctly initialize language properties.
95 * Also loaded in customizer preview, directly reading the request as we act before WP.
96 */
97 if ( 'page' === get_option( 'show_on_front' ) || ( isset( $_REQUEST['wp_customize'] ) && 'on' === $_REQUEST['wp_customize'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
98 $this->static_pages = new PLL_Frontend_Static_Pages( $this );
99 }
100
101 $this->model->set_languages_ready();
102 }
103
104 /**
105 * Setups the language chooser based on options
106 *
107 * @since 1.2
108 */
109 public function init() {
110 parent::init();
111
112 $this->links = new PLL_Frontend_Links( $this );
113
114 // Setup the language chooser
115 $c = array( 'Content', 'Url', 'Url', 'Domain' );
116 $class = 'PLL_Choose_Lang_' . $c[ $this->options['force_lang'] ];
117 $this->choose_lang = new $class( $this );
118 $this->choose_lang->init();
119
120 // Need to load nav menu class early to correctly define the locations in the customizer when the language is set from the content
121 $this->nav_menu = new PLL_Frontend_Nav_Menu( $this );
122 }
123
124 /**
125 * Setups filters and nav menus once the language has been defined
126 *
127 * @since 1.2
128 *
129 * @return void
130 */
131 public function pll_language_defined() {
132 // Filters
133 $this->filters_links = new PLL_Frontend_Filters_Links( $this );
134 $this->filters = new PLL_Frontend_Filters( $this );
135 $this->filters_search = new PLL_Frontend_Filters_Search( $this );
136 $this->filters_widgets = new PLL_Frontend_Filters_Widgets( $this );
137
138 /*
139 * Redirects to canonical url before WordPress redirect_canonical
140 * but after Nextgen Gallery which hacks $_SERVER['REQUEST_URI'] !!!
141 * and restores it in 'template_redirect' with priority 1.
142 */
143 $this->canonical = new PLL_Canonical( $this );
144 add_action( 'template_redirect', array( $this->canonical, 'check_canonical_url' ), 4 );
145
146 // Auto translate for Ajax
147 if ( ( ! defined( 'PLL_AUTO_TRANSLATE' ) || PLL_AUTO_TRANSLATE ) && wp_doing_ajax() ) {
148 $this->auto_translate();
149 }
150 }
151
152 /**
153 * When querying multiple taxonomies, makes sure that the language is not the queried object.
154 *
155 * @since 1.8
156 *
157 * @param WP_Query $query WP_Query object.
158 * @return void
159 */
160 public function parse_tax_query( $query ) {
161 $pll_query = new PLL_Query( $query, $this->model );
162 $queried_taxonomies = $pll_query->get_queried_taxonomies();
163
164 if ( ! empty( $queried_taxonomies ) && 'language' == reset( $queried_taxonomies ) ) {
165 $query->tax_query->queried_terms['language'] = array_shift( $query->tax_query->queried_terms );
166 }
167 }
168
169 /**
170 * Modifies some query vars to "hide" that the language is a taxonomy and avoid conflicts.
171 *
172 * @since 1.2
173 *
174 * @param WP_Query $query WP_Query object.
175 * @return void
176 */
177 public function parse_query( $query ) {
178 $qv = $query->query_vars;
179 $pll_query = new PLL_Query( $query, $this->model );
180 $taxonomies = $pll_query->get_queried_taxonomies();
181
182 // Allow filtering recent posts and secondary queries by the current language
183 if ( ! empty( $this->curlang ) ) {
184 $pll_query->filter_query( $this->curlang );
185 }
186
187 // Modifies query vars when the language is queried
188 if ( ! empty( $qv['lang'] ) || ( ! empty( $taxonomies ) && array( 'language' ) == array_values( $taxonomies ) ) ) {
189 // Do we query a custom taxonomy?
190 $taxonomies = array_diff( $taxonomies, array( 'language', 'category', 'post_tag' ) );
191
192 // Remove pages query when the language is set unless we do a search
193 // Take care not to break the single page, attachment and taxonomies queries!
194 if ( empty( $qv['post_type'] ) && ! $query->is_search && ! $query->is_singular && empty( $taxonomies ) && ! $query->is_category && ! $query->is_tag ) {
195 $query->set( 'post_type', 'post' );
196 }
197
198 // Unset the is_archive flag for language pages to prevent loading the archive template
199 // Keep archive flag for comment feed otherwise the language filter does not work
200 if ( empty( $taxonomies ) && ! $query->is_comment_feed && ! $query->is_post_type_archive && ! $query->is_date && ! $query->is_author && ! $query->is_category && ! $query->is_tag ) {
201 $query->is_archive = false;
202 }
203
204 // Unset the is_tax flag except if another custom tax is queried
205 if ( empty( $taxonomies ) && ( $query->is_category || $query->is_tag || $query->is_author || $query->is_post_type_archive || $query->is_date || $query->is_search || $query->is_feed ) ) {
206 $query->is_tax = false;
207 unset( $query->queried_object ); // FIXME useless?
208 }
209 }
210 }
211
212 /**
213 * Auto translate posts and terms ids
214 *
215 * @since 1.2
216 *
217 * @return void
218 */
219 public function auto_translate() {
220 $this->auto_translate = new PLL_Frontend_Auto_Translate( $this );
221 }
222
223 /**
224 * Resets some variables when the blog is switched.
225 * Overrides the parent method.
226 *
227 * @since 1.5.1
228 *
229 * @param int $new_blog_id New blog ID.
230 * @param int $prev_blog_id Previous blog ID.
231 * @return void
232 */
233 public function switch_blog( $new_blog_id, $prev_blog_id ) {
234 if ( (int) $new_blog_id === (int) $prev_blog_id ) {
235 // Do nothing if same blog.
236 return;
237 }
238
239 parent::switch_blog( $new_blog_id, $prev_blog_id );
240
241 // Need to check that some languages are defined when user is logged in, has several blogs, some without any languages.
242 if ( ! $this->is_active_on_current_site() || ! $this->model->has_languages() || ! did_action( 'pll_language_defined' ) ) {
243 return;
244 }
245
246 static $restore_curlang;
247
248 if ( empty( $restore_curlang ) ) {
249 $restore_curlang = $this->curlang->slug; // To always remember the current language through blogs.
250 }
251
252 $lang = $this->model->get_language( $restore_curlang );
253 $this->curlang = $lang ? $lang : $this->model->get_default_language();
254 if ( empty( $this->curlang ) ) {
255 return;
256 }
257
258 if ( isset( $this->static_pages ) ) {
259 $this->static_pages->init();
260 }
261
262 // Send the slug instead of the locale here to avoid conflicts with same locales.
263 $this->load_strings_translations( $this->curlang->slug );
264 }
265
266 /**
267 * Remove the customize admin bar on front-end when using a block theme.
268 *
269 * WordPress removes the Customizer menu if a block theme is activated and no other plugins interact with it.
270 * As Polylang interacts with the Customizer, we have to delete this menu ourselves in the case of a block theme,
271 * unless another plugin than Polylang interacts with the Customizer.
272 *
273 * @since 3.2
274 *
275 * @return void
276 */
277 public function remove_customize_admin_bar() {
278 if ( ! $this->should_customize_menu_be_removed() ) {
279 return;
280 }
281
282 global $wp_admin_bar;
283
284 remove_action( 'wp_before_admin_bar_render', 'wp_customize_support_script' ); // To avoid the script launch.
285 $wp_admin_bar->remove_menu( 'customize' );
286 }
287 }
288