Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IMPROVEMENT] Add possibility to retrieve specific versions #939

Open
wants to merge 16 commits into
base: 2.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ public function skipPermisssionCheck()
return $this->configuration['security']['skipPermissionCheck'] ?? false;
}

public function disableVersionedRequests(): bool|string
{
return $this->configuration['security']['disableVersionedRequests'] ?? false;
}

/**
* @param string|null $path
*/
Expand Down
25 changes: 24 additions & 1 deletion src/GraphQL/Query/QueryType.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ public function buildFolderQueries($type, &$config = [], $context = [])
}
}

protected function versionWrapper(callable $resolver)
{
return function ($root, $args, $context, $info) use ($resolver) {
$resolvedData = $resolver($root, $args, $context, $info);

if (isset($args['version'])) {
$resolvedData['versionRequest'] = $args['version'];
}

return $resolvedData;
};
}

/**
* @param array $config
* @param array $context
Expand All @@ -132,12 +145,20 @@ public function buildAssetQueries(&$config = [], $context = [])
'id' => ['type' => Type::int()],
'fullpath' => ['type' => Type::string()],
'defaultLanguage' => ['type' => Type::string()],
'version' => ['type' => Type::int()],
],
'type' => $assetType,
'resolve' => [$resolver, 'resolveAssetGetter'],
'resolve' => $this->versionWrapper([$resolver, 'resolveAssetGetter']),
];

$config['fields']['getAsset'] = $defGet;

foreach ($config['fields'] as &$field) {

if (isset($field['resolve']) && is_callable($field['resolve'])) {
$field['resolve'] = $this->versionWrapper($field['resolve']);
}
}
}
}

Expand All @@ -162,6 +183,7 @@ public function buildDocumentQueries(&$config = [], $context = [])
'path' => ['type' => Type::string(), 'description' => "Get document by 'path' is deprecated as it is wrongly named. The 'path' argument will be replaced by 'fullpath' for Release 1.0."],
'fullpath' => ['type' => Type::string()],
'defaultLanguage' => ['type' => Type::string()],
'version' => ['type' => Type::int()],
],
'type' => $this->getGraphQlService()->getDocumentTypeDefinition('document'),
'resolve' => [$resolver, 'resolveDocumentGetter'],
Expand Down Expand Up @@ -215,6 +237,7 @@ public function buildDataObjectQueries(&$config = [], $context = []): void
'id' => ['type' => Type::int()],
'fullpath' => ['type' => Type::string()],
'defaultLanguage' => ['type' => Type::string()],
'version' => ['type' => Type::int()],
],
'type' => ClassTypeDefinitions::get($class),
'resolve' => [$resolver, 'resolveObjectGetter'],
Expand Down
62 changes: 50 additions & 12 deletions src/GraphQL/Resolver/AssetType.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
use GraphQL\Type\Definition\ResolveInfo;
use Pimcore\Bundle\DataHubBundle\Event\GraphQL\AssetMetadataEvents;
use Pimcore\Bundle\DataHubBundle\GraphQL\ElementDescriptor;
use Pimcore\Bundle\DataHubBundle\GraphQL\Exception\ClientSafeException;
use Pimcore\Bundle\DataHubBundle\GraphQL\Traits\ElementTagTrait;
use Pimcore\Bundle\DataHubBundle\GraphQL\Traits\ServiceTrait;
use Pimcore\Bundle\DataHubBundle\WorkspaceHelper;
use Pimcore\Event\Model\AssetEvent;
use Pimcore\Model\Asset;
use Pimcore\Model\Version;
use Symfony\Component\EventDispatcher\EventDispatcher;

class AssetType
Expand All @@ -41,7 +43,7 @@ class AssetType
*/
public function resolveTag($value = null, $args = [], $context = [], ?ResolveInfo $resolveInfo = null)
{
$asset = $this->getAssetFromValue($value, $context);
$asset = $this->resolveVersionData($value, $context);

if ($asset) {
$result = $this->getTags('asset', $asset->getId());
Expand All @@ -64,7 +66,8 @@ public function resolveTag($value = null, $args = [], $context = [], ?ResolveInf
*/
public function resolveMetadata($value = null, $args = [], $context = [], ?ResolveInfo $resolveInfo = null)
{
$asset = $this->getAssetFromValue($value, $context);
$asset = $this->resolveVersionData($value, $context);

$metadata = $asset?->getMetadata(raw: true);
if (!$metadata) {
return null;
Expand Down Expand Up @@ -127,7 +130,8 @@ public function resolveMetadata($value = null, $args = [], $context = [], ?Resol
*/
public function resolveEmbeddedMetaInfo($value = null, $args = [], $context = [], ?ResolveInfo $resolveInfo = null)
{
$asset = $this->getAssetFromValue($value, $context);
$asset = $this->resolveVersionData($value, $context);

if (!$asset) {
return null;
}
Expand All @@ -150,7 +154,8 @@ public function resolveEmbeddedMetaInfo($value = null, $args = [], $context = []
*/
public function resolvePath($value = null, $args = [], $context = [], ?ResolveInfo $resolveInfo = null)
{
$asset = $this->getAssetFromValue($value, $context);
$asset = $this->resolveVersionData($value, $context);

$thumbNailConfig = $args['thumbnail'] ?? null;
$thumbNailFormat = $args['format'] ?? null;
$deferred = $args['deferred'] ?? false;
Expand All @@ -174,7 +179,8 @@ public function resolvePath($value = null, $args = [], $context = [], ?ResolveIn
*/
public function resolveData($value = null, $args = [], $context = [], ?ResolveInfo $resolveInfo = null)
{
$asset = $this->getAssetFromValue($value, $context);
$asset = $this->resolveVersionData($value, $context);

$thumbNailConfig = $args['thumbnail'] ?? null;
$thumbNailFormat = $args['format'] ?? null;
$deferred = $args['deferred'] ?? false;
Expand All @@ -199,7 +205,8 @@ public function resolveData($value = null, $args = [], $context = [], ?ResolveIn
*/
public function resolveSrcSet($value = null, $args = [], $context = [], ?ResolveInfo $resolveInfo = null)
{
$asset = $this->getAssetFromValue($value, $context);
$asset = $this->resolveVersionData($value, $context);

$thumbNailConfig = $args['thumbnail'] ?? null;
$thumbNailFormat = $args['format'] ?? null;
$deferred = $args['deferred'] ?? null;
Expand Down Expand Up @@ -235,6 +242,8 @@ public function resolveSrcSet($value = null, $args = [], $context = [], ?Resolve
*/
public function resolveResolutions($value = null, $args = [], $context = [], ?ResolveInfo $resolveInfo = null)
{
$asset = $this->resolveVersionData($value, $context);

$types = $args['types'];
$thumbnail = $value['url'] ?? null;

Expand Down Expand Up @@ -268,7 +277,6 @@ public function resolveResolutions($value = null, $args = [], $context = [], ?Re
$assetFieldHelper = $this->getGraphQLService()->getAssetFieldHelper();

/** @var Asset\Image $asset */
$asset = $this->getAssetFromValue($value, $context);
$thumbnail = $assetFieldHelper->getAssetThumbnail($asset, $thumbnailName, $thumbnailFormat);
if (isset($thumbnail)) {
$thumbnailConfig = $thumbnail->getConfig();
Expand All @@ -289,6 +297,32 @@ public function resolveResolutions($value = null, $args = [], $context = [], ?Re
return [];
}

/**
* @throws Exception
*/
private function resolveVersionData($value = null, $context = [])
{
$versionId = null;

if (is_array($value) && isset($value['versionRequest'])) {
$versionId = $value['versionRequest'];
} elseif (is_object($value) && isset($value->versionRequest)) {
$versionId = $value->versionRequest;
}

if ($versionId !== null) {
$version = Version::getById($versionId);
$versionData = $version->getData();
if (!$versionData) {
throw new ClientSafeException("Failed to load version data for version '{$versionId}'.");
}

return $version->getData();
} else {
return $this->getAssetFromValue($value, $context);
}
}

/**
* @param ElementDescriptor|null $value
* @param array $args
Expand All @@ -300,9 +334,11 @@ public function resolveResolutions($value = null, $args = [], $context = [], ?Re
*/
public function resolveDimensions($value = null, $args = [], $context = [], ?ResolveInfo $resolveInfo = null)
{

$asset = $this->resolveVersionData($value, $context);

if ($value instanceof ElementDescriptor) {
$thumbnailName = $args['thumbnail'] ?? null;
$asset = $this->getAssetFromValue($value, $context);

if ($asset instanceof Asset\Video) {
$width = $asset->getCustomSetting('videoWidth');
Expand Down Expand Up @@ -351,12 +387,12 @@ public function resolveDimensions($value = null, $args = [], $context = [], ?Res
*/
public function resolveDuration(ElementDescriptor | null $value = null, array $context = []): ?float
{
$asset = $this->resolveVersionData($value, $context);

if (!$value instanceof ElementDescriptor) {
return null;
}

$asset = $this->getAssetFromValue($value, $context);

if (!$asset instanceof Asset\Video) {
return null;
}
Expand All @@ -369,7 +405,8 @@ public function resolveDuration(ElementDescriptor | null $value = null, array $c
*/
public function resolveVersion($value = null, $args = [], $context = [], ?ResolveInfo $resolveInfo = null)
{
$asset = $this->getAssetFromValue($value, $context);
$asset = $this->resolveVersionData($value, $context);

if ($asset) {
foreach (array_reverse($asset->getVersions()) as $version) {
if ($asset->getModificationDate() === $version->getDate()) {
Expand All @@ -387,7 +424,8 @@ public function resolveVersion($value = null, $args = [], $context = [], ?Resolv
public function resolveModificationDate(
ElementDescriptor $value
): ?string {
$asset = $this->getAssetFromValue($value, []);
$asset = $this->resolveVersionData($value);

if (!$asset) {
return null;
}
Expand Down
62 changes: 60 additions & 2 deletions src/GraphQL/Resolver/QueryType.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@
use Pimcore\Bundle\DataHubBundle\GraphQL\Traits\ServiceTrait;
use Pimcore\Bundle\DataHubBundle\WorkspaceHelper;
use Pimcore\Db;
use Pimcore\Logger;
use Pimcore\Model\DataObject\AbstractObject;
use Pimcore\Model\DataObject\ClassDefinition;
use Pimcore\Model\DataObject\Listing;
use Pimcore\Model\DataObject\Service;
use Pimcore\Model\Translation;
use Pimcore\Model\Version;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class QueryType
Expand Down Expand Up @@ -161,7 +163,19 @@ public function resolveDocumentGetter($value = null, $args = [], $context = [],
$this->getGraphQlService()->getLocaleService()->setLocale($args['defaultLanguage']);
}

$documentElement = $this->getElementByTypeAndIdOrPath($args, 'document');
$configuration = $context['configuration'];
if ($configuration->disableVersionedRequests() && isset($args['version'])) {
unset($args['version']);
}

$documentElement = null;

if (isset($args['version'])) {
$version = Version::getById($args['version']);
$documentElement = $version->getData();
} else {
$documentElement = $this->getElementByTypeAndIdOrPath($args, 'document');
}

if (!$documentElement) {
return null;
Expand Down Expand Up @@ -200,6 +214,11 @@ public function resolveAssetGetter($value = null, $args = [], $context = [], ?Re
return null;
}

$configuration = $context['configuration'];
if ($configuration->disableVersionedRequests() && isset($args['version'])) {
unset($args['version']);
}

if (!$this->omitPermissionCheck) {
if (!WorkspaceHelper::checkPermission($assetElement, 'read')) {
return null;
Expand Down Expand Up @@ -246,6 +265,37 @@ public function resolveTranslationGetter(mixed $value = null, array $args = [],
);
}

/**
* @throws ClientSafeException
*/
private function resolveVersionObject($args, $currentObject)
{
if (!isset($args['version'])) {
return $currentObject;
}

if (!isset($args['id'])) {
throw new ClientSafeException('Version query requires object id to be set');
}

$versionId = (int)$args['version'];
$version = Version::getById($versionId);

if (!$version || $version->getCid() !== $currentObject->getId()) {
throw new ClientSafeException("Version with id '{$versionId}' not found for object with id "
. "'{$currentObject->getId()}'.");
}

$versionData = $version->getData();
if (!$versionData) {
throw new ClientSafeException("Failed to load version data for version '{$versionId}'.");
}

Logger::debug('Version data loaded successfully for version: ' . $versionId);

return $versionData;
}

/**
* @param ElementDescriptor|null $value
* @param array $args
Expand All @@ -260,6 +310,11 @@ public function resolveObjectGetter($value = null, $args = [], $context = [], ?R
$isIdSet = $args['id'] ?? false;
$isFullpathSet = $args['fullpath'] ?? false;

$configuration = $context['configuration'];
if ($configuration->disableVersionedRequests() && isset($args['version'])) {
unset($args['version']);
}

if (!$isIdSet && !$isFullpathSet) {
throw new ClientSafeException('object id or fullpath expected');
}
Expand Down Expand Up @@ -297,7 +352,10 @@ public function resolveObjectGetter($value = null, $args = [], $context = [], ?R

throw new ClientSafeException($errorMessage);
}
$object = $objectList[0];

$currentObject = $objectList[0];

$object = $this->resolveVersionObject($args, $currentObject);

if (!$this->omitPermissionCheck) {
if (!WorkspaceHelper::checkPermission($object, 'read')) {
Expand Down
10 changes: 9 additions & 1 deletion src/Resources/public/js/configuration/graphql/configItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,13 @@ pimcore.plugin.datahub.configuration.graphql.configItem = Class.create(pimcore.e
value: this.data.security ? this.data.security.skipPermissionCheck : ""
});

let disableVersionedRequests = new Ext.form.Checkbox({
fieldLabel: t('plugin_pimcore_datahub_disable_versioned_requests'),
labelWidth: 200,
name: "disableVersionedRequests",
value: this.data.security ? this.data.security.disableVersionedRequests : ""
});

this.securityForm = new Ext.form.FormPanel({
bodyStyle: "padding:10px;",
autoScroll: true,
Expand Down Expand Up @@ -260,7 +267,8 @@ pimcore.plugin.datahub.configuration.graphql.configItem = Class.create(pimcore.e
readOnly: true,
disabled: true
},
skipPermissionCheck
skipPermissionCheck,
disableVersionedRequests
]
});

Expand Down
1 change: 1 addition & 0 deletions src/Resources/translations/admin.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ plugin_pimcore_datahub_graphql_special_translation_listing: "Translation Listing
plugin_pimcore_datahub_graphql_special_translation: "Translation"
read: "Read"
plugin_pimcore_datahub_skip_permission_check: "Skip Permission Check"
plugin_pimcore_datahub_disable_versioned_requests: "Disabled Versioned Requests"
plugin_pimcore_datahub_configpanel_permissions: "Permissions"
plugin_pimcore_datahub_graphql_permissions_roles: "Role Permissions"
plugin_pimcore_datahub_graphql_permissions_users: "User Permissions"
Expand Down