Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/dev/1.10' into 1.10
Browse files Browse the repository at this point in the history
  • Loading branch information
rgrebenchuk committed Feb 1, 2017
2 parents 53513c5 + e1498b0 commit ad30034
Show file tree
Hide file tree
Showing 20 changed files with 344 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ oro:
per_page.label: Items Per Page By Default
email_threads:
use_threads_in_activities:
label: Display Emails in Activities as
label: Display email conversations in activity lists as
choices:
non_threaded.label: Non-Threaded
threaded.label: Threaded
Expand Down
25 changes: 22 additions & 3 deletions src/Oro/Bundle/AddressBundle/Resources/public/js/address/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,28 @@ define([
},

getSearchableString: function() {
return this.get('country') + ', ' +
this.get('city') + ', ' +
this.get('street') + ' ' + (this.get('street2') || '');
var address = '';

if (this.get('country')) {
address += this.get('country') + ', ';
}
if (this.get('region')) {
address += this.get('region') + ', ';
}
if (this.get('city')) {
address += this.get('city') + ', ';
}
if (this.get('street')) {
address += this.get('street') + ' ';
}
if (this.get('street2')) {
address += this.get('street2') + ' ';
}
if (this.get('postalCode')) {
address += this.get('postalCode') + ', ';
}

return address;
}
});
});
10 changes: 9 additions & 1 deletion src/Oro/Bundle/ApiBundle/Resources/doc/how_to.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ oro_api:
Acme\Bundle\ProductBundle\Product: ~
```
**Attention**: In version 2.0, use:
```yaml
api:
entities:
Acme\Bundle\ProductBundle\Product: ~
```
Turn on API for entity disabled in Resources/config/oro/entity.yml
------------------------------------------------------------------
Expand Down Expand Up @@ -117,7 +125,7 @@ oro_api:
Acme\Bundle\ProductBundle\Product:
actions:
delete:
excluded: true
exclude: true
```

Also, you can use short syntax:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
* Get optimized query builder for count calculation.
*
* @param QueryBuilder $queryBuilder
*
* @return QueryBuilder
* @throws \Exception
*/
Expand All @@ -60,11 +61,9 @@ public function getCountQueryBuilder(QueryBuilder $queryBuilder)
$this->context = null;

return $qb;
} catch (\Exception $e) {
} finally {
// make sure that a link to the context is removed even if an exception occurred
$this->context = null;
// rethrow an exception
throw $e;
}
}

