PluginProbe ʕ •ᴥ•ʔ
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel / trunk
WP All Export – Drag & Drop Export to Any Custom CSV, XML & Excel vtrunk
trunk 0.9.0 0.9.1 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0 1.2.1 1.2.10 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.14 1.4.15 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0
wp-all-export / libraries / XmlCsvExport.php
wp-all-export / libraries Last commit date
VariableProductTitle 4 weeks ago .gitkeep 10 years ago WpaeInvalidPhpException.php 9 years ago WpaeInvalidStringException.php 9 years ago WpaeMethodNotFoundException.php 9 years ago WpaePhpInterpreterErrorHandler.php 4 weeks ago WpaeString.php 8 years ago WpaeTooMuchRecursionException.php 9 years ago XmlCsvExport.php 4 weeks ago XmlExportCpt.php 4 weeks ago XmlExportCustomRecord.php 4 weeks ago XmlExportEngine.php 4 weeks ago XmlExportFiltering.php 4 weeks ago XmlExportMediaGallery.php 4 weeks ago XmlExportTaxonomy.php 4 weeks ago
XmlCsvExport.php
1115 lines
1 <?php
2
3 // phpcs:ignoreFile WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound,WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedFunctionFound,WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- legitimate plugin prefixes (pmxe/PMXE/wpae/Wpae/wp_all_export/wpallexport/XmlExport/CdataStrategy/VariableProductTitle/Soflyy/GF_Export); Plugin Check does not honor phpcs.xml prefix declaration
4 defined( 'ABSPATH' ) || exit;
5
6
7 final Class XmlCsvExport
8 {
9 public static $main_xml_tag = '';
10
11 public static $node_xml_tag = '';
12
13 /** @var \Wpae\Csv\CsvWriter */
14 private static $csvWriter;
15
16 public static function export()
17 {
18 switch ( XmlExportEngine::$exportOptions['export_to'] )
19 {
20 case 'xml':
21 self::export_xml();
22 break;
23
24 case XmlExportEngine::EXPORT_TYPE_CSV:
25 self::export_csv();
26 break;
27 default:
28 # code...
29 break;
30 }
31 }
32
33 public static function export_csv( $preview = false, $is_cron = false, $file_path = false, $exported_by_cron = 0 )
34 {
35
36 if ( XmlExportEngine::$exportOptions['delimiter'] == '\t' ) XmlExportEngine::$exportOptions['delimiter'] = "\t";
37
38 ob_start();
39
40 $stream = fopen("php://output", 'w');
41
42 $headers = array();
43 $woo = array();
44 $woo_order = array();
45 $acfs = array();
46 $articles = array();
47
48 // [ Exporting requested data ]
49
50 if ( XmlExportEngine::$is_user_export ) { // exporting WordPress users
51
52 foreach ( XmlExportEngine::$exportQuery->results as $user ) {
53 $articles[] = XmlExportUser::prepare_data($user, XmlExportEngine::$exportOptions ,false, $acfs, XmlExportEngine::$implode, $preview);
54 $articles = apply_filters('wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
55 if (!$preview) do_action('pmxe_exported_post', $user->ID, XmlExportEngine::$exportRecord);
56 }
57 }
58 elseif ( XmlExportEngine::$is_comment_export ) { // exporting comments
59 die(wp_kses(\__('WP All Export Pro is required to run this export. If you already own it, you can download it here: <a href="http://www.wpallimport.com/portal/downloads" target="_blank">http://www.wpallimport.com/portal/downloads</a>', 'wp-all-export'), array('a' => array('href' => true, 'target' => true))));
60 }
61 elseif ( XmlExportEngine::$is_taxonomy_export ) { // exporting WordPress taxonomy terms
62
63 add_filter('terms_clauses', 'wp_all_export_terms_clauses', 10, 3);
64 $terms = XmlExportEngine::$exportQuery->get_terms();
65 remove_filter('terms_clauses', 'wp_all_export_terms_clauses');
66 foreach ( $terms as $term ) {
67 $articles[] = XmlExportTaxonomy::prepare_data($term, false, $acfs, XmlExportEngine::$implode, $preview);
68 $articles = apply_filters('wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
69 if (!$preview) do_action('pmxe_exported_post', $term->term_id, XmlExportEngine::$exportRecord);
70 }
71 }
72 elseif (XmlExportEngine::$is_custom_addon_export) {
73
74 foreach (XmlExportEngine::$exportQuery->results as $record) {
75
76 $articles[] = XmlExportCustomRecord::prepare_data($record, XmlExportEngine::$exportOptions, false, $acfs, XmlExportEngine::$implode, $preview);
77 $articles = apply_filters('wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
78 if (!$preview) do_action('pmxe_exported_post', $record->id, XmlExportEngine::$exportRecord);
79 }
80 }
81 else { // exporting custom post types
82
83 $exportOptions = XmlExportEngine::$exportOptions;
84
85 if($exportOptions['export_type'] != 'advanced' && in_array('shop_order', $exportOptions['cpt']) && PMXE_Plugin::hposEnabled()) {
86
87
88 $exported = 0;
89 if(is_object(XmlExportEngine::$exportRecord)) {
90 $exported = XmlExportEngine::$exportRecord->exported;
91 }
92
93 $orders = XmlExportEngine::$exportQuery->getOrders($exported, $exportOptions['records_per_iteration']);
94
95 foreach ($orders as $record) {
96
97 if(!isset($record->ID)) {
98 $recordId = $record->id;
99 } else {
100 $recordId = $record->ID;
101 }
102 $articles[] = XmlExportCpt::prepare_data($record, $exportOptions, false, $acfs, $woo, $woo_order, XmlExportEngine::$implode, $preview);
103 $articles = apply_filters('wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
104 if (!$preview) do_action('pmxe_exported_post', $recordId, XmlExportEngine::$exportRecord);
105 }
106
107 } else {
108 while ( XmlExportEngine::$exportQuery->have_posts() ) {
109 XmlExportEngine::$exportQuery->the_post();
110 $record = get_post( get_the_ID() );
111 $articles[] = XmlExportCpt::prepare_data( $record, XmlExportEngine::$exportOptions, false, $acfs, $woo, $woo_order, XmlExportEngine::$implode, $preview );
112 $articles = apply_filters( 'wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID );
113 if ( ! $preview ) {
114 do_action( 'pmxe_exported_post', $record->ID, XmlExportEngine::$exportRecord );
115 }
116 }
117 }
118
119 wp_reset_postdata();
120 }
121 // [ \Exporting requested data ]
122
123 // [ Prepare CSV headers ]
124 if (XmlExportEngine::$exportOptions['ids']):
125
126 foreach (XmlExportEngine::$exportOptions['ids'] as $ID => $value)
127 {
128 if ( empty(XmlExportEngine::$exportOptions['cc_name'][$ID]) or empty(XmlExportEngine::$exportOptions['cc_type'][$ID]) or ! is_numeric($ID) ) continue;
129
130 self::prepare_csv_headers( $headers, $ID, $acfs );
131 }
132
133 endif;
134
135 $headers = apply_filters( 'wp_all_export_csv_headers', $headers, XmlExportEngine::$exportID );
136
137 if ($is_cron) {
138 if ( ! $exported_by_cron ) {
139 self::getCsvWriter()->writeCsv($stream, array_map(array('XmlCsvExport', '_get_valid_header_name'), $headers), XmlExportEngine::$exportOptions['delimiter']);
140 apply_filters('wp_all_export_after_csv_line', $stream, XmlExportEngine::$exportID);
141 }
142 else {
143 self::merge_headers( $file_path, $headers );
144 }
145 }
146 else
147 {
148 if ($preview or empty(PMXE_Plugin::$session->file)) {
149 self::getCsvWriter()->writeCsv($stream, array_map(array('XmlCsvExport', '_get_valid_header_name'), $headers), XmlExportEngine::$exportOptions['delimiter']);
150 apply_filters('wp_all_export_after_csv_line', $stream, XmlExportEngine::$exportID);
151 }
152 else {
153 self::merge_headers( PMXE_Plugin::$session->file, $headers );
154 }
155 }
156
157 // [ \Prepare CSV headers ]
158 if (!empty($articles)) {
159 foreach ($articles as $article) { if (empty($article)) continue;
160 $line = array();
161 foreach ($headers as $header) {
162 $line[$header] = (isset($article[$header])) ? $article[$header] : '';
163 }
164 self::getCsvWriter()->writeCsv($stream, $line, XmlExportEngine::$exportOptions['delimiter']);
165 apply_filters('wp_all_export_after_csv_line', $stream, XmlExportEngine::$exportID);
166 }
167 }
168
169 if ($preview) return ob_get_clean();
170
171 return self::save_csv_to_file( $file_path, $is_cron, $exported_by_cron );
172
173 }
174
175 public static function export_xml( $preview = false, $is_cron = false, $file_path = false, $exported_by_cron = 0 )
176 {
177 $is_custom_xml = ( ! empty(XmlExportEngine::$exportOptions['xml_template_type']) && in_array(XmlExportEngine::$exportOptions['xml_template_type'], array('custom', 'XmlGoogleMerchants')) ) ? true : false;
178
179 if ( ! empty(XmlExportEngine::$exportOptions['xml_template_type']) ){
180
181 switch (XmlExportEngine::$exportOptions['xml_template_type']) {
182 case 'custom':
183 case 'XmlGoogleMerchants':
184 XmlExportEngine::$exportOptions['ids'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['ids'];
185 XmlExportEngine::$exportOptions['cc_label'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['cc_label'];
186 XmlExportEngine::$exportOptions['cc_type'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['cc_type'];
187 XmlExportEngine::$exportOptions['cc_value'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['cc_value'];
188 XmlExportEngine::$exportOptions['cc_name'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['cc_name'];
189 XmlExportEngine::$exportOptions['cc_php'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['cc_php'];
190 XmlExportEngine::$exportOptions['cc_code'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['cc_code'];
191 XmlExportEngine::$exportOptions['cc_sql'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['cc_sql'];
192 XmlExportEngine::$exportOptions['cc_options'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['cc_options'];
193 XmlExportEngine::$exportOptions['cc_settings'] = XmlExportEngine::$exportOptions['custom_xml_template_options']['cc_settings'];
194 break;
195 default:
196 # code...
197 break;
198 }
199 }
200
201 if ( XmlExportEngine::$exportOptions['delimiter'] == '\t' ) XmlExportEngine::$exportOptions['delimiter'] = "\t";
202
203 require_once PMXE_ROOT_DIR . '/classes/XMLWriter.php';
204
205 $woo = array();
206 $woo_order = array();
207 $acfs = array();
208
209 self::$main_xml_tag = apply_filters('wp_all_export_main_xml_tag', XmlExportEngine::$exportOptions['main_xml_tag'], XmlExportEngine::$exportID);
210 self::$node_xml_tag = apply_filters('wp_all_export_record_xml_tag', XmlExportEngine::$exportOptions['record_xml_tag'], XmlExportEngine::$exportID);
211
212 // self::$implode = (XmlExportEngine::$exportOptions['delimiter'] == ',') ? '|' : ',';
213 //
214 // if ( $is_custom_xml ) self::$implode = '#delimiter#';
215
216 $xmlWriter = new PMXE_XMLWriter();
217
218 if ( ! $is_custom_xml ) {
219
220 $xmlWriter->openMemory();
221 $xmlWriter->setIndent(true);
222 $xmlWriter->setIndentString("\t");
223 $xmlWriter->startDocument('1.0', XmlExportEngine::$exportOptions['encoding']);
224 $xmlWriter->startElement(self::$main_xml_tag);
225 // add additional data after XML root element
226 self::xml_header( $xmlWriter, $is_cron, $exported_by_cron );
227 }
228
229 // [ Exporting requested data ]
230
231 if ( XmlExportEngine::$is_user_export ) // exporting WordPress users
232 {
233 foreach ( XmlExportEngine::$exportQuery->results as $user ) :
234
235 $is_export_record = apply_filters('wp_all_export_xml_rows', true, $user, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
236
237 if ( ! $is_export_record ) continue;
238
239 if ( ! $is_custom_xml ) {
240 // add additional information before each node
241 self::before_xml_node( $xmlWriter, $user->ID);
242
243 $xmlWriter->startElement(self::$node_xml_tag);
244
245 XmlExportUser::prepare_data( $user, XmlExportEngine::$exportOptions, $xmlWriter, $acfs, XmlExportEngine::$implode, $preview );
246
247 $xmlWriter->closeElement(); // end post
248
249 // add additional information after each node
250 self::after_xml_node( $xmlWriter, $user->ID);
251 }
252 else {
253 $articles = array();
254 $articles[] = XmlExportUser::prepare_data( $user, XmlExportEngine::$exportOptions, $xmlWriter, $acfs, XmlExportEngine::$implode, $preview );
255 $articles = apply_filters('wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
256
257 $xmlWriter->writeArticle( $articles );
258 }
259
260 if ( ! $preview) do_action('pmxe_exported_post', $user->ID, XmlExportEngine::$exportRecord );
261
262 endforeach;
263
264 }
265 elseif ( XmlExportEngine::$is_taxonomy_export ) // exporting WordPress taxonomy terms
266 {
267 add_filter('terms_clauses', 'wp_all_export_terms_clauses', 10, 3);
268 $terms = XmlExportEngine::$exportQuery->get_terms();
269 remove_filter('terms_clauses', 'wp_all_export_terms_clauses');
270 foreach ( $terms as $term ) {
271
272 $is_export_record = apply_filters('wp_all_export_xml_rows', true, $term, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
273
274 if (!$is_export_record) continue;
275
276 if (!$is_custom_xml) {
277 // add additional information before each node
278 self::before_xml_node($xmlWriter, $term->term_id);
279
280 $xmlWriter->startElement(self::$node_xml_tag);
281
282 XmlExportTaxonomy::prepare_data($term, $xmlWriter, $acfs, XmlExportEngine::$implode, $preview);
283
284 $xmlWriter->closeElement(); // end post
285
286 // add additional information after each node
287 self::after_xml_node($xmlWriter, $term->term_id);
288 } else {
289 $articles = array();
290 $articles[] = XmlExportTaxonomy::prepare_data($term, $xmlWriter, $acfs, XmlExportEngine::$implode, $preview);
291 $articles = apply_filters('wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
292
293 $xmlWriter->writeArticle($articles);
294 }
295
296 if (!$preview) do_action('pmxe_exported_post', $term->term_id, XmlExportEngine::$exportRecord);
297
298 }
299
300 } else if ( XmlExportEngine::$exportOptions['export_type'] != 'advanced' && XmlExportEngine::$is_woo_order_export && PMXE_Plugin::hposEnabled() ) {
301 add_filter( 'posts_where', 'wp_all_export_numbering_where', 15, 1 );
302
303
304 $exported = 0;
305 if ( is_object( XmlExportEngine::$exportRecord ) ) {
306 $exported = XmlExportEngine::$exportRecord->exported;
307 }
308 $orders = XmlExportEngine::$exportQuery->getOrders( $exported, XmlExportEngine::$exportOptions['records_per_iteration'] );
309
310 foreach ( $orders as $record ) {
311
312 if ( ! isset( $record->ID ) ) {
313 $recordId = $record->id;
314 } else {
315 $recordId = $record->ID;
316 }
317
318 if ( ! $is_custom_xml ) {
319 // add additional information before each node
320 self::before_xml_node( $xmlWriter, $record->id );
321 $xmlWriter->startElement( self::$node_xml_tag );
322
323 XmlExportCpt::prepare_data( $record, XmlExportEngine::$exportOptions, $xmlWriter, $acfs, $woo, $woo_order, XmlExportEngine::$implode, $preview );
324
325 $xmlWriter->closeElement(); // end post
326
327 // add additional information after each node
328 self::after_xml_node( $xmlWriter, $record->id );
329 } else {
330 $articles = [];
331 $articles[] = XmlExportCpt::prepare_data( $record, XmlExportEngine::$exportOptions, false, $acfs, $woo, $woo_order, XmlExportEngine::$implode, $preview );
332 $articles = apply_filters( 'wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID );
333 $xmlWriter->writeArticle( $articles );
334 }
335
336 if ( ! $preview ) {
337 do_action( 'pmxe_exported_post', $recordId, XmlExportEngine::$exportRecord );
338 }
339 }
340 } elseif (XmlExportEngine::$is_custom_addon_export) {
341
342 foreach (XmlExportEngine::$exportQuery->results as $record) {
343
344 $is_export_record = apply_filters('wp_all_export_xml_rows', true, $record, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
345
346 if (!$is_export_record) continue;
347
348 if (!$is_custom_xml) {
349 // add additional information before each node
350 self::before_xml_node($xmlWriter, $record->id);
351 $xmlWriter->startElement(self::$node_xml_tag);
352
353 XmlExportCustomRecord::prepare_data($record, XmlExportEngine::$exportOptions, $xmlWriter, XmlExportEngine::$implode, $preview);
354
355 $xmlWriter->closeElement(); // end post
356
357 // add additional information after each node
358 self::after_xml_node($xmlWriter, $record->id);
359 } else {
360 $articles = array();
361 $articles[] = XmlExportCustomRecord::prepare_data($record, XmlExportEngine::$exportOptions, $xmlWriter, XmlExportEngine::$implode, $preview);
362 $articles = apply_filters('wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
363
364 $xmlWriter->writeArticle($articles);
365 }
366
367 if (!$preview) {
368 do_action('pmxe_exported_post', $record->id, XmlExportEngine::$exportRecord);
369 }
370 }
371 }
372 elseif ( XmlExportEngine::$is_comment_export ) // exporting comments
373 {
374 die(wp_kses(\__('WP All Export Pro is required to run this export. If you already own it, you can download it here: <a href="http://www.wpallimport.com/portal/downloads" target="_blank">http://www.wpallimport.com/portal/downloads</a>', 'wp-all-export'), array('a' => array('href' => true, 'target' => true))));
375 }
376 else {// exporting custom post types
377 while ( XmlExportEngine::$exportQuery->have_posts() ) {
378 XmlExportEngine::$exportQuery->the_post();
379 $record = get_post(get_the_ID());
380
381 $is_export_record = apply_filters('wp_all_export_xml_rows', true, $record, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
382
383 if (!$is_export_record) continue;
384
385 if (!$is_custom_xml) {
386 // add additional information before each node
387 self::before_xml_node($xmlWriter, $record->ID);
388 $xmlWriter->startElement(self::$node_xml_tag);
389 XmlExportCpt::prepare_data($record, XmlExportEngine::$exportOptions, $xmlWriter, $acfs, $woo, $woo_order, XmlExportEngine::$implode, $preview);
390
391 $xmlWriter->closeElement(); // end post
392
393 // add additional information after each node
394 self::after_xml_node($xmlWriter, $record->ID);
395 } else {
396 $articles = array();
397 $articles[] = XmlExportCpt::prepare_data($record, XmlExportEngine::$exportOptions, $xmlWriter, $acfs, $woo, $woo_order, XmlExportEngine::$implode, $preview);
398 $articles = apply_filters('wp_all_export_csv_rows', $articles, XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
399
400 $xmlWriter->writeArticle($articles);
401 }
402
403 if (!$preview) do_action('pmxe_exported_post', $record->ID, XmlExportEngine::$exportRecord);
404 }
405 wp_reset_postdata();
406 }
407 // [ \Exporting requested data ]
408
409 if ( ! $is_custom_xml ) $xmlWriter->closeElement(); // close root XML element
410
411 if ($preview) {
412 return $xmlWriter->wpae_flush();
413 }
414
415 return self::save_xml_to_file( $xmlWriter, $file_path, $is_cron, $exported_by_cron );
416
417 }
418
419 // [ XML Export Helpers ]
420 private static function xml_header($xmlWriter, $is_cron, $exported_by_cron)
421 {
422 if ($is_cron) {
423 if ( ! $exported_by_cron ) {
424
425 $additional_data = apply_filters('wp_all_export_additional_data', array(), XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
426
427 if ( ! empty($additional_data)) {
428 foreach ($additional_data as $key => $value) {
429 self::addElement($xmlWriter, $key, $value);
430 }
431 }
432 }
433 }
434 else
435 {
436
437 if ( empty(PMXE_Plugin::$session->file) ){
438
439 $additional_data = apply_filters('wp_all_export_additional_data', array(), XmlExportEngine::$exportOptions, XmlExportEngine::$exportID);
440
441 if ( ! empty($additional_data)) {
442 foreach ($additional_data as $key => $value) {
443 self::addElement($xmlWriter, $key, $value);
444 }
445 }
446 }
447 }
448 }
449
450 private static function before_xml_node( $xmlWriter, $pid )
451 {
452 $add_before_node = apply_filters('wp_all_export_add_before_node', array(), XmlExportEngine::$exportOptions, XmlExportEngine::$exportID, $pid);
453
454 if ( ! empty($add_before_node)) {
455 foreach ($add_before_node as $key => $value) {
456 self::addElement($xmlWriter, $key, $value);
457 }
458 }
459 }
460
461 private static function after_xml_node( $xmlWriter, $pid )
462 {
463 $add_after_node = apply_filters('wp_all_export_add_after_node', array(), XmlExportEngine::$exportOptions, XmlExportEngine::$exportID, $pid);
464
465 if ( ! empty($add_after_node)) {
466 foreach ($add_after_node as $key => $value) {
467 self::addElement($xmlWriter, $key, $value);
468 }
469 }
470 }
471
472 private static function save_xml_to_file( $xmlWriter, $file_path, $is_cron, $exported_by_cron )
473 {
474 $is_custom_xml = in_array(XmlExportEngine::$exportOptions['xml_template_type'], array('custom', 'XmlGoogleMerchants'));
475
476 if ($is_cron)
477 {
478 if ( ! $is_custom_xml ) {
479 $xml_header = apply_filters('wp_all_export_xml_header', '<?xml version="1.0" encoding="UTF-8"?>', XmlExportEngine::$exportID);
480
481 $xml = str_replace('<?xml version="1.0" encoding="UTF-8"?>', $xml_header, $xmlWriter->wpae_flush());
482 }
483 else {
484 $xml_header = XmlExportEngine::$exportOptions['custom_xml_template_header'];
485
486 $xml = ( ! $exported_by_cron ) ? PMXE_XMLWriter::preprocess_xml($xml_header) . $xmlWriter->wpae_flush() : $xmlWriter->wpae_flush();
487 }
488
489 if ( ! $exported_by_cron ) {
490 if ( ! $is_custom_xml ) $xml = substr($xml, 0, (strlen(self::$main_xml_tag) + 4) * (-1));
491
492 // The BOM will help some programs like Microsoft Excel read your export file if it includes non-English characters.
493 if (XmlExportEngine::$exportOptions['include_bom']) {
494 file_put_contents($file_path, chr(0xEF).chr(0xBB).chr(0xBF).$xml);
495 }
496 else {
497 file_put_contents($file_path, $xml);
498 }
499 }
500 else {
501 $xml = ( ! $is_custom_xml ) ? substr(substr($xml, 41 + strlen(self::$main_xml_tag)), 0, (strlen(self::$main_xml_tag) + 4) * (-1)) : $xml;
502 file_put_contents($file_path, $xml, FILE_APPEND);
503 }
504
505 return $file_path;
506
507 }
508 else {
509
510 if ( empty(PMXE_Plugin::$session->file) ){
511
512 // generate export file name
513 $export_file = wp_all_export_generate_export_file( XmlExportEngine::$exportID );
514
515 if ( ! $is_custom_xml ) {
516 $xml_header = apply_filters('wp_all_export_xml_header', '<?xml version="1.0" encoding="UTF-8"?>', XmlExportEngine::$exportID);
517
518 $xml = str_replace('<?xml version="1.0" encoding="UTF-8"?>', $xml_header, $xmlWriter->wpae_flush());
519 }
520 else {
521 $xml_header = XmlExportEngine::$exportOptions['custom_xml_template_header'];
522
523 $xml = PMXE_XMLWriter::preprocess_xml($xml_header) . $xmlWriter->wpae_flush();
524 }
525
526 if ( ! $is_custom_xml ) $xml = substr($xml, 0, (strlen(self::$main_xml_tag) + 4) * (-1));
527
528 // The BOM will help some programs like Microsoft Excel read your export file if it includes non-English characters.
529 if (XmlExportEngine::$exportOptions['include_bom']) {
530 file_put_contents($export_file, chr(0xEF).chr(0xBB).chr(0xBF).$xml);
531 }
532 else {
533 file_put_contents($export_file, $xml);
534 }
535
536 PMXE_Plugin::$session->set('file', $export_file);
537 PMXE_Plugin::$session->save_data();
538
539 }
540 else {
541 $xml = ( ! $is_custom_xml ) ? substr(substr($xmlWriter->wpae_flush(), 41 + strlen(self::$main_xml_tag)), 0, (strlen(self::$main_xml_tag) + 4) * (-1)) : $xmlWriter->wpae_flush();
542
543 file_put_contents(PMXE_Plugin::$session->file, $xml, FILE_APPEND);
544 }
545
546 return true;
547
548 }
549 }
550 // [ \XML Export Helpers ]
551
552 // [ CSV Export Helpers ]
553 public static function prepare_csv_headers( & $headers, $ID, &$acfs )
554 {
555 $element_name = ( ! empty(XmlExportEngine::$exportOptions['cc_name'][$ID]) ) ? XmlExportEngine::$exportOptions['cc_name'][$ID] : 'untitled_' . $ID;
556 $element_name = apply_filters('wp_all_export_field_name', wp_all_export_parse_field_name($element_name), XmlExportEngine::$exportID);
557
558 if ( strpos(XmlExportEngine::$exportOptions['cc_label'][$ID], "item_data__") !== false ) {
559 XmlExportEngine::$woo_order_export->get_element_header( $headers, XmlExportEngine::$exportOptions, $ID );
560 return;
561 }
562
563 switch (XmlExportEngine::$exportOptions['cc_type'][$ID])
564 {
565 case 'woo':
566 if(XmlExportEngine::$woo_export) {
567 XmlExportEngine::$woo_export->get_element_header($headers, XmlExportEngine::$exportOptions, $ID);
568 }
569 break;
570
571 case 'woo_order':
572 if(XmlExportEngine::$woo_order_export) {
573 XmlExportEngine::$woo_order_export->get_element_header($headers, XmlExportEngine::$exportOptions, $ID);
574 }
575 break;
576
577 case 'acf':
578 if ( ! empty($acfs) ) {
579 $single_acf_field = array_shift($acfs);
580
581 if ( is_array($single_acf_field)) {
582 foreach ($single_acf_field as $acf_header) {
583 if ( ! in_array($acf_header, $headers)) $headers[] = $acf_header;
584 }
585 }
586 else {
587 if ( ! in_array($single_acf_field, $headers)) $headers[] = $single_acf_field;
588 }
589 }
590 break;
591
592 default:
593
594 // For ID columns make first element in lowercase for Excel export
595 if ($element_name == 'ID' && ! $ID && isset(XmlExportEngine::$exportOptions['export_to_sheet']) && XmlExportEngine::$exportOptions['export_to_sheet'] != 'csv'){
596 $element_name = 'id';
597 }
598
599 if ( ! in_array($element_name, $headers)) {
600 $headers[] = $element_name;
601 }
602 else {
603 $is_added = false;
604 $i = 0;
605 do {
606 $new_element_name = $element_name . '_' . md5($i);
607
608 if ( ! in_array($new_element_name, $headers) ) {
609 $headers[] = $new_element_name;
610 $is_added = true;
611 }
612
613 $i++;
614 }
615 while ( ! $is_added );
616 }
617
618 // if ( XmlExportEngine::$exportOptions['cc_label'][$ID] == 'product_type' and ! in_array('parent_id', $headers)) {
619 // $headers[] = 'parent_id';
620 // }
621
622 break;
623 }
624
625 $field_type = XmlExportEngine::$exportOptions['cc_type'][$ID];
626 $addons = XmlExportEngine::get_addons();
627
628 if (in_array($field_type, $addons)) {
629 $ccOptions = XmlExportEngine::$exportOptions['cc_options'][$ID];
630 $fieldOptions = maybe_unserialize($ccOptions);
631
632 $headers = apply_filters(
633 "pmxe_{$field_type}_addon_get_headers",
634 $headers,
635 $fieldOptions,
636 XmlExportEngine::$exportOptions,
637 $ID,
638 $element_name
639 );
640 }
641 }
642
643 public static function _get_valid_header_name( $element_name )
644 {
645 $element_name_parts = explode("_", $element_name);
646
647 $elementIndex = array_pop($element_name_parts);
648
649 if (wp_all_export_isValidMd5($elementIndex)) {
650 $element_name_in_file = str_replace("_" . $elementIndex, "", $element_name);
651 }
652 else {
653 $element_name_in_file = $element_name;
654 }
655
656 $element_name_in_file = XmlExportEngine::sanitizeFieldName($element_name_in_file);
657
658 return $element_name_in_file;
659 }
660
661
662 // Add missing ACF headers
663 public static function merge_headers( $file, &$headers )
664 {
665
666 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- export plugin reads/writes its own files in uploads dir, WP_Filesystem not viable for streamed CSV/XML output
667 $in = fopen($file, 'r');
668
669 $clear_old_headers = fgetcsv($in, 0, XmlExportEngine::$exportOptions['delimiter'], '"', '\\');
670
671 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- export plugin reads/writes its own files in uploads dir, WP_Filesystem not viable for streamed CSV/XML output
672 fclose($in);
673
674 $old_headers = array();
675 $sanitized_headers = array();
676 $urldecoded_sanitized_headers = array();
677
678 foreach($headers as $header) {
679 $sanitizedHeaderValue = str_replace("'", "", str_replace('"', "", str_replace(chr(0xEF) . chr(0xBB) . chr(0xBF), "", $header)));
680 $sanitized_headers[] = $sanitizedHeaderValue;
681 $urldecoded_sanitized_headers[] = urldecode($sanitizedHeaderValue);
682
683 }
684 foreach ($clear_old_headers as $i => $header) {
685 $header = str_replace("'", "", str_replace('"', "", str_replace(chr(0xEF).chr(0xBB).chr(0xBF), "", $header)));
686
687 if ( ! in_array($header, $old_headers)) {
688 $old_headers[] = $header;
689 }
690 else {
691 $is_added = false;
692 $i = 0;
693 do {
694 $new_element_name = $header . '_' . md5($i);
695
696 if ( ! in_array($new_element_name, $old_headers) ) {
697 $old_headers[] = str_replace("'", "", str_replace('"', "", str_replace(chr(0xEF).chr(0xBB).chr(0xBF), "", $new_element_name)));
698 $is_added = true;
699 }
700
701 $i++;
702 }
703 while ( ! $is_added );
704 }
705 }
706
707 $is_update_headers = false;
708
709 foreach ($sanitized_headers as $header) {
710 if ( ! in_array(XmlExportEngine::sanitizeFieldName($header), $old_headers)) {
711 $is_update_headers = true;
712 break;
713 }
714 }
715
716 foreach ($old_headers as $old_header) {
717 if ( ! in_array(XmlExportEngine::sanitizeFieldName($old_header), $urldecoded_sanitized_headers)) {
718 $is_update_headers = true;
719 break;
720 }
721 }
722
723 if ($is_update_headers) {
724 $tmp_headers = $headers;
725 $headers = $old_headers;
726 foreach ($tmp_headers as $theader){
727 if (!in_array(XmlExportEngine::sanitizeFieldName($theader), $headers)) $headers[] = $theader;
728 }
729 $tmp_file = str_replace(basename($file), 'iteration_' . basename($file), $file);
730 copy($file, $tmp_file);
731 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- export plugin reads/writes its own files in uploads dir, WP_Filesystem not viable for streamed CSV/XML output
732 $in = fopen($tmp_file, 'r');
733 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- export plugin reads/writes its own files in uploads dir, WP_Filesystem not viable for streamed CSV/XML output
734 $out = fopen($file, 'w');
735 $headers = apply_filters('wp_all_export_csv_headers', $headers, XmlExportEngine::$exportID);
736
737 if ( XmlExportEngine::$exportOptions['include_bom'] ) {
738 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite -- export plugin reads/writes its own files in uploads dir, WP_Filesystem not viable for streamed CSV/XML output
739 fwrite($out, chr(0xEF).chr(0xBB).chr(0xBF));
740 self::getCsvWriter()->writeCsv($out, array_map(array('XmlCsvExport', '_get_valid_header_name'), $headers), XmlExportEngine::$exportOptions['delimiter']);
741 }
742 else {
743 self::getCsvWriter()->writeCsv($out, array_map(array('XmlCsvExport', '_get_valid_header_name'), $headers), XmlExportEngine::$exportOptions['delimiter']);
744 }
745
746 apply_filters('wp_all_export_after_csv_line', $out, XmlExportEngine::$exportID);
747
748 $exclude_old_headers = fgetcsv($in, 0, ',', '"', '\\');
749
750 if (is_resource($in)) {
751 while ( ! feof($in) ) {
752 $data = fgetcsv($in, 0, XmlExportEngine::$exportOptions['delimiter'], '"', '\\');
753 if ( empty($data) ) continue;
754
755 // Handle CSV parsing issues by ensuring proper column count
756 $data_values = array_values($data);
757 $data_count = count($data_values);
758 $headers_count = count($old_headers);
759
760 if ($data_count < $headers_count) {
761 // Add empty values for missing columns
762 $difference = $headers_count - $data_count;
763 for ($i = 0; $i < $difference; $i++) {
764 $data_values[] = "";
765 }
766 } elseif ($data_count > $headers_count) {
767 // Handle case where CSV parsing created too many columns due to unescaped delimiters
768 // Try to reconstruct the original data by joining excess columns
769 $excess_count = $data_count - $headers_count;
770 if ($excess_count > 0) {
771 // Take the expected number of columns minus 1, then join the rest
772 $fixed_data = array_slice($data_values, 0, $headers_count - 1);
773 $remaining_data = array_slice($data_values, $headers_count - 1);
774 $fixed_data[] = implode(XmlExportEngine::$exportOptions['delimiter'], $remaining_data);
775 $data_values = $fixed_data;
776 }
777 }
778
779 $data_assoc = array_combine($old_headers, $data_values);
780
781 $line = array();
782 foreach ($headers as $header) {
783 $value = ( isset($data_assoc[$header]) ) ? $data_assoc[$header] : '';
784 // Only sanitize when reconstructing from corrupted CSV data
785 $line[$header] = self::sanitizeCorruptedCsvData($value);
786 }
787 self::getCsvWriter()->writeCsv($out, $line, XmlExportEngine::$exportOptions['delimiter']);
788 apply_filters('wp_all_export_after_csv_line', $out, XmlExportEngine::$exportID);
789 }
790 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- export plugin reads/writes its own files in uploads dir, WP_Filesystem not viable for streamed CSV/XML output
791 fclose($in);
792 }
793 // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- export plugin reads/writes its own files in uploads dir, WP_Filesystem not viable for streamed CSV/XML output
794 fclose($out);
795 wp_delete_file($tmp_file);
796 }
797 }
798
799 private static function save_csv_to_file( $file_path, $is_cron, $exported_by_cron )
800 {
801 if ($is_cron) {
802 if ( ! $exported_by_cron ) {
803 // The BOM will help some programs like Microsoft Excel read your export file if it includes non-English characters.
804 if (XmlExportEngine::$exportOptions['include_bom']) {
805 file_put_contents($file_path, chr(0xEF).chr(0xBB).chr(0xBF).ob_get_clean());
806 }
807 else {
808 file_put_contents($file_path, ob_get_clean());
809 }
810 }
811 else {
812 file_put_contents($file_path, ob_get_clean(), FILE_APPEND);
813 }
814
815 return $file_path;
816
817 }
818 else
819 {
820 if ( empty(PMXE_Plugin::$session->file) ){
821
822 // generate export file name
823 $export_file = wp_all_export_generate_export_file( XmlExportEngine::$exportID );
824
825 // The BOM will help some programs like Microsoft Excel read your export file if it includes non-English characters.
826 if (XmlExportEngine::$exportOptions['include_bom']) {
827 file_put_contents($export_file, chr(0xEF).chr(0xBB).chr(0xBF).ob_get_clean());
828 }
829 else {
830 file_put_contents($export_file, ob_get_clean());
831 }
832
833 PMXE_Plugin::$session->set('file', $export_file);
834 PMXE_Plugin::$session->save_data();
835
836 }
837 else {
838 file_put_contents(PMXE_Plugin::$session->file, ob_get_clean(), FILE_APPEND);
839 }
840
841 return true;
842 }
843 }
844 // [ \CSV Export Helpers ]
845
846 public static function auto_generate_export_fields($post, $errors = false)
847 {
848 $errors or $errors = new WP_Error();
849
850 remove_all_filters("wp_all_export_init_fields", 10);
851 remove_all_filters("wp_all_export_default_fields", 10);
852 remove_all_filters("wp_all_export_other_fields", 10);
853 remove_all_filters("wp_all_export_available_sections", 10);
854 remove_all_filters("wp_all_export_available_data", 10);
855
856 $engine = new XmlExportEngine($post, $errors);
857 $engine->init_additional_data();
858
859 $auto_generate = array(
860 'ids' => array(),
861 'cc_label' => array(),
862 'cc_php' => array(),
863 'cc_code' => array(),
864 'cc_sql' => array(),
865 'cc_type' => array(),
866 'cc_options' => array(),
867 'cc_value' => array(),
868 'cc_name' => array()
869 );
870
871 $available_data = $engine->init_available_data();
872
873 $available_sections = apply_filters("wp_all_export_available_sections", $engine->get('available_sections'));
874
875 foreach ($available_sections as $slug => $section) {
876 if (!empty($section['content']) and !empty($available_data[$section['content']])) {
877 foreach ($available_data[$section['content']] as $field) {
878 if(is_string($post['cpt'])) {
879 $post['cpt'] = [$post['cpt']];
880 }
881 if (is_array($field) and (isset($field['auto']) or (!in_array('product', $post['cpt']) || !\class_exists('WooCommerce')))) {
882 $auto_generate['ids'][] = 1;
883 $auto_generate['cc_label'][] = is_array($field) ? $field['label'] : $field;
884 $auto_generate['cc_php'][] = 0;
885 $auto_generate['cc_code'][] = '';
886 $auto_generate['cc_sql'][] = '';
887 $auto_generate['cc_settings'][] = '';
888 $auto_generate['cc_type'][] = is_array($field) ? $field['type'] : $slug;
889 $auto_generate['cc_options'][] = '';
890 $auto_generate['cc_value'][] = is_array($field) ? $field['label'] : $field;
891 $auto_generate['cc_name'][] = is_array($field) ? $field['name'] : $field;
892 }
893 }
894 }
895 if (!empty($section['additional'])) {
896 foreach ($section['additional'] as $sub_slug => $sub_section) {
897 foreach ($sub_section['meta'] as $field) {
898 $field_options = (in_array($sub_slug, array('images', 'attachments'))) ? esc_attr('{"is_export_featured":true,"is_export_attached":true,"image_separator":"|"}') : '0';
899 $field_name = '';
900 switch ($sub_slug) {
901 case 'images':
902 $field_name = 'Image ' . $field['name'];
903 break;
904 case 'attachments':
905 $field_name = 'Attachment ' . $field['name'];
906 break;
907 default:
908 $field_name = $field['name'];
909 break;
910 }
911
912 if (is_array($field) and isset($field['auto'])) {
913 $auto_generate['ids'][] = 1;
914 $auto_generate['cc_label'][] = is_array($field) ? $field['label'] : $field;
915 $auto_generate['cc_php'][] = 0;
916 $auto_generate['cc_code'][] = '';
917 $auto_generate['cc_sql'][] = '';
918 $auto_generate['cc_settings'][] = '';
919 $auto_generate['cc_type'][] = is_array($field) ? $field['type'] : $sub_slug;
920 $auto_generate['cc_options'][] = $field_options;
921 $auto_generate['cc_value'][] = is_array($field) ? $field['label'] : $field;
922 $auto_generate['cc_name'][] = $field_name;
923 }
924 }
925 }
926 }
927 }
928
929 if (
930 (
931 XmlExportEngine::get_addons_service()->isWooCommerceAddonActive() ||
932 XmlExportEngine::get_addons_service()->isWooCommerceOrderAddonActive()
933 )
934 && XmlExportWooCommerceOrder::$is_active) {
935
936 foreach (XmlExportWooCommerceOrder::$order_sections as $slug => $section) {
937 if (!empty($section['meta'])) {
938 foreach ($section['meta'] as $cur_meta_key => $field) {
939 $auto_generate['ids'][] = 1;
940 $auto_generate['cc_label'][] = is_array($field) ? $field['label'] : $cur_meta_key;
941 $auto_generate['cc_php'][] = 0;
942 $auto_generate['cc_code'][] = '';
943 $auto_generate['cc_sql'][] = '';
944 $auto_generate['cc_settings'][] = '';
945 $auto_generate['cc_type'][] = is_array($field) ? $field['type'] : 'woo_order';
946 $auto_generate['cc_options'][] = is_array($field) ? $field['options'] : $slug;
947 $auto_generate['cc_value'][] = is_array($field) ? $field['label'] : $cur_meta_key;
948 $auto_generate['cc_name'][] = is_array($field) ? $field['name'] : $field;
949 }
950 }
951 }
952 }
953
954 if (XmlExportEngine::get_addons_service()->isAcfAddonActive() && !XmlExportEngine::$is_comment_export) XmlExportEngine::$acf_export->auto_generate_export_fields($auto_generate);
955
956 if(XmlExportEngine::$is_custom_addon_export) {
957
958 $auto_generate = [];
959
960 $addon = GF_Export_Add_On::get_instance();
961 $addon->run();
962 $available_data = $addon->add_on->init_available_data([]);
963
964 foreach($available_data as $section) {
965 foreach($section as $field) {
966 if($field['auto']) {
967 $auto_generate['ids'][] = 1;
968 $auto_generate['cc_label'][] = $field['label'];
969 $auto_generate['cc_php'][] = 0;
970 $auto_generate['cc_code'][] = '';
971 $auto_generate['cc_sql'][] = '';
972 $auto_generate['cc_settings'][] = '';
973 $auto_generate['cc_type'][] = $field['type'];
974 $auto_generate['cc_value'][] = $field['label'];
975 $auto_generate['cc_name'][] = $field['name'];
976 }
977 }
978 }
979
980 }
981
982 return $auto_generate;
983 }
984
985
986 /**
987 * @param $xmlWriter
988 * @param $key
989 * @param $value
990 */
991 private static function addElement($xmlWriter, $key, $value)
992 {
993 $xmlWriter->startElement(preg_replace('/[^a-z0-9_-]/i', '', $key));
994 $xmlWriter->writeData($value, preg_replace('/[^a-z0-9_-]/i', '', $key));
995 $xmlWriter->closeElement();
996 }
997
998 /**
999 * @return \Wpae\Csv\CsvWriter
1000 */
1001 private static function getCsvWriter()
1002 {
1003 if(is_null(self::$csvWriter)) {
1004
1005 $csvStrategy = apply_filters('wp_all_export_csv_strategy', \Wpae\Csv\CsvWriter::CSV_STRATEGY_DEFAULT);
1006 $useRcfCompliantLineEndings = apply_filters('wp_all_export_use_csv_compliant_line_endings', false);
1007
1008 if($useRcfCompliantLineEndings) {
1009 \Wpae\Csv\CsvRfcUtils::setDefaultWriteEol(\Wpae\Csv\CsvRfcUtils::EOL_WRITE_RFC);
1010 }
1011
1012 self::$csvWriter = new \Wpae\Csv\CsvWriter($csvStrategy);
1013 }
1014
1015 return self::$csvWriter;
1016 }
1017
1018 private static function isNotProductExport($cpt) {
1019
1020 if(is_array($cpt)) {
1021 return !in_array('product', $cpt);
1022 } else {
1023 return 'product' !== $cpt;
1024 }
1025 }
1026
1027 /**
1028 * Sanitize corrupted CSV data during merge operations only
1029 * This is specifically for handling data that was already corrupted in existing CSV files
1030 *
1031 * @param mixed $value The value to sanitize
1032 * @return mixed The sanitized value
1033 */
1034 private static function sanitizeCorruptedCsvData($value) {
1035 // Only process strings
1036 if (!is_string($value)) {
1037 return $value;
1038 }
1039
1040 // Don't modify empty values
1041 if (empty($value)) {
1042 return $value;
1043 }
1044
1045 // Allow filtering to disable or customize sanitization
1046 $sanitize = apply_filters('wp_all_export_sanitize_csv_data', true, $value);
1047 if (!$sanitize) {
1048 return $value;
1049 }
1050
1051 // Skip sanitization for serialized data or JSON to avoid breaking structured data
1052 if (is_serialized($value) || self::isJson($value)) {
1053 return $value;
1054 }
1055
1056 // Skip sanitization for ACF field data patterns to avoid breaking addon compatibility
1057 if (self::looksLikeAcfData($value)) {
1058 return $value;
1059 }
1060
1061 // Only apply minimal sanitization to fix the specific issues that caused array_combine() errors:
1062 // 1. Normalize line endings that break CSV row parsing
1063 // 2. Don't modify the content otherwise - let the CSV writer handle proper escaping
1064
1065 // Convert Windows/Mac line endings to Unix, but preserve the newlines
1066 $value = str_replace(["\r\n", "\r"], "\n", $value);
1067
1068 // Allow custom sanitization
1069 return apply_filters('wp_all_export_csv_sanitized_value', $value);
1070 }
1071
1072 /**
1073 * Check if a string is valid JSON
1074 *
1075 * @param string $string
1076 * @return bool
1077 */
1078 private static function isJson($string) {
1079 if (!is_string($string)) {
1080 return false;
1081 }
1082 json_decode($string);
1083 return (json_last_error() == JSON_ERROR_NONE);
1084 }
1085
1086 /**
1087 * Check if a string looks like ACF field data that shouldn't be sanitized
1088 *
1089 * @param string $value
1090 * @return bool
1091 */
1092 private static function looksLikeAcfData($value) {
1093 if (!is_string($value) || strlen($value) < 10) {
1094 return false;
1095 }
1096
1097 // Check for common ACF field patterns
1098 $acf_patterns = [
1099 'field_', // ACF field keys
1100 'acf-field', // ACF field references
1101 'a:', // Serialized array start
1102 's:', // Serialized string start
1103 'O:', // Serialized object start
1104 ];
1105
1106 foreach ($acf_patterns as $pattern) {
1107 if (strpos($value, $pattern) === 0) {
1108 return true;
1109 }
1110 }
1111
1112 return false;
1113 }
1114 }
1115