File manager - Edit - /home/opticamezl/www/newok/templates/yootheme/packages/graphql/src/SchemaBuilder.php
Back
<?php namespace YOOtheme\GraphQL; use YOOtheme\GraphQL\Error\InvariantViolation; use YOOtheme\GraphQL\Executor\Executor; use YOOtheme\GraphQL\Executor\Values; use YOOtheme\GraphQL\Language\AST\DirectiveNode; use YOOtheme\GraphQL\Language\AST\NodeList; use YOOtheme\GraphQL\Language\Parser; use YOOtheme\GraphQL\Type\Definition\Directive; use YOOtheme\GraphQL\Type\Definition\InputObjectType; use YOOtheme\GraphQL\Type\Definition\NamedType; use YOOtheme\GraphQL\Type\Definition\ObjectType; use YOOtheme\GraphQL\Type\Definition\ResolveInfo; use YOOtheme\GraphQL\Type\Definition\Type; use YOOtheme\GraphQL\Type\Schema; use YOOtheme\GraphQL\Utils\ASTHelper; use YOOtheme\GraphQL\Utils\BuildSchema; use YOOtheme\GraphQL\Utils\Middleware; class SchemaBuilder { /** * @var callable[][] */ protected $hooks = []; /** * @var Type[] */ protected $types = []; /** * @var Type[] */ protected $loadedTypes = []; /** * @var array */ protected $directives = []; /** * Constructor. * * @param array $plugins */ public function __construct(array $plugins = []) { $this->hooks = [ 'onLoad' => [], 'onLoadType' => [], 'onLoadField' => [], ]; foreach ($plugins as $plugin) { $this->loadPlugin($plugin); } /** @phpstan-ignore-next-line */ foreach ($this->hooks['onLoad'] as $hook) { $hook($this); } } /** * @param string $file * @param string $cache * * @return Schema */ public function loadSchema($file, $cache = null) { $isCached = is_file($cache) && filectime($cache) > filectime($file); $document = $isCached ? ASTHelper::fromArray(require $cache) : Parser::parse(file_get_contents($file), ['noLocation' => true]); $result = BuildSchema::build( $document, fn(array $config) => ['resolveField' => [$this, 'resolveField']] + $config, ['assumeValid' => $isCached, 'assumeValidSDL' => $isCached], ); if (!$isCached && $cache) { file_put_contents( $cache, "<?php\n\nreturn {$this->exportValue(ASTHelper::toArray($document))};", ); } return $result; } /** * @param array $config * * @return Schema */ public function buildSchema(array $config = []) { $config = array_replace_recursive( [ 'query' => 'Query', 'mutation' => 'Mutation', 'subscription' => 'Subscription', 'directives' => $this->directives, 'typeLoader' => [$this, 'getType'], ], $config, ); if (is_string($config['query'])) { $config['query'] = $this->getType($config['query']); } if (is_string($config['mutation'])) { $config['mutation'] = $this->getType($config['mutation']); } if (is_string($config['subscription'])) { $config['subscription'] = $this->getType($config['subscription']); } return new Schema($config); } /** * @param array $config * * @return string */ public function printSchema(array $config = []) { return SchemaPrinter::doPrint($this->buildSchema($config)); } /** * @param string $name * * @return Directive */ public function getDirective($name) { return $this->directives[$name] ?? null; } /** * @param Directive $directive */ public function setDirective(Directive $directive) { $this->directives[$directive->name] = $directive; } /** * @param string $name * * @return bool */ public function hasType($name) { return isset($this->types[$name]); } /** * @param string $name * * @return Type|void */ public function getType($name) { if (empty($this->loadedTypes)) { $this->loadedTypes = Type::getStandardTypes(); } if (isset($this->loadedTypes[$name])) { return $this->loadedTypes[$name]; } if (isset($this->types[$name])) { return $this->loadType($this->loadedTypes[$name] = $this->types[$name]); } } /** * @param Type $type */ public function setType(Type $type) { /** @var NamedType $type */ $this->types[$type->name] = $type; } /** * @param array|callable $config * * @return ObjectType */ public function queryType($config = []) { return $this->objectType('Query', $config); } /** * @param string $name * @param array|callable $config * * @return InputObjectType */ public function inputType($name, $config = []) { $type = $this->types[$name] ?? new InputObjectType([ 'name' => $name, 'fields' => [], ]); if (!$type instanceof InputObjectType) { throw new InvariantViolation("Type '{$name}' must be an InputObjectType."); } return $this->types[$name] = $this->extendType($type, $config); } /** * @param string $name * @param array|callable $config * * @return ObjectType */ public function objectType($name, $config = []) { $type = $this->types[$name] ?? new ObjectType([ 'name' => $name, 'fields' => [], 'resolveField' => [$this, 'resolveField'], ]); if (!$type instanceof ObjectType) { throw new InvariantViolation("Type '{$name}' must be an ObjectType."); } return $this->types[$name] = $this->extendType($type, $config); } /** * @template T of Type * @param T $type * @param array|callable $config * @return T */ public function extendType(Type $type, $config = []) { if (is_callable($config)) { $config = $config($type, $this); } if (is_array($config) && property_exists($type, 'config')) { $type->config = array_replace_recursive($type->config, $config); } return $type; } /** * @template T of Type * @param T $type * @return T */ public function loadType(Type $type) { foreach ($this->hooks['onLoadType'] as $hook) { $hook($type, $this); } if (isset($type->config['description']) && property_exists($type, 'description')) { $type->description = $type->config['description']; } if (isset($type->config['resolveField']) && $type instanceof ObjectType) { $type->resolveFieldFn = $type->config['resolveField']; } if (isset($type->config['fields'])) { $type->config['fields'] = $this->loadFields($type, $type->config['fields']); } if ($type instanceof ObjectType) { $type->astNode = ASTHelper::objectType($type); } elseif ($type instanceof InputObjectType) { $type->astNode = ASTHelper::inputType($type); } return $type; } /** * @param mixed $value * @param mixed $args * @param mixed $context * @param ResolveInfo $info * * @return mixed */ public function resolveField($value, $args, $context, ResolveInfo $info) { $resolver = new Middleware([Executor::class, 'defaultFieldResolver']); foreach ($this->resolveDirectives($info) as $directiveNode) { $directiveDef = $this->getDirective($directiveNode->name->value); if (is_callable($directiveDef)) { $directive = $directiveDef( Values::getArgumentValues($directiveDef, $directiveNode, $info->variableValues), $resolver, ); if (is_callable($directive)) { $resolver->push($directive); } } } return $resolver($value, $args, $context, $info); } /** * @return NodeList<DirectiveNode> */ public function resolveDirectives(ResolveInfo $info) { $nodes = new NodeList([]); $field = $info->parentType->getField($info->fieldName); // type directives if (isset($info->parentType->astNode->directives)) { $nodes = $nodes->merge($info->parentType->astNode->directives); } // field directives if (isset($field->astNode->directives)) { $nodes = $nodes->merge($field->astNode->directives); } // query field directives foreach ($info->fieldNodes as $node) { if ($info->fieldName === $node->name->value) { return $nodes->merge($node->directives); } } return $nodes; } /** * @param Type $type * @param array $field * * @return array */ protected function loadField(Type $type, array $field) { $field += ['type' => null]; if (is_string($field['type'])) { $field['type'] = $this->getType($field['type']); } if (is_array($field['type'])) { $field['type'] = $this->loadModifiers($field['type']); } if (empty($field['type'])) { /** @var NamedType $type */ throw new InvariantViolation( "Field '{$field['name']}' on '{$type->name}' does not have a Type.", ); } return $field; } /** * @param Type $type * @param array $fields * * @return array */ protected function loadFields(Type $type, array $fields) { $result = []; foreach ($fields as $name => $field) { $field = $this->loadField( $type, $field + [ 'name' => lcfirst($name), 'args' => [], ], ); foreach ($field['args'] as $key => $arg) { $field['args'][$key] = $this->loadField($type, $arg); } foreach ($this->hooks['onLoadField'] as $hook) { $field = $hook($type, $field, $this); } $result[$name] = $field; } return $result; } /** * @param array $type * * @return Type|array */ protected function loadModifiers(array $type) { if (isset($type['nonNull'])) { if (is_string($type['nonNull'])) { $nonNull = $this->getType($type['nonNull']); } elseif (is_array($type['nonNull'])) { $nonNull = $this->loadModifiers($type['nonNull']); } $type = Type::nonNull($nonNull ?? Type::string()); } elseif (isset($type['listOf'])) { if (is_string($type['listOf'])) { $listOf = $this->getType($type['listOf']); } elseif (is_array($type['listOf'])) { $listOf = $this->loadModifiers($type['listOf']); } $type = Type::listOf($listOf ?? Type::string()); } return $type; } /** * @param mixed $plugin */ protected function loadPlugin($plugin) { foreach ($this->hooks as $method => &$hooks) { $hook = [$plugin, $method]; if (is_callable($hook)) { $hooks[] = $hook; } } } /** * Export a parsable string representation of a value. * * @param mixed $value * @param int $indent * * @return string */ protected function exportValue($value, $indent = 0) { if (is_array($value)) { $array = []; $assoc = array_values($value) !== $value; $indention = str_repeat(' ', $indent); $indentlast = $assoc ? "\n" . $indention : ''; foreach ($value as $key => $val) { $array[] = ($assoc ? "\n " . $indention . var_export($key, true) . ' => ' : '') . $this->exportValue($val, $indent + 1); } return '[' . join(', ', $array) . $indentlast . ']'; } return var_export($value, true); } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.23 | Generation time: 0.05 |
proxy
|
phpinfo
|
Settings