Skip to content

Commit

Permalink
v1.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
misaki-web committed Jul 15, 2024
1 parent 72d9d7d commit 3e95e90
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 47 deletions.
31 changes: 22 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ ACF JSON Field is a Wordpress plugin adding a new ACF field to edit, save and ou

- Extract the archive and copy the folder (`acf-json-field`) to the Wordpress plugins folder (`/wp-content/plugins/`).

- Go to the Wordpress plugins manager on your website (`/wp-admin/plugins.php`) and enable the plugin **ACF JSON Field**. Note that you can enable auto-updates.
- Go to the Wordpress plugins manager on your website (`https://.../wp-admin/plugins.php`) and enable the plugin **ACF JSON Field**. Note that you can enable auto-updates.

## Usage

Go to the ACF administration page (`/wp-admin/edit.php?post_type=acf-field-group`), add a new field group and choose the field **JSON**. Change the field settings as needed.
Go to the ACF administration page (`https://.../wp-admin/edit.php?post_type=acf-field-group`), add a new field group and choose the field **JSON**. Change the field settings as needed.

![JSON Field in the list of ACF fields](/assets/screenshots/json-field.png)
![JSON Field in the list of ACF fields](assets/screenshots/json-field.png)

When editing a page containing a JSON field, an editor will allow the user to edit the JSON data:

![JSON editor](assets/screenshots/editor.png)

### Utilities and shortcode

The plugin provides a utility method to retrieve and format JSON data from a specified ACF field, as well as a shortcode to display this data on the front end.
The plugin provides utility methods to retrieve, format, and set JSON data from a specified ACF field, as well as a shortcode to display this data on the front end.

The `get_json_field` method can be called as follows:

Expand All @@ -31,14 +31,11 @@ use \AcfJsonField\JsonUtils;

// Retrieve the JSON data as a PHP type (array, boolean, etc.) for the current post
$json_data = JsonUtils::get_json_field('field_name_or_key');
$json_data = JsonUtils::get_json_field('field_name_or_key', null);
$json_data = JsonUtils::get_json_field('field_name_or_key', 'null');
$json_data = JsonUtils::get_json_field('field_name_or_key', false);
$json_data = JsonUtils::get_json_field('field_name_or_key', 'false');
$json_data = JsonUtils::get_json_field('field_name_or_key', null);

// For a specific post ID
$json_data = JsonUtils::get_json_field('field_name_or_key', 125);
$json_data = JsonUtils::get_json_field('field_name_or_key', '125');

// For the current user
$json_data = JsonUtils::get_json_field('field_name_or_key', 'user');
Expand All @@ -56,7 +53,23 @@ Or as follows:
$json_data = \AcfJsonField\JsonUtils::get_json_field('field_name_or_key');
```

To display the field value on the front end, the shortcode `acf_json_field` can be used. This shortcode internally calls the `get_json_field` method with the `html` format. By default, it'll look at the current post where the shortcode is added:
To set the JSON data for a specific ACF field, use the `set_json_field` method:

```php
$php_data = ['lorem1' => 'ipsum2', 'lorem2' => 'ipsum2'];
$success = JsonUtils::set_json_field('field_name_or_key', $php_data, 125);

