Home

Awesome

Logo

WPGraphQL for FacetWP

Adds WPGraphQL support for FacetWP.


Packagist License Packagist Version GitHub commits since latest release (by SemVer) GitHub forks GitHub Repo stars<br /> CodeQuality GitHub Workflow Status Coding Standards


Overview

This plugin exposes configured facets through the graph schema. Once registered for a type, a query is available. The payload includes both facet choices and information and a connection to the post type data. This allows for standard GraphQL pagination of the returned data set.

This plugin has been tested and is functional with SearchWP.

System Requirements

Quick Install

  1. Install & activate WPGraphQL.
  2. Install & activate FacetWP.
  3. Download the latest release .zip file, upload it to your WordPress install, and activate the plugin.

With Composer

composer require hsimah-services/wp-graphql-facetwp

Updating and Versioning

As we work towards a 1.0 Release, we will need to introduce numerous breaking changes. We will do our best to group multiple breaking changes together in a single release, to make it easier on developers to keep their projects up-to-date.

Until we hit v1.0, we're using a modified version of SemVer, where:

Development and Support

WPGraphQL for FacetWP was initially created by Hamish Blake. Maintainance and development are now provided by AxePress Development. Community contributions are welcome and encouraged.

Basic support is provided for free, both in this repo and at the #facetwp channel in WPGraphQL Slack.

Priority support and custom development is available to AxePress Development sponsors.

Usage:

Registering a facet to WPGraphQL

It is assumed that facets have been configured.

To register a FacetWP query in the WPGraphQL schema for a WordPress post type (eg post) simply call the following function:

// Register facet for Posts
add_action( 'graphql_facetwp_init', function () {
  register_graphql_facet_type( 'post' );
} );

This will create a WPGraphQL postFacet field on the RootQuery. The payload includes a collection of queried facets and a posts connection. The connection is a standard WPGraphQL connection supporting pagination and server side ordering. The connection payload only includes filtered posts.

Example query

Note This is not a complete list of GraphQL fields and types added to the schema. Please refer to the WPGraph<strong>i</strong>QL IDE for more queries and their documentation.

query GetPostsByFacet( $query: FacetQueryArgs, $after: String, $search: String, $orderBy: [PostObjectsConnectionOrderbyInput] ) {
  postFacet(
    where: { 
      status: PUBLISH,
      query: $query # The query arguments are determined by the Facet type.
    }
  ) {
    facets { # The facet configuration
      selected
      name
      label
      choices {
        value
        label
        count
      }
    }
    posts ( # The results of the facet query. Can be filtered by WPGraphQL connection where args 
      first: 10,
      after: $after,
      where: { search: $search, orderby: $orderBy} # The `orderby` arg is ignored if using the Sort facet.
    ) {
      pageInfo {
        hasNextPage
        endCursor
      }
      nodes {
        title
        excerpt
      }
    }
  }
}

WooCommerce Support

Support for WooCommerce Products can be added with following configuration:

// This is the same as all CPTs.
add_action( 'graphql_facetwp_init', function () {
  register_graphql_facet_type( 'product' );
});

// This is required because WooGQL uses a custom connection resolver.
add_filter( 'facetwp_graphql_facet_connection_config', 
  function ( array $default_graphql_config, array $facet_config ) {
    $type = $config['type'];

    $use_graphql_pagination = \WPGraphQL\FacetWP\Registry\FacetRegistry::use_graphql_pagination();

    return array_merge(
      $default_graphql_config,
      [
        'connectionArgs'    => \WPGraphQL\WooCommerce\Connection\Products::get_connection_args(),
        'resolveNode'       => function ( $node, $_args, $context ) use ( $type ) {
            return $context->get_loader( $type )->load_deferred( $node->ID );
        },
        'resolve'           => function ( $source, $args, $context, $info ) use ( $type, $use_graphql_pagination ) {
          // If we're using FWP's offset pagination, we need to override the connection args.
            if ( ! $use_graphql_pagination ) {
              $args['first'] = $source['pager']['per_page'];
            }

            $resolver = new \WPGraphQL\Data\Connection\PostObjectConnectionResolver( $source, $args, $context, $info, $type );

            // Override the connection results with the FWP results.
            if( ! empty( $source['results'] ) ) {
              $resolver->->set_query_arg( 'post__in', $source['results'] );
            }

            // Use post__in when delegating sorting to FWP.
            if ( ! empty( $source['is_sort'] ) ) {
              $resolver->set_query_arg( 'orderby', 'post__in' );
            } elseif( 'product' === $type ) {
              // If we're relying on WPGQL to sort, we need to to handle WooCommerce meta.
              $resolver = Products::set_ordering_query_args( $resolver, $args );
            }

            return $resolver ->get_connection();
        },
      ]
    );
  },
  100,
  2
);

Limitations

Currently the plugin only has been tested using Checkbox, Radio, and Sort facet types. Support for additional types is in development.

Testing

  1. Update your .env file to your testing environment specifications.
  2. Run composer install-test-env to create the test environment.
  3. Run your test suite with Codeception. E.g. vendor/bin/codecept run wpunit will run all WPUnit tests.