PluginProbe
Polylang / 3.0.2
Polylang v3.0.2
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 / admin / admin-model.php

admin-model.php in Polylang 3.0.2, at admin/admin-model.php

618 lines 20.9 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 * Extends the PLL_Model class with methods needed only in Polylang settings pages.
8 *
9 * @since 1.2
10 */
11 class PLL_Admin_Model extends PLL_Model {
12
13 /**
14 * Adds a new language
15 * and creates a default category for this language.
16 *
17 * @since 1.2
18 *
19 * @param array $args {
20 * @type string $name Language name ( used only for display ).
21 * @type string $slug Language code ( ideally 2-letters ISO 639-1 language code ).
22 * @type string $locale WordPress locale. If something wrong is used for the locale, the .mo files will not be loaded...
23 * @type int $rtl 1 if rtl language, 0 otherwise.
24 * @type int $term_group Language order when displayed.
25 * @type string $no_default_cat Optional, if set, no default category will be created for this language.
26 * @type string $flag Optional, country code, @see flags.php.
27 * }
28 * @return WP_Error|true true if success / WP_Error if failed.
29 */
30 public function add_language( $args ) {
31 $errors = $this->validate_lang( $args );
32 if ( $errors->get_error_code() ) { // Using has_errors() would be more meaningful but is available only since WP 5.0
33 return $errors;
34 }
35
36 // First the language taxonomy
37 $description = maybe_serialize( array( 'locale' => $args['locale'], 'rtl' => (int) $args['rtl'], 'flag_code' => empty( $args['flag'] ) ? '' : $args['flag'] ) );
38 $r = wp_insert_term( $args['name'], 'language', array( 'slug' => $args['slug'], 'description' => $description ) );
39 if ( is_wp_error( $r ) ) {
40 // Avoid an ugly fatal error if something went wrong ( reported once in the forum )
41 return new WP_Error( 'pll_add_language', __( 'Impossible to add the language.', 'polylang' ) );
42 }
43 wp_update_term( (int) $r['term_id'], 'language', array( 'term_group' => (int) $args['term_group'] ) ); // can't set the term group directly in wp_insert_term
44
45 // The term_language taxonomy
46 // Don't want shared terms so use a different slug
47 wp_insert_term( $args['name'], 'term_language', array( 'slug' => 'pll_' . $args['slug'] ) );
48
49 $this->clean_languages_cache(); // Update the languages list now !
50
51 if ( ! isset( $this->options['default_lang'] ) ) {
52 // If this is the first language created, set it as default language
53 $this->options['default_lang'] = $args['slug'];
54 update_option( 'polylang', $this->options );
55
56 // And assign default language to default category
57 $this->term->set_language( (int) get_option( 'default_category' ), (int) $r['term_id'] );
58 } elseif ( empty( $args['no_default_cat'] ) ) {
59 $this->create_default_category( $args['slug'] );
60 }
61
62 // Init a mo_id for this language
63 $mo = new PLL_MO();
64 $mo->export_to_db( $this->get_language( $args['slug'] ) );
65
66 /**
67 * Fires when a language is added.
68 *
69 * @since 1.9
70 *
71 * @param array $args Arguments used to create the language. @see PLL_Admin_Model::add_language().
72 */
73 do_action( 'pll_add_language', $args );
74
75 $this->clean_languages_cache(); // Again to set add mo_id in the cached languages list
76 flush_rewrite_rules(); // Refresh rewrite rules
77 return true;
78 }
79
80 /**
81 * Delete a language.
82 *
83 * @since 1.2
84 *
85 * @param int $lang_id Language term_id.
86 * @return bool
87 */
88 public function delete_language( $lang_id ) {
89 $lang = $this->get_language( (int) $lang_id );
90
91 if ( empty( $lang ) ) {
92 return false;
93 }
94
95 // Oops ! we are deleting the default language...
96 // Need to do this before loosing the information for default category translations
97 if ( $this->options['default_lang'] == $lang->slug ) {
98 $slugs = $this->get_languages_list( array( 'fields' => 'slug' ) );
99 $slugs = array_diff( $slugs, array( $lang->slug ) );
100
101 if ( ! empty( $slugs ) ) {
102 $this->update_default_lang( reset( $slugs ) ); // Arbitrary choice...
103 } else {
104 unset( $this->options['default_lang'] );
105 }
106 }
107
108 // Delete the translations
109 $this->update_translations( $lang->slug );
110
111 // Delete language option in widgets
112 foreach ( $GLOBALS['wp_registered_widgets'] as $widget ) {
113 if ( ! empty( $widget['callback'][0] ) && ! empty( $widget['params'][0]['number'] ) ) {
114 $obj = $widget['callback'][0];
115 $number = $widget['params'][0]['number'];
116 if ( is_object( $obj ) && method_exists( $obj, 'get_settings' ) && method_exists( $obj, 'save_settings' ) ) {
117 $settings = $obj->get_settings();
118 if ( isset( $settings[ $number ]['pll_lang'] ) && $settings[ $number ]['pll_lang'] == $lang->slug ) {
119 unset( $settings[ $number ]['pll_lang'] );
120 $obj->save_settings( $settings );
121 }
122 }
123 }
124 }
125
126 // Delete menus locations
127 if ( ! empty( $this->options['nav_menus'] ) ) {
128 foreach ( $this->options['nav_menus'] as $theme => $locations ) {
129 foreach ( array_keys( $locations ) as $location ) {
130 unset( $this->options['nav_menus'][ $theme ][ $location ][ $lang->slug ] );
131 }
132 }
133 }
134
135 // Delete users options
136 foreach ( get_users( array( 'fields' => 'ID' ) ) as $user_id ) {
137 delete_user_meta( $user_id, 'pll_filter_content', $lang->slug );
138 delete_user_meta( $user_id, 'description_' . $lang->slug );
139 }
140
141 // Delete the string translations
142 $post = wpcom_vip_get_page_by_title( 'polylang_mo_' . $lang->term_id, OBJECT, 'polylang_mo' );
143 if ( $post instanceof WP_Post ) {
144 wp_delete_post( $post->ID );
145 }
146
147 // Delete domain
148 unset( $this->options['domains'][ $lang->slug ] );
149
150 // Delete the language itself
151 wp_delete_term( $lang->term_id, 'language' );
152 wp_delete_term( $lang->tl_term_id, 'term_language' );
153
154 // Update languages list
155 $this->clean_languages_cache();
156
157 update_option( 'polylang', $this->options );
158 flush_rewrite_rules(); // refresh rewrite rules
159 return true;
160 }
161
162 /**
163 * Updates language properties.
164 *
165 * @since 1.2
166 *
167 * @param array $args {
168 * @type int $lang_id Id of the language to modify.
169 * @type string $name Language name ( used only for display ).
170 * @type string $slug Language code ( ideally 2-letters ISO 639-1 language code ).
171 * @type string $locale WordPress locale. If something wrong is used for the locale, the .mo files will not be loaded...
172 * @type int $rtl 1 if rtl language, 0 otherwise.
173 * @type int $term_group Language order when displayed.
174 * @type string $flag Optional, country code, @see flags.php.
175 * }
176 * @return WP_Error|true true if success / WP_Error if failed.
177 */
178 public function update_language( $args ) {
179 $lang = $this->get_language( (int) $args['lang_id'] );
180
181 $errors = $this->validate_lang( $args, $lang );
182 if ( $errors->get_error_code() ) { // Using has_errors() would be more meaningful but is available only since WP 5.0
183 return $errors;
184 }
185
186 // Update links to this language in posts and terms in case the slug has been modified
187 $slug = $args['slug'];
188 $old_slug = $lang->slug;
189
190 if ( $old_slug != $slug ) {
191 // Update the language slug in translations
192 $this->update_translations( $old_slug, $slug );
193
194 // Update language option in widgets
195 foreach ( $GLOBALS['wp_registered_widgets'] as $widget ) {
196 if ( ! empty( $widget['callback'][0] ) && ! empty( $widget['params'][0]['number'] ) ) {
197 $obj = $widget['callback'][0];
198 $number = $widget['params'][0]['number'];
199 if ( is_object( $obj ) && method_exists( $obj, 'get_settings' ) && method_exists( $obj, 'save_settings' ) ) {
200 $settings = $obj->get_settings();
201 if ( isset( $settings[ $number ]['pll_lang'] ) && $settings[ $number ]['pll_lang'] == $old_slug ) {
202 $settings[ $number ]['pll_lang'] = $slug;
203 $obj->save_settings( $settings );
204 }
205 }
206 }
207 }
208
209 // Update menus locations
210 if ( ! empty( $this->options['nav_menus'] ) ) {
211 foreach ( $this->options['nav_menus'] as $theme => $locations ) {
212 foreach ( array_keys( $locations ) as $location ) {
213 if ( ! empty( $this->options['nav_menus'][ $theme ][ $location ][ $old_slug ] ) ) {
214 $this->options['nav_menus'][ $theme ][ $location ][ $slug ] = $this->options['nav_menus'][ $theme ][ $location ][ $old_slug ];
215 unset( $this->options['nav_menus'][ $theme ][ $location ][ $old_slug ] );
216 }
217 }
218 }
219 }
220
221 // Update domains
222 if ( ! empty( $this->options['domains'][ $old_slug ] ) ) {
223 $this->options['domains'][ $slug ] = $this->options['domains'][ $old_slug ];
224 unset( $this->options['domains'][ $old_slug ] );
225 }
226
227 // Update the default language option if necessary
228 if ( $this->options['default_lang'] == $old_slug ) {
229 $this->options['default_lang'] = $slug;
230 }
231 }
232
233 update_option( 'polylang', $this->options );
234
235 // And finally update the language itself
236 $description = maybe_serialize( array( 'locale' => $args['locale'], 'rtl' => (int) $args['rtl'], 'flag_code' => empty( $args['flag'] ) ? '' : $args['flag'] ) );
237 wp_update_term( (int) $lang->term_id, 'language', array( 'slug' => $slug, 'name' => $args['name'], 'description' => $description, 'term_group' => (int) $args['term_group'] ) );
238 wp_update_term( (int) $lang->tl_term_id, 'term_language', array( 'slug' => 'pll_' . $slug, 'name' => $args['name'] ) );
239
240 /**
241 * Fires when a language is updated.
242 *
243 * @since 1.9
244 *
245 * @param array $args Arguments used to modify the language. @see PLL_Admin_Model::update_language().
246 */
247 do_action( 'pll_update_language', $args );
248
249 $this->clean_languages_cache();
250 flush_rewrite_rules(); // Refresh rewrite rules
251 return true;
252 }
253
254 /**
255 * Validates data entered when creating or updating a language.
256 *
257 * @see PLL_Admin_Model::add_language().
258 *
259 * @since 0.4
260 *
261 * @param array $args Parameters of {@see PLL_Admin_Model::add_language() or @see PLL_Admin_Model::update_language()}.
262 * @param PLL_Language $lang Optional the language currently updated, the language is created if not set.
263 * @return WP_Error
264 */
265 protected function validate_lang( $args, $lang = null ) {
266 $errors = new WP_Error();
267
268 // Validate locale with the same pattern as WP 4.3. See #28303
269 if ( ! preg_match( '#^[a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?$#', $args['locale'], $matches ) ) {
270 $errors->add( 'pll_invalid_locale', __( 'Enter a valid WordPress locale', 'polylang' ) );
271 }
272
273 // Validate slug characters
274 if ( ! preg_match( '#^[a-z_-]+$#', $args['slug'] ) ) {
275 $errors->add( 'pll_invalid_slug', __( 'The language code contains invalid characters', 'polylang' ) );
276 }
277
278 // Validate slug is unique
279 foreach ( $this->get_languages_list() as $language ) {
280 if ( $language->slug === $args['slug'] && ( null === $lang || $lang->term_id !== $language->term_id ) ) {
281 $errors->add( 'pll_non_unique_slug', __( 'The language code must be unique', 'polylang' ) );
282 }
283 }
284
285 // Validate name
286 // No need to sanitize it as wp_insert_term will do it for us
287 if ( empty( $args['name'] ) ) {
288 $errors->add( 'pll_invalid_name', __( 'The language must have a name', 'polylang' ) );
289 }
290
291 // Validate flag
292 if ( ! empty( $args['flag'] ) && ! file_exists( POLYLANG_DIR . '/flags/' . $args['flag'] . '.png' ) ) {
293 $flag = PLL_Language::get_flag_informations( $args['flag'] );
294
295 if ( ! empty( $flag['url'] ) ) {
296 $response = function_exists( 'vip_safe_wp_remote_get' ) ? vip_safe_wp_remote_get( esc_url_raw( $flag['url'] ) ) : wp_remote_get( esc_url_raw( $flag['url'] ) );
297 }
298
299 if ( empty( $response ) || is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
300 $errors->add( 'pll_invalid_flag', __( 'The flag does not exist', 'polylang' ) );
301 }
302 }
303
304 return $errors;
305 }
306
307 /**
308 * Assigns a language to posts or terms in mass.
309 *
310 * @since 1.2
311 *
312 * @param string $type Either 'post' or 'term'.
313 * @param int[] $ids Array of post ids or term ids.
314 * @param PLL_Language|string $lang Language to assign to the posts or terms.
315 * @return void
316 */
317 public function set_language_in_mass( $type, $ids, $lang ) {
318 global $wpdb;
319
320 $lang = $this->get_language( $lang );
321
322 if ( empty( $lang ) ) {
323 return;
324 }
325
326 $tt_id = 'term' === $type ? $lang->tl_term_taxonomy_id : $lang->term_taxonomy_id;
327 $values = array();
328 $ids = array_map( 'intval', $ids );
329
330 foreach ( $ids as $id ) {
331 $values[] = $wpdb->prepare( '( %d, %d )', $id, $tt_id );
332 }
333
334 if ( ! empty( $values ) ) {
335 // PHPCS:ignore WordPress.DB.PreparedSQL.NotPrepared
336 $wpdb->query( "INSERT INTO {$wpdb->term_relationships} ( object_id, term_taxonomy_id ) VALUES " . implode( ',', array_unique( $values ) ) );
337 $lang->update_count(); // Updating term count is mandatory ( thanks to AndyDeGroo )
338 }
339
340 if ( 'term' === $type ) {
341 clean_term_cache( $ids, 'term_language' );
342 $translations = array();
343
344 foreach ( $ids as $id ) {
345 $translations[] = array( $lang->slug => $id );
346 }
347
348 if ( ! empty( $translations ) ) {
349 $this->set_translation_in_mass( 'term', $translations );
350 }
351 } else {
352 clean_term_cache( $ids, 'language' );
353 }
354 }
355
356 /**
357 * Creates translations groups in mass.
358 *
359 * @since 1.6.3
360 *
361 * @param string $type Either 'post' or 'term'
362 * @param array $translations Array of translations arrays.
363 * @return void
364 */
365 public function set_translation_in_mass( $type, $translations ) {
366 global $wpdb;
367
368 $taxonomy = $type . '_translations';
369 $terms = array();
370 $slugs = array();
371 $description = array();
372 $count = array();
373
374 foreach ( $translations as $t ) {
375 $term = uniqid( 'pll_' ); // the term name
376 $terms[] = $wpdb->prepare( '( %s, %s )', $term, $term );
377 $slugs[] = $wpdb->prepare( '%s', $term );
378 $description[ $term ] = maybe_serialize( $t );
379 $count[ $term ] = count( $t );
380 }
381
382 // Insert terms
383 if ( ! empty( $terms ) ) {
384 // PHPCS:ignore WordPress.DB.PreparedSQL.NotPrepared
385 $wpdb->query( "INSERT INTO {$wpdb->terms} ( slug, name ) VALUES " . implode( ',', array_unique( $terms ) ) );
386 }
387
388 // Get all terms with their term_id
389 // PHPCS:ignore WordPress.DB.PreparedSQL.NotPrepared
390 $terms = $wpdb->get_results( "SELECT term_id, slug FROM {$wpdb->terms} WHERE slug IN ( " . implode( ',', $slugs ) . ' )' );
391 $term_ids = array();
392 $tts = array();
393
394 // Prepare terms taxonomy relationship
395 foreach ( $terms as $term ) {
396 $term_ids[] = $term->term_id;
397 $tts[] = $wpdb->prepare( '( %d, %s, %s, %d )', $term->term_id, $taxonomy, $description[ $term->slug ], $count[ $term->slug ] );
398 }
399
400 // Insert term_taxonomy
401 if ( ! empty( $tts ) ) {
402 // PHPCS:ignore WordPress.DB.PreparedSQL.NotPrepared
403 $wpdb->query( "INSERT INTO {$wpdb->term_taxonomy} ( term_id, taxonomy, description, count ) VALUES " . implode( ',', array_unique( $tts ) ) );
404 }
405
406 // Get all terms with term_taxonomy_id
407 $terms = get_terms( $taxonomy, array( 'hide_empty' => false ) );
408 $trs = array();
409
410 // Prepare objects relationships.
411 if ( is_array( $terms ) ) {
412 foreach ( $terms as $term ) {
413 $t = maybe_unserialize( $term->description );
414 if ( in_array( $t, $translations ) ) {
415 foreach ( $t as $object_id ) {
416 if ( ! empty( $object_id ) ) {
417 $trs[] = $wpdb->prepare( '( %d, %d )', $object_id, $term->term_taxonomy_id );
418 }
419 }
420 }
421 }
422 }
423
424 // Insert term_relationships
425 if ( ! empty( $trs ) ) {
426 // PHPCS:ignore WordPress.DB.PreparedSQL.NotPrepared
427 $wpdb->query( "INSERT INTO {$wpdb->term_relationships} ( object_id, term_taxonomy_id ) VALUES " . implode( ',', $trs ) );
428 $trs = array_unique( $trs );
429 }
430
431 clean_term_cache( $term_ids, $taxonomy );
432 }
433
434 /**
435 * Returns untranslated posts and terms ids ( used in settings ).
436 *
437 * @since 0.9
438 * @since 2.2.6 Add the $limit argument.
439 *
440 * @param int $limit Max number of posts or terms to return. Defaults to -1 (no limit).
441 * @return array {
442 * Objects without language.
443 *
444 * @type int[] $posts Array of post ids.
445 * @type int[] $terms Array of term ids.
446 * }
447 */
448 public function get_objects_with_no_lang( $limit = -1 ) {
449 global $wpdb;
450
451 /**
452 * Filters the max number of posts or terms to return when searching objects with no language.
453 * This filter can be used to decrease the memory usage in case the number of objects
454 * without language is too big. Using a negative value is equivalent to have no limit.
455 *
456 * @since 2.2.6
457 *
458 * @param int $limit Max number of posts or terms to retrieve from the database.
459 */
460 $limit = (int) apply_filters( 'get_objects_with_no_lang_limit', $limit );
461
462 $posts = get_posts(
463 array(
464 'numberposts' => $limit,
465 'nopaging' => $limit <= 0,
466 'post_type' => $this->get_translated_post_types(),
467 'post_status' => 'any',
468 'fields' => 'ids',
469 'tax_query' => array(
470 array(
471 'taxonomy' => 'language',
472 'terms' => $this->get_languages_list( array( 'fields' => 'term_id' ) ),
473 'operator' => 'NOT IN',
474 ),
475 ),
476 )
477 );
478
479 // PHPCS:disable WordPress.DB.PreparedSQL
480 $terms = $wpdb->get_col(
481 sprintf(
482 "SELECT {$wpdb->term_taxonomy}.term_id FROM {$wpdb->term_taxonomy}
483 WHERE taxonomy IN ('%s')
484 AND {$wpdb->term_taxonomy}.term_id NOT IN (
485 SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN (%s)
486 )
487 %s",
488 implode( "','", array_map( 'esc_sql', $this->get_translated_taxonomies() ) ),
489 implode( ',', array_map( 'intval', $this->get_languages_list( array( 'fields' => 'tl_term_taxonomy_id' ) ) ) ),
490 $limit > 0 ? "LIMIT {$limit}" : ''
491 )
492 );
493 // PHPCS:enable
494
495 /**
496 * Filters the list of untranslated posts ids and terms ids
497 *
498 * @since 0.9
499 *
500 * @param array|false $objects false if no ids found, list of post and/or term ids otherwise.
501 */
502 return apply_filters( 'pll_get_objects_with_no_lang', empty( $posts ) && empty( $terms ) ? false : array( 'posts' => $posts, 'terms' => $terms ) );
503 }
504
505 /**
506 * Updates the translations when a language slug has been modified in settings
507 * or deletes them when a language is removed.
508 *
509 * @since 0.5
510 *
511 * @param string $old_slug The old language slug.
512 * @param string $new_slug Optional, the new language slug, if not set it means that the language has been deleted.
513 * @return void
514 */
515 public function update_translations( $old_slug, $new_slug = '' ) {
516 global $wpdb;
517
518 $terms = get_terms( array( 'post_translations', 'term_translations' ) );
519 $term_ids = array();
520 $dr = array();
521 $dt = array();
522 $ut = array();
523
524 if ( is_array( $terms ) ) {
525 foreach ( $terms as $term ) {
526 $term_ids[ $term->taxonomy ][] = $term->term_id;
527 $tr = maybe_unserialize( $term->description );
528 if ( ! empty( $tr[ $old_slug ] ) ) {
529 if ( $new_slug ) {
530 $tr[ $new_slug ] = $tr[ $old_slug ]; // Suppress this for delete
531 } else {
532 $dr['id'][] = (int) $tr[ $old_slug ];
533 $dr['tt'][] = (int) $term->term_taxonomy_id;
534 }
535 unset( $tr[ $old_slug ] );
536
537 if ( empty( $tr ) || 1 == count( $tr ) ) {
538 $dt['t'][] = (int) $term->term_id;
539 $dt['tt'][] = (int) $term->term_taxonomy_id;
540 } else {
541 $ut['case'][] = $wpdb->prepare( 'WHEN %d THEN %s', $term->term_id, maybe_serialize( $tr ) );
542 $ut['in'][] = (int) $term->term_id;
543 }
544 }
545 }
546 }
547
548 // Delete relationships
549 if ( ! empty( $dr ) ) {
550 // PHPCS:disable WordPress.DB.PreparedSQL.NotPrepared
551 $wpdb->query(
552 "DELETE FROM $wpdb->term_relationships
553 WHERE object_id IN ( " . implode( ',', $dr['id'] ) . ' )
554 AND term_taxonomy_id IN ( ' . implode( ',', $dr['tt'] ) . ' )'
555 );
556 // PHPCS:enable
557 }
558
559 // Delete terms
560 if ( ! empty( $dt ) ) {
561 $wpdb->query( "DELETE FROM $wpdb->terms WHERE term_id IN ( " . implode( ',', $dt['t'] ) . ' )' ); // PHPCS:ignore WordPress.DB.PreparedSQL.NotPrepared
562 $wpdb->query( "DELETE FROM $wpdb->term_taxonomy WHERE term_taxonomy_id IN ( " . implode( ',', $dt['tt'] ) . ' )' ); // PHPCS:ignore WordPress.DB.PreparedSQL.NotPrepared
563 }
564
565 // Update terms
566 if ( ! empty( $ut ) ) {
567 // PHPCS:disable WordPress.DB.PreparedSQL.NotPrepared
568 $wpdb->query(
569 "UPDATE $wpdb->term_taxonomy
570 SET description = ( CASE term_id " . implode( ' ', $ut['case'] ) . ' END )
571 WHERE term_id IN ( ' . implode( ',', $ut['in'] ) . ' )'
572 );
573 // PHPCS:enable
574 }
575
576 if ( ! empty( $term_ids ) ) {
577 foreach ( $term_ids as $taxonomy => $ids ) {
578 clean_term_cache( $ids, $taxonomy );
579 }
580 }
581 }
582
583 /**
584 * Updates the default language
585 * taking care to update the default category & the nav menu locations.
586 *
587 * @since 1.8
588 *
589 * @param string $slug New language slug.
590 * @return void
591 */
592 public function update_default_lang( $slug ) {
593 // The nav menus stored in theme locations should be in the default language
594 $theme = get_stylesheet();
595 if ( ! empty( $this->options['nav_menus'][ $theme ] ) ) {
596 $menus = array();
597
598 foreach ( $this->options['nav_menus'][ $theme ] as $key => $loc ) {
599 $menus[ $key ] = empty( $loc[ $slug ] ) ? 0 : $loc[ $slug ];
600 }
601 set_theme_mod( 'nav_menu_locations', $menus );
602 }
603
604 // The default category should be in the default language
605 $default_cats = $this->term->get_translations( get_option( 'default_category' ) );
606 if ( isset( $default_cats[ $slug ] ) ) {
607 update_option( 'default_category', $default_cats[ $slug ] );
608 }
609
610 // Update options
611 $this->options['default_lang'] = $slug;
612 update_option( 'polylang', $this->options );
613
614 $this->clean_languages_cache();
615 flush_rewrite_rules();
616 }
617 }
618