Skip to content

Instantly share code, notes, and snippets.

@arfaram
Last active October 17, 2021 11:43
Show Gist options
  • Save arfaram/b65f1e7efbfe92ba233b3b6f8515e67e to your computer and use it in GitHub Desktop.
Save arfaram/b65f1e7efbfe92ba233b3b6f8515e67e to your computer and use it in GitHub Desktop.
Creating custom action for Ibexa data migration v3.3.3 with migration bundle v1.0.2 to add locations for content

Content Create:

{ action: assign_content_locations, value: '{"add": [369,153]}' } 

Content Update(NOT SUPPORTED NOW):

{ action: assign_content_locations, value: '{"add": [154],"remove": [369,153]}' }
<?php
declare(strict_types=1);
namespace App\Actions\Location;
use Ibexa\Platform\Migration\ValueObject\Step\Action;
final class AssignContentLocations implements Action
{
public const TYPE = 'assign_content_locations';
/**
* @var string
*/
private $value;
public function __construct(string $value = null)
{
$this->value = $value;
}
/**
* @return string
*/
public function getValue()
{
try {
return \json_decode($this->value, true, 512, JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
throw new \RuntimeException('Value of field `assign_content_locations` has invalid JSON', $e->getCode(), $e);
}
}
public function getSupportedType(): string
{
return self::TYPE;
}
}
<?php
declare(strict_types=1);
namespace App\Actions\Location;
use Ibexa\Platform\Migration\ValueObject\Step\Action;
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Webmozart\Assert\Assert;
/**
*
* Class AssignContentLocationsActionDenormalizer
*
*/
final class AssignContentLocationsActionDenormalizer implements DenormalizerInterface, CacheableSupportsMethodInterface
{
/**
* @var array<string, class-string>
*/
private $map;
/**
* @param array<array{
* action: string,
* class: class-string,
* }> $supportedActions
*/
public function __construct(array $supportedActions)
{
$this->map = $this->mapSupportedActions($supportedActions);
}
private function mapSupportedActions(array $supportedActions): array
{
return array_column($supportedActions, 'class', 'action');
}
public function denormalize($data, string $type, string $format = null, array $context = [])
{
Assert::keyExists($data, 'value');
return new AssignContentLocations($data['value']);
}
public function hasCacheableSupportsMethod(): bool
{
return true;
}
public function supportsDenormalization($data, string $type, string $format = null)
{
return Action::class === $type;
}
}
<?php
declare(strict_types=1);
namespace App\Actions\Location;
use eZ\Publish\API\Repository\ContentService;
use eZ\Publish\API\Repository\LocationService;
use Ibexa\Platform\Migration\ValueObject;
use Ibexa\Platform\Migration\StepExecutor\ActionExecutor\ExecutorInterface;
use eZ\Publish\API\Repository\Values\ValueObject as APIValueObject;
/**
* Usage { action: assign_content_locations, value: '{"add": [369,153],"remove": [153]}'}
*
* Class AssignContentLocationsExecutor
*/
final class AssignContentLocationsExecutor implements ExecutorInterface
{
/*** @var LocationService */
private $locationService;
private ContentService $contentService;
public function __construct(
LocationService $locationService
) {
$this->locationService = $locationService;
}
/**
* @param AssignContentLocations $action
* @param \eZ\Publish\API\Repository\Values\Content\Content $content
*/
public function handle(ValueObject\Step\Action $action, APIValueObject $content): void
{
$values = array_filter($action->getValue());
$contentInfo = $content->contentInfo;
if(array_key_exists('add',$values) && is_array($values) ){
try {
foreach ($values['add'] as $parentLocationId){
$locationCreateStruct = $this->locationService->newLocationCreateStruct($parentLocationId);
$this->locationService->createLocation($contentInfo, $locationCreateStruct);
}
} catch (\Exception $e) {
throw new \RuntimeException('create Location(s) during `assign_content_locations` has failed with: '. $e->getMessage(), $e->getCode(), $e);
}
}
//throw an error when deleteLocation: Could not find 'location' with identifier '123456'
// if(array_key_exists('remove',$values) && is_array($values) ){
// try {
// foreach ($values['remove'] as $parentLocationId){
// $contentLocations = $this->locationService->loadLocations($contentInfo);
// foreach ($contentLocations as $location){
// if(in_array((string)$parentLocationId,explode('/',$location->pathString))){
// $this->locationService->deleteLocation($location);
// }
// }
// }
// } catch (\Exception $e) {
// throw new \RuntimeException('remove location(s) during `assign_content_locations` has failed with: '. $e->getMessage(), $e->getCode(), $e,);
// }
// }
}
}
services:
_defaults:
autowire: true
autoconfigure: false
public: false
#Custom Executor to assign content to many locations on content create only ! (Update not supported in v.3.3.3)
App\Actions\Location\AssignContentLocationsExecutor:
tags:
- { name: 'ibexa.migrations.executor.action.content', key: !php/const \App\Actions\Location\AssignContentLocations::TYPE }
# Add a denormalizer class.
App\Actions\Location\AssignContentLocationsActionDenormalizer:
arguments:
-
-
action: !php/const \App\Actions\Location\AssignContentLocations::TYPE
class: App\Actions\Location\AssignContentLocations
tags:
- { name: 'ibexa.migrations.serializer.normalizer', priority: 20 }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment