installed plugin Easy Digital Downloads version 3.1.0.3

This commit is contained in:
2022-11-27 15:03:07 +00:00
committed by Gitium
parent 555673545b
commit c5dce2cec6
1200 changed files with 238970 additions and 0 deletions

View File

@ -0,0 +1,66 @@
<?php
/**
* General admin functions for blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Admin\Functions;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
add_filter( 'display_post_states', __NAMESPACE__ . '\display_post_states', 15, 2 );
/**
* Updates the post states array to show states specific to EDD.
*
* @since 2.0
* @param array $post_states An array of post display states.
* @param WP_Post $post Post object.
* @return array
*/
function display_post_states( $post_states, $post ) {
if ( intval( edd_get_option( 'login_page' ) ) === $post->ID ) {
$post_states['edd_login_page'] = __( 'Login Page', 'easy-digital-downloads' );
}
if ( intval( edd_get_option( 'purchase_history_page' ) ) === $post->ID ) {
$post_states['edd_purchase_history_page'] = __( 'Order History Page', 'easy-digital-downloads' );
}
if ( intval( edd_get_option( 'success_page' ) ) === $post->ID ) {
$post_states['edd_success_page'] = __( 'Receipt Page', 'easy-digital-downloads' );
}
if ( intval( edd_get_option( 'confirmation_page' ) ) === $post->ID ) {
$post_states['edd_confirmation_page'] = __( 'Confirmation Page', 'easy-digital-downloads' );
}
return $post_states;
}
add_filter( 'widget_types_to_hide_from_legacy_widget_block', __NAMESPACE__ . '\remove_legacy_widgets' );
/**
* Removes legacy widgets if they're not being used on the site and have block equivalents.
*
* @since 2.0
* @param array $widget_types
* @return array
*/
function remove_legacy_widgets( $widget_types ) {
$legacy_widgets = array(
'edd_cart_widget',
'edd_categories_tags_widget',
);
foreach ( $legacy_widgets as $widget ) {
if ( ! is_active_widget( false, false, $widget ) ) {
$widget_types[] = $widget;
}
}
return $widget_types;
}

View File

@ -0,0 +1,32 @@
<?php
/**
* General admin functions for blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Admin\Notices;
defined( 'ABSPATH' ) || exit;
add_action( 'admin_notices', __NAMESPACE__ . '\existing_blocks_plugin' );
/**
* Shows a notice if the original EDD Blocks plugin is active.
*
* @since 2.0
* @return void
*/
function existing_blocks_plugin() {
if ( ! class_exists( 'EDD_Blocks' ) ) {
return;
}
?>
<div id="edd-blocks-core-notice" class="notice notice-warning">
<p><strong><?php esc_html_e( 'EDD Blocks are now a part of Easy Digital Downloads', 'easy-digital-downloads' ); ?></strong></p>
<p><?php esc_html_e( 'If you are using the original Downloads block, you will need to update it to use either the new EDD Products or EDD Downloads Terms block. All other blocks functionality is automatically updated. Once you\'ve replaced your blocks, you can deactivate the EDD Blocks plugin.', 'easy-digital-downloads' ); ?></p>
</div>
<?php
}

View File

@ -0,0 +1,52 @@
<?php
/**
* reCAPTCHA settings.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Recaptcha\Settings;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
add_filter( 'edd_settings_misc', __NAMESPACE__ . '\register_keys' );
/**
* Register the settings for reCAPTCHA keys.
*
* @since 2.0
* @param array $settings EDD settings array.
* @return array
*/
function register_keys( $settings ) {
$settings['main']['recaptcha'] = array(
'id' => 'recaptcha',
'name' => __( 'reCAPTCHA v3', 'easy-digital-downloads' ),
'desc' => sprintf(
/* translators: 1. opening anchor tag; 2. closing anchor tag */
__( '%1$sRegister with Google%2$s to get reCAPTCHA v3 keys. Setting the keys here will enable reCAPTCHA on your registration block and when a user requests a password reset using the login block.', 'easy-digital-downloads' ),
'<a href="https://www.google.com/recaptcha/admin#list" target="_blank">',
'</a>'
),
'type' => 'descriptive_text',
);
$settings['main']['recaptcha_site_key'] = array(
'id' => 'recaptcha_site_key',
'name' => __( 'reCAPTCHA Site Key', 'easy-digital-downloads' ),
'type' => 'text',
'std' => '',
);
$settings['main']['recaptcha_secret_key'] = array(
'id' => 'recaptcha_secret_key',
'name' => __( 'reCAPTCHA Secret Key', 'easy-digital-downloads' ),
'type' => 'text',
'std' => '',
);
return $settings;
}

View File

@ -0,0 +1,46 @@
<?php
namespace EDD\Blocks\Admin\Scripts;
add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\localize' );
/**
* Adds a custom variable to the JS to allow a user in the block editor
* to preview sensitive data.
*
* @since 2.0
* @return void
*/
function localize() {
$user = wp_get_current_user();
wp_localize_script(
'wp-block-editor',
'EDDBlocks',
array(
'current_user' => md5( $user->user_email ),
'all_access' => function_exists( 'edd_all_access' ),
'recurring' => function_exists( 'EDD_Recurring' ),
)
);
}
/**
* Makes sure the payment icons show on the checkout block in the editor.
*
* @since 2.0
*/
add_action( 'admin_print_footer_scripts', '\edd_print_payment_icons_on_checkout' );
add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\add_edd_styles_block_editor' );
/**
* If the EDD styles are registered, load them for the block editor.
*
* @since 2.0
* @return void
*/
function add_edd_styles_block_editor() {
if ( wp_style_is( 'edd-styles', 'registered' ) ) {
wp_enqueue_style( 'edd-styles' );
}
}

View File

@ -0,0 +1,171 @@
<?php
/**
* Block settings.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Admin\Settings;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
add_filter( 'edd_settings_general', __NAMESPACE__ . '\pages' );
/**
* Updates some of the pages settings.
*
* @since 2.0
* @param array $settings
* @return array
*/
function pages( $settings ) {
if ( empty( $settings['pages'] ) ) {
return $settings;
}
$pages = edd_get_pages();
// Login page.
$settings['pages']['login_page'] = array(
'id' => 'login_page',
'name' => __( 'Login Page', 'easy-digital-downloads' ),
'desc' => __( 'This page must include the EDD Login block. Setting this allows the front end form to be used for resetting passwords.', 'easy-digital-downloads' ),
'type' => 'select',
'options' => $pages,
'chosen' => true,
'placeholder' => __( 'Select a page', 'easy-digital-downloads' ),
);
if ( ! empty( $settings['pages']['purchase_page']['desc'] ) ) {
$description = __( 'This is the checkout page where customers will complete their purchases.', 'easy-digital-downloads' );
$description .= '<br />';
$description .= sprintf(
/* translators: 1. opening code tag, do not translate; 2. closing code tag, do not translate. */
__( 'The Checkout block or %1$s[download_checkout]%2$s shortcode must be on this page.', 'easy-digital-downloads' ),
'<code>',
'</code>'
);
$settings['pages']['purchase_page']['desc'] = $description;
}
// Update the login redirect description.
if ( ! empty( $settings['pages']['login_redirect_page']['desc'] ) ) {
$description = sprintf(
/* translators: 1. opening code tag, do not translate; 2. closing code tag, do not translate. */
__( 'If a customer logs in using the EDD Login block or %1$s[edd_login]%2$s shortcode, will be redirected to this page.', 'easy-digital-downloads' ),
'<code>',
'</code>'
);
$description .= '<br />';
$description .= __( 'This can be overridden in the block settings or shortcode parameters.', 'easy-digital-downloads' );
$settings['pages']['login_redirect_page']['desc'] = $description;
}
// Update the purchase history page setting name/description.
if ( ! empty( $settings['pages']['purchase_history_page']['desc'] ) ) {
$description = __( 'This page shows a complete order history for the current user, including download links.', 'easy-digital-downloads' );
$description .= '<br />';
$description .= sprintf(
/* translators: 1. opening code tag, do not translate; 2. closing code tag, do not translate. */
__( 'Either the EDD Order History block or the %1$s[purchase_history]%2$s shortcode must be on this page.', 'easy-digital-downloads' ),
'<code>',
'</code>'
);
$settings['pages']['purchase_history_page']['desc'] = $description;
$settings['pages']['purchase_history_page']['name'] = __( 'Order History Page', 'easy-digital-downloads' );
}
$confirmation_description = __( 'This page must include the EDD Confirmation block.', 'easy-digital-downloads' );
$confirmation_description .= '<br />';
$confirmation_description .= __( 'Use this page separately from your receipt page to ensure proper conversion tracking.', 'easy-digital-downloads' );
$confirmation_page = array(
'confirmation_page' => array(
'id' => 'confirmation_page',
'name' => __( 'Confirmation Page', 'easy-digital-downloads' ),
'desc' => $confirmation_description,
'type' => 'select',
'options' => $pages,
'chosen' => true,
'placeholder' => __( 'Select a page', 'easy-digital-downloads' ),
),
);
// Insert the confirmation page after checkout and before the receipt.
array_splice( $settings['pages'], 2, 0, $confirmation_page );
if ( ! empty( $settings['pages']['success_page']['desc'] ) ) {
$receipt_description = __( 'This is the page to show a detailed receipt for an order.', 'easy-digital-downloads' );
$receipt_description .= '<br />';
$receipt_description .= sprintf(
/* translators: 1. opening code tag, do not translate; 2. closing code tag, do not translate. */
__( 'Use the EDD Receipt block or the %1$s[edd_receipt]%2$s shortcode to work with the confirmation page.', 'easy-digital-downloads' ),
'<code>',
'</code>'
);
$settings['pages']['success_page']['desc'] = $receipt_description;
$settings['pages']['success_page']['name'] = __( 'Receipt Page', 'easy-digital-downloads' );
}
return $settings;
}
add_filter( 'edd_settings_misc', __NAMESPACE__ . '\button_color' );
/**
* Adds the EDD block button color setting to the miscellaneous section.
*
* @since 2.0
* @param array $settings
* @return array
*/
function button_color( $settings ) {
$color_settings = array(
'button_colors' => array(
'id' => 'blocks_button_colors',
'name' => __( 'Default Button Colors', 'easy-digital-downloads' ),
'type' => 'hook',
),
);
array_splice( $settings['button_text'], 1, 0, $color_settings );
$new_colors = edd_get_option( 'button_colors' );
if ( ! empty( $new_colors['background'] ) ) {
unset( $settings['button_text']['checkout_color'] );
}
return $settings;
}
add_action( 'edd_blocks_button_colors', __NAMESPACE__ . '\button_colors' );
/**
* Renders the settings field for the button colors.
*
* @since 2.0
* @param array $args
* @return void
*/
function button_colors( $args ) {
$colors = edd_get_option( 'button_colors' );
$settings = array(
'background' => __( 'Background', 'easy-digital-downloads' ),
'text' => __( 'Text', 'easy-digital-downloads' ),
);
echo '<div class="edd-settings-colors">';
foreach ( $settings as $setting => $label ) {
$color_value = ! empty( $colors[ $setting ] ) ? $colors[ $setting ] : '';
?>
<div class="edd-settings-color">
<label for="edd_settings[button_colors][<?php echo esc_attr( $setting ); ?>]"><?php echo esc_html( $label ); ?></label>
<input type="text" class="edd-color-picker" id="edd_settings[button_colors][<?php echo esc_attr( $setting ); ?>]" name="edd_settings[button_colors][<?php echo esc_attr( $setting ); ?>]" value="<?php echo esc_attr( $color_value ); ?>" data-default-color="" />
</div>
<?php
}
echo '</div>';
}

