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 129121b + ba17325 commit 3f8f955
Show file tree
Hide file tree
Showing 11 changed files with 531 additions and 301 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use Oro\Bundle\DataGridBundle\Datagrid\ParameterBag;
use Oro\Bundle\DataGridBundle\Datagrid\Common\DatagridConfiguration;
use Oro\Bundle\DataGridBundle\Event\PreBuild;
use Oro\Bundle\DataGridBundle\Extension\Sorter\OrmSorterExtension;
use Oro\Bundle\FilterBundle\Grid\Extension\OrmFilterExtension;

class CustomerDataGridListener
Expand All @@ -18,7 +17,6 @@ public function onPreBuild(PreBuild $event)
$config = $event->getConfig();
$parameters = $event->getParameters();
$this->addNewsletterSubscribers($config, $parameters);
$this->convertJoinsToSubQueries($config, $parameters);
}

/**
Expand Down Expand Up @@ -79,158 +77,4 @@ protected function addNewsletterSubscribers(DatagridConfiguration $config, Param
];
$config->offsetSetByPath('[source][query]', $query);
}

/**
* @param DatagridConfiguration $config
* @param ParameterBag $parameters
*/
protected function convertJoinsToSubQueries(DatagridConfiguration $config, ParameterBag $parameters)
{
// by a performance reasons, convert some joins to sub-queries
$sorters = $parameters->get(OrmSorterExtension::SORTERS_ROOT_PARAM, []);
if (empty($sorters['channelName'])) {
$this->convertAssociationJoinToSubquery(
$config,
'dataChannel',
'channelName',
'OroCRM\Bundle\ChannelBundle\Entity\Channel'
);
}
if (empty($sorters['websiteName'])) {
$this->convertAssociationJoinToSubquery(
$config,
'cw',
'websiteName',
'OroCRM\Bundle\MagentoBundle\Entity\Website'
);
}
if (empty($sorters['customerGroup'])) {
$this->convertAssociationJoinToSubquery(
$config,
'cg',
'customerGroup',
'OroCRM\Bundle\MagentoBundle\Entity\CustomerGroup'
);
}
}

/**
* @param DatagridConfiguration $config
* @param string $joinAlias
* @param string $columnAlias
* @param string $joinEntityClass
*/
private function convertAssociationJoinToSubquery(
DatagridConfiguration $config,
$joinAlias,
$columnAlias,
$joinEntityClass
) {
list(
$join,
$joinPath,
$selectExpr,
$selectPath
) = $this->findJoinAndSelectByAliases($config, $joinAlias, $columnAlias);
if (!$join || !$selectExpr) {
return;
}

$subQuery = sprintf(
'SELECT %1$s FROM %4$s AS %3$s WHERE %3$s = %2$s',
$selectExpr,
$join['join'],
$joinAlias,
$joinEntityClass
);
if (!empty($join['condition'])) {
$subQuery .= sprintf(' AND %s', $join['condition']);
}

$config->offsetSetByPath($selectPath, sprintf('(%s) AS %s', $subQuery, $columnAlias));
$config->offsetUnsetByPath($joinPath);
}

/**
* @param DatagridConfiguration $config
* @param string $joinAlias
* @param string $columnAlias
*
* @return array [join, join path, select expression without column alias, select item path]
*/
private function findJoinAndSelectByAliases(DatagridConfiguration $config, $joinAlias, $columnAlias)
{
list($join, $joinPath) = $this->findJoinByAlias($config, $joinAlias, '[source][query][join][left]');
$selectExpr = null;
$selectPath = null;
if (null !== $join) {
list($selectExpr, $selectPath) = $this->findSelectExprByAlias($config, $columnAlias);
}

return [$join, $joinPath, $selectExpr, $selectPath];
}

/**
* @param DatagridConfiguration $config
* @param string $joinAlias
* @param string $joinsPath
*
* @return array [join, join path]
*/
private function findJoinByAlias(DatagridConfiguration $config, $joinAlias, $joinsPath)
{
$foundJoin = null;
$foundJoinPath = null;
$joins = $config->offsetGetByPath($joinsPath, []);
foreach ($joins as $key => $join) {
if ($join['alias'] === $joinAlias) {
$foundJoin = $join;
$foundJoinPath = sprintf('%s[%s]', $joinsPath, $key);
break;
}
}

return [$foundJoin, $foundJoinPath];
}

