diff --git a/CHANGELOG.md b/CHANGELOG.md index 314deb6..0402953 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Release Notes for Store Hours +## Unreleased + +- Added GraphQL support. ([#55](https://github.com/craftcms/store-hours/pull/55)) +- Added `craft\storehours\gql\types\Day`. +- Added `craft\storehours\gql\types\generators\DayType`. + ## 3.0.0 - 2022-05-03 ### Added diff --git a/src/Field.php b/src/Field.php index 9f855a9..9894611 100644 --- a/src/Field.php +++ b/src/Field.php @@ -10,13 +10,19 @@ use Craft; use craft\base\ElementInterface; use craft\elements\User; +use craft\gql\GqlEntityRegistry; use craft\helpers\Cp; use craft\helpers\DateTimeHelper; use craft\helpers\Json; use craft\i18n\Locale; use craft\storehours\data\DayData; use craft\storehours\data\FieldData; +use craft\storehours\gql\types\Day; +use craft\storehours\gql\types\generators\DayType; use craft\web\assets\timepicker\TimepickerAsset; +use GraphQL\Type\Definition\InputObjectType; +use GraphQL\Type\Definition\ListOfType; +use GraphQL\Type\Definition\Type; use yii\db\Schema; /** @@ -124,7 +130,7 @@ public function getSettingsHtml(): ?string /** * @inheritdoc */ - public function getInputHtml(mixed $value, ?\craft\base\ElementInterface $element = null): string + public function inputHtml(mixed $value, ?ElementInterface $element = null): string { Craft::$app->getView()->registerAssetBundle(TimepickerAsset::class); @@ -135,7 +141,7 @@ public function getInputHtml(mixed $value, ?\craft\base\ElementInterface $elemen /** * @inheritdoc */ - public function normalizeValue(mixed $value, ?\craft\base\ElementInterface $element = null): mixed + public function normalizeValue(mixed $value, ?ElementInterface $element = null): mixed { if (is_string($value) && !empty($value)) { $value = Json::decodeIfJson($value); @@ -164,7 +170,7 @@ public function normalizeValue(mixed $value, ?\craft\base\ElementInterface $elem /** * @inheritdoc */ - public function serializeValue(mixed $value, ?\craft\base\ElementInterface $element = null): mixed + public function serializeValue(mixed $value, ?ElementInterface $element = null): mixed { /** @var FieldData $value */ $serialized = []; @@ -261,4 +267,26 @@ private function _getInputHtml(FieldData $value, bool $static): string 'staticRows' => true, ]); } + + /** + * @inheritdoc + * @since 3.1.0 + */ + public function getContentGqlType(): ListOfType + { + return Type::listOf(DayType::generateType($this)); + } + + /** + * @inheritdoc + * @since 3.1.0 + */ + public function getContentGqlMutationArgumentType(): Type|array + { + $typeName = "{$this->handle}_DayInput"; + return Type::listOf(GqlEntityRegistry::getOrCreate($typeName, fn() => new InputObjectType([ + 'name' => $typeName, + 'fields' => fn() => Day::prepareFieldDefinition($this->slots), + ]))); + } } diff --git a/src/gql/types/Day.php b/src/gql/types/Day.php new file mode 100644 index 0000000..a5db1d5 --- /dev/null +++ b/src/gql/types/Day.php @@ -0,0 +1,45 @@ + + * @since 3.1.0 + */ +class Day extends ObjectType +{ + /** + * @inheritdoc + */ + protected function resolve(mixed $source, array $arguments, mixed $context, ResolveInfo $resolveInfo): mixed + { + return $source[$resolveInfo->fieldName]; + } + + /** + * Returns day fields prepared for GraphQL object definition. + * + * @param array $slots + * @return array + */ + public static function prepareFieldDefinition(array $slots): array + { + $contentFields = []; + foreach ($slots as $slotId => $slot) { + $handle = ($slot['handle'] ?? false) ?: $slotId; + $contentFields[$handle] = DateTime::getType(); + } + return $contentFields; + } +} diff --git a/src/gql/types/generators/DayType.php b/src/gql/types/generators/DayType.php new file mode 100644 index 0000000..fdd4d20 --- /dev/null +++ b/src/gql/types/generators/DayType.php @@ -0,0 +1,61 @@ + + * @since 3.1.0 + */ +class DayType implements GeneratorInterface, SingleGeneratorInterface +{ + /** + * @inheritdoc + */ + public static function generateTypes(mixed $context = null): array + { + return [static::generateType($context)]; + } + + /** + * Returns the generator name. + * + * @return string + */ + public static function getName($context = null): string + { + /** @var Field $context */ + return "{$context->handle}_Day"; + } + + /** + * @inheritdoc + */ + public static function generateType(mixed $context): ObjectType + { + $typeName = self::getName($context); + + return GqlEntityRegistry::getOrCreate($typeName, fn() => new Day([ + 'name' => $typeName, + 'fields' => function() use ($context, $typeName) { + /** @var Field $context */ + $contentFields = Day::prepareFieldDefinition($context->slots); + return Craft::$app->getGql()->prepareFieldDefinitions($contentFields, $typeName); + }, + ])); + } +}