Skip to content

Commit

Permalink
ACP-3963 Algolia Event-Based Features. (#11158)
Browse files Browse the repository at this point in the history
ACP-3963 Algolia Event-Based Features.
  • Loading branch information
vol4onok authored Nov 21, 2024
1 parent 06d7e2b commit 30f6c79
Show file tree
Hide file tree
Showing 18 changed files with 409 additions and 2 deletions.
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"spryker/checkout-extension": "^1.2.0",
"spryker/country": "^3.1.0 || ^4.0.0",
"spryker/customer-extension": "^1.5.0",
"spryker/event-dispatcher-extension": "^1.0.0",
"spryker/gui": "^3.39.0",
"spryker/kernel": "^3.72.0",
"spryker/locale": "^3.0.0 || ^4.0.0",
Expand Down Expand Up @@ -47,6 +48,8 @@
},
"suggest": {
"spryker/checkout": "If you want to use Checkout plugins.",
"spryker/container": "To use EventDispatcher plugins.",
"spryker/event-dispatcher": "To use EventDispatcher plugins.",
"spryker/log": "If you want to use Log plugins.",
"spryker/sales": "If you want customer information in sales."
},
Expand Down
12 changes: 12 additions & 0 deletions src/Spryker/Client/Customer/CustomerClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -577,4 +577,16 @@ public function updateCustomerAddresses(CustomerTransfer $customerTransfer): voi
->createCustomerAddressUpdater()
->updateCustomerAddresses($customerTransfer);
}

/**
* {@inheritDoc}
*
* @api
*
* @return string
*/
public function getUserIdentifier(): string
{
return $this->getFactory()->createSessionCustomerSession()->getUserIdentifier();
}
}
11 changes: 11 additions & 0 deletions src/Spryker/Client/Customer/CustomerClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -447,4 +447,15 @@ public function getCustomerByAccessToken(string $accessToken): CustomerResponseT
* @return void
*/
public function updateCustomerAddresses(CustomerTransfer $customerTransfer): void;

/**
* Specification:
* - Returns logged-in customer identifier.
* - Otherwise, returns an identifier for anonymous from the session.
*
* @api
*
* @return string
*/
public function getUserIdentifier(): string;
}
2 changes: 1 addition & 1 deletion src/Spryker/Client/Customer/CustomerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public function getCustomerSecuredPatternRulePlugins(): array
/**
* @return \Spryker\Client\Session\SessionClientInterface
*/
protected function getSessionClient()
public function getSessionClient()
{
return $this->getProvidedDependency(CustomerDependencyProvider::SERVICE_SESSION);
}
Expand Down
11 changes: 11 additions & 0 deletions src/Spryker/Client/Customer/Session/CustomerSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Generated\Shared\Transfer\CustomerTransfer;
use Spryker\Client\Customer\Exception\EmptyCustomerTransferCacheException;
use Spryker\Client\Session\SessionClientInterface;
use Spryker\Shared\Customer\CustomerConfig;