/**
* @param DatagridConfiguration $config
* @param string $columnAlias
*
* @return array [select expression without column alias, select item path]
*/
private function findSelectExprByAlias(DatagridConfiguration $config, $columnAlias)
{
$foundSelectExpr = null;
$foundSelectPath = null;
$pattern = sprintf('#(?P<expr>.+?)\\s+AS\\s+%s#i', $columnAlias);
$selects = $config->offsetGetByPath('[source][query][select]', []);
foreach ($selects as $key => $select) {
if (preg_match($pattern, $select, $matches)) {
$foundSelectExpr = $matches['expr'];
$foundSelectPath = sprintf('[source][query][select][%s]', $key);
break;
}
}

return [$foundSelectExpr, $foundSelectPath];
}

/**
* @param DatagridConfiguration $config
*
* @return string|null
*/
private function getRootAlias(DatagridConfiguration $config)
{
$fromPart = $config->offsetGetByPath('[source][query][from]', []);
if (empty($fromPart)) {
return null;
}
$from = reset($fromPart);

return array_key_exists('alias', $from)
? $from['alias']
: null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,107 +162,4 @@ public function testAddNewsletterSubscribersWhenFilteringByIsSubscriberWasReques
$config->toArray()
);
}

public function testConvertJoinsToSubQueriesWhenSortingWasNotRequested()
{
$parameters = new ParameterBag();

$config = DatagridConfiguration::create(
[
'source' => [
'query' => [
'select' => [
'c.id',
'dataChannel.name as channelName',
'cw.name as websiteName',
'cg.name as customerGroup'
],
'from' => [
['table' => 'OroCRM\Bundle\MagentoBundle\Entity\Customer', 'alias' => 'c']
],
'join' => [
'left' => [
['join' => 'c.dataChannel', 'alias' => 'dataChannel'],
['join' => 'c.website', 'alias' => 'cw'],
['join' => 'c.group', 'alias' => 'cg']
]
]
]
]
]
);

$this->listener->onPreBuild(new PreBuild($config, $parameters));

$this->assertEquals(
[
'source' => [
'query' => [
'select' => [
'c.id',
'(SELECT dataChannel.name FROM OroCRM\Bundle\ChannelBundle\Entity\Channel AS dataChannel'
. ' WHERE dataChannel = c.dataChannel) AS channelName',
'(SELECT cw.name FROM OroCRM\Bundle\MagentoBundle\Entity\Website AS cw'
. ' WHERE cw = c.website) AS websiteName',
'(SELECT cg.name FROM OroCRM\Bundle\MagentoBundle\Entity\CustomerGroup AS cg'
. ' WHERE cg = c.group) AS customerGroup'
],
'from' => [
['table' => 'OroCRM\Bundle\MagentoBundle\Entity\Customer', 'alias' => 'c']
],
'join' => [
'left' => []
]
]
]
],
$config->toArray(['source'])
);
}

public function testConvertJoinsToSubQueriesWhenSortingWasRequested()
{
$parameters = new ParameterBag();
$parameters->set(
'_sort_by',
[
'channelName' => '1',
'websiteName' => '2',
'customerGroup' => '3'
]
);

$config = DatagridConfiguration::create(
[
'source' => [
'query' => [
'select' => [
'c.id',
'dataChannel.name as channelName',
'cw.name as websiteName',
'cg.name as customerGroup'
],
'from' => [
['table' => 'OroCRM\Bundle\MagentoBundle\Entity\Customer', 'alias' => 'c']
],
'join' => [
'left' => [
['join' => 'c.dataChannel', 'alias' => 'dataChannel'],
['join' => 'c.website', 'alias' => 'cw'],
['join' => 'c.group', 'alias' => 'cg']
]
]
]
]
]
);
$originalConfig = $config->toArray(['source']);

$this->listener->onPreBuild(new PreBuild($config, $parameters));

$this->assertEquals(
$originalConfig,
$config->toArray(['source'])
);
}
}

0 comments on commit 3f8f955

Please sign in to comment.