PluginProbe ʕ •ᴥ•ʔ
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets / trunk
WP All Import – Drag & Drop Import for CSV, XML, Excel & Google Sheets vtrunk
4.1.1 3.9.5 3.9.6 4.0.0 4.0.1 4.1.0 trunk 2.12 2.13 2.14 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.6.9 3.7.0 3.7.1 3.7.2 3.7.3 3.7.3-beta-1.0 3.7.4 3.7.4-beta-1.0 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4
wp-all-import / addon-api / classes / importer.php
wp-all-import / addon-api / classes Last commit date
admin.php 1 month ago base.php 1 month ago data-importer.php 1 month ago helpers.php 1 month ago importer.php 1 month ago manager.php 1 month ago parser.php 1 month ago post-data-importer.php 1 month ago rest.php 1 month ago updater.php 1 month ago view.php 1 month ago
importer.php
334 lines
1 <?php
2
3 namespace Wpai\AddonAPI;
4
5 if ( ! defined( 'ABSPATH' ) ) exit;
6
7 class PMXI_Addon_Importer {
8
9 public PMXI_Addon_Base $addon;
10
11 public function __construct( $addon ) {
12 $this->addon = $addon;
13 }
14
15 /**
16 * Get the default options for the addon
17 */
18 public function defaults(
19 string $type,
20 ?string $subtype = null
21 ) {
22 $addon_options = [];
23 $options = [];
24
25 $fields = $this->addon->fields( $type, $subtype );
26
27 foreach ( $fields as $field ) {
28 $addon_options[ $field['key'] ] = '';
29 }
30
31 $options[ $this->addon->slug ] = $addon_options;
32 $options[ $this->addon->slug . '_groups' ] = [];
33 $options[ $this->addon->slug . '_switchers' ] = [];
34 $options[ $this->addon->slug . '_multiple' ] = [];
35
36 if ( ! isset( $options['update_addons'] ) ) {
37 $options['update_addons'] = [];
38 }
39
40 $options['update_addons'][ $this->addon->slug ] = $this->addon->defaultUpdateOptions();
41
42 return $options;
43 }
44
45 public function isFieldEmpty( $value ) {
46 return $value == '' || $value == null || $value == [];
47 }
48
49 public function isRepeatable( $field ) {
50 return $field['type'] === 'repeater' || ( $field['args']['is_cloneable'] ?? false );
51 }
52
53 /*
54 * Return data for the given record index
55 */
56 public function unwrapValue( $field, $value, $index ) {
57 if ( is_array( $value ) ) {
58 if ( isAssocArray( $value ) ) {
59 if ( empty( $value ) ) {
60 return null;
61 }
62
63 return $value[ $index ];
64 }
65
66 $unwrappedData = [];
67
68 foreach ( $value as $key => $item ) {
69 if ( $this->isRepeatable( $field ) && $key === "rows" ) {
70 $unwrappedData[ $key ] = [];
71 foreach ( $item as $rowIndex => $row ) {
72 $unwrappedData[ $key ][ $rowIndex ] = $this->unwrapValue( $field, $row, $index );
73 }
74 } elseif ( is_array( $item ) ) {
75 if ( isset( $item[ $index ] ) ) {
76 $unwrappedData[ $key ] = $item[ $index ];
77 } else {
78 $unwrappedData[ $key ] = $this->unwrapValue( $field, $item, $index );
79 }
80 } else {
81 $unwrappedData[ $key ] = $item;
82 }
83 }
84
85 return $unwrappedData;
86 } else {
87 return $value;
88 }
89 }
90
91 public function castValue( $field, $value, $post_id, $post_type ) {
92 if ( isset( $this->addon->casts[ $field['type'] ] ) ) {
93 $cast = new $this->addon->casts[ $field['type'] ];
94
95 return $cast( $field, $value, $post_id, $post_type );
96 }
97
98 return $value;
99 }
100
101 public function getImportFields( $type, $subtype, $groups, $data ) {
102 // Filter out fields that don't exist in the parsed data
103 $fields = array_filter(
104 $this->addon->fields( $type, $subtype ),
105 fn( $field ) => isset( $data[ $field['key'] ] )
106 );
107
108 // Filter out fields from disabled groups
109 $fields = array_filter(
110 $fields,
111 fn( $field ) => in_array( $field['group'], $groups )
112 );
113
114 return array_values( $fields );
115 }
116
117 /**
118 * Simplify import data
119 * TODO: Make this more functional
120 *
121 * @return array|null
122 */
123 public function simplify( array $importData, array $parsedData ) {
124 $options = $importData['import']['options'];
125 $type = $options['custom_type'];
126 $subtype = $options['taxonomy_type'];
127 $view = PMXI_Addon_View::create(
128 $this->addon->slug,
129 $type,
130 $subtype
131 );
132
133 if ( ! $this->addon->isAvailableForType( $type, $options ) ) {
134 return null;
135 }
136
137 if ( $importData['logger'] ) {
138 call_user_func( $importData['logger'], '<strong>' . sprintf(
139 /* translators: %s: add-on name */
140 __( '%s:', 'wp-all-import' ),
141 strtoupper( $this->addon->name() )
142 ) . '</strong>' );
143 }
144
145 if ( ! array_key_exists( $this->addon->slug, $options ) ) {
146 call_user_func( $importData['logger'], __( 'No options found for this addon, skipping...', 'wp-all-import' ) );
147
148 return null;
149 }
150
151 $import_options = $options[ $this->addon->slug ];
152 $switchers = $options[ $this->addon->slug . '_switchers' ];
153 $multiples = $options[ $this->addon->slug . '_multiple' ];
154 $groups = $options[ $this->addon->slug . '_groups' ];
155
156 if ( empty( $parsedData ) ) {
157 return null;
158 }
159
160 $data = [];
161 $post_id = $importData['pid'];
162 $index = $importData['i'];
163
164 $fields = $this->getImportFields( $type, $subtype, $groups, $parsedData );
165
166 foreach ( $fields as $field_index => $field ) {
167 $field_slug = $field['key'];
168 $field_value = $this->unwrapValue( $field, $parsedData[ $field_slug ], $index );
169
170 if ( ! $this->canUpdateField( $field, $options ) ) {
171 /* translators: %s: field key */
172 call_user_func( $importData['logger'], sprintf( __( '- Field `%s` skipped due to import settings.', 'wp-all-import' ), $field['key'] ) );
173 unset($fields[$field_index]);
174 continue;
175 }
176
177 if (
178 isset( $switchers[ $field_slug ] ) &&
179 isset( $multiples[ $field_slug ] ) &&
180 $switchers[ $field_slug ] == 'yes'
181 ) {
182 $field_value = $multiples[ $field_slug ];
183 }
184
185 // Handle nested switchers
186 if ( $this->isRepeatable( $field ) && isset( $field_value['rows'] ) ) {
187 foreach ( $field_value['rows'] as $rowIndex => $row ) {
188 foreach ( $field['subfields'] as $subfield ) {
189 $subfield_slug = $subfield['key'];
190 $subfield_switcher = $switchers[ $field_slug ]['rows'][ $rowIndex ][ $subfield_slug ] ?? 'no';
191
192 if ( $subfield_switcher == 'yes' ) {
193 $field_value['rows'][ $rowIndex ][ $subfield_slug ] = $multiples[ $field_slug ]['rows'][ $rowIndex ][ $subfield_slug ] ?? 0;
194 }
195 }
196 }
197 }
198
199 // If the field is empty and has a default value, use that instead
200 if ( $this->isFieldEmpty( $field_value ) ) {
201 if ( isset( $field['default'] ) ) {
202 $field_value = $field['default'];
203 } else {
204 continue;
205 }
206 }
207
208 // Apply before import filters
209 $field_instance = PMXI_Addon_Field::from( $field, $view );
210
211 $data[ $field_slug ] = $field_instance->beforeImport(
212 $post_id,
213 $field_value,
214 $importData,
215 $importData['logger'],
216 $import_options[ $field_slug ] ?? []
217 );
218
219 // Cast the value to a new value if a cast class exists
220 if ( $this->isRepeatable( $field ) ) {
221 foreach ( $data[ $field_slug ] as $rowIndex => $row ) {
222 foreach ( $field['subfields'] as $subfield ) {
223 $subfield_slug = $subfield['key'];
224
225 if ( isset( $row[ $subfield_slug ] ) ) {
226 $data[ $field_slug ][ $rowIndex ][ $subfield_slug ] = $this->castValue(
227 $subfield,
228 $row[ $subfield_slug ],
229 $post_id,
230 $type
231 );
232 }
233 }
234 }
235 }
236
237 $data[ $field_slug ] = $this->castValue( $field, $data[ $field_slug ], $post_id, $type );
238 // --------------------
239
240 // Apply mapping rules if they exist
241 if ( ! empty( $import_options['mapping'][ $field_slug ] ) ) {
242 $mapping_rules = json_decode( $import_options['mapping'][ $field_slug ], true );
243
244 if ( ! empty( $mapping_rules ) and is_array( $mapping_rules ) ) {
245 foreach ( $mapping_rules as $rule_number => $map_to ) {
246 if ( isset( $map_to[ trim( $data[ $field_slug ] ) ] ) ) {
247 $data[ $field_slug ] = trim( $map_to[ trim( $data[ $field_slug ] ) ] );
248 break;
249 }
250 }
251 }
252 }
253 // --------------------
254 }
255
256 // If no fields are found, skip the import
257 if ( empty( $data ) ) {
258 call_user_func( $importData['logger'], __( 'No options found for this addon, skipping...', 'wp-all-import' ) );
259
260 return null;
261 }
262
263 return [ $post_id, $fields, $data, $importData['import'], $importData['articleData'], $importData['logger'] ];
264 }
265
266
267 /**
268 * @param $field
269 * @param array $import_options
270 *
271 * @return bool
272 */
273 public function canDeleteField( $field, $import_options ) {
274 if ( $import_options['is_keep_former_posts'] === 'yes' ) {
275 return false;
276 }
277
278 return $this->canUpdateField( $field, $import_options );
279 }
280
281
282 /**
283 * @param $field
284 * @param array $import_options
285 *
286 * @return bool
287 */
288 public function canUpdateField( $field, $import_options ) {
289 $rules = $import_options['update_addons'][ $this->addon->slug ] ?? null;
290
291 // Support for old templates
292 if ( ! isset( $rules ) ) {
293 return true;
294 }
295
296 if ( $import_options['update_all_data'] === 'yes' ) {
297 return true;
298 }
299
300 if ( ! $rules['is_update'] ) {
301 return false;
302 }
303
304 if ( $rules['update_logic'] === "full_update" ) {
305 return true;
306 }
307
308 if (
309 $rules['update_logic'] === "only" &&
310 ! empty( $rules['fields_list'] ) &&
311 is_array( $rules['fields_list'] ) &&
312 in_array( $field['key'], $rules['fields_list'] )
313 ) {
314 return true;
315 }
316
317 if (
318 $rules['update_logic'] === "all_except" &&
319 (
320 empty( $rules['fields_list'] ) ||
321 ! in_array( $field['key'], $rules['fields_list'] )
322 )
323 ) {
324 return true;
325 }
326
327 return false;
328 }
329
330 public static function from( PMXI_Addon_Base $addon ) {
331 return new static( $addon );
332 }
333 }
334