Source of file FragmentBuilder.php
Size: 6,793 Bytes - Last Modified: 2021-12-24T07:09:53+00:00
/var/www/docs.ssmods.com/process/src/src/Services/FragmentBuilder.php
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 | <?php namespace SilverStripe\NextJS\Services; use GraphQL\Type\Definition\EnumType; use GraphQL\Type\Definition\InterfaceType; use GraphQL\Type\Definition\ObjectType; use GraphQL\Type\Definition\Type; use GraphQL\Type\Definition\TypeWithFields; use SilverStripe\Core\Injector\Injectable; use SilverStripe\GraphQL\Schema\DataObject\InterfaceBuilder; use SilverStripe\GraphQL\Schema\Exception\SchemaBuilderException; use GraphQL\Type\Schema as GraphQLSchema; use SilverStripe\GraphQL\Schema\SchemaConfig; use Exception; class FragmentBuilder { use Injectable; /** * @var GraphQLSchema */ private $schema; /** * @var SchemaConfig */ private $config; /** * @var string[] */ private $baseFields; /** * @var int */ private $maxNesting = 2; /** * FragmentBuilder constructor. * @param GraphQLSchema $schema * @param SchemaConfig $config * @param array $baseFields */ public function __construct(GraphQLSchema $schema, SchemaConfig $config, array $baseFields = []) { $this->schema = $schema; $this->config = $config; $this->baseFields = $baseFields; } /** * @param string $class * @param null $name * @return string|null * @throws SchemaBuilderException */ public function getFragmentForClass(string $class, $name = null): ?string { $typeName = $this->getConfig()->getTypeNameForClass($class); if (!$typeName) { return null; } try { $type = $this->getSchema()->getType($typeName); if (!$type instanceof ObjectType) { return null; } } catch (Exception $e) { return null; } $fragmentName = $name ?? $typeName . 'Fields'; $result = $this->getFieldsForType($type); if (empty($result)) { return null; } $body = $this->formatResult($result); $parts = [ sprintf('fragment %s on %s {', $fragmentName, $typeName), $body, '}' ]; return implode("\n", $parts); } /** * @param TypeWithFields $type * @param int $level * @return array|string[] * @throws SchemaBuilderException */ private function getFieldsForType(TypeWithFields $type, int $level = 1): array { $interfaceName = $type instanceof InterfaceType ? $type->name : InterfaceBuilder::interfaceName($type->name, $this->getConfig()); $leafInterfaceName = null; try { $interface = $this->getSchema()->getType($interfaceName); if ($interface instanceof InterfaceType) { $leafInterfaceName = $interface->name; } else { return []; } } catch (Exception $e) {} $result = []; foreach ($this->baseFields as $baseField) { $result[$baseField] = true; } $ignoreFields = []; $inheritedInterfaces = array_filter( $type->getInterfaces(), function (InterfaceType $i) use ($leafInterfaceName) { return !$leafInterfaceName || $i->name !== $leafInterfaceName; } ); foreach ($inheritedInterfaces as $interface) { $ignoreFields = array_unique( array_merge($ignoreFields, $interface->getFieldNames()) ); } foreach ($type->getFields() as $field) { if (in_array($field->name, $ignoreFields)) { continue; } $nestedTypeObj = Type::getNamedType($field->getType()); if (Type::isBuiltInType($nestedTypeObj)) { $result[$field->name] = true; continue; } if($nestedTypeObj instanceof TypeWithFields) { $result[$field->name] = [ '__typename ## add your fields below' => true ]; continue; } if ($nestedTypeObj instanceof EnumType) { $result[$field->name] = true; continue; } // try { // if (!$nestedTypeObj instanceof TypeWithFields) { // continue; // } // } catch (Exception $e) { // continue; // } // // // Block recursion // if ($level === $this->getMaxNesting()) { // continue; // } // $nestedFields = $nestedTypeObj->getFields(); // if (isset($nestedFields['edges']) && isset($nestedFields['nodes'])) { // $nodeType = Type::getNamedType($nestedFields['nodes']->getType()); // if (!$nodeType instanceof TypeWithFields || $nodeType === $type) { // continue; // } // $nodeFields = $this->getFieldsForType($nodeType, $level + 1); // if (!empty($nodeFields)) { // $result[$field->name]['nodes'] = $nodeFields; // } // } else { // $nodeFields = $this->getFieldsForType($nestedTypeObj, $level + 1); // if (!empty($nodeFields)) { // $result[$field->name] = $nodeFields; // } // } } return $result; } /** * @return GraphQLSchema */ public function getSchema(): GraphQLSchema { return $this->schema; } /** * @return SchemaConfig */ public function getConfig(): SchemaConfig { return $this->config; } /** * @return int */ public function getMaxNesting(): int { return $this->maxNesting; } /** * @param int $maxNesting */ public function setMaxNesting(int $maxNesting): void { $this->maxNesting = $maxNesting; } /** * @param array $fields * @param int $level * @return string */ private function formatResult(array $fields, $level = 1): string { $tabs = str_repeat("\t", $level); $result = ''; foreach ($fields as $field => $branch) { if (!is_array($branch)) { $result .= sprintf('%s%s%s', $tabs, $field, "\n"); continue; } if (empty($branch)) { continue; } $result .= sprintf( '%s%s { %s %s%s}%s', $tabs, $field, "\n", $this->formatResult($branch, $level + 1), $tabs, "\n" ); } return $result; } } |