View File

@ -0,0 +1,51 @@
<?php
/**
* Ajax functions for EDD checkout blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Checkout\Ajax;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
add_action( 'enqueue_block_assets', __NAMESPACE__ . '\enqueue_cart_script' );
/**
* Enqueues a small script to update the cart block when an item is added to the cart.
*
* @since 2.0
* @return void
*/
function enqueue_cart_script() {
wp_register_script( 'edd-blocks-cart', EDD_BLOCKS_URL . 'assets/js/cart.js', array( 'edd-ajax' ), EDD_VERSION, true );
}
add_filter( 'edd_ajax_remove_from_cart_response', __NAMESPACE__ . '\update_cart_response' );
add_filter( 'edd_ajax_add_to_cart_response', __NAMESPACE__ . '\update_cart_response' );
/**
* Filters the add to cart response to update the block cart.
*
* @since 2.0
* @param array $response
* @return array
*/
function update_cart_response( $response ) {
$cart_items = edd_get_cart_contents();
if ( empty( $cart_items ) ) {
$response['block_cart'] = '<p class="edd-blocks-form__cart">' . esc_html( __( 'Your cart is empty.', 'easy-digital-downloads' ) ) . '</p>';
} else {
$is_cart_widget = true;
ob_start();
include EDD_BLOCKS_DIR . 'views/checkout/cart/cart.php';
$response['block_cart'] = ob_get_clean();
}
$response['quantity_formatted'] = \EDD\Blocks\Checkout\Functions\get_quantity_string();
return $response;
}

View File

@ -0,0 +1,391 @@
<?php
/**
* Checkout blocks for EDD.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Checkout;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
use EDD\Blocks\Functions as Helpers;
require_once EDD_BLOCKS_DIR . 'includes/checkout/ajax.php';
require_once EDD_BLOCKS_DIR . 'includes/checkout/forms.php';
require_once EDD_BLOCKS_DIR . 'includes/checkout/functions.php';
require_once EDD_BLOCKS_DIR . 'includes/checkout/gateways.php';
add_action( 'init', __NAMESPACE__ . '\register' );
/**
* Registers all of the EDD core blocks.
*
* @since 2.0
* @return void
*/
function register() {
$blocks = array(
'cart' => array(
'render_callback' => __NAMESPACE__ . '\cart',
'view_script' => 'edd-blocks-cart',
),
'checkout' => array(
'render_callback' => __NAMESPACE__ . '\checkout',
),
);
foreach ( $blocks as $block => $args ) {
register_block_type( EDD_BLOCKS_DIR . 'build/' . $block, $args );
}
}
/**
* Renders the cart.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return string Cart HTML.
*/
function cart( $block_attributes = array() ) {
$block_attributes = wp_parse_args(
$block_attributes,
array(
'hide_on_checkout' => true,
'mini' => true,
'show_quantity' => true,
'show_total' => true,
'link' => true,
'hide_empty' => false,
'title' => '',
)
);
if ( edd_is_checkout() && $block_attributes['hide_on_checkout'] ) {
return '';
}
wp_enqueue_script( 'edd-blocks-cart' );
$classes = Helpers\get_block_classes(
$block_attributes,
array(
'wp-block-edd-cart',
'edd-blocks__cart',
)
);
if ( ! empty( $block_attributes['mini'] ) ) {
$classes[] = 'edd-blocks__cart-mini';
} else {
$classes[] = 'edd-blocks__cart-full';
}
ob_start();
?>
<div class="<?php echo esc_attr( implode( ' ', array_filter( $classes ) ) ); ?>">
<?php
do_cart_form( $block_attributes );
?>
</div>
<?php
return ob_get_clean();
}
/**
* Generates the cart form depending on contents and options.
*
* @since 2.0
* @param array $block_attributes
* @return void
*/
function do_cart_form( $block_attributes ) {
$cart_items = get_cart_contents();
$cart_has_contents = $cart_items || edd_cart_has_fees();
if ( ! $cart_has_contents && ! empty( $block_attributes['hide_empty'] ) ) {
return;
}
if ( ! empty( $block_attributes['mini'] ) ) {
include EDD_BLOCKS_DIR . 'views/checkout/cart/mini.php';
return;
}
if ( ! empty( $block_attributes['title'] ) ) {
?>
<h3><?php echo esc_html( $block_attributes['title'] ); ?></h3>
<?php
}
if ( ! $cart_has_contents ) {
?>
<p class="edd-blocks-form__cart"><?php esc_html_e( 'Your cart is empty.', 'easy-digital-downloads' ); ?></p>
<?php
return;
}
$is_cart_widget = true;
include EDD_BLOCKS_DIR . 'views/checkout/cart/cart.php';
// Link to checkout if it's not currently the checkout screen.
if ( ! edd_is_checkout() ) {
?>
<a class="edd-blocks__button" href="<?php echo esc_url( edd_get_checkout_uri() ); ?>"><?php esc_html_e( 'Checkout', 'easy-digital-downloads' ); ?></a>
<?php
}
}
/**
* Renders the entire EDD checkout block.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return string Checkout HTML.
*/
function checkout( $block_attributes = array() ) {
$block_attributes = wp_parse_args(
$block_attributes,
array(
'show_register_form' => edd_get_option( 'show_register_form' ),
)
);
$classes = Helpers\get_block_classes(
$block_attributes,
array(
'wp-block-edd-checkout',
'edd-blocks__checkout',
)
);
$cart_items = get_cart_contents();
if ( ! $cart_items && ! edd_cart_has_fees() ) {
return '<p>' . esc_html( __( 'Your cart is empty.', 'easy-digital-downloads' ) ) . '</p>';
}
if ( edd_item_quantities_enabled() ) {
add_action( 'edd_cart_footer_buttons', 'edd_update_cart_button' );
}
// Check if the Save Cart button should be shown.
if ( ! edd_is_cart_saving_disabled() ) {
add_action( 'edd_cart_footer_buttons', 'edd_save_cart_button' );
}
ob_start();
?>
<div id="edd_checkout_form_wrap" class="<?php echo esc_attr( implode( ' ', array_filter( $classes ) ) ); ?>">
<?php
if ( is_user_logged_in() ) {
$customer = get_customer();
include EDD_BLOCKS_DIR . 'views/checkout/logged-in.php';
}
do_action( 'edd_before_checkout_cart' );
include EDD_BLOCKS_DIR . 'views/checkout/cart/cart.php';
Forms\do_purchase_form( $block_attributes );
?>
</div>
<?php
return ob_get_clean();
}
/**
* Gets the cart contents.
* In the block editor, generates a sample cart.
*
* @since 2.0
* @return false|array
*/
function get_cart_contents() {
if ( ! Helpers\is_block_editor() ) {
return edd_get_cart_contents();
}
$downloads = new \WP_Query(
array(
'post_type' => 'download',
'fields' => 'ids',
'posts_per_page' => 10,
'no_found_rows' => true,
)
);
if ( empty( $downloads->posts ) ) {
return false;
}
$download_id = array_rand( array_flip( $downloads->posts ) );
$download = edd_get_download( $download_id );
$price_id = null;
if ( $download->has_variable_prices() ) {
$price_ids = $download->get_prices();
$price_ids = wp_list_pluck( $price_ids, 'index' );
$price_id = array_rand( array_flip( $price_ids ) );
}
return array(
array(
'id' => $download_id,
'options' => array(
'price_id' => $price_id,
),
'quantity' => 1,
),
);
}
add_action( 'edd_purchase_form_top', __NAMESPACE__ . '\remove_default_purchase_fields' );
/**
* Remove some of the default EDD fields from the purchase form.
* Loaded in this hook because we have to account for ajax.
*
* @since 2.0
* @return void
*/
function remove_default_purchase_fields() {
if ( ! Functions\checkout_has_blocks() ) {
return;
}
remove_action( 'edd_purchase_form_after_user_info', 'edd_user_info_fields' );
remove_action( 'edd_register_fields_before', 'edd_user_info_fields' );
remove_action( 'edd_purchase_form_before_submit', 'edd_checkout_final_total', 999 );
add_filter( 'edd_get_option_show_register_form', function() { return 'none'; } );
add_filter( 'edd_pre_cc_address_fields', '__return_true' );
add_filter( 'edd_pre_cc_fields', '__return_true' );
}
add_filter( 'edd_get_checkout_cart', __NAMESPACE__ . '\do_checkout_cart' );
/**
* Gets the checkout cart markup when EDD recalculates taxes.
*
* @param string $cart The cart HTML markup.
* @return string
*/
function do_checkout_cart( $cart ) {
if ( ! Functions\checkout_has_blocks() ) {
return $cart;
}
$cart_items = get_cart_contents();
ob_start();
do_action( 'edd_before_checkout_cart' );
include EDD_BLOCKS_DIR . 'views/checkout/cart/cart.php';
return ob_get_clean();
}
/**
* Gets the array of customer information from the session and potentially the logged in user information.
*
* @since 2.0
* @return array
*/
function get_customer() {
$session = EDD()->session->get( 'customer' );
$customer = wp_parse_args(
$session,
array(
'first_name' => '',
'last_name' => '',
'email' => '',
)
);
if ( is_user_logged_in() ) {
$user_data = get_userdata( get_current_user_id() );
foreach ( $customer as $key => $field ) {
if ( 'email' === $key && empty( $field ) ) {
$customer[ $key ] = $user_data->user_email;
} elseif ( empty( $field ) ) {
$customer[ $key ] = $user_data->$key;
}
}
}
return array_map( 'sanitize_text_field', $customer );
}
/**
* Gets the customer address for checkout.
*
* @since 2.0
* @param array $customer
* @return array
*/
function get_customer_address( $customer ) {
$address = array(
'line1' => '',
'line2' => '',
'city' => '',
'zip' => '',
'state' => '',
'country' => '',
);
if ( is_user_logged_in() ) {
$user_address = edd_get_customer_address();
foreach ( $address as $key => $field ) {
if ( empty( $field ) && ! empty( $user_address[ $key ] ) ) {
$address[ $key ] = $user_address[ $key ];
}
}
}
/**
* Filter the billing address details that will be pre-populated on the checkout form.
*
* @since 2.8
*
* @param array $address The customer address.
* @param array $customer The customer data from the session
*/
return array_map( 'sanitize_text_field', apply_filters( 'edd_checkout_billing_details_address', $address, $customer ) );
}
add_action( 'edd_cc_address_fields', __NAMESPACE__ . '\do_address' );
/**
* Renders the customer address fields for checkout.
*
* @since 2.0
* @return void
*/
function do_address() {
$customer = get_customer();
$customer['address'] = get_customer_address( $customer );
include EDD_BLOCKS_DIR . 'views/checkout/purchase-form/address.php';
}
add_action( 'edd_cc_fields', __NAMESPACE__ . '\do_cc_fields' );
/**
* Renders the default credit card fields on checkout.
*
* @since 2.0
* @return void
*/
function do_cc_fields() {
do_action( 'edd_before_cc_fields' );
include EDD_BLOCKS_DIR . 'views/checkout/purchase-form/credit-card.php';
do_action( 'edd_after_cc_fields' );
}
add_filter( 'edd_is_checkout', __NAMESPACE__ . '\is_checkout' );
/**
* If the checkout block is on a page that isn't set as the checkout option, set edd_is_checkout to true.
*
* @since 2.0
* @param bool $is_checkout
* @return bool
*/
function is_checkout( $is_checkout ) {
if ( $is_checkout ) {
return $is_checkout;
}
if ( has_block( 'edd/checkout' ) ) {
return true;
}
$current_page = ! empty( $_POST['current_page'] ) ? absint( $_POST['current_page'] ) : false;
if ( $current_page && edd_doing_ajax() && has_block( 'edd/checkout', $current_page ) ) {
return true;
}
return $is_checkout;
}

