Skip to content

Commit

Permalink
A GQL attempt was made
Browse files Browse the repository at this point in the history
  • Loading branch information
Tam committed Apr 14, 2020
1 parent 2fb72ba commit 8e112b4
Show file tree
Hide file tree
Showing 4 changed files with 320 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/Thumbro.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@

use craft\base\Model;
use craft\base\Plugin;
use craft\events\RegisterGqlDirectivesEvent;
use craft\events\RegisterGqlTypesEvent;
use craft\services\Gql;
use craft\web\twig\variables\CraftVariable;
use ether\thumbro\gql\ThumbroTypes;
use yii\base\Event;
use yii\base\InvalidConfigException;

Expand All @@ -37,6 +41,18 @@ public function init ()
CraftVariable::EVENT_INIT,
[$this, 'onRegisterVariable']
);

Event::on(
Gql::class,
Gql::EVENT_REGISTER_GQL_TYPES,
[$this, 'onRegisterGqlTypes']
);

Event::on(
Gql::class,
Gql::EVENT_REGISTER_GQL_DIRECTIVES,
[$this, 'onRegisterGqlDirectives']
);
}

// Settings
Expand Down Expand Up @@ -70,6 +86,16 @@ public function onRegisterVariable (Event $event)
$variable->set('thumbro', Variable::class);
}

public function onRegisterGqlTypes (RegisterGqlTypesEvent $event)
{
ThumbroTypes::register($event);
}

public function onRegisterGqlDirectives (RegisterGqlDirectivesEvent $event)
{
$event->directives[] = ThumbroDirective::class;
}

// Helpers
// =========================================================================

Expand Down
106 changes: 106 additions & 0 deletions src/ThumbroDirective.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php
/**
* Thumbro for Craft CMS
*
* @link https://ethercreative.co.uk
* @copyright Copyright (c) 2020 Ether Creative
*/

namespace ether\thumbro;

use craft\elements\Asset;
use craft\gql\base\Directive;
use craft\gql\GqlEntityRegistry;
use GraphQL\Language\DirectiveLocation;
use GraphQL\Type\Definition\Directive as GqlDirective;
use GraphQL\Type\Definition\FieldArgument;
use GraphQL\Type\Definition\ResolveInfo;

/**
* Class ThumbroDirective
*
* @author Ether Creative
* @package ether\thumbro
*/
class ThumbroDirective extends Directive
{

public function __construct(array $config)
{
$args = &$config['args'];

foreach ($args as &$argument) {
$argument = new FieldArgument($argument);
}

parent::__construct($config);
}

/**
* @inheritDoc
*/
public static function create (): GqlDirective
{
if ($type = GqlEntityRegistry::getEntity(self::name()))
return $type;

$type = GqlEntityRegistry::createEntity(static::name(), new self([
'name' => static::name(),
'locations' => [
DirectiveLocation::FIELD,
],
// TODO: Make args an array of transform arguments
'args' => ThumbroTransformArguments::getArguments(),
'description' => 'Transform an image using Thumbro',
]));

return $type;
}

/**
* @inheritDoc
*/
public static function name (): string
{
return 'thumbro';
}

/**
* @inheritDoc
*/
public static function apply (
$source, $value, array $transform, ResolveInfo $resolveInfo
) {
$onAssetElement = $source === null && $value instanceof Asset;
$onAssetElementList = $source === null && is_array($value) && !empty($value);
$onApplicableAssetField = $source instanceof Asset && $resolveInfo->fieldName === 'url';

if (!($onAssetElement || $onAssetElementList || $onApplicableAssetField) || empty($arguments) ) {
return $value;
}

$variable = new Variable();

// If this directive is applied to an entire Asset
if ($onAssetElement || $onApplicableAssetField)
return $variable->img($value, $transform);

if ($onAssetElementList) {
$res = [];

foreach ($value as &$asset) {
// If this somehow ended up being a mix of elements, don't explicitly fail, just set the transform on the asset elements
if ($asset instanceof Asset) {
$res[] = $variable->img($asset, $transform);
} else {
$res[] = $asset;
}
}

return $res;
}

return $value;
}

}
64 changes: 64 additions & 0 deletions src/ThumbroTransformArguments.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
/**
* Thumbro for Craft CMS
*
* @link https://ethercreative.co.uk
* @copyright Copyright (c) 2020 Ether Creative
*/

