Skip to content

Commit 1090dfd

Browse files
dxopsbelendel
andcommitted
Akeneo PIM OroCommerce Connector
Co-authored-by: Ben <[email protected]>
0 parents  commit 1090dfd

File tree

108 files changed

+9968
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+9968
-0
lines changed

Acl/Voter/CategoryVoter.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
namespace Oro\Bundle\AkeneoBundle\Acl\Voter;
4+
5+
use Oro\Bundle\AkeneoBundle\Integration\AkeneoChannel;
6+
use Oro\Bundle\CatalogBundle\Entity\Category;
7+
use Oro\Bundle\SecurityBundle\Acl\Voter\AbstractEntityVoter;
8+
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
9+
10+
class CategoryVoter extends AbstractEntityVoter
11+
{
12+
const ATTRIBUTE_EDIT = 'EDIT';
13+
14+
/**
15+
* @var Category
16+
*/
17+
protected $object;
18+
19+
/**
20+
* @var array
21+
*/
22+
protected $supportedAttributes = [self::ATTRIBUTE_EDIT];
23+
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
public function vote(TokenInterface $token, $object, array $attributes)
28+
{
29+
$this->object = $object;
30+
31+
return parent::vote($token, $object, $attributes);
32+
}
33+
34+
/**
35+
* {@inheritdoc}
36+
*/
37+
protected function getPermissionForAttribute($class, $identifier, $attribute)
38+
{
39+
if (is_a($this->object, $this->className, true)
40+
&& null !== $this->object->getChannel()
41+
&& AkeneoChannel::TYPE === $this->object->getChannel()->getType()
42+
&& true === $this->object->getChannel()->getTransport()->isAclVoterEnabled()
43+
) {
44+
return self::ACCESS_DENIED;
45+
}
46+
47+
return self::ACCESS_ABSTAIN;
48+
}
49+
}