class CustomerSession implements CustomerSessionInterface
{
Expand Down Expand Up @@ -196,4 +197,14 @@ protected function invalidateCustomerTransferCache(): void
{
static::$customerTransferCache = null;
}

/**
* @return string
*/
public function getUserIdentifier(): string
{
$customerTransfer = $this->getCustomer();

return $customerTransfer ? $customerTransfer->getCustomerReference() : $this->sessionClient->get(CustomerConfig::ANONYMOUS_SESSION_KEY, '');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,9 @@ public function findCustomerRawData(): ?CustomerTransfer;
* @return void
*/
public function markCustomerAsDirty();

/**
* @return string
*/
public function getUserIdentifier(): string;
}
5 changes: 5 additions & 0 deletions src/Spryker/Shared/Customer/CustomerConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@

class CustomerConfig extends AbstractSharedConfig
{
/**
* @var string
*/
public const ANONYMOUS_SESSION_KEY = 'anonymousID';

/**
* @api
*
Expand Down
20 changes: 20 additions & 0 deletions src/Spryker/Yves/Customer/CustomerDependencyProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ class CustomerDependencyProvider extends AbstractBundleDependencyProvider
*/
public const SERVICE_REQUEST_STACK = 'request_stack';

/**
* @var string
*/
public const SERVICE_UTIL_TEXT = 'SERVICE_UTIL_TEXT';

/**
* @param \Spryker\Yves\Kernel\Container $container
*
Expand All @@ -30,6 +35,7 @@ class CustomerDependencyProvider extends AbstractBundleDependencyProvider
public function provideDependencies(Container $container): Container
{
$container = $this->addRequestStackService($container);
$container = $this->addUtilTextService($container);

return $container;
}
Expand All @@ -47,4 +53,18 @@ protected function addRequestStackService(Container $container): Container

return $container;
}

/**
* @param \Spryker\Yves\Kernel\Container $container
*
* @return \Spryker\Yves\Kernel\Container
*/
protected function addUtilTextService(Container $container)
{
$container->set(static::SERVICE_UTIL_TEXT, function (Container $container) {
return $container->getLocator()->utilText()->service();
});

return $container;
}
}
19 changes: 19 additions & 0 deletions src/Spryker/Yves/Customer/CustomerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

namespace Spryker\Yves\Customer;

use Spryker\Service\UtilText\UtilTextServiceInterface;
use Spryker\Yves\Customer\Processor\CurrentCustomerDataRequestLogProcessor;
use Spryker\Yves\Customer\Processor\CurrentCustomerDataRequestLogProcessorInterface;
use Spryker\Yves\Customer\Session\AnonymousIdProvider;
use Spryker\Yves\Customer\Session\AnonymousIdProviderInterface;
use Spryker\Yves\Kernel\AbstractFactory;
use Symfony\Component\HttpFoundation\RequestStack;

Expand All @@ -29,4 +32,20 @@ public function getRequestStackService(): RequestStack
{
return $this->getProvidedDependency(CustomerDependencyProvider::SERVICE_REQUEST_STACK);
}

/**
* @return \Spryker\Yves\Customer\Session\AnonymousIdProviderInterface
*/
public function createAnonymousIdProvider(): AnonymousIdProviderInterface
{
return new AnonymousIdProvider($this->getUtilTextService());
}

/**
* @return \Spryker\Service\UtilText\UtilTextServiceInterface
*/
public function getUtilTextService(): UtilTextServiceInterface
{
return $this->getProvidedDependency(CustomerDependencyProvider::SERVICE_UTIL_TEXT);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/**
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
*/

namespace Spryker\Yves\Customer\Plugin\EventDispatcher;

use Spryker\Service\Container\ContainerInterface;
use Spryker\Shared\Customer\CustomerConfig;
use Spryker\Shared\EventDispatcher\EventDispatcherInterface;
use Spryker\Shared\EventDispatcherExtension\Dependency\Plugin\EventDispatcherPluginInterface;
use Spryker\Yves\Kernel\AbstractPlugin;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
* @method \Spryker\Yves\Customer\CustomerFactory getFactory()
*/
class AnonymousIdSessionAssignEventDispatcherPlugin extends AbstractPlugin implements EventDispatcherPluginInterface
{
/**
* @var int
*/
protected const LISTENER_PRIORITY = 8;

/**
* @param \Spryker\Shared\EventDispatcher\EventDispatcherInterface $eventDispatcher
* @param \Spryker\Service\Container\ContainerInterface $container
*
* @return \Spryker\Shared\EventDispatcher\EventDispatcherInterface
*/
public function extend(EventDispatcherInterface $eventDispatcher, ContainerInterface $container): EventDispatcherInterface
{
$eventDispatcher->addListener(KernelEvents::REQUEST, function (RequestEvent $event) {
if (!$event->isMainRequest()) {
return;
}

$request = $event->getRequest();
$session = $request->getSession();

$anonymousId = $session->get(CustomerConfig::ANONYMOUS_SESSION_KEY);
if ($anonymousId === null) {
$session->set(CustomerConfig::ANONYMOUS_SESSION_KEY, $this->getFactory()->createAnonymousIdProvider()->generateUniqueId());
}
}, static::LISTENER_PRIORITY);

return $eventDispatcher;
}
}
31 changes: 31 additions & 0 deletions src/Spryker/Yves/Customer/Session/AnonymousIdProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

/**
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
*/

namespace Spryker\Yves\Customer\Session;

use Spryker\Service\UtilText\UtilTextServiceInterface;

class AnonymousIdProvider implements AnonymousIdProviderInterface
{
protected UtilTextServiceInterface $utilTextService;

/**
* @param \Spryker\Service\UtilText\UtilTextServiceInterface $utilTextService
*/
public function __construct(UtilTextServiceInterface $utilTextService)
{
$this->utilTextService = $utilTextService;
}

/**
* @return string
*/
public function generateUniqueId(): string
{
return 'anonymous-' . $this->utilTextService->generateRandomString(16);
}
}
16 changes: 16 additions & 0 deletions src/Spryker/Yves/Customer/Session/AnonymousIdProviderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

/**
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
*/

namespace Spryker\Yves\Customer\Session;

interface AnonymousIdProviderInterface
{
/**
* @return string
*/
public function generateUniqueId(): string;
}
77 changes: 77 additions & 0 deletions tests/SprykerTest/Client/Customer/CustomerClientTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php

/**
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
*/

namespace SprykerTest\Client\Customer;

use Codeception\Test\Unit;
use Generated\Shared\Transfer\CustomerTransfer;
use Spryker\Client\Customer\CustomerClient;
use Spryker\Client\Customer\Session\CustomerSession;
use Spryker\Shared\Customer\CustomerConfig;

/**
* Auto-generated group annotations
*
* @group SprykerTest
* @group Client
* @group Customer
* @group CustomerClientTest
* Add your own group annotations below this line
*/
class CustomerClientTest extends Unit
{
/**
* @var \SprykerTest\Client\Customer\CustomerClientTester
*/
protected $tester;

/**
* @return void
*/
public function testGetUserIdentifierReturnsTheAnonymousIdFromTheSession(): void
{
// Arrange
$this->tester->mockFactoryMethod(
'createSessionCustomerSession',
new CustomerSession(
$this->tester->getSessionClientMock([CustomerConfig::ANONYMOUS_SESSION_KEY => 'anonymous:123']),
),
);

$customerClient = new CustomerClient();
$customerClient->setFactory($this->tester->getFactory());

// Act
$userIdentifier = $customerClient->getUserIdentifier();

// Assert
$this->assertSame('anonymous:123', $userIdentifier);
}

/**
* @return void
*/
public function testGetUserIdentifierReturnsTheCustomerReferenceFromTheSession(): void
{
// Arrange
$this->tester->mockFactoryMethod(
'createSessionCustomerSession',
new CustomerSession(
$this->tester->getSessionClientMock([CustomerSession::SESSION_KEY => (new CustomerTransfer())->setCustomerReference('registered:123')]),
),
);

$customerClient = new CustomerClient();
$customerClient->setFactory($this->tester->getFactory());

// Act
$userIdentifier = $customerClient->getUserIdentifier();

// Assert
$this->assertSame('registered:123', $userIdentifier);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
namespace SprykerTest\Client\Customer;

use Codeception\Actor;
use Codeception\Stub;
use Spryker\Client\Session\SessionClientInterface;

/**
* Inherited Methods
Expand All @@ -30,6 +32,16 @@ class CustomerClientTester extends Actor
use _generated\CustomerClientTesterActions;

/**
* Define custom actions here
* @param array $returnedValues
*
* @return \Spryker\Client\Session\SessionClientInterface
*/
public function getSessionClientMock(array $returnedValues = []): SessionClientInterface
{
return Stub::makeEmpty(SessionClientInterface::class, [
'get' => function ($key) use (&$returnedValues) {
return $returnedValues[$key] ?? null;
},
]);
}
}
1 change: 1 addition & 0 deletions tests/SprykerTest/Client/Customer/codeception.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ suites:
- \SprykerTest\Shared\Testify\Helper\Environment
- \SprykerTest\Shared\Testify\Helper\ConfigHelper
- \SprykerTest\Shared\Testify\Helper\LocatorHelper
- \SprykerTest\Client\Testify\Helper\FactoryHelper
Loading

0 comments on commit 30f6c79

Please sign in to comment.