Expand Down Expand Up @@ -159,43 +158,52 @@ protected function addJoins(
$havingAliases = $this->qbTools->getUsedTableAliases($originalQueryParts['having']);
$joinAliases = array_merge($whereAliases, $groupByAliases, $havingAliases);
$joinAliases = array_unique($joinAliases);
$fromQueryPart = $originalQueryParts['from'];
$joinQueryPart = $originalQueryParts['join'];

// this joins cannot be removed outside of this class
$requiredJoinAliases = $joinAliases;

if ($useNonSymmetricJoins) {
$joinAliases = array_merge(
$joinAliases,
$this->getNonSymmetricJoinAliases(
$originalQueryParts['from'],
$originalQueryParts['join'],
$groupByAliases
)
);
}
$rootAliases = array_map(
function ($from) {
return $from->getAlias();
},
$fromQueryPart
);

$joinAliases = $this->addRequiredJoins(
$joinAliases,
$fromQueryPart,
$joinQueryPart,
$groupByAliases,
$useNonSymmetricJoins
);

$requiredJoinAliases = array_intersect(
array_diff($requiredJoinAliases, $rootAliases),
$this->context->getAliases()
);

$collectedAliases = $joinAliases;
$joinAliases = $this->dispatchQueryOptimizationEvent($joinAliases, $requiredJoinAliases);

$rootAliases = [];
/** @var Expr\From $from */
foreach ($originalQueryParts['from'] as $from) {
$rootAliases[] = $from->getAlias();
$joinAliases = array_merge(
$joinAliases,
$this->qbTools->getUsedJoinAliases($originalQueryParts['join'], $joinAliases, $from->getAlias())
// additional check joins after the events in case if events change joins list
if (count($joinAliases) !== count($collectedAliases)) {
$joinAliases = $this->addRequiredJoins(
$requiredJoinAliases,
$fromQueryPart,
$this->removeAliasesFromQueryJoinParts($joinQueryPart, $joinAliases),
$groupByAliases,
$useNonSymmetricJoins
);
}

$allAliases = $this->context->getAliases();
$joinAliases = array_intersect(array_diff(array_unique($joinAliases), $rootAliases), $allAliases);
$requiredJoinAliases = array_intersect(array_diff($requiredJoinAliases, $rootAliases), $allAliases);

$joinAliases = $this->dispatchQueryOptimizationEvent($joinAliases, $requiredJoinAliases);

foreach ($rootAliases as $rootAlias) {
if (!isset($originalQueryParts['join'][$rootAlias])) {
if (!isset($joinQueryPart[$rootAlias])) {
continue;
}
/** @var Expr\Join $join */
foreach ($originalQueryParts['join'][$rootAlias] as $join) {
foreach ($joinQueryPart[$rootAlias] as $join) {
$alias = $join->getAlias();
// To count results number join all tables with inner join and required to tables
if ($join->getJoinType() === Expr\Join::INNER_JOIN || in_array($alias, $joinAliases, true)) {
Expand Down Expand Up @@ -421,6 +429,7 @@ protected function getAssociationType($entityClass, $associationName, $targetEnt
* then them also should be selected as DISTINCT in optimized Query Builder.
*
* @param array $originalQueryParts
*
* @return array
*/
protected function getFieldsToSelect(array $originalQueryParts)
Expand Down Expand Up @@ -452,4 +461,76 @@ protected function getFieldsToSelect(array $originalQueryParts)

return $fieldsToSelect;
}

/**
* Removes list of aliases from original query parts
*
* @param array $originalQueryParts
* @param array $joinAliases
*
* @return array
*/
protected function removeAliasesFromQueryJoinParts(array $originalQueryParts, array $joinAliases)
{
$filteredJoins = [];
foreach ($originalQueryParts as $root => $joins) {
foreach ($joins as $declaration) {
/** @var Expr\Join $name */
$name = $declaration->getAlias();
if (in_array($name, $joinAliases)) {
if (!array_key_exists($root, $filteredJoins)) {
$filteredJoins[$root] = [];
}
$filteredJoins[$root][] = $declaration;
}
}
}

return $filteredJoins;
}

/**
* Collect and add the joins should be added to query
*
* @param array $joinAliases
* @param array $fromQueryPart
* @param array $joinQueryPart
* @param array $groupByAliases
* @param boolean $useNonSymmetricJoins
*
* @return array
*/
protected function addRequiredJoins(
array $joinAliases,
array $fromQueryPart,
array $joinQueryPart,
array $groupByAliases,
$useNonSymmetricJoins
) {
if ($useNonSymmetricJoins) {
$joinAliases = array_merge(
$joinAliases,
$this->getNonSymmetricJoinAliases(
$fromQueryPart,
$joinQueryPart,
$groupByAliases
)
);
}

$rootAliases = [];
/** @var Expr\From $from */
foreach ($fromQueryPart as $from) {
$rootAliases[] = $from->getAlias();
$joinAliases = array_merge(
$joinAliases,
$this->qbTools->getUsedJoinAliases($joinQueryPart, $joinAliases, $from->getAlias())
);
}

$allAliases = $this->context->getAliases();
$joinAliases = array_intersect(array_diff(array_unique($joinAliases), $rootAliases), $allAliases);

return $joinAliases;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
use Doctrine\ORM\Query\Expr\Join;
use Doctrine\ORM\QueryBuilder;

use Symfony\Component\EventDispatcher\EventDispatcherInterface;

use Oro\Component\TestUtils\ORM\Mocks\EntityManagerMock;
use Oro\Component\TestUtils\ORM\OrmTestCase;
use Oro\Bundle\BatchBundle\Event\CountQueryOptimizationEvent;
use Oro\Bundle\BatchBundle\ORM\QueryBuilder\CountQueryBuilderOptimizer;

class CountQueryBuilderOptimizerTest extends OrmTestCase
Expand Down Expand Up @@ -534,4 +537,132 @@ public static function createQueryBuilder(EntityManager $entityManager)
{
return new QueryBuilder($entityManager);
}

/**
* @dataProvider getCountQueryBuilderDataProviderWithEventDispatcher
*
* @param callback $queryBuilder
* @param array $joinsToDelete
* @param string $expectedDql
*/
public function testGetCountQueryBuilderWithEventDispatcher($queryBuilder, array $joinsToDelete, $expectedDql)
{
$optimizer = new CountQueryBuilderOptimizer();
$eventDispatcher = $this->getMockBuilder(EventDispatcherInterface::class)->getMock();
$eventDispatcher->expects($this->once())
->method('dispatch')
->willReturnCallback(
function ($eventName, CountQueryOptimizationEvent $event) use ($joinsToDelete) {
if (count($joinsToDelete)) {
foreach ($joinsToDelete as $deletedJoin) {
$event->removeJoinFromOptimizedQuery($deletedJoin);
}
}
}
);
$optimizer->setEventDispatcher($eventDispatcher);
$countQb = $optimizer->getCountQueryBuilder(call_user_func($queryBuilder, $this->em));

$this->assertInstanceOf('Doctrine\ORM\QueryBuilder', $countQb);
// Check for expected DQL
$this->assertEquals($expectedDql, $countQb->getQuery()->getDQL());
// Check that Optimized DQL can be converted to SQL
$this->assertNotEmpty($countQb->getQuery()->getSQL());
}

public function getCountQueryBuilderDataProviderWithEventDispatcher()
{
return [
'delete_one_join_table' => [
'queryBuilder' => function ($em) {
return self::createQueryBuilder($em)
->from('Test:User', 'u')
->leftJoin('u.businessUnits', 'bu', Join::WITH, 'bu.id = 456')
->leftJoin('bu.users', 'o', Join::WITH, 'o.id = 123')
->select('u.id, o.username');
},
['o'],
'expectedDQL' => 'SELECT u.id FROM Test:User u '
. 'LEFT JOIN u.businessUnits bu WITH bu.id = 456'
],
'request_with_3th_join_table_without_deleting' => [
'queryBuilder' => function ($em) {
return self::createQueryBuilder($em)
->from('Test:User', 'u')
->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456')
->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123')
->select('u.id, o.username');
},
[],
'expectedDQL' => 'SELECT u.id FROM Test:User u '
. 'LEFT JOIN u.organization o WITH o.id = 456 '
. 'LEFT JOIN o.businessUnits businessUnits WITH businessUnits.id = 123'
],
'request_with_3th_join_table_delete_main_join_table' => [
'queryBuilder' => function ($em) {
return self::createQueryBuilder($em)
->from('Test:User', 'u')
->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456')
->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123')
->select('u.id, o.username');
},
['o'],
'expectedDQL' => 'SELECT u.id FROM Test:User u LEFT '
. 'JOIN u.organization o WITH o.id = 456 '
. 'LEFT JOIN o.businessUnits businessUnits WITH businessUnits.id = 123'
],
'request_with_3th_join_table_delete_3th_join_table' => [
'queryBuilder' => function ($em) {
return self::createQueryBuilder($em)
->from('Test:User', 'u')
->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456')
->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123')
->select('u.id, o.username');
},
['businessUnits'],
'expectedDQL' => 'SELECT u.id FROM Test:User u'
],
'request_with_2_3th_join_tables_without_deleting' => [
'queryBuilder' => function ($em) {
return self::createQueryBuilder($em)
->from('Test:User', 'u')
->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456')
->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123')
->leftJoin('o.users', 'users', Join::WITH, 'users.id = 123')
->select('u.id, o.username');
},
[],
'expectedDQL' => 'SELECT u.id FROM Test:User u '
. 'LEFT JOIN u.organization o WITH o.id = 456 '
. 'LEFT JOIN o.businessUnits businessUnits WITH businessUnits.id = 123 '
. 'LEFT JOIN o.users users WITH users.id = 123'
],
'request_with_2_3th_join_tables_delete_3th_join_table' => [
'queryBuilder' => function ($em) {
return self::createQueryBuilder($em)
->from('Test:User', 'u')
->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456')
->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123')
->leftJoin('o.users', 'users', Join::WITH, 'users.id = 123')
->select('u.id, o.username');
},
['businessUnits'],
'expectedDQL' => 'SELECT u.id FROM Test:User u '
. 'LEFT JOIN u.organization o WITH o.id = 456 '
. 'LEFT JOIN o.users users WITH users.id = 123'
],
'request_with_2_3th_join_tables_delete_both_3th_join_table' => [
'queryBuilder' => function ($em) {
return self::createQueryBuilder($em)
->from('Test:User', 'u')
->leftJoin('u.organization', 'o', Join::WITH, 'o.id = 456')
->leftJoin('o.businessUnits', 'businessUnits', Join::WITH, 'businessUnits.id = 123')
->leftJoin('o.users', 'users', Join::WITH, 'users.id = 123')
->select('u.id, o.username');
},
['businessUnits', 'users'],
'expectedDQL' => 'SELECT u.id FROM Test:User u'
]
];
}
}
Loading

0 comments on commit ad30034

Please sign in to comment.