PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / trunk
Secure Custom Fields vtrunk
6.9.1 6.9.0 6.8.9 6.8.7 6.8.8 6.8.6 6.8.4 6.8.5 trunk 6.4.0-beta1 6.4.0-beta2 6.4.1 6.4.1-beta3 6.4.1-beta4 6.4.1-beta5 6.4.1-beta6 6.4.1-beta7 6.4.2 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.6.0 6.7.0 6.7.1 6.8.0 6.8.1 6.8.2 6.8.3
secure-custom-fields / includes / admin / tools / class-acf-admin-tool-export.php
secure-custom-fields / includes / admin / tools Last commit date
class-acf-admin-tool-export.php 1 year ago class-acf-admin-tool-import.php 7 months ago class-acf-admin-tool.php 1 year ago index.php 1 year ago
class-acf-admin-tool-export.php
531 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'ACF_Admin_Tool_Export' ) ) :
8
9 class ACF_Admin_Tool_Export extends ACF_Admin_Tool {
10
11
12 /** @var string View context */
13 var $view = '';
14
15
16 /** @var array Export data */
17 var $json = '';
18
19
20 /**
21 * initialize
22 *
23 * This function will initialize the admin tool
24 *
25 * @date 10/10/17
26 * @since ACF 5.6.3
27 *
28 * @param n/a
29 * @return n/a
30 */
31 function initialize() {
32
33 // vars
34 $this->name = 'export';
35 $this->title = __( 'Export Field Groups', 'secure-custom-fields' );
36
37 // active
38 if ( $this->is_active() ) {
39 $this->title .= ' - ' . __( 'Generate PHP', 'secure-custom-fields' );
40 }
41 }
42
43
44 /**
45 * submit
46 *
47 * This function will run when the tool's form has been submit
48 *
49 * @date 10/10/17
50 * @since ACF 5.6.3
51 *
52 * @param n/a
53 * @return n/a
54 */
55 function submit() {
56
57 // vars
58 $action = acf_maybe_get_POST( 'action' );
59
60 // download
61 if ( $action === 'download' ) {
62 $this->submit_download();
63
64 // generate
65 } elseif ( $action === 'generate' ) {
66 $this->submit_generate();
67 }
68 }
69
70
71 /**
72 * submit_download
73 *
74 * description
75 *
76 * @date 17/10/17
77 * @since ACF 5.6.3
78 *
79 * @param n/a
80 * @return n/a
81 */
82 function submit_download() {
83
84 // vars
85 $json = $this->get_selected();
86
87 // validate
88 if ( $json === false ) {
89 return acf_add_admin_notice( __( 'No field groups selected', 'secure-custom-fields' ), 'warning' );
90 }
91
92 // headers
93 $file_name = 'scf-export-' . date( 'Y-m-d' ) . '.json';
94 header( 'Content-Description: File Transfer' );
95 header( "Content-Disposition: attachment; filename={$file_name}" );
96 header( 'Content-Type: application/json; charset=utf-8' );
97
98 // return
99 echo acf_json_encode( $json ) . "\r\n"; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped as JSON export.
100 die;
101 }
102
103
104 /**
105 * submit_generate
106 *
107 * description
108 *
109 * @date 17/10/17
110 * @since ACF 5.6.3
111 *
112 * @param n/a
113 * @return n/a
114 */
115 function submit_generate() {
116
117 // vars
118 $keys = $this->get_selected_keys();
119
120 // validate
121 if ( ! $keys ) {
122 return acf_add_admin_notice( __( 'No field groups selected', 'secure-custom-fields' ), 'warning' );
123 }
124
125 // url
126 $url = add_query_arg( 'keys', implode( '+', $keys ), $this->get_url() );
127
128 // redirect
129 wp_safe_redirect( $url );
130 exit;
131 }
132
133
134 /**
135 * load
136 *
137 * description
138 *
139 * @date 21/10/17
140 * @since ACF 5.6.3
141 *
142 * @param n/a
143 * @return n/a
144 */
145 function load() {
146
147 // active
148 if ( $this->is_active() ) {
149
150 // get selected keys
151 $selected = $this->get_selected_keys();
152
153 // add notice
154 if ( $selected ) {
155 $count = count( $selected );
156 /* translators: %s: number of items exported */
157 $text = sprintf( _n( 'Exported %s item.', 'Exported %s items.', $count, 'secure-custom-fields' ), $count );
158 acf_add_admin_notice( $text, 'success' );
159 }
160 }
161 }
162
163
164 /**
165 * html
166 *
167 * This function will output the metabox HTML
168 *
169 * @date 10/10/17
170 * @since ACF 5.6.3
171 *
172 * @param n/a
173 * @return n/a
174 */
175 function html() {
176
177 // single (generate PHP)
178 if ( $this->is_active() ) {
179 $this->html_single();
180
181 // archive
182 } else {
183 $this->html_archive();
184 }
185 }
186
187
188 /**
189 * Renders the checkboxes to select items to export.
190 *
191 * @since ACF 5.6.3
192 */
193 public function html_field_selection() {
194 // Ensure `l10n_var_export` is always false at the point we're outputting the options.
195 acf_update_setting( 'l10n_var_export', false );
196 // Reset the field-groups store which may have been corrupted by export.
197 $store = acf_get_store( 'field-groups' );
198 if ( $store ) {
199 $store->reset();
200 }
201
202 $choices = array();
203 $selected = $this->get_selected_keys();
204 $field_groups = array_filter(
205 acf_get_internal_post_type_posts( 'acf-field-group' ),
206 'acf_internal_post_object_contains_valid_key'
207 );
208
209 if ( $field_groups ) {
210 foreach ( $field_groups as $field_group ) {
211 $choices[ $field_group['key'] ] = esc_html( $field_group['title'] );
212 }
213 }
214
215 acf_render_field_wrap(
216 array(
217 'label' => __( 'Select Field Groups', 'secure-custom-fields' ),
218 'type' => 'checkbox',
219 'name' => 'keys',
220 'prefix' => false,
221 'value' => $selected,
222 'toggle' => true,
223 'choices' => $choices,
224 )
225 );
226
227 $choices = array();
228 $selected = $this->get_selected_keys();
229 $post_types = array_filter(
230 acf_get_internal_post_type_posts( 'acf-post-type' ),
231 'acf_internal_post_object_contains_valid_key'
232 );
233
234 if ( $post_types ) {
235 foreach ( $post_types as $post_type ) {
236 $choices[ $post_type['key'] ] = esc_html( $post_type['title'] );
237 }
238
239 acf_render_field_wrap(
240 array(
241 'label' => __( 'Select Post Types', 'secure-custom-fields' ),
242 'type' => 'checkbox',
243 'name' => 'post_type_keys',
244 'prefix' => false,
245 'value' => $selected,
246 'toggle' => true,
247 'choices' => $choices,
248 )
249 );
250 }
251
252 $choices = array();
253 $selected = $this->get_selected_keys();
254 $taxonomies = array_filter(
255 acf_get_internal_post_type_posts( 'acf-taxonomy' ),
256 'acf_internal_post_object_contains_valid_key'
257 );
258
259 if ( $taxonomies ) {
260 foreach ( $taxonomies as $taxonomy ) {
261 $choices[ $taxonomy['key'] ] = esc_html( $taxonomy['title'] );
262 }
263
264 acf_render_field_wrap(
265 array(
266 'label' => __( 'Select Taxonomies', 'secure-custom-fields' ),
267 'type' => 'checkbox',
268 'name' => 'taxonomy_keys',
269 'prefix' => false,
270 'value' => $selected,
271 'toggle' => true,
272 'choices' => $choices,
273 )
274 );
275 }
276
277 $choices = array();
278 $selected = $this->get_selected_keys();
279 $options_pages = array_filter(
280 acf_get_internal_post_type_posts( 'acf-ui-options-page' ),
281 'acf_internal_post_object_contains_valid_key'
282 );
283
284 if ( $options_pages ) {
285 foreach ( $options_pages as $options_page ) {
286 $choices[ $options_page['key'] ] = esc_html( $options_page['title'] );
287 }
288
289 acf_render_field_wrap(
290 array(
291 'label' => __( 'Select Options Pages', 'secure-custom-fields' ),
292 'type' => 'checkbox',
293 'name' => 'ui_options_page_keys',
294 'prefix' => false,
295 'value' => $selected,
296 'toggle' => true,
297 'choices' => $choices,
298 )
299 );
300 }
301 }
302
303 /**
304 * Renders the side panel for selecting ACF items to export via PHP.
305 *
306 * @since ACF 5.6.3
307 */
308 public function html_panel_selection() {
309 ?>
310 <div class="acf-panel acf-panel-selection">
311 <?php $this->html_field_selection(); ?>
312 </div>
313 <?php
314 }
315
316
317 /**
318 * html_archive
319 *
320 * description
321 *
322 * @date 20/10/17
323 * @since ACF 5.6.3
324 *
325 * @param n/a
326 * @return n/a
327 */
328 function html_archive() {
329
330 ?>
331 <div class="acf-postbox-header">
332 <h2 class="acf-postbox-title"><?php esc_html_e( 'Export', 'secure-custom-fields' ); ?></h2>
333 <div class="acf-tip"><i tabindex="0" class="acf-icon acf-icon-help acf-js-tooltip" title="<?php esc_attr_e( 'Select the items you would like to export and then select your export method. Export As JSON to export to a .json file which you can then import to another SCF installation. Generate PHP to export to PHP code which you can place in your theme.', 'secure-custom-fields' ); ?>">?</i></div>
334 </div>
335 <div class="acf-postbox-inner">
336 <div class="acf-fields">
337 <?php $this->html_field_selection(); ?>
338 </div>
339 <p class="acf-submit acf-actions-strip">
340 <button type="submit" name="action" class="acf-btn acf-button-primary" value="download"><?php esc_html_e( 'Export As JSON', 'secure-custom-fields' ); ?></button>
341 <button type="submit" name="action" class="acf-btn acf-btn-secondary" value="generate"><?php esc_html_e( 'Generate PHP', 'secure-custom-fields' ); ?></button>
342 </p>
343 </div>
344 <?php
345 }
346
347 /**
348 * Renders the PHP export screen.
349 *
350 * @since ACF 5.6.3
351 */
352 public function html_single() {
353 ?>
354 <div class="acf-postbox-header">
355 <h2 class="acf-postbox-title"><?php esc_html_e( 'Export - Generate PHP', 'secure-custom-fields' ); ?></h2>
356 <i tabindex="0" class="acf-icon acf-icon-help acf-js-tooltip" title="<?php esc_attr_e( "The following code can be used to register a local version of the selected items. Storing field groups, post types, or taxonomies locally can provide many benefits such as faster load times, version control & dynamic fields/settings. Simply copy and paste the following code to your theme's functions.php file or include it within an external file, then deactivate or delete the items from the ACF admin.", 'secure-custom-fields' ); ?>">?</i>
357 </div>
358 <div class="acf-postbox-columns">
359 <div class="acf-postbox-main">
360 <?php $this->html_generate(); ?>
361 </div>
362 <div class="acf-postbox-side">
363 <?php $this->html_panel_selection(); ?>
364 <p class="acf-submit">
365 <button type="submit" name="action" class="acf-btn" value="generate"><?php esc_html_e( 'Generate PHP', 'secure-custom-fields' ); ?></button>
366 </p>
367 </div>
368 </div>
369 <?php
370 }
371
372 /**
373 * Generates the HTML for the PHP export functionality.
374 *
375 * @since ACF 5.6.3
376 */
377 public function html_generate() {
378 // Prevent default translation and fake __() within string.
379 acf_update_setting( 'l10n_var_export', true );
380
381 $json = $this->get_selected();
382 $to_export = array();
383
384 // Sort by ACF post type first so we can wrap them in related functions.
385 foreach ( $json as $post ) {
386 $post_type = acf_determine_internal_post_type( $post['key'] );
387
388 if ( $post_type ) {
389 $to_export[ $post_type ][] = $post;
390 }
391 }
392
393 echo '<textarea id="acf-export-textarea" readonly="readonly">';
394
395 foreach ( $to_export as $post_type => $posts ) {
396 if ( 'acf-field-group' === $post_type ) {
397 echo "add_action( 'acf/include_fields', function() {\r\n";
398 echo "\tif ( ! function_exists( 'acf_add_local_field_group' ) ) {\r\n\t\treturn;\r\n\t}\r\n\r\n";
399 } elseif ( 'acf-post-type' === $post_type || 'acf-taxonomy' === $post_type ) {
400 echo "add_action( 'init', function() {\r\n";
401 } elseif ( 'acf-ui-options-page' === $post_type ) {
402 echo "add_action( 'acf/init', function() {\r\n";
403 }
404
405 $count = 0;
406 foreach ( $posts as $post ) {
407 if ( $count !== 0 ) {
408 echo "\r\n";
409 }
410
411 echo "\t" . acf_export_internal_post_type_as_php( $post, $post_type ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- esc_textarea() used earlier.
412 ++$count;
413 }
414
415 if ( in_array( $post_type, array( 'acf-post-type', 'acf-taxonomy', 'acf-field-group', 'acf-ui-options-page' ), true ) ) {
416 echo "} );\r\n\r\n";
417 }
418
419 if ( 'acf-post-type' === $post_type ) {
420 echo acf_export_enter_title_here( $posts ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- esc_textarea() used earlier.
421 }
422 }
423
424 echo '</textarea>';
425 ?>
426 <p class="acf-submit">
427 <a class="button" id="acf-export-copy"><?php esc_html_e( 'Copy to clipboard', 'secure-custom-fields' ); ?></a>
428 </p>
429 <script type="text/javascript">
430 (function($) {
431 const $a = $('#acf-export-copy');
432 const $textarea = $('#acf-export-textarea');
433
434 // Remove $a if 'copy' is not supported.
435 if (!document.queryCommandSupported('copy')) {
436 return $a.remove();
437 }
438
439 $a.on('click', function(e) {
440 e.preventDefault();
441
442 $textarea.get(0).select();
443
444 try {
445 var copy = document.execCommand('copy');
446 if (!copy) {
447 return;
448 }
449
450 acf.newTooltip({
451 text: "<?php esc_html_e( 'Copied', 'secure-custom-fields' ); ?>",
452 timeout: 250,
453 target: $(this),
454 });
455 } catch (err) {
456 // Do nothing.
457 }
458 });
459 })(jQuery);
460 </script>
461 <?php
462 }
463
464 /**
465 * Return an array of keys that have been selected in the export tool.
466 *
467 * @since ACF 5.6.3
468 *
469 * @return array|boolean
470 */
471 public function get_selected_keys() {
472 $key_names = array( 'keys', 'taxonomy_keys', 'post_type_keys', 'ui_options_page_keys' );
473 $all_keys = array();
474
475 foreach ( $key_names as $key_name ) {
476 if ( $keys = acf_maybe_get_POST( $key_name ) ) {
477 $all_keys = array_merge( $all_keys, (array) $keys );
478 } elseif ( $keys = acf_maybe_get_GET( $key_name ) ) {
479 $keys = str_replace( ' ', '+', $keys );
480 $keys = explode( '+', $keys );
481 $all_keys = array_merge( $all_keys, (array) $keys );
482 }
483 }
484
485 if ( ! empty( $all_keys ) ) {
486 return $all_keys;
487 }
488
489 return false;
490 }
491
492 /**
493 * Returns the JSON data for given $_POST args.
494 *
495 * @since ACF 5.6.3
496 *
497 * @return array|boolean
498 */
499 public function get_selected() {
500 $selected = $this->get_selected_keys();
501 $json = array();
502
503 if ( ! $selected ) {
504 return false;
505 }
506
507 foreach ( $selected as $key ) {
508 $post_type = acf_determine_internal_post_type( $key );
509 $post = acf_get_internal_post_type( $key, $post_type );
510
511 if ( empty( $post ) ) {
512 continue;
513 }
514
515 if ( 'acf-field-group' === $post_type ) {
516 $post['fields'] = acf_get_fields( $post );
517 }
518
519 $post = acf_prepare_internal_post_type_for_export( $post, $post_type );
520 $json[] = $post;
521 }
522
523 return $json;
524 }
525 }
526
527 // initialize
528 acf_register_admin_tool( 'ACF_Admin_Tool_Export' );
529 endif; // class_exists check
530
531 ?>