1

So, I'm probably taking the wrong approach here, but I am attempting to write a custom graphQL query interface, resolver, DB and graphQL query classes in order to return values from a custom Plugin table in the DB.

This custom table has a foreign key to the Assets table, and is essentially key-value table for storing 1:N key-value metadata per asset. The metadata and asset info are coming from an external digital asset manager.

So in some ways I'm taking code examples from the corresponding asset query-related classes as well as some plugins I've checked out. I know my interface class is being picked up by Craft because I can see it in the GraphQL API schema explorer, and when I hover over the fields I've defined I can see the descriptions.

Regarding the error message, the name of my class is DAMAssetInterface and it extends craft\gql\interfaces\Element so maybe that's where the Element reference in the error message is coming from?

At any rate, I think the issue is isolated to the interface class (see attached screenshot):

<?php

namespace rosas\dam\gql\interfaces;

use Craft;
use GraphQL\Type\Definition\Type;
// use craft\gql\base\InterfaceType as BaseInterfaceType;
use craft\gql\interfaces\Element as ElementInterface;
use craft\gql\TypeManager;
use craft\gql\GqlEntityRegistry;
use GraphQL\Type\Definition\InterfaceType;
use craft\gql\types\generators\AssetType;
use craft\helpers\Json;

class MyGraphqlInterface extends ElementInterface {

    /**
     * @inheritdoc
     */
    public static function getType($fields = null): Type
    {
        if ($type = GqlEntityRegistry::getEntity(self::getName())) {
            return $type;
        }

        $type = GqlEntityRegistry::createEntity(self::getName(), new InterfaceType([
            'name' => static::getName(),
            'fields' => self::class . '::getFieldDefinitions',
            'description' => 'This is the interface implemented by all assets.',
            'resolveType' => self::class . '::resolveElementTypeName',
        ]));

        AssetType::generateTypes();

        return $type;
    }

    

    /**
     * @inheritdoc
     */
    public static function getTypeGenerator(): string
    {
        return AssetType::class;
    }

    /**
     * @inheritdoc
     */
    public static function getName(): string
    {
        return 'MyGraphqlInterface';
        //return 'AssetInterface';
    }

    /**
     * @inheritdoc
     */
    public static function getFieldDefinitions(): array
    {
        return TypeManager::prepareFieldDefinitions(array_merge(parent::getFieldDefinitions(), self::getConditionalFields(), [
            'dam_meta_key' => [
                'name' => 'dam_meta_key',
                'type' => Type::string(),
                'description' => 'Gets the key from the dam metadata table.'
            ],
            'volumeId' => [
                'name' => 'volumeId',
                'type' => Type::int(),
                'description' => 'The ID of the volume that the asset belongs to.',
            ],
        ]), self::getName());
    }
}

I'm starting to think I need a custom generator type for my interface, but not entirely sure as the message in the logs isn't very helpful. Any help offered will be greatly appreciated!

1 Answer 1

1

in your code there is a line

 'resolveType' => self::class . '::resolveElementTypeName',

if you don't resolve element type, it assumes this is base element which it throws the mentioned error.

if you track the code, resolveElementTypeName calls getGqlTypeName() here:

https://github.com/craftcms/cms/blob/926bd277f6022c20bbbc288c3bcd67691d312842/src/gql/base/InterfaceType.php#L43

and for example for the asset element type getGqlTypeName() is defined here:

https://github.com/craftcms/cms/blob/926bd277f6022c20bbbc288c3bcd67691d312842/src/elements/Asset.php#L2269

and gqlTypeNameByContext() for the asset element type is defined here:

https://github.com/craftcms/cms/blob/926bd277f6022c20bbbc288c3bcd67691d312842/src/elements/Asset.php#L314

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.