Skip to content

Commit

Permalink
EZP-29849: Allow user to remove location in subtree/location limitation
Browse files Browse the repository at this point in the history
  • Loading branch information
adamwojs committed Jan 14, 2019
1 parent 56fcaed commit 38a4c75
Show file tree
Hide file tree
Showing 7 changed files with 403 additions and 44 deletions.
83 changes: 83 additions & 0 deletions lib/Limitation/DataTransformer/UDWBasedValueModelTransformer.php
@@ -0,0 +1,83 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace EzSystems\RepositoryForms\Limitation\DataTransformer;

use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use eZ\Publish\API\Repository\LocationService;
use eZ\Publish\API\Repository\Values\Content\Location;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

/**
* DataTransformer for UDWBasedMapper.
*
* Needed to display the form field correctly and transform it back to an appropriate value object.
*/
class UDWBasedValueModelTransformer implements DataTransformerInterface
{
/** @var \eZ\Publish\API\Repository\LocationService */
private $locationService;

/**
* @param \eZ\Publish\API\Repository\LocationService $locationService
*/
public function __construct(LocationService $locationService)
{
$this->locationService = $locationService;
}

/**
* {@inheritdoc}
*/
public function transform($value)
{
if (!is_array($value)) {
return null;
}

try {
return array_map(function (string $path) {
return $this->locationService->loadLocation(
$this->extractLocationIdFromPath($path)
);
}, $value);
} catch (NotFoundException | UnauthorizedException $e) {
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
}
}

/**
* {@inheritdoc}
*/
public function reverseTransform($value)
{
if (!is_array($value)) {
return null;
}

return array_map(function(Location $location) {
return $location->id;
}, $value);
}

/**
* Extracts and returns an item id from a path, e.g. /1/2/58/ => 58.
*
* @param string $path
*
* @return string|null
*/
private function extractLocationIdFromPath(string $path): ?string
{
$pathParts = explode('/', trim($path, '/'));

return array_pop($pathParts);
}
}
43 changes: 2 additions & 41 deletions lib/Limitation/DataTransformer/UDWBasedValueTransformer.php
Expand Up @@ -8,48 +8,9 @@
*/
namespace EzSystems\RepositoryForms\Limitation\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;

/**
* DataTransformer for UDWBasedMapper.
* Needed to display the form field correctly and transform it back to an appropriate value object.
* @deprecated since v2.5.0. Use \EzSystems\RepositoryForms\Limitation\DataTransformer\UDWBasedValueModelTransformer instead.
*/
class UDWBasedValueTransformer implements DataTransformerInterface
class UDWBasedValueTransformer extends UDWBasedValueModelTransformer
{
public function transform($value)
{
if (!is_array($value)) {
return null;
}

$locations = [];
foreach ($value as $key => $path) {
$locations[] = $this->extractLocationIdFromPath($path);
}

return implode(',', $locations);
}

public function reverseTransform($value)
{
if (!is_string($value)) {
return null;
}

return explode(',', $value);
}

/**
* Extracts and returns an item id from a path, e.g. /1/2/58 => 58.
*
* @param string $path
*
* @return mixed
*/
private function extractLocationIdFromPath($path)
{
$pathParts = explode('/', trim($path, '/'));

return array_pop($pathParts);
}
}
64 changes: 64 additions & 0 deletions lib/Limitation/DataTransformer/UDWBasedValueViewTransformer.php
@@ -0,0 +1,64 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace EzSystems\RepositoryForms\Limitation\DataTransformer;

use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use eZ\Publish\API\Repository\LocationService;
use eZ\Publish\API\Repository\Values\Content\Location;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;