Async/ImportProductProcessor.php

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
3+
namespace Oro\Bundle\AkeneoBundle\Async;
4+
5+
use Doctrine\ORM\EntityManagerInterface;
6+
use Oro\Bundle\EntityBundle\ORM\DoctrineHelper;
7+
use Oro\Bundle\IntegrationBundle\Authentication\Token\IntegrationTokenAwareTrait;
8+
use Oro\Bundle\IntegrationBundle\Entity\Channel as Integration;
9+
use Oro\Bundle\IntegrationBundle\Provider\SyncProcessorRegistry;
10+
use Oro\Component\MessageQueue\Client\TopicSubscriberInterface;
11+
use Oro\Component\MessageQueue\Consumption\MessageProcessorInterface;
12+
use Oro\Component\MessageQueue\Job\Job;
13+
use Oro\Component\MessageQueue\Job\JobRunner;
14+
use Oro\Component\MessageQueue\Transport\MessageInterface;
15+
use Oro\Component\MessageQueue\Transport\SessionInterface;
16+
use Oro\Component\MessageQueue\Util\JSON;
17+
use Psr\Log\LoggerInterface;
18+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
19+
20+
class ImportProductProcessor implements MessageProcessorInterface, TopicSubscriberInterface
21+
{
22+
use IntegrationTokenAwareTrait;
23+
24+
/** @var DoctrineHelper */
25+
private $doctrineHelper;
26+
27+
/** @var JobRunner */
28+
private $jobRunner;
29+
30+
/** @var LoggerInterface */
31+
private $logger;
32+
33+
/** @var SyncProcessorRegistry */
34+
private $syncProcessorRegistry;
35+
36+
/**
37+
* @param DoctrineHelper $doctrineHelper
38+
* @param JobRunner $jobRunner
39+
* @param TokenStorageInterface $tokenStorage
40+
* @param LoggerInterface $logger
41+
* @param SyncProcessorRegistry $syncProcessorRegistry
42+
*/
43+
public function __construct(
44+
DoctrineHelper $doctrineHelper,
45+
JobRunner $jobRunner,
46+
TokenStorageInterface $tokenStorage,
47+
LoggerInterface $logger,
48+
SyncProcessorRegistry $syncProcessorRegistry
49+
) {
50+
$this->doctrineHelper = $doctrineHelper;
51+
$this->jobRunner = $jobRunner;
52+
$this->tokenStorage = $tokenStorage;
53+
$this->logger = $logger;
54+
$this->syncProcessorRegistry = $syncProcessorRegistry;
55+
}
56+
57+
/**
58+
* {@inheritdoc}
59+
*/
60+
public static function getSubscribedTopics()
61+
{
62+
return [Topics::IMPORT_PRODUCTS];
63+
}
64+
65+
/**
66+
* {@inheritdoc}
67+
*/
68+
public function process(MessageInterface $message, SessionInterface $session)
69+
{
70+
$body = JSON::decode($message->getBody());
71+
$body = array_replace_recursive(['integrationId' => null, 'jobId' => null], $body);
72+
73+
if (!$body['integrationId']) {
74+
$this->logger->critical('The message invalid. It must have integrationId set');
75+
76+
return self::REJECT;
77+
}
78+
79+
/** @var EntityManagerInterface $em */
80+
$em = $this->doctrineHelper->getEntityManagerForClass(Integration::class);
81+
82+
/** @var Integration $integration */
83+
$integration = $em->find(Integration::class, $body['integrationId']);
84+
85+
if (!$integration) {
86+
$this->logger->error(
87+
sprintf('The integration not found: %s', $body['integrationId'])
88+
);
89+
90+
return self::REJECT;
91+
}
92+
if (!$integration->isEnabled()) {
93+
$this->logger->error(
94+
sprintf('The integration is not enabled: %s', $body['integrationId'])
95+
);
96+
97+
return self::REJECT;
98+
}
99+
100+
$this->setTemporaryIntegrationToken($integration);
101+
102+
$result = $this->jobRunner->runDelayed(
103+
$body['jobId'],
104+
function (JobRunner $jobRunner, Job $child) use ($integration, $body) {
105+
$this->doctrineHelper->refreshIncludingUnitializedRelations($integration);
106+
$processor = $this->syncProcessorRegistry->getProcessorForIntegration($integration);
107+
$status = $processor->process(
108+
$integration,
109+
$body['connector'] ?? null,
110+
$body['connector_parameters'] ?? []
111+
);
112+
113+
return $status;
114+
}
115+
);
116+
117+
return $result ? self::ACK : self::REJECT;
118+
}
119+
}

Async/Topics.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Oro\Bundle\AkeneoBundle\Async;
4+
5+
class Topics
6+
{
7+
const IMPORT_PRODUCTS = 'oro_akeneo.importexport.product';
8+
}

