mirror of
https://github.com/wp-graphql/wp-graphql-woocommerce.git
synced 2026-08-14 12:53:44 +02:00
* fix: downloadsRemaining returns null for valid numeric string values Use is_numeric() + intval() instead of 'integer' === gettype() to handle cases where WooCommerce stores downloads_remaining as a numeric string. Mirrors WooCommerce's own approach in its download templates. Co-authored-by: Nestor Vera <hacknug@users.noreply.github.com> Closes #937 * fix: Match CI phpcov php-code-coverage version to Docker container The Docker container uses php-code-coverage 9.2.x which serializes coverage with v9 classes (e.g. Xdebug3Driver). phpcov v9 bundles php-code-coverage v11 with different classes, causing __PHP_Incomplete_Class errors. Pin to phpcov v8 + php-code-coverage v9 to match the Docker environment. --------- Co-authored-by: Nestor Vera <hacknug@users.noreply.github.com>
170 lines
4.7 KiB
PHP
170 lines
4.7 KiB
PHP
<?php
|
|
/**
|
|
* ConnectionResolver - Downloadable_Item_Connection_Resolver
|
|
*
|
|
* Resolves connections to DownloadableItem
|
|
*
|
|
* @package WPGraphQL\WooCommerce\Data\Connection
|
|
* @since 0.4.0
|
|
*/
|
|
|
|
namespace WPGraphQL\WooCommerce\Data\Connection;
|
|
|
|
use WPGraphQL\Data\Connection\AbstractConnectionResolver;
|
|
use WPGraphQL\WooCommerce\Model\Customer;
|
|
|
|
/**
|
|
* Class Downloadable_Item_Connection_Resolver
|
|
*
|
|
* @property \WPGraphQL\WooCommerce\Data\Loader\WC_Db_Loader $loader
|
|
*
|
|
* @package WPGraphQL\WooCommerce\Data\Connection
|
|
*/
|
|
class Downloadable_Item_Connection_Resolver extends AbstractConnectionResolver {
|
|
/**
|
|
* Return the name of the loader to be used with the connection resolver
|
|
*
|
|
* @return string
|
|
*/
|
|
public function get_loader_name() {
|
|
return 'downloadable_item';
|
|
}
|
|
|
|
/**
|
|
* Confirms if downloadable items should be retrieved.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function should_execute() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Creates downloadable item filters.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_query_args() {
|
|
$query_args = [ 'filters' => [] ];
|
|
if ( ! empty( $this->args['where'] ) ) {
|
|
$where_args = $this->args['where'];
|
|
if ( isset( $where_args['active'] ) ) {
|
|
$active = $where_args['active'];
|
|
|
|
$query_args['filters'][] = static function ( $downloadable_item ) use ( $active ) {
|
|
$is_expired = isset( $downloadable_item['access_expires'] )
|
|
? time() > $downloadable_item['access_expires']->getTimestamp()
|
|
: false;
|
|
$downloads_remaining = ( is_numeric( $downloadable_item['downloads_remaining'] ) )
|
|
? 0 < intval( $downloadable_item['downloads_remaining'] )
|
|
: true;
|
|
|
|
return $active ? ( ! $is_expired && $downloads_remaining ) : ( $is_expired || ! $downloads_remaining );
|
|
};
|
|
}
|
|
|
|
if ( isset( $where_args['expired'] ) ) {
|
|
$expired = $where_args['expired'];
|
|
|
|
$query_args['filters'][] = static function ( $downloadable_item ) use ( $expired ) {
|
|
$is_expired = isset( $downloadable_item['access_expires'] )
|
|
? time() < $downloadable_item['access_expires']->getTimestamp()
|
|
: false;
|
|
|
|
return $expired === $is_expired;
|
|
};
|
|
}
|
|
|
|
if ( isset( $where_args['hasDownloadsRemaining'] ) ) {
|
|
$has_downloads_remaining = $where_args['hasDownloadsRemaining'];
|
|
|
|
$query_args['filters'][] = static function ( $downloadable_item ) use ( $has_downloads_remaining ) {
|
|
$downloads_remaining = ( is_numeric( $downloadable_item['downloads_remaining'] ) )
|
|
? 0 < intval( $downloadable_item['downloads_remaining'] )
|
|
: true;
|
|
|
|
return $has_downloads_remaining === $downloads_remaining;
|
|
};
|
|
}
|
|
}//end if
|
|
|
|
/**
|
|
* Filter the $query_args to allow folks to customize queries programmatically.
|
|
*
|
|
* @param array $query_args The args that will be passed to the WP_Query.
|
|
* @param mixed $source The source that's passed down the GraphQL queries.
|
|
* @param array<string, mixed>|null $args The inputArgs on the field.
|
|
* @param \WPGraphQL\AppContext $context The AppContext passed down the GraphQL tree.
|
|
* @param \GraphQL\Type\Definition\ResolveInfo $info The ResolveInfo passed down the GraphQL tree.
|
|
*/
|
|
$query_args = apply_filters( 'graphql_downloadable_item_connection_query_args', $query_args, $this->source, $this->args, $this->context, $this->info );
|
|
|
|
return $query_args;
|
|
}
|
|
|
|
/**
|
|
* Executes query
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_query() {
|
|
$items = 0;
|
|
if ( is_a( $this->source, Customer::class ) ) {
|
|
$items = wc_get_customer_available_downloads( $this->source->ID );
|
|
} else {
|
|
$items = $this->source->downloadable_items;
|
|
}
|
|
|
|
if ( empty( $items ) ) {
|
|
return [];
|
|
}
|
|
|
|
if ( ! empty( $this->query_args['filters'] ) && is_array( $this->query_args['filters'] ) ) {
|
|
foreach ( $this->query_args['filters'] as $filter ) {
|
|
$items = array_filter( $items, $filter );
|
|
}
|
|
}
|
|
|
|
// Cache items for later.
|
|
foreach ( $items as $item ) {
|
|
$this->loader->prime( $item['download_id'], $item );
|
|
}
|
|
|
|
return array_column( $items, 'download_id' );
|
|
}
|
|
|
|
/**
|
|
* Return an array of items from the query
|
|
*
|
|
* @return array
|
|
*/
|
|
public function get_ids_from_query() {
|
|
return ! empty( $this->query ) ? $this->query : [];
|
|
}
|
|
|
|
/**
|
|
* Validates offset.
|
|
*
|
|
* @param integer $offset Post ID.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function is_valid_offset( $offset ) {
|
|
return 'string' === gettype( $offset );
|
|
}
|
|
|
|
/**
|
|
* Validates Model.
|
|
*
|
|
* If model isn't a class with a `fields` member, this function with have be overridden in
|
|
* the Connection class.
|
|
*
|
|
* @param array $model Downloadable item model.
|
|
*
|
|
* @return bool
|
|
*/
|
|
protected function is_valid_model( $model ) {
|
|
return ! empty( $model ) && ! empty( $model['download_id'] );
|
|
}
|
|
}
|