View File

@ -0,0 +1,198 @@
<?php
/**
* Checkout form functions for EDD checkout blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Checkout\Forms;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
/**
* Gets the array of personal info forms for the checkout form.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @param bool $customer_info_complete Whether the logged in customer information is complete.
* @return array
*/
function get_personal_info_forms( $block_attributes, $customer_info_complete = true ) {
$forms = array();
if ( is_user_logged_in() && $customer_info_complete ) {
return $forms;
}
$options = array(
'login' => array(
'label' => __( 'Log in', 'easy-digital-downloads' ),
'view' => EDD_BLOCKS_DIR . 'views/checkout/purchase-form/login.php',
),
'register' => array(
'label' => __( 'Register for a new account', 'easy-digital-downloads' ),
'view' => EDD_BLOCKS_DIR . 'views/checkout/purchase-form/register.php',
),
'guest' => array(
'label' => __( 'Check out as a guest', 'easy-digital-downloads' ),
'view' => EDD_BLOCKS_DIR . 'views/checkout/purchase-form/personal-info.php',
),
);
if ( ! edd_no_guest_checkout() || ( ! $customer_info_complete && is_user_logged_in() ) ) {
$forms['guest'] = $options['guest'];
}
if ( ! empty( $block_attributes['show_register_form'] ) ) {
$setting = $block_attributes['show_register_form'];
if ( 'both' === $setting ) {
$forms['login'] = $options['login'];
$forms['register'] = $options['register'];
} elseif ( 'registration' === $setting ) {
$forms['register'] = $options['register'];
} elseif ( ! empty( $options[ $setting ] ) ) {
$forms[ $setting ] = $options[ $setting ];
}
}
// If no forms have been set, add the registration form (guest checkout is disabled).
if ( empty( $forms ) ) {
$forms['register'] = $options['register'];
}
return $forms;
}
/**
* Shows the login and/or registration form for guest users in checkout.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return void
*/
function do_personal_info_forms( $block_attributes ) {
$customer = \EDD\Blocks\Checkout\get_customer();
$customer_info_complete = true;
if ( is_user_logged_in() ) {
include EDD_BLOCKS_DIR . 'views/checkout/purchase-form/logged-in.php';
if ( ! empty( $customer['email'] ) && ! empty( $customer['first_name'] ) ) {
return;
}
$customer_info_complete = false;
}
?>
<div class="edd-blocks__checkout-user">
<?php
$forms = get_personal_info_forms( $block_attributes, $customer_info_complete );
if ( ! empty( $forms ) && count( $forms ) > 1 ) {
$i = 0;
echo '<div class="edd-blocks__checkout-forms">';
foreach ( $forms as $id => $form ) {
printf(
'<button class="edd-button-secondary edd-blocks__checkout-%1$s link" data-attr="%1$s"%2$s%4$s>%3$s</button>',
esc_attr( $id ),
empty( $i ) ? ' disabled' : '',
esc_html( $form['label'] ),
'guest' === $id ? ' style="display:none;"' : ''
);
$i++;
}
echo '</div>';
}
$form = reset( $forms );
echo '<div class="edd-checkout-block__personal-info">';
if ( is_callable( $form['view'] ) ) {
echo call_user_func( $form['view'], array( 'current' => true ) );
} else {
include $form['view'];
}
?>
</div>
</div>
<?php
}
/**
* Outputs the purchase form for checkout.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return void
*/
function do_purchase_form( $block_attributes ) {
$payment_mode = edd_get_chosen_gateway();
$form_action = edd_get_checkout_uri( 'payment-mode=' . $payment_mode );
do_action( 'edd_before_purchase_form' );
?>
<form id="edd_purchase_form" class="edd_form edd-blocks-form edd-blocks-form__purchase" action="<?php echo esc_url( $form_action ); ?>" method="POST">
<?php
do_personal_info_forms( $block_attributes );
if ( edd_show_gateways() && edd_get_cart_total() > 0 ) {
include EDD_BLOCKS_DIR . 'views/checkout/purchase-form/gateways.php';
}
if ( ! edd_show_gateways() ) {
do_action( 'edd_purchase_form' );
} else {
?>
<div id="edd_purchase_form_wrap"></div>
<?php
}
?>
</form>
<?php
}
add_action( 'enqueue_block_assets', __NAMESPACE__ . '\add_user_script' );
/**
* Adds the guest checkout button switcher script to the EDD global checkout script.
*
* @since 2.0
* @return void
*/
function add_user_script() {
if ( ! edd_is_checkout() ) {
return;
}
// Manually trigger a blur event on the hidden email input for logged in users.
if ( is_user_logged_in() ) {
$script = "jQuery(document).ready(function($) {
$( '#edd-email[type=\"hidden\"]' ).trigger( 'blur' );
} );";
wp_add_inline_script( 'edd-checkout-global', $script );
return;
}
// For guest users, enqueue the script to toggle the login/registration forms.
$forms = get_personal_info_forms( array( 'show_register_form' => edd_get_option( 'show_register_form' ) ) );
if ( ! empty( $forms ) && count( $forms ) > 1 ) {
wp_enqueue_script( 'edd-blocks-checkout-forms', EDD_BLOCKS_URL . 'assets/js/checkout-forms.js', array( 'edd-checkout-global' ), EDD_VERSION, true );
}
}
add_action( 'wp_ajax_nopriv_edd_blocks_swap_personal_info', __NAMESPACE__ . '\swap_form' );
add_action( 'wp_ajax_edd_blocks_swap_personal_info', __NAMESPACE__ . '\swap_form' );
/**
* Swaps out the currently displayed form for the selected one.
*
* @since 2.0
* @return void
*/
function swap_form() {
if ( empty( $_GET['form_id'] ) ) {
return;
}
$form_id = sanitize_text_field( $_GET['form_id'] );
$forms = get_personal_info_forms( array( 'show_register_form' => 'both' ) );
$form = $forms[ $form_id ];
$customer = \EDD\Blocks\Checkout\get_customer();
if ( is_callable( $form['view'] ) ) {
wp_send_json_success( call_user_func( $form['view'], array( 'current' => true ) ) );
}
ob_start();
$form = include $form['view'];
wp_send_json_success( ob_get_clean() );
}

View File

@ -0,0 +1,44 @@
<?php
/**
* General functions for EDD checkout blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Checkout\Functions;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
/**
* Whether the checkout page is using blocks.
*
* @since 2.0
* @return bool
*/
function checkout_has_blocks() {
if ( edd_doing_ajax() && ! empty( $_POST['current_page'] ) ) {
return has_block( 'edd/checkout', absint( $_POST['current_page'] ) );
}
return has_block( 'edd/checkout' ) || has_block( 'edd/checkout', absint( edd_get_option( 'purchase_page' ) ) );
}
/**
* Gets a string to represent the cart quantity.
*
* @since 2.0
* @return string
*/
function get_quantity_string() {
$quantity = absint( edd_get_cart_quantity() );
return sprintf(
'%1$s %2$s',
$quantity,
_n( 'item', 'items', $quantity, 'easy-digital-downloads' )
);
}

View File

@ -0,0 +1,84 @@
<?php
/**
* Gateway functions for EDD checkout blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Checkout\Gateways;
defined( 'ABSPATH' ) || exit;
/**
* Gets the accepted payment icons.
*
* @since 2.0
* @return false|array
*/
function get_payment_icons() {
$payment_icons = edd_get_option( 'accepted_cards', false );
if ( empty( $payment_icons ) ) {
return false;
}
$order = edd_get_option( 'payment_icons_order', '' );
if ( empty( $order ) ) {
return $payment_icons;
}
$order = array_flip( explode( ',', $order ) );
$order = array_intersect_key( $order, $payment_icons );
return array_merge( $order, $payment_icons );
}
/**
* Outputs the payment icons for a given gateway.
*
* @since 2.0
* @param array $payment_icons The array of accepted cards for the site.
* @param array $gateway_icons The accepted icons for the specific gateway.
* @return void
*/
function do_payment_icons( $payment_icons, $gateway_icons ) {
echo '<div class="edd-payment-icons">';
foreach ( $payment_icons as $key => $option ) {
if ( ! in_array( $key, $gateway_icons, true ) ) {
continue;
}
echo edd_get_payment_image( $key, $option );
}
echo '</div>';
}
/**
* Gets the accepted payment icons for a gateway.
*
* @since 2.0
* @param array $gateway
* @return array|false
*/
function get_gateway_icons( $gateway_id, $gateway ) {
if ( ! empty( $gateway['icons'] ) ) {
return $gateway['icons'];
}
if ( 'stripe' === $gateway_id ) {
return array(
'mastercard',
'visa',
'discover',
'americanexpress',
);
}
if ( false !== strpos( $gateway_id, 'paypal' ) ) {
return array( 'paypal' );
}
return false;
}

