Skip to content

Commit 9d873e2

Browse files
authored
Block Bindings: Add editor preview to acf-field source. (#175)
* Add editor preview to acf-field * Follow recommendations * More fixes
1 parent 0e65f48 commit 9d873e2

File tree

5 files changed

+123
-9
lines changed

5 files changed

+123
-9
lines changed

assets/src/js/bindings/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './sources.js';

assets/src/js/bindings/sources.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* WordPress dependencies.
3+
*/
4+
import { __ } from '@wordpress/i18n';
5+
import { registerBlockBindingsSource } from '@wordpress/blocks';
6+
import { store as coreDataStore } from '@wordpress/core-data';
7+
8+
/**
9+
* Get the value of a specific field from the ACF fields.
10+
*
11+
* @param {Object} fields The ACF fields object.
12+
* @param {string} fieldName The name of the field to retrieve.
13+
* @returns {string} The value of the specified field, or undefined if not found.
14+
*/
15+
const getFieldValue = ( fields, fieldName ) => fields?.acf?.[ fieldName ];
16+
17+
const resolveImageAttribute = ( imageObj, attribute ) => {
18+
if ( ! imageObj ) return '';
19+
switch ( attribute ) {
20+
case 'url':
21+
case 'content':
22+
return imageObj.source_url;
23+
case 'alt':
24+
return imageObj.alt_text || '';
25+
case 'title':
26+
return imageObj.title?.rendered || '';
27+
default:
28+
return '';
29+
}
30+
};
31+
32+
registerBlockBindingsSource( {
33+
name: 'acf/field',
34+
label: 'SCF Fields',
35+
getValues( { context, bindings, select } ) {
36+
const { getEditedEntityRecord, getMedia } = select( coreDataStore );
37+
let fields =
38+
context?.postType && context?.postId
39+
? getEditedEntityRecord(
40+
'postType',
41+
context.postType,
42+
context.postId
43+
)
44+
: undefined;
45+
const result = {};
46+
47+
Object.entries( bindings ).forEach(
48+
( [ attribute, { args } = {} ] ) => {
49+
const fieldName = args?.key;
50+
51+
const fieldValue = getFieldValue( fields, fieldName );
52+
if ( typeof fieldValue === 'object' && fieldValue !== null ) {
53+
let value = '';
54+
55+
if ( fieldValue[ attribute ] ) {
56+
value = fieldValue[ attribute ];
57+
} else if ( attribute === 'content' && fieldValue.url ) {
58+
value = fieldValue.url;
59+
}
60+
61+
result[ attribute ] = value;
62+
} else if ( typeof fieldValue === 'number' ) {
63+
if ( attribute === 'content' ) {
64+
result[ attribute ] = fieldValue.toString() || '';
65+
} else {
66+
const imageObj = getMedia( fieldValue );
67+
result[ attribute ] = resolveImageAttribute(
68+
imageObj,
69+
attribute
70+
);
71+
}
72+
} else {
73+
result[ attribute ] = fieldValue || '';
74+
}
75+
}
76+
);
77+
78+
return result;
79+
},
80+
canUserEditValue() {
81+
return false;
82+
},
83+
} );

includes/Blocks/Bindings.php

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function register_binding_sources() {
3737
array(
3838
'label' => _x( 'SCF Fields', 'The core SCF block binding source name for fields on the current page', 'secure-custom-fields' ),
3939
'get_value_callback' => array( $this, 'get_value' ),
40+
'uses_context' => array( 'postId', 'postType' ),
4041
)
4142
);
4243
}
@@ -78,15 +79,33 @@ public function get_value( array $source_attrs, \WP_Block $block_instance, strin
7879
}
7980
}
8081

81-
$value = $field['value'];
82+
switch ( $attribute_name ) {
83+
case 'id':
84+
case 'alt':
85+
case 'title':
86+
// The value is in the field of the same name.
87+
$value = $field['value'][ $attribute_name ] ?? '';
88+
break;
89+
case 'url':
90+
// The URL is the field value.
91+
$value = $field['value']['url'] ?? $field['value'] ?? '';
92+
break;
93+
case 'rel':
94+
// Handle checkbox field for rel attribute by joining array values.
95+
if ( is_array( $field['value'] ) ) {
96+
$value = implode( ' ', $field['value'] );
97+
} else {
98+
$value = $field['value'] ?? '';
99+
}
100+
break;
101+
default:
102+
$value = $field['value'];
82103

83-
if ( is_array( $value ) ) {
84-
$value = implode( ', ', $value );
85-
}
86-
87-
// If we're not a scalar we'd throw an error, so return early for safety.
88-
if ( ! is_scalar( $value ) ) {
89-
$value = null;
104+
if ( is_array( $value ) ) {
105+
$value = wp_json_encode( $value );
106+
} elseif ( ! is_scalar( $value ) && null !== $value ) {
107+
$value = '';
108+
}
90109
}
91110
}
92111

includes/assets.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,14 @@ public function register_scripts() {
189189
'version' => $version,
190190
'in_footer' => true,
191191
),
192+
'scf-bindings' => array(
193+
'handle' => 'scf-bindings',
194+
'src' => acf_get_url( sprintf( $js_path_patterns['base'], 'scf-bindings' ) ),
195+
'asset_file' => acf_get_path( sprintf( $asset_path_patterns['base'], 'scf-bindings' ) ),
196+
'version' => $version,
197+
'deps' => array(),
198+
'in_footer' => true,
199+
),
192200
);
193201

194202
// Define style registrations.
@@ -529,6 +537,7 @@ public function enqueue_scripts() {
529537
// @todo integrate into the above. Previously, they were simply hooked into the hook below.
530538
wp_enqueue_script( 'acf-pro-input' );
531539
wp_enqueue_script( 'acf-pro-ui-options-page' );
540+
wp_enqueue_script( 'scf-bindings' );
532541
wp_enqueue_style( 'acf-pro-input' );
533542

534543
/**

webpack.config.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@ const commonConfig = {
1616
'js/acf-internal-post-type':
1717
'./assets/src/js/acf-internal-post-type.js',
1818
'js/commands/scf-admin': './assets/src/js/commands/admin-commands.js',
19-
'js/commands/scf-custom-post-types': './assets/src/js/commands/custom-post-type-commands.js',
19+
'js/commands/scf-custom-post-types':
20+
'./assets/src/js/commands/custom-post-type-commands.js',
2021
'js/acf': './assets/src/js/acf.js',
2122
'js/pro/acf-pro-blocks': './assets/src/js/pro/acf-pro-blocks.js',
2223
'js/pro/acf-pro-field-group':
2324
'./assets/src/js/pro/acf-pro-field-group.js',
2425
'js/pro/acf-pro-input': './assets/src/js/pro/acf-pro-input.js',
2526
'js/pro/acf-pro-ui-options-page':
2627
'./assets/src/js/pro/acf-pro-ui-options-page.js',
28+
'js/scf-bindings': './assets/src/js/bindings/index.js',
2729

2830
// CSS files
2931
'css/acf-dark': './assets/src/sass/acf-dark.scss',

0 commit comments

Comments
 (0)