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 / assets / src / js / bindings / hooks.js
secure-custom-fields / assets / src / js / bindings Last commit date
block-editor.js 6 months ago constants.js 6 months ago field-processing.js 6 months ago fieldMetadataCache.js 6 months ago hooks.js 6 months ago index.js 11 months ago sources.js 6 months ago utils.js 6 months ago
hooks.js
182 lines
1 /**
2 * Custom hooks for block bindings
3 */
4
5 import { useState, useEffect } from '@wordpress/element';
6 import { useSelect } from '@wordpress/data';
7 import { store as coreDataStore } from '@wordpress/core-data';
8 import { store as editorStore } from '@wordpress/editor';
9 import apiFetch from '@wordpress/api-fetch';
10 import { addQueryArgs } from '@wordpress/url';
11
12 import { extractPostTypeFromTemplate, formatFieldGroupsData } from './utils';
13 import { addFieldMetadata } from './fieldMetadataCache';
14
15 /**
16 * Custom hook to detect if we're in the site editor and get the template info.
17 *
18 * @since 6.7.0
19 * @return {Object} Object containing isSiteEditor flag and templatePostType.
20 */
21 export function useSiteEditorContext() {
22 return useSelect( ( select ) => {
23 const { getCurrentPostType, getCurrentPostId } = select( editorStore );
24 const { getEditedEntityRecord } = select( coreDataStore );
25
26 const postType = getCurrentPostType();
27 const postId = getCurrentPostId();
28
29 const isSiteEditor = postType === 'wp_template';
30
31 if ( ! isSiteEditor ) {
32 return {
33 isSiteEditor: false,
34 templatePostType: null,
35 };
36 }
37
38 const template = getEditedEntityRecord(
39 'postType',
40 'wp_template',
41 postId
42 );
43
44 const templatePostType = extractPostTypeFromTemplate(
45 template?.slug || ''
46 );
47
48 return {
49 isSiteEditor: true,
50 templatePostType,
51 };
52 }, [] );
53 }
54
55 /**
56 * Custom hook to get SCF fields for the current post editor context.
57 *
58 * @since 6.7.0
59 * @return {Object} Object containing the fields map.
60 */
61 export function usePostEditorFields() {
62 return useSelect( ( select ) => {
63 const { getCurrentPostType, getCurrentPostId } = select( editorStore );
64 const { getEditedEntityRecord } = select( coreDataStore );
65
66 const postType = getCurrentPostType();
67 const postId = getCurrentPostId();
68
69 if ( ! postType || ! postId || postType === 'wp_template' ) {
70 return {};
71 }
72
73 const record = getEditedEntityRecord( 'postType', postType, postId );
74
75 // Extract fields that have '_source' counterparts
76 const sourcedFields = {};
77 if ( record?.acf ) {
78 Object.entries( record.acf ).forEach( ( [ key, value ] ) => {
79 if ( key.endsWith( '_source' ) ) {
80 const baseFieldName = key.replace( '_source', '' );
81 if ( Object.hasOwn( record.acf, baseFieldName ) ) {
82 sourcedFields[ baseFieldName ] = value;
83 }
84 }
85 } );
86 }
87
88 return sourcedFields;
89 }, [] );
90 }
91
92 /**
93 * Custom hook to fetch and manage SCF field groups from the REST API.
94 *
95 * @since 6.7.0
96 * @param {string|null} postType The post type to fetch fields for.
97 * @return {Object} Object containing fields, isLoading, and error.
98 */
99 export function useSiteEditorFields( postType ) {
100 const [ fields, setFields ] = useState( {} );
101 const [ isLoading, setIsLoading ] = useState( false );
102 const [ error, setError ] = useState( null );
103
104 useEffect( () => {
105 if ( ! postType ) {
106 setFields( {} );
107 setIsLoading( false );
108 setError( null );
109 return;
110 }
111
112 let isCancelled = false;
113 setIsLoading( true );
114 setError( null );
115
116 const fetchFields = async () => {
117 try {
118 const path = addQueryArgs( `/wp/v2/types/${ postType }`, {
119 context: 'edit',
120 } );
121
122 const postTypeData = await apiFetch( { path } );
123
124 if ( isCancelled ) {
125 return;
126 }
127
128 const fieldsMap = formatFieldGroupsData(
129 postTypeData.scf_field_groups
130 );
131
132 // Store field metadata in the data store
133 addFieldMetadata( fieldsMap );
134
135 setFields( fieldsMap );
136 setIsLoading( false );
137 } catch ( err ) {
138 if ( ! isCancelled ) {
139 setError( err );
140 setIsLoading( false );
141 }
142 }
143 };
144
145 fetchFields();
146
147 // Cleanup function to prevent state updates after unmount
148 return () => {
149 isCancelled = true;
150 };
151 }, [ postType ] );
152
153 return { fields, isLoading, error };
154 }
155
156 /**
157 * Custom hook to manage block bindings state.
158 *
159 * @since 6.7.0
160 * @param {Object} blockAttributes The block attributes object.
161 * @return {Object} Object containing boundFields and sync function.
162 */
163 export function useBoundFields( blockAttributes ) {
164 const [ boundFields, setBoundFields ] = useState( {} );
165
166 useEffect( () => {
167 const currentBindings = blockAttributes?.metadata?.bindings || {};
168 const newBoundFields = {};
169
170 Object.keys( currentBindings ).forEach( ( attribute ) => {
171 if ( currentBindings[ attribute ]?.args?.key ) {
172 newBoundFields[ attribute ] =
173 currentBindings[ attribute ].args.key;
174 }
175 } );
176
177 setBoundFields( newBoundFields );
178 }, [ blockAttributes?.metadata?.bindings ] );
179
180 return { boundFields, setBoundFields };
181 }
182