PluginProbe
Polylang / 3.7.1
Polylang v3.7.1
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 | settings/settings-module.php +85 -48 2.83.7.1 View file →
@@ -16,10 +16,8 @@
16 16 */
17 17 public $options;
18 18
19 19 /**
20 - * Instance of PLL_Model.
21 - *
22 20 * @var PLL_Model
23 21 */
24 22 public $model;
25 23
@@ -30,11 +28,17 @@
30 28 */
31 29 public $links_model;
32 30
33 31 /**
34 - * Stores if the module is active.
32 + * Key to use to manage the module activation state.
33 + * Possible values:
34 + * - An option key for a module that can be activated/deactivated.
35 + * - 'none' for a module that doesn't have a activation/deactivation setting.
36 + * - 'preview' for a preview module whose functionalities are available in the Pro version.
35 37 *
36 - * @var bool
38 + * @var string
39 + *
40 + * @phpstan-var non-falsy-string
37 41 */
38 42 public $active_option;
39 43
40 44 /**
@@ -48,8 +52,10 @@
48 52 * Stores the module name.
49 53 * It must be unique.
50 54 *
51 55 * @var string
56 + *
57 + * @phpstan-var non-falsy-string
52 58 */
53 59 public $module;
54 60
55 61 /**
@@ -82,9 +88,9 @@
82 88
83 89 /**
84 90 * Stores html form when provided by a child class.
85 91 *
86 - * @var bool|string
92 + * @var string|false
87 93 */
88 94 protected $form = false;
89 95
90 96 /**
@@ -91,14 +97,31 @@
91 97 * Constructor
92 98 *
93 99 * @since 1.8
94 100 *
95 - * @param object $polylang Polylang object
96 - * @param array $args
101 + * @param object $polylang The Polylang object.
102 + * @param array $args {
103 + * @type string $module Unique module name.
104 + * @type string $title The title of the settings module.
105 + * @type string $description The description of the settings module.
106 + * @type string $active_option Optional. Key to use to manage the module activation state.
107 + * Possible values:
108 + * - An option key for a module that can be activated/deactivated.
109 + * - 'none' for a module that doesn't have a activation/deactivation setting.
110 + * - 'preview' for a preview module whose functionalities are available in the Pro version.
111 + * Default is 'none'.
112 + * }
113 + *
114 + * @phpstan-param array{
115 + * module: non-falsy-string,
116 + * title: string,
117 + * description: string,
118 + * active_option?: non-falsy-string
119 + * } $args
97 120 */
98 121 public function __construct( &$polylang, $args ) {
99 - $this->options = &$polylang->options;
100 - $this->model = &$polylang->model;
122 + $this->options = &$polylang->options;
123 + $this->model = &$polylang->model;
101 124 $this->links_model = &$polylang->links_model;
102 125
103 126 $args = wp_parse_args(
104 127 $args,
@@ -104,12 +127,17 @@
104 127 $args,
105 128 array(
106 129 'title' => '',
107 130 'description' => '',
108 - 'active_option' => false,
131 + 'active_option' => 'none',
109 132 )
110 133 );
111 134
135 + if ( empty( $args['active_option'] ) ) {
136 + // Backward compatibility.
137 + $args['active_option'] = 'none';
138 + }
139 +
112 140 foreach ( $args as $prop => $value ) {
113 141 $this->$prop = $value;
114 142 }
115 143
@@ -141,14 +169,14 @@
141 169 'cancel' => sprintf( '<button type="button" class="button button-secondary cancel">%s</button>', esc_html__( 'Cancel', 'polylang' ) ),
142 170 'save' => sprintf( '<button type="button" class="button button-primary save">%s</button>', esc_html__( 'Save Changes', 'polylang' ) ),
143 171 );
144 172
145 - // Ajax action to save options
173 + // Ajax action to save options.
146 174 add_action( 'wp_ajax_pll_save_options', array( $this, 'save_options' ) );
147 175 }
148 176
149 177 /**
150 - * Tells if the module is active
178 + * Tells if the module is active.
151 179 *
152 180 * @since 1.8
153 181 *
154 182 * @return bool
@@ -153,46 +181,50 @@
153 181 *
154 182 * @return bool
155 183 */
156 184 public function is_active() {
157 - return empty( $this->active_option ) || ! empty( $this->options[ $this->active_option ] );
185 + return 'none' === $this->active_option || ( 'preview' !== $this->active_option && ! empty( $this->options[ $this->active_option ] ) );
158 186 }
159 187
160 188 /**
161 - * Activates the module
189 + * Activates the module.
162 190 *
163 191 * @since 1.8
192 + *
193 + * @return void
164 194 */
165 195 public function activate() {
166 - if ( ! empty( $this->active_option ) ) {
196 + if ( 'none' !== $this->active_option && 'preview' !== $this->active_option ) {
167 197 $this->options[ $this->active_option ] = true;
168 - update_option( 'polylang', $this->options );
169 198 }
170 199 }
171 200
172 201 /**
173 - * Deactivates the module
202 + * Deactivates the module.
174 203 *
175 204 * @since 1.8
205 + *
206 + * @return void
176 207 */
177 208 public function deactivate() {
178 - if ( ! empty( $this->active_option ) ) {
209 + if ( 'none' !== $this->active_option && 'preview' !== $this->active_option ) {
179 210 $this->options[ $this->active_option ] = false;
180 - update_option( 'polylang', $this->options );
181 211 }
182 212 }
183 213
184 214 /**
185 - * Protected method to display a configuration form
215 + * Protected method to display a configuration form.
186 216 *
187 217 * @since 1.8
218 + *
219 + * @return void
188 220 */
189 221 protected function form() {
190 - // Child classes can provide a form
222 + // Child classes can provide a form.
191 223 }
192 224
193 225 /**
194 - * Public method returning the form if any
226 + * Public method returning the form if any.
195 227 *
196 228 * @since 1.8
197 229 *
198 230 * @return string
@@ -197,8 +229,12 @@
197 229 *
198 230 * @return string
199 231 */
200 232 public function get_form() {
233 + if ( ! $this->is_active() ) {
234 + return '';
235 + }
236 +
201 237 // Read the form only once
202 238 if ( false === $this->form ) {
203 239 ob_start();
204 240 $this->form();
@@ -208,23 +244,25 @@
208 244 return $this->form;
209 245 }
210 246
211 247 /**
212 - * Allows child classes to validate their options before saving
248 + * Allows child classes to prepare the received data before saving.
213 249 *
214 - * @since 1.8
250 + * @since 3.7
215 251 *
216 - * @param array $options Raw options
217 - * @return array Options
252 + * @param array $options Raw values to save.
253 + * @return array
218 254 */
219 - protected function update( $options ) {
220 - return array(); // It's responsibility of the child class to decide what is saved
255 + protected function prepare_raw_data( array $options ): array {
256 + return $options;
221 257 }
222 258
223 259 /**
224 - * Ajax method to save the options
260 + * Ajax method to save the options.
225 261 *
226 262 * @since 1.8
263 + *
264 + * @return void
227 265 */
228 266 public function save_options() {
229 267 check_ajax_referer( 'pll_options', '_pll_nonce' );
230 268 if ( ! current_user_can( 'manage_options' ) ) {
@@ -232,31 +270,30 @@
232 270 }
233 271
234 272 if ( isset( $_POST['module'] ) && $this->module === $_POST['module'] ) {
235 273 // It's up to the child class to decide which options are saved, whether there are errors or not
236 - $post = array_diff_key( $_POST, array_flip( array( 'action', 'module', 'pll_ajax_backend', '_pll_nonce' ) ) );
237 - $options = $this->update( $post );
238 - $this->options = array_merge( $this->options, $options );
239 - update_option( 'polylang', $this->options );
274 + $posted_options = array_diff_key( $_POST, array_flip( array( 'action', 'module', 'pll_ajax_backend', 'pll_ajax_settings', '_pll_nonce' ) ) );
275 + $errors = $this->options->merge( $this->prepare_raw_data( $posted_options ) );
240 276
241 277 // Refresh language cache in case home urls have been modified
242 278 $this->model->clean_languages_cache();
243 279
244 - // Refresh rewrite rules in case rewrite, hide_default, post types or taxonomies options have been modified
280 + // Refresh rewrite rules in case rewrite, hide_default, post types or taxonomies options have been modified
245 281 // Don't use flush_rewrite_rules as we don't have the right links model and permastruct
246 282 delete_option( 'rewrite_rules' );
247 283
248 284 ob_start();
249 285
250 - if ( ! get_settings_errors() ) {
286 + if ( ! $errors->has_errors() ) {
251 287 // Send update message
252 - add_settings_error( 'general', 'settings_updated', __( 'Settings saved.', 'polylang' ), 'updated' );
253 - settings_errors();
288 + pll_add_notice( new WP_Error( 'settings_updated', __( 'Settings saved.', 'polylang' ), 'success' ) );
289 + settings_errors( 'polylang' );
254 290 $x = new WP_Ajax_Response( array( 'what' => 'success', 'data' => ob_get_clean() ) );
255 291 $x->send();
256 292 } else {
257 293 // Send error messages
258 - settings_errors();
294 + pll_add_notice( $errors );
295 + settings_errors( 'polylang' );
259 296 $x = new WP_Ajax_Response( array( 'what' => 'error', 'data' => ob_get_clean() ) );
260 297 $x->send();
261 298 }
262 299 }
@@ -262,13 +299,13 @@
262 299 }
263 300 }
264 301
265 302 /**
266 - * Get the row actions
303 + * Get the row actions.
267 304 *
268 305 * @since 1.8
269 306 *
270 - * @return array
307 + * @return string[]
271 308 */
272 309 protected function get_actions() {
273 310 $actions = array();
274 311
@@ -275,9 +312,9 @@
275 312 if ( $this->is_active() && $this->get_form() ) {
276 313 $actions[] = 'configure';
277 314 }
278 315
279 - if ( $this->active_option ) {
316 + if ( 'none' !== $this->active_option && 'preview' !== $this->active_option ) {
280 317 $actions[] = $this->is_active() ? 'deactivate' : 'activate';
281 318 }
282 319
283 320 if ( empty( $actions ) ) {
@@ -287,13 +324,13 @@
287 324 return $actions;
288 325 }
289 326
290 327 /**
291 - * Get the actions links
328 + * Get the actions links.
292 329 *
293 330 * @since 1.8
294 331 *
295 - * @return array
332 + * @return string[] Action links.
296 333 */
297 334 public function get_action_links() {
298 335 return array_intersect_key( $this->action_links, array_flip( $this->get_actions() ) );
299 336 }
@@ -298,9 +335,9 @@
298 335 return array_intersect_key( $this->action_links, array_flip( $this->get_actions() ) );
299 336 }
300 337
301 338 /**
302 - * Default upgrade message ( to Pro version )
339 + * Default upgrade message (to Pro version).
303 340 *
304 341 * @since 1.9
305 342 *
306 343 * @return string
@@ -314,9 +351,9 @@
314 351 );
315 352 }
316 353
317 354 /**
318 - * Allows child classes to display an upgrade message
355 + * Allows child classes to display an upgrade message.
319 356 *
320 357 * @since 1.9
321 358 *
322 359 * @return string
@@ -321,17 +358,17 @@
321 358 *
322 359 * @return string
323 360 */
324 361 public function get_upgrade_message() {
325 - return '';
362 + return 'preview' === $this->active_option ? $this->default_upgrade_message() : '';
326 363 }
327 364
328 365 /**
329 - * Get the buttons
366 + * Get the buttons.
330 367 *
331 368 * @since 1.9
332 369 *
333 - * @return array
370 + * @return string[] An array of html fragment for the buttons.
334 371 */
335 372 public function get_buttons() {
336 373 return $this->buttons;
337 374 }