Skip to content

Instantly share code, notes, and snippets.

@ollietreend
Last active April 22, 2024 11:12
Show Gist options
  • Star 95 You must be signed in to star a gist
  • Fork 21 You must be signed in to fork a gist
  • Save ollietreend/df32c5cbe2914f6fc407332bf6cbfca5 to your computer and use it in GitHub Desktop.
Save ollietreend/df32c5cbe2914f6fc407332bf6cbfca5 to your computer and use it in GitHub Desktop.
Convert Advanced Custom Fields Pro configuration from PHP to JSON.
<?php
/**
* Plugin Name: Convert ACF PHP to JSON
* Description: Convert Advanced Custom Fields Pro configuration from PHP to JSON.
*/
namespace ConvertAcfPhpToJson;
/**
* Add submenu item under 'Custom Fields'
*/
function admin_menu() {
add_submenu_page('edit.php?post_type=acf-field-group', 'Convert PHP fields to JSON', 'PHP to JSON', 'manage_options', 'acf-php-to-json', __NAMESPACE__ . '\\admin_page');
}
add_action('admin_menu', __NAMESPACE__ . '\\admin_menu', 20);
/**
* Output the admin page
*/
function admin_page() {
?>
<div class="wrap">
<h1>Convert PHP fields to JSON</h1>
<?php
if (!isset($_GET['continue']) || $_GET['continue'] !== 'true') {
admin_page_intro();
}
else {
admin_page_convert();
}
?>
</div>
<?php
}
/**
* Output the introductory page
*/
function admin_page_intro() {
$groups = get_groups_to_convert();
if (empty($groups)) {
echo '<p>No PHP field group configuration found. Nothing to convert.</p>';
return;
}
else {
echo sprintf('<p>%d field groups will be converted from PHP to JSON configuration.</p>', count($groups));
echo '<a href="edit.php?post_type=acf-field-group&page=acf-php-to-json&continue=true" class="button button-primary">Convert Field Groups</a>';
}
}
/**
* Convert the field groups and output the conversion page
*/
function admin_page_convert() {
$groups = get_groups_to_convert();
echo sprintf('<p>Converting %d field groups from PHP to JSON configuration...</p>', count($groups));
echo '<ol>';
foreach ($groups as $group) {
if (convert_group($group)) {
echo sprintf('<li>Converted: <strong>%s</strong> (%s)</li>', $group['title'], $group['key']);
}
else {
echo sprintf('<li><strong>Failed to convert: %s</strong> (%s)</li>', $group['title'], $group['key']);
}
}
echo '</ol>';
echo '<p>Done. Now remove the PHP field group configuration.</p>';
}
/**
* Get the PHP field groups which will be converted.
*
* @return array
*/
function get_groups_to_convert() {
$groups = acf_get_local_field_groups();
if (!$groups) return [];
return array_filter($groups, function($group) {
return $group['local'] == 'php';
});
}
/**
* Convert a field group to JSON
*
* @param array $group
* @return bool
*/
function convert_group($group) {
$group['fields'] = acf_get_fields($group['key']);
return acf_write_json_field_group($group);
}
@ollietreend
Copy link
Author

Usage

  1. Put this file in your plugins directory and activate it in the WordPress admin.

  2. Convert your PHP configuration to JSON by going to 'PHP to JSON' from the 'Custom Fields' admin menu.
    PHP to JSON menu item

  3. After conversion, be sure to remove the PHP configuration so that ACF reads the JSON instead.

Failed to convert?

  • Check that the directory acf-json exists in your theme.
  • The web server must have permission to write to this directory.

@tinhochu
Copy link

tinhochu commented Aug 7, 2018

Amazing man! thanks!

@moritzbappert
Copy link

moritzbappert commented Apr 24, 2019

@ollietreend Thanks for this great little plugin!

I had one problem though: sub fields were missing in my converted JSON files.

If you change
$group['fields'] = acf_get_local_fields($group['key']); to
$group['fields'] = acf_get_fields($group['key']);,
everything is converting nicely.

@lincolnlemos
Copy link

Awesome @moritzbappert! You saved me :)

@levnhub
Copy link

levnhub commented Feb 20, 2020

@jeffleeder
Copy link

Amazing thank you

@artneo7
Copy link

