diff --git a/src/lib/Form/Type/FieldType/AbstractRelationFieldType.php b/src/lib/Form/Type/FieldType/AbstractRelationFieldType.php new file mode 100644 index 00000000..1d42602f --- /dev/null +++ b/src/lib/Form/Type/FieldType/AbstractRelationFieldType.php @@ -0,0 +1,157 @@ +permissionResolver = $permissionResolver; + $this->contentService = $contentService; + } + + /** + * @return array{ + * contentInfo: \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo|null, + * contentType: \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType|null, + * contentId: int, + * languageCodes: array, + * unauthorized: bool, + * } + * + * @throws \Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException + */ + protected function getRelationData(int $contentId): array + { + $contentInfo = null; + $contentType = null; + $languages = []; + $unauthorized = false; + + try { + $versionInfo = $this->contentService->loadVersionInfoById($contentId); + $contentInfo = $versionInfo->getContentInfo(); + $contentType = $contentInfo->getContentType(); + $languages = $this->getAvailableLanguages($versionInfo); + } catch (UnauthorizedException $e) { + $unauthorized = true; + } + + return [ + 'contentInfo' => $contentInfo, + 'contentType' => $contentType, + 'contentId' => $contentId, + 'languages' => $languages, + 'unauthorized' => $unauthorized, + ]; + } + + /** + * @param array $languages + * + * @return array + */ + protected function getAvailableLanguages(VersionInfo $versionInfo): array + { + $languages = $versionInfo->getLanguages(); + $lookupLimitationResult = $this->getLookupLimitationResult( + $versionInfo->getContentInfo(), + $this->extractLanguageCodes($languages) + ); + + if (!$lookupLimitationResult->hasAccess) { + return []; + } + + if ( + empty($lookupLimitationResult->lookupPolicyLimitations) + && empty($lookupLimitationResult->roleLimitations) + ) { + return $languages; + } + + $limitationLanguageCodes = $this->getLimitationLanguageCodes($lookupLimitationResult); + + return array_filter( + $languages, + static function (Language $language) use ($limitationLanguageCodes): bool { + return in_array($language->getLanguageCode(), $limitationLanguageCodes, true); + } + ); + } + + private function getLookupLimitationResult(ContentInfo $contentInfo, array $languageCodes): LookupLimitationResult + { + return $this->permissionResolver->lookupLimitations( + 'content', + 'edit', + $contentInfo, + [ + (new Target\Builder\VersionBuilder())->translateToAnyLanguageOf($languageCodes)->build(), + $contentInfo->getMainLocation(), + ], + [Limitation::LANGUAGE] + ); + } + + /** + * @return array + */ + private function getLimitationLanguageCodes(LookupLimitationResult $lookupLimitations): array + { + $limitationLanguageCodes = []; + foreach ($lookupLimitations->roleLimitations as $roleLimitation) { + foreach ($roleLimitation->limitationValues as $limitationValue) { + $limitationLanguageCodes[$limitationValue] = true; + } + } + + foreach ($lookupLimitations->lookupPolicyLimitations as $lookupPolicyLimitation) { + foreach ($lookupPolicyLimitation->limitations as $limitation) { + foreach ($limitation->limitationValues as $limitationValue) { + $limitationLanguageCodes[$limitationValue] = true; + } + } + } + + return array_keys($limitationLanguageCodes); + } + + /** + * @param array<\Ibexa\Contracts\Core\Repository\Values\Content\Language> $languages + * + * @return array + */ + private function extractLanguageCodes(array $languages): array + { + $languageCodes = []; + foreach ($languages as $language) { + $languageCodes[] = $language->getLanguageCode(); + } + + return $languageCodes; + } +} diff --git a/src/lib/Form/Type/FieldType/RelationFieldType.php b/src/lib/Form/Type/FieldType/RelationFieldType.php index 11dbcc2c..dff102dc 100644 --- a/src/lib/Form/Type/FieldType/RelationFieldType.php +++ b/src/lib/Form/Type/FieldType/RelationFieldType.php @@ -9,12 +9,8 @@ namespace Ibexa\ContentForms\Form\Type\FieldType; use Ibexa\ContentForms\FieldType\DataTransformer\RelationValueTransformer; -use Ibexa\Contracts\Core\Repository\ContentService; -use Ibexa\Contracts\Core\Repository\ContentTypeService; -use Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException; use Ibexa\Contracts\Core\Repository\Values\Content\Location; use Ibexa\Core\FieldType\Relation\Value; -use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\IntegerType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; @@ -24,24 +20,8 @@ /** * Form Type representing ezobjectrelation field type. */ -class RelationFieldType extends AbstractType +class RelationFieldType extends AbstractRelationFieldType { - /** @var \Ibexa\Contracts\Core\Repository\ContentService */ - private $contentService; - - /** @var \Ibexa\Contracts\Core\Repository\ContentTypeService */ - private $contentTypeService; - - /** - * @param \Ibexa\Contracts\Core\Repository\ContentService $contentService - * @param \Ibexa\Contracts\Core\Repository\ContentTypeService $contentTypeService - */ - public function __construct(ContentService $contentService, ContentTypeService $contentTypeService) - { - $this->contentService = $contentService; - $this->contentTypeService = $contentTypeService; - } - public function getName() { return $this->getBlockPrefix(); @@ -75,23 +55,8 @@ public function finishView(FormView $view, FormInterface $form, array $options) return; } $contentId = $data->destinationContentId; - $contentInfo = null; - $contentType = null; - $unauthorized = false; - - try { - $contentInfo = $this->contentService->loadContentInfo($contentId); - $contentType = $this->contentTypeService->loadContentType($contentInfo->contentTypeId); - } catch (UnauthorizedException $e) { - $unauthorized = true; - } - $view->vars['relations'][$data->destinationContentId] = [ - 'contentInfo' => $contentInfo, - 'contentType' => $contentType, - 'unauthorized' => $unauthorized, - 'contentId' => $contentId, - ]; + $view->vars['relations'][$contentId] = $this->getRelationData($contentId); } public function configureOptions(OptionsResolver $resolver) diff --git a/src/lib/Form/Type/FieldType/RelationListFieldType.php b/src/lib/Form/Type/FieldType/RelationListFieldType.php index 8c570f53..9d845245 100644 --- a/src/lib/Form/Type/FieldType/RelationListFieldType.php +++ b/src/lib/Form/Type/FieldType/RelationListFieldType.php @@ -9,12 +9,8 @@ namespace Ibexa\ContentForms\Form\Type\FieldType; use Ibexa\ContentForms\FieldType\DataTransformer\RelationListValueTransformer; -use Ibexa\Contracts\Core\Repository\ContentService; -use Ibexa\Contracts\Core\Repository\ContentTypeService; -use Ibexa\Contracts\Core\Repository\Exceptions\UnauthorizedException; use Ibexa\Contracts\Core\Repository\Values\Content\Location; use Ibexa\Core\FieldType\RelationList\Value; -use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; @@ -24,24 +20,8 @@ /** * Form Type representing ezobjectrelationlist field type. */ -class RelationListFieldType extends AbstractType +class RelationListFieldType extends AbstractRelationFieldType { - /** @var \Ibexa\Contracts\Core\Repository\ContentService */ - private $contentService; - - /** @var \Ibexa\Contracts\Core\Repository\ContentTypeService */ - private $contentTypeService; - - /** - * @param \Ibexa\Contracts\Core\Repository\ContentService $contentService - * @param \Ibexa\Contracts\Core\Repository\ContentTypeService $contentTypeService - */ - public function __construct(ContentService $contentService, ContentTypeService $contentTypeService) - { - $this->contentService = $contentService; - $this->contentTypeService = $contentTypeService; - } - public function getName() { return $this->getBlockPrefix(); @@ -76,23 +56,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) } foreach ($data->destinationContentIds as $contentId) { - $contentInfo = null; - $contentType = null; - $unauthorized = false; - - try { - $contentInfo = $this->contentService->loadContentInfo($contentId); - $contentType = $this->contentTypeService->loadContentType($contentInfo->contentTypeId); - } catch (UnauthorizedException $e) { - $unauthorized = true; - } - - $view->vars['relations'][$contentId] = [ - 'contentInfo' => $contentInfo, - 'contentType' => $contentType, - 'unauthorized' => $unauthorized, - 'contentId' => $contentId, - ]; + $view->vars['relations'][$contentId] = $this->getRelationData($contentId); } }