PluginProbe ʕ •ᴥ•ʔ
Atarim – AI Agency for WordPress: Edit Pages, Fix Code, Update Plugins, SEO & Client Feedback / 5.0
Atarim – AI Agency for WordPress: Edit Pages, Fix Code, Update Plugins, SEO & Client Feedback v5.0
5.1.3 5.1.2 5.1.1 5.1 5.0 trunk 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 3.2.0 3.2.1 3.22 3.22.1 3.22.2 3.22.3 3.22.4 3.22.5 3.22.6 3.3.0 3.3.1 3.3.2 3.3.2.1 3.3.2.2 3.3.3 3.30 3.31 3.32 3.4 3.4.1 3.4.3 3.4.4 3.5 3.5.1 3.6 3.6.1 3.7 3.8 3.9 3.9.1 3.9.2 3.9.3 3.9.4 3.9.6 3.9.6.1 4.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.2 4.1.3 4.2 4.2.1 4.2.2 4.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.4
atarim-visual-collaboration / third-party / content-model / acf / class-avcf-acf-helpers.php
atarim-visual-collaboration / third-party / content-model / acf Last commit date
class-avcf-acf-abilities.php 1 month ago class-avcf-acf-content-models.php 1 month ago class-avcf-acf-detector.php 1 month ago class-avcf-acf-field-groups.php 1 month ago class-avcf-acf-helpers.php 1 month ago
class-avcf-acf-helpers.php
203 lines
1 <?php
2 /**
3 * Shared helpers for the ACF ability cluster.
4 *
5 * Static utilities used by the field-group, post-type, taxonomy, and
6 * options-page ability classes: detecting where a field group is stored
7 * (DB vs PHP vs local JSON), generating valid ACF field keys, mapping the
8 * "kind" argument to ACF's internal post types, gating the management APIs
9 * behind ACF Pro 6.5+, and normalising records for output.
10 *
11 * @package atarim-visual-collaboration
12 */
13
14 if ( ! defined('ABSPATH') ) {
15 exit;
16 }
17
18 class AVCF_ACF_Helpers {
19
20 /**
21 * Map a public "kind" to ACF's internal post type slug.
22 *
23 * @param string $kind one of 'post-type' | 'taxonomy' | 'options-page'
24 * @return string|null ACF internal post type, or null if unknown.
25 */
26 public static function internal_post_type( $kind ) {
27 switch ( $kind ) {
28 case 'post-type':
29 return 'acf-post-type';
30 case 'taxonomy':
31 return 'acf-taxonomy';
32 case 'options-page':
33 return 'acf-ui-options-page';
34 default:
35 return null;
36 }
37 }
38
39 /**
40 * Storage location of a field group array.
41 *
42 * ACF marks PHP- and JSON-registered groups via the 'local' key; groups
43 * stored in the database have no 'local' marker and a positive numeric ID.
44 *
45 * @param array $group An acf_get_field_group() result.
46 * @return string 'php' | 'json' | 'db'
47 */
48 public static function storage_mode( $group ) {
49 $local = isset( $group['local'] ) ? $group['local'] : null;
50 if ( $local === 'php' ) {
51 return 'php';
52 }
53 if ( $local === 'json' ) {
54 return 'json';
55 }
56 return 'db';
57 }
58
59 /**
60 * Whether a group can be written to (only DB-stored groups are mutable).
61 *
62 * @param array $group
63 * @return bool
64 */
65 public static function is_mutable( $group ) {
66 return self::storage_mode( $group ) === 'db';
67 }
68
69 /**
70 * Human message explaining why a non-DB group cannot be modified.
71 *
72 * @param array $group
73 * @param string $key
74 * @return string
75 */
76 public static function immutable_message( $group, $key ) {
77 $mode = self::storage_mode( $group );
78 return sprintf(
79 'Field group "%s" is registered via %s and is read-only. Only field groups stored in the database (created in the ACF admin UI or via these abilities) can be modified or deleted.',
80 $key,
81 $mode === 'php' ? 'PHP (acf_add_local_field_group / register code)' : 'local JSON (acf-json sync)'
82 );
83 }
84
85 /**
86 * Generate a valid, unique ACF field key.
87 *
88 * ACF field keys must be prefixed with "field_". We never let the agent
89 * invent keys — any field supplied without one gets a generated key here.
90 *
91 * @return string
92 */
93 public static function generate_field_key() {
94 return 'field_' . substr( md5( uniqid( (string) wp_rand(), true ) ), 0, 13 );
95 }
96
97 /**
98 * Generate a valid, unique ACF field group key.
99 *
100 * @return string
101 */
102 public static function generate_group_key() {
103 return 'group_' . substr( md5( uniqid( (string) wp_rand(), true ) ), 0, 13 );
104 }
105
106 /**
107 * Ensure every field in a (possibly nested) fields array has a key.
108 *
109 * Recurses into sub_fields (repeater/group) and layouts (flexible content)
110 * so complex fields are fully keyed before import.
111 *
112 * @param array $fields
113 * @return array
114 */
115 public static function ensure_field_keys( $fields ) {
116 if ( ! is_array( $fields ) ) {
117 return [];
118 }
119 foreach ( $fields as $idx => $field ) {
120 if ( ! is_array( $field ) ) {
121 continue;
122 }
123 if ( empty( $field['key'] ) ) {
124 $field['key'] = self::generate_field_key();
125 }
126 if ( isset( $field['sub_fields'] ) && is_array( $field['sub_fields'] ) ) {
127 $field['sub_fields'] = self::ensure_field_keys( $field['sub_fields'] );
128 }
129 if ( isset( $field['layouts'] ) && is_array( $field['layouts'] ) ) {
130 foreach ( $field['layouts'] as $lidx => $layout ) {
131 if ( isset( $layout['sub_fields'] ) && is_array( $layout['sub_fields'] ) ) {
132 $field['layouts'][ $lidx ]['sub_fields'] = self::ensure_field_keys( $layout['sub_fields'] );
133 }
134 }
135 }
136 $fields[ $idx ] = $field;
137 }
138 return $fields;
139 }
140
141 /**
142 * Compact summary of a field group for list views.
143 *
144 * @param array $group
145 * @return array
146 */
147 public static function group_summary( $group ) {
148 return [
149 'key' => isset( $group['key'] ) ? (string) $group['key'] : '',
150 'title' => isset( $group['title'] ) ? (string) $group['title'] : '',
151 'active' => isset( $group['active'] ) ? (bool) $group['active'] : true,
152 'storage' => self::storage_mode( $group ),
153 'mutable' => self::is_mutable( $group ),
154 'location' => isset( $group['location'] ) ? $group['location'] : [],
155 'field_count' => function_exists( 'acf_get_fields' ) ? count( (array) acf_get_fields( isset( $group['key'] ) ? $group['key'] : '' ) ) : 0,
156 ];
157 }
158
159 /**
160 * Reduce a raw ACF field array to the schema-relevant keys for output.
161 *
162 * Recurses into sub_fields and flexible-content layouts.
163 *
164 * @param array $field
165 * @return array
166 */
167 public static function field_schema( $field ) {
168 if ( ! is_array( $field ) ) {
169 return [];
170 }
171 $out = [
172 'key' => isset( $field['key'] ) ? (string) $field['key'] : '',
173 'label' => isset( $field['label'] ) ? (string) $field['label'] : '',
174 'name' => isset( $field['name'] ) ? (string) $field['name'] : '',
175 'type' => isset( $field['type'] ) ? (string) $field['type'] : '',
176 'required' => isset( $field['required'] ) ? (bool) $field['required'] : false,
177 ];
178 foreach ( [ 'instructions', 'default_value', 'choices', 'min', 'max', 'return_format', 'allow_null', 'multiple' ] as $opt ) {
179 if ( isset( $field[ $opt ] ) ) {
180 $out[ $opt ] = $field[ $opt ];
181 }
182 }
183 if ( isset( $field['sub_fields'] ) && is_array( $field['sub_fields'] ) ) {
184 $out['sub_fields'] = array_map( [ __CLASS__, 'field_schema' ], $field['sub_fields'] );
185 }
186 if ( isset( $field['layouts'] ) && is_array( $field['layouts'] ) ) {
187 $out['layouts'] = [];
188 foreach ( $field['layouts'] as $layout ) {
189 $lo = [
190 'key' => isset( $layout['key'] ) ? (string) $layout['key'] : '',
191 'name' => isset( $layout['name'] ) ? (string) $layout['name'] : '',
192 'label' => isset( $layout['label'] ) ? (string) $layout['label'] : '',
193 ];
194 if ( isset( $layout['sub_fields'] ) && is_array( $layout['sub_fields'] ) ) {
195 $lo['sub_fields'] = array_map( [ __CLASS__, 'field_schema' ], $layout['sub_fields'] );
196 }
197 $out['layouts'][] = $lo;
198 }
199 }
200 return $out;
201 }
202 }
203