Skip to content

Commit

Permalink
Merge pull request #219 from kidunot89/feature/downloadable-items-typ…
Browse files Browse the repository at this point in the history
…e-and-connection

"DownloadableItem" type and connection added.
  • Loading branch information
kidunot89 authored Jan 22, 2020
2 parents 60140be + b57ec1c commit 98af2b0
Show file tree
Hide file tree
Showing 25 changed files with 1,007 additions and 51 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ before_script:
docker-compose build \
--build-arg DESIRED_PHP_VERSION=${PHP_VERSION} \
--build-arg DESIRED_WP_VERSION=${WP_VERSION} \
--build-arg USE_XDEBUG=${USE_XDEBUG} \
testing
fi
# Install PHP CodeSniffer and WPCS.
Expand Down
9 changes: 8 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ SHELL [ "/bin/bash", "-c" ]
# Redeclare ARGs and set as environmental variables for reuse.
ARG DESIRED_WP_VERSION
ARG DESIRED_PHP_VERSION
ARG USE_XDEBUG
ENV WP_VERSION=${DESIRED_WP_VERSION}
ENV PHP_VERSION=${DESIRED_PHP_VERSION}
ENV USING_XDEBUG=${USE_XDEBUG}

# Install php extensions
RUN docker-php-ext-install pdo_mysql

# Install PCOV and XDebug
RUN if [ "$PHP_VERSION" != "5.6" ] && [ "$PHP_VERSION" != "7.0" ]; then \
RUN if [ "$PHP_VERSION" != "5.6" ] && [ "$PHP_VERSION" != "7.0" ] && [[ -z "$USING_XDEBUG" ]]; then \
apt-get install zip unzip -y && \
pecl install pcov && \
docker-php-ext-enable pcov && \
Expand All @@ -35,6 +37,11 @@ RUN if [ "$PHP_VERSION" != "5.6" ] && [ "$PHP_VERSION" != "7.0" ]; then \
&& echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.remote_enable=on" >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.remote_autostart=off" >> /usr/local/etc/php/conf.d/xdebug.ini; \
elif [ "$PHP_VERSION" == "7.0" ]; then \
yes | pecl install xdebug-2.6.1 \
&& echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.remote_enable=on" >> /usr/local/etc/php/conf.d/xdebug.ini \
&& echo "xdebug.remote_autostart=off" >> /usr/local/etc/php/conf.d/xdebug.ini; \
else \
yes | pecl install xdebug \
&& echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini \
Expand Down
17 changes: 14 additions & 3 deletions bin/testing-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ fi
COMPOSER_MEMORY_LIMIT=-1 composer install --prefer-source --no-interaction

# Install pcov/clobber if PHP7.1+
if version_gt $PHP_VERSION 7.0 && [[ "$COVERAGE" == "1" ]]; then
if version_gt $PHP_VERSION 7.0 && [[ "$COVERAGE" == "1" ]] && [[ -z "$USING_XDEBUG" ]]; then
echo "Installing pcov/clobber"
COMPOSER_MEMORY_LIMIT=-1 composer require --dev pcov/clobber
vendor/bin/pcov clobber
elif [ "$COVERAGE" == "1" ]; then
echo "Sorry, there is no PCOV support for this PHP ${PHP_VERSION} at this time"
echo "Using XDebug for codecoverage"
fi

# Set output permission
Expand All @@ -81,11 +81,22 @@ if [ -f "${TESTS_OUTPUT}/coverage.xml" ] && [[ "$COVERAGE" == "1" ]]; then
sed -i "s~$pattern~~g" "$TESTS_OUTPUT"/coverage.xml

# Remove pcov/clobber
if version_gt $PHP_VERSION 7.0 && [ "$SKIP_TESTS_CLEANUP" != "1" ]; then
if version_gt $PHP_VERSION 7.0 && [ "$SKIP_TESTS_CLEANUP" != "1" ] && [[ -z "$USING_XDEBUG" ]]; then
echo 'Removing pcov/clobber.'
vendor/bin/pcov unclobber
COMPOSER_MEMORY_LIMIT=-1 composer remove --dev pcov/clobber
fi

if [ "$SKIP_TESTS_CLEANUP" != "1" ]; then
echo 'Changing composer configuration in container.'
composer config --global discard-changes true

echo 'Removing devDependencies.'
composer install --no-dev -n