Client/AkeneoClientFactory.php

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
<?php
2+
3+
namespace Oro\Bundle\AkeneoBundle\Client;
4+
5+
use Akeneo\PimEnterprise\ApiClient\AkeneoPimEnterpriseClient;
6+
use Akeneo\PimEnterprise\ApiClient\AkeneoPimEnterpriseClientBuilder;
7+
use Oro\Bundle\AkeneoBundle\Encoder\Crypter;
8+
use Oro\Bundle\AkeneoBundle\Entity\AkeneoSettings;
9+
use Oro\Bundle\EntityBundle\ORM\DoctrineHelper;
10+
11+
class AkeneoClientFactory
12+
{
13+
const MASTER_CHANNEL_NAME = 'master';
14+
15+
/**
16+
* @var Crypter
17+
*/
18+
private $crypter;
19+
20+
/**
21+
* @var string
22+
*/
23+
private $akeneoUrl;
24+
25+
/**
26+
* @var string
27+
*/
28+
private $clientId;
29+
30+
/**
31+
* @var string
32+
*/
33+
private $secret;
34+
35+
/**
36+
* @var string
37+
*/
38+
private $userName;
39+
40+
/**
41+
* @var string
42+
*/
43+
private $password;
44+
45+
/**
46+
* @var string
47+
*/
48+
private $token;
49+
50+
/**
51+
* @var string
52+
*/
53+
private $refreshToken;
54+
55+
/**
56+
* @var AkeneoPimEnterpriseClient
57+
*/
58+
private $client;
59+
60+
/**
61+
* @var AkeneoSettings
62+
*/
63+
private $akeneoSettings;
64+
65+
/**
66+
* @var DoctrineHelper
67+
*/
68+
private $doctrineHelper;
69+
70+
/**
71+
* AkeneoClientFactory constructor.
72+
*
73+
* @param DoctrineHelper $doctrineHelper
74+
* @param Crypter $crypter
75+
*/
76+
public function __construct(DoctrineHelper $doctrineHelper, Crypter $crypter)
77+
{
78+
$this->doctrineHelper = $doctrineHelper;
79+
$this->crypter = $crypter;
80+
}
81+
82+
/**
83+
* Create Akeneo PIM client instance.
84+
*
85+
* @param AkeneoSettings $akeneoSettings
86+
* @param bool $tokensEnabled
87+
*
88+
* @return AkeneoPimEnterpriseClient
89+
*/
90+
public function getInstance(AkeneoSettings $akeneoSettings, $tokensEnabled = true)
91+
{
92+
$this->initProperties($akeneoSettings);
93+
94+
if ($akeneoSettings->getToken() &&
95+
$akeneoSettings->getTokenExpiryDateTime() &&
96+
$akeneoSettings->getTokenExpiryDateTime() > new \DateTime('now') &&
97+
true === $tokensEnabled
98+
) {
99+
$this->createClientByToken();
100+
} else {
101+
$this->createClient();
102+
}
103+
104+
return $this->client;
105+
}
106+
107+
/**
108+
* Set properties from AkeneoSettings entity.
109+
*
110+
* @param AkeneoSettings $akeneoSettings
111+
*/
112+
private function initProperties(AkeneoSettings $akeneoSettings)
113+
{
114+
$this->akeneoSettings = $akeneoSettings;
115+
$this->akeneoUrl = $akeneoSettings->getUrl();
116+
$this->clientId = $akeneoSettings->getClientId();
117+
$this->secret = $akeneoSettings->getSecret();
118+
$this->userName = $akeneoSettings->getUsername();
119+
$this->password = $this->crypter->getDecryptData($akeneoSettings->getPassword());
120+
$this->token = $akeneoSettings->getToken();
121+
$this->refreshToken = $akeneoSettings->getRefreshToken();
122+
}
123+
124+
/**
125+
* Build client by token.
126+
*
127+
* @return AkeneoPimEnterpriseClient
128+
*/
129+
private function createClientByToken()
130+
{
131+
$clientBuilder = new AkeneoPimEnterpriseClientBuilder($this->akeneoUrl);
132+
$this->client = $clientBuilder->buildAuthenticatedByToken(
133+
$this->clientId,
134+
$this->secret,
135+
$this->token,
136+
$this->refreshToken
137+
);
138+
139+
return $this->client;
140+
}
141+
142+
/**
143+
* Build token by username and password.
144+
*
145+
* @return AkeneoPimEnterpriseClient
146+
*/
147+
private function createClient()
148+
{
149+
$clientBuilder = new AkeneoPimEnterpriseClientBuilder($this->akeneoUrl);
150+
$this->client = $clientBuilder->buildAuthenticatedByPassword(
151+
$this->clientId,
152+
$this->secret,
153+
$this->userName,
154+
$this->password
155+
);
156+
157+
if ($this->akeneoSettings->getId()) {
158+
$this->persistTokens();
159+
}
160+
161+
return $this->client;
162+
}
163+
164+
/**
165+
* Persist authentication tokens.
166+
*/
167+
private function persistTokens()
168+
{
169+
$this->client->getCategoryApi()->get(self::MASTER_CHANNEL_NAME);
170+
$this->akeneoSettings->setToken($this->client->getToken());
171+
$this->akeneoSettings->setRefreshToken($this->client->getRefreshToken());
172+
$this->akeneoSettings->setTokenExpiryDateTime(new \DateTime('now +3590 seconds'));
173+
$em = $this->doctrineHelper->getEntityManager($this->akeneoSettings);
174+
$em->persist($this->akeneoSettings);
175+
$em->flush();
176+
}
177+
}

0 commit comments

Comments
 (0)