-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CRM-7972: Slow Ecommerce widget leads to 40 seconds login (#9087)
- Loading branch information
1 parent
dafc4d4
commit 23a5169
Showing
9 changed files
with
770 additions
and
0 deletions.
There are no files selected for viewing
128 changes: 128 additions & 0 deletions
128
src/Oro/Bridge/MarketingCRM/Provider/AbstractPrecalculatedVisitProvider.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
<?php | ||
|
||
namespace Oro\Bridge\MarketingCRM\Provider; | ||
|
||
use Doctrine\Common\Persistence\ManagerRegistry; | ||
use Doctrine\DBAL\Connection; | ||
use Doctrine\ORM\EntityRepository; | ||
use Doctrine\ORM\NoResultException; | ||
use Doctrine\ORM\QueryBuilder; | ||
use Oro\Bundle\ConfigBundle\Config\ConfigManager; | ||
use Oro\Bundle\FeatureToggleBundle\Checker\FeatureCheckerHolderTrait; | ||
use Oro\Bundle\FeatureToggleBundle\Checker\FeatureToggleableInterface; | ||
use Oro\Bundle\SecurityBundle\ORM\Walker\AclHelper; | ||
use Oro\Bundle\TrackingBundle\Entity\UniqueTrackingVisit; | ||
|
||
class AbstractPrecalculatedVisitProvider implements FeatureToggleableInterface | ||
{ | ||
use FeatureCheckerHolderTrait; | ||
|
||
/** | ||
* @var ManagerRegistry | ||
*/ | ||
private $registry; | ||
|
||
/** | ||
* @var AclHelper | ||
*/ | ||
private $aclHelper; | ||
|
||
/** | ||
* @var ConfigManager | ||
*/ | ||
private $configManager; | ||
|
||
/** | ||
* @param ManagerRegistry $registry | ||
* @param ConfigManager $configManager | ||
* @param AclHelper $aclHelper | ||
*/ | ||
public function __construct( | ||
ManagerRegistry $registry, | ||
ConfigManager $configManager, | ||
AclHelper $aclHelper | ||
) { | ||
$this->registry = $registry; | ||
$this->aclHelper = $aclHelper; | ||
$this->configManager = $configManager; | ||
} | ||
|
||
/** | ||
* @param QueryBuilder $queryBuilder | ||
* @return int | ||
*/ | ||
protected function getSingleIntegerResult(QueryBuilder $queryBuilder) | ||
{ | ||
try { | ||
return (int)$this->aclHelper->apply($queryBuilder)->getSingleScalarResult(); | ||
} catch (NoResultException $ex) { | ||
return 0; | ||
} | ||
} | ||
|
||
/** | ||
* @param QueryBuilder $queryBuilder | ||
* @param \DateTime $from | ||
* @param \DateTime $to | ||
*/ | ||
protected function applyDateLimit(QueryBuilder $queryBuilder, \DateTime $from, \DateTime $to) | ||
{ | ||
if ($from && $to && $this->getDate($from) === $this->getDate($to)) { | ||
$queryBuilder->andWhere($queryBuilder->expr()->eq('t.actionDate', ':date')) | ||
->setParameter('date', $this->getDate($from)); | ||
} else { | ||
if ($from) { | ||
$queryBuilder | ||
->andWhere($queryBuilder->expr()->gte('t.actionDate', ':from')) | ||
->setParameter('from', $this->getDate($from)); | ||
} | ||
if ($to) { | ||
$queryBuilder | ||
->andWhere($queryBuilder->expr()->lte('t.actionDate', ':to')) | ||
->setParameter('to', $this->getDate($to)); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* @return QueryBuilder | ||
*/ | ||
protected function createUniqueVisitQueryBuilder() | ||
{ | ||
$queryBuilder = $this | ||
->getUniqueTrackingVisitRepository() | ||
->createQueryBuilder('t'); | ||
|
||
return $queryBuilder; | ||
} | ||
|
||
/** | ||
* @return bool | ||
*/ | ||
protected function isPrecalculatedStatisticEnabled() | ||
{ | ||
return $this->configManager->get('oro_tracking.precalculated_statistic_enabled'); | ||
} | ||
|
||
/** | ||
* @return EntityRepository | ||
*/ | ||
private function getUniqueTrackingVisitRepository() | ||
{ | ||
return $this->registry->getManagerForClass(UniqueTrackingVisit::class) | ||
->getRepository(UniqueTrackingVisit::class); | ||
} | ||
|
||
/** | ||
* @param \DateTime $dateTime | ||
* @return string | ||
*/ | ||
private function getDate(\DateTime $dateTime) | ||
{ | ||
/** @var Connection $connection */ | ||
$connection = $this->registry->getConnection(); | ||
$dateFormat = $connection->getDatabasePlatform()->getDateFormatString(); | ||
|
||
return $dateTime->format($dateFormat); | ||
} | ||
} |
104 changes: 104 additions & 0 deletions
104
src/Oro/Bridge/MarketingCRM/Provider/PrecalculatedTrackingVisitProvider.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<?php | ||
|
||
namespace Oro\Bridge\MarketingCRM\Provider; | ||
|
||
use Doctrine\ORM\QueryBuilder; | ||
use Oro\Bundle\ChannelBundle\Entity\Channel; | ||
use Oro\Bundle\MagentoBundle\Entity\Customer; | ||
use Oro\Bundle\MagentoBundle\Provider\ChannelType; | ||
use Oro\Bundle\MagentoBundle\Provider\TrackingVisitProviderInterface; | ||
|
||
class PrecalculatedTrackingVisitProvider extends AbstractPrecalculatedVisitProvider implements | ||
TrackingVisitProviderInterface | ||
{ | ||
/** | ||
* @var TrackingVisitProviderInterface | ||
*/ | ||
private $trackingVisitProvider; | ||
|
||
/** | ||
* @param TrackingVisitProviderInterface $trackingVisitProvider | ||
*/ | ||
public function setVisitProvider(TrackingVisitProviderInterface $trackingVisitProvider) | ||
{ | ||
$this->trackingVisitProvider = $trackingVisitProvider; | ||
} | ||
|
||
/** | ||
* Return total number of visits, last visit date and visits per month | ||
* filtered by customers | ||
* | ||
* @param Customer[] $customers | ||
* | ||
* @return array | ||
*/ | ||
public function getAggregates(array $customers) | ||
{ | ||
return $this->trackingVisitProvider->getAggregates($customers); | ||
} | ||
|
||
/** | ||
* @param \DateTime $from | ||
* @param \DateTime $to | ||
* | ||
* @return int | ||
*/ | ||
public function getDeeplyVisitedCount(\DateTime $from = null, \DateTime $to = null) | ||
{ | ||
if (!$this->isPrecalculatedStatisticEnabled()) { | ||
return $this->trackingVisitProvider->getDeeplyVisitedCount($from, $to); | ||
} | ||
|
||
if (!$this->isFeaturesEnabled()) { | ||
return 0; | ||
} | ||
|
||
$queryBuilder = $this->getVisitCountQueryBuilder($from, $to); | ||
$queryBuilder->andHaving('COUNT(t.userIdentifier) > 1'); | ||
|
||
return $this->getSingleIntegerResult($queryBuilder); | ||
} | ||
|
||
/** | ||
* @param \DateTime $from | ||
* @param \DateTime $to | ||
* | ||
* @return int | ||
*/ | ||
public function getVisitedCount(\DateTime $from = null, \DateTime $to = null) | ||
{ | ||
if (!$this->isPrecalculatedStatisticEnabled()) { | ||
return $this->trackingVisitProvider->getVisitedCount($from, $to); | ||
} | ||
|
||
if (!$this->isFeaturesEnabled()) { | ||
return 0; | ||
} | ||
|
||
$queryBuilder = $this->getVisitCountQueryBuilder($from, $to); | ||
|
||
return $this->getSingleIntegerResult($queryBuilder); | ||
} | ||
|
||
/** | ||
* @param \DateTime|null $from | ||
* @param \DateTime|null $to | ||
* @return QueryBuilder | ||
*/ | ||
private function getVisitCountQueryBuilder(\DateTime $from = null, \DateTime $to = null) | ||
{ | ||
$queryBuilder = $this->createUniqueVisitQueryBuilder(); | ||
$this->applyDateLimit($queryBuilder, $from, $to); | ||
|
||
$queryBuilder | ||
->select($queryBuilder->expr()->countDistinct('t.userIdentifier')) | ||
->join('t.trackingWebsite', 'tw') | ||
->join('tw.channel', 'c') | ||
->andWhere($queryBuilder->expr()->eq('c.channelType', ':channel')) | ||
->andWhere($queryBuilder->expr()->eq('c.status', ':status')) | ||
->setParameter('channel', ChannelType::TYPE) | ||
->setParameter('status', Channel::STATUS_ACTIVE); | ||
|
||
return $queryBuilder; | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
src/Oro/Bridge/MarketingCRM/Provider/PrecalculatedWebsiteVisitProvider.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<?php | ||
|
||
namespace Oro\Bridge\MarketingCRM\Provider; | ||
|
||
use Doctrine\ORM\QueryBuilder; | ||
use Oro\Bundle\ChannelBundle\Entity\Channel; | ||
use Oro\Bundle\MagentoBundle\Provider\ChannelType; | ||
use Oro\Bundle\MagentoBundle\Provider\WebsiteVisitProviderInterface; | ||
|
||
class PrecalculatedWebsiteVisitProvider extends AbstractPrecalculatedVisitProvider implements | ||
WebsiteVisitProviderInterface | ||
{ | ||
/** | ||
* @var WebsiteVisitProviderInterface | ||
*/ | ||
private $visitProvider; | ||
|
||
/** | ||
* @param WebsiteVisitProviderInterface $visitProvider | ||
*/ | ||
public function setVisitProvider(WebsiteVisitProviderInterface $visitProvider) | ||
{ | ||
$this->visitProvider = $visitProvider; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getSiteVisitsValues($dateRange) | ||
{ | ||
if (!$this->isPrecalculatedStatisticEnabled()) { | ||
return $this->visitProvider->getSiteVisitsValues($dateRange); | ||
} | ||
|
||
if (!$this->isFeaturesEnabled()) { | ||
return 0; | ||
} | ||
|
||
$queryBuilder = $this->getVisitsCountQueryBuilder($dateRange['start'], $dateRange['end']); | ||
|
||
return $this->getSingleIntegerResult($queryBuilder); | ||
} | ||
|
||
/** | ||
* @param \DateTime|null $from | ||
* @param \DateTime|null $to | ||
* @return QueryBuilder | ||
*/ | ||
private function getVisitsCountQueryBuilder(\DateTime $from = null, \DateTime $to = null) | ||
{ | ||
$queryBuilder = $this->createUniqueVisitQueryBuilder(); | ||
|
||
$queryBuilder->select('SUM(t.visitCount)') | ||
->join('t.trackingWebsite', 'site') | ||
->leftJoin('site.channel', 'channel') | ||
->where($queryBuilder->expr()->orX( | ||
$queryBuilder->expr()->isNull('channel.id'), | ||
$queryBuilder->expr()->andX( | ||
$queryBuilder->expr()->eq('channel.channelType', ':channel'), | ||
$queryBuilder->expr()->eq('channel.status', ':status') | ||
) | ||
)) | ||
->setParameter('channel', ChannelType::TYPE) | ||
->setParameter('status', Channel::STATUS_ACTIVE); | ||
|
||
$this->applyDateLimit($queryBuilder, $from, $to); | ||
|
||
return $queryBuilder; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
41 changes: 41 additions & 0 deletions
41
...Bridge/MarketingCRM/Tests/Functional/DataFixtures/LoadTrackingWebsiteToMagentoChannel.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?php | ||
|
||
namespace Oro\Bridge\MarketingCRM\Tests\Functional\DataFixtures; | ||
|
||
use Doctrine\Common\DataFixtures\AbstractFixture; | ||
use Doctrine\Common\DataFixtures\DependentFixtureInterface; | ||
use Doctrine\Common\Persistence\ObjectManager; | ||
use Oro\Bundle\ChannelBundle\Entity\Channel; | ||
use Oro\Bundle\MagentoBundle\Tests\Functional\Fixture\LoadMagentoChannel; | ||
use Oro\Bundle\TrackingBundle\Entity\TrackingWebsite; | ||
use Oro\Bundle\TrackingBundle\Tests\Functional\DataFixtures\LoadTrackingWebsites; | ||
|
||
class LoadTrackingWebsiteToMagentoChannel extends AbstractFixture implements DependentFixtureInterface | ||
{ | ||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getDependencies() | ||
{ | ||
return [ | ||
LoadTrackingWebsites::class, | ||
LoadMagentoChannel::class | ||
]; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function load(ObjectManager $manager) | ||
{ | ||
/** @var TrackingWebsite $website */ | ||
$website = $this->getReference(LoadTrackingWebsites::TRACKING_WEBSITE); | ||
|
||
if (method_exists($website, 'setChannel')) { | ||
/** @var Channel $channel */ | ||
$channel = $this->getReference('default_channel'); | ||
$website->setChannel($channel); | ||
$manager->flush($website); | ||
} | ||
} | ||
} |
Oops, something went wrong.