artneo7 commented Sep 9, 2020

Awesome! Thank you!

@apsolut
Copy link

apsolut commented Dec 18, 2020

Awesome!

@paramir
Copy link

paramir commented Oct 10, 2021

Works perfectly! Create the acf-json folder in your theme and see @moritzbappert comment if you have sub fields!

@ollietreend
Copy link
Author

ollietreend commented Nov 17, 2021

Thanks for your feedback @moritzbappert (and sorry this is so long overdue!)

Whilst I've not worked with WordPress for a few years now, it looks like this gist is still useful to others. So I've updated it to include your improvements so that sub-fields aren't missed out.

@archondigital
Copy link

It still works. I just used it today to edit an old theme I inherited that had roughly 70 blocks and field groups. Great work!

@krishaamer
Copy link

Thank you! Very useful!

@relaxdd
Copy link

relaxdd commented Mar 29, 2022

Does not work, installed the plugin, created the acf-json folder and... nothing, there are no fields, the folder is also empty

@relaxdd
Copy link

relaxdd commented Mar 29, 2022

that's it, I caught up, I had to go to the local acf fields after deleting php and synchronize them, so supplement your instructions

@bengillin
Copy link

Thanks for making this. You just saved me a lot of time. 😄

@relaxdd
Copy link

relaxdd commented Apr 3, 2022

Спасибо, что сделали это. Ты просто сэкономил мне много времени. 😄

yes, no problem, actually for this I wrote a comment

@bigheadzach
Copy link

bigheadzach commented Apr 5, 2022

This seemed to work but it looks like it took clone fields and compressed them somehow - the exported PHP is different and results in a structure that causes all sorts of problems.
Before import:

			'label' => 'Accessibility',
			'name' => 'accessability',
			'type' => 'clone',
			'instructions' => '',
			'required' => 0,
			'conditional_logic' => 0,
			'wrapper' => array(
				'width' => '',
				'class' => '',
				'id' => '',
			),
			'clone' => array(
				0 => 'field_5b058cc491a9c',
			),
			'display' => 'seamless',
			'layout' => 'block',
			'prefix_label' => 1,
			'prefix_name' => 1,

After import and re-export:

			'label' => 'Accessibility Accordion Items',
			'name' => 'accessability_items',
			'type' => 'repeater',
			'instructions' => '',
			'required' => 1,
			'conditional_logic' => 0,
			'wrapper' => array(
				'width' => '',
				'class' => '',
				'id' => '',
			),
			'collapsed' => 'field_5b058cd191a9d',
			'min' => 1,
			'max' => 0,
			'layout' => 'block',
			'button_label' => 'Add Item',
			'_clone' => 'field_5df01d8a5312e',
			'__key' => 'field_5b058cc491a9c',
			'__name' => 'items',
			'__label' => 'Accordion Items',
			'sub_fields' => array(
			),

Noting that the original PHP was written awhile back and possibly a few minor versions ago, so it's possible that the format has changed in the meantime - however the expectation is that the field machine names (by which I'm actually pulling the field values) shouldn't change, but they are and that breaks a lot of stuff. Anyone else having similar issues?

NOTE: Getting this error for each group that is imported:

Undefined index: ID in /wp-content/plugins/advanced-custom-fields-pro/includes/local-json.php on line 215

This just seems to be a check-for-existing-fieldgroup-post that isn't properly null-coalesced, so not crucial to the issue above.

@ollietreend
Copy link
Author

Hi @bigheadzach

I haven't used WordPress for several years now, so am not best placed to help figure out why that's happened in your case. However, I wonder if it could be related to the issue AdvancedCustomFields/acf#266.

Within this plugin, the conversion from PHP to JSON happens in the convert_group function:

function convert_group($group) {
    $group['fields'] = acf_get_fields($group['key']);
    return acf_write_json_field_group($group);
}

The functions acf_get_fields and acf_write_json_field_group are provided by ACF itself. This plugin essentially just acts as the glue between those two functions – but it doesn't perform any conversion logic of its own, as that's all handled by those ACF functions.

I hope that helps!

@anybodesign
Copy link

Thanks a lot!!

@joviczarko
Copy link

@ollietreend Thank you for this!

@kulterryan
Copy link

I'm getting failed to convert error. I've check acf json and file permission already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment