Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions code_samples/collaboration/config/services.yaml
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
7 changes: 7 additions & 0 deletions code_samples/collaboration/ibexa_collaboration_cart.mysql.sql
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

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use VARCHAR2 instead of VARCHAR.

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZziMS3jnJNlvdrJldDl&open=AZziMS3jnJNlvdrJldDl&pullRequest=3055
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

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

App\Collaboration\Cart\CartResolverDecorator must not depend on Ibexa\ProductCatalog\Exception\UnauthorizedException (CodeSamples on IbexaNotAllowed)
return null;
}
}

private function hasSharedCart(): bool
{
return $this->requestStack->getSession()->has(PermissionResolverDecorator::COLLABORATION_SESSION_ID);
}
}
31 changes: 31 additions & 0 deletions code_samples/collaboration/src/Collaboration/Cart/CartSession.php
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

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

This function has 8 parameters, which is greater than the 7 authorized.

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZxHY5XQMhwzEEUeQ1pi&open=AZxHY5XQMhwzEEUeQ1pi&pullRequest=3055
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

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

App\Collaboration\Cart\Mapper\CartProxyMapper must not depend on Ibexa\Core\Repository\ProxyFactory\ProxyGeneratorInterface (CodeSamples on IbexaNotAllowed)
) {
}

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

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "$proxy".

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZxHY5KnMhwzEEUeQ1pf&open=AZxHY5KnMhwzEEUeQ1pf&pullRequest=3055
$method,

Check warning on line 25 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "$method".

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZxHY5KnMhwzEEUeQ1pg&open=AZxHY5KnMhwzEEUeQ1pg&pullRequest=3055
array $parameters,

Check warning on line 26 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the unused function parameter "$parameters".

See more on https://sonarcloud.io/project/issues?id=ezsystems_developer-documentation&issues=AZxHY5KnMhwzEEUeQ1ph&open=AZxHY5KnMhwzEEUeQ1ph&pullRequest=3055
&$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

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

App\Collaboration\Cart\Mapper\CartSessionDomainMapper must not depend on Ibexa\Collaboration\Mapper\Domain\SessionDomainMapperInterface (CodeSamples on IbexaNotAllowed)
{
public function __construct(
private CartProxyMapperInterface $cartProxyMapper,
private UserProxyDomainMapperInterface $userDomainMapper,

Check failure on line 21 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

App\Collaboration\Cart\Mapper\CartSessionDomainMapper must not depend on Ibexa\Collaboration\Mapper\Domain\UserProxyDomainMapperInterface (CodeSamples on IbexaNotAllowed)
private ParticipantCollectionDomainMapperInterface $participantCollectionDomainMapper

Check failure on line 22 in code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

App\Collaboration\Cart\Mapper\CartSessionDomainMapper must not depend on Ibexa\Collaboration\Mapper\Domain\ParticipantCollectionDomainMapperInterface (CodeSamples on IbexaNotAllowed)
) {
}

/**
* @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

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

App\Collaboration\Cart\Mapper\CartSessionDomainMapper must not depend on Ibexa\Collaboration\Persistence\Values\AbstractSession (CodeSamples on IbexaNotAllowed)
{
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

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

App\Collaboration\Cart\Mapper\CartSessionPersistenceMapper must not depend on Ibexa\Collaboration\Mapper\Persistence\SessionPersistenceMapperInterface (CodeSamples on IbexaNotAllowed)
{
/**
* @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

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

App\Collaboration\Cart\Mapper\CartSessionPersistenceMapper must not depend on Ibexa\Collaboration\Persistence\Values\AbstractSessionCreateStruct (CodeSamples on IbexaNotAllowed)
$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

View workflow job for this annotation

GitHub Actions / Validate code samples (8.3)

App\Collaboration\Cart\Mapper\CartSessionPersistenceMapper must not depend on Ibexa\Collaboration\Persistence\Values\AbstractSessionUpdateStruct (CodeSamples on IbexaNotAllowed)
return new CartSessionUpdateStruct(
$session->getId(),
$updateStruct->getToken(),
($updateStruct->getOwner() ?? $session->getOwner())->getUserId()
);
}
}
Loading
Loading