@@ -72,18 +72,47 @@ public static function applySingleDiff($model, $diff)
7272 $ path = $ diff ->path ;
7373 $ allButLast = $ path ; // This is a copy
7474 $ last = array_pop ($ allButLast );
75- $ isLexValue = false ;
76- if ($ last === 'value ' ) {
77- $ isLexValue = true ;
78- $ last = array_pop ($ allButLast );
79- }
8075 $ target = $ model ;
76+ $ value = $ diff ->getValue ();
77+ $ customFieldsIdx = array_search ('customFields ' , $ allButLast , true );
78+ $ customFieldData = [];
79+ if ($ customFieldsIdx !== false && $ customFieldsIdx +2 <= count ($ path )) {
80+ // Custom fields need special handling
81+ $ allButLast = array_slice ($ path , 0 , $ customFieldsIdx +2 );
82+ $ customFieldName = $ path [$ customFieldsIdx +1 ];
83+ $ rest = array_slice ($ path , $ customFieldsIdx +2 );
84+ foreach (\array_reverse ($ rest ) as $ step ) {
85+ $ customFieldData = [$ step => $ customFieldData ];
86+ }
87+ }
88+ // Custom fields need to call MapOf->generate() with a specific shape in order to work:
89+ // For LexValue fields (list fields with a single value): ['value' => (anything)]
90+ // For LexMultiValue fields (list fields where you can choose multiple values): ['values' => (anything)]
91+ // For LexMultiParagraph fields: ['paragraphs' => (anything)] *or* ['type' => 'multiparagraph']
92+ // For LexMultiText fields: ['en' => ['value' => (anything)]], where any writing system can be in place of 'en' here
93+
94+ // The tricky part is distinguishing LexMultiText fields from LexValue fields, hence the slightly-convoluted construction of $customFieldData
95+
96+ $ prevStep = '' ;
8197 foreach ($ allButLast as $ step ) {
82- $ target = static ::getNextStep ($ target , $ step );
98+ if ($ prevStep === 'customFields ' ) {
99+ $ target = static ::getCustomFieldStep ($ target , $ step , $ customFieldData );
100+ } else {
101+ $ target = static ::getNextStep ($ target , $ step , $ last , $ value );
102+ }
103+ if ($ target instanceof \Api \Model \Languageforge \Lexicon \LexMultiText && $ last === 'value ' ) {
104+ // For MultiText fields, we need $last to be NEXT-to-last step (the writing system), not "value"
105+ $ last = $ path [count ($ path ) - 2 ];
106+ // $last = $step;
107+ break ;
108+ }
109+ // For a custom single-line MultiText field: [customFields, cf_entry_Cust_Single_Line, en, value] and value is "what was typed"
110+ // For a custom list field, [customFields, cf_entry_Cust_Single_ListRef, value] and value is "what was selected"
111+ $ prevStep = $ step ;
83112 }
84113 if ($ diff instanceof ArrayDiff) {
85114 if ($ diff ->item ['kind ' ] == 'N ' ) {
86- static ::pushValue ($ target , $ last , $ diff -> getValue () );
115+ static ::pushValue ($ target , $ last , $ value );
87116 } elseif ($ diff ->item ['kind ' ] == 'D ' ) {
88117 if ($ target instanceof \ArrayObject) {
89118 array_pop ($ target [$ last ]);
@@ -94,25 +123,23 @@ public static function applySingleDiff($model, $diff)
94123 // Invalid ArrayDiff; do nothing
95124 }
96125 } else {
97- static ::setValue ($ target , $ last , $ diff -> getValue () );
126+ static ::setValue ($ target , $ last , $ value );
98127 // TODO: Verify that this works as desired for deletions
99128 }
100129 }
101130
131+ private static function getCustomFieldStep ($ target , $ step , $ customFieldData ) {
132+ if (isset ($ target [$ step ])) {
133+ return $ target [$ step ];
134+ } else {
135+ $ object = $ target ->generate ($ customFieldData );
136+ $ target [$ step ] = $ object ;
137+ return $ object ;
138+ }
139+ }
140+
102141 private static function getNextStep ($ target , $ step ) {
103- if ($ target instanceof \Api \Model \Shared \Mapper \MapOf && strpos ($ step , 'customField_ ' ) === 0 ) {
104- // Custom fields should be created if they do not exist
105- if (isset ($ target [$ step ])) {
106- return $ target [$ step ];
107- } else {
108- if ($ target ->hasGenerator ()) {
109- return $ target ->generate ([$ step ]);
110- } else {
111- // This will probably fail
112- return $ target [$ step ];
113- }
114- }
115- } else if ($ target instanceof \ArrayObject) {
142+ if ($ target instanceof \ArrayObject) {
116143 return $ target [$ step ];
117144 } else {
118145 return $ target ->$ step ;
@@ -122,10 +149,16 @@ private static function getNextStep($target, $step) {
122149 private static function setValue (&$ target , $ last , $ value ) {
123150 if ($ target instanceof \Api \Model \Languageforge \Lexicon \LexMultiText) {
124151 $ target ->form ($ last , $ value );
152+ } else if ($ target instanceof \Api \Model \Languageforge \Lexicon \LexValue) {
153+ $ target ->value ($ value ); // TODO: Test this
125154 } else if ($ target instanceof \ArrayObject) {
126155 $ target [$ last ] = $ value ;
127156 } else {
128- $ target ->$ last = $ value ;
157+ if ($ target ->$ last instanceof \Api \Model \Languageforge \Lexicon \LexValue) {
158+ $ target ->$ last ->value ($ value );
159+ } else {
160+ $ target ->$ last = $ value ;
161+ }
129162 }
130163 }
131164
0 commit comments