Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The .gitignore rules were still ingoring some necessary vendor files
- Loading branch information
Showing
9 changed files
with
1,725 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
178 changes: 178 additions & 0 deletions
178
vendor/ivome/graphql-relay-php/src/Connection/ArrayConnection.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
<?php | ||
/** | ||
* @author: Ivo Meißner | ||
* Date: 22.02.16 | ||
* Time: 18:54 | ||
*/ | ||
|
||
namespace GraphQLRelay\Connection; | ||
|
||
|
||
class ArrayConnection | ||
{ | ||
const PREFIX = 'arrayconnection:'; | ||
|
||
/** | ||
* Creates the cursor string from an offset. | ||
*/ | ||
public static function offsetToCursor($offset) | ||
{ | ||
return base64_encode(self::PREFIX . $offset); | ||
} | ||
|
||
/** | ||
* Rederives the offset from the cursor string. | ||
*/ | ||
public static function cursorToOffset($cursor) | ||
{ | ||
$offset = substr(base64_decode($cursor), strlen(self::PREFIX)); | ||
if (is_numeric($offset)){ | ||
return intval($offset); | ||
} else { | ||
return null; | ||
} | ||
} | ||
|
||
/** | ||
* Given an optional cursor and a default offset, returns the offset | ||
* to use; if the cursor contains a valid offset, that will be used, | ||
* otherwise it will be the default. | ||
*/ | ||
public static function getOffsetWidthDefault($cursor, $defaultOffset) | ||
{ | ||
if ($cursor == null){ | ||
return $defaultOffset; | ||
} | ||
$offset = self::cursorToOffset($cursor); | ||
return $offset !== null ? $offset: $defaultOffset; | ||
} | ||
|
||
/** | ||
* A simple function that accepts an array and connection arguments, and returns | ||
* a connection object for use in GraphQL. It uses array offsets as pagination, | ||
* so pagination will only work if the array is static. | ||
* @param array $data | ||
* @param $args | ||
* | ||
* @return array | ||
*/ | ||
public static function connectionFromArray(array $data, $args) | ||
{ | ||
return self::connectionFromArraySlice($data, $args, [ | ||
'sliceStart' => 0, | ||
'arrayLength' => count($data) | ||
]); | ||
} | ||
|
||
/** | ||
* Given a slice (subset) of an array, returns a connection object for use in | ||
* GraphQL. | ||
* | ||
* This function is similar to `connectionFromArray`, but is intended for use | ||
* cases where you know the cardinality of the connection, consider it too large | ||
* to materialize the entire array, and instead wish pass in a slice of the | ||
* total result large enough to cover the range specified in `args`. | ||
* | ||
* @return array | ||
*/ | ||
public static function connectionFromArraySlice(array $arraySlice, $args, $meta) | ||
{ | ||
$after = self::getArrayValueSafe($args, 'after'); | ||
$before = self::getArrayValueSafe($args, 'before'); | ||
$first = self::getArrayValueSafe($args, 'first'); | ||
$last = self::getArrayValueSafe($args, 'last'); | ||
$sliceStart = self::getArrayValueSafe($meta, 'sliceStart'); | ||
$arrayLength = self::getArrayValueSafe($meta, 'arrayLength'); | ||
$sliceEnd = $sliceStart + count($arraySlice); | ||
$beforeOffset = self::getOffsetWidthDefault($before, $arrayLength); | ||
$afterOffset = self::getOffsetWidthDefault($after, -1); | ||
|
||
$startOffset = max([ | ||
$sliceStart - 1, | ||
$afterOffset, | ||
-1 | ||
]) + 1; | ||
|
||
$endOffset = min([ | ||
$sliceEnd, | ||
$beforeOffset, | ||
$arrayLength | ||
]); | ||
if ($first !== null) { | ||
$endOffset = min([ | ||
$endOffset, | ||
$startOffset + $first | ||
]); | ||
} | ||
|
||
if ($last !== null) { | ||
$startOffset = max([ | ||
$startOffset, | ||
$endOffset - $last | ||
]); | ||
} | ||
|
||
$slice = array_slice($arraySlice, | ||
max($startOffset - $sliceStart, 0), | ||
count($arraySlice) - ($sliceEnd - $endOffset) - max($startOffset - $sliceStart, 0) | ||
); | ||
|
||
$edges = array_map(function($item, $index) use ($startOffset) { | ||
return [ | ||
'cursor' => self::offsetToCursor($startOffset + $index), | ||
'node' => $item | ||
]; | ||
}, $slice, array_keys($slice)); | ||
|
||
$firstEdge = $edges ? $edges[0] : null; | ||
$lastEdge = $edges ? $edges[count($edges) - 1] : null; | ||
$lowerBound = $after ? ($afterOffset + 1) : 0; | ||
$upperBound = $before ? ($beforeOffset) : $arrayLength; | ||
|
||
return [ | ||
'edges' => $edges, | ||
'pageInfo' => [ | ||
'startCursor' => $firstEdge ? $firstEdge['cursor'] : null, | ||
'endCursor' => $lastEdge ? $lastEdge['cursor'] : null, | ||
'hasPreviousPage' => $last !== null ? $startOffset > $lowerBound : false, | ||
'hasNextPage' => $first !== null ? $endOffset < $upperBound : false | ||
] | ||
]; | ||
} | ||
|
||
/** | ||
* Return the cursor associated with an object in an array. | ||
* | ||
* @param array $data | ||
* @param $object | ||
* @return null|string | ||
*/ | ||
public static function cursorForObjectInConnection(array $data, $object) | ||
{ | ||
$offset = -1; | ||
for ($i = 0; $i < count($data); $i++) { | ||
if ($data[$i] == $object){ | ||
$offset = $i; | ||
break; | ||
} | ||
} | ||
|
||
if ($offset === -1) { | ||
return null; | ||
} | ||
|
||
return self::offsetToCursor($offset); | ||
} | ||
|
||
/** | ||
* Returns the value for the given array key, NULL, if it does not exist | ||
* | ||
* @param array $array | ||
* @param string $key | ||
* @return mixed | ||
*/ | ||
protected static function getArrayValueSafe(array $array, $key) | ||
{ | ||
return array_key_exists($key, $array) ? $array[$key] : null; | ||
} | ||
} |
195 changes: 195 additions & 0 deletions
195
vendor/ivome/graphql-relay-php/src/Connection/Connection.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
<?php | ||
/** | ||
* @author: Ivo Meißner | ||
* Date: 22.02.16 | ||
* Time: 17:15 | ||
*/ | ||
|
||
namespace GraphQLRelay\Connection; | ||
|
||
use GraphQL\Type\Definition\ObjectType; | ||
use GraphQL\Type\Definition\Type; | ||
|
||
class Connection { | ||
/** | ||
* @var ObjectType | ||
*/ | ||
protected static $pageInfoType; | ||
|
||
/** | ||
* Returns a GraphQLFieldConfigArgumentMap appropriate to include on a field | ||
* whose return type is a connection type with forward pagination. | ||
* | ||
* @return array | ||
*/ | ||
public static function forwardConnectionArgs() | ||
{ | ||
return [ | ||
'after' => [ | ||
'type' => Type::string() | ||
], | ||
'first' => [ | ||
'type' => Type::int() | ||
] | ||
]; | ||
} | ||
|
||
/** | ||
* Returns a GraphQLFieldConfigArgumentMap appropriate to include on a field | ||
* whose return type is a connection type with backward pagination. | ||
* | ||
* @return array | ||
*/ | ||
public static function backwardConnectionArgs() | ||
{ | ||
return [ | ||
'before' => [ | ||
'type' => Type::string() | ||
], | ||
'last' => [ | ||
'type' => Type::int() | ||
] | ||
]; | ||
} | ||
|
||
/** | ||
* Returns a GraphQLFieldConfigArgumentMap appropriate to include on a field | ||
* whose return type is a connection type with bidirectional pagination. | ||
* | ||
* @return array | ||
*/ | ||
public static function connectionArgs() | ||
{ | ||
return array_merge( | ||
self::forwardConnectionArgs(), | ||
self::backwardConnectionArgs() | ||
); | ||
} | ||
|
||
/** | ||
* Returns a GraphQLObjectType for a connection with the given name, | ||
* and whose nodes are of the specified type. | ||
*/ | ||
public static function connectionDefinitions(array $config) | ||
{ | ||
return [ | ||
'edgeType' => self::createEdgeType($config), | ||
'connectionType' => self::createConnectionType($config) | ||
]; | ||
} | ||
|
||
/** | ||
* Returns a GraphQLObjectType for a connection with the given name, | ||
* and whose nodes are of the specified type. | ||
* | ||
* @return ObjectType | ||
*/ | ||
public static function createConnectionType(array $config) | ||
{ | ||
if (!array_key_exists('nodeType', $config)){ | ||
throw new \InvalidArgumentException('Connection config needs to have at least a node definition'); | ||
} | ||
$nodeType = $config['nodeType']; | ||
$name = array_key_exists('name', $config) ? $config['name'] : $nodeType->name; | ||
$connectionFields = array_key_exists('connectionFields', $config) ? $config['connectionFields'] : []; | ||
$edgeType = array_key_exists('edgeType', $config) ? $config['edgeType'] : null; | ||
|
||
$connectionType = new ObjectType([ | ||
'name' => $name . 'Connection', | ||
'description' => 'A connection to a list of items.', | ||
'fields' => function() use ($edgeType, $connectionFields, $config) { | ||
return array_merge([ | ||
'pageInfo' => [ | ||
'type' => Type::nonNull(self::pageInfoType()), | ||
'description' => 'Information to aid in pagination.' | ||
], | ||
'edges' => [ | ||
'type' => Type::listOf($edgeType ?: self::createEdgeType($config)), | ||
'description' => 'Information to aid in pagination' | ||
] | ||
], self::resolveMaybeThunk($connectionFields)); | ||
} | ||
]); | ||
|
||
return $connectionType; | ||
} | ||
|
||
/** | ||
* Returns a GraphQLObjectType for an edge with the given name, | ||
* and whose nodes are of the specified type. | ||
* | ||
* @param array $config | ||
* @return ObjectType | ||
*/ | ||
public static function createEdgeType(array $config) | ||
{ | ||
if (!array_key_exists('nodeType', $config)){ | ||
throw new \InvalidArgumentException('Edge config needs to have at least a node definition'); | ||
} | ||
$nodeType = $config['nodeType']; | ||
$name = array_key_exists('name', $config) ? $config['name'] : $nodeType->name; | ||
$edgeFields = array_key_exists('edgeFields', $config) ? $config['edgeFields'] : []; | ||
$resolveNode = array_key_exists('resolveNode', $config) ? $config['resolveNode'] : null; | ||
$resolveCursor = array_key_exists('resolveCursor', $config) ? $config['resolveCursor'] : null; | ||
|
||
$edgeType = new ObjectType(array_merge([ | ||
'name' => $name . 'Edge', | ||
'description' => 'An edge in a connection', | ||
'fields' => function() use ($nodeType, $resolveNode, $resolveCursor, $edgeFields) { | ||
return array_merge([ | ||
'node' => [ | ||
'type' => $nodeType, | ||
'resolve' => $resolveNode, | ||
'description' => 'The item at the end of the edge' | ||
], | ||
'cursor' => [ | ||
'type' => Type::nonNull(Type::string()), | ||
'resolve' => $resolveCursor, | ||
'description' => 'A cursor for use in pagination' | ||
] | ||
], self::resolveMaybeThunk($edgeFields)); | ||
} | ||
])); | ||
|
||
return $edgeType; | ||
} | ||
|
||
/** | ||
* The common page info type used by all connections. | ||
* | ||
* @return ObjectType | ||
*/ | ||
public static function pageInfoType() | ||
{ | ||
if (self::$pageInfoType === null){ | ||
self::$pageInfoType = new ObjectType([ | ||
'name' => 'PageInfo', | ||
'description' => 'Information about pagination in a connection.', | ||
'fields' => [ | ||
'hasNextPage' => [ | ||
'type' => Type::nonNull(Type::boolean()), | ||
'description' => 'When paginating forwards, are there more items?' | ||
], | ||
'hasPreviousPage' => [ | ||
'type' => Type::nonNull(Type::boolean()), | ||
'description' => 'When paginating backwards, are there more items?' | ||
], | ||
'startCursor' => [ | ||
'type' => Type::string(), | ||
'description' => 'When paginating backwards, the cursor to continue.' | ||
], | ||
'endCursor' => [ | ||
'type' => Type::string(), | ||
'description' => 'When paginating forwards, the cursor to continue.' | ||
] | ||
] | ||
]); | ||
} | ||
return self::$pageInfoType; | ||
} | ||
|
||
protected static function resolveMaybeThunk ($thinkOrThunk) | ||
{ | ||
return is_callable($thinkOrThunk) ? call_user_func($thinkOrThunk) : $thinkOrThunk; | ||
} | ||
} |
Oops, something went wrong.