class UDWBasedValueViewTransformer implements DataTransformerInterface
{
const DELIMITER = ',';

/** @var \eZ\Publish\API\Repository\LocationService */
private $locationService;

/**
* @param \eZ\Publish\API\Repository\LocationService $locationService
*/
public function __construct(LocationService $locationService)
{
$this->locationService = $locationService;
}

/**
* {@inheritdoc}
*/
public function transform($value)
{
if (!is_array($value)) {
return null;
}

return implode(self::DELIMITER, array_map(function (Location $location) {
return $location->id;
}, $value));
}

/**
* {@inheritdoc}
*/
public function reverseTransform($value)
{
if (!is_string($value) || $value === '') {
return $value;
}

try {
return array_map(function ($id) {
return $this->locationService->loadLocation($id);
}, explode(self::DELIMITER, $value));
} catch (NotFoundException | UnauthorizedException $e) {
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
}
}
}
7 changes: 5 additions & 2 deletions lib/Limitation/Mapper/UDWBasedMapper.php
Expand Up @@ -14,6 +14,7 @@
use eZ\Publish\API\Repository\Values\Content\Query\SortClause\Location\Path;
use eZ\Publish\API\Repository\Values\User\Limitation;
use EzSystems\RepositoryForms\Limitation\DataTransformer\UDWBasedValueTransformer;
use EzSystems\RepositoryForms\Limitation\DataTransformer\UDWBasedValueViewTransformer;
use EzSystems\RepositoryForms\Limitation\LimitationFormMapperInterface;
use EzSystems\RepositoryForms\Limitation\LimitationValueMapperInterface;
use EzSystems\RepositoryForms\Translation\LimitationTranslationExtractor;
Expand Down Expand Up @@ -67,12 +68,14 @@ public function mapLimitationForm(FormInterface $form, Limitation $data)
{
$form->add(
// Creating from FormBuilder as we need to add a DataTransformer.
$form->getConfig()->getFormFactory()->createBuilder()
$form->getConfig()->getFormFactory()
->createBuilder()
->create('limitationValues', HiddenType::class, [
'required' => false,
'label' => LimitationTranslationExtractor::identifierToLabel($data->getIdentifier()),
])
->addModelTransformer(new UDWBasedValueTransformer())
->addViewTransformer(new UDWBasedValueViewTransformer($this->locationService))
->addModelTransformer(new UDWBasedValueTransformer($this->locationService))
// Deactivate auto-initialize as we're not on the root form.
->setAutoInitialize(false)->getForm()
);
Expand Down
@@ -0,0 +1,126 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace EzSystems\RepositoryForms\Tests\Limitation\DataTransformer;

use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use eZ\Publish\API\Repository\LocationService;
use eZ\Publish\API\Repository\Values\Content\Location;
use EzSystems\RepositoryForms\Limitation\DataTransformer\UDWBasedValueModelTransformer;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Form\Exception\TransformationFailedException;

class UDWBasedValueModelTransformerTest extends TestCase
{
/** @var \eZ\Publish\API\Repository\LocationService|\PHPUnit\Framework\MockObject\MockObject */
private $locationService;

/** @var \EzSystems\RepositoryForms\Limitation\DataTransformer\UDWBasedValueModelTransformer */
private $transformer;

protected function setUp()
{
$this->locationService = $this->createMock(LocationService::class);
$this->transformer = new UDWBasedValueModelTransformer(
$this->locationService
);
}

/**
* @dataProvider dataProviderForTransform
*/
public function testTransform(?array $given, ?array $expected)
{
$this->locationService
->method('loadLocation')
->willReturnCallback(function($id) {
return $this->createLocation($id);
});

$this->assertEquals($expected, $this->transformer->transform($given));
}

public function dataProviderForTransform(): array
{
return [
[ null, null ],
[
[
'/1/2/54/',
'/1/2/54/56/',
'/1/2/54/58/'
],
[
$this->createLocation(54),
$this->createLocation(56),
$this->createLocation(58),
]
]
];
}

/**
* @dataProvider dataProviderForTransformThrowsTransformationFailedException
*/
public function testTransformThrowsTransformationFailedException(string $exceptionClass)
{
$this->expectException(TransformationFailedException::class);

$this->locationService
->expects($this->any())
->method('loadLocation')
->willThrowException(
$this->createMock($exceptionClass)
);

$this->transformer->transform(['/1/2/54']);
}

public function dataProviderForTransformThrowsTransformationFailedException(): array
{
return [
[NotFoundException::class],
[UnauthorizedException::class],
];
}

/**
* @dataProvider dataProviderForReverseTransform
*/
public function testReverseTransform(?array $given, ?array $expected)
{
$this->assertEquals($expected, $this->transformer->reverseTransform($given));
}

public function dataProviderForReverseTransform(): array
{
return [
[ null, null ],
[
[
$this->createLocation(54),
$this->createLocation(56),
$this->createLocation(58),
],
[ 54, 56, 58 ],
]
];
}

private function createLocation($id): Location
{
$location = $this->createMock(Location::class);
$location
->method('__get')
->with('id')
->willReturn($id);

return $location;
}
}

0 comments on commit 38a4c75

Please sign in to comment.