@@ -4996,8 +4996,8 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
49964996
49974997    protected  function  preSaveRelatedRecords (<AdapterInterface> connection, related, <CollectionInterface> visited ) ->  bool
49984998    {
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; 
50015001        let  nesting =  false ;
50025002
50035003        /** 
@@ -5034,17 +5034,6 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
50345034                            " Only objects can be stored as part of belongs-to relations in '"   . get_class(this ) . " ' Relation "   . name
50355035                        );
50365036                    }
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-                     }
50485037
50495038                    /** 
50505039                     * If dynamic update is enabled, saving the record must not take any action 
@@ -5069,7 +5058,18 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
50695058                     * Read the attribute from the referenced model and assign 
50705059                     * it to the current model 
50715060                     */  
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+                     }
50735073                }
50745074            }
50755075        }
@@ -5105,11 +5105,14 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
51055105    protected  function  postSaveRelatedRecords (<AdapterInterface> connection, related, <CollectionInterface> visited ) ->  bool
51065106    {
51075107        var  nesting, className, manager, relation, name, record,
5108-             columns, referencedModel, referencedFields, relatedRecords, value, 
5108+             columns, referencedModel, referencedFields, relatedRecords,
51095109            recordAfter, intermediateModel, intermediateFields,
5110-             intermediateValue,  intermediateModelName,
5111-             intermediateReferencedFields, existingIntermediateModel;
5110+             intermediateModelName,
5111+             intermediateReferencedFields, existingIntermediateModel, columnA, columnB ;
51125112        bool isThrough;
5113+         int  columnCount, referencedFieldsCount, i, j, t;
5114+         string  intermediateConditions;
5115+         array  conditions, placeholders;
51135116
51145117        let  nesting =  false ,
51155118            className =  get_class(this ),
@@ -5144,12 +5147,6 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
51445147                    referencedModel =  relation-> getReferencedModel(),
51455148                    referencedFields =  relation-> getReferencedFields();
51465149
5147-                 if  unlikely  typeof  columns ===  " array"   {
5148-                     connection-> rollback(nesting);
5149- 
5150-                     throw  new  Exception (" Not implemented in '"   . className . " ' on Relation "   . name);
5151-                 }
5152- 
51535150                /** 
51545151                 * Create an implicit array for has-many/has-one records 
51555152                 */  
@@ -5159,18 +5156,6 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
51595156                    let  relatedRecords =  record;
51605157                }
51615158
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-                  */  
51745159                let  isThrough =  (bool) relation-> isThrough();
51755160
51765161                /** 
@@ -5180,7 +5165,36 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
51805165                    let  intermediateModelName =  relation-> getIntermediateModel(),
51815166                        intermediateFields =  relation-> getIntermediateFields(),
51825167                        intermediateReferencedFields =  relation-> getIntermediateReferencedFields();
5168+                     let  placeholders =  [];
5169+                     let  conditions =  [];
51835170
5171+                     /** 
5172+                      * Always check for existing intermediate models 
5173+                      * otherwise conflicts will arise on insert instead of update 
5174+                      */  
5175+                     if  unlikely  typeof  columns ===  " array"   {
5176+                         let  columnCount =  count(columns) -  1 ;
5177+                         for  i in  range(0 , columnCount) {
5178+                             let  columnA =  columns[i];
5179+                             let  conditions[] =  " ["  . intermediateFields[i] . " ] = :APR"   . i . " :"  ,
5180+                             placeholders[" APR"   . i] =  this -> {columnA};
5181+                         }
5182+                         let  i =  columnCount +  1 ;
5183+                     } else  {
5184+                         let  conditions[] =  " ["   . intermediateFields . " ] = :APR0:"  ;
5185+                         let  placeholders[" APR0"  ] =  this -> {columns};
5186+                         let  i =  1 ;
5187+                     }
5188+                     if  unlikely  typeof  referencedFields ===  " array"   {
5189+                         let  referencedFieldsCount =  count(referencedFields) -  1 ;
5190+                         for  j in  range(0 , referencedFieldsCount) {
5191+                             let  t =  j +  i;
5192+                             let  conditions[] =  " ["  . intermediateReferencedFields[j] . " ] = :APR"   . t . " :"  ;
5193+                         }
5194+                     } else  {
5195+                         let  conditions[] =  " ["  . intermediateReferencedFields . " ] = :APR"   . i . " :"  ;
5196+                     }
5197+                     let  intermediateConditions =  join("  AND "  , conditions);
51845198                    for  recordAfter in  relatedRecords {
51855199                        /** 
51865200                         * Save the record and get messages 
@@ -5191,14 +5205,23 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
51915205                             * referenced model 
51925206                             */  
51935207                            this -> appendMessagesFrom(recordAfter);
5194-      
5208+ 
51955209                            /** 
51965210                             * Rollback the implicit transaction 
51975211                             */  
51985212                            connection-> rollback(nesting);
5199-      
5213+ 
52005214                            return  false ;
52015215                        }
5216+                         if  unlikely  typeof  referencedFields ===  " array"   {
5217+                             for  j in  range(0 , referencedFieldsCount) {
5218+                                 let  columnA =  referencedFields[j];
5219+                                 let  t =  j +  i;
5220+                                 let  placeholders[" APR"   . t] =  recordAfter-> {columnA};
5221+                             }
5222+                         } else  {
5223+                             let  placeholders[" APR"   . i] =  recordAfter-> {referencedFields};
5224+                         }
52025225                        /** 
52035226                         * Create a new instance of the intermediate model 
52045227                         */  
@@ -5207,44 +5230,42 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
52075230                        );
52085231
52095232                        /** 
5210-                          * Has-one-through relations can only use one intermediate model. 
52115233                         * If it already exist, it can be updated with the new referenced key. 
52125234                         */  
5213-                         if  relation-> getType() ==  Relation:: HAS_ONE_THROUGH  {
5214-                             let  existingIntermediateModel =  intermediateModel-> findFirst(
5215-                                 [
5216-                                     " ["   . intermediateFields . " ] = ?0"  ,
5217-                                     " bind"  : [value]
5218-                                 ]
5219-                             );
5235+                         let  existingIntermediateModel =  intermediateModel-> findFirst(
5236+                             [
5237+                                 intermediateConditions,
5238+                                 " bind"  : placeholders
5239+                             ]
5240+                         );
52205241
5221-                             if  existingIntermediateModel {
5222-                                 let  intermediateModel =  existingIntermediateModel;
5242+                         if  existingIntermediateModel {
5243+                             let  intermediateModel =  existingIntermediateModel;
5244+                         }
5245+                         if  unlikely  typeof  columns ===  " array"   {
5246+                             for  i in  range(0 , columnCount) {
5247+                                 let  columnA =  columns[i];
5248+                                 let  columnB =  intermediateFields[i];
5249+                                 let  intermediateModel-> {columnB} =  this -> {columnA};
52235250                            }
5251+                         } else  {
5252+                             /** 
5253+                              * Write value in the intermediate model 
5254+                              */  
5255+                             let  intermediateModel-> {intermediateFields} =  this -> {columns};
5256+                         }
5257+                         if  unlikely  typeof  referencedFields ===  " array"   {
5258+                             for  i in  range(0 , referencedFieldsCount) {
5259+                                 let  columnA =  referencedFields[i];
5260+                                 let  columnB =  intermediateReferencedFields[i];
5261+                                 let  intermediateModel-> {columnB} =  recordAfter-> {columnA};
5262+                             }
5263+                         } else  {
5264+                             /** 
5265+                              * Write the intermediate value in the intermediate model 
5266+                              */  
5267+                             let  intermediateModel-> {intermediateReferencedFields} =  recordAfter-> {referencedFields};
52245268                        }
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-                         );
52485269
52495270                        /** 
52505271                         * Save the record and get messages 
@@ -5264,27 +5285,56 @@ abstract class Model extends AbstractInjectionAware implements EntityInterface,
52645285                        }
52655286                    }
52665287                } 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) {
5288+                     if  unlikely  typeof  columns ===  " array"   {
5289+                         let  columnCount =  count(columns) -  1 ;
5290+                         for  recordAfter in  relatedRecords {
5291+                             for  i in  range(0 , columnCount) {
5292+                                 let  columnA =  columns[i];
5293+                                 let  columnB =  referencedFields[i];
5294+                                 let  recordAfter-> {columnB} =  this -> {columnA};
5295+                             }
52765296                            /** 
5277-                              * Get the validation messages generated by the 
5278-                              * referenced model 
5297+                              * Save the record and get messages 
52795298                             */  
5280-                             this -> appendMessagesFrom(recordAfter);
5281-     
5299+                             if  ! recordAfter-> doSave(visited) {
5300+                                 /** 
5301+                                  * Get the validation messages generated by the 
5302+                                  * referenced model 
5303+                                  */  
5304+                                 this -> appendMessagesFrom(recordAfter);
5305+         
5306+                                 /** 
5307+                                  * Rollback the implicit transaction 
5308+                                  */  
5309+                                 connection-> rollback(nesting);
5310+ 
5311+                                 return  false ;
5312+                             }
5313+                         }
5314+                     } else  {
5315+                         for  recordAfter in  relatedRecords {
52825316                            /** 
5283-                              * Rollback  the implicit transaction  
5317+                              * Assign  the value to the  
52845318                             */  
5285-                             connection-> rollback(nesting);
5319+                             let  recordAfter-> {referencedFields} =  this -> {columns};
5320+                             /** 
5321+                              * Save the record and get messages 
5322+                              */  
5323+                             if  ! recordAfter-> doSave(visited) {
52865324
5287-                             return  false ;
5325+                                 /** 
5326+                                  * Get the validation messages generated by the 
5327+                                  * referenced model 
5328+                                  */  
5329+                                 this -> appendMessagesFrom(recordAfter);
5330+         
5331+                                 /** 
5332+                                  * Rollback the implicit transaction 
5333+                                  */  
5334+                                 connection-> rollback(nesting);
5335+ 
5336+                                 return  false ;
5337+                             }
52885338                        }
52895339                    }
52905340                }
0 commit comments