namespace ether\thumbro;

use craft\gql\base\Arguments;
use ether\thumbro\gql\ThumbroTypes;
use GraphQL\Type\Definition\Type;

/**
* Class ThumbroTransformArguments
*
* @author Ether Creative
* @package ether\thumbro
*/
class ThumbroTransformArguments extends Arguments
{

public static function getArguments (): array
{
return [
'format' => [
'name' => 'format',
'type' => ThumbroTypes::Formats(),
'description' => 'Format of the created image. If unset (default) it will be the same format as the source image.',
],
'trim' => [
'name' => 'trim',
'type' => Type::boolean(),
'description' => 'Removing surrounding space in images can be done using the trim option.',
],
'mode' => [
'name' => 'mode',
'type' => ThumbroTypes::Modes(),
'description' => 'The transform mode to use',
],
'width' => [
'name' => 'width',
'type' => Type::int(),
'description' => 'Width of the image, in pixels.',
],
'height' => [
'name' => 'height',
'type' => Type::int(),
'description' => 'Height of the image, in pixels.',
],
'ratio' => [
'name' => 'ratio',
'type' => Type::float(),
'description' => 'An aspect ratio (width/height) that is used to calculate the missing size, if width or height is not provided.',
],
'effects' => [
'name' => 'effects',
'type' => ThumbroTypes::Effects(),
],
];
}

}
124 changes: 124 additions & 0 deletions src/gql/ThumbroTypes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?php
/**
* Thumbro for Craft CMS
*
* @link https://ethercreative.co.uk
* @copyright Copyright (c) 2020 Ether Creative
*/

namespace ether\thumbro\gql;

use craft\events\RegisterGqlTypesEvent;
use GraphQL\Type\Definition\EnumType;
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\UnionType;

/**
* Class ThumbroTypes
*
* @author Ether Creative
* @package ether\thumbro\gql
*/
final class ThumbroTypes
{

public static function register (RegisterGqlTypesEvent $event)
{
$methods = get_class_methods(new self());

foreach ($methods as $method) if ($method !== 'register')
$event->types[] = self::{$method}();
}

public static function Formats ()
{
return new EnumType([
'name' => 'Format',
'description' => 'Valid transform formats',
'values' => [
'JPG' => [
'value' => 'jpg',
],
'PNG' => [
'value' => 'png',
],
'GIF' => [
'value' => 'gif',
],
'WEBP' => [
'value' => 'webp',
],
],
]);
}

public static function Modes ()
{
return new EnumType([
'name' => 'Mode',
'description' => 'Transform modes',
'values' => [
'CROP' => [
'value' => 'crop',
'description' => 'Crops the image to the given size, scaling the image to fill as much as possible of the size.',
],
'FIT' => [
'value' => 'fit',
'description' => 'Scales the image to fit within the given size while maintaining the aspect ratio of the original image.',
],
'STRETCH' => [
'value' => 'stretch',
'description' => 'Scales the image to the given size, stretching it if the aspect ratio is different from the original.',
],
],
]);
}

public static function Coordinates ()
{
return new ObjectType([
'name' => 'Coordinates',
'description' => 'Percentage coordinates of an image',
'fields' => [
'x' => [
'name' => 'x',
'type' => Type::float(),
],
'y' => [
'name' => 'y',
'type' => Type::float(),
],
],
]);
}

public static function Position ()
{
return new UnionType([
'name' => 'Position',
'type' => [
Type::string(),
self::Coordinates(),
],
'resolveType' => function ($value) {
return $value->name === 'Coordinates' ? self::Coordinates() : Type::string();
},
]);
}

public static function Effects ()
{
return new ObjectType([
'name' => 'Effects',
'description' => 'Effects to perform on the image',
'fields' => [
'position' => [
'name' => 'position',
'type' => self::Position(),
]
],
]);
}

}

0 comments on commit 8e112b4

Please sign in to comment.