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,78 @@
<?php
/**
* A Base Backwards Compatibility Class.
*
* @package EDD
* @subpackage Compat
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Compat;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Base class.
*
* @since 3.0
*/
abstract class Base {
/**
* Holds the component for which we are handling back-compat. There is a chance that two methods have the same name
* and need to be dispatched to completely other methods. When a new instance of Back_Compat is created, a component
* can be passed to the constructor which will allow __call() to dispatch to the correct methods.
*
* @since 3.0
* @access protected
* @var string
*/
protected $component;
/**
* Whether or not to show deprecated notices.
*
* @var bool
*/
protected $show_notices;
/**
* Whether or not to show backtrace.
*
* @var bool
*/
protected $show_backtrace;
/**
* Constructor.
*
* @since 3.0
*/
public function __construct() {
$this->hooks();
$this->show_notices = apply_filters( 'edd_show_deprecated_notices', ( defined( 'WP_DEBUG' ) && WP_DEBUG ) );
$this->show_backtrace = apply_filters( 'edd_show_backtrace', ( defined( 'WP_DEBUG' ) && WP_DEBUG ) && ! defined( 'EDD_DOING_TESTS' ) );
}
/**
* Getter for component.
*
* @since 3.0
*
* @return string Component.
*/
public function get_component() {
return $this->component;
}
/**
* Backwards compatibility hooks for component.
*
* @since 3.0
* @access protected
*/
abstract protected function hooks();
}

View File

