diff --git a/README.md b/README.md index 13834ad..efa3061 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ The URI your site's REST API can be accessed from. ### `recommender.included_content_types` This allows you to define content types on which tracking script will be shown. Go to the Tracking section to get more details. -If content's author or image are stored in different field, you can specify it in __default_settings.yml__ +If content's author or image are stored in different field, you can specify it in __parameters.yml__ ```yaml ez_recommendation.field_identifiers: diff --git a/Resources/config/services.yml b/Resources/config/services.yml index a1775ac..ba39d17 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -102,16 +102,30 @@ services: ez_recommendation.rest.controller.content: class: %ez_recommendation.rest.controller.content.class% arguments: - - @ezpublish.config.resolver.core - - @ezpublish.image_alias.imagine.alias_generator - @ezpublish.urlalias_router - @ezpublish.api.service.content - @ezpublish.api.service.location - @ezpublish.api.service.content_type - @ezpublish.api.service.search + - @ez_recommendation.rest.field.value parent: ezpublish_rest.controller.base ez_recommendation.rest.controller.contenttype: class: %ez_recommendation.rest.controller.contenttype.class% parent: ez_recommendation.rest.controller.content + ez_recommendation.rest.field.value: + class: EzSystems\RecommendationBundle\Rest\Field\Value + arguments: + - @ezpublish.api.service.content + - @ezpublish.api.service.content_type + - @ez_recommendation.rest.field.type_value + - {fieldIdentifiers: %ez_recommendation.field_identifiers%} + + ez_recommendation.rest.field.type_value: + class: EzSystems\RecommendationBundle\Rest\Field\TypeValue + arguments: + - @request_stack + - @ezpublish.config.resolver.core + - @ezpublish.fieldtype.ezxmltext.converter.html5 + - @ezpublish.image_alias.imagine.alias_generator \ No newline at end of file diff --git a/Rest/Controller/ContentController.php b/Rest/Controller/ContentController.php index e86bbbb..312b420 100644 --- a/Rest/Controller/ContentController.php +++ b/Rest/Controller/ContentController.php @@ -8,16 +8,14 @@ */ namespace EzSystems\RecommendationBundle\Rest\Controller; -use eZ\Bundle\EzPublishCoreBundle\Imagine\AliasGenerator as ImageVariationService; use eZ\Publish\API\Repository\Values\Content\Content; -use eZ\Publish\API\Repository\Values\Content\Field; use eZ\Publish\API\Repository\Values\ContentType\ContentType; -use eZ\Publish\Core\MVC\ConfigResolverInterface; use eZ\Publish\Core\REST\Server\Controller as BaseController; use eZ\Publish\API\Repository\ContentService; use eZ\Publish\API\Repository\LocationService; use eZ\Publish\API\Repository\ContentTypeService; use eZ\Publish\API\Repository\SearchService; +use EzSystems\RecommendationBundle\Rest\Field\Value as FieldValue; use EzSystems\RecommendationBundle\Rest\Values\ContentData as ContentDataValue; use Symfony\Component\Routing\Generator\UrlGeneratorInterface as UrlGenerator; @@ -26,12 +24,6 @@ */ class ContentController extends BaseController { - /** @var \eZ\Publish\Core\MVC\ConfigResolverInterface */ - protected $configResolver; - - /** @var \eZ\Bundle\EzPublishCoreBundle\Imagine\AliasGenerator */ - protected $imageVariationService; - /** @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface */ protected $generator; @@ -47,31 +39,31 @@ class ContentController extends BaseController /** @var \eZ\Publish\Core\Repository\SearchService */ protected $searchService; + /** @var \EzSystems\RecommendationBundle\Rest\Field\Value */ + protected $value; + /** - * @param \eZ\Publish\Core\MVC\ConfigResolverInterface $configResolver - * @param \eZ\Bundle\EzPublishCoreBundle\Imagine\AliasGenerator $imageVariationService * @param \Symfony\Component\Routing\Generator\UrlGeneratorInterface $generator * @param \eZ\Publish\API\Repository\ContentService $contentService * @param \eZ\Publish\API\Repository\LocationService $locationService * @param \eZ\Publish\API\Repository\ContentTypeService $contentTypeService * @param \eZ\Publish\API\Repository\SearchService $searchService + * @param \EzSystems\RecommendationBundle\Rest\Field\Value $value */ public function __construct( - ConfigResolverInterface $configResolver, - ImageVariationService $imageVariationService, UrlGenerator $generator, ContentService $contentService, LocationService $locationService, ContentTypeService $contentTypeService, - SearchService $searchService + SearchService $searchService, + FieldValue $value ) { - $this->configResolver = $configResolver; - $this->imageVariationService = $imageVariationService; $this->generator = $generator; $this->contentService = $contentService; $this->locationService = $locationService; $this->contentTypeService = $contentTypeService; $this->searchService = $searchService; + $this->value = $value; } /** @@ -114,6 +106,7 @@ protected function prepareContent($contentIds) $contentType = $this->contentTypeService->loadContentType($contentValue->contentInfo->contentTypeId); $location = $this->locationService->loadLocation($contentValue->contentInfo->mainLocationId); $language = (null === $requestLanguage) ? $contentType->mainLanguageCode : $requestLanguage; + $this->value->setFieldDefinitionsList($contentType); $content[$contentId] = array( 'contentId' => $contentId, @@ -134,30 +127,10 @@ protected function prepareContent($contentIds) ); $fields = $this->prepareFields($contentType, $requestedFields); - $imageFieldIdentifier = $this->getImageFieldIdentifier($contentId, $language); - if (!empty($fields)) { foreach ($fields as $field) { - $fieldValue = $contentValue->getFieldValue($field, $language); - - $relatedField = $this->getRelation($contentValue, $field, $imageFieldIdentifier, $language); - - if (null === $fieldValue && !$relatedField) { - continue; - } - - if ($relatedField) { - $fieldValue = $this->getRelatedFieldValue($relatedField, $language, $imageFieldIdentifier); - $field = $imageFieldIdentifier; - } elseif ($field == $imageFieldIdentifier) { - $fieldObj = $contentValue->getFieldsByLanguage($language); - $fieldValue = $this->imageVariations($fieldObj[$field], $contentValue->versionInfo, $this->request->get('image')); - } - - $content[$contentId]['fields'][] = array( - 'key' => $field, - 'value' => (string) $fieldValue, - ); + $field = $this->value->getConfiguredFieldIdentifier($field, $contentType); + $content[$contentId]['fields'][] = $this->value->getFieldValue($contentValue, $field, $language); } } } @@ -189,113 +162,6 @@ protected function prepareFields(ContentType $contentType, $fields = null) return $fields; } - /** - * Returns image uri based on variation provided in url. - * If none is set original is returned. - * - * @param \eZ\Publish\API\Repository\Values\Content\Field $fieldValue - * @param \eZ\Publish\API\Repository\Values\Content\VersionInfo $versionInfo - * @param string|null $variation - * - * @return string - * - * @throws \eZ\Publish\API\Repository\Exceptions\InvalidVariationException - * @throws \eZ\Publish\Core\MVC\Exception\SourceImageNotFoundException - */ - private function imageVariations(Field $fieldValue, $versionInfo, $variation = null) - { - if (!isset($fieldValue->value->id)) { - return ''; - } - - $variations = $this->configResolver->getParameter('image_variations'); - - if ((null === $variation) || !in_array($variation, array_keys($variations))) { - $variation = 'original'; - } - - return $this->imageVariationService->getVariation($fieldValue, $versionInfo, $variation)->uri; - } - - /** - * Return uri of the related image field. - * - * @param mixed $contentId - * @param string $language - * @param string $imageFieldIdentifier - * - * @return string - */ - private function getRelatedFieldValue($contentId, $language, $imageFieldIdentifier) - { - $content = $this->contentService->loadContent($contentId); - $fieldObj = $content->getFieldsByLanguage($language); - - if (!isset($fieldObj[$imageFieldIdentifier])) { - return ''; - } - - return $this->imageVariations($fieldObj[$imageFieldIdentifier], $content->versionInfo, $this->request->get('image')); - } - - /** - * Return identifier of a field of ezimage type. - * - * @param mixed $contentId - * @param string $language - * - * @return string - */ - private function getImageFieldIdentifier($contentId, $language) - { - $content = $this->contentService->loadContent($contentId); - $contentType = $this->contentTypeService->loadContentType($content->contentInfo->contentTypeId); - - if ($identifier = $this->getConfiguredFieldIdentifier('image', $contentType)) { - return $identifier; - } - - foreach ($contentType->fieldDefinitions as $fieldDefinition) { - if ($fieldDefinition->fieldTypeIdentifier == 'ezimage') { - return $fieldDefinition->identifier; - } elseif ($fieldDefinition->fieldTypeIdentifier == 'ezobjectrelation') { - $field = $content->getFieldValue($fieldDefinition->identifier, $language); - - return $this->getImageFieldIdentifier($field->destinationContentId, $language); - } - } - - return false; - } - - /** - * Checks if content has image relation field, returns its ID if true. - * - * @param \eZ\Publish\API\Repository\Values\Content\Content $content - * @param string $field - * @param string $imageFieldIdentifier - * @param string $language - * - * @return int|null - */ - private function getRelation(Content $content, $field, $imageFieldIdentifier, $language) - { - $contentType = $this->contentTypeService->loadContentType($content->contentInfo->contentTypeId); - - foreach ($contentType->fieldDefinitions as $fieldDef) { - $isRelation = ($fieldDef->fieldTypeIdentifier == 'ezobjectrelation' && $field == $fieldDef->identifier); - if ($isRelation || $field == $imageFieldIdentifier) { - $fieldValue = $content->getFieldValue($fieldDef->identifier, $language); - - if (isset($fieldValue->destinationContentId)) { - return $fieldValue->destinationContentId; - } - } - } - - return false; - } - /** * Returns author of the content. * @@ -306,7 +172,9 @@ private function getRelation(Content $content, $field, $imageFieldIdentifier, $l */ private function getAuthor(Content $contentValue, ContentType $contentType) { - $author = $contentValue->getFieldValue($this->getConfiguredFieldIdentifier('author', $contentType)); + $author = $contentValue->getFieldValue( + $this->value->getConfiguredFieldIdentifier('author', $contentType) + ); if (null === $author) { $userContentInfo = $this->contentService->loadContentInfo($contentValue->contentInfo->ownerId); @@ -315,36 +183,4 @@ private function getAuthor(Content $contentValue, ContentType $contentType) return (string) $author; } - - /** - * Returns field name. - * - * To define another field name for specific value (e. g. author) add it to default_settings.yml - * - * For example: - * - * ez_recommendation.field_identifiers: - * author: - * blog_post: authors - * image: - * blog_post: thumbnail - * - * @param string $fieldName - * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType - * - * @return string - */ - private function getConfiguredFieldIdentifier($fieldName, ContentType $contentType) - { - $contentTypeName = $contentType->identifier; - if ($this->container->hasParameter('ez_recommendation.field_identifiers')) { - $fieldDefinitions = $this->container->getParameter('ez_recommendation.field_identifiers'); - - if (isset($fieldDefinitions[$fieldName]) && !empty($fieldDefinitions[$fieldName][$contentTypeName])) { - return $fieldDefinitions[$fieldName][$contentTypeName]; - } - } else { - return $fieldName; - } - } } diff --git a/Rest/Field/TypeValue.php b/Rest/Field/TypeValue.php new file mode 100644 index 0000000..86401d4 --- /dev/null +++ b/Rest/Field/TypeValue.php @@ -0,0 +1,126 @@ +request = $request; + $this->configResolver = $configResolver; + $this->html5Converter = $html5Converter; + $this->imageVariationService = $imageVariationService; + } + + /** + * Default field value parsing. + * + * @param string $fieldName + * @param mixed $args + * + * @return string + */ + public function __call($fieldName, $args) + { + $field = array_shift($args); + + return (string) $field->value; + } + + /** + * Method for parsing ezxmltext field. + * + * @param \eZ\Publish\API\Repository\Values\Content\Field $field + * + * @return string + */ + public function ezxmltext(Field $field) + { + return $this->html5Converter->convert($field->value->xml); + } + + /** + * Method for parsing ezimage field. + * + * @param \eZ\Publish\API\Repository\Values\Content\Field $field + * @param \eZ\Publish\API\Repository\Values\Content\Content $content + * + * @return string + * + * @throws \eZ\Publish\API\Repository\Exceptions\InvalidVariationException + * @throws \eZ\Publish\Core\MVC\Exception\SourceImageNotFoundException + */ + public function ezimage(Field $field, Content $content) + { + if (!isset($field->value->id)) { + return ''; + } + + $variations = $this->configResolver->getParameter('image_variations'); + $variation = 'original'; + $requestedVariation = $this->request->getCurrentRequest()->get('image'); + + if ((null !== $requestedVariation) || in_array($requestedVariation, array_keys($variations))) { + $variation = $requestedVariation; + } + + return $this->imageVariationService->getVariation($field, $content->versionInfo, $variation)->uri; + } + + /** + * Method for parsing ezobjectrelation field. + * For now related fields refer to images. + * + * @param \eZ\Publish\API\Repository\Values\Content\Field $field + * @param \eZ\Publish\API\Repository\Values\Content\Content $content + * @param string $language + * @param string $imageFieldIdentifier + * + * @return string + */ + public function ezobjectrelation(Field $field, Content $content, $language, $imageFieldIdentifier) + { + $fields = $content->getFieldsByLanguage($language); + foreach ($fields as $type => $field) { + if ($type == $imageFieldIdentifier) { + return $this->ezimage($field, $content); + } + } + + return ''; + } +} diff --git a/Rest/Field/Value.php b/Rest/Field/Value.php new file mode 100644 index 0000000..22b97f7 --- /dev/null +++ b/Rest/Field/Value.php @@ -0,0 +1,219 @@ +contentService = $contentService; + $this->contentTypeService = $contentTypeService; + $this->typeValue = $typeValue; + $this->parameters = $parameters; + } + + /** + * Returns parsed field value. + * + * @param \eZ\Publish\API\Repository\Values\Content\Content $content + * @param string $field + * @param string $language + * + * @return array + */ + public function getFieldValue(Content $content, $field, $language) + { + $fieldObj = $content->getField($field, $language); + $relatedField = $this->getRelation($content, $field, $language); + $imageFieldIdentifier = $this->getImageFieldIdentifier($content->id, $language); + + if ($relatedField) { + $content = $this->contentService->loadContent($relatedField); + $field = $imageFieldIdentifier; + } + + $value = ''; + if ($fieldObj) { + $value = $this->getParsedFieldValue($fieldObj, $content, $language, $imageFieldIdentifier); + } + + return array( + 'key' => $field, + 'value' => $value, + ); + } + + /** + * Return identifier of a field of ezimage type. + * + * @param mixed $contentId + * @param string $language + * @param bool $related + * + * @return string + */ + private function getImageFieldIdentifier($contentId, $language, $related = false) + { + $content = $this->contentService->loadContent($contentId); + $contentType = $this->contentTypeService->loadContentType($content->contentInfo->contentTypeId); + + $fieldDefinitions = $this->getFieldDefinitionList(); + $fieldNames = array_flip($fieldDefinitions); + + if (in_array('ezimage', $fieldDefinitions)) { + return $fieldNames['ezimage']; + } elseif (in_array('ezobjectrelation', $fieldDefinitions) && !$related) { + $field = $content->getFieldValue($fieldNames['ezobjectrelation'], $language); + + return $this->getImageFieldIdentifier($field->destinationContentId, $language, true); + } else { + return $this->getConfiguredFieldIdentifier('image', $contentType); + } + } + + /** + * Checks if content has image relation field, returns its ID if true. + * + * @param \eZ\Publish\API\Repository\Values\Content\Content $content + * @param string $field + * @param string $language + * + * @return int|null + */ + private function getRelation(Content $content, $field, $language) + { + $fieldDefinitions = $this->getFieldDefinitionList(); + $fieldNames = array_flip($fieldDefinitions); + $isRelation = (in_array('ezobjectrelation', $fieldDefinitions) && $field == $fieldNames['ezobjectrelation']); + + if ($isRelation && $field == $fieldNames['ezobjectrelation']) { + $fieldValue = $content->getFieldValue($fieldNames['ezobjectrelation'], $language); + + if (isset($fieldValue->destinationContentId)) { + return $fieldValue->destinationContentId; + } + } + + return null; + } + + /** + * Returns field name. + * + * To define another field name for specific value (e. g. author) add it to parameters.yml + * + * For example: + * + * ez_recommendation.field_identifiers: + * author: + * blog_post: authors + * image: + * blog_post: thumbnail + * + * @param string $fieldName + * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType + * + * @return string + */ + public function getConfiguredFieldIdentifier($fieldName, ContentType $contentType) + { + $contentTypeName = $contentType->identifier; + + if (isset($this->parameters['fieldIdentifiers'])) { + $fieldDefinitions = $this->parameters['fieldIdentifiers']; + + if (isset($fieldDefinitions[$fieldName]) && !empty($fieldDefinitions[$fieldName][$contentTypeName])) { + return $fieldDefinitions[$fieldName][$contentTypeName]; + } + } + + return $fieldName; + } + + /** + * Prepares an array with field type identifiers. + * + * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType + */ + public function setFieldDefinitionsList(ContentType $contentType) + { + foreach ($contentType->fieldDefinitions as $fieldDef) { + $this->fieldDefIdentifiers[$fieldDef->identifier] = $fieldDef->fieldTypeIdentifier; + } + } + + /** + * Returns field definition. + * + * @param string $identifier + * + * @return mixed + */ + public function getFieldDefinition($identifier) + { + return $this->fieldDefIdentifiers[$identifier]; + } + + /** + * Returns field definitions. + * + * @return mixed + */ + public function getFieldDefinitionList() + { + return $this->fieldDefIdentifiers; + } + + /** + * Returns parsed field value. + * + * @param \eZ\Publish\API\Repository\Values\Content\Field $field + * @param \eZ\Publish\API\Repository\Values\Content\Content $content + * @param string $language + * @param string $imageFieldIdentifier + * + * @return mixed + */ + public function getParsedFieldValue(Field $field, Content $content, $language, $imageFieldIdentifier) + { + $fieldType = $this->fieldDefIdentifiers[$field->fieldDefIdentifier]; + + return $this->typeValue->$fieldType($field, $content, $language, $imageFieldIdentifier); + } +}