PluginProbe
Polylang / 2.0.12
Polylang v2.0.12
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 / links-directory.php

links-directory.php in Polylang 2.0.12, at include/links-directory.php

255 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Links model for use when the language code is added in url as a directory
5 * for example mysite.com/en/something
6 * implements the "links_model interface"
7 *
8 * @since 1.2
9 */
10 class PLL_Links_Directory extends PLL_Links_Permalinks {
11
12 /**
13 * Constructor
14 *
15 * @since 1.2
16 *
17 * @param object $model PLL_Model instance
18 */
19 public function __construct( &$model ) {
20 parent::__construct( $model );
21
22 if ( did_action( 'pll_init' ) ) {
23 $this->init();
24 } else {
25 add_action( 'pll_init', array( $this, 'init' ) );
26 }
27 }
28
29 /**
30 * Called only at first object creation to avoid duplicating filters when switching blog
31 *
32 * @since 1.6
33 */
34 public function init() {
35 if ( did_action( 'setup_theme' ) ) {
36 $this->add_permastruct();
37 } else {
38 add_action( 'setup_theme', array( $this, 'add_permastruct' ), 2 );
39 }
40
41 // Make sure to prepare rewrite rules when flushing
42 add_action( 'pre_option_rewrite_rules', array( $this, 'prepare_rewrite_rules' ) );
43 }
44
45 /**
46 * Adds the language code in url
47 * links_model interface
48 *
49 * @since 1.2
50 *
51 * @param string $url url to modify
52 * @param object $lang language
53 * @return string modified url
54 */
55 public function add_language_to_link( $url, $lang ) {
56 if ( ! empty( $lang ) ) {
57 $base = $this->options['rewrite'] ? '' : 'language/';
58 $slug = $this->options['default_lang'] == $lang->slug && $this->options['hide_default'] ? '' : $base . $lang->slug . '/';
59 return str_replace( $this->home . '/' . $this->root, $this->home . '/' . $this->root . $slug, $url );
60 }
61 return $url;
62 }
63
64 /**
65 * Returns the url without language code
66 * links_model interface
67 *
68 * @since 1.2
69 *
70 * @param string $url url to modify
71 * @return string modified url
72 */
73 function remove_language_from_link( $url ) {
74 foreach ( $this->model->get_languages_list() as $language ) {
75 if ( ! $this->options['hide_default'] || $this->options['default_lang'] != $language->slug ) {
76 $languages[] = $language->slug;
77 }
78 }
79
80 if ( ! empty( $languages ) ) {
81 $pattern = str_replace( '/', '\/', $this->home . '/' . $this->root );
82 $pattern = '#' . $pattern . ( $this->options['rewrite'] ? '' : 'language\/' ) . '('.implode( '|', $languages ).')(\/|$)#';
83 $url = preg_replace( $pattern, $this->home . '/' . $this->root, $url );
84 }
85 return $url;
86 }
87
88 /**
89 * Returns the language based on language code in url
90 * links_model interface
91 *
92 * @since 1.2
93 * @since 2.0 add $url argument
94 *
95 * @param string $url optional, defaults to current url
96 * @return string language slug
97 */
98 public function get_language_from_url( $url = '' ) {
99 if ( empty( $url ) ) {
100 $url = ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
101 }
102
103 $pattern = str_replace( '/', '\/', $this->home . '/' . $this->root . ( $this->options['rewrite'] ? '' : 'language/' ) );
104 $pattern = '#' . $pattern . '('. implode( '|', $this->model->get_languages_list( array( 'fields' => 'slug' ) ) ) . ')(\/|$)#';
105 return preg_match( $pattern, trailingslashit( $url ), $matches ) ? $matches[1] : ''; // $matches[1] is the slug of the requested language
106 }
107
108 /**
109 * Returns the home url
110 * links_model interface
111 *
112 * @since 1.3.1
113 *
114 * @param object $lang PLL_Language object
115 * @return string
116 */
117 public function home_url( $lang ) {
118 $base = $this->options['rewrite'] ? '' : 'language/';
119 $slug = $this->options['default_lang'] == $lang->slug && $this->options['hide_default'] ? '' : '/' . $this->root . $base . $lang->slug;
120 return trailingslashit( $this->home . $slug );
121 }
122
123 /**
124 * Optionaly removes 'language' in permalinks so that we get http://www.myblog/en/ instead of http://www.myblog/language/en/
125 *
126 * @since 1.2
127 */
128 function add_permastruct() {
129 // Language information always in front of the uri ( 'with_front' => false )
130 // The 3rd parameter structure has been modified in WP 3.4
131 // Leads to error 404 for pages when there is no language created yet
132 if ( $this->model->get_languages_list() ) {
133 add_permastruct( 'language', $this->options['rewrite'] ? '%language%' : 'language/%language%', array( 'with_front' => false ) );
134 }
135 }
136
137 /**
138 * Prepares rewrite rules filters
139 *
140 * @since 0.8.1
141 *
142 * @param array $pre not used
143 * @return unmodified $pre
144 */
145 public function prepare_rewrite_rules( $pre ) {
146 // Don't modify the rules if there is no languages created yet
147 // Make sure to add filter only once and if all custom post types and taxonomies have been registered
148 if ( $this->model->get_languages_list() && did_action( 'wp_loaded' ) && ! has_filter( 'language_rewrite_rules', '__return_empty_array' ) ) {
149 // Suppress the rules created by WordPress for our taxonomy
150 add_filter( 'language_rewrite_rules', '__return_empty_array' );
151
152 foreach ( $this->get_rewrite_rules_filters() as $type ) {
153 add_filter( $type . '_rewrite_rules', array( $this, 'rewrite_rules' ) );
154 }
155
156 add_filter( 'rewrite_rules_array', array( $this, 'rewrite_rules' ) ); // needed for post type archives
157 }
158 return $pre;
159 }
160
161 /**
162 * The rewrite rules !
163 * always make sure the default language is at the end in case the language information is hidden for default language
164 * thanks to brbrbr http://wordpress.org/support/topic/plugin-polylang-rewrite-rules-not-correct
165 *
166 * @since 0.8.1
167 *
168 * @param array $rules rewrite rules
169 * @return array modified rewrite rules
170 */
171 public function rewrite_rules( $rules ) {
172 $filter = str_replace( '_rewrite_rules', '', current_filter() );
173
174 global $wp_rewrite;
175 $newrules = array();
176
177 $languages = $this->model->get_languages_list( array( 'fields' => 'slug' ) );
178 if ( $this->options['hide_default'] ) {
179 $languages = array_diff( $languages, array( $this->options['default_lang'] ) );
180 }
181
182 if ( ! empty( $languages ) ) {
183 $slug = $wp_rewrite->root . ( $this->options['rewrite'] ? '' : 'language/' ) . '(' . implode( '|', $languages ) . ')/';
184 }
185
186 // For custom post type archives
187 $cpts = array_intersect( $this->model->get_translated_post_types(), get_post_types( array( '_builtin' => false ) ) );
188 $cpts = $cpts ? '#post_type=(' . implode( '|', $cpts ) . ')#' : '';
189
190 foreach ( $rules as $key => $rule ) {
191 // Special case for translated post types and taxonomies to allow canonical redirection
192 if ( $this->options['force_lang'] && in_array( $filter, array_merge( $this->model->get_translated_post_types(), $this->model->get_translated_taxonomies() ) ) ) {
193
194 /**
195 * Filters the rewrite rules to modify
196 *
197 * @since 1.9.1
198 *
199 * @param bool $modify whether to modify or not the rule, defaults to true
200 * @param array $rule original rewrite rule
201 * @param string $filter current set of rules being modified
202 * @param string|bool $archive custom post post type archive name or false if it is not a cpt archive
203 */
204 if ( ! apply_filters( 'pll_modify_rewrite_rule', true, array( $key => $rule ), $filter, false ) ) {
205 continue;
206 }
207
208 if ( isset( $slug ) ) {
209 $newrules[ $slug . str_replace( $wp_rewrite->root, '', $key ) ] = str_replace(
210 array( '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]', '?' ),
211 array( '[9]', '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '?lang=$matches[1]&' ),
212 $rule
213 ); // Should be enough!
214 }
215
216 if ( $this->options['hide_default'] ) {
217 $newrules[ $key ] = $rules[ $key ];
218 // Unset only if we hide the code for the default language as check_language_code_in_url will do its job in other cases
219 unset( $rules[ $key ] );
220 }
221 }
222
223 // Rewrite rules filtered by language
224 elseif ( in_array( $filter, $this->always_rewrite ) || in_array( $filter, $this->model->get_filtered_taxonomies() ) || ( $cpts && preg_match( $cpts, $rule, $matches ) && ! strpos( $rule, 'name=' ) ) || ( 'rewrite_rules_array' != $filter && $this->options['force_lang'] ) ) {
225
226 /** This filter is documented in include/links-directory.php */
227 if ( ! apply_filters( 'pll_modify_rewrite_rule', true, array( $key => $rule ), $filter, empty( $matches[1] ) ? false : $matches[1] ) ) {
228 continue;
229 }
230
231 if ( isset( $slug ) ) {
232 $newrules[ $slug . str_replace( $wp_rewrite->root, '', $key ) ] = str_replace(
233 array( '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '[1]', '?' ),
234 array( '[9]', '[8]', '[7]', '[6]', '[5]', '[4]', '[3]', '[2]', '?lang=$matches[1]&' ),
235 $rule
236 ); // Should be enough!
237 }
238
239 if ( $this->options['hide_default'] ) {
240 $newrules[ $key ] = str_replace( '?', '?lang=' . $this->options['default_lang'] . '&', $rule );
241 }
242
243 unset( $rules[ $key ] ); // Now useless
244 }
245 }
246
247 // The home rewrite rule
248 if ( 'root' == $filter && isset( $slug ) ) {
249 $newrules[ $slug . '?$' ] = $wp_rewrite->index.'?lang=$matches[1]';
250 }
251
252 return $newrules + $rules;
253 }
254 }
255