View File

@ -0,0 +1,213 @@
<?php
/**
* EDD downloads blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Downloads;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
use EDD\Blocks\Functions;
if ( ! function_exists( 'edd_blocks_api_products_product' ) ) {
require_once EDD_BLOCKS_DIR . 'includes/downloads/rest.php';
}
add_action( 'init', __NAMESPACE__ . '\register' );
/**
* Registers all of the EDD core blocks.
*
* @since 2.0
* @return void
*/
function register() {
$blocks = array(
'downloads' => array(
'render_callback' => __NAMESPACE__ . '\downloads',
),
'buy-button' => array(
'render_callback' => __NAMESPACE__ . '\buy_button',
),
);
foreach ( $blocks as $block => $args ) {
register_block_type( EDD_BLOCKS_DIR . 'build/' . $block, $args );
}
}
/**
* Renders the order history block.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return string Order history HTML.
*/
function downloads( $block_attributes = array() ) {
// Set up defaults.
$defaults = array(
'image_location' => 'before_entry_header',
'image_size' => 'large',
'image_alignment' => 'center',
'title' => true,
'content' => 'excerpt',
'columns' => 3,
'orderby' => 'post_date',
'order' => 'DESC',
'pagination' => true,
'buy_button' => true,
'category' => array(),
'pagination' => true,
'number' => 6,
'price' => true,
'image_link' => true,
'purchase_link_align' => 'none',
'tag' => array(),
'show_price' => true,
'all_access' => false,
);
$block_attributes = wp_parse_args( $block_attributes, $defaults );
if ( 'rand' === $block_attributes['orderby'] ) {
$block_attributes['pagination'] = false;
}
if ( ! empty( $block_attributes['all_access'] ) ) {
$block_attributes['all_access_customer_downloads_only'] = true;
}
require_once EDD_BLOCKS_DIR . 'includes/downloads/query.php';
$query = new Query( $block_attributes );
$query_args = $query->get_query();
$downloads = new \WP_Query( $query_args );
if ( ! $downloads->have_posts() ) {
/* translators: the plurals downloads name. */
return sprintf( _x( 'No %s found.', 'download post type name', 'easy-digital-downloads' ), edd_get_label_plural() );
}
// Set up classes.
$classes = array(
'wp-block-edd-downloads',
'edd-blocks__downloads',
);
$classes = Functions\get_block_classes( $block_attributes, $classes );
if ( ! empty( $block_attributes['image_location'] ) ) {
add_action( "edd_blocks_downloads_{$block_attributes['image_location']}", __NAMESPACE__ . '\image' );
}
// Always disable the Stripe express checkout buttons in the block editor.
if ( \EDD\Blocks\Functions\is_block_editor() ) {
add_filter( 'edds_prb_purchase_link_enabled', '__return_false' );
}
ob_start();
include EDD_BLOCKS_DIR . 'views/downloads/downloads.php';
wp_reset_postdata();
if ( ! empty( $block_attributes['image_location'] ) ) {
remove_action( "edd_blocks_downloads_{$block_attributes['image_location']}", __NAMESPACE__ . '\image' );
}
return ob_get_clean();
}
/**
* Renders the EDD buy button block.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return string Buy button HTML.
*/
function buy_button( $block_attributes = array() ) {
$block_attributes = wp_parse_args(
$block_attributes,
array(
'download_id' => get_the_ID(),
'show_price' => true,
'align' => '',
)
);
if ( empty( $block_attributes['download_id'] ) || 'download' !== get_post_type( $block_attributes['download_id'] ) ) {
return '';
}
$block_attributes_for_classes = $block_attributes;
unset( $block_attributes_for_classes['align'] );
$classes = array(
'wp-block-edd-buy-button',
'edd-blocks__buy-button',
);
$classes = Functions\get_block_classes( $block_attributes_for_classes, $classes );
remove_filter( 'edd_purchase_link_args', __NAMESPACE__ . '\maybe_update_purchase_links', 100 );
if ( wp_style_is( 'edd-styles', 'registered' ) ) {
wp_enqueue_style( 'edd-styles' );
}
$output = sprintf( '<div class="%s">', implode( ' ', $classes ) );
$output .= edd_get_purchase_link(
array(
'class' => implode( ' ', get_purchase_link_classes( $block_attributes ) ),
'download_id' => absint( $block_attributes['download_id'] ),
'price' => (bool) $block_attributes['show_price'],
)
);
$output .= '</div>';
add_filter( 'edd_purchase_link_args', __NAMESPACE__ . '\maybe_update_purchase_links', 100 );
return $output;
}
/**
* Gets the array of classes for the purchase link buttons from the block attributes.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return array
*/
function get_purchase_link_classes( $block_attributes = array() ) {
$classes = array(
'edd-submit',
);
if ( ! empty( $block_attributes['align'] ) ) {
$classes[] = "align{$block_attributes['align']}";
}
return $classes;
}
add_filter( 'edd_purchase_link_args', __NAMESPACE__ . '\maybe_update_purchase_links', 100 );
/**
* If the blocks button colors have been defined, update all purchase links everywhere.
*
* @since 2.0
* @param array $args
* @return array
*/
function maybe_update_purchase_links( $args ) {
$classes = get_purchase_link_classes();
$current_class = explode( ' ', $args['class'] );
$classes = array_merge( $classes, $current_class );
$args['class'] = implode( ' ', array_unique( $classes ) );
return $args;
}
/**
* Renders a featured image if one is set.
*
* @since 2.0
* @param array $block_attributes
* @return void
*/
function image( $block_attributes ) {
if ( ! \has_post_thumbnail() ) {
return;
}
include EDD_BLOCKS_DIR . 'views/downloads/image.php';
}

View File

@ -0,0 +1,327 @@
<?php
/**
* Query building for EDD downloads blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Downloads;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
class Query {
/**
* The block attributes.
*
* @var array
*/
protected $attributes;
public function __construct( $block_attributes ) {
$this->attributes = $block_attributes;
}
/**
* Gets the downloads query parameters from the block attributes.
*
* @since 2.0
* @return array
*/
public function get_query() {
$query = array(
'post_type' => 'download',
'order' => $this->attributes['order'],
);
$query = $this->parse_pagination( $query, $this->attributes );
$query = $this->parse_orderby( $query, $this->attributes );
$query = $this->parse_tax_query( $query, $this->attributes );
if ( ! empty( $this->attributes['ids'] ) ) {
$query['post__in'] = explode( ',', $this->attributes['ids'] );
}
$query['paged'] = (int) $this->get_paged();
/**
* Allow extensions to filter the downloads query.
* This is the same filter used in EDD core for the downloads shortcode query.
*
* @since 2.0
* @param array $query The array of query parameters.
* @param array $this->attributes The block attributes.
*/
return apply_filters( 'edd_downloads_query', $query, $this->attributes );
}
/**
* Parses the pagination parameters for the downloads query.
*
* @since 2.0
* @param array $query Download query args.
* @return array
*/
private function parse_pagination( $query ) {
if ( $this->attributes['pagination'] || ( ! $this->attributes['pagination'] && $this->attributes['number'] ) ) {
$query['posts_per_page'] = (int) $this->attributes['number'];
if ( $query['posts_per_page'] < 0 ) {
$query['posts_per_page'] = abs( $query['posts_per_page'] );
}
} else {
$query['nopaging'] = true;
}
return $query;
}
/**
* Parses the orderby parameters for the downloads query.
*
* @since 2.0
* @param array $query Download query args.
* @return array
*/
private function parse_orderby( $query ) {
switch ( $this->attributes['orderby'] ) {
case 'price':
$query['meta_key'] = 'edd_price';
$query['orderby'] = 'meta_value_num';
break;
case 'sales':
$query['meta_key'] = '_edd_download_sales';
$query['orderby'] = 'meta_value_num';
break;
case 'earnings':
$query['meta_key'] = '_edd_download_earnings';
$query['orderby'] = 'meta_value_num';
break;
default:
$query['orderby'] = $this->attributes['orderby'];
break;
}
return $query;
}
/**
* Parses the taxonomy parameters for the downloads query.
*
* @since 2.0
* @param array $query Download query args.
* @return array
*/
private function parse_tax_query( $query ) {
if ( empty( $this->attributes['tag'] ) && empty( $this->attributes['category'] ) && empty( $this->attributes['exclude_category'] ) && empty( $this->attributes['exclude_tags'] ) ) {
return $query;
}
$query['tax_query'] = array(
'relation' => ! empty( $this->attributes['relation'] ) ? $this->attributes['relation'] : 'AND',
);
$query = $this->parse_tags( $query, $this->attributes );
$query = $this->parse_categories( $query, $this->attributes );
$query = $this->parse_exclude_category( $query, $this->attributes );
$query = $this->parse_exclude_tags( $query, $this->attributes );
$query = $this->parse_author( $query, $this->attributes );
if ( ! empty( $this->attributes['exclude_tags'] ) || ! empty( $this->attributes['exclude_category'] ) ) {
$query['tax_query']['relation'] = 'AND';
}
return $query;
}
/**
* Parses the tag parameters for the downloads query.
*
* @since 2.0
* @param array $query Download query args.
* @return array
*/
private function parse_tags( $query ) {
if ( empty( $this->attributes['tag'] ) ) {
return $query;
}
$term_ids = $this->get_term_ids( array_filter( (array) $this->attributes['tag'] ), 'download_tag' );
if ( ! empty( $term_ids ) ) {
$query['tax_query'][] = array(
'taxonomy' => 'download_tag',
'field' => 'term_id',
'terms' => $term_ids,
);
}
return $query;
}
/**
* Parses the category parameters for the downloads query.
*
* @since 2.0
* @param array $query Download query args.
* @return array
*/
private function parse_categories( $query ) {
if ( empty( $this->attributes['category'] ) ) {
return $query;
}
$term_ids = $this->get_term_ids( array_filter( (array) $this->attributes['category'] ) );
if ( ! empty( $term_ids ) ) {
$query['tax_query'][] = array(
'taxonomy' => 'download_category',
'field' => 'term_id',
'terms' => $term_ids,
);
}
return $query;
}
/**
* Parses the excluded category parameters for the downloads query.
*
* @since 2.0
* @param array $query Download query args.
* @return array
*/
private function parse_exclude_category( $query ) {
if ( empty( $this->attributes['exclude_category'] ) ) {
return $query;
}
$term_ids = $this->get_term_ids( $this->attributes['exclude_category'] );
if ( ! empty( $term_ids ) ) {
$query['tax_query'][] = array(
'taxonomy' => 'download_category',
'field' => 'term_id',
'terms' => $term_ids,
'operator' => 'NOT IN',
);
}
return $query;
}
/**
* Parses the excluded tags parameters for the downloads query.
*
* @since 2.0
* @param array $query Download query args.
* @return array
*/
private function parse_exclude_tags( $query ) {
if ( empty( $this->attributes['exclude_tags'] ) ) {
return $query;
}
$term_ids = $this->get_term_ids( $this->attributes['exclude_tags'], 'download_tag' );
if ( ! empty( $term_ids ) ) {
$query['tax_query'][] = array(
'taxonomy' => 'download_tag',
'field' => 'term_id',
'terms' => $term_ids,
'operator' => 'NOT IN',
);
}
return $query;
}
/**
* Gets an array of term ids for a parameter.
*
* @param array|string $list The term IDs to evaluate.
* @param string $taxonomy The taxonomy to check.
* @return array
*/
private function get_term_ids( $list, $taxonomy = 'download_category' ) {
$term_list = is_array( $list ) ? $list : explode( ',', $list );
$term_ids = array();
foreach ( $term_list as $term ) {
$t_id = (int) $term;
$is_id = is_int( $t_id ) && ! empty( $t_id );
if ( $is_id ) {
$term_ids[] = $t_id;
continue;
}
$term_object = get_term_by( 'slug', $term, $taxonomy );
if ( ! empty( $term_object->term_id ) ) {
$term_ids[] = $term_object->term_id;
}
}
return $term_ids;
}
/**
* Parses the author parameters for the downloads query.
*
* @since 2.0
* @param array $query
* @return array
*/
private function parse_author( $query ) {
if ( empty( $this->attributes['author'] ) ) {
return $query;
}
$authors = explode( ',', $this->attributes['author'] );
if ( ! empty( $authors ) ) {
$author_ids = array();
$author_names = array();
foreach ( $authors as $author ) {
if ( is_numeric( $author ) ) {
$author_ids[] = $author;
} else {
$user = get_user_by( 'login', $author );
if ( $user ) {
$author_ids[] = $user->ID;
}
}
}
if ( ! empty( $author_ids ) ) {
$author_ids = array_unique( array_map( 'absint', $author_ids ) );
$query['author'] = implode( ',', $author_ids );
}
}
return $query;
}
/**
* Parses the paged parameters for the downloads query.
*
* @since 2.0
* @return int
*/
private function get_paged() {
if ( get_query_var( 'paged' ) ) {
return get_query_var( 'paged' );
}
if ( get_query_var( 'page' ) ) {
return get_query_var( 'page' );
}
return 1;
}
}

