44
55use Smartling \Base \ExportedAPI ;
66use Smartling \Bootstrap ;
7- use Smartling \Exception \SmartlingConfigException ;
87use Smartling \Exception \SmartlingDirectRunRuntimeException ;
98use Smartling \Extensions \AcfOptionPages \ContentTypeAcfOption ;
109use Smartling \Helpers \ArrayHelper ;
@@ -31,7 +30,7 @@ class AcfDynamicSupport
3130 public const REFERENCED_TYPE_POST = 'post ' ;
3231 public const REFERENCED_TYPE_TAXONOMY = 'taxonomy ' ;
3332
34- public static array $ acfReverseDefinitionAction = [];
33+ private array $ filterConfigurations = [];
3534
3635 private ?array $ definitions = null ;
3736
@@ -47,20 +46,6 @@ public function getDefinitions(): array
4746 return $ this ->definitions ?? [];
4847 }
4948
50- /**
51- * @throws SmartlingConfigException
52- */
53- private function getAcf (): mixed
54- {
55- global $ acf ;
56-
57- if (!isset ($ acf )) {
58- throw new SmartlingConfigException ('ACF plugin is not installed or activated. ' );
59- }
60-
61- return $ acf ;
62- }
63-
6449 public function __construct (
6550 private ArrayHelper $ arrayHelper ,
6651 private SettingsManager $ settingsManager ,
@@ -108,7 +93,7 @@ private function getBlogListForSearch(): array
10893 /**
10994 * @throws SmartlingDirectRunRuntimeException
11095 */
111- private function getDatabaseDefinitions (): array
96+ private function loadDefinitions (): array
11297 {
11398 $ defs = [];
11499 $ this ->getLogger ()->debug ('Looking for ACF definitions via ACF API ' );
@@ -130,177 +115,78 @@ private function getDatabaseDefinitions(): array
130115 return $ defs ;
131116 }
132117
133- private function collectAcfDefinitions ( ): array
118+ public function getFilterConfiguration ( string $ key ): ? array
134119 {
135- $ defs = [];
136- foreach (acf_get_field_groups () as $ group ) {
137- $ defs [$ group ['key ' ]] = [
138- 'global_type ' => 'group ' ,
139- 'active ' => $ group ['active ' ] ?? 1 ,
140- ];
141- $ stack = [$ group ];
142- while (null !== ($ parent = array_shift ($ stack ))) {
143- foreach (acf_get_fields ($ parent ) as $ field ) {
144- if (!is_array ($ field ) || !isset ($ field ['key ' ], $ field ['type ' ])) {
145- continue ;
146- }
147- $ defs [$ field ['key ' ]] = ['global_type ' => 'field ' , 'type ' => $ field ['type ' ]];
148- if ('clone ' === $ field ['type ' ]) {
149- if (array_key_exists ('clone ' , $ field )) {
150- $ defs [$ field ['key ' ]]['clone ' ] = $ field ['clone ' ];
151- } else {
152- $ this ->getLogger ()->debug ('ACF field fieldType="clone" has no target. ' . json_encode ($ field ));
153- }
154- }
155- if (in_array ($ field ['type ' ], ['repeater ' , 'group ' , 'flexible_content ' ], true )) {
156- $ stack [] = $ field ;
157- }
158- }
159- }
160- }
161-
162- return $ defs ;
120+ return $ this ->filterConfigurations [$ key ] ?? null ;
163121 }
164122
165- public function getReferencedType (string $ type ): string
166- {
167- return match ($ type ) {
168- 'image ' , 'image_aspect_ratio_crop ' , 'file ' , 'gallery ' => self ::REFERENCED_TYPE_MEDIA ,
169- 'post_object ' , 'page_link ' , 'relationship ' => self ::REFERENCED_TYPE_POST ,
170- 'taxonomy ' => self ::REFERENCED_TYPE_TAXONOMY ,
171- default => self ::REFERENCED_TYPE_NONE ,
172- };
173- }
174-
175- protected function extractGroupsDefinitions (array $ groups ): array
123+ private function collectAcfDefinitions (): array
176124 {
177125 $ defs = [];
178- foreach ($ groups as $ group ) {
126+ foreach (acf_get_raw_field_groups () as $ group ) {
127+ if (!is_array ($ group ) || !isset ($ group ['key ' ], $ group ['ID ' ])) {
128+ continue ;
129+ }
179130 $ defs [$ group ['key ' ]] = [
180131 'global_type ' => 'group ' ,
132+ 'active ' => $ group ['active ' ] ?? 1 ,
181133 ];
182- if ( array_key_exists ( ' active ' , $ group ) ) {
183- $ defs [ $ group [ ' key ' ]][ ' active ' ] = $ group [ ' active ' ] ;
134+ foreach ( acf_get_raw_fields ( $ group [ ' ID ' ]) as $ field ) {
135+ $ this -> addAcfFieldToDefs ( $ field , $ defs ) ;
184136 }
185137 }
186138
187139 return $ defs ;
188140 }
189141
190- protected function extractFieldDefinitions ( array $ fields ): array
142+ private function addAcfFieldToDefs ( mixed $ field , array & $ defs ): void
191143 {
192- $ defs = [];
193-
194- foreach ($ fields as $ field ) {
195- $ defs [$ field ['key ' ]] = [
196- 'global_type ' => 'field ' ,
197- 'type ' => $ field ['type ' ],
198- 'name ' => $ field ['name ' ],
199- 'parent ' => $ field ['parent ' ],
200- ];
201-
202- if ('clone ' === $ field ['type ' ]) {
144+ if (!is_array ($ field ) || !isset ($ field ['key ' ], $ field ['type ' ])) {
145+ return ;
146+ }
147+ $ defs [$ field ['key ' ]] = ['global_type ' => 'field ' , 'type ' => $ field ['type ' ]];
148+ if ('clone ' === $ field ['type ' ]) {
149+ if (array_key_exists ('clone ' , $ field )) {
203150 $ defs [$ field ['key ' ]]['clone ' ] = $ field ['clone ' ];
151+ } else {
152+ $ this ->getLogger ()->debug ('ACF field fieldType="clone" has no target. ' . json_encode ($ field ));
204153 }
205154 }
206-
207- return $ defs ;
208- }
209-
210- /**
211- * Get local definitions for ACF Pro ver < 5.7.12
212- */
213- private function getLocalDefinitionsOld (): array
214- {
215- $ defs = [];
216- try {
217- $ acf = (array )$ this ->getAcf ();
218- } catch (SmartlingConfigException $ e ) {
219- $ this ->getLogger ()->warning ($ e ->getMessage ());
220- $ this ->getLogger ()->warning ('Unable to load old type local ACF definitions. ' );
221-
222- return $ defs ;
155+ if (!in_array ($ field ['type ' ], ['repeater ' , 'group ' , 'flexible_content ' ], true )) {
156+ return ;
223157 }
224-
225- if (array_key_exists ('local ' , $ acf )) {
226- if ($ acf ['local ' ] instanceof \acf_local) {
227- $ local = $ acf ['local ' ];
228-
229- $ defs = array_merge ($ defs , $ this ->extractGroupsDefinitions ($ local ->groups ));
230- $ defs = array_merge ($ defs , $ this ->extractFieldDefinitions ($ local ->fields ));
231-
158+ if (isset ($ field ['ID ' ]) && (int )$ field ['ID ' ] > 0 ) {
159+ foreach (acf_get_raw_fields ((int )$ field ['ID ' ]) as $ child ) {
160+ $ this ->addAcfFieldToDefs ($ child , $ defs );
232161 }
233162 }
234-
235- return $ defs ;
236- }
237-
238- protected function validateAcfStores (): bool
239- {
240- global $ acf_stores ;
241-
242- return is_array ($ acf_stores )
243- && array_key_exists ('local-groups ' , $ acf_stores )
244- && ($ acf_stores ['local-groups ' ] instanceof \ACF_Data)
245- && array_key_exists ('local-fields ' , $ acf_stores )
246- && ($ acf_stores ['local-fields ' ] instanceof \ACF_Data);
247- }
248-
249- /**
250- * Get local definitions for ACF Pro ver 5.7.12+
251- */
252- private function getLocalDefinitionsNew (): array
253- {
254- $ defs = [];
255-
256- if ($ this ->validateAcfStores ()) {
257- global $ acf_stores ;
258-
259- $ defs = array_merge ($ defs , $ this ->extractGroupsDefinitions ($ acf_stores ['local-groups ' ]->get_data ()));
260- $ defs = array_merge ($ defs , $ this ->extractFieldDefinitions ($ acf_stores ['local-fields ' ]->get_data ()));
261-
262- } else {
263- $ this ->getLogger ()->warning ('Unable to load new type local ACF definitions. ' );
264- }
265-
266- return $ defs ;
267- }
268-
269- /**
270- * Reads local (PHP and JSON) ACF Definitions
271- */
272- private function getLocalDefinitions (): array
273- {
274- $ defs = $ this ->getLocalDefinitionsOld ();
275-
276- if (empty ($ defs )) {
277- $ defs = $ this ->getLocalDefinitionsNew ();
278- }
279-
280- return $ defs ;
281- }
282-
283- private function verifyDefinitions (array $ localDefinitions , array $ dbDefinitions ): bool
284- {
285- foreach ($ dbDefinitions as $ key => $ definition ) {
286- if (!array_key_exists ($ key , $ localDefinitions )) {
287- return false ;
163+ if (isset ($ field ['sub_fields ' ]) && is_array ($ field ['sub_fields ' ])) {
164+ foreach ($ field ['sub_fields ' ] as $ child ) {
165+ $ this ->addAcfFieldToDefs ($ child , $ defs );
288166 }
289-
290- if ($ definition ['global_type ' ] === 'field ' ) {
291- $ local = $ localDefinitions [$ key ];
292- if ($ local ['type ' ] !== $ definition ['type ' ]) {
293- // ACF Option Pages has internal issue in definition, so skip it:
294- if ('group_572b269b668a4 ' !== $ local ['parent ' ]) {
295- return false ;
167+ }
168+ if (isset ($ field ['layouts ' ]) && is_array ($ field ['layouts ' ])) {
169+ foreach ($ field ['layouts ' ] as $ layout ) {
170+ if (is_array ($ layout ) && isset ($ layout ['sub_fields ' ]) && is_array ($ layout ['sub_fields ' ])) {
171+ foreach ($ layout ['sub_fields ' ] as $ child ) {
172+ $ this ->addAcfFieldToDefs ($ child , $ defs );
296173 }
297174 }
298175 }
299176 }
177+ }
300178
301- return true ;
179+ public function getReferencedType (string $ type ): string
180+ {
181+ return match ($ type ) {
182+ 'image ' , 'image_aspect_ratio_crop ' , 'file ' , 'gallery ' => self ::REFERENCED_TYPE_MEDIA ,
183+ 'post_object ' , 'page_link ' , 'relationship ' => self ::REFERENCED_TYPE_POST ,
184+ 'taxonomy ' => self ::REFERENCED_TYPE_TAXONOMY ,
185+ default => self ::REFERENCED_TYPE_NONE ,
186+ };
302187 }
303188
189+
304190 private function tryRegisterACFOptions (): void
305191 {
306192 $ this ->getLogger ()->debug ('Checking if ACF Option Pages presents... ' );
@@ -399,31 +285,16 @@ private function tryRegisterACF(): void
399285 $ this ->getLogger ()->debug ('Checking if ACF presents... ' );
400286 if ($ this ->isAcfActive ()) {
401287 $ this ->getLogger ()->debug ('ACF detected. ' );
402- $ localDefinitions = $ this ->getLocalDefinitions ();
403-
404288 try {
405- $ dbDefinitions = $ this ->getDatabaseDefinitions ();
289+ $ this -> definitions = $ this ->loadDefinitions ();
406290 } catch (SmartlingDirectRunRuntimeException $ e ) {
407- $ dbDefinitions = [];
291+ $ this -> definitions = [];
408292 DiagnosticsHelper::addDiagnosticsMessage (
409- 'Failed to get ACF definitions from database. ' .
293+ 'Failed to get ACF definitions. ' .
410294 'Please ensure that WordPress network is set up properly.<br> ' .
411295 "Exception message: {$ e ->getMessage ()}"
412296 );
413297 }
414-
415- if (false === $ this ->verifyDefinitions ($ localDefinitions , $ dbDefinitions )) {
416- $ url = admin_url ('edit.php?post_type=acf-field-group&page=acf-tools ' );
417- $ msg = [
418- 'ACF Configuration has been changed. ' ,
419- 'Please update groups and fields definitions for all sites (As PHP generated code). ' ,
420- vsprintf ('Use <strong><a href="%s">this</a></strong> page to generate export code and add it to your theme or extra plugin. ' ,
421- [$ url ]),
422- ];
423- DiagnosticsHelper::addDiagnosticsMessage (implode ('<br/> ' , $ msg ));
424- }
425-
426- $ this ->definitions = array_merge ($ localDefinitions , $ dbDefinitions );
427298 $ this ->buildRules ();
428299 $ this ->prepareFilters ();
429300 } else {
@@ -437,6 +308,13 @@ public function run(): void
437308 $ this ->tryRegisterACF ();
438309 }
439310
311+ public function runIfRequired (): void
312+ {
313+ if (count ($ this ->getDefinitions ()) === 0 ) {
314+ $ this ->run ();
315+ }
316+ }
317+
440318 private function prepareFilters (): void
441319 {
442320 $ rules = [];
@@ -468,7 +346,7 @@ private function prepareFilters(): void
468346 }
469347 }
470348
471- static :: $ acfReverseDefinitionAction = $ rules ;
349+ $ this -> filterConfigurations = $ rules ;
472350 }
473351
474352 public function getReplacerIdForField (array $ attributes , string $ key ): ?string
0 commit comments