2121
2222namespace Drupal \json_forms \Form \Control \Rule ;
2323
24- use Drupal \json_forms \Form \Control \Util \FormPropertyUtil ;
25- use Drupal \json_forms \JsonForms \ScopePointer ;
26-
24+ use Drupal \json_forms \JsonForms \Definition \Control \ObjectControlDefinition ;
25+ use Drupal \json_forms \JsonForms \Definition \DefinitionInterface ;
26+ use Drupal \json_forms \JsonForms \Definition \Layout \LayoutDefinition ;
27+
28+ /**
29+ * This class tries to create a Drupal states array from a JSON Forms rule.
30+ * Though, not everything in a condition schema can be mapped to Drupal
31+ * functionality.
32+ *
33+ * Note: In JSON Forms controls inside of arrays cannot reference properties
34+ * outside of that array.
35+ * See: https://github.com/eclipsesource/jsonforms/issues/2094.
36+ *
37+ * @see https://jsonforms.io/docs/uischema/rules
38+ * @see https://www.drupal.org/docs/drupal-apis/form-api/conditional-form-fields
39+ */
2740final class StatesArrayFactory implements StatesArrayFactoryInterface {
2841
2942 private StatesBuilder $ statesBuilder ;
@@ -35,49 +48,72 @@ public function __construct() {
3548 /**
3649 * @phpstan-return array<string, mixed>
3750 */
38- public function createStatesArray (\stdClass $ rule ): array {
51+ public function createStatesArray (DefinitionInterface $ definition ): array {
52+ $ rule = $ definition ->getRule ();
53+ if (NULL === $ rule ) {
54+ return [];
55+ }
56+
57+ $ rootDefinition = $ definition ->getRootDefinition ();
58+ if ($ rootDefinition instanceof ObjectControlDefinition) {
59+ $ rootDefinition = $ rootDefinition ->getLayoutDefinition ();
60+ }
61+ elseif (!$ rootDefinition instanceof LayoutDefinition) {
62+ return [];
63+ }
64+
3965 $ this ->statesBuilder ->clear ();
4066 $ this ->addStates (
4167 $ rule ->effect ,
42- $ this ->getFieldName ($ rule ->condition ->scope ),
43- $ rule ->condition ->schema ,
68+ $ rootDefinition ,
69+ $ rule ->condition ->scope ,
70+ $ rule ->condition ->schema
4471 );
4572
4673 return $ this ->statesBuilder ->toArray ();
4774 }
4875
49- private function getFieldName (string $ scope ): string {
50- return FormPropertyUtil::getFormNameForPropertyPath (ScopePointer::new ($ scope )->getPropertyPath ());
51- }
52-
5376 private function addStates (
5477 string $ effect ,
55- string $ fieldName ,
56- \stdClass $ schema ,
78+ LayoutDefinition $ rootDefinition ,
79+ string $ scope ,
80+ \stdClass $ conditionSchema ,
5781 bool $ negate = FALSE ,
5882 bool $ isContains = FALSE
5983 ): void {
60- if (property_exists ($ schema , 'not ' )) {
61- $ this ->addStates ($ effect , $ fieldName , $ schema ->not , !$ negate , $ isContains );
84+ if (property_exists ($ conditionSchema , 'const ' )) {
85+ $ controlDefinition = $ rootDefinition ->findControlDefinition ($ scope );
86+ if (NULL !== $ controlDefinition ) {
87+ $ this ->statesBuilder ->add ($ effect , $ controlDefinition , $ conditionSchema ->const , $ negate , $ isContains );
88+ }
6289 }
6390
64- if (property_exists ($ schema , 'const ' )) {
65- $ this ->statesBuilder ->add ($ effect , $ fieldName , $ schema ->const , $ negate , $ isContains );
91+ if (property_exists ($ conditionSchema , 'enum ' )) {
92+ $ controlDefinition = $ rootDefinition ->findControlDefinition ($ scope );
93+ if (NULL !== $ controlDefinition ) {
94+ $ this ->statesBuilder ->add ($ effect , $ controlDefinition , $ conditionSchema ->enum , $ negate , $ isContains );
95+ }
6696 }
6797
68- if (property_exists ($ schema , 'enum ' )) {
69- $ this ->statesBuilder -> add ($ effect , $ fieldName , $ schema -> enum , $ negate , $ isContains );
98+ if (property_exists ($ conditionSchema , 'not ' )) {
99+ $ this ->addStates ($ effect , $ rootDefinition , $ scope , $ conditionSchema -> not , ! $ negate , $ isContains );
70100 }
71101
72- if (property_exists ($ schema , 'properties ' )) {
73- foreach ($ schema ->properties as $ property => $ propertySchema ) {
74- $ propertyFieldName = $ fieldName . '[ ' . $ property . '] ' ;
75- $ this ->addStates ($ effect , $ propertyFieldName , $ propertySchema , $ negate , $ isContains );
76- }
102+ if (property_exists ($ conditionSchema , 'contains ' )) {
103+ $ this ->addStates ($ effect , $ rootDefinition , $ scope , $ conditionSchema ->contains , $ negate , TRUE );
77104 }
78105
79- if (property_exists ($ schema , 'contains ' )) {
80- $ this ->addStates ($ effect , $ fieldName , $ schema ->contains , $ negate , TRUE );
106+ if (property_exists ($ conditionSchema , 'properties ' )) {
107+ foreach ($ conditionSchema ->properties as $ property => $ propertyConditionSchema ) {
108+ $ this ->addStates (
109+ $ effect ,
110+ $ rootDefinition ,
111+ "$ scope/properties/ $ property " ,
112+ $ propertyConditionSchema ,
113+ $ negate ,
114+ $ isContains
115+ );
116+ }
81117 }
82118 }
83119
0 commit comments