View File

@ -0,0 +1,83 @@
<?php
/**
* REST API block functions.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Downloads\Rest;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
add_action( 'rest_api_init', __NAMESPACE__ . '\register_rest_fields' );
/**
* Register rest fields.
*
* @since 2.0
* @return void
*/
function register_rest_fields() {
$taxonomies = array( 'download_category', 'download_tag' );
foreach ( $taxonomies as $taxonomy ) {
register_rest_field(
$taxonomy,
'meta',
array(
'get_callback' => __NAMESPACE__ . '\get_term_meta',
)
);
}
}
/**
* Get term meta.
*
* @since 2.0
* @param array $object
* @param string $field_name
* @param mixed $request
*
* @return array
*/
function get_term_meta( $object, $field_name, $request ) {
if ( empty( $object['id'] ) ) {
return false;
}
// Get the image ID.
$image_id = get_term_meta( $object['id'], 'download_term_image', true );
// Build meta array.
return array( 'image' => wp_get_attachment_image( $image_id ) );
}
add_filter( 'edd_api_products_product', __NAMESPACE__ . '\update_products_api' );
/**
* Add data to the products API output.
*
* @since 2.0
* @param array $product
* @return array
*/
function update_products_api( $product ) {
// Get the product ID.
$product_id = $product['info']['id'];
// Download Image.
$product['info']['image'] = wp_get_attachment_image( get_post_meta( $product_id, '_thumbnail_id', true ) );
// Purchase link.
$product['info']['purchase_link'] = edd_get_purchase_link( array( 'download_id' => $product_id ) );
// Price.
$product['info']['price'] = edd_price( $product_id, false );
return $product;
}

View File

@ -0,0 +1,154 @@
<?php
/**
* Form blocks for EDD.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Forms;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
use EDD\Blocks\Functions;
require_once EDD_BLOCKS_DIR . 'includes/forms/recaptcha.php';
add_action( 'init', __NAMESPACE__ . '\register' );
/**
* Registers all of the EDD core blocks.
*
* @since 2.0
* @return void
*/
function register() {
$blocks = array(
'login' => array(
'render_callback' => __NAMESPACE__ . '\login',
),
'register' => array(
'render_callback' => __NAMESPACE__ . '\registration',
),
);
foreach ( $blocks as $block => $args ) {
register_block_type( EDD_BLOCKS_DIR . 'build/' . $block, $args );
}
}
/**
* Renders the login form block.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return string Login form HTML.
*/
function login( $block_attributes = array() ) {
if ( is_user_logged_in() && empty( $_GET['reauth'] ) ) {
return '';
}
$block_attributes = wp_parse_args(
$block_attributes,
array(
'current' => false,
'redirect' => '',
)
);
$action = ! empty( $_GET['action'] ) ? sanitize_text_field( $_GET['action'] ) : false;
$block_classes = array( 'wp-block-edd-login' );
if ( $action ) {
$block_classes[] = "wp-block-edd-login__{$action}";
}
$classes = Functions\get_block_classes( $block_attributes, $block_classes );
ob_start();
?>
<div class="<?php echo esc_attr( implode( ' ', $block_classes ) ); ?>">
<?php
// Show any error messages after form submission.
edd_print_errors();
if ( 'lostpassword' === $action ) {
include EDD_BLOCKS_DIR . 'views/forms/lost-password.php';
} elseif ( 'rp' === $action ) {
list( $rp_login, $rp_key ) = explode( ':', wp_unslash( $_COOKIE[ 'wp-resetpass-' . COOKIEHASH ] ), 2 );
include EDD_BLOCKS_DIR . 'views/forms/reset-password.php';
} else {
$redirect_url = get_redirect_url( $block_attributes, true );
include EDD_BLOCKS_DIR . 'views/forms/login.php';
}
?>
</div>
<?php
return ob_get_clean();
}
/**
* Renders the registration form block.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return string Registration from HTML.
*/
function registration( $block_attributes = array() ) {
$block_attributes = wp_parse_args(
$block_attributes,
array(
'current' => true,
'redirect' => '',
)
);
ob_start();
?>
<div class="wp-block-edd-register">
<?php
edd_print_errors();
if ( ! is_user_logged_in() ) {
$redirect_url = get_redirect_url( $block_attributes );
include EDD_BLOCKS_DIR . 'views/forms/registration.php';
}
?>
</div>
<?php
return ob_get_clean();
}
/**
* Gets the redirect URL from the block attributes.
*
* @since 2.0
* @param array $block_attributes
* @param bool $is_login_form
* @return string
*/
function get_redirect_url( $block_attributes, $is_login_form = false ) {
// Check for the WordPress redirect URL.
if ( $is_login_form && ! empty( $_GET['redirect_to'] ) && filter_var( $_GET['redirect_to'], FILTER_VALIDATE_URL ) ) {
return $_GET['redirect_to'];
}
// Set the redirect to the current page by default.
$redirect_url = edd_get_current_page_url();
// If the block is set to redirect to the current page, return.
if ( ! empty( $block_attributes['current'] ) ) {
return $redirect_url;
}
// If a custom redirect URL is set for the block, use that.
if ( ! empty( $block_attributes['redirect'] ) && filter_var( $block_attributes['redirect'], FILTER_VALIDATE_URL ) ) {
return $block_attributes['redirect'];
}
// Otherwise, check for the EDD login redirect page.
$login_redirect_page = $is_login_form ? edd_get_option( 'login_redirect_page', false ) : false;
return $login_redirect_page ? get_permalink( $login_redirect_page ) : $redirect_url;
}

View File

@ -0,0 +1,195 @@
<?php
/**
* reCAPTCHA handling for blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Recaptcha;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
add_action( 'wp_enqueue_scripts', __NAMESPACE__ . '\register_script' );
/**
* Registers the reCAPTCHA script.
*
* @since 2.0
* @return void
*/
function register_script() {
$site_key = get_site_key();
if ( ! $site_key ) {
return;
}
$url = add_query_arg(
array(
'render' => $site_key,
),
'https://www.google.com/recaptcha/api.js'
);
wp_register_script( 'google-recaptcha', esc_url_raw( $url ), array(), '3', true );
wp_register_script( 'edd-recaptcha', EDD_BLOCKS_URL . 'assets/js/recaptcha.js', array( 'google-recaptcha' ), EDD_VERSION, true );
wp_localize_script(
'edd-recaptcha',
'EDDreCAPTCHA',
get_localize_args()
);
}
/**
* Initialize reCAPTCHA scripts and fields.
*
* @since 2.0
* @return void
*/
function initialize() {
if ( ! get_site_key() ) {
return;
}
enqueue();
do_inputs();
}
/**
* Renders the hidden inputs needed for reCAPTCHA validation.
*
* @since 2.0
* @return void
*/
function do_inputs() {
?>
<input style="position: fixed; bottom: 0px; left: -10000px; width: 1px; height: 1px; overflow: hidden;" type="text" name="edd-blocks-recaptcha" id="edd-blocks-recaptcha" required value=""/>
<input type="hidden" name="edd_blocks_ip" value="<?php echo esc_attr( edd_get_ip() ); ?>"/>
<?php
}
/**
* Enqueues the script.
*
* @since 2.0
* @param string $submit
* @param string $action
* @return void
*/
function enqueue() {
wp_enqueue_script( 'edd-recaptcha' );
}
add_action( 'wp_ajax_nopriv_edd_recaptcha_validate', __NAMESPACE__ . '\validate' );
add_action( 'wp_ajax_edd_recaptcha_validate', __NAMESPACE__ . '\validate' );
/**
* Checks for the reCAPTCHA validation.
*
* @since 2.0
* @return void
*/
function validate() {
$token = ! empty( $_POST['token'] ) ? trim( sanitize_text_field( $_POST['token'] ) ) : false;
if ( ! $token ) {
wp_send_json_error(
array(
'error' => 'invalid_recaptcha_missing',
'message' => __( 'reCAPTCHA validation missing.', 'easy-digital-downloads' ),
)
);
}
try {
$args = array(
'headers' => array(
'Content-type' => 'application/x-www-form-urlencoded',
),
'body' => array(
'secret' => edd_get_option( 'recaptcha_secret_key', false ),
'response' => $token,
'remoteip' => trim( sanitize_text_field( $_POST['ip'] ) ),
),
);
$validated = validate_recaptcha(
wp_safe_remote_post(
'https://www.google.com/recaptcha/api/siteverify',
$args
)
);
// No errors with data validation.
if ( true === $validated ) {
wp_send_json_success(
array( 'success' => true )
);
} else {
wp_send_json_error( $validated );
}
} catch ( Exception $e ) {
wp_send_json_error(
array(
'error' => 'invalid_recaptcha_bad',
'message' => __( 'There was an error validating the reCAPTCHA. Please try again.', 'easy-digital-downloads' ),
)
);
}
}
/**
* Evaluates the reCAPTCHA response.
*
* @since 2.0
* @param array|WP_Error $response
* @return bool
*/
function validate_recaptcha( $response ) {
if ( is_wp_error( $response ) ) {
return array(
'error' => 'invalid_recaptcha_bad',
'message' => __( 'Unexpected reCAPTCHA error. Please try again.', 'easy-digital-downloads' ),
);
}
$verify = json_decode( wp_remote_retrieve_body( $response ) );
if ( true !== $verify->success ) {
return array(
'error' => 'invalid_recaptcha_bad',
'message' => __( 'reCAPTCHA verification failed. Please contact a site administrator.', 'easy-digital-downloads' ),
);
}
if ( isset( $verify->score ) && (float) $verify->score < 0.5 ) {
return array(
'error' => 'invalid_recaptcha_low_score',
'message' => __( 'reCAPTCHA verification failed with low score. Please contact a site administrator.', 'easy-digital-downloads' ),
);
}
return true;
}
/**
* Gets the array of localized parameters for the recaptcha.
*
* @since 2.0
* @return array
*/
function get_localize_args() {
return array(
'ajaxurl' => edd_get_ajax_url(),
'sitekey' => get_site_key(),
'error' => __( 'Error', 'easy-digital-downloads' ),
);
}
/**
* Gets the reCAPTCHA site key if both the site key and secret key are set.
*
* @since 2.0
* @return false|string
*/
function get_site_key() {
$site_key = edd_get_option( 'recaptcha_site_key', false );
$secret_key = edd_get_option( 'recaptcha_secret_key', false );
return ! empty( $site_key ) && ! empty( $secret_key ) ? $site_key : false;
}

