Skip to content

Commit b266d3e

Browse files
committed
dev: refactor AbstractConnectionResolver::get_nodes() and get_edges() into prepare_*()
1 parent 1d084e8 commit b266d3e

File tree

1 file changed

+101
-56
lines changed

1 file changed

+101
-56
lines changed

src/Data/Connection/AbstractConnectionResolver.php

Lines changed: 101 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,14 @@ abstract class AbstractConnectionResolver {
126126
/**
127127
* The nodes (usually GraphQL models) returned from the query.
128128
*
129-
* @var \WPGraphQL\Model\Model[]|mixed[]
129+
* @var \WPGraphQL\Model\Model[]|mixed[]|null
130130
*/
131131
protected $nodes;
132132

133133
/**
134134
* The edges for the connection.
135135
*
136-
* @var array<string,mixed>[]
136+
* @var ?array<string,mixed>[]
137137
*/
138138
protected $edges;
139139

@@ -558,19 +558,11 @@ public function get_ids() {
558558
* @throws \Exception
559559
*/
560560
public function get_nodes() {
561-
$nodes = [];
562-
563-
// These are already sliced and ordered, we're just populating node data.
564-
$ids = $this->get_ids_for_nodes();
565-
566-
foreach ( $ids as $id ) {
567-
$model = $this->get_node_by_id( $id );
568-
if ( true === $this->get_is_valid_model( $model ) ) {
569-
$nodes[ $id ] = $model;
570-
}
561+
if ( ! isset( $this->nodes ) ) {
562+
$this->nodes = $this->prepare_nodes();
571563
}
572564

573-
return $nodes;
565+
return $this->nodes;
574566
}
575567

576568
/**
@@ -579,43 +571,11 @@ public function get_nodes() {
579571
* @return array<string,mixed>[]
580572
*/
581573
public function get_edges() {
582-
// Bail early if there are no nodes.
583-
if ( empty( $this->nodes ) ) {
584-
return [];
574+
if ( ! isset( $this->edges ) ) {
575+
$this->edges = $this->prepare_edges( $this->get_nodes() );
585576
}
586577

587-
$edges = [];
588-
589-
// The nodes are already ordered, sliced, and populated. What's left is to populate the edge data for each one.
590-
foreach ( $this->nodes as $id => $node ) {
591-
$edge = [
592-
'cursor' => $this->get_cursor_for_node( $id ),
593-
'node' => $node,
594-
'source' => $this->source,
595-
'connection' => $this,
596-
];
597-
598-
/**
599-
* Create the edge, pass it through a filter.
600-
*
601-
* @param array<string,mixed> $edge The edge within the connection
602-
* @param \WPGraphQL\Data\Connection\AbstractConnectionResolver $connection_resolver Instance of the connection resolver class
603-
*/
604-
$edge = apply_filters(
605-
'graphql_connection_edge',
606-
$edge,
607-
$this
608-
);
609-
610-
/**
611-
* If not empty, add the edge to the edges
612-
*/
613-
if ( ! empty( $edge ) ) {
614-
$edges[] = $edge;
615-
}
616-
}
617-
618-
return $edges;
578+
return $this->edges;
619579
}
620580

621581
/**
@@ -809,22 +769,28 @@ function () {
809769
*
810770
* Filters the nodes in the connection
811771
*
812-
* @param array<int|string,mixed|\WPGraphQL\Model\Model|null> $nodes The nodes in the connection
813-
* @param \WPGraphQL\Data\Connection\AbstractConnectionResolver $connection_resolver Instance of the Connection Resolver
772+
* @todo We reinstantate this here for b/c. Once that is not a concern, we should relocate this filter to ::get_nodes().
773+
*
774+
* @param \WPGraphQL\Model\Model[]|mixed[]|null $nodes The nodes in the connection
775+
* @param self $resolver Instance of the Connection Resolver
814776
*/
815777
$this->nodes = apply_filters( 'graphql_connection_nodes', $this->get_nodes(), $this );
816778

817779
/**
818-
* Filters the edges in the connection
780+
* Filters the edges in the connection.
781+
*
782+
* @todo We reinstantate this here for b/c. Once that is not a concern, we should relocate this filter to ::get_edges().
819783
*
820-
* @param array<int|string,mixed|\WPGraphQL\Model\Model|null> $nodes The nodes in the connection
821-
* @param \WPGraphQL\Data\Connection\AbstractConnectionResolver $connection_resolver Instance of the Connection Resolver
784+
* @param array<string,mixed> $edges The edges in the connection
785+
* @param self $resolver Instance of the Connection Resolver
822786
*/
823787
$this->edges = apply_filters( 'graphql_connection_edges', $this->get_edges(), $this );
824788

789+
// @todo: we should also shortcircuit fetching/populating the actual nodes/edges if we only need one result.
825790
if ( true === $this->one_to_one ) {
826791
// For one to one connections, return the first edge.
827-
$connection = ! empty( $this->edges[ array_key_first( $this->edges ) ] ) ? $this->edges[ array_key_first( $this->edges ) ] : null;
792+
$first_edge_key = array_key_first( $this->edges );
793+
$connection = isset( $first_edge_key ) && ! empty( $this->edges[ $first_edge_key ] ) ? $this->edges[ $first_edge_key ] : null;
828794
} else {
829795
// For plural connections (default) return edges/nodes/pageInfo
830796
$connection = [
@@ -840,8 +806,8 @@ function () {
840806
*
841807
* This filter allows additional fields to be returned to the connection resolver
842808
*
843-
* @param array<string,mixed> $connection The connection data being returned
844-
* @param \WPGraphQL\Data\Connection\AbstractConnectionResolver $connection_resolver The instance of the connection resolver
809+
* @param ?array<string,mixed> $connection The connection data being returned. A single edge or null if the connection is one-to-one.
810+
* @param self $resolver The instance of the connection resolver
845811
*/
846812
return apply_filters( 'graphql_connection', $connection, $this );
847813
}
@@ -978,6 +944,29 @@ public function get_array_index_for_offset( $offset, $ids ) {
978944
return array_search( $offset, array_values( $ids ), true );
979945
}
980946

947+
/**
948+
* Prepares the nodes for the connection.
949+
*
950+
* @used-by self::get_nodes()
951+
*
952+
* @return array<int|string,mixed|\WPGraphQL\Model\Model|null>
953+
*/
954+
protected function prepare_nodes(): array {
955+
$nodes = [];
956+
957+
// These are already sliced and ordered, we're just populating node data.
958+
$ids = $this->get_ids_for_nodes();
959+
960+
foreach ( $ids as $id ) {
961+
$model = $this->get_node_by_id( $id );
962+
if ( true === $this->get_is_valid_model( $model ) ) {
963+
$nodes[ $id ] = $model;
964+
}
965+
}
966+
967+
return $nodes;
968+
}
969+
981970
/**
982971
* Gets the IDs for the currently-paginated slice of nodes.
983972
*
@@ -1033,6 +1022,62 @@ protected function get_is_valid_model( $model ): bool {
10331022
return apply_filters( 'graphql_connection_is_valid_model', $is_valid, $model, $this );
10341023
}
10351024

1025+
/**
1026+
* Prepares the edges for the connection.
1027+
*
1028+
* @used-by self::get_edges()
1029+
*
1030+
* @param array<int|string,mixed|\WPGraphQL\Model\Model|null> $nodes The nodes for the connection.
1031+
*
1032+
* @return array<string,mixed>[]
1033+
*/
1034+
protected function prepare_edges( array $nodes ): array {
1035+
// Bail early if there are no nodes.
1036+
if ( empty( $nodes ) ) {
1037+
return [];
1038+
}
1039+
1040+
// The nodes are already ordered, sliced, and populated. What's left is to populate the edge data for each one.
1041+
$edges = [];
1042+
foreach ( $nodes as $id => $node ) {
1043+
$edge = $this->prepare_edge( $id, $node );
1044+
1045+
/**
1046+
* Filter the edge within the connection.
1047+
*
1048+
* @param array<string,mixed> $edge The edge within the connection
1049+
* @param self $resolver Instance of the connection resolver class
1050+
*/
1051+
$edge = apply_filters(
1052+
'graphql_connection_edge',
1053+
$edge,
1054+
$this
1055+
);
1056+
1057+
$edges[] = $edge;
1058+
}
1059+
1060+
return $edges;
1061+
}
1062+
1063+
/**
1064+
* Prepares a single edge for the connection.
1065+
*
1066+
* @used-by self::prepare_edges()
1067+
*
1068+
* @param int|string $id The ID of the node.
1069+
* @param mixed|\WPGraphQL\Model\Model|null $node The node for the edge.
1070+
*
1071+
* @return array<string,mixed>
1072+
*/
1073+
protected function prepare_edge( $id, $node ): array {
1074+
return [
1075+
'cursor' => $this->get_cursor_for_node( $id ),
1076+
'node' => $node,
1077+
'source' => $this->get_source(),
1078+
'connection' => $this,
1079+
];
1080+
}
10361081

10371082
/**
10381083
* Given an ID, a cursor is returned.

0 commit comments

Comments
 (0)