echo 'Removing composer.lock'
rm composer.lock
fi
fi

# Set public test result files permissions.
Expand Down
5 changes: 3 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ services:
context: .
dockerfile: Dockerfile
args:
DESIRED_PHP_VERSION: "${PHP_VERSION:-7.3}"
DESIRED_WP_VERSION: "${WP_VERSION:-5.2}"
- DESIRED_PHP_VERSION="${PHP_VERSION:-7.3}"
- DESIRED_WP_VERSION="${WP_VERSION:-5.2}"
- USE_XDEBUG
image: woographql-testing
volumes:
- '.:/var/www/html/wp-content/plugins/wp-graphql-woocommerce'
Expand Down
2 changes: 2 additions & 0 deletions includes/class-type-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public function init( \WPGraphQL\Registry\TypeRegistry $type_registry ) {
\WPGraphQL\WooCommerce\Type\WPObject\Product_Variation_Type::register();
\WPGraphQL\WooCommerce\Type\WPObject\Order_Type::register();
\WPGraphQL\WooCommerce\Type\WPObject\Order_Item_Type::register();
\WPGraphQL\WooCommerce\Type\WPObject\Downloadable_Item_Type::register();
\WPGraphQL\WooCommerce\Type\WPObject\Refund_Type::register();
\WPGraphQL\WooCommerce\Type\WPObject\Product_Download_Type::register();
\WPGraphQL\WooCommerce\Type\WPObject\Customer_Type::register();
Expand All @@ -88,6 +89,7 @@ public function init( \WPGraphQL\Registry\TypeRegistry $type_registry ) {
\WPGraphQL\WooCommerce\Connection\Products::register_connections();
\WPGraphQL\WooCommerce\Connection\Orders::register_connections();
\WPGraphQL\WooCommerce\Connection\Order_Items::register_connections();
\WPGraphQL\WooCommerce\Connection\Downloadable_Items::register_connections();
\WPGraphQL\WooCommerce\Connection\Refunds::register_connections();
\WPGraphQL\WooCommerce\Connection\Product_Attributes::register_connections();
\WPGraphQL\WooCommerce\Connection\Variation_Attributes::register_connections();
Expand Down
70 changes: 70 additions & 0 deletions includes/connection/class-downloadable-items.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
/**
* Connection - Downloadable_Items
*
* Registers connections to DownloadableItem
*
* @package WPGraphQL\WooCommerce\Connection
* @since 0.4.0
*/

namespace WPGraphQL\WooCommerce\Connection;

use WPGraphQL\WooCommerce\Data\Factory;

/**
* Class - Downloadable_Items
*/
class Downloadable_Items {
/**
* Registers the various connections from other Types to DownloadableItem
*/
public static function register_connections() {
// From Order.
register_graphql_connection( self::get_connection_config() );
}

/**
* Given an array of $args, this returns the connection config, merging the provided args
* with the defaults
*
* @access public
* @param array $args - Connection configuration.
*
* @return array
*/
public static function get_connection_config( $args = array() ) {
$defaults = array(
'fromType' => 'Order',
'toType' => 'DownloadableItem',
'fromFieldName' => 'downloadableItems',
'connectionArgs' => self::get_connection_args(),
'resolve' => function ( $source, $args, $context, $info ) {
return Factory::resolve_downloadable_item_connection( $source, $args, $context, $info );
},
);
return array_merge( $defaults, $args );
}

/**
* Returns array of where args
*
* @return array
*/
public static function get_connection_args() {
return array(
'active' => array(
'type' => 'Boolean',
'description' => __( 'Limit results to downloadable items that can be downloaded now.', 'wp-graphql-woocommerce' ),
),
'expired' => array(
'type' => 'Boolean',
'description' => __( 'Limit results to downloadable items that are expired.', 'wp-graphql-woocommerce' ),
),
'hasDownloadsRemaining' => array(
'type' => 'Boolean',
'description' => __( 'Limit results to downloadable items that have downloads remaining.', 'wp-graphql-woocommerce' ),
),
);
}
}
17 changes: 17 additions & 0 deletions includes/data/class-factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
use WPGraphQL\WooCommerce\Data\Connection\Shipping_Method_Connection_Resolver;
use WPGraphQL\WooCommerce\Data\Connection\Cart_Item_Connection_Resolver;
use WPGraphQL\WooCommerce\Data\Connection\Payment_Gateway_Connection_Resolver;
use WPGraphQL\WooCommerce\Data\Connection\Downloadable_Item_Connection_Resolver;
use WPGraphQL\WooCommerce\Model\Order_Item;
use WPGraphQL\WooCommerce\Model\Product;
use WPGraphQL\WooCommerce\Model\Customer;
Expand Down Expand Up @@ -491,6 +492,22 @@ public static function resolve_cart_item_connection( $source, array $args, AppCo
return $resolver->get_connection();
}

/**
* Resolves DownloadableItem connections
*
* @param mixed $source - Data resolver for connection source.
* @param array $args - Connection arguments.
* @param AppContext $context - AppContext object.
* @param ResolveInfo $info - ResolveInfo object.
*
* @return array
* @access public
*/
public static function resolve_downloadable_item_connection( $source, array $args, AppContext $context, ResolveInfo $info ) {
$resolver = new Downloadable_Item_Connection_Resolver( $source, $args, $context, $info );
return $resolver->get_connection();
}

/**
* Resolves PaymentGateway connections
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<?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 GraphQL\Type\Definition\ResolveInfo;
use GraphQLRelay\Relay;
use GraphQLRelay\Connection\ArrayConnection;
use WPGraphQL\AppContext;
use WPGraphQL\Data\Connection\AbstractConnectionResolver;

/**
* Class Downloadable_Item_Connection_Resolver
*/
class Downloadable_Item_Connection_Resolver extends AbstractConnectionResolver {
/**
* Include shared connection functions.
*/
use WC_Connection_Functions;

/**
* 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 = array( 'filters' => array() );
if ( ! empty( $this->args['where'] ) ) {
$where_args = $this->args['where'];
if ( isset( $where_args['active'] ) ) {
$active = $where_args['active'];

$query_args['filters'][] = function( $downloadable_item ) use ( $active ) {
$is_expired = isset( $downloadable_item['access_expires'] )
? time() > $downloadable_item['access_expires']->getTimestamp()
: false;
$downloads_remaining = ( 'integer' === gettype( $downloadable_item['downloads_remaining'] ) )
? 0 < $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'][] = 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'][] = function( $downloadable_item ) use ( $has_downloads_remaining ) {
$downloads_remaining = ( 'integer' === gettype( $downloadable_item['downloads_remaining'] ) )
? 0 < $downloadable_item['downloads_remaining']
: true;

return $has_downloads_remaining === $downloads_remaining;
};
}
}

/**
* 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 $args The inputArgs on the field.
* @param AppContext $context The AppContext passed down the GraphQL tree.
* @param 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 \WP_Query
*/
public function get_query() {
$items = $this->source->downloadable_items;

if ( empty( $items ) ) {
return array();
}

if ( ! empty( $this->query_args['filters'] ) && is_array( $this->query_args['filters'] ) ) {
foreach ( $this->query_args['filters'] as $filter ) {
$items = array_filter( $items, $filter );
}
}

$cursor_key = $this->get_offset();
$cursor_offset = array_search( $cursor_key, \array_column( $items, 'download_id' ), true );

if ( ! empty( $this->args['after'] ) ) {
$items = array_splice( $items, $cursor_offset + 1 );
} elseif ( $cursor_offset ) {
$items = array_splice( $items, 0, $cursor_offset );
}

return $items;
}

/**
* This returns the offset to be used in the $query_args based on the $args passed to the
* GraphQL query.
*
* @return int|mixed
*/
public function get_offset() {
$offset = null;

// Get the offset.
if ( ! empty( $this->args['after'] ) ) {
$offset = $this->args['after'];
} elseif ( ! empty( $this->args['before'] ) ) {
$offset = $this->args['before'];
}

/**
* Return the higher of the two values
*/
return $offset;
}

/**
* Create cursor for downloadable item node.
*
* @param array $node Cart item.
* @param string $key Cart item key.
*
* @return string
*/
protected function get_cursor_for_node( $node, $key = null ) {
return $node['download_id'];
}

/**
* Return an array of items from the query
*
* @return array
*/
public function get_items() {
return ! empty( $this->query ) ? $this->query : array();
}

/**
* Validates offset.
*
* @param integer $offset Post ID.
*
* @return bool
*/
public function is_valid_offset( $offset ) {
return 'string' === gettype( $offset );
}
}
Loading

0 comments on commit 98af2b0

Please sign in to comment.