View File

@ -0,0 +1,128 @@
<?php
/**
* General blocks functions.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Functions;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
add_filter( 'block_categories_all', __NAMESPACE__ . '\register_edd_block_category', 10, 2 );
/**
* Registers the EDD category for blocks.
*
* @since 2.0
* @param array $block_categories
* @param \WP_Block_Editor_Context $editor_context
* @return array
*/
function register_edd_block_category( $block_categories, $editor_context ) {
$block_categories[] = array(
'slug' => 'easy-digital-downloads',
'title' => __( 'Easy Digital Downloads', 'easy-digital-downloads' ),
'icon' => 'download',
);
return $block_categories;
}
/**
* Gets the array of classes for a block.
*
* @since 2.0
* @param array $block_attributes
* @param array $classes
* @return array
*/
function get_block_classes( $block_attributes, $classes = array() ) {
if ( ! empty( $block_attributes['columns'] ) && 1 < (int) $block_attributes['columns'] ) {
$columns = (int) $block_attributes['columns'];
$classes[] = 'edd-blocks__columns';
if ( 3 <= $columns ) {
$classes[] = "edd-blocks__columns-{$columns}";
}
}
if ( ! empty( $block_attributes['align'] ) ) {
$classes[] = "align{$block_attributes['align']}";
}
if ( ! empty( $block_attributes['className'] ) ) {
$classes[] = $block_attributes['className'];
}
return array_filter( array_unique( $classes ) );
}
/**
* Marks a field as required with the HTML5 attribute.
*
* @since 2.0
* @param string $field
* @return void
*/
function mark_field_required( $field ) {
if ( edd_field_is_required( $field ) ) {
echo 'required';
}
}
/**
* Gets an array of CSS classes for an edd-submit button.
*
* @since 2.0
* @param array $classes Optional custom classes.
* @return array
*/
function get_button_classes( $classes = array() ) {
$button_classes = array_merge(
$classes,
array(
'button',
'edd-submit',
edd_get_button_color_class(),
)
);
return array_filter( $button_classes );
}
/**
* Gets an array of classes for a given input field.
*
* @since 2.0
* @param string $field
* @param array $classes
* @return array
*/
function get_input_classes( $field, $classes = array() ) {
$classes = array_merge( array( $field ), $classes );
if ( edd_field_is_required( $field ) ) {
$classes[] = 'required';
}
return array_filter( array_unique( $classes ) );
}
/**
* Checks whether we are viewing content in the block editor.
*
* @since 2.0
* @param string $current_user_can Whether the current user needs to have a specific capability.
* @return false|string
*/
function is_block_editor( $current_user_can = '' ) {
$is_block_editor = ! empty( $_GET['edd_blocks_is_block_editor'] ) ? $_GET['edd_blocks_is_block_editor'] : false;
// If not the block editor or custom capabilities are not required, return.
if ( ! $is_block_editor || empty( $current_user_can ) ) {
return $is_block_editor;
}
$user = wp_get_current_user();
return hash_equals( md5( $user->user_email ), $is_block_editor ) && current_user_can( $current_user_can );
}

View File

@ -0,0 +1,184 @@
<?php
/**
* Functions for orders blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Orders\Functions;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
/**
* Gets the order details/downloads link.
* Also pulls data from the original order history row.
*
* @since 2.0
* @param \EDD\Orders\Order $order
* @return void
*/
function get_details( $order ) {
if ( $order->is_recoverable() ) :
$recovery_url = $order->get_recovery_url();
if ( $recovery_url ) :
?>
&mdash; <a href="<?php echo esc_url( $recovery_url ); ?>">
<?php esc_html_e( 'Complete Purchase', 'easy-digital-downloads' ); ?>
</a>
<?php
endif;
?>
<?php else : ?>
<div class="edd-blocks-orders__order-downloads-link">
<a href="<?php echo esc_url( edd_get_receipt_page_uri( $order->id ) ); ?>">
<?php esc_html_e( 'View Details and Downloads', 'easy-digital-downloads' ); ?>
</a>
</div>
<?php
endif;
do_action( 'edd_order_history_order_details', $order );
do_order_details( $order );
}
/**
* Outputs the additional order data. Table markup is replaced.
*
* @since 2.0
* @param \EDD\Orders\Order $order
* @param string $action The action being called.
* @param mixed $args
* @return string
*/
function do_order_details( $order, $action = 'edd_order_history_row_end', ...$args ) {
ob_start();
do_action( $action, $order, $args );
$details = ob_get_clean();
if ( empty( $details ) ) {
return;
}
$details = replace_table_markup( $details );
echo wp_kses_post( $details );
}
/**
* Replaces table markup in a string with <div> elements.
*
* @since 2.0
* @param string $string
* @return string
*/
function replace_table_markup( $string ) {
$string = str_replace( '<td', '<div', $string );
$string = str_replace( '</td', '</div', $string );
return $string;
}
/**
* Gets the array of args for retrieving orders for the order history block.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return array
*/
function get_order_history_args( $block_attributes ) {
$number = (int) $block_attributes['number'];
$current_page = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$args = array(
'user_id' => get_current_user_id(),
'type' => 'sale',
'number' => $number,
'offset' => $number * ( intval( $current_page ) - 1 ),
'status__not_in' => array( 'trash' )
);
if ( ! empty( $block_attributes['recurring'] ) ) {
$args['status__not_in'] = array( 'edd_subscription' );
}
return apply_filters( 'edd_blocks_order_history_args', $args, $block_attributes );
}
/**
* Gets the EDD purchase session, unless the user is in the block editor.
* Then it creates a dummy purchase session and uses that to show a sample confirmation screen.
*
* @since 2.0
* @return array|false
*/
function get_purchase_session() {
if ( ! \EDD\Blocks\Functions\is_block_editor() ) {
return edd_get_purchase_session();
}
$sample_order_key = get_sample_order_payment_key();
if ( $sample_order_key ) {
return array(
'purchase_key' => $sample_order_key,
);
}
return false;
}
/**
* Gets the payment key:
* Checks the URL directly
* Checks for the order ID and hashed order value
* Checks the current purchase session
*
* @since 2.0
* @return string|false
*/
function get_payment_key() {
if ( \EDD\Blocks\Functions\is_block_editor( 'edit_shop_payments' ) ) {
$sample_order_key = get_sample_order_payment_key();
if ( $sample_order_key ) {
return $sample_order_key;
}
}
if ( isset( $_GET['payment_key'] ) ) {
return urldecode( $_GET['payment_key'] );
}
if ( ! empty( $_GET['order'] ) && ! empty( $_GET['id'] ) ) {
return edd_get_payment_key( absint( $_GET['id'] ) );
}
$session = edd_get_purchase_session();
if ( $session ) {
return $session['purchase_key'];
}
return false;
}
/**
* Gets some orders from the site for use in the editor.
*
* @since 2.0
* @return false|array
*/
function get_sample_order_payment_key() {
if ( ! \EDD\Blocks\Functions\is_block_editor( 'edit_shop_payments' ) ) {
return false;
}
$orders = edd_get_orders(
array(
'number' => 10,
'type' => 'sale',
'status' => 'complete',
'fields' => 'payment_key',
'orderby' => array_rand( array_flip( array( 'email', 'id', 'payment_key', 'total', 'customer_id', 'date_created' ) ) ),
'order' => 'ASC',
'no_found_rows' => true,
)
);
return $orders ? array_rand( array_flip( $orders ) ) : false;
}

View File

