-
Notifications
You must be signed in to change notification settings - Fork 81
IBX-11083: Extending collaboration described in Developer Documentation #3055
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
39800ae
b5b738a
d2add64
631bdb3
96811d7
70284f9
bd800f0
d0e3c85
42ede63
22dab12
efe4ef4
8eb1654
6071a92
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # This file is the entry point to configure your own services. | ||
| # Files in the packages/ subdirectory configure your dependencies. | ||
|
|
||
| # Put parameters here that don't need to change on each machine where the app is deployed | ||
| # https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration | ||
| parameters: | ||
|
|
||
| services: | ||
| # default configuration for services in *this* file | ||
| _defaults: | ||
| autowire: true # Automatically injects dependencies in your services. | ||
| autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. | ||
|
|
||
| # makes classes in src/ available to be used as services | ||
| # this creates a service per class whose id is the fully-qualified class name | ||
| App\: | ||
| resource: '../src/' | ||
|
|
||
| # add more service definitions when explicit configuration is needed | ||
| # please note that last definitions always *replace* previous ones | ||
|
|
||
| App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway: | ||
| arguments: | ||
| $connection: '@ibexa.persistence.connection' | ||
| tags: | ||
| - name: 'ibexa.collaboration.persistence.session.gateway' | ||
| discriminator: !php/const App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway::DISCRIMINATOR | ||
|
|
||
| App\Collaboration\Cart\Persistence\Mapper: | ||
| tags: | ||
| - name: 'ibexa.collaboration.persistence.session.mapper' | ||
| discriminator: !php/const App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway::DISCRIMINATOR | ||
|
|
||
| App\Collaboration\Cart\Mapper\CartSessionDomainMapper: | ||
| tags: | ||
| - name: 'ibexa.collaboration.service.session.domain.mapper' | ||
| type: App\Collaboration\Cart\Persistence\Values\CartSession | ||
|
|
||
| App\Collaboration\Cart\Mapper\CartSessionPersistenceMapper: | ||
| tags: | ||
| - name: 'ibexa.collaboration.service.session.persistence.mapper' | ||
| type: !php/const App\Collaboration\Cart\CartSessionType::IDENTIFIER | ||
|
|
||
| App\Collaboration\Cart\PermissionResolverDecorator: | ||
| decorates: Ibexa\Contracts\ProductCatalog\PermissionResolverInterface | ||
|
|
||
| App\Collaboration\Cart\CartResolverDecorator: | ||
| decorates: Ibexa\Contracts\Cart\CartResolverInterface |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| CREATE TABLE ibexa_collaboration_cart ( | ||
| id INT NOT NULL PRIMARY KEY, | ||
| cart_identifier VARCHAR(255) NOT NULL, | ||
| CONSTRAINT ibexa_collaboration_cart_ibexa_collaboration_id_fk | ||
| FOREIGN KEY (id) REFERENCES ibexa_collaboration (id) | ||
| ON DELETE CASCADE | ||
| ) COLLATE = utf8mb4_general_ci; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| CREATE TABLE ibexa_collaboration_cart ( | ||
| id INTEGER NOT NULL PRIMARY KEY, | ||
| cart_identifier VARCHAR(255) NOT NULL, | ||
|
Check warning on line 3 in code_samples/collaboration/ibexa_collaboration_cart.postgresql.sql
|
||
| CONSTRAINT ibexa_collaboration_cart_ibexa_collaboration_id_fk | ||
| FOREIGN KEY (id) REFERENCES ibexa_collaboration (id) | ||
| ON DELETE CASCADE | ||
| ); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\Collaboration\Cart; | ||
|
|
||
| use Ibexa\Contracts\Cart\CartResolverInterface; | ||
| use Ibexa\Contracts\Cart\Value\CartInterface; | ||
| use Ibexa\Contracts\Collaboration\SessionServiceInterface; | ||
| use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException; | ||
| use Ibexa\Contracts\Core\Repository\Values\User\User; | ||
| use Symfony\Component\HttpFoundation\RequestStack; | ||
|
|
||
| final readonly class CartResolverDecorator implements CartResolverInterface | ||
| { | ||
| public function __construct( | ||
| private CartResolverInterface $innerCartResolver, | ||
| private SessionServiceInterface $sessionService, | ||
| private RequestStack $requestStack | ||
| ) { | ||
| } | ||
|
|
||
| public function resolveCart(?User $user = null): CartInterface | ||
| { | ||
| if ($this->hasSharedCart()) { | ||
| return $this->getSharedCart() ?? $this->innerCartResolver->resolveCart($user); | ||
| } | ||
|
|
||
| return $this->innerCartResolver->resolveCart($user); | ||
| } | ||
|
|
||
| private function getSharedCart(): ?CartInterface | ||
| { | ||
| try { | ||
| $session = $this->sessionService->getSessionByToken( | ||
| $this->requestStack->getSession()->get(PermissionResolverDecorator::COLLABORATION_SESSION_ID) | ||
| ); | ||
|
|
||
| if (!$session instanceof CartSession) { | ||
| return null; | ||
| } | ||
|
|
||
| return $session->getCart(); | ||
| } catch (NotFoundException|\Ibexa\ProductCatalog\Exception\UnauthorizedException) { | ||
|
Check failure on line 42 in code_samples/collaboration/src/Collaboration/Cart/CartResolverDecorator.php
|
||
| return null; | ||
| } | ||
| } | ||
|
|
||
| private function hasSharedCart(): bool | ||
| { | ||
| return $this->requestStack->getSession()->has(PermissionResolverDecorator::COLLABORATION_SESSION_ID); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\Collaboration\Cart; | ||
|
|
||
| use DateTimeInterface; | ||
| use Ibexa\Contracts\Cart\Value\CartInterface; | ||
| use Ibexa\Contracts\Collaboration\Participant\ParticipantCollectionInterface; | ||
| use Ibexa\Contracts\Collaboration\Session\AbstractSession; | ||
| use Ibexa\Contracts\Core\Repository\Values\User\User; | ||
|
|
||
| final class CartSession extends AbstractSession | ||
| { | ||
| public function __construct( | ||
| int $id, | ||
| private readonly CartInterface $cart, | ||
| string $token, | ||
| User $owner, | ||
| ParticipantCollectionInterface $participants, | ||
| bool $isActive, | ||
| bool $hasPublicLink, | ||
| DateTimeInterface $createdAt, | ||
| DateTimeInterface $updatedAt | ||
| ) { | ||
|
Check warning on line 23 in code_samples/collaboration/src/Collaboration/Cart/CartSession.php
|
||
| parent::__construct($id, $token, $owner, $participants, $isActive, $hasPublicLink, $createdAt, $updatedAt); | ||
| } | ||
|
|
||
| public function getCart(): CartInterface | ||
| { | ||
| return $this->cart; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\Collaboration\Cart; | ||
|
|
||
| use Ibexa\Contracts\Cart\Value\CartInterface; | ||
| use Ibexa\Contracts\Collaboration\Session\AbstractSessionCreateStruct; | ||
|
|
||
| final class CartSessionCreateStruct extends AbstractSessionCreateStruct | ||
| { | ||
| public function __construct(private CartInterface $cart) | ||
| { | ||
| parent::__construct(); | ||
| } | ||
|
|
||
| public function getCart(): CartInterface | ||
| { | ||
| return $this->cart; | ||
| } | ||
|
|
||
| public function setCart(CartInterface $cart): void | ||
| { | ||
| $this->cart = $cart; | ||
| } | ||
|
|
||
| public function getType(): string | ||
| { | ||
| return CartSessionType::IDENTIFIER; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\Collaboration\Cart; | ||
|
|
||
| use Ibexa\Contracts\Collaboration\Session\SessionScopeInterface; | ||
|
|
||
| final class CartSessionType implements SessionScopeInterface | ||
| { | ||
| public const string SCOPE_VIEW = 'view'; | ||
| public const string SCOPE_EDIT = 'edit'; | ||
|
|
||
| public const string IDENTIFIER = 'cart'; | ||
|
|
||
| private function __construct() | ||
| { | ||
| // This class is not intended to be instantiated | ||
| } | ||
|
|
||
| public function getDefaultScope(): string | ||
| { | ||
| return self::SCOPE_VIEW; | ||
| } | ||
|
|
||
| public function isValidScope(string $scope): bool | ||
| { | ||
| return in_array($scope, $this->getScopes(), true); | ||
| } | ||
|
|
||
| public function getScopes(): array | ||
| { | ||
| return [ | ||
| self::SCOPE_VIEW, | ||
| self::SCOPE_EDIT, | ||
| ]; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\Collaboration\Cart; | ||
|
|
||
| use Ibexa\Contracts\Collaboration\Session\AbstractSessionUpdateStruct; | ||
|
|
||
| final class CartSessionUpdateStruct extends AbstractSessionUpdateStruct | ||
| { | ||
| public function getType(): string | ||
| { | ||
| return CartSessionType::IDENTIFIER; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\Collaboration\Cart\Mapper; | ||
|
|
||
| use Ibexa\Contracts\Cart\CartServiceInterface; | ||
| use Ibexa\Contracts\Cart\Value\CartInterface; | ||
| use Ibexa\Contracts\Core\Repository\Repository; | ||
| use Ibexa\Core\Repository\ProxyFactory\ProxyGeneratorInterface; | ||
| use ProxyManager\Proxy\LazyLoadingInterface; | ||
|
|
||
| final readonly class CartProxyMapper implements CartProxyMapperInterface | ||
| { | ||
| public function __construct( | ||
| private Repository $repository, | ||
| private CartServiceInterface $cartService, | ||
| private ProxyGeneratorInterface $proxyGenerator | ||
|
Check failure on line 16 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php
|
||
| ) { | ||
| } | ||
|
|
||
| public function createCartProxy(string $identifier): CartInterface | ||
| { | ||
| $initializer = function ( | ||
| &$wrappedObject, | ||
| LazyLoadingInterface $proxy, | ||
|
Check warning on line 24 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php
|
||
| $method, | ||
|
Check warning on line 25 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php
|
||
| array $parameters, | ||
|
Check warning on line 26 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php
|
||
| &$initializer | ||
| ) use ($identifier): bool { | ||
| $initializer = null; | ||
| $wrappedObject = $this->repository->sudo(fn (): CartInterface => $this->cartService->getCart($identifier)); | ||
|
|
||
| return true; | ||
| }; | ||
|
|
||
| return $this->proxyGenerator->createProxy(CartInterface::class, $initializer); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\Collaboration\Cart\Mapper; | ||
|
|
||
| use Ibexa\Contracts\Cart\Value\CartInterface; | ||
|
|
||
| interface CartProxyMapperInterface | ||
| { | ||
| public function createCartProxy(string $identifier): CartInterface; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\Collaboration\Cart\Mapper; | ||
|
|
||
| use App\Collaboration\Cart\CartSession; | ||
| use Ibexa\Collaboration\Mapper\Domain\ParticipantCollectionDomainMapperInterface; | ||
| use Ibexa\Collaboration\Mapper\Domain\SessionDomainMapperInterface; | ||
| use Ibexa\Collaboration\Mapper\Domain\UserProxyDomainMapperInterface; | ||
| use Ibexa\Collaboration\Persistence\Values\AbstractSession as SessionData; | ||
| use Ibexa\Contracts\Collaboration\Session\SessionInterface; | ||
|
|
||
| /** | ||
| * @template-implements \Ibexa\Collaboration\Mapper\Domain\SessionDomainMapperInterface< | ||
| * \App\Collaboration\Cart\Persistence\Values\CartSession | ||
| * > | ||
| */ | ||
| final readonly class CartSessionDomainMapper implements SessionDomainMapperInterface | ||
|
Check failure on line 17 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php
|
||
| { | ||
| public function __construct( | ||
| private CartProxyMapperInterface $cartProxyMapper, | ||
| private UserProxyDomainMapperInterface $userDomainMapper, | ||
|
Check failure on line 21 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php
|
||
| private ParticipantCollectionDomainMapperInterface $participantCollectionDomainMapper | ||
|
Check failure on line 22 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php
|
||
| ) { | ||
| } | ||
|
|
||
| /** | ||
| * @param \App\Collaboration\Cart\Persistence\Values\CartSession $data | ||
| */ | ||
| public function fromPersistence(SessionData $data): SessionInterface | ||
|
Check failure on line 29 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php
|
||
| { | ||
| return new CartSession( | ||
| $data->getId(), | ||
| $this->cartProxyMapper->createCartProxy($data->getCartIdentifier()), | ||
| $data->getToken(), | ||
| $this->userDomainMapper->createUserProxy($data->getOwnerId()), | ||
| $this->participantCollectionDomainMapper->createParticipantCollectionProxy($data->getId()), | ||
| $data->isActive(), | ||
| $data->hasPublicLink(), | ||
| $data->getCreatedAt(), | ||
| $data->getUpdatedAt(), | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| <?php declare(strict_types=1); | ||
|
|
||
| namespace App\Collaboration\Cart\Mapper; | ||
|
|
||
| use App\Collaboration\Cart\Persistence\Values\CartSessionCreateStruct; | ||
| use App\Collaboration\Cart\Persistence\Values\CartSessionUpdateStruct; | ||
| use Ibexa\Collaboration\Mapper\Persistence\SessionPersistenceMapperInterface; | ||
| use Ibexa\Collaboration\Persistence\Values\AbstractSessionCreateStruct as PersistenceSessionCreateStruct; | ||
| use Ibexa\Collaboration\Persistence\Values\AbstractSessionUpdateStruct as PersistenceSessionUpdateStruct; | ||
| use Ibexa\Contracts\Collaboration\Session\AbstractSessionCreateStruct as SessionCreateStruct; | ||
| use Ibexa\Contracts\Collaboration\Session\AbstractSessionUpdateStruct as SessionUpdateStruct; | ||
| use Ibexa\Contracts\Collaboration\Session\SessionInterface; | ||
|
|
||
| final class CartSessionPersistenceMapper implements SessionPersistenceMapperInterface | ||
|
Check failure on line 14 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionPersistenceMapper.php
|
||
| { | ||
| /** | ||
| * @param \App\Collaboration\Cart\CartSessionCreateStruct $createStruct | ||
| */ | ||
| public function toPersistenceCreateStruct( | ||
| SessionCreateStruct $createStruct | ||
| ): PersistenceSessionCreateStruct { | ||
|
Check failure on line 21 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionPersistenceMapper.php
|
||
| $token = $createStruct->getToken(); | ||
| $owner = $createStruct->getOwner(); | ||
| $hasPublicLink = $createStruct->hasPublicLink(); | ||
|
|
||
| assert($token !== null); | ||
| assert($owner !== null); | ||
| assert($hasPublicLink !== null); | ||
|
|
||
| return new CartSessionCreateStruct( | ||
| $token, | ||
| $createStruct->getCart()->getIdentifier(), | ||
| $owner->getUserId(), | ||
| $createStruct->isActive(), | ||
| $hasPublicLink, | ||
| new \DateTimeImmutable(), | ||
| new \DateTimeImmutable() | ||
| ); | ||
| } | ||
|
|
||
| public function toPersistenceUpdateStruct( | ||
| SessionInterface $session, | ||
| SessionUpdateStruct $updateStruct | ||
| ): PersistenceSessionUpdateStruct { | ||
|
Check failure on line 44 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionPersistenceMapper.php
|
||
| return new CartSessionUpdateStruct( | ||
| $session->getId(), | ||
| $updateStruct->getToken(), | ||
| ($updateStruct->getOwner() ?? $session->getOwner())->getUserId() | ||
| ); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dependency ignored in following #3093
Still, PhpStorm doesn't like the use of a class tagged as
@internal