PluginProbe
Polylang / trunk
Polylang vtrunk
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 / src / frontend / frontend-static-pages.php

frontend-static-pages.php in Polylang trunk, at src/frontend/frontend-static-pages.php

321 lines 9.8 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 * Manages the static front page and the page for posts on frontend
8 *
9 * @since 1.8
10 */
11 class PLL_Frontend_Static_Pages extends PLL_Static_Pages {
12 /**
13 * Instance of a child class of PLL_Links_Model.
14 *
15 * @var PLL_Links_Model
16 */
17 protected $links_model;
18
19 /**
20 * @var PLL_Frontend_Links|null
21 */
22 protected $links;
23
24 /**
25 * Stores plugin's options.
26 *
27 * @var \WP_Syntex\Polylang\Options\Options
28 */
29 protected $options;
30
31 /**
32 * Constructor: setups filters and actions.
33 *
34 * @since 1.8
35 *
36 * @param PLL_Frontend $polylang The Polylang object.
37 */
38 public function __construct( PLL_Frontend &$polylang ) {
39 parent::__construct( $polylang );
40
41 $this->links_model = &$polylang->links_model;
42 $this->links = &$polylang->links;
43 $this->options = $polylang->options;
44
45 add_action( 'pll_home_requested', array( $this, 'pll_home_requested' ) );
46
47 // Manages the redirection of the homepage.
48 add_filter( 'redirect_canonical', array( $this, 'redirect_canonical' ) );
49
50 add_filter( 'pll_pre_translation_url', array( $this, 'pll_pre_translation_url' ), 10, 3 );
51 add_filter( 'pll_check_canonical_url', array( $this, 'pll_check_canonical_url' ) );
52
53 add_filter( 'pll_set_language_from_query', array( $this, 'page_on_front_query' ), 10, 2 );
54 add_filter( 'pll_set_language_from_query', array( $this, 'page_for_posts_query' ), 10, 2 );
55
56 // Specific cases for the customizer.
57 add_action( 'customize_register', array( $this, 'filter_customizer' ) );
58 }
59
60 /**
61 * Translates the page_id query var when the site root page is requested
62 *
63 * @since 1.8
64 *
65 * @return void
66 */
67 public function pll_home_requested() {
68 set_query_var( 'page_id', $this->curlang->page_on_front );
69 }
70
71 /**
72 * Manages the canonical redirect of the homepage when using a page on front.
73 *
74 * @since 0.1
75 *
76 * @param string $redirect_url The redirect url.
77 * @return string|false The modified url, false if the redirect is canceled.
78 */
79 public function redirect_canonical( $redirect_url ) {
80 if ( is_page() && ! is_feed() && get_queried_object_id() == $this->curlang->page_on_front ) {
81 $url = is_paged() ? $this->links_model->add_paged_to_link( $this->links->get_home_url(), get_query_var( 'page' ) ) : $this->links->get_home_url();
82
83 // Don't forget additional query vars
84 $query = wp_parse_url( $redirect_url, PHP_URL_QUERY );
85 if ( ! empty( $query ) ) {
86 parse_str( $query, $query_vars );
87 $query_vars = rawurlencode_deep( $query_vars ); // WP encodes query vars values
88 $url = add_query_arg( $query_vars, $url );
89 }
90
91 return $url;
92 }
93
94 return $redirect_url;
95 }
96
97 /**
98 * Translates the url of the page on front and page for posts.
99 *
100 * @since 1.8
101 *
102 * @param string $url Empty string or the url of the translation of the current page.
103 * @param PLL_Language $language Language of the translation.
104 * @param int $queried_object_id Queried object ID.
105 * @return string The translation url.
106 */
107 public function pll_pre_translation_url( $url, $language, $queried_object_id ) {
108 if ( empty( $queried_object_id ) ) {
109 return $url;
110 }
111
112 // Page for posts.
113 if ( $GLOBALS['wp_query']->is_posts_page ) {
114 $id = $this->model->post->get( $queried_object_id, $language );
115
116 if ( ! empty( $id ) ) {
117 return (string) get_permalink( $id );
118 }
119 }
120
121 // Page on front.
122 if ( is_front_page() && ! empty( $language->page_on_front ) ) {
123 $id = $this->model->post->get( $queried_object_id, $language );
124
125 if ( $language->page_on_front === $id ) {
126 return $language->get_home_url();
127 }
128 }
129
130 return $url;
131 }
132
133 /**
134 * Prevents the canonical redirect if we are on a static front page.
135 *
136 * @since 1.8
137 *
138 * @param string $redirect_url The redirect url.
139 * @return string|false
140 */
141 public function pll_check_canonical_url( $redirect_url ) {
142 return $this->options['redirect_lang'] && ! $this->options['force_lang'] && ! empty( $this->curlang->page_on_front ) && is_page( $this->curlang->page_on_front ) ? false : $redirect_url;
143 }
144
145 /**
146 * Is the query for a the static front page (redirected from the language page)?
147 *
148 * @since 2.3
149 *
150 * @param WP_Query $query The WP_Query object.
151 * @return bool
152 */
153 protected function is_front_page( $query ) {
154 $query = array_diff( array_keys( (array) $query->query ), array( 'preview', 'page', 'paged', 'cpage', 'orderby' ) );
155 return 1 === count( $query ) && in_array( 'lang', $query );
156 }
157
158 /**
159 * Setups query vars when requesting a static front page
160 *
161 * @since 1.8
162 *
163 * @param PLL_Language|false $lang The current language, false if it is not set yet.
164 * @param WP_Query $query The main WP query.
165 * @return PLL_Language|false
166 */
167 public function page_on_front_query( $lang, $query ) {
168 if ( ! empty( $lang ) || ! $this->page_on_front ) {
169 return $lang;
170 }
171
172 // Redirect the language page to the homepage when using a static front page
173 if ( ( $this->options['redirect_lang'] || $this->options['hide_default'] ) && $this->is_front_page( $query ) && $lang = $this->model->get_language( get_query_var( 'lang' ) ) ) {
174 $query->is_archive = false;
175 $query->is_tax = false;
176 if ( 'page' === get_option( 'show_on_front' ) && ! empty( $lang->page_on_front ) ) {
177 $query->set( 'page_id', $lang->page_on_front );
178 $query->is_singular = true;
179 $query->is_page = true;
180 unset( $query->query_vars['lang'], $query->queried_object ); // Reset queried object
181 } else {
182 // Handle case where the static front page hasn't be translated to avoid a possible infinite redirect loop.
183 $query->is_home = true;
184 }
185 }
186
187 // Fix paged static front page in plain permalinks when Settings > Reading doesn't match the default language
188 elseif ( ! $this->links_model->using_permalinks && count( (array) $query->query ) === 1 && ! empty( $query->query['page'] ) ) {
189 $lang = $this->model->get_default_language();
190 if ( empty( $lang ) ) {
191 return $lang;
192 }
193 $query->set( 'page_id', $lang->page_on_front );
194 $query->is_singular = true;
195 $query->is_page = true;
196 $query->is_archive = false;
197 $query->is_tax = false;
198 unset( $query->query_vars['lang'], $query->queried_object ); // Reset queried object
199 }
200
201 // Set the language when requesting a static front page
202 else {
203 $page_id = $this->get_page_id( $query );
204 $languages = $this->model->get_languages_list();
205 $pages = wp_list_pluck( $languages, 'page_on_front' );
206
207 if ( ! empty( $page_id ) && false !== $n = array_search( $page_id, $pages ) ) {
208 $lang = $languages[ $n ];
209 }
210 }
211
212 // Fix <!--nextpage--> for page_on_front
213 if ( ( $this->options['force_lang'] < 2 || ! $this->options['redirect_lang'] ) && $this->links_model->using_permalinks && ! empty( $lang ) && isset( $query->query['paged'] ) ) {
214 $query->set( 'page', $query->query['paged'] );
215 unset( $query->query['paged'] );
216 } elseif ( ! $this->links_model->using_permalinks && ! empty( $query->query['page'] ) ) {
217 $query->is_paged = true;
218 }
219
220 return $lang;
221 }
222
223 /**
224 * Setups query vars when requesting a posts page
225 *
226 * @since 1.8
227 *
228 * @param PLL_Language|false $lang The current language, false if it is not set yet.
229 * @param WP_Query $query The main WP query.
230 * @return PLL_Language|false
231 */
232 public function page_for_posts_query( $lang, $query ) {
233 if ( ! empty( $lang ) || ! $this->page_for_posts ) {
234 return $lang;
235 }
236
237 $page_id = $this->get_page_id( $query );
238
239 if ( empty( $page_id ) ) {
240 return $lang;
241 }
242
243 $pages = $this->model->get_languages_list( array( 'fields' => 'page_for_posts' ) );
244 $pages = array_filter( $pages );
245
246 if ( in_array( $page_id, $pages ) ) {
247 _prime_post_caches( $pages ); // Fill the cache with all pages for posts to avoid one query per page later.
248
249 $lang = $this->model->post->get_language( $page_id );
250 $query->is_singular = false;
251 $query->is_page = false;
252 $query->is_home = true;
253 $query->is_posts_page = true;
254 }
255
256 return $lang;
257 }
258
259 /**
260 * Get the queried page_id (if it exists ).
261 *
262 * If permalinks are used, WordPress does set and use `$query->queried_object_id` and sets `$query->query_vars['page_id']` to 0,
263 * and does set and use `$query->query_vars['page_id']` if permalinks are not used :(.
264 *
265 * @since 1.5
266 *
267 * @param WP_Query $query Instance of WP_Query.
268 * @return int The page_id.
269 */
270 protected function get_page_id( $query ) {
271 if ( ! empty( $query->query_vars['pagename'] ) && isset( $query->queried_object_id ) ) {
272 return $query->queried_object_id;
273 }
274
275 return $query->query_vars['page_id'] ?? 0; // No page queried.
276 }
277
278 /**
279 * Adds support for the theme customizer.
280 *
281 * @since 3.4.2
282 *
283 * @return void
284 */
285 public function filter_customizer() {
286 add_filter( 'pre_option_page_on_front', array( $this, 'customize_page' ), 20 ); // After the customizer.
287 add_filter( 'pre_option_page_for_post', array( $this, 'customize_page' ), 20 );
288
289 add_filter( 'pll_pre_translation_url', array( $this, 'customize_translation_url' ), 20, 2 ); // After the generic hook in this class.
290 }
291
292 /**
293 * Translates the page ID when customized.
294 *
295 * @since 3.4.2
296 *
297 * @param int|false $pre A page ID if the setting is customized, false otherwise.
298 * @return int|false
299 */
300 public function customize_page( $pre ) {
301 return is_numeric( $pre ) ? pll_get_post( (int) $pre ) : $pre;
302 }
303
304 /**
305 * Fixes the translation URL if the option 'show_on_front' is customized.
306 *
307 * @since 3.4.2
308 *
309 * @param string $url An empty string or the URL of the translation of the current page.
310 * @param PLL_Language $language The language of the translation.
311 * @return string
312 */
313 public function customize_translation_url( $url, $language ) {
314 if ( 'posts' === get_option( 'show_on_front' ) && is_front_page() ) {
315 // When the page on front displays posts, the home URL is the same as the search URL.
316 return $language->get_search_url();
317 }
318 return $url;
319 }
320 }
321