@ -0,0 +1,315 @@
<?php
/**
* Orders blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Orders;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
use EDD\Blocks\Functions as Helpers;
require_once EDD_BLOCKS_DIR . 'includes/orders/functions.php';
add_action( 'init', __NAMESPACE__ . '\register' );
/**
* Registers all of the EDD core blocks.
*
* @since 2.0
* @return void
*/
function register() {
$blocks = array(
'order-history' => array(
'render_callback' => __NAMESPACE__ . '\orders',
),
'confirmation' => array(
'render_callback' => __NAMESPACE__ . '\confirmation',
),
'receipt' => array(
'render_callback' => __NAMESPACE__ . '\receipt',
),
);
foreach ( $blocks as $block => $args ) {
register_block_type( EDD_BLOCKS_DIR . 'build/' . $block, $args );
}
}
/**
* Renders the order history block.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return string
*/
function orders( $block_attributes = array() ) {
if ( ! is_user_logged_in() ) {
return '';
}
if ( edd_user_pending_verification() ) {
ob_start();
if ( ! empty( $_GET['edd-verify-request'] ) ) :
?>
<p class="edd-account-pending edd_success">
<?php esc_html_e( 'An email with an activation link has been sent.', 'easy-digital-downloads' ); ?>
</p>
<?php endif; ?>
<p class="edd-account-pending">
<?php
printf(
wp_kses_post(
/* translators: 1. Opening anchor tag. 2. Closing anchor tag. */
__( 'Your account is pending verification. Please click the link in your email to activate your account. No email? %1$sSend a new activation code.%2$s', 'easy-digital-downloads' )
),
'<a href="' . esc_url( edd_get_user_verification_request_url() ) . '">',
'</a>'
);
?>
</p>
<?php
return ob_get_clean();
}
$block_attributes = wp_parse_args(
$block_attributes,
array(
'number' => 20,
'columns' => 2,
)
);
$number = (int) $block_attributes['number'];
$args = Functions\get_order_history_args( $block_attributes );
// Set up classes.
$classes = array(
'wp-block-edd-orders',
'edd-blocks__orders',
);
ob_start();
?>
<div class="<?php echo esc_attr( implode( ' ', array_filter( $classes ) ) ); ?>">
<?php
$classes = Helpers\get_block_classes( $block_attributes, array( 'edd-blocks__orders-grid' ) );
$orders = edd_get_orders( $args );
include EDD_BLOCKS_DIR . 'views/orders/orders.php';
unset( $args['number'], $args['offset'] );
$count = edd_count_orders( $args );
include EDD_BLOCKS_DIR . 'views/orders/pagination.php';
?>
</div>
<?php
return ob_get_clean();
}
/**
* Renders the order confirmation block.
*
* @since 2.0
* @return string
*/
function confirmation( $block_attributes = array() ) {
$session = Functions\get_purchase_session();
if ( empty( $session['purchase_key'] ) ) {
if ( Helpers\is_block_editor() ) {
return '<p class="edd-alert edd-alert-info">' . esc_html( __( 'To view a sample confirmation screen, you need to have at least one order in your store.', 'easy-digital-downloads' ) ) . '</p>';
}
return '<p class="edd-alert edd-alert-error">' . esc_html( __( 'Your purchase session could not be retrieved.', 'easy-digital-downloads' ) ) . '</p>';
}
global $edd_receipt_args;
$edd_receipt_args = wp_parse_args(
$block_attributes,
array(
'payment_key' => false,
'payment_method' => true,
)
);
// Set up classes.
$classes = array(
'wp-block-edd-confirmation',
'edd-blocks__confirmation',
);
ob_start();
?>
<div class="<?php echo esc_attr( implode( ' ', array_filter( $classes ) ) ); ?>">
<?php
$order = edd_get_order_by( 'payment_key', $session['purchase_key'] );
$edd_receipt_args['id'] = $order->id;
include EDD_BLOCKS_DIR . 'views/orders/receipt-items.php';
include EDD_BLOCKS_DIR . 'views/orders/totals.php';
?>
<div class="edd-blocks__confirmation-details">
<a href="<?php echo esc_url( edd_get_receipt_page_uri( $order->id ) ); ?>">
<?php esc_html_e( 'View Details and Downloads', 'easy-digital-downloads' ); ?>
</a>
</div>
</div>
<?php
return ob_get_clean();
}
/**
* Renders the full order receipt.
*
* @since 2.0
* @param array $block_attributes
* @return string
*/
function receipt( $block_attributes = array() ) {
global $edd_receipt_args;
$edd_receipt_args = wp_parse_args(
$block_attributes,
array(
'error' => __( 'Sorry, trouble retrieving order receipt.', 'easy-digital-downloads' ),
'payment_key' => false,
'payment_method' => true,
)
);
$payment_key = Functions\get_payment_key();
// No key found.
if ( ! $payment_key ) {
if ( Helpers\is_block_editor() ) {
return '<p class="edd-alert edd-alert-info">' . esc_html( __( 'To view a sample receipt, you need to have at least one order in your store.', 'easy-digital-downloads' ) ) . '</p>';
}
return '<p class="edd-alert edd-alert-error">' . esc_html( $edd_receipt_args['error'] ) . '</p>';
}
ob_start();
edd_print_errors();
$order = edd_get_order_by( 'payment_key', $payment_key );
$user_can_view = edd_can_view_receipt( $payment_key );
if ( ! $user_can_view ) {
show_no_access_message( $order );
return ob_get_clean();
}
$classes = array(
'wp-block-edd-receipt',
'edd-blocks__receipt',
);
?>
<div class="<?php echo esc_attr( implode( ' ', array_filter( $classes ) ) ); ?>">
<?php
include EDD_BLOCKS_DIR . 'views/orders/totals.php';
maybe_show_receipt( $order );
?>
</div>
<?php
return ob_get_clean();
}
/**
* Shows the message if the current viewer doesn't have access to any order information.
*
* @since 2.0
* @param EDD\Orders\Order $order
* @return void
*/
function show_no_access_message( $order ) {
// User is logged in, but does not have access.
if ( is_user_logged_in() ) {
printf(
'<p class="edd-alert edd-alert-error">%s</p>',
esc_html__( 'Sorry, you do not have permission to view this receipt.', 'easy-digital-downloads' )
);
return;
}
// User is not logged in and can view a guest order.
if ( empty( $order->user_id ) ) {
printf(
'<p>%s</p>',
esc_html__( 'Please confirm your email address to access your downloads.', 'easy-digital-downloads' )
);
include EDD_BLOCKS_DIR . 'views/orders/guest.php';
return;
}
// Otherwise, the order was made by a customer with a user account.
printf(
'<p>%s</p>',
esc_html__( 'Please log in to view your order.', 'easy-digital-downloads' )
);
echo \EDD\Blocks\Forms\login( array( 'redirect' => edd_get_receipt_page_uri( $order->id ) ) );
}
/**
* Shows the full receipt details if criteria are met; otherwise show a verification or login form.
*
* @since 2.0
* @param EDD\Orders\Order $order
* @return void
*/
function maybe_show_receipt( $order ) {
$session = edd_get_purchase_session();
if ( is_user_logged_in() || ( ! empty( $session['purchase_key'] ) && $session['purchase_key'] === $order->payment_key ) ) {
global $edd_receipt_args;
include EDD_BLOCKS_DIR . 'views/orders/receipt-items.php';
/**
* Fires after the order receipt table.
*
* @since 3.0
* @param \EDD\Orders\Order $order Current order.
* @param array $edd_receipt_args [edd_receipt] shortcode arguments.
*/
do_action( 'edd_order_receipt_after_table', $order, $edd_receipt_args );
return;
}
// The order belongs to a registered WordPress user.
?>
<p>
<?php esc_html_e( 'Please log in to access your downloads.', 'easy-digital-downloads' ); ?>
</p>
<?php
echo \EDD\Blocks\Forms\login( array( 'current' => true ) );
}
add_action( 'edd_view_receipt_guest', __NAMESPACE__ . '\verify_guest_email' );
/**
* Verfies the email address to view the details for a guest order.
*
* @since 2.0
* @param array $data
* @return void
*/
function verify_guest_email( $data ) {
if ( empty( $data['edd_guest_email'] ) || empty( $data['edd_guest_nonce'] ) || ! wp_verify_nonce( $data['edd_guest_nonce'], 'edd-guest-nonce' ) ) {
edd_set_error( 'edd-guest-error', __( 'Your email address could not be verified.', 'easy-digital-downloads' ) );
return;
}
$order = edd_get_order( $data['order_id'] );
if ( $order instanceof \EDD\Orders\Order && $data['edd_guest_email'] === $order->email ) {
edd_set_purchase_session(
array(
'purchase_key' => $order->payment_key,
)
);
return;
}
edd_set_error( 'edd-guest-error', __( 'Your email address could not be verified.', 'easy-digital-downloads' ) );
}

View File

@ -0,0 +1,72 @@
<?php
/**
* Style functions for blocks.
*
* @since 2.0
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
*/
namespace EDD\Blocks\Styles;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
add_action( 'enqueue_block_assets', __NAMESPACE__ . '\add_to_global_styles' );
/**
* Adds our custom EDD button colors to the global stylesheet.
*
* @since 2.0
* @return void
*/
function add_to_global_styles() {
$styles = array(
'--edd-blocks-light-grey:#eee;',
);
$rules = array();
$colors = edd_get_option( 'button_colors' );
if ( ! empty( $colors ) ) {
foreach ( $colors as $setting => $value ) {
if ( empty( $value ) ) {
continue;
}
$styles[] = "--edd-blocks-button-{$setting}:{$value };";
if ( 'text' === $setting ) {
$rules[] = '.edd-submit,.has-edd-button-text-color{color: var(--edd-blocks-button-text) !important;}';
} elseif ( 'background' === $setting ) {
$rules[] = '.edd-submit,.has-edd-button-background-color{background-color: var(--edd-blocks-button-background) !important;}';
$rules[] = '.has-edd-button-background-text-color{color: var(--edd-blocks-button-background) !important;}';
}
}
}
if ( empty( $styles ) ) {
return;
}
$inline_style = 'body{' . implode( ' ', $styles ) . '}';
if ( ! empty( $rules ) ) {
$inline_style .= implode( ' ', $rules );
}
$stylesheet = wp_style_is( 'edd-styles', 'registered' ) ? 'edd-styles' : 'global-styles';
wp_add_inline_style( $stylesheet, $inline_style );
}
add_filter( 'edd_button_color_class', __NAMESPACE__ . '\update_button_color_class' );
/**
* Update the EDD button color class from the new color settings.
*
* @since 2.0
* @param string $class
* @return string
*/
function update_button_color_class( $class ) {
$classes = array();
$color_options = edd_get_option( 'button_colors' );
if ( ! empty( $color_options['background'] ) ) {
$classes[] = 'has-edd-button-background-color';
}
if ( ! empty( $color_options['text'] ) ) {
$classes[] = 'has-edd-button-text-color';
}
return ! empty( $classes ) ? implode( ' ', $classes ) : $class;
}

View File

