From b84d74816b393a8edd2cac585664c0c4b8023aef Mon Sep 17 00:00:00 2001 From: Geoff Taylor Date: Wed, 13 Nov 2019 17:31:39 -0500 Subject: [PATCH 1/3] Revert "More connection registration cleanup" This reverts commit 0bf891cb2088977b6c43c79a41272609d3a96632. --- composer.json | 6 +-- includes/class-woocommerce-filters.php | 45 ++++++++++++------- includes/class-wp-graphql-woocommerce.php | 2 +- .../connection/class-product-attributes.php | 12 ++++- .../connection/class-variation-attributes.php | 18 +++++--- .../class-product-connection-resolver.php | 8 ---- 6 files changed, 55 insertions(+), 36 deletions(-) diff --git a/composer.json b/composer.json index 6260152a..c4713a36 100644 --- a/composer.json +++ b/composer.json @@ -44,9 +44,9 @@ "scripts": { "install-wp-tests": "bash bin/install-wp-tests.sh", "test": "vendor/bin/codecept run", - "functional": "vendor/bin/codecept run functional", - "acceptance": "vendor/bin/codecept run acceptance", - "wpunit": "vendor/bin/codecept run wpunit" + "functional-test": "vendor/bin/codecept run functional", + "acceptance-test": "vendor/bin/codecept run acceptance", + "wpunit-test": "vendor/bin/codecept run wpunit" }, "support" : { "issues": "https://github.com/wp-graphql/wp-graphql-woocommerce/issues", diff --git a/includes/class-woocommerce-filters.php b/includes/class-woocommerce-filters.php index 4feca381..de916077 100644 --- a/includes/class-woocommerce-filters.php +++ b/includes/class-woocommerce-filters.php @@ -22,28 +22,22 @@ class WooCommerce_Filters { private static $session_header; /** - * Initializes hooks for WooCommerce-related utilities. + * Register filters */ - public static function setup() { - self::$session_header = apply_filters( 'woocommerce_graphql_session_header_name', 'woocommerce-session' ); + public static function add_filters() { + // Setup QL session handler. if ( ! defined( 'NO_QL_SESSION_HANDLER' ) ) { - add_action( 'init_graphql_request', array( __CLASS__, 'init_graphql_request' ) ); + // Check if request is a GraphQL POST request. + self::$session_header = apply_filters( 'woocommerce_graphql_session_header_name', 'woocommerce-session' ); + if ( self::is_graphql_post_request() ) { + add_filter( 'woocommerce_cookie', array( __CLASS__, 'woocommerce_cookie' ) ); + add_filter( 'woocommerce_session_handler', array( __CLASS__, 'init_ql_session_handler' ) ); + } add_filter( 'graphql_response_headers_to_send', array( __CLASS__, 'add_session_header_to_expose_headers' ) ); add_filter( 'graphql_access_control_allow_headers', array( __CLASS__, 'add_session_header_to_allow_headers' ) ); } } - /** - * Setup QL session handler. - */ - public static function init_graphql_request() { - // Check if request is a GraphQL POST request. - if ( \WPGraphQL\Router::is_graphql_request() ) { - add_filter( 'woocommerce_cookie', array( __CLASS__, 'woocommerce_cookie' ) ); - add_filter( 'woocommerce_session_handler', array( __CLASS__, 'init_ql_session_handler' ) ); - } - } - /** * Filters WooCommerce cookie key to be used as a HTTP Header on GraphQL HTTP requests * @@ -94,4 +88,25 @@ class WooCommerce_Filters { $allowed_headers[] = self::$session_header; return $allowed_headers; } + + /** + * Confirm that the current uri is the GraphQL endpoint. + * + * @return bool + */ + private static function is_graphql_post_request() { + global $wp; + if ( isset( $_SERVER['REQUEST_URI'] ) ) { + $haystack = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ); + $needle = apply_filters( 'graphql_endpoint', 'graphql' ); + $length = strlen( $needle ); + if ( 0 === $length ) { + return true; + } + + return ( substr( $haystack, -$length ) === $needle ); + } + + return false; + } } diff --git a/includes/class-wp-graphql-woocommerce.php b/includes/class-wp-graphql-woocommerce.php index 4116c239..d9dffc80 100644 --- a/includes/class-wp-graphql-woocommerce.php +++ b/includes/class-wp-graphql-woocommerce.php @@ -159,7 +159,7 @@ if ( ! class_exists( 'WP_GraphQL_WooCommerce' ) ) : */ private function setup() { // Register WooCommerce filters. - \WPGraphQL\WooCommerce\WooCommerce_Filters::setup(); + \WPGraphQL\WooCommerce\WooCommerce_Filters::add_filters(); // Register WPGraphQL core filters. \WPGraphQL\WooCommerce\Core_Schema_Filters::add_filters(); diff --git a/includes/connection/class-product-attributes.php b/includes/connection/class-product-attributes.php index f28bbe2d..ec7deef9 100644 --- a/includes/connection/class-product-attributes.php +++ b/includes/connection/class-product-attributes.php @@ -20,7 +20,15 @@ class Product_Attributes { * Registers the various connections from other Types to ProductAttribute */ public static function register_connections() { - register_graphql_connection( self::get_connection_config() ); + // From product types. + $product_types = array_values( \WP_GraphQL_WooCommerce::get_enabled_product_types() ); + foreach ( $product_types as $product_type ) { + register_graphql_connection( + self::get_connection_config( + array( 'fromType' => $product_type ) + ) + ); + } } /** @@ -34,7 +42,7 @@ class Product_Attributes { */ public static function get_connection_config( $args = array() ) { $defaults = array( - 'fromType' => 'Product', + 'fromType' => 'SimpleProduct', 'toType' => 'ProductAttribute', 'fromFieldName' => 'attributes', 'connectionArgs' => array(), diff --git a/includes/connection/class-variation-attributes.php b/includes/connection/class-variation-attributes.php index e7645523..48e7139d 100644 --- a/includes/connection/class-variation-attributes.php +++ b/includes/connection/class-variation-attributes.php @@ -23,14 +23,18 @@ class Variation_Attributes { // From ProductVariation. register_graphql_connection( self::get_connection_config() ); - register_graphql_connection( - self::get_connection_config( - array( - 'fromType' => 'Product', - 'fromFieldName' => 'defaultAttributes', + // From product types. + $product_types = array_values( \WP_GraphQL_WooCommerce::get_enabled_product_types() ); + foreach ( $product_types as $product_type ) { + register_graphql_connection( + self::get_connection_config( + array( + 'fromType' => $product_type, + 'fromFieldName' => 'defaultAttributes', + ) ) - ) - ); + ); + } } /** diff --git a/includes/data/connection/class-product-connection-resolver.php b/includes/data/connection/class-product-connection-resolver.php index 78074956..917d1067 100644 --- a/includes/data/connection/class-product-connection-resolver.php +++ b/includes/data/connection/class-product-connection-resolver.php @@ -164,14 +164,6 @@ class Product_Connection_Resolver extends AbstractConnectionResolver { $query_args['graphql_cursor_offset'] = $cursor_offset; $query_args['graphql_cursor_compare'] = ( ! empty( $last ) ) ? '>' : '<'; - /** - * If the starting offset is not 0 sticky posts will not be queried as the automatic checks in wp-query don't - * trigger due to the page parameter not being set in the query_vars, fixes #732 - */ - if ( 0 !== $cursor_offset ) { - $query_args['ignore_sticky_posts'] = true; - } - /** * Pass the graphql $args to the WP_Query */ From 5d6cab84c6ff3a151837b979b72292bda6807d58 Mon Sep 17 00:00:00 2001 From: Geoff Taylor Date: Wed, 13 Nov 2019 17:32:45 -0500 Subject: [PATCH 2/3] More connection registration cleanup. --- composer.json | 6 +- includes/class-woocommerce-filters.php | 112 ----------- includes/class-wp-graphql-woocommerce.php | 177 ------------------ .../connection/class-product-attributes.php | 12 +- .../connection/class-variation-attributes.php | 18 +- .../class-product-connection-resolver.php | 8 + 6 files changed, 20 insertions(+), 313 deletions(-) delete mode 100644 includes/class-woocommerce-filters.php delete mode 100644 includes/class-wp-graphql-woocommerce.php diff --git a/composer.json b/composer.json index c4713a36..6260152a 100644 --- a/composer.json +++ b/composer.json @@ -44,9 +44,9 @@ "scripts": { "install-wp-tests": "bash bin/install-wp-tests.sh", "test": "vendor/bin/codecept run", - "functional-test": "vendor/bin/codecept run functional", - "acceptance-test": "vendor/bin/codecept run acceptance", - "wpunit-test": "vendor/bin/codecept run wpunit" + "functional": "vendor/bin/codecept run functional", + "acceptance": "vendor/bin/codecept run acceptance", + "wpunit": "vendor/bin/codecept run wpunit" }, "support" : { "issues": "https://github.com/wp-graphql/wp-graphql-woocommerce/issues", diff --git a/includes/class-woocommerce-filters.php b/includes/class-woocommerce-filters.php deleted file mode 100644 index de916077..00000000 --- a/includes/class-woocommerce-filters.php +++ /dev/null @@ -1,112 +0,0 @@ -includes(); - self::$instance->setup(); - } - - /** - * Fire off init action - * - * @param WP_GraphQL_WooCommerce $instance The instance of the WPGraphQLWooCommerce class - */ - do_action( 'graphql_woocommerce_init', self::$instance ); - - /** - * Return the WPGraphQLWooCommerce Instance - */ - return self::$instance; - } - - /** - * Returns WooCommerce post-types registered to the WC_Post_Crud_Loader - * - * @return array - */ - public static function get_post_types() { - return apply_filters( - 'register_graphql_wc_post_types', - array( - 'product', - 'product_variation', - 'shop_coupon', - 'shop_order', - 'shop_order_refund', - ) - ); - } - - /** - * Returns WooCommerce product types to be exposed to the GraphQL schema. - */ - public static function get_enabled_product_types() { - return apply_filters( - 'graphql_enabled_wc_product_types', - array( - 'simple' => 'SimpleProduct', - 'variable' => 'VariableProduct', - 'external' => 'ExternalProduct', - 'grouped' => 'GroupProduct', - ) - ); - } - - /** - * Returns WooCommerce product attribute taxonomies to be registered as - * "TermObject" types in the schema. - * - * @return array - */ - public static function get_product_attribute_taxonomies() { - $attribute_taxonomies = \wc_get_attribute_taxonomies(); - - // Get taxonomy names. - $attributes = array(); - foreach ( $attribute_taxonomies as $tax ) { - $attributes[] = 'pa_' . $tax->attribute_name; - } - - /** - * Filter the $attributes to allow the removal or addition of product attribute taxonomies - * - * @param array $attributes Product attributes being passed. - */ - return apply_filters( - 'register_graphql_wc_product_attributes_taxonomies', - $attributes - ); - } - - /** - * Throw error on object clone. - * The whole idea of the singleton design pattern is that there is a single object - * therefore, we don't want the object to be cloned. - * - * @since 0.0.1 - * @access public - * @return void - */ - public function __clone() { - // Cloning instances of the class is forbidden. - _doing_it_wrong( __FUNCTION__, esc_html__( 'WP_GraphQL_WooCommerce class should not be cloned.', 'wp-graphql-woocommerce' ), '0.0.1' ); - } - - /** - * Disable unserializing of the class. - * - * @since 0.0.1 - * @access protected - * @return void - */ - public function __wakeup() { - // De-serializing instances of the class is forbidden. - _doing_it_wrong( __FUNCTION__, esc_html__( 'De-serializing instances of the WP_GraphQL_WooCommerce class is not allowed', 'wp-graphql-woocommerce' ), '0.0.1' ); - } - - /** - * Include required files. - * Uses composer's autoload - * - * @access private - * @since 0.0.1 - * @return void - */ - private function includes() { - /** - * Autoload Required Classes - */ - if ( defined( 'WPGRAPHQL_WOOCOMMERCE_AUTOLOAD' ) && false !== WPGRAPHQL_WOOCOMMERCE_AUTOLOAD ) { - require_once WPGRAPHQL_WOOCOMMERCE_PLUGIN_DIR . 'vendor/autoload.php'; - } - - // Required non-autoloaded classes. - require_once WPGRAPHQL_WOOCOMMERCE_PLUGIN_DIR . 'access-functions.php'; - require_once WPGRAPHQL_WOOCOMMERCE_PLUGIN_DIR . 'class-inflect.php'; - } - - /** - * Sets up WooGraphQL schema. - */ - private function setup() { - // Register WooCommerce filters. - \WPGraphQL\WooCommerce\WooCommerce_Filters::add_filters(); - - // Register WPGraphQL core filters. - \WPGraphQL\WooCommerce\Core_Schema_Filters::add_filters(); - - // Register WPGraphQL ACF filters. - \WPGraphQL\WooCommerce\ACF_Schema_Filters::add_filters(); - - // Register WPGraphQL JWT Authentication filters. - \WPGraphQL\WooCommerce\JWT_Auth_Schema_Filters::add_filters(); - - $registry = new \WPGraphQL\WooCommerce\Type_Registry(); - add_action( 'graphql_register_types', array( $registry, 'init' ), 10, 1 ); - } - } -endif; diff --git a/includes/connection/class-product-attributes.php b/includes/connection/class-product-attributes.php index ec7deef9..f28bbe2d 100644 --- a/includes/connection/class-product-attributes.php +++ b/includes/connection/class-product-attributes.php @@ -20,15 +20,7 @@ class Product_Attributes { * Registers the various connections from other Types to ProductAttribute */ public static function register_connections() { - // From product types. - $product_types = array_values( \WP_GraphQL_WooCommerce::get_enabled_product_types() ); - foreach ( $product_types as $product_type ) { - register_graphql_connection( - self::get_connection_config( - array( 'fromType' => $product_type ) - ) - ); - } + register_graphql_connection( self::get_connection_config() ); } /** @@ -42,7 +34,7 @@ class Product_Attributes { */ public static function get_connection_config( $args = array() ) { $defaults = array( - 'fromType' => 'SimpleProduct', + 'fromType' => 'Product', 'toType' => 'ProductAttribute', 'fromFieldName' => 'attributes', 'connectionArgs' => array(), diff --git a/includes/connection/class-variation-attributes.php b/includes/connection/class-variation-attributes.php index 48e7139d..e7645523 100644 --- a/includes/connection/class-variation-attributes.php +++ b/includes/connection/class-variation-attributes.php @@ -23,18 +23,14 @@ class Variation_Attributes { // From ProductVariation. register_graphql_connection( self::get_connection_config() ); - // From product types. - $product_types = array_values( \WP_GraphQL_WooCommerce::get_enabled_product_types() ); - foreach ( $product_types as $product_type ) { - register_graphql_connection( - self::get_connection_config( - array( - 'fromType' => $product_type, - 'fromFieldName' => 'defaultAttributes', - ) + register_graphql_connection( + self::get_connection_config( + array( + 'fromType' => 'Product', + 'fromFieldName' => 'defaultAttributes', ) - ); - } + ) + ); } /** diff --git a/includes/data/connection/class-product-connection-resolver.php b/includes/data/connection/class-product-connection-resolver.php index 917d1067..78074956 100644 --- a/includes/data/connection/class-product-connection-resolver.php +++ b/includes/data/connection/class-product-connection-resolver.php @@ -164,6 +164,14 @@ class Product_Connection_Resolver extends AbstractConnectionResolver { $query_args['graphql_cursor_offset'] = $cursor_offset; $query_args['graphql_cursor_compare'] = ( ! empty( $last ) ) ? '>' : '<'; + /** + * If the starting offset is not 0 sticky posts will not be queried as the automatic checks in wp-query don't + * trigger due to the page parameter not being set in the query_vars, fixes #732 + */ + if ( 0 !== $cursor_offset ) { + $query_args['ignore_sticky_posts'] = true; + } + /** * Pass the graphql $args to the WP_Query */ From 8efaa910cce520aef76917cb9634e8003d269ae8 Mon Sep 17 00:00:00 2001 From: Geoff Taylor Date: Wed, 13 Nov 2019 17:35:44 -0500 Subject: [PATCH 3/3] some key files restored. --- includes/class-woocommerce-filters.php | 112 ++++++++++++++ includes/class-wp-graphql-woocommerce.php | 177 ++++++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 includes/class-woocommerce-filters.php create mode 100644 includes/class-wp-graphql-woocommerce.php diff --git a/includes/class-woocommerce-filters.php b/includes/class-woocommerce-filters.php new file mode 100644 index 00000000..de916077 --- /dev/null +++ b/includes/class-woocommerce-filters.php @@ -0,0 +1,112 @@ +includes(); + self::$instance->setup(); + } + + /** + * Fire off init action + * + * @param WP_GraphQL_WooCommerce $instance The instance of the WPGraphQLWooCommerce class + */ + do_action( 'graphql_woocommerce_init', self::$instance ); + + /** + * Return the WPGraphQLWooCommerce Instance + */ + return self::$instance; + } + + /** + * Returns WooCommerce post-types registered to the WC_Post_Crud_Loader + * + * @return array + */ + public static function get_post_types() { + return apply_filters( + 'register_graphql_wc_post_types', + array( + 'product', + 'product_variation', + 'shop_coupon', + 'shop_order', + 'shop_order_refund', + ) + ); + } + + /** + * Returns WooCommerce product types to be exposed to the GraphQL schema. + */ + public static function get_enabled_product_types() { + return apply_filters( + 'graphql_enabled_wc_product_types', + array( + 'simple' => 'SimpleProduct', + 'variable' => 'VariableProduct', + 'external' => 'ExternalProduct', + 'grouped' => 'GroupProduct', + ) + ); + } + + /** + * Returns WooCommerce product attribute taxonomies to be registered as + * "TermObject" types in the schema. + * + * @return array + */ + public static function get_product_attribute_taxonomies() { + $attribute_taxonomies = \wc_get_attribute_taxonomies(); + + // Get taxonomy names. + $attributes = array(); + foreach ( $attribute_taxonomies as $tax ) { + $attributes[] = 'pa_' . $tax->attribute_name; + } + + /** + * Filter the $attributes to allow the removal or addition of product attribute taxonomies + * + * @param array $attributes Product attributes being passed. + */ + return apply_filters( + 'register_graphql_wc_product_attributes_taxonomies', + $attributes + ); + } + + /** + * Throw error on object clone. + * The whole idea of the singleton design pattern is that there is a single object + * therefore, we don't want the object to be cloned. + * + * @since 0.0.1 + * @access public + * @return void + */ + public function __clone() { + // Cloning instances of the class is forbidden. + _doing_it_wrong( __FUNCTION__, esc_html__( 'WP_GraphQL_WooCommerce class should not be cloned.', 'wp-graphql-woocommerce' ), '0.0.1' ); + } + + /** + * Disable unserializing of the class. + * + * @since 0.0.1 + * @access protected + * @return void + */ + public function __wakeup() { + // De-serializing instances of the class is forbidden. + _doing_it_wrong( __FUNCTION__, esc_html__( 'De-serializing instances of the WP_GraphQL_WooCommerce class is not allowed', 'wp-graphql-woocommerce' ), '0.0.1' ); + } + + /** + * Include required files. + * Uses composer's autoload + * + * @access private + * @since 0.0.1 + * @return void + */ + private function includes() { + /** + * Autoload Required Classes + */ + if ( defined( 'WPGRAPHQL_WOOCOMMERCE_AUTOLOAD' ) && false !== WPGRAPHQL_WOOCOMMERCE_AUTOLOAD ) { + require_once WPGRAPHQL_WOOCOMMERCE_PLUGIN_DIR . 'vendor/autoload.php'; + } + + // Required non-autoloaded classes. + require_once WPGRAPHQL_WOOCOMMERCE_PLUGIN_DIR . 'access-functions.php'; + require_once WPGRAPHQL_WOOCOMMERCE_PLUGIN_DIR . 'class-inflect.php'; + } + + /** + * Sets up WooGraphQL schema. + */ + private function setup() { + // Register WooCommerce filters. + \WPGraphQL\WooCommerce\WooCommerce_Filters::add_filters(); + + // Register WPGraphQL core filters. + \WPGraphQL\WooCommerce\Core_Schema_Filters::add_filters(); + + // Register WPGraphQL ACF filters. + \WPGraphQL\WooCommerce\ACF_Schema_Filters::add_filters(); + + // Register WPGraphQL JWT Authentication filters. + \WPGraphQL\WooCommerce\JWT_Auth_Schema_Filters::add_filters(); + + $registry = new \WPGraphQL\WooCommerce\Type_Registry(); + add_action( 'graphql_register_types', array( $registry, 'init' ), 10, 1 ); + } + } +endif;