PluginProbe
Polylang / 3.7.7
Polylang v3.7.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
← All changes | include/class-polylang.php +105 -103 2.73.7.7 View file →
@@ -1,9 +1,15 @@
1 1 <?php
2 +/**
3 + * @package Polylang
4 + */
2 5
6 +use WP_Syntex\Polylang\Options\Options;
7 +use WP_Syntex\Polylang\Options\Registry as Options_Registry;
8 +
3 9 if ( ! defined( 'ABSPATH' ) ) {
4 10 exit; // Don't access directly
5 -};
11 +}
6 12
7 13 // Default directory to store user data such as custom flags
8 14 if ( ! defined( 'PLL_LOCAL_DIR' ) ) {
9 15 define( 'PLL_LOCAL_DIR', WP_CONTENT_DIR . '/polylang' );
@@ -9,9 +15,9 @@
9 15 define( 'PLL_LOCAL_DIR', WP_CONTENT_DIR . '/polylang' );
10 16 }
11 17
12 18 // Includes local config file if exists
13 -if ( file_exists( PLL_LOCAL_DIR . '/pll-config.php' ) ) {
19 +if ( is_readable( PLL_LOCAL_DIR . '/pll-config.php' ) ) {
14 20 include_once PLL_LOCAL_DIR . '/pll-config.php';
15 21 }
16 22
17 23 /**
@@ -17,8 +23,10 @@
17 23 /**
18 24 * Controls the plugin, as well as activation, and deactivation
19 25 *
20 26 * @since 0.1
27 + *
28 + * @template TPLLClass of PLL_Base
21 29 */
22 30 class Polylang {
23 31
24 32 /**
@@ -26,10 +34,9 @@
26 34 *
27 35 * @since 0.1
28 36 */
29 37 public function __construct() {
30 - require_once PLL_INC . '/functions.php'; // VIP functions
31 - spl_autoload_register( array( $this, 'autoload' ) ); // Autoload classes
38 + require_once __DIR__ . '/functions.php'; // VIP functions
32 39
33 40 // register an action when plugin is activating.
34 41 register_activation_hook( POLYLANG_BASENAME, array( 'PLL_Wizard', 'start_wizard' ) );
35 42
@@ -49,66 +56,18 @@
49 56 if ( ! defined( 'PLL_OLT' ) || PLL_OLT ) {
50 57 PLL_OLT_Manager::instance();
51 58 }
52 59
53 - // Extra code for compatibility with some plugins
54 - // Loaded as soon as possible as we may need to act before other plugins are loaded
60 + /*
61 + * Loads the compatibility with some plugins and themes.
62 + * Loaded as soon as possible as we may need to act before other plugins are loaded.
63 + */
55 64 if ( ! defined( 'PLL_PLUGINS_COMPAT' ) || PLL_PLUGINS_COMPAT ) {
56 - PLL_Plugins_Compat::instance();
65 + PLL_Integrations::instance();
57 66 }
58 67 }
59 68
60 69 /**
61 - * Autoload classes
62 - *
63 - * @since 1.2
64 - *
65 - * @param string $class
66 - */
67 - public function autoload( $class ) {
68 - // Not a Polylang class
69 - if ( 0 !== strncmp( 'PLL_', $class, 4 ) ) {
70 - return;
71 - }
72 -
73 - $class = str_replace( '_', '-', strtolower( substr( $class, 4 ) ) );
74 - $dirs = array();
75 - $parts = explode( '-', $class );
76 - $parts = array_values( array_diff( $parts, array( 'frontend', 'admin', 'settings', 'advanced' ) ) );
77 - if ( isset( $parts[0] ) ) {
78 - $dirs[] = PLL_MODULES_INC . "/{$parts[0]}";
79 - if ( isset( $parts[1] ) ) {
80 - $dirs[] = PLL_MODULES_INC . "/{$parts[0]}-{$parts[1]}";
81 - if ( isset( $parts[2] ) && in_array( $parts[1], array( 'post', 'term' ) ) ) {
82 - $dirs[] = PLL_MODULES_INC . "/{$parts[0]}-{$parts[2]}";
83 - }
84 - }
85 - }
86 -
87 - $dirs = array_merge(
88 - array(
89 - PLL_FRONT_INC,
90 - PLL_MODULES_INC,
91 - ),
92 - $dirs,
93 - array(
94 - PLL_MODULES_INC . '/plugins',
95 - PLL_INSTALL_INC,
96 - PLL_ADMIN_INC,
97 - PLL_SETTINGS_INC,
98 - PLL_INC,
99 - )
100 - );
101 -
102 - foreach ( $dirs as $dir ) {
103 - if ( file_exists( $file = "$dir/$class.php" ) ) {
104 - require_once $file; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
105 - return;
106 - }
107 - }
108 - }
109 -
110 - /**
111 70 * Tells whether the current request is an ajax request on frontend or not
112 71 *
113 72 * @since 2.2
114 73 *
@@ -140,13 +99,13 @@
140 99 * @return bool
141 100 */
142 101 public static function is_rest_request() {
143 102 // Handle pretty permalinks.
144 - $home_path = trim( wp_parse_url( home_url(), PHP_URL_PATH ), '/' );
103 + $home_path = trim( (string) wp_parse_url( home_url(), PHP_URL_PATH ), '/' );
145 104 $home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) );
146 105
147 - $req_uri = trim( wp_parse_url( pll_get_requested_url(), PHP_URL_PATH ), '/' );
148 - $req_uri = preg_replace( $home_path_regex, '', $req_uri );
106 + $req_uri = trim( (string) wp_parse_url( pll_get_requested_url(), PHP_URL_PATH ), '/' );
107 + $req_uri = (string) preg_replace( $home_path_regex, '', $req_uri );
149 108 $req_uri = trim( $req_uri, '/' );
150 109 $req_uri = str_replace( 'index.php', '', $req_uri );
151 110 $req_uri = trim( $req_uri, '/' );
152 111
@@ -151,10 +110,10 @@
151 110 $req_uri = trim( $req_uri, '/' );
152 111
153 112 // And also test rest_route query string parameter is not empty for plain permalinks.
154 113 $query_string = array();
155 - wp_parse_str( wp_parse_url( pll_get_requested_url(), PHP_URL_QUERY ), $query_string );
156 - $rest_route = isset( $query_string['rest_route'] ) ? trim( $query_string['rest_route'], '/' ) : false;
114 + wp_parse_str( (string) wp_parse_url( pll_get_requested_url(), PHP_URL_QUERY ), $query_string );
115 + $rest_route = isset( $query_string['rest_route'] ) && is_string( $query_string['rest_route'] ) ? trim( $query_string['rest_route'], '/' ) : false;
157 116
158 117 return 0 === strpos( $req_uri, rest_get_url_prefix() . '/' ) || ! empty( $rest_route );
159 118 }
160 119
@@ -173,8 +132,10 @@
173 132 * Defines constants
174 133 * May be overridden by a plugin if set before plugins_loaded, 1
175 134 *
176 135 * @since 1.6
136 + *
137 + * @return void
177 138 */
178 139 public static function define_constants() {
179 140 // Cookie name. no cookie will be used if set to false
180 141 if ( ! defined( 'PLL_COOKIE' ) ) {
@@ -201,31 +162,31 @@
201 162 * Polylang initialization
202 163 * setups models and separate admin and frontend
203 164 *
204 165 * @since 1.2
166 + *
167 + * @return void
205 168 */
206 169 public function init() {
207 - global $polylang;
170 + self::define_constants();
208 171
209 - self::define_constants();
210 - $options = get_option( 'polylang' );
172 + // Plugin options.
173 + add_action( 'pll_init_options_for_blog', array( Options_Registry::class, 'register' ) );
174 + $options = new Options();
211 175
212 176 // Plugin upgrade
213 - if ( $options && version_compare( $options['version'], POLYLANG_VERSION, '<' ) ) {
214 - $upgrade = new PLL_Upgrade( $options );
215 - if ( ! $upgrade->upgrade() ) { // If the version is too old
216 - return;
177 + if ( ! empty( $options['version'] ) ) {
178 + if ( version_compare( $options['version'], POLYLANG_VERSION, '<' ) ) {
179 + $upgrade = new PLL_Upgrade( $options );
180 + if ( ! $upgrade->upgrade() ) { // If the version is too old
181 + return;
182 + }
217 183 }
184 + } else {
185 + // In some edge cases, it's possible that no options were found in the database.
186 + $options['version'] = POLYLANG_VERSION;
218 187 }
219 188
220 - // In some edge cases, it's possible that no options were found in the database. Load default options as we need some.
221 - if ( ! $options ) {
222 - $options = PLL_Install::get_default_options();
223 - }
224 -
225 - // Make sure that this filter is *always* added before PLL_Model::get_languages_list() is called for the first time
226 - add_filter( 'pll_languages_list', array( 'PLL_Static_Pages', 'pll_languages_list' ), 2, 2 ); // Before PLL_Links_Model
227 -
228 189 /**
229 190 * Filter the model class to use
230 191 * /!\ this filter is fired *before* the $polylang object is available
231 192 *
@@ -233,12 +194,12 @@
233 194 *
234 195 * @param string $class either PLL_Model or PLL_Admin_Model
235 196 */
236 197 $class = apply_filters( 'pll_model', PLL_SETTINGS || self::is_wizard() ? 'PLL_Admin_Model' : 'PLL_Model' );
198 + /** @var PLL_Model $model */
237 199 $model = new $class( $options );
238 - $links_model = $model->get_links_model();
239 200
240 - if ( ! $model->get_languages_list() ) {
201 + if ( ! $model->has_languages() ) {
241 202 /**
242 203 * Fires when no language has been defined yet
243 204 * Used to load overridden textdomains
244 205 *
@@ -254,9 +215,9 @@
254 215 } elseif ( PLL_ADMIN ) {
255 216 $class = 'PLL_Admin';
256 217 } elseif ( self::is_rest_request() ) {
257 218 $class = 'PLL_REST_Request';
258 - } elseif ( $model->get_languages_list() && empty( $_GET['deactivate-polylang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
219 + } elseif ( $model->has_languages() ) {
259 220 $class = 'PLL_Frontend';
260 221 }
261 222
262 223 /**
@@ -268,35 +229,76 @@
268 229 */
269 230 $class = apply_filters( 'pll_context', $class );
270 231
271 232 if ( ! empty( $class ) ) {
272 - $polylang = new $class( $links_model );
233 + /** @phpstan-var class-string<TPLLClass> $class */
234 + $this->init_context( $class, $model );
235 + }
236 + }
273 237
274 - /**
275 - * Fires after the $polylang object is created and before the API is loaded
276 - *
277 - * @since 2.0
278 - *
279 - * @param object $polylang
280 - */
281 - do_action_ref_array( 'pll_pre_init', array( &$polylang ) );
238 + /**
239 + * Polylang initialization.
240 + * Setups the Polylang Context, loads the modules and init Polylang.
241 + *
242 + * @since 3.6
243 + *
244 + * @param string $class The class name.
245 + * @param PLL_Model $model Instance of PLL_Model.
246 + * @return PLL_Base
247 + *
248 + * @phpstan-param class-string<TPLLClass> $class
249 + * @phpstan-return TPLLClass
250 + */
251 + public function init_context( string $class, PLL_Model $model ): PLL_Base {
252 + global $polylang;
282 253
283 - require_once PLL_INC . '/api.php'; // Loads the API
254 + $links_model = $model->get_links_model();
255 + $polylang = new $class( $links_model );
284 256
285 - if ( ! defined( 'PLL_WPML_COMPAT' ) || PLL_WPML_COMPAT ) {
286 - PLL_WPML_Compat::instance(); // WPML API
287 - PLL_WPML_Config::instance(); // wpml-config.xml
257 + /**
258 + * Fires after Polylang's model init.
259 + * This is the best place to register a custom table (see `PLL_Model`'s constructor).
260 + * /!\ This hook is fired *before* the $polylang object is available.
261 + * /!\ The languages are also not available yet.
262 + *
263 + * @since 3.4
264 + *
265 + * @param PLL_Model $model Polylang model.
266 + */
267 + do_action( 'pll_model_init', $model );
268 +
269 + $model->maybe_create_language_terms();
270 +
271 + /**
272 + * Fires after the $polylang object is created and before the API is loaded
273 + *
274 + * @since 2.0
275 + *
276 + * @param object $polylang
277 + */
278 + do_action_ref_array( 'pll_pre_init', array( &$polylang ) );
279 +
280 + // Loads the API
281 + require_once POLYLANG_DIR . '/include/api.php';
282 +
283 + // Loads the modules.
284 + $load_scripts = glob( POLYLANG_DIR . '/modules/*/load.php', GLOB_NOSORT );
285 + if ( is_array( $load_scripts ) ) {
286 + foreach ( $load_scripts as $load_script ) {
287 + require_once $load_script; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
288 288 }
289 + }
289 290
290 - $polylang->init();
291 + $polylang->init();
291 292
292 - /**
293 - * Fires after the $polylang object and the API is loaded
294 - *
295 - * @since 1.7
296 - *
297 - * @param object $polylang
298 - */
299 - do_action_ref_array( 'pll_init', array( &$polylang ) );
300 - }
293 + /**
294 + * Fires after the $polylang object and the API is loaded
295 + *
296 + * @since 1.7
297 + *
298 + * @param object $polylang
299 + */
300 + do_action_ref_array( 'pll_init', array( &$polylang ) );
301 +
302 + return $polylang;
301 303 }
302 304 }