@ -0,0 +1,286 @@
<?php
/**
* Featured images for terms.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Terms;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
class Images {
/**
* The term image meta key.
*
* @var string
*/
private $meta_key = 'download_term_image';
/**
* The taxonomies for which term images are registered.
*
* @var array
*/
private $taxonomies = array( 'download_category', 'download_tag' );
/**
* Constructor
*
* @since 2.0
*/
public function __construct() {
register_meta(
'term',
$this->meta_key,
array(
'type' => 'integer',
'single' => true,
)
);
foreach ( $this->taxonomies as $taxonomy ) {
add_action( "{$taxonomy}_add_form_fields", array( $this, 'add_taxonomy_meta_fields' ), 5, 2 );
add_action( "{$taxonomy}_edit_form_fields", array( $this, 'edit_taxonomy_meta_fields' ), 5, 2 );
add_action( "edited_{$taxonomy}", array( $this, 'save_term_meta' ) );
add_action( "create_{$taxonomy}", array( $this, 'save_term_meta' ) );
add_action( "edit_{$taxonomy}", array( $this, 'save_term_meta' ) );
add_filter( "manage_edit-{$taxonomy}_columns", array( $this, 'add_column' ) );
add_action( "manage_{$taxonomy}_custom_column", array( $this, 'manage_taxonomy_column' ), 10, 3 );
}
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}
/**
* Enqueues the JS needed for uploading term images.
*
* @since 2.0
* @return void
*/
public function enqueue_scripts() {
$screen = get_current_screen();
if ( empty( $screen ) || ! in_array( $screen->taxonomy, $this->taxonomies, true ) ) {
return;
}
wp_enqueue_media();
wp_enqueue_script( 'edd-term-image-upload', EDD_BLOCKS_URL . 'assets/js/term-image.js', array( 'jquery', 'media-upload', 'thickbox' ), EDD_VERSION, true );
wp_localize_script(
'edd-term-image-upload',
'EDDTermImages',
array(
'text' => __( 'Select Image', 'easy-digital-downloads' ),
)
);
}
/**
* Displays the term image UI for adding a new term.
*
* @since 2.0
*
* @return void
*/
public function add_taxonomy_meta_fields() {
?>
<div class="form-field term-image-wrap">
<?php wp_nonce_field( "{$this->meta_key}_save-settings", "{$this->meta_key}_nonce", false ); ?>
<label for="<?php echo esc_attr( $this->meta_key ); ?>" class="screen-reader-text"><?php esc_html_e( 'Term Image', 'easy-digital-downloads' ); ?></label>
<?php $this->render_buttons( $this->meta_key ); ?>
<p class="description">
<?php esc_html_e( 'Set Term Image.', 'easy-digital-downloads' ); ?>
</p>
</div>
<?php
}
/**
* Show the image UI for existing terms.
*
* @param WP_Term $term
* @return void
*/
public function edit_taxonomy_meta_fields( $term ) {
$term_id = $term->term_id;
$image_id = $this->get_meta( $term_id );
wp_nonce_field( "{$this->meta_key}_save-settings", "{$this->meta_key}_nonce", false );
?>
<tr class="form-field term-image-wrap">
<th scope="row" >
<label for="<?php echo esc_attr( $this->meta_key ); ?>">
<?php esc_html_e( 'Term Image', 'easy-digital-downloads' ); ?>
</label>
</th>
<td>
<?php
if ( $image_id ) {
$this->render_image_preview( $image_id, $term->name );
}
$this->render_buttons( $this->meta_key, $image_id );
?>
<p class="description">
<?php
printf(
/* translators: 1. name of the term */
esc_attr__( 'Set Term Image for %1$s.', 'easy-digital-downloads' ),
esc_attr( $term->name )
);
?>
</p>
</td>
</tr>
<?php
}
/**
* Renders the image preview.
*
* @since 2.0
* @param int $id The image ID.
* @param string $alt The alt text.
* @return void
*/
private function render_image_preview( $id, $alt = '' ) {
if ( empty( $id ) ) {
return;
}
/* translators: the placeholder refers to which featured image */
$alt_text = sprintf( __( '%s featured image', 'easy-digital-downloads' ), esc_attr( $alt ) );
$preview = wp_get_attachment_image_src( (int) $id, 'medium' );
?>
<div class="upload-image-preview">
<img src="<?php echo esc_url( $preview[0] ); ?>" alt="<?php echo esc_attr( $alt_text ); ?>" />
</div>
<?php
}
/**
* Show image select/delete buttons
*
* @param string $name name for value/ID/class
* @param int $id image ID
*
* @since 2.3.0
*/
public function render_buttons( $name, $id = '' ) {
?>
<input type="hidden" class="upload-image-id" name="<?php echo esc_attr( $name ); ?>" value="<?php echo absint( $id ); ?>" />
<button id="<?php echo esc_attr( $name ); ?>" class="upload-image button-secondary">
<?php esc_html_e( 'Select Image', 'easy-digital-downloads' ); ?>
</button>
<button class="delete-image button-secondary"<?php echo empty( $id ) ? 'style="display:none;"' : ''; ?>>
<?php esc_html_e( 'Delete Image', 'easy-digital-downloads' ); ?>
</button>
<?php
}
/**
* Save extra taxonomy fields callback function.
* @param $term_id int the id of the term
*
* @since 2.0
*/
public function save_term_meta( $term_id ) {
if ( ! $this->user_can_save( "{$this->meta_key}_save-settings", "{$this->meta_key}_nonce" ) ) {
return;
}
$input = filter_input( INPUT_POST, $this->meta_key, FILTER_SANITIZE_NUMBER_INT );
if ( $input ) {
update_term_meta( $term_id, $this->meta_key, absint( $input ) );
} else {
delete_term_meta( $term_id, $this->meta_key );
}
}
/**
* Adds a featured image column for download terms.
*
* @param array $columns The array of registered columns.
*/
public function add_column( $columns ) {
$new_columns = $columns;
array_splice( $new_columns, 1 );
$new_columns['featured_image'] = __( 'Image', 'easy-digital-downloads' );
return array_merge( $new_columns, $columns );
}
/**
* Render the featured image column for terms.
*
* @param string $value Blank (because WP).
* @param string $column Column ID.
* @param int $term_id The term ID.
*/
public function manage_taxonomy_column( $value, $column, $term_id ) {
if ( 'featured_image' !== $column ) {
return;
}
$image_id = $this->get_meta( $term_id );
if ( ! $image_id ) {
return;
}
$source = wp_get_attachment_image_src( $image_id, 'thumbnail' );
if ( ! $source ) {
return;
}
$taxonomy = ! empty( $_POST['taxonomy'] ) ? sanitize_text_field( $_POST['taxonomy'] ) : null;
$taxonomy = ! is_null( $taxonomy ) ? $taxonomy : get_current_screen()->taxonomy;
?>
<img
src="<?php echo esc_url( $source[0] ); ?>"
alt="<?php echo esc_attr( get_term( $term_id, $taxonomy )->name ); ?>"
width="60"
/>
<?php
}
/**
* Get the current term meta or option, if it exists.
*
* @param $term_id
*
* @return mixed|void
* @since 2.0
*/
private function get_meta( $term_id ) {
return get_term_meta( $term_id, $this->meta_key, true );
}
/**
* Determines if the user has permission to save the information from the submenu
* page.
*
* @since 2.0
*
* @param string $action The name of the action specified on the submenu page
* @param string $nonce The nonce specified on the submenu page
*
* @return bool True if the user has permission to save; false, otherwise.
*/
private function user_can_save( $action, $nonce ) {
$is_nonce_set = isset( $_POST[ $nonce ] );
$is_valid_nonce = false;
if ( $is_nonce_set ) {
$is_valid_nonce = wp_verify_nonce( $_POST[ $nonce ], $action );
}
return ( $is_nonce_set && $is_valid_nonce );
}
}

View File

@ -0,0 +1,58 @@
<?php
/**
* Query building for EDD terms blocks.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0.1
*/
namespace EDD\Blocks\Terms;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
class Query {
/**
* The block attributes.
*
* @var array
*/
protected $attributes;
public function __construct( $block_attributes ) {
$this->attributes = $block_attributes;
}
/**
* Gets the downloads query parameters from the block attributes.
*
* @since 2.0
* @return array
*/
public function get_query() {
$query = array(
'taxonomy' => $this->attributes['taxonomy'],
'orderby' => $this->attributes['orderby'],
'order' => $this->attributes['order'],
'hide_empty' => false === $this->attributes['show_empty'],
);
// Hide child download categories by default.
if ( 'download_category' === $this->attributes['taxonomy'] ) {
$query['parent'] = 0;
}
/**
* Allow extensions to filter the terms query.
*
* @since 2.0.1
* @param array $query The array of query parameters.
* @param array $this->attributes The block attributes.
*/
return apply_filters( 'edd_blocks_terms_query', $query, $this->attributes );
}
}

View File

@ -0,0 +1,103 @@
<?php
/**
* Functionality for terms blocks and images.
*
* @package edd-blocks
* @copyright 2022 Easy Digital Downloads
* @license GPL2+
* @since 2.0
*/
namespace EDD\Blocks\Terms;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
use EDD\Blocks\Functions;
add_action( 'init', __NAMESPACE__ . '\register' );
/**
* Registers all of the EDD core blocks.
*
* @since 2.0
* @return void
*/
function register() {
$blocks = array(
'terms' => array(
'render_callback' => __NAMESPACE__ . '\terms',
),
);
foreach ( $blocks as $block => $args ) {
register_block_type( EDD_BLOCKS_DIR . 'build/' . $block, $args );
}
}
add_action( 'admin_init', __NAMESPACE__ . '\meta' );
/**
* Adds functionality to set featured images for download terms.
*
* @since 2.0
* @return void
*/
function meta() {
// If the original EDD Blocks are active, defer to that for setting term images.
if ( class_exists( 'EDD_Term_Images' ) ) {
return;
}
require_once EDD_BLOCKS_DIR . 'includes/terms/images.php';
new \EDD\Blocks\Terms\Images();
}
/**
* Renders the terms block.
*
* @since 2.0
* @param array $block_attributes The block attributes.
* @return string
*/
function terms( $block_attributes = array() ) {
// Set up defaults.
$defaults = array(
'thumbnails' => true,
'title' => true,
'description' => true,
'show_empty' => false,
'columns' => 3,
'count' => true,
'orderby' => 'count',
'order' => 'DESC',
'taxonomy' => 'download_category',
'image_size' => 'large',
'image_alignment' => 'center',
'align' => '',
);
$block_attributes = wp_parse_args( $block_attributes, $defaults );
// Taxonomy must be specified.
if ( empty( $block_attributes['taxonomy'] ) ) {
return;
}
require_once EDD_BLOCKS_DIR . 'includes/terms/query.php';
$query = new Query( $block_attributes );
$query_args = $query->get_query();
$query = new \WP_Term_Query( $query_args );
if ( empty( $query->terms ) ) {
return '';
}
// Set up classes.
$classes = array(
'wp-block-edd-terms',
'edd-blocks__terms',
);
$classes = Functions\get_block_classes( $block_attributes, $classes );
ob_start();
include EDD_BLOCKS_DIR . 'views/terms.php';
return ob_get_clean();
}