PluginProbe
Polylang / 3.8.6
Polylang v3.8.6
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 / integrations / wp-importer / wp-import.php

wp-import.php in Polylang 3.8.6, at src/integrations/wp-importer/wp-import.php

232 lines 7.2 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 * A class to import languages and translations information form a WXR file
8 *
9 * @since 1.2
10 */
11 class PLL_WP_Import extends WP_Import {
12 /**
13 * Stores post_translations terms.
14 *
15 * @var array
16 */
17 public $post_translations = array();
18
19 /**
20 * Overrides WP_Import::process_terms to remap terms translations.
21 *
22 * @since 1.2
23 */
24 public function process_terms() {
25 $term_translations = array();
26 $term_languages = array();
27
28 // Store this for future usage as parent function unsets $this->terms.
29 foreach ( $this->terms as $term ) {
30 if ( 'post_translations' == $term['term_taxonomy'] ) {
31 $this->post_translations[] = $term;
32 }
33 if ( 'term_translations' == $term['term_taxonomy'] ) {
34 $term_translations[] = $term;
35 }
36
37 if ( 'language' === $term['term_taxonomy'] ) {
38 $term_languages[] = $term;
39 }
40 }
41
42 parent::process_terms();
43
44 // First reset the core terms cache as WordPress Importer calls wp_suspend_cache_invalidation( true );
45 wp_cache_set_terms_last_changed();
46
47 // Assign the default language in case the importer created the first language.
48 if ( empty( PLL()->options['default_lang'] ) ) {
49 $languages = get_terms( array( 'taxonomy' => 'language', 'hide_empty' => false, 'orderby' => 'term_id' ) );
50 $default_lang = reset( $languages );
51 PLL()->options['default_lang'] = $default_lang->slug;
52 }
53
54 /*
55 * Merge strings translations for an already existing language.
56 *
57 * Term metas are handled by the importer when creating a term,
58 * but not when updating an existing term.
59 */
60 foreach ( $term_languages as $term ) {
61 if ( empty( $this->processed_terms[ $term['term_id'] ] ) || empty( $term['termmeta'] ) ) {
62 continue;
63 }
64
65 foreach ( $term['termmeta'] as $term_meta ) {
66 if ( '_pll_strings_translations' !== $term_meta['key'] ) {
67 continue;
68 }
69
70 $language = PLL()->model->languages->get( $term['term_id'] );
71 if ( empty( $language ) ) {
72 continue;
73 }
74
75 $strings = maybe_unserialize( $term_meta['value'] );
76 $mo = new PLL_MO();
77 $mo->import_from_db( $language );
78 foreach ( $strings as $msg ) {
79 $mo->add_entry_or_merge( $mo->make_entry( $msg[0], $msg[1] ) );
80 }
81 $mo->export_to_db( $language );
82 }
83 }
84
85 // Clean languages cache in case some of them were created during import.
86 PLL()->model->languages->clean_cache();
87
88 $this->remap_terms_relations( $term_translations );
89 $this->remap_translations( $term_translations, $this->processed_terms );
90 }
91
92 /**
93 * Overrides WP_Import::process_post to remap posts translations
94 * Also merges strings translations from the WXR file to the existing ones
95 *
96 * @since 1.2
97 */
98 public function process_posts() {
99 $menu_items = array();
100
101 // Store this for future usage as parent function unset $this->posts
102 foreach ( $this->posts as $post ) {
103 if ( 'nav_menu_item' == $post['post_type'] ) {
104 $menu_items[] = $post;
105 }
106 }
107
108 parent::process_posts();
109
110 PLL()->model->languages->clean_cache(); // To update the posts count in (cached) languages list.
111
112 $this->remap_translations( $this->post_translations, $this->processed_posts );
113 unset( $this->post_translations );
114
115 // Language switcher menu items
116 foreach ( $menu_items as $item ) {
117 foreach ( $item['postmeta'] as $meta ) {
118 if ( '_pll_menu_item' == $meta['key'] ) {
119 update_post_meta( $this->processed_menu_items[ $item['post_id'] ], '_pll_menu_item', maybe_unserialize( $meta['value'] ) );
120 }
121 }
122 }
123 }
124
125 /**
126 * Remaps terms languages.
127 *
128 * @since 1.2
129 *
130 * @param array $terms array of terms in 'term_translations' taxonomy.
131 */
132 protected function remap_terms_relations( &$terms ) {
133 global $wpdb;
134
135 $term_relationships = array();
136
137 foreach ( $terms as $term ) {
138 $translations = maybe_unserialize( $term['term_description'] );
139 foreach ( $translations as $slug => $old_id ) {
140 if ( $old_id && ! empty( $this->processed_terms[ $old_id ] ) && $lang = PLL()->model->get_language( $slug ) ) {
141 // Language relationship.
142 $term_relationships[] = array( $this->processed_terms[ $old_id ], $lang->get_tax_prop( 'term_language', 'term_taxonomy_id' ) );
143
144 // Translation relationship.
145 $term_relationships[] = array( $this->processed_terms[ $old_id ], get_term( $this->processed_terms[ $term['term_id'] ], 'term_translations' )->term_taxonomy_id );
146 }
147 }
148 }
149
150 // Insert term_relationships.
151 if ( ! empty( $term_relationships ) ) {
152 // Make sure we don't attempt to insert already existing term relationships.
153 $existing_term_relationships = $wpdb->get_results(
154 "SELECT tr.object_id, tr.term_taxonomy_id FROM {$wpdb->term_relationships} AS tr
155 INNER JOIN {$wpdb->term_taxonomy} AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
156 WHERE tt.taxonomy IN ( 'term_language', 'term_translations' )"
157 );
158
159 foreach ( $existing_term_relationships as $key => $tr ) {
160 $existing_term_relationships[ $key ] = array( $tr->object_id, $tr->term_taxonomy_id );
161 }
162
163 $term_relationships = array_udiff(
164 $term_relationships,
165 $existing_term_relationships,
166 function ( $a, $b ) {
167 return strcmp( implode( ',', $a ), implode( ',', $b ) ); // An easy way to compare arrays (ok if values are int or numeric strings).
168 }
169 );
170
171 if ( ! empty( $term_relationships ) ) {
172 $wpdb->query(
173 $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
174 sprintf(
175 "INSERT INTO {$wpdb->term_relationships} ( object_id, term_taxonomy_id ) VALUES %s",
176 implode( ',', array_fill( 0, count( $term_relationships ), '( %d, %d )' ) )
177 ),
178 array_merge( ...$term_relationships )
179 )
180 );
181 }
182 }
183 }
184
185 /**
186 * Remaps translations for both posts and terms.
187 *
188 * @since 1.2
189 *
190 * @param array $terms Array of terms in 'post_translations' or 'term_translations' taxonomies?
191 * @param array $processed_objects Array of posts or terms processed by WordPress Importer.
192 */
193 protected function remap_translations( &$terms, &$processed_objects ) {
194 global $wpdb;
195
196 $languages = pll_languages_list();
197 $to_update = array();
198
199 foreach ( $terms as $term ) {
200 $translations = maybe_unserialize( $term['term_description'] );
201 $new_translations = array();
202 foreach ( $translations as $slug => $old_id ) {
203 if ( in_array( $slug, $languages, true ) && $old_id && ! empty( $processed_objects[ $old_id ] ) ) {
204 $new_translations[ $slug ] = $processed_objects[ $old_id ];
205 } else {
206 $new_translations[ $slug ] = $old_id; // Preserve values for all keys which are not our language slugs.
207 }
208 }
209
210 if ( ! empty( $new_translations ) ) {
211 $to_update['case'][] = array( $this->processed_terms[ $term['term_id'] ], maybe_serialize( $new_translations ) );
212 $to_update['in'][] = (int) $this->processed_terms[ $term['term_id'] ];
213 }
214 }
215
216 if ( ! empty( $to_update ) ) {
217 $wpdb->query(
218 $wpdb->prepare(
219 sprintf(
220 "UPDATE {$wpdb->term_taxonomy}
221 SET description = ( CASE term_id %s END )
222 WHERE term_id IN (%s)",
223 implode( ' ', array_fill( 0, count( $to_update['case'] ), 'WHEN %d THEN %s' ) ),
224 implode( ',', array_fill( 0, count( $to_update['in'] ), '%d' ) )
225 ),
226 array_merge( array_merge( ...$to_update['case'] ), $to_update['in'] )
227 )
228 );
229 }
230 }
231 }
232