Skip to content

Commit

Permalink
Merge branch '7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
andrerom committed Mar 12, 2018
2 parents 4339a84 + b7670c1 commit 5a694bc
Show file tree
Hide file tree
Showing 14 changed files with 604 additions and 76 deletions.
Expand Up @@ -9,6 +9,7 @@
namespace eZ\Bundle\EzPublishCoreBundle\ApiLoader;

use eZ\Publish\Core\MVC\ConfigResolverInterface;
use eZ\Publish\Core\Repository\Helper\RelationProcessor;
use eZ\Publish\Core\Repository\Values\User\UserReference;
use eZ\Publish\Core\Search\Common\BackgroundIndexer;
use eZ\Publish\SPI\Persistence\Handler as PersistenceHandler;
Expand Down Expand Up @@ -84,20 +85,23 @@ public function __construct(
* @param \eZ\Publish\SPI\Persistence\Handler $persistenceHandler
* @param \eZ\Publish\SPI\Search\Handler $searchHandler
* @param \eZ\Publish\Core\Search\Common\BackgroundIndexer $backgroundIndexer
* @param \eZ\Publish\Core\Repository\Helper\RelationProcessor $relationProcessor
*
* @return \eZ\Publish\API\Repository\Repository
*/
public function buildRepository(
PersistenceHandler $persistenceHandler,
SearchHandler $searchHandler,
BackgroundIndexer $backgroundIndexer
BackgroundIndexer $backgroundIndexer,
RelationProcessor $relationProcessor
) {
$config = $this->container->get('ezpublish.api.repository_configuration_provider')->getRepositoryConfig();

$repository = new $this->repositoryClass(
$persistenceHandler,
$searchHandler,
$backgroundIndexer,
$relationProcessor,
array(
'fieldType' => $this->fieldTypeCollectionFactory->getFieldTypes(),
'nameableFieldTypes' => $this->fieldTypeNameableCollectionFactory->getNameableFieldTypes(),
Expand Down
17 changes: 17 additions & 0 deletions eZ/Publish/API/Repository/Tests/BaseTest.php
Expand Up @@ -8,6 +8,8 @@
*/
namespace eZ\Publish\API\Repository\Tests;

use eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException;
use eZ\Publish\API\Repository\Tests\PHPUnitConstraint\ValidationErrorOccurs as PHPUnitConstraintValidationErrorOccurs;
use EzSystems\EzPlatformSolrSearchEngine\Tests\SetupFactory\LegacySetupFactory as LegacySolrSetupFactory;
use PHPUnit\Framework\TestCase;
use eZ\Publish\API\Repository\Repository;
Expand Down Expand Up @@ -564,4 +566,19 @@ public function createRoleWithPolicies($roleName, array $policiesData)

return $roleService->loadRole($roleDraft->id);
}

/**
* Traverse all errors for all fields in all Translations to find expected one.
*
* @param \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException $exception
* @param string $expectedValidationErrorMessage
*/
protected function assertValidationErrorOccurs(
ContentFieldValidationException $exception,
$expectedValidationErrorMessage
) {
$constraint = new PHPUnitConstraintValidationErrorOccurs($expectedValidationErrorMessage);

self::assertThat($exception, $constraint);
}
}
55 changes: 55 additions & 0 deletions eZ/Publish/API/Repository/Tests/ContentServiceTest.php
Expand Up @@ -21,6 +21,7 @@
use eZ\Publish\API\Repository\Values\User\Limitation\LocationLimitation;
use eZ\Publish\API\Repository\Values\User\Limitation\ContentTypeLimitation;
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use DOMDocument;
use Exception;

/**
Expand Down Expand Up @@ -1655,6 +1656,60 @@ public function testUpdateContentThrowsContentFieldValidationException()
/* END: Use Case */
}

/**
* Test for the updateContent() method.
*
* @covers \eZ\Publish\API\Repository\ContentService::updateContent()
* @depends eZ\Publish\API\Repository\Tests\ContentServiceTest::testUpdateContent
*/
public function testUpdateContentValidatorIgnoresRequiredFieldsOfNotUpdatedLanguages()
{
$repository = $this->getRepository();
/* BEGIN: Use Case */
$contentTypeService = $repository->getContentTypeService();
$contentType = $contentTypeService->loadContentTypeByIdentifier('folder');

// Create multilangual content
$contentService = $repository->getContentService();
$contentCreate = $contentService->newContentCreateStruct($contentType, 'eng-US');
$contentCreate->setField('name', 'An awesome Sidelfingen folder', 'eng-US');
$contentCreate->setField('name', 'An awesome Sidelfingen folder', 'eng-GB');

$contentDraft = $contentService->createContent($contentCreate);

// 2. Update content type definition
$contentTypeDraft = $contentTypeService->createContentTypeDraft($contentType);

$fieldDefinition = $contentType->getFieldDefinition('description');
$fieldDefinitionUpdate = $contentTypeService->newFieldDefinitionUpdateStruct();
$fieldDefinitionUpdate->identifier = 'description';
$fieldDefinitionUpdate->isRequired = true;

$contentTypeService->updateFieldDefinition(
$contentTypeDraft,
$fieldDefinition,
$fieldDefinitionUpdate
);
$contentTypeService->publishContentTypeDraft($contentTypeDraft);

// 3. Update only eng-US translation
$description = new DOMDocument();
$description->loadXML(<<<XML
<?xml version="1.0" encoding="UTF-8"?>
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ezxhtml="http://ez.no/xmlns/ezpublish/docbook/xhtml" xmlns:ezcustom="http://ez.no/xmlns/ezpublish/docbook/custom" version="5.0-variant ezpublish-1.0">
<para>Lorem ipsum dolor</para>
</section>
XML
);

$contentUpdate = $contentService->newContentUpdateStruct();
$contentUpdate->setField('name', 'An awesome Sidelfingen folder (updated)', 'eng-US');
$contentUpdate->setField('description', $description);

$contentService->updateContent($contentDraft->getVersionInfo(), $contentUpdate);
/* END: Use Case */
}

/**
* Test for the updateContent() method.
*
Expand Down
20 changes: 17 additions & 3 deletions eZ/Publish/API/Repository/Tests/FieldType/BaseIntegrationTest.php
Expand Up @@ -309,8 +309,16 @@ protected function createContentType($fieldSettings, $validatorConfiguration, ar
$repository = $this->getRepository();
$contentTypeService = $repository->getContentTypeService();

$contentTypeIdentifier = 'test-' . $this->getTypeName();

try {
return $contentTypeService->loadContentTypeByIdentifier($contentTypeIdentifier);
} catch (Repository\Exceptions\NotFoundException $e) {
// Move on to creating Content Type
}

$createStruct = $contentTypeService->newContentTypeCreateStruct(
'test-' . $this->getTypeName()
$contentTypeIdentifier
);
$createStruct->mainLanguageCode = $this->getOverride('mainLanguageCode', $typeCreateOverride, 'eng-GB');
$createStruct->remoteId = $this->getTypeName();
Expand Down Expand Up @@ -539,10 +547,16 @@ protected function createContent($fieldData, $contentType = null)
*
* @param array $names Content names in the form of <code>[languageCode => name]</code>
* @param array $fieldData FT-specific data in the form of <code>[languageCode => data]</code>
* @param \eZ\Publish\API\Repository\Values\Content\LocationCreateStruct[] $locationCreateStructs
*
* @return \eZ\Publish\API\Repository\Values\Content\Content
*
* @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
* @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
protected function createMultilingualContent(array $names, array $fieldData)
protected function createMultilingualContent(array $names, array $fieldData, array $locationCreateStructs = [])
{
self::assertEquals(array_keys($names), array_keys($fieldData), 'Languages passed to names and data differ');

Expand All @@ -567,7 +581,7 @@ protected function createMultilingualContent(array $names, array $fieldData)
$createStruct->remoteId = md5(uniqid('', true) . microtime());
$createStruct->alwaysAvailable = true;

return $contentService->createContent($createStruct);
return $contentService->createContent($createStruct, $locationCreateStructs);
}

/**
Expand Down
153 changes: 153 additions & 0 deletions eZ/Publish/API/Repository/Tests/FieldType/RichTextIntegrationTest.php
Expand Up @@ -10,6 +10,8 @@

use DirectoryIterator;
use eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException;
use eZ\Publish\API\Repository\Repository;
use eZ\Publish\API\Repository\Values\Content\Location;
use eZ\Publish\Core\FieldType\RichText\Value as RichTextValue;
use eZ\Publish\API\Repository\Values\Content\Field;
use DOMDocument;
Expand Down Expand Up @@ -722,6 +724,157 @@ protected function createDocument($filename)
return $document;
}

/**
* Prepare Content structure with link to deleted Location.
*
* @param \eZ\Publish\API\Repository\Repository $repository
*
* @return array [$deletedLocation, $brokenContent]
*
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
* @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
* @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
private function prepareInternalLinkValidatorBrokenLinksTestCase(Repository $repository)
{
$contentService = $repository->getContentService();
$locationService = $repository->getLocationService();

// Create first content with single Language
$primaryContent = $contentService->publishVersion(
$this->createMultilingualContent(
['eng-US' => 'ContentA'],
['eng-US' => $this->getValidCreationFieldData()],
[$locationService->newLocationCreateStruct(2)]
)->versionInfo
);
// Create secondary Location (to be deleted) for the first Content
$deletedLocation = $locationService->createLocation(
$primaryContent->contentInfo,
$locationService->newLocationCreateStruct(60)
);

// Create second Content with two Languages, one of them linking to secondary Location
$brokenContent = $contentService->publishVersion(
$this->createMultilingualContent(
[
'eng-US' => 'ContentB',
'eng-GB' => 'ContentB',
],
[
'eng-US' => $this->getValidCreationFieldData(),
'eng-GB' => $this->getDocumentWithLocationLink($deletedLocation),
],
[$locationService->newLocationCreateStruct(2)]
)->versionInfo
);

// delete Location making second Content broken
$locationService->deleteLocation($deletedLocation);

return [$deletedLocation, $brokenContent];
}

/**
* Test updating Content which contains links to deleted Location doesn't fail when updating not broken field only.
*
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
* @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
* @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
*/
public function testInternalLinkValidatorIgnoresMissingRelationOnNotUpdatedField()
{
$repository = $this->getRepository();
$contentService = $repository->getContentService();

list(, $contentB) = $this->prepareInternalLinkValidatorBrokenLinksTestCase($repository);

// update field w/o erroneous link to trigger validation
$contentUpdateStruct = $contentService->newContentUpdateStruct();
$contentUpdateStruct->setField('data', $this->getValidUpdateFieldData(), 'eng-US');

$contentDraftB = $contentService->updateContent(
$contentService->createContentDraft($contentB->contentInfo)->versionInfo,
$contentUpdateStruct
);

$contentService->publishVersion($contentDraftB->versionInfo);
}

/**
* Test updating Content which contains links to deleted Location fails when updating broken field.
*
* @throws \eZ\Publish\API\Repository\Exceptions\BadStateException
* @throws \eZ\Publish\API\Repository\Exceptions\ContentValidationException
* @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException
* @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException
* @throws \eZ\Publish\API\Repository\Exceptions\ContentFieldValidationException
*/
public function testInternalLinkValidatorReturnsErrorOnMissingRelationInUpdatedField()
{
$repository = $this->getRepository();
$contentService = $repository->getContentService();

list($deletedLocation, $brokenContent) = $this->prepareInternalLinkValidatorBrokenLinksTestCase(
$repository
);

// update field containing erroneous link to trigger validation
/** @var \DOMDocument $document */
$document = $brokenContent->getField('data', 'eng-GB')->value->xml;
$newParagraph = $document->createElement('para', 'Updated content');
$document
->getElementsByTagName('section')->item(0)
->appendChild($newParagraph);

$contentUpdateStruct = $contentService->newContentUpdateStruct();
$contentUpdateStruct->setField('data', new RichTextValue($document), 'eng-GB');

$expectedValidationErrorMessage = sprintf(
'Invalid link "ezlocation://%s": target location cannot be found',
$deletedLocation->id
);
try {
$contentDraftB = $contentService->updateContent(
$contentService->createContentDraft($brokenContent->contentInfo)->versionInfo,
$contentUpdateStruct
);

$contentService->publishVersion($contentDraftB->versionInfo);
} catch (ContentFieldValidationException $e) {
$this->assertValidationErrorOccurs($e, $expectedValidationErrorMessage);

return;
}

self::fail("Expected ValidationError '{$expectedValidationErrorMessage}' didn't occur");
}

/**
* Get XML Document in DocBook format, containing link to the given Location.
*
* @param \eZ\Publish\API\Repository\Values\Content\Location $location
*
* @return \DOMDocument
*/
private function getDocumentWithLocationLink(Location $location)
{
$document = new DOMDocument();
$document->loadXML(<<<XML
<?xml version="1.0" encoding="UTF-8"?>
<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ezxhtml="http://ez.no/xmlns/ezpublish/docbook/xhtml" xmlns:ezcustom="http://ez.no/xmlns/ezpublish/docbook/custom" version="5.0-variant ezpublish-1.0">
<para><link xlink:href="ezlocation://{$location->id}" xlink:show="none">link1</link></para>
</section>
XML
);

return $document;
}

protected function checkSearchEngineSupport()
{
if (ltrim(get_class($this->getSetupFactory()), '\\') === 'eZ\\Publish\\API\\Repository\\Tests\\SetupFactory\\Legacy') {
Expand Down

0 comments on commit 5a694bc

Please sign in to comment.