@ -0,0 +1,303 @@
<?php
/**
* Backwards Compatibility Handler for Customers.
*
* @package EDD
* @subpackage Compat
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Compat;
use EDD\Database\Table;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Customer Class.
*
* @since 3.0
*/
class Customer extends Base {
/**
* Holds the component for which we are handling back-compat. There is a chance that two methods have the same name
* and need to be dispatched to completely other methods. When a new instance of Back_Compat is created, a component
* can be passed to the constructor which will allow __call() to dispatch to the correct methods.
*
* @since 3.0
* @access protected
* @var string
*/
protected $component = 'customer';
/**
* Magic method to handle calls to properties that no longer exist.
*
* @since 3.0
*
* @param string $property Name of the property.
*
* @return mixed
*/
public function __get( $property ) {
switch( $property ) {
case 'table_name' :
global $wpdb;
return $wpdb->edd_customers;
case 'primary_key' :
return 'id';
case 'version' :
$table = edd_get_component_interface( 'customer', 'table' );
return $table instanceof Table ? $table->get_version() : false;
case 'meta_type' :
return 'customer';
case 'date_key' :
return 'date_created';
case 'cache_group' :
return 'customers';
}
return null;
}
/**
* Magic method to handle calls to method that no longer exist.
*
* @since 3.0
*
* @param string $name Name of the method.
* @param array $arguments Enumerated array containing the parameters passed to the $name'ed method.
* @return mixed Dependent on the method being dispatched to.
*/
public function __call( $name, $arguments ) {
switch ( $name ) {
case 'add':
case 'insert':
return edd_add_customer( $arguments[0] );
case 'update':
return edd_update_customer( $arguments[0], $arguments[1] );
case 'delete':
if ( ! is_bool( $arguments[0] ) ) {
return false;
}
$column = is_email( $arguments[0] ) ? 'email' : 'id';
$customer = edd_get_customer_by( $column, $arguments[0] );
edd_delete_customer( $customer->id );
break;
case 'exists':
return (bool) edd_get_customer_by( 'email', $arguments[0] );
case 'get_customer_by':
return edd_get_customer_by( $arguments[0], $arguments[1] );
case 'get_customers':
return edd_get_customers( $arguments[0] );
case 'count':
return edd_count_customers();
case 'get_column':
return edd_get_customer_by( $arguments[0], $arguments[1] );
case 'attach_payment':
/** @var $customer \EDD_Customer */
$customer = edd_get_customer( $arguments[0] );
if ( ! $customer ) {
return false;
}
return $customer->attach_payment( $arguments[1], false );
case 'remove_payment':
/** @var $customer \EDD_Customer */
$customer = edd_get_customer( $arguments[0] );
if ( ! $customer ) {
return false;
}
return $customer->remove_payment( $arguments[1], false );
case 'increment_stats':
/** @var $customer \EDD_Customer */
$customer = edd_get_customer( $arguments[0] );
if ( ! $customer ) {
return false;
}
$increased_count = $customer->increase_purchase_count();
$increased_value = $customer->increase_value( $arguments[1] );
return ( $increased_count && $increased_value )
? true
: false;
case 'decrement_stats':
/** @var $customer \EDD_Customer */
$customer = edd_get_customer( $arguments[0] );
if ( ! $customer ) {
return false;
}
$decreased_count = $customer->decrease_purchase_count();
$decreased_value = $customer->decrease_value( $arguments[1] );
return ( $decreased_count && $decreased_value )
? true
: false;
}
}
/**
* Backwards compatibility hooks for customers.
*
* @since 3.0
* @access protected
*/
protected function hooks() {
/** Filters **********************************************************/
add_filter( 'get_user_metadata', array( $this, 'get_user_meta' ), 99, 4 );
add_filter( 'update_user_metadata', array( $this, 'update_user_meta' ), 99, 5 );
add_filter( 'add_user_metadata', array( $this, 'update_user_meta' ), 99, 5 );
}
/**
* Backwards compatibility filters for get_user_meta() calls on customers.
*
* @since 3.0
*
* @param mixed $value The value get_post_meta would return if we don't filter.
* @param int $object_id The object ID post meta was requested for.
* @param string $meta_key The meta key requested.
* @param bool $single If a single value or an array of the value is requested.
*
* @return mixed The value to return.
*/
public function get_user_meta( $value, $object_id, $meta_key, $single ) {
if ( 'get_user_metadata' !== current_filter() ) {
$message = __( 'This function is not meant to be called directly. It is only here for backwards compatibility purposes.', 'easy-digital-downloads' );
_doing_it_wrong( __FUNCTION__, esc_html( $message ), 'EDD 3.0' );
}
if ( '_edd_user_address' !== $meta_key ) {
return $value;
}
$value = edd_get_customer_address( $object_id );
if ( $this->show_notices ) {
_doing_it_wrong( 'get_user_meta()', 'User addresses being stored in meta have been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_get_customer_address()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
return array( $value );
}
/**
* Listen for calls to update_user_meta() for customers and see if we need to filter them.
*
* This is here for backwards compatibility purposes with the migration to custom tables in EDD 3.0.
*
* @since 3.0
*
* @param null|bool $check Whether to allow updating metadata for the given type.
* @param int $object_id Object ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value. Must be serializable if non-scalar.
* @param mixed $prev_value Optional. If specified, only update existing metadata entries with the specified value.
* Otherwise, update all entries.
*
* @return mixed Returns 'null' if no action should be taken and WordPress core can continue, or non-null to avoid usermeta.
*/
public function update_user_meta( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
if ( '_edd_user_address' !== $meta_key ) {
return $check;
}
// Fetch saved primary address.
$addresses = edd_get_customer_addresses(
array(
'number' => 1,
'is_primary' => true,
'customer_id' => $object_id,
)
);
// Defaults.
$defaults = array(
'line1' => '',
'line2' => '',
'city' => '',
'state' => '',
'country' => '',
'zip' => '',
);
$address = wp_parse_args( (array) $meta_value, $defaults );
if ( is_array( $addresses ) && ! empty( $addresses[0] ) ) {
$customer_address = $addresses[0];
edd_update_customer_address(
$customer_address->id,
array(
'address' => $address['line1'],
'address2' => $address['line2'],
'city' => $address['city'],
'region' => $address['state'],
'postal_code' => $address['zip'],
'country' => $address['country'],
)
);
} else {
$customer = edd_get_customer_by( 'user_id', absint( $object_id ) );
if ( $customer ) {
edd_add_customer_address(
array(
'customer_id' => $customer->id,
'address' => $address['line1'],
'address2' => $address['line2'],
'city' => $address['city'],
'region' => $address['state'],
'postal_code' => $address['zip'],
'country' => $address['country'],
'is_primary' => true,
)
);
}
}
if ( $this->show_notices ) {
_doing_it_wrong( 'add_user_meta()/update_user_meta()', 'User addresses being stored in meta have been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_add_customer_address()/edd_update_customer_address()()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
return $check;
}
}

View File

@ -0,0 +1,100 @@
<?php
/**
* Backwards Compatibility Handler for Customer Meta.
*
* @package EDD
* @subpackage Compat
* @copyright Copyright (c) 2021, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Compat;
use EDD\Database\Table;
class CustomerMeta extends Base {
protected $component = 'customermeta';
/**
* Magic method to handle calls to properties that no longer exist.
*
* @since 3.0
*
* @param string $property Name of the property.
*
* @return mixed
*/
public function __get( $property ) {
switch( $property ) {
case 'table_name' :
global $wpdb;
return $wpdb->edd_customermeta;
case 'primary_key' :
return 'meta_id';
case 'version' :
$table = edd_get_component_interface( 'customer', 'meta' );
return $table instanceof Table ? $table->get_version() : false;
}
return null;
}
/**
* Magic method to handle calls to method that no longer exist.
*
* @since 3.0
*
* @param string $name Name of the method.
* @param array $arguments Enumerated array containing the parameters passed to the $name'ed method.
* @return mixed Dependent on the method being dispatched to.
*/
public function __call( $name, $arguments ) {
switch ( $name ) {
case 'get_meta' :
return edd_get_customer_meta(
isset( $arguments[0] ) ? $arguments[0] : 0,
isset( $arguments[1] ) ? $arguments[1] : '',
isset( $arguments[2] ) ? $arguments[2] : false
);
case 'add_meta' :
return edd_add_customer_meta(
isset( $arguments[0] ) ? $arguments[0] : 0,
isset( $arguments[1] ) ? $arguments[1] : '',
isset( $arguments[2] ) ? $arguments[2] : false,
isset( $arguments[3] ) ? $arguments[3] : false
);
case 'update_meta' :
return edd_update_customer_meta(
isset( $arguments[0] ) ? $arguments[0] : 0,
isset( $arguments[1] ) ? $arguments[1] : '',
isset( $arguments[2] ) ? $arguments[2] : false,
isset( $arguments[3] ) ? $arguments[3] : ''
);
case 'delete_meta' :
return edd_delete_customer_meta(
isset( $arguments[0] ) ? $arguments[0] : 0,
isset( $arguments[1] ) ? $arguments[1] : '',
isset( $arguments[2] ) ? $arguments[2] : ''
);
}
return null;
}
/**
* Backwards compatibility hooks for customer meta.
*
* @since 3.0
* @access protected
*/
protected function hooks() {
// No hooks.
}
}

View File

@ -0,0 +1,81 @@
<?php
/**
* Discount Query Class.
*
* @package EDD
* @subpackage Database\Queries
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Compat;
use EDD\Database\Queries as Queries;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Class used for querying discounts.
*
* @since 3.0
*
* @see \EDD\Database\Queries\Adjustment::__construct() for accepted arguments.
*/
class Discount_Query extends Queries\Adjustment {
/**
* Callback function for turning IDs into objects
*
* @since 3.0
* @access protected
* @var mixed
*/
protected $item_shape = 'EDD_Discount';
/**
* Swap out types in a query.
*
* @since 3.0
*
* @param array $query Array of query arguments
* @return array
*/
public function query( $query = array() ) {
return parent::query( $this->swap_types( $query ) );
}
/**
* Swap out types in an item.
*
* @since 3.0
*
* @param array $item Array of item arguments
* @return array
*/
public function filter_item( $item = array() ) {
return parent::filter_item( $this->swap_types( $item ) );
}
/**
* Swap out the type arguments.
*
* @since 3.0
*
* @param array $args
* @return array
*/
private function swap_types( $args = array() ) {
// Switch `type` to `amount_type`
if ( empty( $args['amount_type'] ) && ! empty( $args['type'] ) ) {
$args['amount_type'] = $args['type'];
}
// Force `type` to `discount`
$args['type'] = 'discount';
// Return swapped arguments
return $args;
}
}

View File

@ -0,0 +1,546 @@
<?php
/**
* Backwards Compatibility Handler for Discounts.
*
* @package EDD
* @subpackage Compat
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Compat;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Customer Class.
*
* @since 3.0
*/
class Discount extends Base {
/**
* Holds the component for which we are handling back-compat. There is a chance that two methods have the same name
* and need to be dispatched to completely other methods. When a new instance of Back_Compat is created, a component
* can be passed to the constructor which will allow __call() to dispatch to the correct methods.
*
* @since 3.0
* @access protected
* @var string
*/
protected $component = 'discount';
/**
* Backwards compatibility hooks for discounts.
*
* @since 3.0
* @access protected
*/
protected function hooks() {
/** Actions **********************************************************/
add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), 99, 1 );
/** Filters **********************************************************/
add_filter( 'query', array( $this, 'wp_count_posts' ), 10, 1 );
add_filter( 'get_post_metadata', array( $this, 'get_post_metadata' ), 99, 4 );
add_filter( 'update_post_metadata', array( $this, 'update_post_metadata' ), 99, 5 );
add_filter( 'add_post_metadata', array( $this, 'update_post_metadata' ), 99, 5 );
add_filter( 'posts_results', array( $this, 'posts_results' ), 10, 2 );
add_filter( 'posts_request', array( $this, 'posts_request' ), 10, 2 );
}
/**
* Add a message for anyone to trying to get payments via get_post/get_posts/WP_Query.
* Force filters to run for all queries that have `edd_discount` as the post type.
*
* This is here for backwards compatibility purposes with the migration to custom tables in EDD 3.0.
*
* @since 3.0
*
* @param \WP_Query $query
*/
public function pre_get_posts( $query ) {
global $wpdb;
// Bail if not a discount
if ( 'edd_discount' !== $query->get( 'post_type' ) ) {
return;
}
// Force filters to run
$query->set( 'suppress_filters', false );
// Setup doing-it-wrong message
$message = sprintf(
__( 'As of Easy Digital Downloads 3.0, discounts no longer exist in the %1$s table. They have been migrated to %2$s. Discounts should be accessed using %3$s, %4$s or instantiating a new instance of %5$s. See %6$s for more information.', 'easy-digital-downloads' ),
'<code>' . $wpdb->posts . '</code>',
'<code>' . edd_get_component_interface( 'adjustment', 'table' )->table_name . '</code>',
'<code>edd_get_discounts()</code>',
'<code>edd_get_discount()</code>',
'<code>EDD_Discount</code>',
'https://easydigitaldownloads.com/development/'
);
_doing_it_wrong( 'get_posts()/get_post()', $message, '3.0' );
}
/**
* Backwards compatibility layer for wp_count_posts().
*
* @since 3.0
*
* @param string $query SQL query.
* @return string $request Rewritten SQL query.
*/
public function wp_count_posts( $query ) {
global $wpdb;
$expected = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = 'edd_discount' GROUP BY post_status";
if ( $expected === $query ) {
$query = "SELECT status AS post_status, COUNT( * ) AS num_posts FROM {$wpdb->edd_adjustments} WHERE type = 'discount' GROUP BY post_status";
}
return $query;
}
/**
* Fill the returned WP_Post objects with the data from the discounts table.
*
* @since 3.0
*
* @param array $posts Posts returned from the SQL query.
* @param \WP_Query $query Instance of WP_Query.
*
* @return array New WP_Post objects.
*/
public function posts_results( $posts, $query ) {
if ( 'posts_results' !== current_filter() ) {
$message = __( 'This function is not meant to be called directly. It is only here for backwards compatibility purposes.', 'easy-digital-downloads' );
_doing_it_wrong( __FUNCTION__, esc_html( $message ), 'EDD 3.0' );
}
if ( 'edd_discount' === $query->get( 'post_type' ) ) {
$new_posts = array();
foreach ( $posts as $post ) {
$discount = edd_get_discount( $post->id );
$object_vars = array(
'ID' => $discount->id,
'post_title' => $discount->name,
'post_status' => $discount->status,
'post_type' => 'edd_discount',
'post_date' => EDD()->utils->date( $discount->date_created, null, true )->toDateTimeString(),
'post_date_gmt' => $discount->date_created,
'post_modified' => EDD()->utils->date( $discount->date_modified, null, true )->toDateTimeString(),
'post_modified_gmt' => $discount->date_created,
);
foreach ( $object_vars as $object_var => $value ) {
$post->{$object_var} = $value;
}
$post = new \WP_Post( $post );
$new_posts[] = $post;
}
return $new_posts;
}
return $posts;
}
/**
* Hijack the SQL query and rewrite it to fetch data from the discounts table.
*
* @since 3.0
*
* @param string $request SQL query.
* @param \WP_Query $query Instance of WP_Query.
*
* @return string $request Rewritten SQL query.
*/
public function posts_request( $request, $query ) {
global $wpdb;
if ( 'posts_request' !== current_filter() ) {
$message = __( 'This function is not meant to be called directly. It is only here for backwards compatibility purposes.', 'easy-digital-downloads' );
_doing_it_wrong( __FUNCTION__, esc_html( $message ), '3.0' );
}
if ( 'edd_discount' === $query->get( 'post_type' ) ) {
$defaults = array(
'number' => 30,
'status' => array( 'active', 'inactive', 'expired' ),
'order' => 'DESC',
'orderby' => 'date_created',
);
$args = array(
'number' => $query->get( 'posts_per_page' ),
'status' => $query->get( 'post_status', array( 'active', 'inactive' ) ),
);
$orderby = $query->get( 'orderby', false );
if ( $orderby ) {
switch ( $orderby ) {
case 'none':
case 'ID':
case 'author':
case 'post__in':
case 'type':
case 'post_type':
$args['orderby'] = 'id';
break;
case 'title':
$args['orderby'] = 'name';
break;
case 'date':
case 'post_date':
case 'modified':
case 'post_modified':
$args['orderby'] = 'date_created';
break;
default:
$args['orderby'] = 'id';
break;
}
}
$offset = $query->get( 'offset', false );
if ( $offset ) {
$args['offset'] = absint( $offset );
} else {
$args['offset'] = 0;
}
if ( 'any' === $args['status'] ) {
$args['status'] = $defaults['status'];
}
$args = wp_parse_args( $args, $defaults );
if ( array_key_exists( 'number', $args ) ) {
$args['number'] = absint( $args['number'] );
}
$table_name = edd_get_component_interface( 'adjustment', 'table' )->table_name;
$meta_query = $query->get( 'meta_query' );
$clauses = array();
$sql_where = "WHERE type = 'discount'";
$meta_key = $query->get( 'meta_key', false );
$meta_value = $query->get( 'meta_value', false );
$columns = wp_list_pluck( edd_get_component_interface( 'adjustment', 'schema' )->columns, 'name' );
// 'meta_key' and 'meta_value' passed as arguments
if ( $meta_key && $meta_value ) {
/**
* Check that the key exists as a column in the table.
* Note: there is no backwards compatibility support for product requirements and excluded
* products as these would be serialized under the old schema.
*/
if ( in_array( $meta_key, $columns, true ) ) {
$sql_where .= ' ' . $wpdb->prepare( "{$meta_key} = %s", $meta_value );
}
}
if ( ! empty( $meta_query ) ) {
foreach ( $meta_query as $key => $query ) {
$relation = 'AND'; // Default relation
if ( is_string( $query ) && 'relation' === $key ) {
$relation = $query;
}
if ( is_array( $query ) ) {
if ( array_key_exists( 'key', $query ) ) {
$query['key'] = str_replace( '_edd_discount_', '', $query['key'] );
/**
* Check that the key exists as a column in the table.
* Note: there is no backwards compatibility support for product requirements and excluded
* products as these would be serialized under the old schema.
*/
if ( in_array( $query['key'], $columns, true ) && array_key_exists( 'value', $query ) ) {
$meta_compare = ! empty( $query['compare'] ) ? $query['compare'] : '=';
$meta_compare = strtoupper( $meta_compare );
$meta_value = $query['value'];
$where = null;
switch ( $meta_compare ) {
case 'IN':
case 'NOT IN':
$meta_compare_string = '(' . substr( str_repeat( ',%s', count( $meta_value ) ), 1 ) . ')';
$where = $wpdb->prepare( $meta_compare_string, $meta_value );
break;
case 'BETWEEN':
case 'NOT BETWEEN':
$meta_value = array_slice( $meta_value, 0, 2 );
$where = $wpdb->prepare( '%1$s AND %1$s', $meta_value );
break;
case 'LIKE':
case 'NOT LIKE':
$meta_value = '%' . $wpdb->esc_like( $meta_value ) . '%';
$where = $wpdb->prepare( '%s', $meta_value );
break;
// EXISTS with a value is interpreted as '='.
case 'EXISTS':
$where = $wpdb->prepare( '%s', $meta_value );
break;
// 'value' is ignored for NOT EXISTS.
case 'NOT EXISTS':
$where = $query['key'] . ' IS NULL';
break;
default:
$where = $wpdb->prepare( '%s', $meta_value );
break;
}
if ( ! is_null( $where ) ) {
$clauses['where'][] = $query['key'] . ' ' . $meta_compare . ' ' . $where;
}
}
}
if ( ! empty( $clauses['where'] ) && is_array( $clauses['where'] ) ) {
$sql_where .= ' AND ( ' . implode( ' ' . $relation . ' ', $clauses['where'] ) . ' )';
}
}
}
}
$request = "SELECT id FROM {$table_name} {$sql_where} ORDER BY {$args['orderby']} {$args['order']} LIMIT {$args['offset']}, {$args['number']};";
}
return $request;
}
/**
* Backwards compatibility filters for get_post_meta() calls on discounts.
*
* @since 3.0
*
* @param mixed $value The value get_post_meta would return if we don't filter.
* @param int $object_id The object ID post meta was requested for.
* @param string $meta_key The meta key requested.
* @param bool $single If a single value or an array of the value is requested.
*
* @return mixed The value to return.
*/
public function get_post_metadata( $value, $object_id, $meta_key, $single ) {
$meta_keys = apply_filters( 'edd_post_meta_discount_backwards_compat_keys', array(
'_edd_discount_status',
'_edd_discount_amount',
'_edd_discount_uses',
'_edd_discount_name',
'_edd_discount_code',
'_edd_discount_expiration',
'_edd_discount_start',
'_edd_discount_is_single_use',
'_edd_discount_is_not_global',
'_edd_discount_product_condition',
'_edd_discount_min_price',
'_edd_discount_max_uses'
) );
// Bail early of not a back-compat key
if ( ! in_array( $meta_key, $meta_keys, true ) ) {
return $value;
}
// Bail if discount does not exist
$discount = edd_get_discount( $object_id );
if ( empty( $discount->id ) ) {
return $value;
}
switch ( $meta_key ) {
case '_edd_discount_name':
case '_edd_discount_status':
case '_edd_discount_amount':
case '_edd_discount_uses':
case '_edd_discount_code':
case '_edd_discount_expiration':
case '_edd_discount_start':
case '_edd_discount_product_condition':
case '_edd_discount_min_price':
case '_edd_discount_max_uses':
$key = str_replace( '_edd_discount_', '', $meta_key );
$value = $discount->{$key};
if ( $this->show_notices ) {
_doing_it_wrong( 'get_post_meta()', 'All discount postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_get_adjustment_meta()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
break;
case '_edd_discount_is_single_use':
$value = $discount->get_once_per_customer();
if ( $this->show_notices ) {
_doing_it_wrong( 'get_post_meta()', 'All discount postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_get_adjustment_meta()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
break;
case '_edd_discount_is_not_global':
$value = $discount->get_scope();
if ( $this->show_notices ) {
_doing_it_wrong( 'get_post_meta()', 'All discount postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_get_adjustment_meta()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
break;
default:
/*
* Developers can hook in here with add_filter( 'edd_get_post_meta_discount_backwards_compat-meta_key... in order to
* Filter their own meta values for backwards compatibility calls to get_post_meta instead of EDD_Discount::get_meta
*/
$value = apply_filters( 'edd_get_post_meta_discount_backwards_compat-' . $meta_key, $value, $object_id );
break;
}
return $value;
}
/**
* Backwards compatibility filters for add/update_post_meta() calls on discounts.
*
* @since 3.0
*
* @param mixed $check Comes in 'null' but if returned not null, WordPress Core will not interact with the postmeta table.
* @param int $object_id The object ID post meta was requested for.
* @param string $meta_key The meta key requested.
* @param mixed $meta_value The value get_post_meta would return if we don't filter.
* @param mixed $prev_value The previous value of the meta
*
* @return mixed Returns 'null' if no action should be taken and WordPress core can continue, or non-null to avoid postmeta.
*/
public function update_post_metadata( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
$meta_keys = apply_filters( 'edd_update_post_meta_discount_backwards_compat_keys', array(
'_edd_discount_status',
'_edd_discount_amount',
'_edd_discount_uses',
'_edd_discount_name',
'_edd_discount_code',
'_edd_discount_expiration',
'_edd_discount_start',
'_edd_discount_is_single_use',
'_edd_discount_is_not_global',
'_edd_discount_product_condition',
'_edd_discount_min_price',
'_edd_discount_max_uses'
) );
// Bail early of not a back-compat key
if ( ! in_array( $meta_key, $meta_keys, true ) ) {
return $check;
}
// Bail if discount does not exist
$discount = edd_get_discount( $object_id );
if ( empty( $discount->id ) ) {
return $check;
}
switch ( $meta_key ) {
case '_edd_discount_name':
case '_edd_discount_status':
case '_edd_discount_amount':
case '_edd_discount_uses':
case '_edd_discount_code':
case '_edd_discount_expiration':
case '_edd_discount_start':
case '_edd_discount_product_condition':
case '_edd_discount_min_price':
case '_edd_discount_max_uses':
$key = str_replace( '_edd_discount_', '', $meta_key );
$discount->{$key} = $meta_value;
$check = $discount->save();
if ( $this->show_notices ) {
_doing_it_wrong( 'add_post_meta()/update_post_meta()', 'All discount postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_add_adjustment_meta()/edd_update_adjustment_meta()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
break;
case '_edd_discount_is_single_use':
$discount->once_per_customer = $meta_value;
$check = $discount->save();
// Since the old discounts data was simply stored in a single post meta entry, just don't let it be added.
if ( $this->show_notices ) {
_doing_it_wrong( 'add_post_meta()/update_post_meta()', 'All discount postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_add_adjustment_meta()/edd_update_adjustment_meta()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
break;
case '_edd_discount_is_not_global':
$discount->scope = $meta_value;
$check = $discount->save();
// Since the old discounts data was simply stored in a single post meta entry, just don't let it be added.
if ( $this->show_notices ) {
_doing_it_wrong( 'add_post_meta()/update_post_meta()', 'All discount postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_add_adjustment_meta()/edd_update_adjustment_meta()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
break;
default:
/*
* Developers can hook in here with add_filter( 'edd_get_post_meta_discount_backwards_compat-meta_key... in order to
* Filter their own meta values for backwards compatibility calls to get_post_meta instead of EDD_Discount::get_meta
*/
$check = apply_filters( 'edd_update_post_meta_discount_backwards_compat-' . $meta_key, $check, $object_id, $meta_value, $prev_value );
break;
}
return $check;
}
}

View File

@ -0,0 +1,972 @@
<?php
/**
* This class is used to build an EDD_Payment object
* from a WP_Post object.
*
* This is intended for internal use only, to ensure that existing
* payments can be accessed before the migration is complete.
*
* @package EDD
* @subpackage Compat
* @copyright Copyright (c) 2022, Easy Digital Downloads
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* EDD_Payment_Compat Class
*
* @since 3.0
*
* @property int $ID
* @property string $number
* @property string $mode
* @property string $key
* @property float $total
* @property float $subtotal
* @property float $tax
* @property float $discounted_amount
* @property float $tax_rate
* @property array $fees
* @property float $fees_total
* @property string $discounts
* @property string $completed_date
* @property string $status
* @property int $customer_id
* @property int $user_id
* @property string $first_name
* @property string $last_name
* @property string $email
* @property array $user_info
* @property array $payment_meta
* @property array $address
* @property string $transaction_id
* @property array $downloads
* @property string $ip
* @property string $gateway
* @property string $currency
* @property array $cart_details
* @property bool $has_unlimited_downloads
* @property int $parent_payment
*/
class EDD_Payment_Compat {
/**
* The Payment ID
*
* @since 3.0
* @var integer
*/
public $ID = 0;
/**
* The Payment number (for use with sequential payments)
*
* @since 3.0
* @var string
*/
public $number = '';
/**
* The Gateway mode the payment was made in
*
* @since 3.0
* @var string
*/
public $mode = 'live';
/**
* The Unique Payment Key
*
* @since 3.0
* @var string
*/
public $key = '';
/**
* The total amount the payment is for
* Includes items, taxes, fees, and discounts
*
* @since 3.0
* @var float
*/
public $total = 0.00;
/**
* The Subtotal fo the payment before taxes
*
* @since 3.0
* @var float
*/
public $subtotal = 0;
/**
* The amount of tax for this payment
*
* @since 3.0
* @var float
*/
public $tax = 0;
/**
* The amount the payment has been discounted through discount codes
*
* @since 3.0
* @var int
*/
public $discounted_amount = 0;
/**
* The tax rate charged on this payment
*
* @since 3.0
* @var float
*/
public $tax_rate = '';
/**
* Array of global fees for this payment
*
* @since 3.0
* @var array
*/
public $fees = array();
/**
* The sum of the fee amounts
*
* @since 3.0
* @var float
*/
public $fees_total = 0;
/**
* Any discounts applied to the payment
*
* @since 3.0
* @var string
*/
public $discounts = 'none';
/**
* The date the payment was created
*
* @since 3.0
* @var string
*/
public $date = '';
/**
* The date the payment was marked as 'complete'
*
* @since 3.0
* @var string
*/
public $completed_date = '';
/**
* The status of the payment
*
* @since 3.0
* @var string
*/
public $status = 'pending';
/**
* The customer ID that made the payment
*
* @since 3.0
* @var integer
*/
public $customer_id = null;
/**
* The User ID (if logged in) that made the payment
*
* @since 3.0
* @var integer
*/
public $user_id = 0;
/**
* The first name of the payee
*
* @since 3.0
* @var string
*/
public $first_name = '';
/**
* The last name of the payee
*
* @since 3.0
* @var string
*/
public $last_name = '';
/**
* The email used for the payment
*
* @since 3.0
* @var string
*/
public $email = '';
/**
* Legacy (not to be accessed) array of user information
*
* @since 3.0
* @var array
*/
public $user_info = array();
/**
* Legacy (not to be accessed) payment meta array
*
* @since 3.0
* @var array
*/
public $payment_meta = array();
/**
* The physical address used for the payment if provided
*
* @since 3.0
* @var array
*/
public $address = array();
/**
* The transaction ID returned by the gateway
*
* @since 3.0
* @var string
*/
public $transaction_id = '';
/**
* Array of downloads for this payment
*
* @since 3.0
* @var array
*/
public $downloads = array();
/**
* IP Address payment was made from
*
* @since 3.0
* @var string
*/
public $ip = '';
/**
* The gateway used to process the payment
*
* @since 3.0
* @var string
*/
public $gateway = '';
/**
* The the payment was made with
*
* @since 3.0
* @var string
*/
public $currency = '';
/**
* The cart details array
*
* @since 3.0
* @var array
*/
public $cart_details = array();
/**
* Allows the files for this payment to be downloaded unlimited times (when download limits are enabled)
*
* @since 3.0
* @var boolean
*/
public $has_unlimited_downloads = false;
/**
* Order object.
*
* @since 3.0
* @var EDD\Orders\Order
*/
public $order;
/**
* The parent payment (if applicable)
*
* @since 3.0
* @var integer
*/
public $parent_payment = 0;
/**
* Post object.
*
* @since 3.0
* @var WP_Post
*/
private $payment;
/**
* Setup the EDD Payments class
*
* @since 3.0
* @param int $payment_id A given payment
* @return mixed void|false
*/
public function __construct( $payment_id = false ) {
if ( empty( $payment_id ) ) {
return false;
}
$this->ID = absint( $payment_id );
$this->payment = get_post( $this->ID );
if ( ! $this->payment instanceof WP_Post ) {
return false;
}
$this->setup();
}
/**
* Sets up the payment object.
*
* @since 3.0
* @return void
*/
private function setup() {
$this->payment_meta = $this->get_meta();
$this->cart_details = $this->setup_cart_details();
$this->status = $this->setup_status();
$this->completed_date = $this->setup_completed_date();
$this->mode = $this->setup_mode();
$this->total = $this->setup_total();
$this->tax = $this->setup_tax();
$this->tax_rate = $this->setup_tax_rate();
$this->fees_total = $this->setup_fees_total();
$this->subtotal = $this->setup_subtotal();
$this->discounts = $this->setup_discounts();
$this->currency = $this->setup_currency();
$this->fees = $this->setup_fees();
$this->gateway = $this->setup_gateway();
$this->transaction_id = $this->setup_transaction_id();
$this->ip = $this->setup_ip();
$this->customer_id = $this->setup_customer_id();
$this->user_id = $this->setup_user_id();
$this->email = $this->setup_email();
$this->user_info = $this->setup_user_info();
$this->address = $this->setup_address();
$this->key = $this->setup_payment_key();
$this->number = $this->setup_payment_number();
$this->downloads = $this->setup_downloads();
$this->has_unlimited_downloads = $this->setup_has_unlimited();
$this->order = $this->_shim_order();
}
/**
* Get a post meta item for the payment
*
* @since 3.0
* @param string $meta_key The Meta Key
* @param boolean $single Return single item or array
* @return mixed The value from the post meta
*/
private function get_meta( $meta_key = '_edd_payment_meta', $single = true ) {
$meta = get_post_meta( $this->ID, $meta_key, $single );
if ( '_edd_payment_meta' === $meta_key ) {
if ( empty( $meta ) ) {
$meta = array();
}
// #5228 Fix possible data issue introduced in 2.6.12
if ( is_array( $meta ) && isset( $meta[0] ) ) {
$bad_meta = $meta[0];
unset( $meta[0] );
if ( is_array( $bad_meta ) ) {
$meta = array_merge( $meta, $bad_meta );
}
update_post_meta( $this->ID, '_edd_payment_meta', $meta );
}
// Payment meta was simplified in EDD v1.5, so these are here for backwards compatibility
if ( empty( $meta['key'] ) ) {
$meta['key'] = $this->setup_payment_key();
}
if ( empty( $meta['email'] ) ) {
$meta['email'] = $this->setup_email();
}
if ( empty( $meta['date'] ) ) {
$meta['date'] = get_post_field( 'post_date', $this->ID );
}
}
$meta = apply_filters( 'edd_get_payment_meta_' . $meta_key, $meta, $this->ID );
if ( is_serialized( $meta ) ) {
preg_match( '/[oO]\s*:\s*\d+\s*:\s*"\s*(?!(?i)(stdClass))/', $meta, $matches );
if ( ! empty( $matches ) ) {
$meta = array();
}
}
return apply_filters( 'edd_get_payment_meta', $meta, $this->ID, $meta_key );
}
/**
* Setup the payment completed date
*
* @since 3.0
* @return string The date the payment was completed
*/
private function setup_completed_date() {
if ( in_array( $this->payment->post_status, array( 'pending', 'preapproved', 'processing' ), true ) ) {
return false; // This payment was never completed
}
$date = $this->get_meta( '_edd_completed_date', true );
// phpcs:ignore WordPress.PHP.DisallowShortTernary
return $date ?: $this->payment->date;
}
/**
* Setup the payment mode
*
* @since 3.0
* @return string The payment mode
*/
private function setup_mode() {
return $this->get_meta( '_edd_payment_mode' );
}
/**
* Setup the payment total
*
* @since 3.0
* @return float The payment total
*/
private function setup_total() {
$amount = $this->get_meta( '_edd_payment_total', true );
if ( empty( $amount ) && '0.00' != $amount ) {
$meta = $this->get_meta( '_edd_payment_meta', true );
$meta = maybe_unserialize( $meta );
if ( isset( $meta['amount'] ) ) {
$amount = $meta['amount'];
}
}
return $amount;
}
/**
* Setup the payment tax
*
* @since 3.0
* @return float The tax for the payment
*/
private function setup_tax() {
$tax = $this->get_meta( '_edd_payment_tax', true );
// We don't have tax as its own meta and no meta was passed
if ( '' === $tax ) {
$tax = isset( $this->payment_meta['tax'] ) ? $this->payment_meta['tax'] : 0;
}
return $tax;
}
/**
* Setup the payment tax rate
*
* @since 3.0
* @return float The tax rate for the payment
*/
private function setup_tax_rate() {
return $this->get_meta( '_edd_payment_tax_rate', true );
}
/**
* Setup the payment fees
*
* @since 3.0
* @return float The fees total for the payment
*/
private function setup_fees_total() {
$fees_total = (float) 0.00;
$payment_fees = isset( $this->payment_meta['fees'] ) ? $this->payment_meta['fees'] : array();
if ( ! empty( $payment_fees ) ) {
foreach ( $payment_fees as $fee ) {
$fees_total += (float) $fee['amount'];
}
}
return $fees_total;
}
/**
* Setup the payment subtotal
*
* @since 3.0
* @return float The subtotal of the payment
*/
private function setup_subtotal() {
$subtotal = 0;
$cart_details = $this->cart_details;
if ( is_array( $cart_details ) ) {
foreach ( $cart_details as $item ) {
if ( isset( $item['subtotal'] ) ) {
$subtotal += $item['subtotal'];
}
}
} else {
$subtotal = $this->total;
$tax = edd_use_taxes() ? $this->tax : 0;
$subtotal -= $tax;
}
return $subtotal;
}
/**
* Setup the payments discount codes
*
* @since 3.0
* @return array Array of discount codes on this payment
*/
private function setup_discounts() {
return ! empty( $this->payment_meta['user_info']['discount'] ) ? $this->payment_meta['user_info']['discount'] : array();
}
/**
* Setup the currency code
*
* @since 3.0
* @return string The currency for the payment
*/
private function setup_currency() {
return isset( $this->payment_meta['currency'] ) ? $this->payment_meta['currency'] : apply_filters( 'edd_payment_currency_default', edd_get_currency(), $this );
}
/**
* Setup any fees associated with the payment
*
* @since 3.0
* @return array The Fees
*/
private function setup_fees() {
return isset( $this->payment_meta['fees'] ) ? $this->payment_meta['fees'] : array();
}
/**
* Setup the gateway used for the payment
*
* @since 3.0
* @return string The gateway
*/
private function setup_gateway() {
return $this->get_meta( '_edd_payment_gateway', true );
}
/**
* Setup the transaction ID
*
* @since 3.0
* @return string The transaction ID for the payment
*/
private function setup_transaction_id() {
$transaction_id = $this->get_meta( '_edd_payment_transaction_id', true );
if ( empty( $transaction_id ) || (int) $transaction_id === (int) $this->ID ) {
$gateway = $this->gateway;
$transaction_id = apply_filters( 'edd_get_payment_transaction_id-' . $gateway, $this->ID );
}
return $transaction_id;
}
/**
* Setup the IP Address for the payment
*
* @since 3.0
* @return string The IP address for the payment
*/
private function setup_ip() {
return $this->get_meta( '_edd_payment_user_ip', true );
}
/**
* Setup the customer ID
*
* @since 3.0
* @return int The Customer ID
*/
private function setup_customer_id() {
return $this->get_meta( '_edd_payment_customer_id', true );
}
/**
* Setup the User ID associated with the purchase
*
* @since 3.0
* @return int The User ID
*/
private function setup_user_id() {
$user_id = $this->get_meta( '_edd_payment_user_id', true );
$customer = new EDD_Customer( $this->customer_id );
// Make sure it exists, and that it matches that of the associated customer record
if ( ! empty( $customer->user_id ) && ( empty( $user_id ) || (int) $user_id !== (int) $customer->user_id ) ) {
$user_id = $customer->user_id;
// Backfill the user ID, or reset it to be correct in the event of data corruption
update_post_meta( $this->ID, '_edd_payment_user_id', $user_id );
}
return $user_id;
}
/**
* Setup the email address for the purchase
*
* @since 3.0
* @return string The email address for the payment
*/
private function setup_email() {
$email = $this->get_meta( '_edd_payment_user_email', true );
if ( empty( $email ) ) {
$email = EDD()->customers->get_column( 'email', $this->customer_id );
}
return $email;
}
/**
* Setup the user info
*
* @since 3.0
* @return array The user info associated with the payment
*/
private function setup_user_info() {
$defaults = array(
'first_name' => $this->first_name,
'last_name' => $this->last_name,
'discount' => $this->discounts,
);
$user_info = isset( $this->payment_meta['user_info'] ) ? $this->payment_meta['user_info'] : array();
if ( is_serialized( $user_info ) ) {
preg_match( '/[oO]\s*:\s*\d+\s*:\s*"\s*(?!(?i)(stdClass))/', $user_info, $matches );
if ( ! empty( $matches ) ) {
$user_info = array();
}
}
// As per Github issue #4248, we need to run maybe_unserialize here still.
$user_info = wp_parse_args( maybe_unserialize( $user_info ), $defaults );
// Ensure email index is in the old user info array
if ( empty( $user_info['email'] ) ) {
$user_info['email'] = $this->email;
}
if ( empty( $user_info ) ) {
// Get the customer, but only if it's been created
$customer = new EDD_Customer( $this->customer_id );
if ( $customer->id > 0 ) {
$name = explode( ' ', $customer->name, 2 );
$user_info = array(
'first_name' => $name[0],
'last_name' => $name[1],
'email' => $customer->email,
'discount' => 'none',
);
}
} else {
// Get the customer, but only if it's been created
$customer = new EDD_Customer( $this->customer_id );
if ( $customer->id > 0 ) {
foreach ( $user_info as $key => $value ) {
if ( ! empty( $value ) ) {
continue;
}
switch ( $key ) {
case 'first_name':
$name = explode( ' ', $customer->name, 2 );
$user_info[ $key ] = $name[0];
break;
case 'last_name':
$name = explode( ' ', $customer->name, 2 );
$last_name = ! empty( $name[1] ) ? $name[1] : '';
$user_info[ $key ] = $last_name;
break;
case 'email':
$user_info[ $key ] = $customer->email;
break;
}
}
}
}
return $user_info;
}
/**
* Setup the Address for the payment
*
* @since 3.0
* @return array The Address information for the payment
*/
private function setup_address() {
$address = ! empty( $this->payment_meta['user_info']['address'] ) ? $this->payment_meta['user_info']['address'] : array();
$defaults = array(
'line1' => '',
'line2' => '',
'city' => '',
'country' => '',
'state' => '',
'zip' => '',
);
return wp_parse_args( $address, $defaults );
}
/**
* Setup the payment key
*
* @since 3.0
* @return string The Payment Key
*/
private function setup_payment_key() {
return $this->get_meta( '_edd_payment_purchase_key', true );
}
/**
* Setup the payment number
*
* @since 3.0
* @return int|string Integer by default, or string if sequential order numbers is enabled
*/
private function setup_payment_number() {
$number = false;
if ( edd_get_option( 'enable_sequential' ) ) {
$number = $this->get_meta( '_edd_payment_number', true );
}
return $number ?: $this->ID;
}
/**
* Setup the cart details
*
* @since 3.0
* @return array The cart details
*/
private function setup_cart_details() {
return isset( $this->payment_meta['cart_details'] ) ? maybe_unserialize( $this->payment_meta['cart_details'] ) : array();
}
/**
* Setup the downloads array
*
* @since 3.0
* @return array Downloads associated with this payment
*/
private function setup_downloads() {
return isset( $this->payment_meta['downloads'] ) ? maybe_unserialize( $this->payment_meta['downloads'] ) : array();
}
/**
* Setup the Unlimited downloads setting
*
* @since 3.0
* @return bool If this payment has unlimited downloads
*/
private function setup_has_unlimited() {
return (bool) $this->get_meta( '_edd_payment_unlimited_downloads', true );
}
/**
* Sets up the payment status.
*
* @since 3.0
* @return string
*/
private function setup_status() {
return 'publish' === $this->payment->post_status ? 'complete' : $this->payment->post_status;
}
/**
* Shims the payment, as much as possible, into an EDD Order object.
* @todo deprecate in 3.1
*
* @return EDD\Orders\Order
*/
public function _shim_order() {
return new \EDD\Orders\Order(
array(
'id' => $this->ID,
'parent' => $this->payment->parent,
'order_number' => $this->number,
'status' => $this->status,
'type' => 'sale',
'user_id' => $this->user_id,
'customer_id' => $this->customer_id,
'email' => $this->email,
'ip' => $this->ip,
'gateway' => $this->gateway,
'mode' => $this->mode,
'currency' => $this->currency,
'payment_key' => $this->key,
'subtotal' => $this->subtotal,
'discount' => $this->discounted_amount,
'tax' => $this->tax,
'total' => $this->total,
'rate' => $this->get_order_tax_rate(),
'date_created' => $this->payment->post_date_gmt,
'date_modified' => $this->payment->post_modified,
'date_completed' => $this->completed_date,
'items' => $this->get_order_items(),
)
);
}
/**
* Updates the payment tax rate to match the expected order tax rate.
*
* @since 3.0
* @return float
*/
private function get_order_tax_rate() {
$tax_rate = (float) $this->tax_rate;
if ( $tax_rate < 1 ) {
$tax_rate = $tax_rate * 100;
}
return $tax_rate;
}
/**
* Gets an array of order item objects from the cart details.
*
* @since 3.0
* @return array
*/
private function get_order_items() {
$order_items = array();
if ( empty( $this->cart_details ) ) {
return $order_items;
}
foreach ( $this->cart_details as $key => $cart_item ) {
$product_name = isset( $cart_item['name'] )
? $cart_item['name']
: '';
$price_id = $this->get_valid_price_id_for_cart_item( $cart_item );
if ( ! empty( $product_name ) ) {
$option_name = edd_get_price_option_name( $cart_item['id'], $price_id );
if ( ! empty( $option_name ) ) {
$product_name .= ' — ' . $option_name;
}
}
$order_item_args = array(
'order_id' => $this->ID,
'product_id' => $cart_item['id'],
'product_name' => $product_name,
'price_id' => $price_id,
'cart_index' => $key,
'type' => 'download',
'status' => $this->status,
'quantity' => ! empty( $cart_item['quantity'] ) ? $cart_item['quantity'] : 1,
'amount' => ! empty( $cart_item['item_price'] ) ? (float) $cart_item['item_price'] : (float) $cart_item['price'],
'subtotal' => (float) $cart_item['subtotal'],
'discount' => ! empty( $cart_item['discount'] ) ? (float) $cart_item['discount'] : 0.00,
'tax' => $cart_item['tax'],
'total' => (float) $cart_item['price'],
'date_created' => $this->payment->post_date_gmt,
'date_modified' => $this->payment->post_modified_gmt,
);
$order_items[] = new EDD\Orders\Order_Item( $order_item_args );
}
return $order_items;
}
/**
* Retrieves a valid price ID for a given cart item.
* If the product does not have variable prices, then `null` is always returned.
* If the supplied price ID does not match a price ID that actually exists, then the default
* variable price is returned instead of the supplied one.
*
* @since 3.0
*
* @param array $cart_item Array of cart item details.
*
* @return int|null
*/
private function get_valid_price_id_for_cart_item( $cart_item ) {
// If the product doesn't have variable prices, just return `null`.
if ( ! edd_has_variable_prices( $cart_item['id'] ) ) {
return null;
}
$variable_prices = edd_get_variable_prices( $cart_item['id'] );
if ( ! is_array( $variable_prices ) || empty( $variable_prices ) ) {
return null;
}
// Get the price ID that's set to the cart item right now.
$price_id = isset( $cart_item['item_number']['options']['price_id'] ) && is_numeric( $cart_item['item_number']['options']['price_id'] )
? absint( $cart_item['item_number']['options']['price_id'] )
: null;
// Now let's confirm it's actually a valid price ID.
$variable_price_ids = array_map( 'intval', array_column( $variable_prices, 'index' ) );
return in_array( $price_id, $variable_price_ids, true ) ? $price_id : edd_get_default_variable_price( $cart_item['id'] );
}
}

View File

@ -0,0 +1,344 @@
<?php
/**
* Backwards Compatibility Handler for Logs.
*
* @package EDD
* @subpackage Compat
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Compat;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Log Class.
*
* @since 3.0
*/
class Log extends Base {
/**
* Holds the component for which we are handling back-compat. There is a chance that two methods have the same name
* and need to be dispatched to completely other methods. When a new instance of Back_Compat is created, a component
* can be passed to the constructor which will allow __call() to dispatch to the correct methods.
*
* @since 3.0
* @access protected
* @var string
*/
protected $component = 'payment';
/**
* Backwards compatibility hooks for logs.
*
* @since 3.0
* @access protected
*/
protected function hooks() {
/* Filters ************************************************************/
add_filter( 'get_post_metadata', array( $this, 'api_request_log_get_post_meta' ), 99, 4 );
add_filter( 'update_post_metadata', array( $this, 'api_request_log_update_post_meta' ), 99, 5 );
add_filter( 'add_post_metadata', array( $this, 'api_request_log_update_post_meta' ), 99, 5 );
add_filter( 'get_post_metadata', array( $this, 'file_download_log_get_post_meta' ), 99, 4 );
add_filter( 'update_post_metadata', array( $this, 'file_download_log_update_post_meta' ), 99, 5 );
add_filter( 'add_post_metadata', array( $this, 'file_download_log_update_post_meta' ), 99, 5 );
}
/**
* Backwards compatibility filters for get_post_meta() calls on API request logs.
*
* @since 3.0
*
* @param mixed $value The value get_post_meta would return if we don't filter.
* @param int $object_id The object ID post meta was requested for.
* @param string $meta_key The meta key requested.
* @param bool $single If a single value or an array of the value is requested.
*
* @return mixed The value to return.
*/
public function api_request_log_get_post_meta( $value, $object_id, $meta_key, $single ) {
if ( 'get_post_metadata' !== current_filter() ) {
$message = __( 'This function is not meant to be called directly. It is only here for backwards compatibility purposes.', 'easy-digital-downloads' );
_doing_it_wrong( __FUNCTION__, $message, 'EDD 3.0' );
}
$meta_keys = array(
'_edd_log_request_ip',
'_edd_log_user',
'_edd_log_key',
'_edd_log_token',
'_edd_log_time',
'_edd_log_version',
);
if ( ! in_array( $meta_key, $meta_keys, true ) ) {
return $value;
}
$api_request_log = edd_get_api_request_log( $object_id );
if ( ! $api_request_log ) {
return $value;
}
switch ( $meta_key ) {
case '_edd_log_request_ip':
case '_edd_log_user':
case '_edd_log_key':
case '_edd_log_token':
case '_edd_log_time':
case '_edd_log_version':
$key = str_replace( '_edd_log_', '', $meta_key );
switch ( $key ) {
case 'request_ip':
$key = 'ip';
break;
case 'key':
$key = 'api_key';
break;
case 'user':
$key = 'user_id';
break;
}
$value = $api_request_log->{$key};
break;
}
if ( $this->show_notices ) {
_doing_it_wrong( 'get_post_meta()', 'All log postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_get_api_request_log()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
return $value;
}
/**
* Listen for calls to update_post_meta for API request logs and see if we need to filter them.
*
* This is here for backwards compatibility purposes with the migration to custom tables in EDD 3.0.
*
* @since 3.0
*
* @param mixed $check Comes in 'null' but if returned not null, WordPress Core will not interact with the
* postmeta table.
* @param int $object_id The object ID post meta was requested for.
* @param string $meta_key The meta key requested.
* @param mixed $meta_value The value get_post_meta would return if we don't filter.
* @param mixed $prev_value The previous value of the meta.
* @return mixed Returns 'null' if no action should be taken and WordPress core can continue, or non-null to avoid postmeta.
*/
public function api_request_log_update_post_meta( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
$meta_keys = array(
'_edd_log_request_ip',
'_edd_log_user',
'_edd_log_key',
'_edd_log_token',
'_edd_log_time',
'_edd_log_version',
);
if ( ! in_array( $meta_key, $meta_keys, true ) ) {
return $check;
}
$api_request_log = edd_get_api_request_log( $object_id );
if ( ! $api_request_log ) {
return $check;
}
switch ( $meta_key ) {
case '_edd_log_request_ip':
case '_edd_log_user':
case '_edd_log_key':
case '_edd_log_token':
case '_edd_log_time':
case '_edd_log_version':
$key = str_replace( '_edd_log_', '', $meta_key );
switch ( $key ) {
case 'request_ip':
$key = 'ip';
break;
case 'key':
$key = 'api_key';
break;
case 'user':
$key = 'user_id';
break;
}
$check = edd_update_api_request_log( $object_id, array(
$key => $meta_value,
) );
break;
}
if ( $this->show_notices ) {
_doing_it_wrong( 'add_post_meta()/update_post_meta()', 'All log postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_add_order_meta()/edd_update_order_meta()()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
return $check;
}
/**
* Backwards compatibility filters for get_post_meta() calls on file download logs.
*
* @since 3.0
*
* @param mixed $value The value get_post_meta would return if we don't filter.
* @param int $object_id The object ID post meta was requested for.
* @param string $meta_key The meta key requested.
* @param bool $single If a single value or an array of the value is requested.
*
* @return mixed The value to return.
*/
public function file_download_log_get_post_meta( $value, $object_id, $meta_key, $single ) {
if ( 'get_post_metadata' !== current_filter() ) {
$message = __( 'This function is not meant to be called directly. It is only here for backwards compatibility purposes.', 'easy-digital-downloads' );
_doing_it_wrong( __FUNCTION__, $message, 'EDD 3.0' );
}
$meta_keys = array(
'_edd_log_user_info',
'_edd_log_user_id',
'_edd_log_file_id',
'_edd_log_ip',
'_edd_log_payment_id',
'_edd_log_price_id',
'_edd_log_customer_id',
);
if ( ! in_array( $meta_key, $meta_keys, true ) ) {
return $value;
}
$file_download_log = edd_get_file_download_log( $object_id );
if ( ! $file_download_log ) {
return $value;
}
switch ( $meta_key ) {
case '_edd_log_user_id':
case '_edd_log_file_id':
case '_edd_log_ip':
case '_edd_log_payment_id':
case '_edd_log_price_id':
case '_edd_log_customer_id':
$key = str_replace( '_edd_log_', '', $meta_key );
switch ( $key ) {
case 'request_ip':
$key = 'ip';
break;
case 'key':
$key = 'api_key';
break;
case 'user':
$key = 'user_id';
break;
case 'payment_id':
$key = 'order_id';
break;
}
if ( isset( $file_download_log->{$key} ) ) {
$value = $file_download_log->{$key};
}
if ( 'user_id' === $key ) {
$customer = new \EDD_Customer( $file_download_log->customer_id );
$value = ! empty( $customer->user_id ) ? $customer->user_id : 0;
}
break;
}
if ( $this->show_notices ) {
_doing_it_wrong( 'get_post_meta()', __( 'All log postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_get_api_request_log()</code> instead.', 'easy-digital-downloads' ), 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
return $value;
}
/**
* Listen for calls to update_post_meta for file download logs and see if we need to filter them.
*
* This is here for backwards compatibility purposes with the migration to custom tables in EDD 3.0.
*
* @since 3.0
*
* @param mixed $check Comes in 'null' but if returned not null, WordPress Core will not interact with
* the postmeta table.
* @param int $object_id The object ID post meta was requested for.
* @param string $meta_key The meta key requested.
* @param mixed $meta_value The value get_post_meta would return if we don't filter.
* @param mixed $prev_value The previous value of the meta
*
* @return mixed Returns 'null' if no action should be taken and WordPress core can continue, or non-null to avoid postmeta
*/
public function file_download_log_update_post_meta( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
$meta_keys = array(
'_edd_log_user_info',
'_edd_log_user_id',
'_edd_log_file_id',
'_edd_log_ip',
'_edd_log_payment_id',
'_edd_log_price_id',
'_edd_log_customer_id',
);
if ( ! in_array( $meta_key, $meta_keys, true ) ) {
return $check;
}
$file_download_log = edd_get_file_download_log( $object_id );
if ( ! $file_download_log ) {
return $check;
}
switch ( $meta_key ) {
case '_edd_log_user_id':
case '_edd_log_file_id':
case '_edd_key_ip':
case '_edd_log_payment_id':
case '_edd_log_price_id':
case '_edd_log_customer_id':
$key = str_replace( '_edd_log_', '', $meta_key );
if ( 'payment_id' === $key ) {
$key = 'order_id';
}
$check = edd_update_file_download_log( $object_id, array(
$key => $meta_value,
) );
break;
}
return $check;
}
}

View File

@ -0,0 +1,313 @@
<?php
/**
* Backwards Compatibility Handler for Payments.
*
* @package EDD
* @subpackage Compat
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Compat;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Payment Class.
*
* EDD 3.0 moves away from storing payment data in wp_posts. This class handles all the backwards compatibility for the
* transition to custom tables.
*
* @since 3.0
*/
class Payment extends Base {
/**
* Holds the component for which we are handling back-compat. There is a chance that two methods have the same name
* and need to be dispatched to completely other methods. When a new instance of Back_Compat is created, a component
* can be passed to the constructor which will allow __call() to dispatch to the correct methods.
*
* @since 3.0
* @access protected
* @var string
*/
protected $component = 'payment';
/**
* Backwards compatibility hooks for payments.
*
* @since 3.0
* @access protected
*/
protected function hooks() {
/* Actions ************************************************************/
add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), 99, 1 );
/* Filters ************************************************************/
add_filter( 'query', array( $this, 'wp_count_posts' ), 10, 1 );
add_filter( 'get_post_metadata', array( $this, 'get_post_metadata' ), 99, 4 );
add_filter( 'update_post_metadata', array( $this, 'update_post_metadata' ), 99, 5 );
add_filter( 'add_post_metadata', array( $this, 'update_post_metadata' ), 99, 5 );
}
/**
* Backwards compatibility layer for wp_count_posts().
*
* This is here for backwards compatibility purposes with the migration to custom tables in EDD 3.0.
*
* @since 3.0
*
* @param string $query SQL request.
*
* @return string $request Rewritten SQL query.
*/
public function wp_count_posts( $query ) {
global $wpdb;
$expected = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = 'edd_payment' GROUP BY post_status";
if ( $expected === $query ) {
$query = "SELECT status AS post_status, COUNT( * ) AS num_posts FROM {$wpdb->edd_orders} GROUP BY post_status";
}
return $query;
}
/**
* Add a message for anyone to trying to get payments via get_post/get_posts/WP_Query.
* Force filters to run for all queries that have `edd_discount` as the post type.
*
* This is here for backwards compatibility purposes with the migration to custom tables in EDD 3.0.
*
* @since 3.0
*
* @param \WP_Query $query
*/
public function pre_get_posts( $query ) {
global $wpdb;
if ( 'pre_get_posts' !== current_filter() ) {
$message = __( 'This function is not meant to be called directly. It is only here for backwards compatibility purposes.', 'easy-digital-downloads' );
_doing_it_wrong( __FUNCTION__, $message, 'EDD 3.0' );
}
// Bail if not a payment
if ( 'edd_payment' !== $query->get( 'post_type' ) ) {
return;
}
// Force filters to run
$query->set( 'suppress_filters', false );
// Setup doing-it-wrong message
$message = sprintf(
__( 'As of Easy Digital Downloads 3.0, orders no longer exist in the %1$s table. They have been migrated to %2$s. Orders should be accessed using %3$s or %4$s. See %5$s for more information.', 'easy-digital-downloads' ),
'<code>' . $wpdb->posts . '</code>',
'<code>' . edd_get_component_interface( 'order', 'table' )->table_name . '</code>',
'<code>edd_get_orders()</code>',
'<code>edd_get_order()</code>',
'https://easydigitaldownloads.com/development/'
);
_doing_it_wrong( 'get_posts()/get_post()/WP_Query', $message, 'EDD 3.0' );
}
/**
* Backwards compatibility filters for get_post_meta() calls on payments.
*
* @since 3.0
*
* @param mixed $value The value get_post_meta would return if we don't filter.
* @param int $object_id The object ID post meta was requested for.
* @param string $meta_key The meta key requested.
* @param bool $single If a single value or an array of the value is requested.
*
* @return mixed The value to return.
*/
public function get_post_metadata( $value, $object_id, $meta_key, $single ) {
if ( 'get_post_metadata' !== current_filter() ) {
$message = __( 'This function is not meant to be called directly. It is only here for backwards compatibility purposes.', 'easy-digital-downloads' );
_doing_it_wrong( __FUNCTION__, esc_html( $message ), 'EDD 3.0' );
}
// Bail early of not a back-compat key
if ( ! in_array( $meta_key, $this->get_meta_key_whitelist(), true ) ) {
return $value;
}
// Bail if order does not exist
$order = $this->_shim_edd_get_order( $object_id );
if ( empty( $order ) ) {
return $value;
}
switch ( $meta_key ) {
case '_edd_payment_purchase_key':
$value = $order->payment_key;
break;
case '_edd_payment_transaction_id':
$value = $order->get_transaction_id();
break;
case '_edd_payment_user_email':
$value = $order->email;
break;
case '_edd_payment_meta':
$p = edd_get_payment( $object_id );
$value = array( $p->get_meta( '_edd_payment_meta' ) );
break;
case '_edd_completed_date':
$value = $order->date_completed;
break;
case '_edd_payment_gateway':
$value = $order->gateway;
break;
case '_edd_payment_user_id':
$value = $order->user_id;
break;
case '_edd_payment_user_ip':
$value = $order->ip;
break;
case '_edd_payment_mode':
$value = $order->mode;
break;
case '_edd_payment_tax_rate':
$value = $order->get_tax_rate();
/*
* Tax rates are now stored as percentages (e.g. `20.00`) but previously they were stored as
* decimals (e.g. `0.2`) so we convert it back to a decimal.
*/
if ( is_numeric( $value ) ) {
$value = $value / 100;
}
break;
case '_edd_payment_customer_id':
$value = $order->customer_id;
break;
case '_edd_payment_total':
$value = $order->total;
break;
case '_edd_payment_tax':
$value = $order->tax;
break;
case '_edd_payment_number':
$value = $order->get_number();
break;
default :
$value = edd_get_order_meta( $order->id, $meta_key, true );
break;
}
if ( $this->show_notices ) {
_doing_it_wrong( 'get_post_meta()', 'All payment postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_get_order()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
return $value;
}
/**
* Backwards compatibility filters for add/update_post_meta() calls on payments.
*
* @since 3.0
*
* @param mixed $check Comes in 'null' but if returned not null, WordPress Core will not interact with the postmeta table.
* @param int $object_id The object ID post meta was requested for.
* @param string $meta_key The meta key requested.
* @param mixed $meta_value The value get_post_meta would return if we don't filter.
* @param mixed $prev_value The previous value of the meta
*
* @return mixed Returns 'null' if no action should be taken and WordPress core can continue, or non-null to avoid postmeta.
*/
public function update_post_metadata( $check, $object_id, $meta_key, $meta_value, $prev_value ) {
// Bail early of not a back-compat key
if ( ! in_array( $meta_key, $this->get_meta_key_whitelist(), true ) ) {
return $check;
}
// Bail if payment does not exist
$payment = edd_get_payment( $object_id );
if ( empty( $payment ) ) {
return $check;
}
$check = $payment->update_meta( $meta_key, $meta_value );
if ( $this->show_notices ) {
_doing_it_wrong( 'add_post_meta()/update_post_meta()', 'All payment postmeta has been <strong>deprecated</strong> since Easy Digital Downloads 3.0! Use <code>edd_add_order_meta()/edd_update_order_meta()()</code> instead.', 'EDD 3.0' );
if ( $this->show_backtrace ) {
$backtrace = debug_backtrace();
trigger_error( print_r( $backtrace, 1 ) );
}
}
return $check;
}
/**
* Retrieves a list of whitelisted meta keys that we want to catch in get/update post meta calls.
*
* @since 3.0
* @return array
*/
private function get_meta_key_whitelist() {
$meta_keys = array(
'_edd_payment_purchase_key',
'_edd_payment_transaction_id',
'_edd_payment_meta',
'_edd_completed_date',
'_edd_payment_gateway',
'_edd_payment_user_id',
'_edd_payment_user_email',
'_edd_payment_user_ip',
'_edd_payment_mode',
'_edd_payment_tax_rate',
'_edd_payment_customer_id',
'_edd_payment_total',
'_edd_payment_tax',
'_edd_payment_number',
'_edd_sl_upgraded_payment_id', // EDD SL
'_edd_sl_is_renewal', // EDD SL
'_edds_stripe_customer_id', // EDD Stripe
);
/**
* Allows the whitelisted post meta keys to be filtered. Extensions should add their meta key(s) to this
* list if they want add/update/get post meta calls to be routed to order meta.
*
* @param array $meta_keys
*
* @since 3.0
*/
$meta_keys = apply_filters( 'edd_30_post_meta_key_whitelist', $meta_keys );
return (array) $meta_keys;
}
/**
* Gets the order from the database.
* This is a duplicate of edd_get_order, but is defined separately here
* for pending migration purposes.
*
* @todo deprecate in 3.1
*
* @param int $order_id
* @return false|EDD\Orders\Order
*/
private function _shim_edd_get_order( $order_id ) {
$orders = new \EDD\Database\Queries\Order();
// Return order
return $orders->get_item( $order_id );
}
}

View File

@ -0,0 +1,97 @@
<?php
/**
* Backwards Compatibility Handler for Taxes.
*
* @package EDD
* @subpackage Compat
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Compat;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Tax Class.
*
* EDD 3.0 moves away from storing tax rates in wp_options. This class handles all the backwards compatibility for the
* transition to custom tables.
*
* @since 3.0
*/
class Tax extends Base {
/**
* Holds the component for which we are handling back-compat. There is a chance that two methods have the same name
* and need to be dispatched to completely other methods. When a new instance of Back_Compat is created, a component
* can be passed to the constructor which will allow __call() to dispatch to the correct methods.
*
* @since 3.0
* @access protected
* @var string
*/
protected $component = 'tax';
/**
* Backwards compatibility hooks for payments.
*
* @since 3.0
* @access protected
*/
protected function hooks() {
/* Filters ************************************************************/
add_filter( 'pre_update_option', array( $this, 'update_option' ), 10, 3 );
}
/**
* Backwards compatibility layer for update_option().
*
* This is here for backwards compatibility purposes with the migration to custom tables in EDD 3.0.
*
* @since 3.0
*
* @param mixed $value The new, unserialized option value.
* @param string $option Name of the option.
* @param mixed $old_value The old option value.
*
* @return string $value Option value.
*/
public function update_option( $value, $option, $old_value ) {
// Bail if tax rates are not being updated.
if ( 'edd_tax_rates' !== $option ) {
return $value;
}
$value = (array) $value;
foreach ( $value as $tax_rate ) {
if ( empty( $tax_rate['country'] ) || empty( $tax_rate['rate'] ) ) {
continue;
}
$scope = ! empty( $tax_rate['global'] )
? 'country'
: 'region';
$region = ! empty( $tax_rate['state'] )
? sanitize_text_field( $tax_rate['state'] )
: '';
$adjustment_data = array(
'name' => $tax_rate['country'],
'scope' => $scope,
'amount' => floatval( $tax_rate['rate'] ),
'description' => $region,
);
edd_add_tax_rate( $adjustment_data );
}
// Return the value so it is stored for backwards compatibility purposes.
return $value;
}
}

View File

@ -0,0 +1,119 @@
<?php
/**
* Backwards Compatibility Handler for Templates.
*
* @package EDD
* @subpackage Compat
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
namespace EDD\Compat;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Template Class.
*
* EDD 3.0 stores data in custom tables making get_post() backwards incompatible. This class handles template changes
* required for template to carry on working as expected.
*
* @since 3.0
*/
class Template extends Base {
/**
* Holds the component for which we are handling back-compat. There is a chance that two methods have the same name
* and need to be dispatched to completely other methods. When a new instance of Back_Compat is created, a component
* can be passed to the constructor which will allow __call() to dispatch to the correct methods.
*
* @since 3.0
* @access protected
* @var string
*/
protected $component = 'template';
/**
* Backwards compatibility hooks for payments.
*
* @since 3.0
* @access protected
*/
protected function hooks() {
/* Actions ***********************************************************/
add_action( 'admin_init', array( $this, 'update_receipt_template' ) );
}
/**
* Update the receipt template to use `edd_get_payment()` instead of `get_post()`.
*
* @since 3.0
*/
public function update_receipt_template() {
$access_type = get_filesystem_method();
$last_checked = get_transient( 'edd-sc-receipt-check' );
if ( false !== $last_checked ) {
return false;
}
// Only run this once a day.
set_transient( 'edd-sc-receipt-check', DAY_IN_SECONDS );
// Retrieve the path to the template being used.
$template = edd_locate_template( 'shortcode-receipt.php' );
// Bail if the template has not been overridden.
if ( false === strpos( $template, 'edd_templates' ) ) {
return false;
}
if ( 'direct' === $access_type ) {
// Request credentials from the user, if necessary.
$credentials = request_filesystem_credentials( admin_url(), '', false, false, array() );
// Authenticate & instantiate the WordPress Filesystem classes.
if ( ! WP_Filesystem( $credentials ) ) {
// Request credentials again in case they were wrong the first time.
request_filesystem_credentials( admin_url(), '', true, false, array() );
return false;
}
global $wp_filesystem;
/** @var \WP_Filesystem_Base $wp_filesystem */
if ( $wp_filesystem->exists( $template ) && $wp_filesystem->is_writable( $template ) ) {
$contents = $wp_filesystem->get_contents( $template );
$get_post_call_exists = strstr( $contents, 'get_post( $edd_receipt_args[\'id\'] )' );
if ( false === $get_post_call_exists ) {
return;
}
$contents = str_replace( 'get_post( $edd_receipt_args[\'id\'] )', 'edd_get_payment( $edd_receipt_args[\'id\'] )', $contents );
$updated = $wp_filesystem->put_contents( $template, $contents );
// Only display a notice if we could not update the file.
if ( ! $updated ) {
add_action( 'admin_notices', function() use ( $template ) {
?>
<div class="notice notice-error">
<p><?php esc_html_e( 'Easy Digital Downloads failed to automatically update your purchase receipt template. This update is necessary for the purchase receipt to display correctly.', 'easy-digital-downloads' ); ?></p>
<p><?php printf( __( 'This update must be completed manually. Please click %shere%s for more information.', 'easy-digital-downloads' ), '<a href="https://easydigitaldownloads.com/development/2018/06/21/breaking-changes-to-orders-in-easy-digital-downloads-3-0/">', '</a>' ); ?></p>
<p><?php esc_html_e( 'The file that needs to be updated is located at:', 'easy-digital-downloads' ); ?> <code><?php echo esc_html( $template ); ?></code></p>
</div>
<?php
} );
}
}
}
}
}