Skip to content
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

Refractor dimension content collection #204

Draft
wants to merge 2 commits into
base: 0.8
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion Content/Application/ContentCopier/ContentCopier.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,6 @@ public function copyFromDimensionContent(
): DimensionContentInterface {
$data = $this->contentNormalizer->normalize($dimensionContent);

return $this->contentPersister->persist($targetContentRichEntity, $data, $targetDimensionAttributes);
return $this->contentPersister->persist($targetContentRichEntity, $targetDimensionAttributes, $data);
}
}
11 changes: 4 additions & 7 deletions Content/Application/ContentDataMapper/ContentDataMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,10 @@ public function map(
$localizedDimensionAttributes = $dimensionAttributes;
$unlocalizedDimensionAttributes = $dimensionAttributes;
$unlocalizedDimensionAttributes['locale'] = null;
$unlocalizedDimensionContent = $dimensionContentCollection->getDimensionContent($unlocalizedDimensionAttributes);
$localizedDimensionContent = $dimensionContentCollection->getDimensionContent($localizedDimensionAttributes);

if (!$unlocalizedDimensionContent || !$localizedDimensionContent) {
// TODO see https://github.com/sulu/SuluContentBundle/pull/204
throw new \RuntimeException('Create unlocalized and localized dimension content.');
}
$unlocalizedDimensionContent = $dimensionContentCollection->getDimensionContent($unlocalizedDimensionAttributes)
?: $dimensionContentCollection->createDimensionContent($unlocalizedDimensionAttributes);
$localizedDimensionContent = $dimensionContentCollection->getDimensionContent($localizedDimensionAttributes)
?: $dimensionContentCollection->createDimensionContent($localizedDimensionAttributes);

foreach ($this->dataMappers as $mapper) {
$mapper->map($unlocalizedDimensionContent, $localizedDimensionContent, $data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ public function map(
$entityClass = null;
$routeSchema = null;
$resourceKey = $localizedDimensionContent::getResourceKey();

foreach ($this->routeMappings as $key => $mapping) {
if ($resourceKey === $mapping['resource_key']) {
$entityClass = $mapping['entityClass'] ?? $key;
Expand Down
5 changes: 3 additions & 2 deletions Content/Application/ContentManager/ContentManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Sulu\Bundle\ContentBundle\Content\Application\ContentResolver\ContentResolverInterface;
use Sulu\Bundle\ContentBundle\Content\Application\ContentWorkflow\ContentWorkflowInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentCollectionInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface;

class ContentManager implements ContentManagerInterface
Expand Down Expand Up @@ -75,9 +76,9 @@ public function resolve(ContentRichEntityInterface $contentRichEntity, array $di
return $this->contentResolver->resolve($contentRichEntity, $dimensionAttributes);
}

public function persist(ContentRichEntityInterface $contentRichEntity, array $data, array $dimensionAttributes): DimensionContentInterface
public function persist(ContentRichEntityInterface $contentRichEntity, array $dimensionAttributes, array $data): DimensionContentCollectionInterface
{
return $this->contentPersister->persist($contentRichEntity, $data, $dimensionAttributes);
return $this->contentPersister->persist($contentRichEntity, $dimensionAttributes, $data);
}

public function normalize(DimensionContentInterface $dimensionContent): array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Sulu\Bundle\ContentBundle\Content\Application\ContentManager;

use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentCollectionInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface;

interface ContentManagerInterface
Expand All @@ -24,10 +25,10 @@ interface ContentManagerInterface
public function resolve(ContentRichEntityInterface $contentRichEntity, array $dimensionAttributes): DimensionContentInterface;

/**
* @param mixed[] $data
* @param mixed[] $dimensionAttributes
* @param mixed[] $data
*/
public function persist(ContentRichEntityInterface $contentRichEntity, array $data, array $dimensionAttributes): DimensionContentInterface;
public function persist(ContentRichEntityInterface $contentRichEntity, array $dimensionAttributes, array $data): DimensionContentCollectionInterface;

/**
* @return mixed[]
Expand Down
28 changes: 1 addition & 27 deletions Content/Application/ContentMerger/ContentMerger.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,6 @@ public function __construct(

public function merge(DimensionContentCollectionInterface $dimensionContentCollection): DimensionContentInterface
{
if (!$dimensionContentCollection->count()) {
throw new \RuntimeException('Expected at least one dimensionContent given.');
}

$mergedDimensionContent = null;

foreach ($dimensionContentCollection as $dimensionContent) {
if (!$mergedDimensionContent) {
$contentRichEntity = $dimensionContent->getResource();
$mergedDimensionContent = $contentRichEntity->createDimensionContent();
$mergedDimensionContent->markAsMerged();
}

foreach ($this->mergers as $merger) {
$merger->merge($mergedDimensionContent, $dimensionContent);
}

foreach ($dimensionContentCollection->getDimensionAttributes() as $key => $value) {
$this->propertyAccessor->setValue(
$mergedDimensionContent,
$key,
$this->propertyAccessor->getValue($dimensionContent, $key)
);
}
}

return $mergedDimensionContent;
return $dimensionContentCollection->getMergedDimensionContent();
}
}
29 changes: 11 additions & 18 deletions Content/Application/ContentPersister/ContentPersister.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@

namespace Sulu\Bundle\ContentBundle\Content\Application\ContentPersister;

use Sulu\Bundle\ContentBundle\Content\Application\ContentMerger\ContentMergerInterface;
use Sulu\Bundle\ContentBundle\Content\Application\ContentDataMapper\ContentDataMapperInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Factory\DimensionContentCollectionFactoryInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentCollectionInterface;

class ContentPersister implements ContentPersisterInterface
{
Expand All @@ -26,34 +26,27 @@ class ContentPersister implements ContentPersisterInterface
private $dimensionContentCollectionFactory;

/**
* @var ContentMergerInterface
* @var ContentDataMapperInterface
*/
private $contentMerger;
private $contentDataMapper;

public function __construct(
DimensionContentCollectionFactoryInterface $dimensionContentCollectionFactory,
ContentMergerInterface $contentMerger
ContentDataMapperInterface $contentDataMapper
) {
$this->dimensionContentCollectionFactory = $dimensionContentCollectionFactory;
$this->contentMerger = $contentMerger;
$this->contentDataMapper = $contentDataMapper;
}

public function persist(ContentRichEntityInterface $contentRichEntity, array $data, array $dimensionAttributes): DimensionContentInterface
public function persist(ContentRichEntityInterface $contentRichEntity, array $dimensionAttributes, array $data): DimensionContentCollectionInterface
{
/*
* Data should always be persisted to the STAGE_DRAFT content-dimension of the given $dimensionAttributes.
* Modifying data of other content-dimensions (eg. STAGE_LIVE) should only be possible by applying transitions
* of the ContentWorkflow.
*
* TODO: maybe throw an exception here if the $dimensionAttributes contain another stage than 'STAGE_DRAFT'
*/

$dimensionContentCollection = $this->dimensionContentCollectionFactory->create(
$contentRichEntity,
$dimensionAttributes,
$data
$dimensionAttributes
);

return $this->contentMerger->merge($dimensionContentCollection);
$this->contentDataMapper->map($dimensionContentCollection, $dimensionAttributes, $data);

return $dimensionContentCollection;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
namespace Sulu\Bundle\ContentBundle\Content\Application\ContentPersister;

use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentCollectionInterface;

interface ContentPersisterInterface
{
/**
* @param mixed[] $data
* @param mixed[] $dimensionAttributes
*/
public function persist(ContentRichEntityInterface $contentRichEntity, array $data, array $dimensionAttributes): DimensionContentInterface;
public function persist(ContentRichEntityInterface $contentRichEntity, array $dimensionAttributes, array $data): DimensionContentCollectionInterface;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,115 +13,45 @@

namespace Sulu\Bundle\ContentBundle\Content\Application\DimensionContentCollectionFactory;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Sulu\Bundle\ContentBundle\Content\Application\ContentDataMapper\ContentDataMapperInterface;
use Sulu\Bundle\ContentBundle\Content\Application\ContentMerger\Merger\MergerInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Factory\DimensionContentCollectionFactoryInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\ContentRichEntityInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentCollection;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentCollectionInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Model\DimensionContentInterface;
use Sulu\Bundle\ContentBundle\Content\Domain\Repository\DimensionContentRepositoryInterface;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;

class DimensionContentCollectionFactory implements DimensionContentCollectionFactoryInterface
{
/**
* @var DimensionContentRepositoryInterface
* @var iterable<MergerInterface>
*/
private $dimensionContentRepository;
private $mergers;

/**
* @var ContentDataMapperInterface
* @var PropertyAccessor
*/
private $contentDataMapper;
private $propertyAccessor;

/**
* @var PropertyAccessorInterface
* @param iterable<MergerInterface> $mergers
*/
private $propertyAccessor;

public function __construct(
DimensionContentRepositoryInterface $dimensionContentRepository,
ContentDataMapperInterface $contentDataMapper,
iterable $mergers,
PropertyAccessor $propertyAccessor
) {
$this->dimensionContentRepository = $dimensionContentRepository;
$this->contentDataMapper = $contentDataMapper;
$this->mergers = $mergers;
$this->propertyAccessor = $propertyAccessor;
}

public function create(
ContentRichEntityInterface $contentRichEntity,
array $dimensionAttributes,
array $data
array $dimensionAttributes
): DimensionContentCollectionInterface {
$dimensionContentCollection = $this->dimensionContentRepository->load($contentRichEntity, $dimensionAttributes);
$dimensionAttributes = $dimensionContentCollection->getDimensionAttributes();

$orderedContentDimensions = \iterator_to_array($dimensionContentCollection);
$dimensionContents = new ArrayCollection($orderedContentDimensions);

$unlocalizedAttributes = $dimensionAttributes;
$unlocalizedAttributes['locale'] = null;

// get or create unlocalized dimension content
$unlocalizedDimensionContent = $dimensionContentCollection->getDimensionContent($unlocalizedAttributes);

if (!$unlocalizedDimensionContent) {
$unlocalizedDimensionContent = $this->createContentDimension(
$contentRichEntity,
$dimensionContents,
$unlocalizedAttributes
);
$orderedContentDimensions[] = $unlocalizedDimensionContent;
}

$localizedDimensionContent = null;
if (isset($dimensionAttributes['locale'])) {
// get or create localized dimension content
$localizedDimensionContent = $dimensionContentCollection->getDimensionContent($dimensionAttributes);

if (!$localizedDimensionContent) {
$localizedDimensionContent = $this->createContentDimension(
$contentRichEntity,
$dimensionContents,
$dimensionAttributes
);
$orderedContentDimensions[] = $localizedDimensionContent;
}
}

$dimensionContentCollection = new DimensionContentCollection(
$orderedContentDimensions,
return new DimensionContentCollection(
$contentRichEntity,
$dimensionAttributes,
$dimensionContentCollection->getDimensionContentClass()
$this->mergers,
$this->propertyAccessor
);

$this->contentDataMapper->map($dimensionContentCollection, $dimensionAttributes, $data);

return $dimensionContentCollection;
}

/**
* @param Collection<int, DimensionContentInterface> $dimensionContents
* @param mixed[] $attributes
*/
private function createContentDimension(
ContentRichEntityInterface $contentRichEntity,
Collection $dimensionContents,
array $attributes
): DimensionContentInterface {
$dimensionContent = $contentRichEntity->createDimensionContent();

foreach ($attributes as $attributeName => $attributeValue) {
$this->propertyAccessor->setValue($dimensionContent, $attributeName, $attributeValue);
}

$contentRichEntity->addDimensionContent($dimensionContent);
$dimensionContents->add($dimensionContent);

return $dimensionContent;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ interface DimensionContentCollectionFactoryInterface
*/
public function create(
ContentRichEntityInterface $contentRichEntity,
array $dimensionAttributes,
array $data
array $dimensionAttributes
): DimensionContentCollectionInterface;
}
11 changes: 11 additions & 0 deletions Content/Domain/Model/ContentRichEntityInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Sulu\Bundle\ContentBundle\Content\Domain\Model;

use Doctrine\Common\Collections\Collection;
use Sulu\Bundle\ContentBundle\Content\Domain\Factory\DimensionContentCollectionFactoryInterface;

interface ContentRichEntityInterface
{
Expand All @@ -27,6 +28,16 @@ public function getId();
*/
public function getDimensionContents(): Collection;

/**
* @param mixed[] $dimensionAttributes
*/
public function findDimensionContent(array $dimensionAttributes): ?DimensionContentInterface;

/**
* @return class-string<DimensionContentInterface>
*/
public static function getDimensionContentClass(): string;

public function createDimensionContent(): DimensionContentInterface;

public function addDimensionContent(DimensionContentInterface $dimensionContent): void;
Expand Down
19 changes: 19 additions & 0 deletions Content/Domain/Model/ContentRichEntityTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;

trait ContentRichEntityTrait
{
Expand All @@ -33,6 +34,24 @@ public function getDimensionContents(): Collection
return $this->dimensionContents;
}

public function findDimensionContent(array $dimensionAttributes): ?DimensionContentInterface
{
$dimensionAttributes = static::getDimensionContentClass()::getEffectiveDimensionAttributes($dimensionAttributes);

$criteria = Criteria::create();
foreach ($dimensionAttributes as $key => $value) {
if (null === $value) {
$expr = $criteria->expr()->isNull($key);
} else {
$expr = $criteria->expr()->eq($key, $value);
}

$criteria->andWhere($expr);
}

return $this->getDimensionContents()->matching($criteria)->first() ?: null;
}

public function addDimensionContent(DimensionContentInterface $dimensionContent): void
{
$this->initializeDimensionContents();
Expand Down
Loading