mirror of
https://github.com/wp-graphql/wp-graphql-woocommerce.git
synced 2026-08-14 12:53:44 +02:00
* fix: address WordPress.org plugin review feedback - Prefix the session transaction queue transient with the plugin's graphql_woocommerce_ namespace instead of the generic "woo_" word, to avoid collisions (Plugin Directory: prefix data storage). - Declare the WooCommerce dependency via the "Requires Plugins: woocommerce" plugin header. - Bump README.txt "Tested up to" to 7.0. - Ship composer.json in the distributed plugin (drop it, and composer.lock, from composer archive excludes) so the build is reproducible/reviewable. * chore: rename plugin to "GraphQL for eCommerce" for trademark compliance The WordPress.org plugin review flagged the display name/slug for beginning with the "WPGraphQL" trademark (and the "WooGraphQL" portmanteau of the WooCommerce mark), which can imply official affiliation. - Display name (plugin header + readme title) -> "GraphQL for eCommerce". - Slug/text domain -> "graphql-for-ecommerce" (header, all i18n string literals, and the PHPCS WordPress.WP.I18n text_domain config). - Update user-facing notices/errors that named the old plugin. "WooGraphQL" remains the project's informal nickname (repo, docs, community), just not in the WordPress.org directory's official name/slug. Internal file names and GitHub URLs are unchanged. * fix: keep test-only dev deps out of the committed composer.json The committed manifest mirrors develop (lint/stan dev deps only); CI adds the test suite deps at runtime via `composer installTestEnv`. A previous commit captured the installTestEnv-modified composer.json, desyncing it from composer.lock and breaking `composer install` in CI. * chore: regenerate composer.lock (refresh dev dependencies) Regenerate the lock from the manifest so it is in sync (fixes the CI `composer install` failure) and refresh dependencies in the process — firebase/php-jwt v7.0.4 -> v7.1.0 plus 11 others, with vendor-prefixed re-strauss'd to match. Full wpunit suite passes against the updated deps (305 tests, 835 assertions). * chore: rename text domain in createdVia/attribution strings from #1018 #1018 (createdVia + order attribution) merged into develop after the rename commit was authored, so its new i18n strings still used the old 'wp-graphql-woocommerce' text domain. Update them to 'graphql-for-ecommerce' to match the rename.
295 lines
7.3 KiB
PHP
295 lines
7.3 KiB
PHP
<?php
|
|
/**
|
|
* DataLoader - WC_Db_Loader
|
|
*
|
|
* Loads Models for WooCommerce objects defined in custom DB tables.
|
|
*
|
|
* @package WPGraphQL\WooCommerce\Data\Loader
|
|
* @since 0.5.0
|
|
*/
|
|
|
|
namespace WPGraphQL\WooCommerce\Data\Loader;
|
|
|
|
use GraphQL\Error\UserError;
|
|
use WPGraphQL\Data\Loader\AbstractDataLoader;
|
|
use WPGraphQL\WooCommerce\Data\Factory;
|
|
use WPGraphQL\WooCommerce\Model\Shipping_Method;
|
|
use WPGraphQL\WooCommerce\Model\Shipping_Zone;
|
|
use WPGraphQL\WooCommerce\Model\Tax_Rate;
|
|
|
|
/**
|
|
* Class WC_Db_Loader
|
|
*/
|
|
class WC_Db_Loader extends AbstractDataLoader {
|
|
/**
|
|
* Stores loaded data objects.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $loaded_objects;
|
|
|
|
/**
|
|
* Loader type
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $loader_type;
|
|
|
|
/**
|
|
* WC_Db_Loader constructor
|
|
*
|
|
* @param \WPGraphQL\AppContext $context AppContext instance.
|
|
* @param string $loader_type Type of loader be initialized.
|
|
*/
|
|
public function __construct( $context, $loader_type ) {
|
|
$this->loader_type = $loader_type;
|
|
|
|
parent::__construct( $context );
|
|
}
|
|
|
|
/**
|
|
* Given array of keys, loads and returns a map consisting of keys from `keys` array and loaded
|
|
* posts as the values
|
|
*
|
|
* @param array $keys - array of IDs.
|
|
*
|
|
* @return array
|
|
* @throws \Exception Invalid loader type.
|
|
*/
|
|
public function loadKeys( array $keys ) {
|
|
$loader = null;
|
|
switch ( $this->loader_type ) {
|
|
case 'CART_ITEM':
|
|
$loader = [ $this, 'load_cart_item_from_key' ];
|
|
break;
|
|
case 'DOWNLOADABLE_ITEM':
|
|
$loader = [ $this, 'load_downloadable_item_from_id' ];
|
|
break;
|
|
case 'TAX_CLASS':
|
|
$loader = [ $this, 'load_tax_class_from_slug' ];
|
|
break;
|
|
case 'TAX_RATE':
|
|
$loader = [ $this, 'load_tax_rate_from_id' ];
|
|
break;
|
|
case 'ORDER_ITEM':
|
|
$loader = [ $this, 'load_order_item_from_id' ];
|
|
break;
|
|
case 'SHIPPING_METHOD':
|
|
$loader = [ $this, 'load_shipping_method_from_id' ];
|
|
break;
|
|
case 'SHIPPING_ZONE':
|
|
$loader = [ $this, 'load_shipping_zone_from_id' ];
|
|
break;
|
|
default:
|
|
/**
|
|
* For adding custom key types to this loader
|
|
*
|
|
* @param callable|null $loader Callback that gets entry from key.
|
|
* @param string $loader_type Used to determine loader being used for this instance of the loader.
|
|
*/
|
|
$loader = apply_filters( 'woographql_db_loader_func', null, $this->loader_type );
|
|
|
|
if ( empty( $loader ) ) {
|
|
throw new \Exception(
|
|
/* translators: %s: Loader Type */
|
|
sprintf( __( 'Loader type invalid: %s', 'graphql-for-ecommerce' ), $this->loader_type )
|
|
);
|
|
}
|
|
}//end switch
|
|
|
|
$loaded_items = [];
|
|
|
|
/**
|
|
* Loop over the keys and return an array of items.
|
|
*/
|
|
foreach ( $keys as $key ) {
|
|
$loaded_items[ $key ] = call_user_func( $loader, $key );
|
|
}
|
|
|
|
return ! empty( $loaded_items ) ? $loaded_items : [];
|
|
}
|
|
|
|
/**
|
|
* Returns the cart item connected the provided key.
|
|
*
|
|
* @param string $key - Cart item key.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function load_cart_item_from_key( $key ) {
|
|
// Add the cart item's product and product variation to WC-CPT buffer.
|
|
return Factory::resolve_cart()->get_cart_item( $key );
|
|
}
|
|
|
|
/**
|
|
* Returns the downloadable item connected the provided IDs.
|
|
*
|
|
* @param int $id - Downloadable item ID.
|
|
*
|
|
* @return \WC_Customer_Download|null
|
|
*/
|
|
public function load_downloadable_item_from_id( $id ) {
|
|
$node = new \WC_Customer_Download( $id );
|
|
return 0 === $node->get_id() ? $node : null;
|
|
}
|
|
|
|
/**
|
|
* Returns the tax class connected the provided IDs.
|
|
*
|
|
* @param int $slug - Tax class slug.
|
|
*
|
|
* @return array|null
|
|
*/
|
|
public function load_tax_class_from_slug( $slug ) {
|
|
if ( 'standard' === $slug ) {
|
|
return [
|
|
'slug' => 'standard',
|
|
'name' => __( 'Standard rate', 'graphql-for-ecommerce' ),
|
|
];
|
|
} else {
|
|
$tax_class = \WC_Tax::get_tax_class_by( 'slug', $slug );
|
|
return is_array( $tax_class ) && ! empty( $tax_class ) ? $tax_class : null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the tax rate connected the provided IDs.
|
|
*
|
|
* @param int $id - Tax rate IDs.
|
|
*
|
|
* @return \WPGraphQL\WooCommerce\Model\Tax_Rate|null
|
|
*/
|
|
public function load_tax_rate_from_id( $id ) {
|
|
global $wpdb;
|
|
|
|
/**
|
|
* Get tax rate from WooCommerce.
|
|
*
|
|
* @var \stdClass&object{
|
|
* tax_rate_id: int,
|
|
* tax_rate_class: string,
|
|
* tax_rate_country: string,
|
|
* tax_rate_state: string,
|
|
* tax_rate: string,
|
|
* tax_rate_name: string,
|
|
* tax_rate_priority: int,
|
|
* tax_rate_compound: bool,
|
|
* tax_rate_shipping: bool,
|
|
* tax_rate_order: int,
|
|
* tax_rate_city: string,
|
|
* tax_rate_postcode: string,
|
|
* tax_rate_postcodes: string,
|
|
* tax_rate_cities: string
|
|
* } $rate
|
|
*/
|
|
$rate = \WC_Tax::_get_tax_rate( $id, OBJECT );
|
|
if ( ! empty( $rate ) && is_object( $rate ) ) {
|
|
$rate->tax_rate_city = '';
|
|
$rate->tax_rate_postcode = '';
|
|
$rate->tax_rate_postcodes = '';
|
|
$rate->tax_rate_cities = '';
|
|
|
|
// Get locales from a tax rate.
|
|
// phpcs:ignore WordPress.DB.DirectDatabaseQuery
|
|
$locales = $wpdb->get_results(
|
|
$wpdb->prepare(
|
|
"
|
|
SELECT location_code, location_type
|
|
FROM {$wpdb->prefix}woocommerce_tax_rate_locations
|
|
WHERE tax_rate_id = %d
|
|
",
|
|
$rate->tax_rate_id
|
|
)
|
|
);
|
|
|
|
$cities = [];
|
|
$postcodes = [];
|
|
foreach ( $locales as $locale ) {
|
|
if ( 'city' === $locale->location_type ) {
|
|
$cities[] = $locale->location_code;
|
|
} elseif ( 'postcode' === $locale->location_type ) {
|
|
$postcodes[] = $locale->location_code;
|
|
} else {
|
|
$rate->{'tax_rate_' . $locale->location_type} = $locale->location_code;
|
|
}
|
|
}
|
|
|
|
if ( ! empty( $cities ) ) {
|
|
$rate->tax_rate_cities = implode( ';', $cities );
|
|
$rate->tax_rate_city = end( $cities );
|
|
}
|
|
|
|
if ( ! empty( $postcodes ) ) {
|
|
$rate->tax_rate_postcodes = implode( ';', $postcodes );
|
|
$rate->tax_rate_postcode = end( $postcodes );
|
|
}
|
|
return new Tax_Rate( $rate );
|
|
} else {
|
|
return null;
|
|
}//end if
|
|
}
|
|
|
|
/**
|
|
* Returns the shipping method Model for the shipping method ID.
|
|
*
|
|
* @param int $id - Shipping method ID.
|
|
*
|
|
* @return \WPGraphQL\WooCommerce\Model\Shipping_Method
|
|
*
|
|
* @throws \GraphQL\Error\UserError Invalid object.
|
|
*/
|
|
public function load_shipping_method_from_id( $id ) {
|
|
$wc_shipping = \WC_Shipping::instance();
|
|
$methods = $wc_shipping->get_shipping_methods();
|
|
if ( empty( $methods[ $id ] ) ) {
|
|
throw new UserError(
|
|
/* translators: shipping method ID */
|
|
sprintf( __( 'No Shipping Method assigned to ID %s was found ', 'graphql-for-ecommerce' ), $id )
|
|
);
|
|
}
|
|
|
|
$method = $methods[ $id ];
|
|
|
|
return new Shipping_Method( $method );
|
|
}
|
|
|
|
/**
|
|
* Returns the shipping zone connected the provided IDs.
|
|
*
|
|
* @param int $id - Shipping zone IDs.
|
|
*
|
|
* @return \WPGraphQL\WooCommerce\Model\Shipping_Zone|null
|
|
*/
|
|
public function load_shipping_zone_from_id( $id ) {
|
|
/** @var \WC_Shipping_Zone|false $zone */
|
|
$zone = \WC_Shipping_Zones::get_zone( $id );
|
|
|
|
if ( false === $zone ) {
|
|
return null;
|
|
}
|
|
|
|
$zone = new Shipping_Zone( $zone );
|
|
|
|
return $zone;
|
|
}
|
|
|
|
/**
|
|
* Returns the order item connected the provided IDs.
|
|
*
|
|
* @param int $id - Order item IDs.
|
|
*
|
|
* @return \WPGraphQL\WooCommerce\Model\Order_Item|null
|
|
*/
|
|
public function load_order_item_from_id( $id ) {
|
|
$item = \WC()->order_factory::get_order_item( $id );
|
|
|
|
if ( false === $item ) {
|
|
return null;
|
|
}
|
|
|
|
$item = new \WPGraphQL\WooCommerce\Model\Order_Item( $item );
|
|
|
|
return $item;
|
|
}
|
|
}
|