@@ -1333,7 +1333,11 @@ protected function registerVirtualColumnQueryAliases($query, $mainEntityJoinId)
1333
1333
}
1334
1334
$ joinType = $ mapItem ['type ' ];
1335
1335
$ join = $ query ['join ' ][$ joinType ][$ mapItem ['key ' ]];
1336
- $ parentJoinId = $ this ->getParentJoinIdForVirtualColumnJoin ($ join ['join ' ], $ mainEntityJoinId );
1336
+ $ parentJoinId = $ this ->getParentJoinIdForVirtualColumn (
1337
+ $ joinMap ,
1338
+ $ join ['join ' ],
1339
+ $ mainEntityJoinId
1340
+ );
1337
1341
if (null !== $ parentJoinId ) {
1338
1342
$ alias = $ join ['alias ' ];
1339
1343
$ joinId = $ this ->buildJoinIdentifier ($ join , $ parentJoinId , $ joinType );
@@ -1348,7 +1352,8 @@ protected function registerVirtualColumnQueryAliases($query, $mainEntityJoinId)
1348
1352
if (!isset ($ mapItem ['processed ' ])) {
1349
1353
$ joinType = $ mapItem ['type ' ];
1350
1354
$ join = $ query ['join ' ][$ joinType ][$ mapItem ['key ' ]];
1351
- $ parentJoinId = $ this ->getParentJoinIdForVirtualColumnJoin (
1355
+ $ parentJoinId = $ this ->getParentJoinIdForVirtualColumn (
1356
+ $ joinMap ,
1352
1357
$ join ['join ' ],
1353
1358
$ mainEntityJoinId
1354
1359
);
@@ -1374,6 +1379,32 @@ protected function registerVirtualColumnQueryAliases($query, $mainEntityJoinId)
1374
1379
['processed ' => true , 'joinId ' => $ joinId ]
1375
1380
);
1376
1381
unset($ joinMap [$ alias ]);
1382
+
1383
+ /**
1384
+ * It is required to update parentAliases in the map with the new alias,
1385
+ * because there could be a case when one of the joins use another one and in this case
1386
+ * second join alias will start to be invalid after replacement.
1387
+ *
1388
+ * Example of such virtual field con figuration:
1389
+ * select:
1390
+ * expr: defaultContactEmails.email
1391
+ * return_type: string
1392
+ * join:
1393
+ * left:
1394
+ * - { join: entity.defaultContact, alias: defaultContact }
1395
+ * - {
1396
+ * join: defaultContact.emails,
1397
+ * alias: defaultContactEmails,
1398
+ * conditionType: 'WITH',
1399
+ * condition: 'defaultContactEmails.primary = true'
1400
+ * }
1401
+ * Example of $joinMap value for this configuration of the virtual field above:
1402
+ * [
1403
+ * '__tmp1__' => ['['type'=> left, 'key' => 0, 'parentAlias' => t1],
1404
+ * '__tmp2__' => ['['type'=> left, 'key' => 1, 'parentAlias' => __tmp1__],
1405
+ * ]
1406
+ */
1407
+ $ joinMap = $ this ->replaceParentAliasInJoinMapItems ($ joinMap , $ alias , $ newAlias );
1377
1408
}
1378
1409
}
1379
1410
}
@@ -1402,6 +1433,36 @@ protected function findExistingTableAlias($virtualColumnJoinId, $virtualColumnJo
1402
1433
return $ foundAlias ;
1403
1434
}
1404
1435
1436
+ /**
1437
+ * Method added to avoid problem with backward compatibility and will be removed in the next release.
1438
+ * Instead signature of the method:
1439
+ * @see \Oro\Bundle\QueryDesignerBundle\QueryDesigner\AbstractQueryConverter::getParentJoinIdForVirtualColumnJoin
1440
+ * will be changed to fix a bug: $joinMap parameter was not passed to the function but it is used in it to get
1441
+ * correct parent join id from the already processed joins
1442
+ *
1443
+ * @param array $joinMap
1444
+ * @param string $joinExpr
1445
+ * @param string $mainEntityJoinId
1446
+ *
1447
+ * @return string|null
1448
+ */
1449
+ private function getParentJoinIdForVirtualColumn ($ joinMap , $ joinExpr , $ mainEntityJoinId )
1450
+ {
1451
+ $ parentJoinId = $ this ->getParentJoinIdForVirtualColumnJoin ($ joinExpr , $ mainEntityJoinId );
1452
+ if (!$ parentJoinId ) {
1453
+ $ parts = explode ('. ' , $ joinExpr , 2 );
1454
+
1455
+ $ parentAlias = count ($ parts ) === 2
1456
+ ? $ parts [0 ]
1457
+ : null ;
1458
+ if (isset ($ joinMap [$ parentAlias ]['processed ' ])) {
1459
+ $ parentJoinId = $ joinMap [$ parentAlias ]['joinId ' ];
1460
+ }
1461
+ }
1462
+
1463
+ return $ parentJoinId ;
1464
+ }
1465
+
1405
1466
/**
1406
1467
* @param string $joinExpr
1407
1468
* @param string $mainEntityJoinId
@@ -1494,6 +1555,24 @@ protected function replaceTableAliasesInVirtualColumnQuery(&$query, $aliases)
1494
1555
$ query ['select ' ]['expr ' ] = QueryUtils::replaceTableAliasesInSelectExpr ($ query ['select ' ]['expr ' ], $ aliases );
1495
1556
}
1496
1557
1558
+ /**
1559
+ * Actualize parent alias
1560
+ *
1561
+ * @param array $joinMap
1562
+ * @param string $from
1563
+ * @param string $to
1564
+ */
1565
+ private function replaceParentAliasInJoinMapItems (array $ joinMap , string $ from , string $ to ): array
1566
+ {
1567
+ foreach ($ joinMap as &$ mapItem ) {
1568
+ if (isset ($ mapItem ['parentAlias ' ]) && $ mapItem ['parentAlias ' ] === $ from ) {
1569
+ $ mapItem ['parentAlias ' ] = $ to ;
1570
+ }
1571
+ }
1572
+
1573
+ return $ joinMap ;
1574
+ }
1575
+
1497
1576
/**
1498
1577
* Replaces all table aliases declared in the virtual column query with unique aliases for built query
1499
1578
*
0 commit comments