1 | /** |
---|
2 | * External dependencies. |
---|
3 | */ |
---|
4 | import distinctUntilChanged from 'callbag-distinct-until-changed'; |
---|
5 | import { select } from '@wordpress/data'; |
---|
6 | import { pipe, map } from 'callbag-basics'; |
---|
7 | import { |
---|
8 | get, |
---|
9 | has, |
---|
10 | omit, |
---|
11 | assign, |
---|
12 | repeat, |
---|
13 | mapKeys, |
---|
14 | findIndex, |
---|
15 | startsWith |
---|
16 | } from 'lodash'; |
---|
17 | |
---|
18 | /** |
---|
19 | * Carbon Fields dependencies. |
---|
20 | */ |
---|
21 | import { fromSelector, withConditionalLogic } from '@carbon-fields/core'; |
---|
22 | |
---|
23 | /** |
---|
24 | * Adds the `parent.` parent prefix to field's name. |
---|
25 | * |
---|
26 | * @param {Object[]} fields |
---|
27 | * @param {number} depth |
---|
28 | * @return {Array[]} |
---|
29 | */ |
---|
30 | function mapParentPrefix( fields, depth = 0 ) { |
---|
31 | return mapKeys( fields, ( value, key ) => `${ repeat( 'parent.', depth ) }${ key }` ); |
---|
32 | } |
---|
33 | |
---|
34 | /** |
---|
35 | * Returns whether the given string is a group identifier. |
---|
36 | * |
---|
37 | * @param {string} id |
---|
38 | * @return {boolean} |
---|
39 | */ |
---|
40 | function isComplexGroupIdentifier( id ) { |
---|
41 | return startsWith( id, 'cf-' ); |
---|
42 | } |
---|
43 | |
---|
44 | /** |
---|
45 | * The function used to track dependencies required |
---|
46 | * by conditional logic. |
---|
47 | * |
---|
48 | * @param {Object} props |
---|
49 | * @return {Object} |
---|
50 | */ |
---|
51 | function input( props ) { |
---|
52 | return pipe( |
---|
53 | fromSelector( select( 'core/block-editor' ).getBlock, props.blockId ), |
---|
54 | distinctUntilChanged(), |
---|
55 | map( ( blockData ) => blockData?.attributes?.data ) |
---|
56 | ); |
---|
57 | } |
---|
58 | |
---|
59 | /** |
---|
60 | * The function that provides the data that needs to be |
---|
61 | * evaluated by conditional logic. |
---|
62 | * |
---|
63 | * @param {Object} props |
---|
64 | * @param {Object} fields |
---|
65 | * @return {Object} |
---|
66 | */ |
---|
67 | function output( props, fields ) { |
---|
68 | const isTopLevelField = has( fields, props.field.base_name ); |
---|
69 | let siblingFields = {}; |
---|
70 | |
---|
71 | if ( isTopLevelField ) { |
---|
72 | siblingFields = mapParentPrefix( omit( fields, [ props.field.base_name ] ) ); |
---|
73 | } else { |
---|
74 | // Get the hierarchy. |
---|
75 | const path = props.id.split( '__' ); |
---|
76 | |
---|
77 | // Remove the chunk with identifier of block since |
---|
78 | // we already have it. |
---|
79 | path.shift(); |
---|
80 | |
---|
81 | // Remove the chunk with name of root field. |
---|
82 | const rootFieldName = path.shift(); |
---|
83 | |
---|
84 | // Remove the chunk with name of field since |
---|
85 | // we already have it. |
---|
86 | path.pop(); |
---|
87 | |
---|
88 | // Keep reference to the depth |
---|
89 | // so we can add the `parent.` prefix. |
---|
90 | let depth = path.reduce( ( accumulator, chunk ) => { |
---|
91 | return isComplexGroupIdentifier( chunk ) |
---|
92 | ? accumulator |
---|
93 | : accumulator + 1; |
---|
94 | }, 0 ); |
---|
95 | |
---|
96 | // Collect fields that are siblings of root field. |
---|
97 | siblingFields = omit( fields, [ rootFieldName ] ); |
---|
98 | siblingFields = mapParentPrefix( siblingFields, depth + 1 ); |
---|
99 | |
---|
100 | // Keep reference to the full path of the field. |
---|
101 | let pathPrefix = rootFieldName; |
---|
102 | |
---|
103 | while ( path.length > 0 ) { |
---|
104 | const chunk = path.shift(); |
---|
105 | const isGroup = isComplexGroupIdentifier( chunk ); |
---|
106 | const isNestedComplex = ! isGroup; |
---|
107 | |
---|
108 | if ( isGroup ) { |
---|
109 | const groupIndex = findIndex( get( fields, pathPrefix ), [ '_id', chunk ] ); |
---|
110 | |
---|
111 | pathPrefix = `${ pathPrefix }.${ groupIndex }`; |
---|
112 | |
---|
113 | let groupFields = get( fields, pathPrefix ); |
---|
114 | groupFields = omit( groupFields, [ '_id', '_type', props.field.base_name ] ); |
---|
115 | groupFields = mapParentPrefix( groupFields, depth ); |
---|
116 | |
---|
117 | assign( siblingFields, groupFields ); |
---|
118 | } |
---|
119 | |
---|
120 | if ( isNestedComplex ) { |
---|
121 | pathPrefix = `${ pathPrefix }.${ chunk }`; |
---|
122 | |
---|
123 | depth--; |
---|
124 | } |
---|
125 | } |
---|
126 | } |
---|
127 | |
---|
128 | return siblingFields; |
---|
129 | } |
---|
130 | |
---|
131 | export default withConditionalLogic( input, output ); |
---|