$json_encoded = json_encode($php_data);
$success = JsonUtils::set_json_field('field_name_or_key', $json_encoded, 125, true);
```

To encode PHP data to a JSON string with pretty print formatting, use the `encode` method:

```php
$json_encoded = JsonUtils::encode($php_data);
```

To display the field value on the front end, the shortcode `acf_json_field` can be used. By default, it'll look at the current post where the shortcode is added:

[acf_json_field field="field_name_or_key"]

Expand Down
4 changes: 2 additions & 2 deletions acf-json-field.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Description: A custom ACF field type for manipulating JSON data
* Text Domain: acf-json-field
* Author: Misaki F.
* Version: 1.0.1
* Version: 1.0.2
*/

namespace AcfJsonField;
Expand All @@ -18,7 +18,7 @@
# @title Constants
################################################################################

define('ACF_JSON_FIELD_VERSION', '1.0.1');
define('ACF_JSON_FIELD_VERSION', '1.0.2');

################################################################################
# @title Inclusions
Expand Down
128 changes: 92 additions & 36 deletions includes/class-json-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,64 @@
* Utility class for ACF JSON Field plugin.
*/
class JsonUtils {
/**
* Adds HTML tokens to a JSON-encoded string for syntax highlighting.
*
* @param string $json_encoded The JSON-encoded string.
* @return string The JSON string with HTML tokens for syntax highlighting.
*/
private static function add_html_tokens($json_encoded) {
$token_pattern = '/("(?:\\\\u[a-fA-F0-9]{4}|\\\\[^u]|[^\\\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(\.\d*)?([eE][+-]?\d+)?)/';

return preg_replace_callback($token_pattern, function ($matches) {
$match = $matches[0];
$token_type = 'number';

if (preg_match('/^"/', $match)) {
if (preg_match('/:$/', $match)) {
$token_type = 'key';
} else {
$token_type = 'string';
}
} elseif (preg_match('/true|false/', $match)) {
$token_type = 'boolean';
} elseif (preg_match('/null/', $match)) {
$token_type = 'null';
}

return '<span class="acf-json-field-' . $token_type . '">' . esc_html($match) . '</span>';
}, $json_encoded);
}

/**
* Retrieves the appropriate ID based on the input.
* @return int|string The determined ID.
*/
private static function get_id($id) {
if ($id === 'user') {
$id = 'user_' . get_current_user_id();
} else if (empty($id) || $id === 'null' || $id === 'false') {
$id = get_the_ID();
}

return $id;
}

/**
* Encodes PHP data to a JSON string with formatting options.
*
* @param mixed $php_data The PHP data to be encoded.
* @return string The JSON-encoded string.
*/
public static function encode($php_data) {
$json_encoded = json_encode($php_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$json_encoded = preg_replace_callback('/^( {4,})/m', function ($matches) {
return str_replace(' ', ' ', $matches[1]);
}, $json_encoded);

return $json_encoded;
}

/**
* Retrieves and formats JSON data from a specified ACF field.
*
Expand All @@ -21,12 +79,9 @@ class JsonUtils {
* - `user_\d+`: Uses the specified user ID.
* Examples:
* - get_json_field('field_name_or_key')
* - get_json_field('field_name_or_key', null)
* - get_json_field('field_name_or_key', 'null')
* - get_json_field('field_name_or_key', false)
* - get_json_field('field_name_or_key', 'false')
* - get_json_field('field_name_or_key', null)
* - get_json_field('field_name_or_key', 125)
* - get_json_field('field_name_or_key', '125')
* - get_json_field('field_name_or_key', 'user')
* - get_json_field('field_name_or_key', 'user_24')
* @param string $format The format in which to return the data.
Expand All @@ -36,47 +91,48 @@ class JsonUtils {
* Returns the appropriate PHP type if `$format` is 'php', or an HTML string if `$format` is 'html'.
*/
public static function get_json_field($field, $id = null, $format = 'php') {
if ($id === 'user') {
$id = 'user_' . get_current_user_id();
} else if ($id === '' || $id === null || $id === 'null' || $id === false || $id === 'false') {
$id = get_the_ID();
}

$id = self::get_id($id);
$data = '';
$raw_data = get_field($field, $id);
$json_decoded = json_decode($raw_data, true);

if ($format === 'html') {
$json_encoded = json_encode($json_decoded, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$json_encoded = preg_replace_callback('/^( {4,})/m', function ($matches) {
return str_replace(' ', ' ', $matches[1]);
}, $json_encoded);

$token_pattern = '/("(?:\\\\u[a-fA-F0-9]{4}|\\\\[^u]|[^\\\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(\.\d*)?([eE][+-]?\d+)?)/';
$json_encoded = preg_replace_callback($token_pattern, function ($matches) {
$match = $matches[0];
$token_type = 'number';

if (preg_match('/^"/', $match)) {
if (preg_match('/:$/', $match)) {
$token_type = 'key';
} else {
$token_type = 'string';
}
} elseif (preg_match('/true|false/', $match)) {
$token_type = 'boolean';
} elseif (preg_match('/null/', $match)) {
$token_type = 'null';
}

return '<span class="acf-json-field-' . $token_type . '">' . esc_html($match) . '</span>';
}, $json_encoded);

$json_encoded = self::encode($json_decoded);
$json_encoded = self::add_html_tokens($json_encoded);
$data = '<pre class="acf-json-field-output">' . $json_encoded . '</pre>';
} else if ($format === 'php') {
$data = $json_decoded;
}

return $data;
}

/**
* Sets the JSON data to a specified ACF field.
*
* @param string $field The key or name of the ACF field where the JSON data will be stored.
* @param mixed $data The data to be stored.
* @param int|string|false|null $id The ID of the post or user (see `get_json_field` for details).
* @param bool $is_json_encoded True if the data passed is already JSON encoded, false otherwise.
* @param bool $add_slashes True if slashes should be added to the data to escape it properly, false otherwise.
* @return bool True if the data was successfully updated, false otherwise.
*/
public static function set_json_field($field, $data, $id = null, $is_json_encoded = false, $add_slashes = false) {
$id = self::get_id($id);
$json_encoded = $is_json_encoded ? $data : self::encode($data);

if ($add_slashes) {
$json_encoded = wp_slash($json_encoded);
}

if (str_starts_with($id, 'user_')) {
$ret = update_user_meta(substr($id, 5), $field, $json_encoded);
} else {
$ret = update_post_meta($id, $field, $json_encoded);
}

$success = !empty($ret);

return $success;
}
}

0 comments on commit 3e95e90

Please sign in to comment.