@@ -4996,8 +4996,8 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
4996
4996
4997
4997
protected function preSaveRelatedRecords (<AdapterInterface> connection, related, <CollectionInterface> visited ) -> bool
4998
4998
{
4999
- var className, manager, type, relation, columns, referencedFields, nesting, name, record;
5000
-
4999
+ var className, manager, type, relation, columns, referencedFields, nesting, name, record, columnA, columnB ;
5000
+ int columnCount, i;
5001
5001
let nesting = false ;
5002
5002
5003
5003
/**
@@ -5034,17 +5034,6 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
5034
5034
" Only objects can be stored as part of belongs-to relations in '" . get_class(this ) . " ' Relation " . name
5035
5035
);
5036
5036
}
5037
- let columns = relation-> getFields(),
5038
- referencedFields = relation-> getReferencedFields();
5039
- // let columns = relation->getFields(),
5040
- // referencedModel = relation->getReferencedModel(),
5041
- // referencedFields = relation->getReferencedFields();
5042
-
5043
- if unlikely typeof columns === " array" {
5044
- connection-> rollback(nesting);
5045
-
5046
- throw new Exception (" Not implemented in '" . get_class(this ) . " ' Relation " . name);
5047
- }
5048
5037
5049
5038
/**
5050
5039
* If dynamic update is enabled, saving the record must not take any action
@@ -5069,7 +5058,18 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
5069
5058
* Read the attribute from the referenced model and assign
5070
5059
* it to the current model
5071
5060
*/
5072
- let this -> {columns} = record-> readAttribute(referencedFields);
5061
+ let columns = relation-> getFields(),
5062
+ referencedFields = relation-> getReferencedFields();
5063
+ if unlikely typeof columns === " array" {
5064
+ let columnCount = count(columns) - 1 ;
5065
+ for i in range(0 , columnCount) {
5066
+ let columnA = columns[i];
5067
+ let columnB = referencedFields[i];
5068
+ let this -> {columnA} = record-> {columnB};
5069
+ }
5070
+ } else {
5071
+ let this -> {columns} = record-> {referencedFields};
5072
+ }
5073
5073
}
5074
5074
}
5075
5075
}
@@ -5105,11 +5105,14 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
5105
5105
protected function postSaveRelatedRecords (<AdapterInterface> connection, related, <CollectionInterface> visited ) -> bool
5106
5106
{
5107
5107
var nesting, className, manager, relation, name, record,
5108
- columns, referencedModel, referencedFields, relatedRecords, value,
5108
+ columns, referencedModel, referencedFields, relatedRecords,
5109
5109
recordAfter, intermediateModel, intermediateFields,
5110
- intermediateValue, intermediateModelName,
5111
- intermediateReferencedFields, existingIntermediateModel;
5110
+ intermediateModelName,
5111
+ intermediateReferencedFields, existingIntermediateModel, columnA, columnB ;
5112
5112
bool isThrough;
5113
+ int columnCount, referencedFieldsCount, i;
5114
+ string intermediateConditions;
5115
+ array conditions, placeholders;
5113
5116
5114
5117
let nesting = false ,
5115
5118
className = get_class(this ),
@@ -5144,12 +5147,6 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
5144
5147
referencedModel = relation-> getReferencedModel(),
5145
5148
referencedFields = relation-> getReferencedFields();
5146
5149
5147
- if unlikely typeof columns === " array" {
5148
- connection-> rollback(nesting);
5149
-
5150
- throw new Exception (" Not implemented in '" . className . " ' on Relation " . name);
5151
- }
5152
-
5153
5150
/**
5154
5151
* Create an implicit array for has-many/has-one records
5155
5152
*/
@@ -5159,18 +5156,6 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
5159
5156
let relatedRecords = record;
5160
5157
}
5161
5158
5162
- if unlikely ! fetch value, this -> {columns} {
5163
- connection-> rollback(nesting);
5164
-
5165
- throw new Exception (
5166
- " The column '" . columns . " ' needs to be present in the model '" . className . " '"
5167
- );
5168
- }
5169
-
5170
- /**
5171
- * Get the value of the field from the current model
5172
- * Check if the relation is a has-many-to-many
5173
- */
5174
5159
let isThrough = (bool) relation-> isThrough();
5175
5160
5176
5161
/**
@@ -5180,7 +5165,30 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
5180
5165
let intermediateModelName = relation-> getIntermediateModel(),
5181
5166
intermediateFields = relation-> getIntermediateFields(),
5182
5167
intermediateReferencedFields = relation-> getIntermediateReferencedFields();
5183
-
5168
+ if unlikely typeof columns === " array" {
5169
+ let columnCount = count(columns) - 1 ;
5170
+ if relation-> getType() == Relation:: HAS_ONE_THROUGH {
5171
+ let placeholders = [];
5172
+ let conditions = [];
5173
+ for i in range(0 , columnCount) {
5174
+ let columnA = columns[i];
5175
+ let conditions[] = " [" . intermediateFields[i] . " ] = :APR" . i . " :" ,
5176
+ placeholders[" APR" . i] = this -> {columnA};
5177
+ }
5178
+ let intermediateConditions = join(" AND " , conditions);
5179
+ }
5180
+ } else {
5181
+ if relation-> getType() == Relation:: HAS_ONE_THROUGH {
5182
+ let placeholders = [];
5183
+ let intermediateConditions = " [" . intermediateFields . " ] = ?0" ;
5184
+ let placeholders[] = this -> {columns};
5185
+ }
5186
+ }
5187
+ if unlikely typeof referencedFields === " array" {
5188
+ let referencedFieldsCount = count(referencedFields) - 1 ;
5189
+ } else {
5190
+ let referencedFieldsCount = null ;
5191
+ }
5184
5192
for recordAfter in relatedRecords {
5185
5193
/**
5186
5194
* Save the record and get messages
@@ -5213,38 +5221,39 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
5213
5221
if relation-> getType() == Relation:: HAS_ONE_THROUGH {
5214
5222
let existingIntermediateModel = intermediateModel-> findFirst(
5215
5223
[
5216
- " [ " . intermediateFields . " ] = ?0 " ,
5217
- " bind" : [value]
5224
+ intermediateConditions ,
5225
+ " bind" : placeholders
5218
5226
]
5219
5227
);
5220
5228
5221
5229
if existingIntermediateModel {
5222
5230
let intermediateModel = existingIntermediateModel;
5223
5231
}
5224
5232
}
5225
-
5226
- /**
5227
- * Write value in the intermediate model
5228
- */
5229
- intermediateModel-> writeAttribute(
5230
- intermediateFields,
5231
- value
5232
- );
5233
-
5234
- /**
5235
- * Get the value from the referenced model
5236
- */
5237
- let intermediateValue = recordAfter-> readAttribute(
5238
- referencedFields
5239
- );
5240
-
5241
- /**
5242
- * Write the intermediate value in the intermediate model
5243
- */
5244
- intermediateModel-> writeAttribute(
5245
- intermediateReferencedFields,
5246
- intermediateValue
5247
- );
5233
+ if unlikely typeof columns === " array" {
5234
+ for i in range(0 , columnCount) {
5235
+ let columnA = columns[i];
5236
+ let columnB = intermediateFields[i];
5237
+ let intermediateModel-> {columnB} = this -> {columnA};
5238
+ }
5239
+ } else {
5240
+ /**
5241
+ * Write value in the intermediate model
5242
+ */
5243
+ let intermediateModel-> {intermediateFields} = this -> {columns};
5244
+ }
5245
+ if unlikely typeof referencedFields === " array" {
5246
+ for i in range(0 , referencedFieldsCount) {
5247
+ let columnA = referencedFields[i];
5248
+ let columnB = intermediateReferencedFields[i];
5249
+ let intermediateModel-> {columnB} = recordAfter-> {columnA};
5250
+ }
5251
+ } else {
5252
+ /**
5253
+ * Write the intermediate value in the intermediate model
5254
+ */
5255
+ let intermediateModel-> {intermediateReferencedFields} = recordAfter-> {referencedFields};
5256
+ }
5248
5257
5249
5258
/**
5250
5259
* Save the record and get messages
@@ -5264,27 +5273,56 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
5264
5273
}
5265
5274
}
5266
5275
} else {
5267
- for recordAfter in relatedRecords {
5268
- /**
5269
- * Assign the value to the
5270
- */
5271
- recordAfter-> writeAttribute(referencedFields, value);
5272
- /**
5273
- * Save the record and get messages
5274
- */
5275
- if ! recordAfter-> doSave(visited) {
5276
+ if unlikely typeof columns === " array" {
5277
+ let columnCount = count(columns) - 1 ;
5278
+ for recordAfter in relatedRecords {
5279
+ for i in range(0 , columnCount) {
5280
+ let columnA = columns[i];
5281
+ let columnB = referencedFields[i];
5282
+ let recordAfter-> {columnB} = this -> {columnA};
5283
+ }
5276
5284
/**
5277
- * Get the validation messages generated by the
5278
- * referenced model
5285
+ * Save the record and get messages
5279
5286
*/
5280
- this -> appendMessagesFrom(recordAfter);
5281
-
5287
+ if ! recordAfter-> doSave(visited) {
5288
+ /**
5289
+ * Get the validation messages generated by the
5290
+ * referenced model
5291
+ */
5292
+ this -> appendMessagesFrom(recordAfter);
5293
+
5294
+ /**
5295
+ * Rollback the implicit transaction
5296
+ */
5297
+ connection-> rollback(nesting);
5298
+
5299
+ return false ;
5300
+ }
5301
+ }
5302
+ } else {
5303
+ for recordAfter in relatedRecords {
5282
5304
/**
5283
- * Rollback the implicit transaction
5305
+ * Assign the value to the
5284
5306
*/
5285
- connection-> rollback(nesting);
5307
+ let recordAfter-> {referencedFields} = this -> {columns};
5308
+ /**
5309
+ * Save the record and get messages
5310
+ */
5311
+ if ! recordAfter-> doSave(visited) {
5286
5312
5287
- return false ;
5313
+ /**
5314
+ * Get the validation messages generated by the
5315
+ * referenced model
5316
+ */
5317
+ this -> appendMessagesFrom(recordAfter);
5318
+
5319
+ /**
5320
+ * Rollback the implicit transaction
5321
+ */
5322
+ connection-> rollback(nesting);
5323
+
5324
+ return false ;
5325
+ }
5288
5326
}
5289
5327
}
5290
5328
}
0 commit comments